Skip to content

Commit 4fe675d

Browse files
committed
Implementation for commit range aggregation and refactoring detection
with GitHub API
1 parent 868190e commit 4fe675d

File tree

1 file changed

+180
-0
lines changed

1 file changed

+180
-0
lines changed

src/main/java/org/refactoringminer/rm1/GitHistoryRefactoringMinerImpl.java

Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2043,4 +2043,184 @@ else if(previousFile.isFile() && nextFile.isFile()) {
20432043
}
20442044
return null;
20452045
}
2046+
2047+
public List<Refactoring> detectRefactoringsForCommitRange(String cloneURL, String startCommit, String endCommit) throws Exception {
2048+
Set<String> repositoryDirectoriesBefore = new LinkedHashSet<String>();
2049+
Set<String> repositoryDirectoriesCurrent = new LinkedHashSet<String>();
2050+
Map<String, String> fileContentsBefore = new LinkedHashMap<String, String>();
2051+
Map<String, String> fileContentsCurrent = new LinkedHashMap<String, String>();
2052+
2053+
populateWithGitHubAPIForCommitRange(cloneURL, startCommit, endCommit, fileContentsBefore, fileContentsCurrent, repositoryDirectoriesBefore, repositoryDirectoriesCurrent);
2054+
List<MoveSourceFolderRefactoring> moveSourceFolderRefactorings = processIdenticalFiles(fileContentsBefore, fileContentsCurrent, Collections.emptyMap(), false);
2055+
UMLModel parentUMLModel = createModel(fileContentsBefore, repositoryDirectoriesBefore);
2056+
UMLModel currentUMLModel = createModel(fileContentsCurrent, repositoryDirectoriesCurrent);
2057+
2058+
UMLModelDiff modelDiff = parentUMLModel.diff(currentUMLModel);
2059+
List<Refactoring> refactoringsAtRevision = modelDiff.getRefactorings();
2060+
refactoringsAtRevision.addAll(moveSourceFolderRefactorings);
2061+
refactoringsAtRevision = filter(refactoringsAtRevision);
2062+
return refactoringsAtRevision;
2063+
}
2064+
2065+
public void populateWithGitHubAPIForCommitRange(String cloneURL, String startCommit, String endCommit,
2066+
Map<String, String> filesBefore, Map<String, String> filesCurrent,
2067+
Set<String> repositoryDirectoriesBefore, Set<String> repositoryDirectoriesCurrent) throws IOException, InterruptedException {
2068+
GHRepository repository = getGitHubRepository(cloneURL);
2069+
PagedIterable<GHCommit> commits = repository.queryCommits().from(endCommit).list();
2070+
List<GHCommit> reverseCommits = new ArrayList<>();
2071+
for(GHCommit currentGHCommit : commits) {
2072+
reverseCommits.add(0, currentGHCommit);
2073+
if(currentGHCommit.getSHA1().equals(startCommit)) {
2074+
break;
2075+
}
2076+
}
2077+
for(GHCommit currentGHCommit : reverseCommits) {
2078+
final String commitId = currentGHCommit.getSHA1();
2079+
logger.info("Processing {} {} ...", cloneURL, commitId);
2080+
List<GHCommit.File> commitFiles = new ArrayList<>();
2081+
GHCommit currentCommit = new GHRepositoryWrapper(repository).getCommit(commitId, commitFiles);
2082+
//if parents.size() == 0 then currentCommit is the initial commit of the repository, but then all files will have an ADDED status
2083+
final String parentCommitId = currentCommit.getParents().size() > 0 ? currentCommit.getParents().get(0).getSHA1() : null;
2084+
Set<String> deletedAndRenamedFileParentDirectories = ConcurrentHashMap.newKeySet();
2085+
List<String> commitFileNames = new ArrayList<>();
2086+
ExecutorService pool = Executors.newFixedThreadPool(commitFiles.size());
2087+
for (GHCommit.File commitFile : commitFiles) {
2088+
String fileName = commitFile.getFileName();
2089+
if (commitFile.getFileName().endsWith(".java")) {
2090+
commitFileNames.add(fileName);
2091+
if (commitFile.getStatus().equals("modified")) {
2092+
Runnable r = () -> {
2093+
try {
2094+
String currentRawFile = null;
2095+
String parentRawFile = null;
2096+
if(repository.isPrivate()) {
2097+
InputStream currentRawFileInputStream = repository.getFileContent(fileName, commitId).read();
2098+
currentRawFile = IOUtils.toString(currentRawFileInputStream);
2099+
InputStream parentRawFileInputStream = repository.getFileContent(fileName, parentCommitId).read();
2100+
parentRawFile = IOUtils.toString(parentRawFileInputStream);
2101+
}
2102+
else {
2103+
URL currentRawURL = commitFile.getRawUrl();
2104+
InputStream currentRawFileInputStream = currentRawURL.openStream();
2105+
currentRawFile = IOUtils.toString(currentRawFileInputStream);
2106+
String rawURLInParentCommit = currentRawURL.toString().replace(commitId, parentCommitId);
2107+
InputStream parentRawFileInputStream = new URL(rawURLInParentCommit).openStream();
2108+
parentRawFile = IOUtils.toString(parentRawFileInputStream);
2109+
}
2110+
if(!filesBefore.containsKey(fileName))
2111+
filesBefore.put(fileName, parentRawFile);
2112+
filesCurrent.put(fileName, currentRawFile);
2113+
}
2114+
catch(IOException e) {
2115+
e.printStackTrace();
2116+
}
2117+
};
2118+
pool.submit(r);
2119+
}
2120+
else if (commitFile.getStatus().equals("added")) {
2121+
Runnable r = () -> {
2122+
try {
2123+
String currentRawFile = null;
2124+
if(repository.isPrivate()) {
2125+
InputStream currentRawFileInputStream = repository.getFileContent(fileName, commitId).read();
2126+
currentRawFile = IOUtils.toString(currentRawFileInputStream);
2127+
}
2128+
else {
2129+
URL currentRawURL = commitFile.getRawUrl();
2130+
InputStream currentRawFileInputStream = currentRawURL.openStream();
2131+
currentRawFile = IOUtils.toString(currentRawFileInputStream);
2132+
}
2133+
filesCurrent.put(fileName, currentRawFile);
2134+
}
2135+
catch(IOException e) {
2136+
e.printStackTrace();
2137+
}
2138+
};
2139+
pool.submit(r);
2140+
}
2141+
else if (commitFile.getStatus().equals("removed")) {
2142+
Runnable r = () -> {
2143+
try {
2144+
String parentRawFile = null;
2145+
if(repository.isPrivate()) {
2146+
InputStream parentRawFileInputStream = repository.getFileContent(fileName, parentCommitId).read();
2147+
parentRawFile = IOUtils.toString(parentRawFileInputStream);
2148+
}
2149+
else {
2150+
URL rawURL = commitFile.getRawUrl();
2151+
InputStream rawFileInputStream = rawURL.openStream();
2152+
parentRawFile = IOUtils.toString(rawFileInputStream);
2153+
}
2154+
if(!filesBefore.containsKey(fileName))
2155+
filesBefore.put(fileName, parentRawFile);
2156+
if(fileName.contains("/")) {
2157+
deletedAndRenamedFileParentDirectories.add(fileName.substring(0, fileName.lastIndexOf("/")));
2158+
}
2159+
}
2160+
catch(IOException e) {
2161+
e.printStackTrace();
2162+
}
2163+
};
2164+
pool.submit(r);
2165+
}
2166+
else if (commitFile.getStatus().equals("renamed")) {
2167+
commitFileNames.add(commitFile.getPreviousFilename());
2168+
Runnable r = () -> {
2169+
try {
2170+
String previousFilename = commitFile.getPreviousFilename();
2171+
String currentRawFile = null;
2172+
String parentRawFile = null;
2173+
if(repository.isPrivate()) {
2174+
InputStream currentRawFileInputStream = repository.getFileContent(fileName, commitId).read();
2175+
currentRawFile = IOUtils.toString(currentRawFileInputStream);
2176+
InputStream parentRawFileInputStream = repository.getFileContent(previousFilename, parentCommitId).read();
2177+
parentRawFile = IOUtils.toString(parentRawFileInputStream);
2178+
}
2179+
else {
2180+
URL currentRawURL = commitFile.getRawUrl();
2181+
InputStream currentRawFileInputStream = currentRawURL.openStream();
2182+
currentRawFile = IOUtils.toString(currentRawFileInputStream);
2183+
String encodedFileName = URLEncoder.encode(fileName, StandardCharsets.UTF_8);
2184+
String encodedPreviousFilename = URLEncoder.encode(previousFilename, StandardCharsets.UTF_8);
2185+
String rawURLInParentCommit = currentRawURL.toString().replace(commitId, parentCommitId).replace(encodedFileName, encodedPreviousFilename);
2186+
InputStream parentRawFileInputStream = new URL(rawURLInParentCommit).openStream();
2187+
parentRawFile = IOUtils.toString(parentRawFileInputStream);
2188+
}
2189+
if(!filesBefore.containsKey(fileName))
2190+
filesBefore.put(previousFilename, parentRawFile);
2191+
filesCurrent.put(fileName, currentRawFile);
2192+
//renamedFilesHint.put(previousFilename, fileName);
2193+
if(previousFilename.contains("/")) {
2194+
deletedAndRenamedFileParentDirectories.add(previousFilename.substring(0, previousFilename.lastIndexOf("/")));
2195+
}
2196+
}
2197+
catch(IOException e) {
2198+
e.printStackTrace();
2199+
}
2200+
};
2201+
pool.submit(r);
2202+
}
2203+
}
2204+
}
2205+
pool.shutdown();
2206+
pool.awaitTermination(Long.MAX_VALUE, TimeUnit.MILLISECONDS);
2207+
List<String> orderedFilesBefore = new ArrayList<>();
2208+
List<String> orderedFilesCurrent = new ArrayList<>();
2209+
for(String fileName : commitFileNames) {
2210+
if(filesBefore.containsKey(fileName)) {
2211+
orderedFilesBefore.add(fileName);
2212+
}
2213+
if(filesCurrent.containsKey(fileName)) {
2214+
orderedFilesCurrent.add(fileName);
2215+
}
2216+
}
2217+
repositoryDirectories(currentCommit.getTree(), "", repositoryDirectoriesCurrent, new LinkedHashSet<>(orderedFilesCurrent));
2218+
//repositoryDirectoriesCurrent.addAll(deletedAndRenamedFileParentDirectories);
2219+
//allRepositoryDirectories(currentCommit.getTree(), "", repositoryDirectoriesCurrent);
2220+
if(parentCommitId != null) {
2221+
GHCommit parentCommit = repository.getCommit(parentCommitId);
2222+
repositoryDirectories(parentCommit.getTree(), "", repositoryDirectoriesBefore, new LinkedHashSet<>(orderedFilesBefore));
2223+
}
2224+
}
2225+
}
20462226
}

0 commit comments

Comments
 (0)