JGit 使用说明

JGit 使用说明

初步

  1. jdk 1.8
  2. 第一次我们需要clone这个git,这个git就是我们的schema集。
  Git git=Git.cloneRepository()
                    .setURI("git号")
                    .setDirectory(new File("gitProject"))
                    .call();

这样的话,这个git工程就被clone到了我们指定的目录。
3. 当然第二次我们不能再clone了,我们只需要打开上次的git工程就可以进行操作。

Git git=Git.open(new File("gitProject"));
  1. 当我们新增或是修改一个文件的时候:
 DirCache index=git.add().addFilepattern("schemas/test.md").call();
 RevCommit commit=git.commit().setMessage("addFile").call();
 git.push().call();

这个新增的文件需要位于我们拉下来的那个git工程里面。

  1. 查看一个文件所有的版本(也就是提交记录):在git的命令行中,我们是通过git log 或是git log –filename来实现。这个通过API的实现方式如下:
git.log().addPath(dir/filename.txt).setMaxCount(num).call();

setMaxCount可以指定返回最近num个版本,addPath则是指定查看文件.返回的是Iterable,我们可以通过其迭代器对其进行遍历。我们需要的是得到每一次变更的时间,message,提交的内部识别码,提交人

            Iterable iterable=git.log().call();
            Iterator iter=iterable.iterator();
            while (iter.hasNext()){
                RevCommit commit=iter.next();
                String email=commit.getAuthorIdent().getEmailAddress();
                String name=commit.getAuthorIdent().getName();  //作者

                String commitEmail=commit.getCommitterIdent().getEmailAddress();//提交者
                String commitName=commit.getCommitterIdent().getName();

                int time=commit.getCommitTime();

                String fullMessage=commit.getFullMessage();
                String shortMessage=commit.getShortMessage();  //返回message的firstLine

                String commitID=commit.getName();  //这个应该就是提交的版本号

                System.out.println("authorEmail:"+email);
                System.out.println("authorName:"+name);
                System.out.println("commitEmail:"+commitEmail);
                System.out.println("commitName:"+commitName);
                System.out.println("time:"+time);
                System.out.println("fullMessage:"+fullMessage);
                System.out.println("shortMessage:"+shortMessage);
                System.out.println("commitID:"+commitID);
            }

结果:这个log我们并没有指定哪一个文件,也没有指定返回多少个,我们可以如前面提到那样指定文件,指定返回个数,但是从结果中我们确实得到我们想要的东西

authorEmail:yulin@DESKTOP-ALAIMHD
authorName:yulin
commitEmail:yulin@DESKTOP-ALAIMHD
commitName:yulin
time:1515468403
fullMessage:addFile
shortMessage:addFile
commitID:d22491b948e8013df552549a753dcafd4d9b3c4b


authorEmail:***
authorName:***
commitEmail:***
commitName:***
time:1515463064
fullMessage:[添加]gitignore文件
shortMessage:[添加]gitignore文件
commitID:be1be26068cd4fb5653c6efd3299f465d5863234

注意这里有这样一个问题,如果你使用了.addPath(dir/filename.txt),也就是你只想得到某个文件的提交。这种方式的确可以实现,如果某一次的提交,包含了多个文件,其中包含了这个文件,该次提交也会被包含到结果其中。(其实这个还是可以理解的。)

  1. 我们得到指定文件的所有版本后,需要去取得每一个版本的变化,这样我们才能显示出每一个版本不同的内容。git命令可以用diff实现,那么在JGit中的调用呢.
    如我们比较一个特定文件最近两次的提交内容的不同。那么我们首先需要得到最近两次的commit。然后根据commit得到变化内容。如下:
   Git git=Git.open(new File("gitProject"));
   Repository repository=git.getRepository();
    List list=new ArrayList();
    Iterable iterable=git.log().addPath("schemas/test1.md").setMaxCount(2).call();
    for(RevCommit revCommit:iterable){
                list.add(revCommit);
        }
    if(list.size()==2){
        AbstractTreeIterator newCommit=getAbstractTreeIterator(list.get(0),repository);
        AbstractTreeIterator oldCommit=getAbstractTreeIterator(list.get(1),repository);
        List diff=git.diff().setOldTree(oldCommit).setNewTree(newCommit).call();
        ByteArrayOutputStream outputStream=new ByteArrayOutputStream();
        DiffFormatter diffFormatter=new DiffFormatter(outputStream);
        //设置比较器为忽略空白字符对比(Ignores all whitespace)
        diffFormatter.setDiffComparator(RawTextComparator.WS_IGNORE_ALL);
        diffFormatter.setRepository(repository); // 这里为什么还要设置它
        for(DiffEntry diffEntry:diff){
            diffFormatter.format(diffEntry);
            System.out.println(outputStream.toString("UTF-8"));
            outputStream.reset();
          }
    }

    git.close();

