jgit比较项目不同版本间的差异及统计代码总行数

  • Post author:
  • Post category:其他


通过比较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;
    }



版权声明:本文为u012621115原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。