Skip to content

Commit c4b60b9

Browse files
authored
Merge pull request #469 from fo-code/delta-rename-detection
Enabled rename detection
2 parents b138fb1 + 31294d4 commit c4b60b9

File tree

3 files changed

+79
-11
lines changed

3 files changed

+79
-11
lines changed

plugin/pom.xml

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,11 @@
2828
<echarts-api.version>5.3.2-1</echarts-api.version>
2929
<font-awesome-api.version>6.0.0-1</font-awesome-api.version>
3030
<plugin-util-api.version>2.16.0</plugin-util-api.version>
31-
<data-tables-api.version>1.11.4-3</data-tables-api.version>
32-
<forensics-api-plugin.version>1.12.0</forensics-api-plugin.version>
31+
<data-tables-api.version>1.11.4-4</data-tables-api.version>
32+
<forensics-api-plugin.version>1.13.0</forensics-api-plugin.version>
3333
<bootstrap5-api.version>5.1.3-6</bootstrap5-api.version>
3434
<testcontainers.version>1.17.1</testcontainers.version>
35+
<jquery3-api.version>3.6.0-3</jquery3-api.version>
3536
</properties>
3637

3738
<licenses>
@@ -66,6 +67,11 @@
6667
<artifactId>bootstrap5-api</artifactId>
6768
<version>${bootstrap5-api.version}</version>
6869
</dependency>
70+
<dependency>
71+
<groupId>io.jenkins.plugins</groupId>
72+
<artifactId>jquery3-api</artifactId>
73+
<version>${jquery3-api.version}</version>
74+
</dependency>
6975
</dependencies>
7076
</dependencyManagement>
7177

plugin/src/main/java/io/jenkins/plugins/forensics/git/delta/DeltaRepositoryCallback.java

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,8 @@ private RemoteResultWrapper<Delta> calculateDelta(final Repository repository) t
9494
try (DiffFormatter diffFormatter = new DiffFormatter(diffStream)) {
9595
diffFormatter.setDiffComparator(RawTextComparator.WS_IGNORE_ALL);
9696
diffFormatter.setRepository(repository);
97+
// enabling rename detection requires a set repository
98+
diffFormatter.setDetectRenames(true);
9799

98100
final List<DiffEntry> diffEntries = diffFormatter.scan(referenceCommit, currentCommit);
99101
final Map<String, FileChanges> fileChangesMap = new HashMap<>();
@@ -103,7 +105,9 @@ private RemoteResultWrapper<Delta> calculateDelta(final Repository repository) t
103105
for (DiffEntry diffEntry : diffEntries) {
104106
FileEditType fileEditType = getFileEditType(diffEntry.getChangeType());
105107
FileChanges fileChanges = createFileChanges(fileEditType, diffEntry, diffFormatter, repository);
106-
fileChangesMap.put(diffEntry.getNewId().name(), fileChanges);
108+
109+
String fileId = getFileId(diffEntry, fileEditType);
110+
fileChangesMap.put(fileId, fileChanges);
107111
}
108112

109113
log.logInfo("Creating the Git diff file");
@@ -120,6 +124,26 @@ private RemoteResultWrapper<Delta> calculateDelta(final Repository repository) t
120124
}
121125
}
122126