另外需要通过下面这个方法根据commit得到AbstractTreeIterator,如下:

    public static AbstractTreeIterator getAbstractTreeIterator(RevCommit commit, Repository repository ){
        RevWalk revWalk=new RevWalk(repository);
        CanonicalTreeParser treeParser=null;
        try {
            RevTree revTree=revWalk.parseTree(commit.getTree().getId());
            treeParser=new CanonicalTreeParser();
            treeParser.reset(repository.newObjectReader(),revTree.getId());
            revWalk.dispose();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return treeParser;
    }

通过以上代码,我们可以得到schemas/test1.md文件两次commit内容的不同,结果如下:

diff --git a/schemas/test.md b/schemas/test.md
index e8fce5c..c226794 100644
--- a/schemas/test.md
+++ b/schemas/test.md
@@ -1,4 +1,4 @@
-# JSON测试效率总结
+# JSON测试效率总结  test4

我们可以看到得到的结果的变化内容已经用 - +进行了标注,这与我们平常看到的diff命令结果是相符合的

但是这里就有这样的一个问题,我们虽然通过addPath来得到了某个文件的commit,但是我们得到diff内容是通过commit来的,如果一次commit包含多个文件,那么我们的diff内容自然也会所有更改文件的内容,那么这与我们说的得到某个文件的变化内容就有一定的出入了,但是这是因为我们的一次commit包含多个文件修改导致的。

那么我们能否对DiffEntry的内容进行筛选呢?通过前面的代码我们看到事实上我们的变化内容是通过DiffEntry来得到的,如果一次提交内容包含了多个文件的改变,那么我们也会得到对应数目的DiffEntry,我们需要对DiffEntry进行筛选,从而挑选出对应特定文件的DiffEntry,从而得到特定文件的变化内容,接下来试一试。

  1. 筛选DiffEntry

    发现DiffEntry中有oldPath,newPath这样的属性。

    /** File name of the old (pre-image). */
    protected String oldPath;

    /** File name of the new (post-image). */
    protected String newPath;

那么如果我们得到了文件名,那就就可以根据文件名进行筛选了,如下:

           for(DiffEntry diffEntry:diff){
                diffFormatter.format(diffEntry);
                System.out.println("new Path:____"+diffEntry.getNewPath());
                System.out.println("old path:____"+diffEntry.getOldPath());
                System.out.println(outputStream.toString("UTF-8"));
                outputStream.reset();
            }

结果:确实我们得到了文件名

new Path:____schemas/test.md
old path:____schemas/test.md
diff --git a/schemas/test.md b/schemas/test.md
index e8fce5c..c226794 100644
--- a/schemas/test.md
+++ b/schemas/test.md
@@ -1,4 +1,4 @@
-# JSON测试效率总结
+# JSON测试效率总结  test4
  1. 通过前面我们基本可以得到制指定文件版本之间的差异内容,接下来我们去获取指定文件指定版本的文件内容,以下为示例代码:
 public static ByteArrayOutputStream read(String revision, Git git) {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        Repository repository = null;
        try {
            //gitDir表示git库目录
          //  Git git = Git.open(new File("gitProject"));
            repository = git.getRepository();
            RevWalk walk = new RevWalk(repository);
            ObjectId objId = repository.resolve(revision);
            RevCommit revCommit = walk.parseCommit(objId);
            RevTree revTree = revCommit.getTree();

            //child表示相对git库的文件路径
            TreeWalk treeWalk = TreeWalk.forPath(repository, "schemas/test.md", revTree);
            ObjectId blobId = treeWalk.getObjectId(0);
            ObjectLoader loader = repository.open(blobId);
            loader.copyTo(out);
        } catch (IOException e) {
           e.printStackTrace();
        } catch (JGitInternalException e) {
            e.printStackTrace();
        } finally {
            if (repository != null)
                repository.close();
        }
        return out;
    }


    //调用
     ByteArrayOutputStream outputStream=read("f532e63bac93f05345da1ff665687e69df9732dc",git);
    System.out.println(outputStream.toString("UTF-8"));

我们仍然是通过commitID去获取,不过这里是直接给出了CommitID,我们同样可以像前面的代码那样先获取commit,结果我们确实拿到了这个版本文件的全部内容。(结果太多就不进行展示了)

以上是根据我们的需求进行的相应的git-api调用的调研。

全部代码

import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.LogCommand;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.api.errors.JGitInternalException;
import org.eclipse.jgit.diff.DiffEntry;
import org.eclipse.jgit.diff.DiffFormatter;
import org.eclipse.jgit.diff.RawTextComparator;
import org.eclipse.jgit.dircache.DirCache;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectLoader;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.notes.Note;
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.eclipse.jgit.treewalk.TreeWalk;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class TestOne {
    public static void main(String [] args){
        try {
//            Git git=Git.cloneRepository()
//                    .setURI("git***")
//                    .setDirectory(new File("gitProject"))
//                    .call();

            Git git=Git.open(new File("gitProject"));
//            DirCache index=git.add().addFilepattern("schemas/test.md").call();
//            RevCommit commit=git.commit().setMessage("addFile").call();
//            git.push().call();


//            Iterable iterable=git.log().addPath("schemas/test1.md").setMaxCount(2).call();
//            Iterator iter=iterable.iterator();
//            while (iter.hasNext()){
//                RevCommit commit=iter.next();
//                String email=commit.getAuthorIdent().getEmailAddress();
//                String name=commit.getAuthorIdent().getName();  //作者
//
//                String commitEmail=commit.getCommitterIdent().getEmailAddress();//提交者
//                String commitName=commit.getCommitterIdent().getName();
//
//                int time=commit.getCommitTime();
//
//                String fullMessage=commit.getFullMessage();
//                String shortMessage=commit.getShortMessage();  //返回message的firstLine
//
//                String commitID=commit.getName();  //这个应该就是提交的版本号
//
//                System.out.println("authorEmail:"+email);
//                System.out.println("authorName:"+name);
//                System.out.println("commitEmail:"+commitEmail);
//                System.out.println("commitName:"+commitName);
//                System.out.println("time:"+time);
//                System.out.println("fullMessage:"+fullMessage);
//                System.out.println("shortMessage:"+shortMessage);
//                System.out.println("commitID:"+commitID);
//            }


//            Note note=git.notesShow().call();
//            System.out.println(note.getData().toString());


            // 接下来比如我们需要获得指定文件,最近两个版本之间的差异
//            Repository repository=git.getRepository();
//        List list=new ArrayList();
//        Iterable iterable=git.log().addPath("schemas/test1.md").setMaxCount(2).call();
//        for(RevCommit revCommit:iterable){
//            list.add(revCommit);
//        }
//        if(list.size()==2){
//            AbstractTreeIterator newCommit=getAbstractTreeIterator(list.get(0),repository);
//            AbstractTreeIterator oldCommit=getAbstractTreeIterator(list.get(1),repository);
//            List diff=git.diff().setOldTree(oldCommit).setNewTree(newCommit).call();
//            ByteArrayOutputStream outputStream=new ByteArrayOutputStream();
//            DiffFormatter diffFormatter=new DiffFormatter(outputStream);
//            //设置比较器为忽略空白字符对比(Ignores all whitespace)
//            diffFormatter.setDiffComparator(RawTextComparator.WS_IGNORE_ALL);
//            diffFormatter.setRepository(repository); // 这里为什么还要设置它
//            System.out.println("-----------"+diff.size());
//            for(DiffEntry diffEntry:diff){
//                diffFormatter.format(diffEntry);
//                System.out.println("new Path:____"+diffEntry.getNewPath());
//                System.out.println("old path:____"+diffEntry.getOldPath());
//                System.out.println(outputStream.toString("UTF-8"));
//                outputStream.reset();
//            }
//        }



            ByteArrayOutputStream outputStream=read("f532e63bac93f05345da1ff665687e69df9732dc",git);
            System.out.println(outputStream.toString("UTF-8"));
        git.close();
    } catch (Exception e) {
        e.printStackTrace();
    }

    }


    public static AbstractTreeIterator getAbstractTreeIterator(RevCommit commit, Repository repository ){
        RevWalk revWalk=new RevWalk(repository);
        CanonicalTreeParser treeParser=null;
        try {
            RevTree revTree=revWalk.parseTree(commit.getTree().getId());
            treeParser=new CanonicalTreeParser();
            treeParser.reset(repository.newObjectReader(),revTree.getId());
            revWalk.dispose();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return treeParser;
    }



    public static ByteArrayOutputStream read(String revision, Git git) {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        Repository repository = null;
        try {
            //gitDir表示git库目录
          //  Git git = Git.open(new File("gitProject"));
            repository = git.getRepository();
            RevWalk walk = new RevWalk(repository);
            ObjectId objId = repository.resolve(revision);
            RevCommit revCommit = walk.parseCommit(objId);
            RevTree revTree = revCommit.getTree();

            //child表示相对git库的文件路径
            TreeWalk treeWalk = TreeWalk.forPath(repository, "schemas/test.md", revTree);
            ObjectId blobId = treeWalk.getObjectId(0);
            ObjectLoader loader = repository.open(blobId);
            loader.copyTo(out);
        } catch (IOException e) {
           e.printStackTrace();
        } catch (JGitInternalException e) {
            e.printStackTrace();
        } finally {
            if (repository != null)
                repository.close();
        }
        return out;
    }



}

你可能感兴趣的:(其他)