Skip to content

Commit 20018e5

Browse files
#95 Now using one instance of Git & one instance of Repository
1 parent 0c4e98f commit 20018e5

File tree

8 files changed

+114
-85
lines changed

8 files changed

+114
-85
lines changed

change-proneness-ranker/src/main/java/org/hjug/git/ChangePronenessRanker.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,17 @@
44
import java.util.*;
55
import lombok.extern.slf4j.Slf4j;
66
import org.eclipse.jgit.api.errors.GitAPIException;
7-
import org.eclipse.jgit.lib.Repository;
87

98
@Slf4j
109
public class ChangePronenessRanker {
1110

1211
private final TreeMap<Integer, Integer> changeCountsByTimeStamps = new TreeMap<>();
1312
private final Map<String, ScmLogInfo> cachedScmLogInfos = new HashMap<>();
1413

15-
public ChangePronenessRanker(Repository repository, GitLogReader repositoryLogReader) {
14+
public ChangePronenessRanker(GitLogReader repositoryLogReader) {
1615
try {
1716
log.info("Capturing change count based on commit timestamps");
18-
changeCountsByTimeStamps.putAll(repositoryLogReader.captureChangeCountByCommitTimestamp(repository));
17+
changeCountsByTimeStamps.putAll(repositoryLogReader.captureChangeCountByCommitTimestamp());
1918
} catch (IOException | GitAPIException e) {
2019
log.error("Error reading from repository: {}", e.getMessage());
2120
}

change-proneness-ranker/src/main/java/org/hjug/git/GitLogReader.java

Lines changed: 61 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,39 @@
1515
import org.eclipse.jgit.util.io.NullOutputStream;
1616

1717
@Slf4j
18-
public class GitLogReader {
18+
public class GitLogReader implements AutoCloseable {
1919

2020
static final String JAVA_FILE_TYPE = ".java";
2121

22+
private Repository gitRepository;
23+
24+
private Git git;
25+
26+
public GitLogReader() {}
27+
28+
public GitLogReader(File basedir) throws IOException {
29+
FileRepositoryBuilder repositoryBuilder = new FileRepositoryBuilder().findGitDir(basedir);
30+
String gitIndexFileEnvVariable = System.getenv("GIT_INDEX_FILE");
31+
if (Objects.nonNull(gitIndexFileEnvVariable)
32+
&& !gitIndexFileEnvVariable.trim().isEmpty()) {
33+
log.debug("Setting Index File based on Env Variable GIT_INDEX_FILE {}", gitIndexFileEnvVariable);
34+
repositoryBuilder = repositoryBuilder.setIndexFile(new File(gitIndexFileEnvVariable));
35+
}
36+
37+
git = Git.open(repositoryBuilder.getGitDir());
38+
gitRepository = git.getRepository();
39+
}
40+
41+
GitLogReader(Git git) {
42+
this.git = git;
43+
gitRepository = git.getRepository();
44+
}
45+
46+
@Override
47+
public void close() throws Exception {
48+
git.close();
49+
}
50+
2251
// Based on
2352
// https://github.com/Cosium/git-code-format-maven-plugin/blob/master/src/main/java/com/cosium/code/format/AbstractMavenGitCodeFormatMojo.java
2453
// MIT License
@@ -81,14 +110,12 @@ public Map<String, ByteArrayOutputStream> listRepositoryContentsAtHEAD(Repositor
81110
* Returns the number of commits and earliest commit for a given path
82111
* TODO: Move to a different class???
83112
*
84-
* @param repository
85113
* @param path
86114
* @return a LogInfo object
87115
* @throws GitAPIException
88116
*/
89-
public ScmLogInfo fileLog(Repository repository, String path) throws GitAPIException, IOException {
90-
Git git = new Git(repository);
91-
ObjectId branchId = repository.resolve("HEAD");
117+
public ScmLogInfo fileLog(String path) throws GitAPIException, IOException {
118+
ObjectId branchId = gitRepository.resolve("HEAD");
92119
Iterable<RevCommit> revCommits = git.log().add(branchId).addPath(path).call();
93120

94121
int commitCount = 0;
@@ -101,8 +128,7 @@ public ScmLogInfo fileLog(Repository repository, String path) throws GitAPIExcep
101128
}
102129

103130
// based on https://stackoverflow.com/a/59274329/346247
104-
int mostRecentCommit = new Git(repository)
105-
.log()
131+
int mostRecentCommit = git.log()
106132
.add(branchId)
107133
.addPath(path)
108134
.setMaxCount(1)
@@ -115,49 +141,47 @@ public ScmLogInfo fileLog(Repository repository, String path) throws GitAPIExcep
115141
}
116142

117143
// based on https://stackoverflow.com/questions/27361538/how-to-show-changes-between-commits-with-jgit
118-
public TreeMap<Integer, Integer> captureChangeCountByCommitTimestamp(Repository repository)
119-
throws IOException, GitAPIException {
144+
public TreeMap<Integer, Integer> captureChangeCountByCommitTimestamp() throws IOException, GitAPIException {
120145

121146
TreeMap<Integer, Integer> changesByCommitTimestamp = new TreeMap<>();
122147

123-
try (Git git = new Git(repository)) {
124-
ObjectId branchId = repository.resolve("HEAD");
125-
Iterable<RevCommit> commits = git.log().add(branchId).call();
148+
ObjectId branchId = gitRepository.resolve("HEAD");
149+
Iterable<RevCommit> commits = git.log().add(branchId).call();
126150

127-
RevCommit newCommit = null;
151+
RevCommit newCommit = null;
128152

129-
for (Iterator<RevCommit> iterator = commits.iterator(); iterator.hasNext(); ) {
130-
RevCommit oldCommit = iterator.next();
131-
132-
int count = 0;
133-
if (null == newCommit) {
134-
newCommit = oldCommit;
135-
continue;
136-
}
153+
for (Iterator<RevCommit> iterator = commits.iterator(); iterator.hasNext(); ) {
154+
RevCommit oldCommit = iterator.next();
137155

138-
for (DiffEntry entry : getDiffEntries(git, newCommit, oldCommit)) {
139-
if (entry.getNewPath().endsWith(JAVA_FILE_TYPE)
140-
|| entry.getOldPath().endsWith(JAVA_FILE_TYPE)) {
141-
count++;
142-
}
143-
}
156+
int count = 0;
157+
if (null == newCommit) {
158+
newCommit = oldCommit;
159+
continue;
160+
}
144161

145-
if (count > 0) {
146-
changesByCommitTimestamp.put(newCommit.getCommitTime(), count);
162+
for (DiffEntry entry : getDiffEntries(newCommit, oldCommit)) {
163+
if (entry.getNewPath().endsWith(JAVA_FILE_TYPE)
164+
|| entry.getOldPath().endsWith(JAVA_FILE_TYPE)) {
165+
count++;
147166
}
167+
}
148168

149-
// Handle first / initial commit
150-
if (!iterator.hasNext()) {
151-
changesByCommitTimestamp.putAll(walkFirstCommit(repository, oldCommit));
152-
}
169+
if (count > 0) {
170+
changesByCommitTimestamp.put(newCommit.getCommitTime(), count);
171+
}
153172

154-
newCommit = oldCommit;
173+
// Handle first / initial commit
174+
if (!iterator.hasNext()) {
175+
changesByCommitTimestamp.putAll(walkFirstCommit(oldCommit));
155176
}
177+
178+
newCommit = oldCommit;
156179
}
180+
157181
return changesByCommitTimestamp;
158182
}
159183

160-
private List<DiffEntry> getDiffEntries(Git git, RevCommit newCommit, RevCommit oldCommit) throws IOException {
184+
private List<DiffEntry> getDiffEntries(RevCommit newCommit, RevCommit oldCommit) throws IOException {
161185
CanonicalTreeParser oldTreeIter = new CanonicalTreeParser();
162186
CanonicalTreeParser newTreeIter = new CanonicalTreeParser();
163187
try (ObjectReader reader = git.getRepository().newObjectReader()) {
@@ -172,11 +196,11 @@ private List<DiffEntry> getDiffEntries(Git git, RevCommit newCommit, RevCommit o
172196
return df.scan(oldTreeIter, newTreeIter);
173197
}
174198

175-
Map<Integer, Integer> walkFirstCommit(Repository repository, RevCommit firstCommit) throws IOException {
199+
Map<Integer, Integer> walkFirstCommit(RevCommit firstCommit) throws IOException {
176200
Map<Integer, Integer> changesByCommitTimestamp = new TreeMap<>();
177201
int firstCommitCount = 0;
178202
ObjectId treeId = firstCommit.getTree();
179-
try (TreeWalk treeWalk = new TreeWalk(repository)) {
203+
try (TreeWalk treeWalk = new TreeWalk(gitRepository)) {
180204
treeWalk.setRecursive(false);
181205
treeWalk.reset(treeId);
182206
while (treeWalk.next()) {

change-proneness-ranker/src/test/java/org/hjug/git/ChangePronenessRankerTest.java

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package org.hjug.git;
22

3-
import static org.mockito.ArgumentMatchers.any;
43
import static org.mockito.Mockito.mock;
54
import static org.mockito.Mockito.when;
65

@@ -31,9 +30,9 @@ void testChangePronenessCalculation() throws IOException, GitAPIException {
3130
commitsWithChangeCounts.put(scmLogInfo.getEarliestCommit() + 5 * 60, 3);
3231
commitsWithChangeCounts.put(scmLogInfo.getEarliestCommit() + 10 * 60, 3);
3332

34-
when(repositoryLogReader.captureChangeCountByCommitTimestamp(any())).thenReturn(commitsWithChangeCounts);
33+
when(repositoryLogReader.captureChangeCountByCommitTimestamp()).thenReturn(commitsWithChangeCounts);
3534

36-
changePronenessRanker = new ChangePronenessRanker(null, repositoryLogReader);
35+
changePronenessRanker = new ChangePronenessRanker(repositoryLogReader);
3736
List<ScmLogInfo> scmLogInfos = new ArrayList<>();
3837
scmLogInfos.add(scmLogInfo);
3938
changePronenessRanker.rankChangeProneness(scmLogInfos);
@@ -57,8 +56,8 @@ void testRankChangeProneness() throws IOException, GitAPIException {
5756
commitsWithChangeCounts.put(scmLogInfo2.getEarliestCommit() + 5 * 60, 5);
5857
commitsWithChangeCounts.put(scmLogInfo2.getEarliestCommit() + 10 * 60, 5);
5958

60-
when(repositoryLogReader.captureChangeCountByCommitTimestamp(any())).thenReturn(commitsWithChangeCounts);
61-
changePronenessRanker = new ChangePronenessRanker(null, repositoryLogReader);
59+
when(repositoryLogReader.captureChangeCountByCommitTimestamp()).thenReturn(commitsWithChangeCounts);
60+
changePronenessRanker = new ChangePronenessRanker(repositoryLogReader);
6261

6362
List<ScmLogInfo> scmLogInfos = new ArrayList<>();
6463
scmLogInfos.add(scmLogInfo);

change-proneness-ranker/src/test/java/org/hjug/git/GitLogReaderTest.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ void testFileLog() throws IOException, GitAPIException, InterruptedException {
4040
// This path works when referencing the full Tobago repository
4141
// String filePath = "tobago-core/src/main/java/org/apache/myfaces/tobago/facelets/AttributeHandler.java";
4242

43-
GitLogReader gitLogReader = new GitLogReader();
43+
GitLogReader gitLogReader = new GitLogReader(git);
4444

4545
String attributeHandler = "AttributeHandler.java";
4646
InputStream resourceAsStream = getClass().getClassLoader().getResourceAsStream(attributeHandler);
@@ -59,7 +59,7 @@ void testFileLog() throws IOException, GitAPIException, InterruptedException {
5959
git.add().addFilepattern(".").call();
6060
RevCommit secondCommit = git.commit().setMessage("message").call();
6161

62-
ScmLogInfo scmLogInfo = gitLogReader.fileLog(repository, attributeHandler);
62+
ScmLogInfo scmLogInfo = gitLogReader.fileLog(attributeHandler);
6363

6464
Assertions.assertEquals(2, scmLogInfo.getCommitCount());
6565
Assertions.assertEquals(firstCommit.getCommitTime(), scmLogInfo.getEarliestCommit());
@@ -68,23 +68,23 @@ void testFileLog() throws IOException, GitAPIException, InterruptedException {
6868

6969
@Test
7070
void testWalkFirstCommit() throws IOException, GitAPIException {
71-
GitLogReader gitLogReader = new GitLogReader();
71+
GitLogReader gitLogReader = new GitLogReader(git);
7272

7373
String attributeHandler = "AttributeHandler.java";
7474
InputStream resourceAsStream = getClass().getClassLoader().getResourceAsStream(attributeHandler);
7575
writeFile(attributeHandler, convertInputStreamToString(resourceAsStream));
7676
git.add().addFilepattern(".").call();
7777
RevCommit commit = git.commit().setMessage("message").call();
7878

79-
Map<Integer, Integer> result = gitLogReader.walkFirstCommit(repository, commit);
79+
Map<Integer, Integer> result = gitLogReader.walkFirstCommit(commit);
8080

8181
Assertions.assertTrue(result.containsKey(commit.getCommitTime()));
8282
Assertions.assertEquals(1, result.get(commit.getCommitTime()).intValue());
8383
}
8484

8585
@Test
8686
void testCaptureChangCountByCommitTimestamp() throws Exception {
87-
GitLogReader gitLogReader = new GitLogReader();
87+
GitLogReader gitLogReader = new GitLogReader(git);
8888

8989
String attributeHandler = "AttributeHandler.java";
9090
InputStream resourceAsStream = getClass().getClassLoader().getResourceAsStream(attributeHandler);
@@ -106,7 +106,7 @@ void testCaptureChangCountByCommitTimestamp() throws Exception {
106106
git.add().addFilepattern(".").call();
107107
RevCommit secondCommit = git.commit().setMessage("message").call();
108108

109-
Map<Integer, Integer> commitCounts = gitLogReader.captureChangeCountByCommitTimestamp(repository);
109+
Map<Integer, Integer> commitCounts = gitLogReader.captureChangeCountByCommitTimestamp();
110110

111111
Assertions.assertEquals(1, commitCounts.get(firstCommit.getCommitTime()).intValue());
112112
Assertions.assertEquals(

cost-benefit-calculator/src/main/java/org/hjug/cbc/CostBenefitCalculator.java

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
import net.sourceforge.pmd.*;
1919
import net.sourceforge.pmd.lang.LanguageRegistry;
2020
import org.eclipse.jgit.api.errors.GitAPIException;
21-
import org.eclipse.jgit.lib.Repository;
2221
import org.hjug.cycledetector.CircularReferenceChecker;
2322
import org.hjug.git.ChangePronenessRanker;
2423
import org.hjug.git.GitLogReader;
@@ -33,14 +32,14 @@
3332
import org.jgrapht.graph.DefaultWeightedEdge;
3433

3534
@Slf4j
36-
public class CostBenefitCalculator {
35+
public class CostBenefitCalculator implements AutoCloseable {
3736

3837
private final Map<String, AsSubgraph<String, DefaultWeightedEdge>> renderedSubGraphs = new HashMap<>();
3938

4039
private Report report;
4140
private String repositoryPath;
42-
private final GitLogReader gitLogReader = new GitLogReader();
43-
private Repository repository = null;
41+
private GitLogReader gitLogReader;
42+
4443
private final ChangePronenessRanker changePronenessRanker;
4544
private final JavaProjectParser javaProjectParser = new JavaProjectParser();
4645

@@ -52,16 +51,22 @@ public CostBenefitCalculator(String repositoryPath) {
5251

5352
log.info("Initiating Cost Benefit calculation");
5453
try {
55-
repository = gitLogReader.gitRepository(new File(repositoryPath));
56-
for (String file :
57-
gitLogReader.listRepositoryContentsAtHEAD(repository).keySet()) {
58-
log.info("Files at HEAD: {}", file);
59-
}
54+
gitLogReader = new GitLogReader(new File(repositoryPath));
55+
// repository = gitLogReader.gitRepository(new File(repositoryPath));
56+
// for (String file :
57+
// gitLogReader.listRepositoryContentsAtHEAD(repository).keySet()) {
58+
// log.info("Files at HEAD: {}", file);
59+
// }
6060
} catch (IOException e) {
6161
log.error("Failure to access Git repository", e);
6262
}
6363

64-
changePronenessRanker = new ChangePronenessRanker(repository, gitLogReader);
64+
changePronenessRanker = new ChangePronenessRanker(gitLogReader);
65+
}
66+
67+
@Override
68+
public void close() throws Exception {
69+
gitLogReader.close();
6570
}
6671

6772
public List<RankedCycle> runCycleAnalysis(String outputDirectoryPath, boolean renderImages) {
@@ -148,7 +153,7 @@ public List<RankedCycle> runCycleAnalysis(String outputDirectoryPath, boolean re
148153

149154
private boolean isDuplicateSubGraph(AsSubgraph<String, DefaultWeightedEdge> subGraph, String vertex) {
150155
if (!renderedSubGraphs.isEmpty()) {
151-
for (AsSubgraph<String, DefaultWeightedEdge> renderedSubGraph : renderedSubGraphs.values()) {
156+
for (AsSubgraph<String, DefaultWeightedEdge> renderedSubGraph : renderedSubGraphs.values()) {
152157
if (renderedSubGraph.vertexSet().size() == subGraph.vertexSet().size()
153158
&& renderedSubGraph.edgeSet().size()
154159
== subGraph.edgeSet().size()
@@ -237,7 +242,7 @@ <T extends Disharmony> List<ScmLogInfo> getRankedChangeProneness(List<T> disharm
237242
String path = disharmony.getFileName();
238243
ScmLogInfo scmLogInfo = null;
239244
try {
240-
scmLogInfo = gitLogReader.fileLog(repository, path);
245+
scmLogInfo = gitLogReader.fileLog(path);
241246
log.info("Successfully fetched scmLogInfo for {}", scmLogInfo.getPath());
242247
} catch (GitAPIException | IOException e) {
243248
log.error("Error reading Git repository contents.", e);

refactor-first-maven-plugin/src/main/java/org/hjug/mavenreport/RefactorFirstMavenReport.java

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import org.apache.maven.reporting.AbstractMavenReport;
2323
import org.apache.maven.reporting.MavenReportException;
2424
import org.hjug.cbc.CostBenefitCalculator;
25+
import org.hjug.cbc.RankedCycle;
2526
import org.hjug.cbc.RankedDisharmony;
2627
import org.hjug.gdg.GraphDataGenerator;
2728
import org.hjug.git.GitLogReader;
@@ -209,16 +210,16 @@ public void executeReport(Locale locale) throws MavenReportException {
209210
return;
210211
}
211212

212-
CostBenefitCalculator costBenefitCalculator = new CostBenefitCalculator(projectBaseDir);
213-
try {
213+
List<RankedDisharmony> rankedGodClassDisharmonies;
214+
List<RankedDisharmony> rankedCBODisharmonies;
215+
try (CostBenefitCalculator costBenefitCalculator = new CostBenefitCalculator(projectBaseDir)) {
214216
costBenefitCalculator.runPmdAnalysis();
215-
} catch (IOException e) {
216-
log.error("Error running PMD analysis.");
217+
rankedGodClassDisharmonies = costBenefitCalculator.calculateGodClassCostBenefitValues();
218+
rankedCBODisharmonies = costBenefitCalculator.calculateCBOCostBenefitValues();
219+
} catch (Exception e) {
220+
log.error("Error running analysis.");
217221
throw new RuntimeException(e);
218222
}
219-
List<RankedDisharmony> rankedGodClassDisharmonies = costBenefitCalculator.calculateGodClassCostBenefitValues();
220-
221-
List<RankedDisharmony> rankedCBODisharmonies = costBenefitCalculator.calculateCBOCostBenefitValues();
222223

223224
if (rankedGodClassDisharmonies.isEmpty() && rankedCBODisharmonies.isEmpty()) {
224225
mainSink.text("Contratulations! " + projectName + " " + projectVersion

report/src/main/java/org/hjug/refactorfirst/report/CsvReport.java

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import java.util.*;
1212
import lombok.extern.slf4j.Slf4j;
1313
import org.hjug.cbc.CostBenefitCalculator;
14+
import org.hjug.cbc.RankedCycle;
1415
import org.hjug.cbc.RankedDisharmony;
1516
import org.hjug.git.GitLogReader;
1617

@@ -83,14 +84,14 @@ public void execute(
8384
}
8485

8586
// actual calcualte
86-
CostBenefitCalculator costBenefitCalculator = new CostBenefitCalculator(projectBaseDir);
87-
try {
87+
List<RankedDisharmony> rankedDisharmonies;
88+
try (CostBenefitCalculator costBenefitCalculator = new CostBenefitCalculator(projectBaseDir)) {
8889
costBenefitCalculator.runPmdAnalysis();
89-
} catch (IOException e) {
90-
log.error("Error running PMD analysis.");
90+
rankedDisharmonies = costBenefitCalculator.calculateGodClassCostBenefitValues();
91+
} catch (Exception e) {
92+
log.error("Error running analysis.");
9193
throw new RuntimeException(e);
9294
}
93-
List<RankedDisharmony> rankedDisharmonies = costBenefitCalculator.calculateGodClassCostBenefitValues();
9495

9596
rankedDisharmonies.sort(Comparator.comparing(RankedDisharmony::getPriority));
9697

0 commit comments

Comments
 (0)