127+
/**
128+
* Gets the ID of the edited file, which is represented by the passed {@link DiffEntry}. If it is a deleted file,
129+
* the old ID before the edit is taken in order to provide always unique IDs.
130+
*
131+
* @param diffEntry
132+
* Represents the edits of a file
133+
* @param fileEditType
134+
* The {@link FileEditType}
135+
*
136+
* @return the file ID
137+
*/
138+
private String getFileId(final DiffEntry diffEntry, final FileEditType fileEditType) {
139+
if (FileEditType.DELETE.equals(fileEditType)) {
140+
return diffEntry.getOldId().name();
141+
}
142+
else {
143+
return diffEntry.getNewId().name();
144+
}
145+
}
146+
123147
/**
124148
* Creates an instance of {@link FileChanges} which wraps the information about all changes made to a specific
125149
* file.
@@ -141,20 +165,27 @@ private FileChanges createFileChanges(final FileEditType fileEditType, final Dif
141165
final DiffFormatter diffFormatter, final Repository repository)
142166
throws IOException {
143167
String filePath;
168+
String oldFilePath;
144169
String fileContent;
145-
if (fileEditType == FileEditType.DELETE) {
146-
// file path and content of deleted files have to be read using old ID
147-
filePath = diffEntry.getOldPath();
170+
if (fileEditType.equals(FileEditType.DELETE)) {
148171
fileContent = getFileContent(diffEntry.getOldId().toObjectId(), repository);
172+
oldFilePath = diffEntry.getOldPath();
173+
filePath = "";
149174
}
150175
else {
151-
filePath = diffEntry.getNewPath();
176+
if (fileEditType.equals(FileEditType.ADD)) {
177+
oldFilePath = "";
178+
}
179+
else {
180+
oldFilePath = diffEntry.getOldPath();
181+
}
152182
fileContent = getFileContent(diffEntry.getNewId().toObjectId(), repository);
183+
filePath = diffEntry.getNewPath();
153184
}
154185

155186
diffFormatter.format(diffEntry);
156187

157-
FileChanges fileChanges = new FileChanges(filePath, fileContent, fileEditType, new HashMap<>());
188+
FileChanges fileChanges = new FileChanges(filePath, oldFilePath, fileContent, fileEditType, new HashMap<>());
158189

159190
for (Edit edit : diffFormatter.toFileHeader(diffEntry).toEditList()) {
160191
createChange(edit).ifPresent(fileChanges::addChange);

plugin/src/test/java/io/jenkins/plugins/forensics/git/delta/GitDeltaCalculatorITest.java

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
*/
3535
class GitDeltaCalculatorITest extends GitITest {
3636
private static final String EMPTY_SCM_KEY = "";
37+
private static final String EMPTY_FILE_PATH = "";
3738

3839
/**
3940
* The delta result should be empty if there are invalid commits.
@@ -109,6 +110,7 @@ void shouldDetermineAddedFile() {
109110
Delta delta = result.get();
110111
FileChanges fileChanges = getSingleFileChanges(delta);
111112
assertThat(fileChanges.getFileName()).isEqualTo(newFileName);
113+
assertThat(fileChanges.getOldFileName()).isEqualTo(EMPTY_FILE_PATH);
112114
assertThat(fileChanges.getFileEditType()).isEqualTo(FileEditType.ADD);
113115
assertThat(fileChanges.getFileContent()).isEqualTo(content);
114116
}
@@ -133,7 +135,8 @@ void shouldDetermineModifiedFile() {
133135

134136
Delta delta = result.get();
135137
FileChanges fileChanges = getSingleFileChanges(delta);
136-
assertThat(fileChanges.getFileName()).isEqualTo(GitITest.INITIAL_FILE);
138+
assertThat(fileChanges.getFileName()).isEqualTo(INITIAL_FILE);
139+
assertThat(fileChanges.getOldFileName()).isEqualTo(INITIAL_FILE);
137140
assertThat(fileChanges.getFileEditType()).isEqualTo(FileEditType.MODIFY);
138141
assertThat(fileChanges.getFileContent()).isEqualTo(content);
139142
}
@@ -150,7 +153,7 @@ void shouldDetermineDeletedFile() {
150153
String content = "content";
151154
commitFile(content);
152155
Run<?, ?> referenceBuild = buildSuccessfully(job);
153-
git("rm", GitITest.INITIAL_FILE);
156+
git("rm", INITIAL_FILE);
154157
commit("test");
155158
Run<?, ?> build = buildSuccessfully(job);
156159

@@ -159,11 +162,39 @@ void shouldDetermineDeletedFile() {
159162

160163
Delta delta = result.get();
161164
FileChanges fileChanges = getSingleFileChanges(delta);
162-
assertThat(fileChanges.getFileName()).isEqualTo(GitITest.INITIAL_FILE);
165+
assertThat(fileChanges.getFileName()).isEqualTo(EMPTY_FILE_PATH);
166+
assertThat(fileChanges.getOldFileName()).isEqualTo(INITIAL_FILE);
163167
assertThat(fileChanges.getFileEditType()).isEqualTo(FileEditType.DELETE);
164168
assertThat(fileChanges.getFileContent()).isEqualTo(content);
165169
}
166170

171+
/**
172+
* A renamed file should be determined.
173+
*/
174+
@Test
175+
void shouldDetermineRenamedFile() {
176+
FreeStyleProject job = createJobWithReferenceRecorder();
177+
GitDeltaCalculator deltaCalculator = createDeltaCalculator();
178+
FilteredLog log = createLog();
179+
180+
String content = "content";
181+
commitFile(content);
182+
Run<?, ?> referenceBuild = buildSuccessfully(job);
183+
git("rm", INITIAL_FILE);
184+
writeFileAsAuthorFoo(content);
185+
Run<?, ?> build = buildSuccessfully(job);
186+
187+
Optional<Delta> result = deltaCalculator.calculateDelta(build, referenceBuild, EMPTY_SCM_KEY, log);
188+
assertThat(result).isNotEmpty();
189+
190+
Delta delta = result.get();
191+
FileChanges fileChanges = getSingleFileChanges(delta);
192+
assertThat(fileChanges.getFileName()).isEqualTo(ADDITIONAL_FILE);
193+
assertThat(fileChanges.getOldFileName()).isEqualTo(INITIAL_FILE);
194+
assertThat(fileChanges.getFileEditType()).isEqualTo(FileEditType.RENAME);
195+
assertThat(fileChanges.getFileContent()).isEqualTo(content);
196+
}
197+
167198
/**
168199
* Added lines within a specific file should be determined.
169200
*/

0 commit comments

Comments
 (0)