通过比较git项目两个版本,找出变动的代码,并统计代码的增量和减量
jgit版本
<dependency>
<groupId>org.eclipse.jgit</groupId>
<artifactId>org.eclipse.jgit</artifactId>
<version>4.4.1.201607150455-r</version>
</dependency>
<dependency>
<groupId>org.gitective</groupId>
<artifactId>gitective-core</artifactId>
<version>0.9.9</version>
</dependency>
测试代码:
package com.yy.jgit;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.diff.DiffEntry;
import org.eclipse.jgit.diff.DiffFormatter;
import org.eclipse.jgit.diff.Edit;
import org.eclipse.jgit.diff.EditList;
import org.eclipse.jgit.diff.RawTextComparator;
import org.eclipse.jgit.lib.ObjectReader;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.patch.FileHeader;
import org.eclipse.jgit.patch.HunkHeader;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevTree;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.treewalk.AbstractTreeIterator;
import org.eclipse.jgit.treewalk.CanonicalTreeParser;
import org.junit.Before;
import org.junit.Test;
import junit.framework.TestCase;
/**
* @author <a href= "mailto:" style="color:##E0E;">牵手无奈</a>
* @date 2016年8月9日 下午3:08:35
* @version V1.0
*/
public class JgitTest extends TestCase {
String gitFilePath = "D:\\workspace3\\feedback-classify";
File root = new File(gitFilePath);
Git git;
Repository repository ;
@Before
public void init(){
try {
git =Git.open(root);
repository = git.getRepository();
} catch (IOException e) {
e.printStackTrace();
}
}
@Test
public void test3() throws Exception{
init();
RevWalk walk = new RevWalk(repository);
List<RevCommit> commitList = new ArrayList<>();
//获取最近提交的两次记录
Iterable<RevCommit> commits = git.log().setMaxCount(2).call();
for(RevCommit commit:commits){
commitList.add(commit);
System.out.println(commit.getFullMessage());
System.out.println(commit.getAuthorIdent().getWhen());
}
if(commitList.size()==2){
AbstractTreeIterator newTree = prepareTreeParser(commitList.get(0));
AbstractTreeIterator oldTree = prepareTreeParser(commitList.get(1));
List<DiffEntry> diff = git.diff().setOldTree(oldTree).setNewTree(newTree).setShowNameAndStatusOnly(true).call();
ByteArrayOutputStream out = new ByteArrayOutputStream();
DiffFormatter df = new DiffFormatter(out);
//设置比较器为忽略空白字符对比(Ignores all whitespace)
df.setDiffComparator(RawTextComparator.WS_IGNORE_ALL);
df.setRepository(git.getRepository());
System.out.println("------------------------------start-----------------------------");
//每一个diffEntry都是第个文件版本之间的变动差异
for (DiffEntry diffEntry : diff) {
//打印文件差异具体内容
df.format(diffEntry);
String diffText = out.toString("UTF-8");
System.out.println(diffText);
//获取文件差异位置,从而统计差异的行数,如增加行数,减少行数
FileHeader fileHeader = df.toFileHeader(diffEntry);
List<HunkHeader> hunks = (List<HunkHeader>) fileHeader.getHunks();
int addSize = 0;
int subSize = 0;
for(HunkHeader hunkHeader:hunks){
EditList editList = hunkHeader.toEditList();
for(Edit edit : editList){
subSize += edit.getEndA()-edit.getBeginA();
addSize += edit.getEndB()-edit.getBeginB();
}
}
System.out.println("addSize="+addSize);
System.out.println("subSize="+subSize);
System.out.println("------------------------------end-----------------------------");
out.reset();
}
}
}
public AbstractTreeIterator prepareTreeParser(RevCommit commit){
System.out.println(commit.getId());
try (RevWalk walk = new RevWalk(repository)) {
System.out.println(commit.getTree().getId());
RevTree tree = walk.parseTree(commit.getTree().getId());
CanonicalTreeParser oldTreeParser = new CanonicalTreeParser();
try (ObjectReader oldReader = repository.newObjectReader()) {
oldTreeParser.reset(oldReader, tree.getId());
}
walk.dispose();
return oldTreeParser;
}catch (Exception e) {
// TODO: handle exception
}
return null;
}
//统计指定版本代码总行数
<pre name="code" class="java">public long getAllFileLines(RevCommit commit){
TreeWalk treeWalk = new TreeWalk(repository);
long size = 0;
try {
treeWalk.addTree(commit.getTree());
treeWalk.setRecursive(true);
MutableObjectId id = new MutableObjectId();
while(treeWalk.next()){
treeWalk.getObjectId(id, 0);
String filePath = treeWalk.getPathString();
if(filePathFilter.accept(new ChangeFile(filePath))){
int lines =countAddLine(BlobUtils.getContent(repository, id.toObjectId()));
size +=lines;
}
}
} catch (MissingObjectException e) {
m_logger.error("error:"+e);
} catch (IncorrectObjectTypeException e) {
m_logger.error("error:"+e);
} catch (CorruptObjectException e) {
m_logger.error("error:"+e);
} catch (IOException e) {
m_logger.error("error:"+e);
}
return size;
}
/**统计非空白行数
* @param content
* @return
*/
public int countAddLine(String content){
char[] chars = content.toCharArray();
int sum = 0;
boolean notSpace = false;
for(char ch: chars){
if(ch =='\n' && notSpace){
sum++;
notSpace = false;
}else if(ch > ' '){
notSpace = true;
}
}
//最后一行没有换行时,如果有非空白字符,则+1
if(notSpace){
sum++;
}
return sum;
}