假设以下代码片段已提交给Git存储库:
int test(){
int a = 3;
int b = 4;
int c = a + b;
return c;
}
并稍后更新为
int test(){
return 7;
}
我目前有一个方法,它使用JGit API来访问提交上述内容的Git存储库,并输出一个类似于以下内容的字符串:
int test(){
-int a = 3;
-int b = 4;
-int c = a + b;
-return c;
+return 7;
}
现在,我的要求已经改变,并且只想知道更改行的行号。所以我想要以下内容:
2 -int a = 3;
3 -int b = 4;
4 -int c = a + b;
5 -return c;
2 +return 7;
基本上,GitHub应用程序在进行更新时提供的信息相同。
非常感谢任何帮助:)
如何计算 - / +行的片段:
String oldHash = "ee3e216ab5047748a22e9ec5ad3e92834704f0cc";
Git git = null;
try {
//the path where the repo is.
git = Git.open(new File("C:\\Users\\Administrator\\Documents\\GitHub\\Trial"));
} catch (IOException e1) {
e1.printStackTrace();
}
Repository repository = git.getRepository();
ObjectId old = null;
ObjectId head = null;
//a new reader to read objects from getObjectDatabase()
ObjectReader reader = repository.newObjectReader();
//Create a new parser.
CanonicalTreeParser oldTreeIter = new CanonicalTreeParser();
CanonicalTreeParser newTreeIter = new CanonicalTreeParser();
List<DiffEntry> diffs = null;
try {
//parse a git repository string and return an ObjectId
old = repository.resolve(oldHash + "^{tree}");
head = repository.resolve("HEAD^{tree}");
//Reset this parser to walk through the given tree
oldTreeIter.reset(reader, old);
newTreeIter.reset(reader, head);
diffs = git.diff()//Returns a command object to execute a diff command
.setNewTree(newTreeIter)
.setOldTree(oldTreeIter)
.call();//returns a DiffEntry for each path which is different
} catch (RevisionSyntaxException | IOException | GitAPIException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//DiffLineCountFilter d = new DiffLineCountFilter();
//out is the stream the formatter will write to
ByteArrayOutputStream out = new ByteArrayOutputStream();
//Create a new formatter with a default level of context.
DiffFormatter df = new DiffFormatter(out);
//Set the repository the formatter can load object contents from.
df.setRepository(git.getRepository());
ArrayList<String> diffText = new ArrayList<String>();
//A DiffEntry is 'A value class representing a change to a file' therefore for each file you have a diff entry
for(DiffEntry diff : diffs)
{
try {
//Format a patch script for one file entry.
df.format(diff);
RawText r = new RawText(out.toByteArray());
r.getLineDelimiter();
diffText.add(out.toString());
out.reset();
} catch (IOException e) {
e.printStackTrace();
}
}
答案 0 :(得分:5)
对于可能遇到此问题的人来说,这只是一个提示。我没有设法获取添加和删除的行的行号,但我确实设法得到一个字符串,其中只包含添加和删除的行,而没有其他行没有更改。
这只是通过添加以下行来完成的:
df.setContext(0);
在我上面提供的代码段
之前 df.format(diff);
答案 1 :(得分:5)
你需要在diff结果的A行索引和B行索引之间做区别:
int linesAdded = 0;
int linesDeleted = 0;
int filesChanged = 0;
try {
repo = new FileRepository(new File("repo/.git"));
RevWalk rw = new RevWalk(repo);
RevCommit commit = rw.parseCommit(repo.resolve("486817d67b")); // Any ref will work here (HEAD, a sha1, tag, branch)
RevCommit parent = rw.parseCommit(commit.getParent(0).getId());
DiffFormatter df = new DiffFormatter(DisabledOutputStream.INSTANCE);
df.setRepository(repo);
df.setDiffComparator(RawTextComparator.DEFAULT);
df.setDetectRenames(true);
List<DiffEntry> diffs;
diffs = df.scan(parent.getTree(), commit.getTree());
filesChanged = diffs.size();
for (DiffEntry diff : diffs) {
for (Edit edit : df.toFileHeader(diff).toEditList()) {
linesDeleted += edit.getEndA() - edit.getBeginA();
linesAdded += edit.getEndB() - edit.getBeginB();
}
}
} catch (IOException e1) {
throw new RuntimeException(e1);
}
答案 2 :(得分:0)
我是这样做的,但我不知道它是否正确
public void linesChangeInFile(Git git, List<RevCommit> commits, String fileName, String pathRepository) {
try {
List<RevCommit> commitsComparer = new ArrayList<>();
List<String> linesChange = new ArrayList<>();
for (int i = 0; i < commits.size() - 1; i++) {
ObjectId commitIDOld = commits.get(i).getId();
if (Validador.isFileExistInCommit(commits.get(i), getRepository(), fileName)) {
if (i != commits.size() - 1 && !commitsComparer.contains(commits.get(i))) {
ObjectId commitIDNew = commits.get(i + 1);
commitsComparer.add(commits.get(i));
linesChange.add(diff(git, commitIDOld.getName(), commitIDNew.getName(), fileName));
}
try (final FileInputStream input = new FileInputStream(pathRepository + "\\" + fileName)) {
currentLines = IOUtils.readLines(input, "UTF-8").size();
}
}
}
Integer sumLinesAdd = 0;
Integer sumLinesDel = 0;
for (String lineChange : linesChange) {
String[] lChange = lineChange.split(";");
sumLinesAdd += Integer.parseInt(lChange[0]);
sumLinesDel += Integer.parseInt(lChange[1]);
}
System.out.println("Lines Add total:" + sumLinesAdd);
System.out.println("Lines Del total:" + sumLinesDel);
System.out.println("Total lines change:" + (sumLinesAdd + sumLinesDel));
} catch (RevisionSyntaxException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private String diff(Git git, String commitIDOld, String commitIDNew, String fileName) {
int linesAdded = 0;
int linesDeleted = 0;
DiffFormatter df = null;
try {
AbstractTreeIterator oldTreeParser = prepareTreeParser(getRepository(), commitIDOld);
AbstractTreeIterator newTreeParser = prepareTreeParser(getRepository(), commitIDNew);
List<DiffEntry> diffs = git.diff().setOldTree(oldTreeParser).setNewTree(newTreeParser)
.setPathFilter(PathFilter.create(fileName)).call();
df = new DiffFormatter(DisabledOutputStream.INSTANCE);
df.setRepository(getRepository());
df.setDiffComparator(RawTextComparator.DEFAULT);
df.setDetectRenames(true);
for (DiffEntry entry : diffs) {
// System.out.println("Entry: " + entry + ", from: " + entry.getOldId() + ", to:
// " + entry.getNewId());
// try (DiffFormatter formatter = new DiffFormatter(System.out)) {
// formatter.setContext(0);
// formatter.setRepository(repository);
// formatter.format(entry);
// }
for (Edit edit : df.toFileHeader(entry).toEditList()) {
linesDeleted += edit.getEndA() - edit.getBeginA();
linesAdded += edit.getEndB() - edit.getBeginB();
}
}
} catch (IOException | GitAPIException e) {
System.err.println("Error:" + e.getMessage());
}
return linesAdded + ";" + linesDeleted;
}