#12 -- Get file content for specific commit

This commit is contained in:
Anton Romanov 2021-04-12 10:41:26 +04:00
parent bf611faa38
commit 4265441490
6 changed files with 124 additions and 28 deletions

View File

@ -29,18 +29,24 @@ public abstract class StructuralUnitIdentifier {
return getEntityClasses(projectPath, subDirectory, projectFiles);
}
public abstract boolean canAppliedToCode(String sourceCode);
public abstract boolean canAppliedToFile(File projectFile);
public abstract boolean canAppliedToProject(String projectPath, List<File> projectFiles, List<File> rootProjectFiles);
public abstract boolean isEntityClass(File file);
public abstract boolean isEntityClass(String sourceCode);
protected abstract boolean isBusinessLogicClass(File file);
public abstract List<StructuralUnit> getBusinessLogicClasses();
public abstract boolean isMultiModuleProject();
public abstract Optional<BuildTool> getBuildTool(List<File> rootDirectoryFiles);
public abstract boolean canAppliedToProject(String projectPath, List<File> projectFiles, List<File> rootProjectFiles);
public abstract boolean canAppliedToFile(File projectFile);
protected abstract List<StructuralUnit> getEntityClasses(String projectPath, String subDirectory, List<File> projectFiles);
protected abstract String getSourceDirectory(List<File> rootProjectFiles);
@ -51,8 +57,6 @@ public abstract class StructuralUnitIdentifier {
protected abstract ProgrammingLanguage getProgrammingLanguage();
protected abstract boolean isBusinessLogicClass(File file);
protected Optional<ProgrammingLanguage> getMainProgrammingLanguage(String projectPath, List<File> projectFiles, List<File> rootProjectFiles) {
String subDirectory = getSourceDirectory(rootProjectFiles);
Map<ProgrammingLanguage, Integer> projectFileLanguageFrequency = new HashMap<>();

View File

@ -10,7 +10,9 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import ru.ulstu.extractor.heuristic.model.StructuralUnit;
import ru.ulstu.extractor.heuristic.service.StructuralUnitService;
import ru.ulstu.extractor.service.GitRepositoryService;
import java.io.File;
import java.io.IOException;
import java.util.List;
@ -18,13 +20,17 @@ import java.util.List;
@RequestMapping("StructuralUnitController")
public class StructuralUnitController {
private final StructuralUnitService structuralUnitService;
private final GitRepositoryService gitRepositoryService;
public StructuralUnitController(StructuralUnitService structuralUnitService) {
public StructuralUnitController(StructuralUnitService structuralUnitService,
GitRepositoryService gitRepositoryService) {
this.structuralUnitService = structuralUnitService;
this.gitRepositoryService = gitRepositoryService;
}
@GetMapping("get-entities")
public List<StructuralUnit> getEntities(String repositoryUrl) throws IOException {
return structuralUnitService.getEntities(repositoryUrl);
File rootPath = gitRepositoryService.getProjectDirectoryFile(repositoryUrl);
return structuralUnitService.getEntities(rootPath);
}
}

View File

@ -18,7 +18,8 @@ import ru.ulstu.extractor.heuristic.model.StructuralUnit;
import ru.ulstu.extractor.util.StringUtils;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.file.Files;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
@ -27,6 +28,7 @@ import static ru.ulstu.extractor.heuristic.service.DetectorService.LangDetectScr
@Service
public class JavaIdentifier extends StructuralUnitIdentifier {
private static final String ENTITY_ANNOTATION = "@Entity";
private final DetectorService detectorService;
private final BuildToolService buildToolService;
private final ProgrammingLanguageService programmingLanguageService;
@ -49,6 +51,10 @@ public class JavaIdentifier extends StructuralUnitIdentifier {
return getMainProgrammingLanguage(projectFile, LOW).orElse(null) instanceof JavaProgrammingLanguage;
}
public boolean canAppliedToCode(String sourceCode) {
return getMainProgrammingLanguage(sourceCode).orElse(null) instanceof JavaProgrammingLanguage;
}
@Override
public List<StructuralUnit> getEntityClasses(String projectPath, String subDirectory, List<File> projectFiles) {
return projectFiles.stream()
@ -58,6 +64,12 @@ public class JavaIdentifier extends StructuralUnitIdentifier {
.collect(Collectors.toList());
}
protected Optional<ProgrammingLanguage> getMainProgrammingLanguage(String sourceCode) {
return sourceCodeContainsClass(sourceCode)
? Optional.of(getProgrammingLanguage())
: Optional.empty();
}
@Override
public List<StructuralUnit> getBusinessLogicClasses() {
return null;
@ -91,16 +103,30 @@ public class JavaIdentifier extends StructuralUnitIdentifier {
@Override
public boolean isEntityClass(File file) {
try {
return file.getName().endsWith("java") && classContainsAnnotation(file, "@Entity");
return file.getName().endsWith("java") && classContainsAnnotation(file, ENTITY_ANNOTATION);
} catch (Exception ex) {
ex.printStackTrace();
}
return false;
}
private boolean classContainsAnnotation(File file, String annotationDeclaration) throws FileNotFoundException {
@Override
public boolean isEntityClass(String sourceCode) {
try {
return classContainsAnnotation(sourceCode, ENTITY_ANNOTATION);
} catch (Exception ex) {
ex.printStackTrace();
}
return false;
}
private boolean classContainsAnnotation(File file, String annotationDeclaration) throws IOException {
return classContainsAnnotation(new String(Files.readAllBytes(file.toPath())), annotationDeclaration);
}
private boolean classContainsAnnotation(String sourceCode, String annotationDeclaration) {
JavaParser parser = new JavaParser();
ParseResult<CompilationUnit> parseResult = parser.parse(file);
ParseResult<CompilationUnit> parseResult = parser.parse(sourceCode);
if (parseResult.getResult().isPresent() && parseResult.getResult().get().findCompilationUnit().isPresent()) {
return parseResult.getResult().get().getTypes().stream()
.anyMatch(clazz -> clazz.getAnnotations().stream().anyMatch(annotation -> annotation.toString().startsWith(annotationDeclaration)));
@ -108,6 +134,15 @@ public class JavaIdentifier extends StructuralUnitIdentifier {
return false;
}
private boolean sourceCodeContainsClass(String sourceCode) {
JavaParser parser = new JavaParser();
ParseResult<CompilationUnit> parseResult = parser.parse(sourceCode);
if (parseResult.getResult().isPresent() && parseResult.getResult().get().findCompilationUnit().isPresent()) {
return parseResult.getResult().get().getTypes().stream().findAny().isPresent();
}
return false;
}
@Override
protected String getSourceDirectory(List<File> rootDirectoryFiles) {
return buildToolService.getProjectBuildTool(rootDirectoryFiles)

View File

@ -8,49 +8,53 @@ package ru.ulstu.extractor.heuristic.service;
import org.springframework.stereotype.Service;
import ru.ulstu.extractor.heuristic.api.StructuralUnitIdentifier;
import ru.ulstu.extractor.heuristic.model.StructuralUnit;
import ru.ulstu.extractor.service.GitRepositoryService;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.Optional;
import java.util.function.Predicate;
@Service
public class StructuralUnitService {
private final GitRepositoryService gitRepositoryService;
private final DirectoryService directoryService;
private final List<StructuralUnitIdentifier> structuralUnitIdentifiers;
public StructuralUnitService(GitRepositoryService gitRepositoryService,
DirectoryService directoryService,
public StructuralUnitService(DirectoryService directoryService,
List<StructuralUnitIdentifier> structuralUnitIdentifiers) {
this.gitRepositoryService = gitRepositoryService;
this.directoryService = directoryService;
this.structuralUnitIdentifiers = structuralUnitIdentifiers;
}
public List<StructuralUnit> getEntities(String repositoryUrl) throws IOException {
File rootPath = gitRepositoryService.getProjectDirectoryFile(repositoryUrl);
public List<StructuralUnit> getEntities(File rootPath) throws IOException {
List<File> projectFiles = directoryService.getFilesRecursively(rootPath);
List<File> rootProjectFiles = directoryService.getDirectoryFiles(rootPath.toPath());
return getStructuralUnitIdentifier(
structuralUnitIdentifier -> structuralUnitIdentifier.canAppliedToProject(
rootPath.getPath(),
projectFiles,
rootProjectFiles)
).getEntityClasses(rootPath.getPath(), projectFiles, rootProjectFiles);
rootProjectFiles))
.orElseThrow(() -> new RuntimeException("Identifier not found"))
.getEntityClasses(rootPath.getPath(), projectFiles, rootProjectFiles);
}
public boolean containsEntity(File projectFile) {
return getStructuralUnitIdentifier(
structuralUnitIdentifier -> structuralUnitIdentifier.canAppliedToFile(projectFile)
).isEntityClass(projectFile);
structuralUnitIdentifier -> structuralUnitIdentifier.canAppliedToFile(projectFile))
.map(identifier -> identifier.isEntityClass(projectFile))
.orElse(false);
}
private StructuralUnitIdentifier getStructuralUnitIdentifier(Predicate<StructuralUnitIdentifier> predicate) {
public boolean containsEntity(String sourceCode) {
return getStructuralUnitIdentifier(
structuralUnitIdentifier -> structuralUnitIdentifier.canAppliedToCode(sourceCode))
.map(identifier -> identifier.isEntityClass(sourceCode))
.orElse(false);
}
private Optional<StructuralUnitIdentifier> getStructuralUnitIdentifier(Predicate<StructuralUnitIdentifier> predicate) {
return structuralUnitIdentifiers.stream()
.filter(predicate)
.findAny()
.orElseThrow(() -> new RuntimeException("Identifier not found"));
.findAny();
}
}

View File

@ -1,3 +1,8 @@
/*
* Copyright (C) 2021 Anton Romanov - All Rights Reserved
* You may use, distribute and modify this code, please write to: romanov73@gmail.com.
*/
package ru.ulstu.extractor.model;
import org.hibernate.annotations.Fetch;
@ -20,6 +25,9 @@ public class FileChange extends BaseEntity {
@Transient
private boolean added;
@Transient
private boolean containsEntity;
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@JoinColumn(name = "file_change_id", unique = true)
@Fetch(FetchMode.SUBSELECT)
@ -71,4 +79,12 @@ public class FileChange extends BaseEntity {
public boolean isAdded() {
return added;
}
public boolean isContainsEntity() {
return containsEntity;
}
public void setContainsEntity(boolean containsEntity) {
this.containsEntity = containsEntity;
}
}

View File

@ -12,10 +12,15 @@ import org.eclipse.jgit.api.ListBranchCommand;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.diff.DiffFormatter;
import org.eclipse.jgit.internal.storage.file.FileRepository;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectLoader;
import org.eclipse.jgit.lib.ObjectReader;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.treewalk.TreeWalk;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import ru.ulstu.extractor.heuristic.service.StructuralUnitService;
import ru.ulstu.extractor.model.Author;
import ru.ulstu.extractor.model.Branch;
import ru.ulstu.extractor.model.Commit;
@ -28,6 +33,7 @@ import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.time.Instant;
import java.util.ArrayList;
@ -44,6 +50,12 @@ public class GitRepositoryService {
@Value("${extractor.custom-projects-dir}")
private String customProjectsDir;
private final StructuralUnitService structuralUnitService;
public GitRepositoryService(StructuralUnitService structuralUnitService) {
this.structuralUnitService = structuralUnitService;
}
public List<Branch> getRemoteBranches(String url) throws GitAPIException, IOException {
cloneOrUpdateRepo(url);
Repository localRepo = new FileRepository(getProjectGitDirectory(url));
@ -177,10 +189,10 @@ public class GitRepositoryService {
} catch (IOException e) {
throw new RuntimeException("Error occurred during diff computation. Message: " + e.getMessage());
}
return parseOutputDiff(output);
return parseOutputDiff(output, localRepo, laterCommit);
}
private List<FileChange> parseOutputDiff(String output) {
private List<FileChange> parseOutputDiff(String output, Repository repository, RevCommit commit) {
List<FileChange> changes = new ArrayList<>();
String[] strings = output.split("\n");
FileChange fileChange = new FileChange();
@ -191,6 +203,9 @@ public class GitRepositoryService {
if (maybeFileName.isPresent()) {
fileChange = new FileChange();
fileChange.setFile(maybeFileName.get());
fileChange.setContainsEntity(
structuralUnitService.containsEntity(getContent(repository, commit, maybeFileName.get()))
);
/// вытащить другие изменения из коммита
changes.add(fileChange);
}
@ -226,6 +241,22 @@ public class GitRepositoryService {
return changes;
}
private String getContent(Repository repository, RevCommit commit, String path) {
try (TreeWalk treeWalk = TreeWalk.forPath(repository, path, commit.getTree())) {
if (treeWalk != null) {
ObjectId blobId = treeWalk.getObjectId(0);
try (ObjectReader objectReader = repository.newObjectReader()) {
ObjectLoader objectLoader = objectReader.open(blobId);
byte[] bytes = objectLoader.getBytes();
return new String(bytes, StandardCharsets.UTF_8);
}
}
} catch (Exception ex) {
ex.printStackTrace();
}
return "";
}
private Optional<String> getFileName(String commitString) {
String startString = "diff --git a/";
if (commitString.startsWith(startString)) {