diff --git a/config/import-control.xml b/config/import-control.xml
index 7cafef4..aa87612 100644
--- a/config/import-control.xml
+++ b/config/import-control.xml
@@ -36,5 +36,6 @@
+
diff --git a/src/main/java/com/github/checkstyle/regression/data/GitChange.java b/src/main/java/com/github/checkstyle/regression/data/GitChange.java
index ac337ea..8a75635 100644
--- a/src/main/java/com/github/checkstyle/regression/data/GitChange.java
+++ b/src/main/java/com/github/checkstyle/regression/data/GitChange.java
@@ -19,6 +19,8 @@
package com.github.checkstyle.regression.data;
+import java.util.List;
+
import org.immutables.value.Value;
/**
@@ -32,4 +34,11 @@ public interface GitChange {
* @return the path of the changed file
*/
String path();
+
+ /**
+ * The line numbers of the changed codes.
+ * The first line of a file is marked as line zero.
+ * @return the line numbers of the changed codes
+ */
+ List lines();
}
diff --git a/src/main/java/com/github/checkstyle/regression/git/DiffParser.java b/src/main/java/com/github/checkstyle/regression/git/DiffParser.java
index 449ace0..f77a03c 100644
--- a/src/main/java/com/github/checkstyle/regression/git/DiffParser.java
+++ b/src/main/java/com/github/checkstyle/regression/git/DiffParser.java
@@ -21,12 +21,16 @@
import java.io.File;
import java.io.IOException;
+import java.util.Arrays;
+import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;
+import org.apache.commons.lang.math.IntRange;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.diff.DiffEntry;
+import org.eclipse.jgit.diff.DiffFormatter;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
@@ -36,6 +40,7 @@
import org.eclipse.jgit.storage.file.FileRepositoryBuilder;
import org.eclipse.jgit.treewalk.AbstractTreeIterator;
import org.eclipse.jgit.treewalk.CanonicalTreeParser;
+import org.eclipse.jgit.util.io.DisabledOutputStream;
import com.github.checkstyle.regression.data.GitChange;
import com.github.checkstyle.regression.data.ImmutableGitChange;
@@ -44,6 +49,7 @@
* Parses git diff between PR branch and master for the further use.
* @author LuoLiangchen
*/
+// -@cs[ClassDataAbstractionCoupling] We have to import many classes from JGit
public final class DiffParser {
/** Prevents instantiation. */
private DiffParser() {
@@ -59,7 +65,7 @@ private DiffParser() {
*/
public static List parse(String repositoryPath, String branchName)
throws IOException, GitAPIException {
- final List returnValue;
+ final List returnValue = new LinkedList<>();
final File gitDir = new File(repositoryPath, ".git");
final Repository repository = new FileRepositoryBuilder().setGitDir(gitDir)
.readEnvironment().findGitDir().build();
@@ -67,16 +73,20 @@ public static List parse(String repositoryPath, String branchName)
try {
final TreeParserPair pair = getTreeParserPair(repository, branchName);
final Git git = new Git(repository);
+ final DiffFormatter formatter = new DiffFormatter(DisabledOutputStream.INSTANCE);
+ formatter.setRepository(repository);
try {
- returnValue = git.diff()
+ final List diffs = git.diff()
.setOldTree(pair.commonAncestorTreeParser)
.setNewTree(pair.prTreeParser)
.call()
.stream()
.filter(entry -> entry.getChangeType() != DiffEntry.ChangeType.DELETE)
- .map(DiffParser::convertDiffEntryToGitChange)
.collect(Collectors.toList());
+ for (DiffEntry diff : diffs) {
+ returnValue.add(convertDiffEntryToGitChange(diff, formatter));
+ }
}
finally {
git.close();
@@ -158,11 +168,20 @@ private static AbstractTreeIterator prepareTreeParser(RevWalk walk, RevCommit co
/**
* Converts a {@link DiffEntry} to {@link GitChange} for the further use.
* @param diffEntry the {@link DiffEntry} instance to be converted
+ * @param formatter the diff formatter to provide the line changes information
* @return the {@link GitChange} instance converted from the given {@link DiffEntry}
+ * @throws IOException JGit library exception
*/
- private static GitChange convertDiffEntryToGitChange(DiffEntry diffEntry) {
+ private static GitChange convertDiffEntryToGitChange(
+ DiffEntry diffEntry, DiffFormatter formatter) throws IOException {
+ final List lines = formatter.toFileHeader(diffEntry).toEditList().stream()
+ .flatMapToInt(edit -> Arrays.stream(
+ new IntRange(edit.getBeginB(), edit.getEndB() - 1).toArray()))
+ .boxed()
+ .collect(Collectors.toList());
return ImmutableGitChange.builder()
.path(diffEntry.getNewPath())
+ .addAllLines(lines)
.build();
}
diff --git a/src/test/java/com/github/checkstyle/regression/git/DiffParserTest.java b/src/test/java/com/github/checkstyle/regression/git/DiffParserTest.java
index 2f4f9bc..a53b1d0 100644
--- a/src/test/java/com/github/checkstyle/regression/git/DiffParserTest.java
+++ b/src/test/java/com/github/checkstyle/regression/git/DiffParserTest.java
@@ -79,6 +79,7 @@ public void testParseModifyChange() throws Exception {
assertEquals("There should be 1 change detected", 1, changes.size());
final GitChange expected = ImmutableGitChange.builder()
.path("HelloWorld")
+ .addLines(0)
.build();
assertEquals("The change is not as expected", expected, changes.get(0));
}
@@ -203,4 +204,26 @@ public void testParseFilePermissionChange() throws Exception {
}
}
}
+
+ @Test
+ public void testParseLineChanges() throws Exception {
+ try (Repository repository = GitUtils.createNewRepository()) {
+ final File helloWorld = GitUtils.addAnEmptyFileAndCommit(repository, "HelloWorld");
+ Files.write(helloWorld.toPath(), "line 0\nline 1\nline 2\n"
+ .getBytes(Charset.forName("UTF-8")), StandardOpenOption.APPEND);
+ GitUtils.addAllAndCommit(repository, "add original three lines");
+ GitUtils.createNewBranchAndCheckout(repository, "foo");
+ Files.write(helloWorld.toPath(), "line 0\nline 1 change\nline X\n"
+ .getBytes(Charset.forName("UTF-8")), StandardOpenOption.WRITE);
+ GitUtils.addAllAndCommit(repository, "change line 1, delete line 2, add a line");
+ final List changes = DiffParser.parse(
+ repository.getDirectory().getParent(), "foo");
+ assertEquals("There should be 1 change detected", 1, changes.size());
+ final GitChange expected = ImmutableGitChange.builder()
+ .path("HelloWorld")
+ .addLines(1, 2)
+ .build();
+ assertEquals("The change is not as expected", expected, changes.get(0));
+ }
+ }
}