2009-11-06 58 views
23

後來我一直在尋找embeddable distributed version control system in Java, ,我想我已經在JGit中找到它了,它是純粹的git實現。 但是,示例代碼或教程沒有多少內容。如何在JGit中「貓」一個文件?

如何使用JGit檢索某個文件的HEAD版本(就像svn cathg cat)?

我想這涉及到一些rev-tree-walking,並且正在尋找代碼示例。

+1

開發人員很快就可以在郵件列表上找到答案:https://dev.eclipse.org/mailman/listinfo/egit-dev。我建議你試試看。 – 2009-11-07 16:44:04

回答

18

不幸的是,Thilo的答案不適用於最新的JGit API。這裏是我找到的解決方案:

File repoDir = new File("test-git"); 
// open the repository 
Repository repository = new Repository(repoDir); 
// find the HEAD 
ObjectId lastCommitId = repository.resolve(Constants.HEAD); 
// now we have to get the commit 
RevWalk revWalk = new RevWalk(repository); 
RevCommit commit = revWalk.parseCommit(lastCommitId); 
// and using commit's tree find the path 
RevTree tree = commit.getTree(); 
TreeWalk treeWalk = new TreeWalk(repository); 
treeWalk.addTree(tree); 
treeWalk.setRecursive(true); 
treeWalk.setFilter(PathFilter.create(path)); 
if (!treeWalk.next()) { 
    return null; 
} 
ObjectId objectId = treeWalk.getObjectId(0); 
ObjectLoader loader = repository.open(objectId); 

// and then one can use either 
InputStream in = loader.openStream() 
// or 
loader.copyTo(out) 

我希望它更簡單。

+28

世界上誰設計了這個API? – Jochen 2012-04-19 22:59:22

+1

你知道treeWalk.getObjectId(nth)的第n個值嗎? (即,我們將值傳遞給大於0的treeWalk.getObjectId的情況是什麼) – 2013-07-15 22:50:39

+0

@DinisCruz'TreeWalk'可以遍歷多個樹(通過多次調用addTree)。在這種情況下,您可以使用'getObjectId(N)'從樹N(根據樹可能相同或不同)獲取對象ID。 – robinst 2013-08-16 13:07:16

3

有一些信息在JGit Tutorial(但也沒有真正的幫助也沒有完整,可能已經過時,因爲他們切換到eclipse沒有文檔可用)。

5

自己弄明白了。該API是相當低級的,但它不是太糟糕:

File repoDir = new File("test-git/.git"); 
// open the repository 
Repository repo = new Repository(repoDir); 
// find the HEAD 
Commit head = repo.mapCommit(Constants.HEAD); 
// retrieve the tree in HEAD 
Tree tree = head.getTree(); 
// find a file (as a TreeEntry, which contains the blob object id) 
TreeEntry entry = tree.findBlobMember("b/test.txt"); 
// use the blob id to read the file's data 
byte[] data = repo.openBlob(entry.getId()).getBytes(); 
+2

這似乎是當前JGit版本的過時示例。 API已經改變了一點,要小心。 – 2011-03-24 18:33:49

+1

@Jonathan Dumaine:如有必要,請更新帖子(你知道如何) – Thilo 2011-03-25 02:29:31

4

我已經開始編寫一個名爲gitective的庫,其中包含許多使用JGit處理Blob,提交和樹的幫助程序,並且已獲得MIT許可並可在GitHub上獲得。在頭文件的

獲取內容提交

Repository repo = new FileRepository("/repos/project/.git"); 
String content = BlobUtils.getHeadContent(repo, "src/Buffer.java"); 

分支上獲取文件的內容

Repository repo = new FileRepository("/repos/project/.git"); 
String content = BlobUtils.getContent(repo, "master", "src/Buffer.java"); 

DIFF兩個文件

Repository repo = new FileRepository("/repos/project/.git"); 
ObjectId current = BlobUtils.getId(repo, "master", "Main.java"); 
ObjectId previous = BlobUtils.getId(repo, "master~1", "Main.java"); 
Collection<Edit> edit = BlobUtils.diff(repo, previous, current); 

更多的實用程序示例詳見README

+0

它看起來不錯。如果我還沒有寫我的jGit項目,我肯定會使用它。 – 2013-07-25 21:58:18

11

我跟着@蒂洛的和@ morisil的回答得到這個,兼容JGit 1.2.0:

File repoDir = new File("test-git/.git"); 
// open the repository 
Repository repo = new Repository(repoDir); 
// find the HEAD 
Commit head = repo.mapCommit(Constants.HEAD); 
// retrieve the tree in HEAD 
Tree tree = head.getTree(); 

// 1.2.0 api version here 
// find a file (as a TreeEntry, which contains the blob object id) 
TreeWalk treewalk = TreeWalk.forPath(repo, "b/test.txt", tree); 
// use the blob id to read the file's data 
byte[] data = repo.open(treewalk.getObjectId(0)).getBytes(); 

我沒有測試的Java版本,但它應該工作。它翻譯自

(.getBytes (.open repo (.getObjectId (TreeWalk/forPath repo "b/test.txt" tree) 0))) 

在clojure(遵循與頂部相同的設置),它工作。

+0

工程太棒了!我直接去了file:'FileOutputStream fileOS = new FileOutputStream(path);如果(treewalk!= null){repo.open(treewalk.getObjectId(0))。copyTo(fileOS);}'然後'fileOS.close;' – 2013-10-09 07:53:15

+0

更多的Java問題應該在Clojure中得到解答。 – user12341234 2017-10-13 13:27:52

15

這裏的@ morisil的回答的一個簡化版本,使用一些從@directed笑的概念,並與JGit 2.2.0測試:

private String fetchBlob(String revSpec, String path) throws MissingObjectException, IncorrectObjectTypeException, 
     IOException { 

    // Resolve the revision specification 
    final ObjectId id = this.repo.resolve(revSpec); 

    // Makes it simpler to release the allocated resources in one go 
    ObjectReader reader = this.repo.newObjectReader(); 

    try { 
     // Get the commit object for that revision 
     RevWalk walk = new RevWalk(reader); 
     RevCommit commit = walk.parseCommit(id); 

     // Get the revision's file tree 
     RevTree tree = commit.getTree(); 
     // .. and narrow it down to the single file's path 
     TreeWalk treewalk = TreeWalk.forPath(reader, path, tree); 

     if (treewalk != null) { 
      // use the blob id to read the file's data 
      byte[] data = reader.open(treewalk.getObjectId(0)).getBytes(); 
      return new String(data, "utf-8"); 
     } else { 
      return ""; 
     } 
    } finally { 
     reader.release(); 
    } 
} 

repo是在其他的答案中創建一個資源庫對象。

+1

看起來不錯,除了在返回類型爲String時返回getBytes()。請注意,您還必須在'walk'和'treeWalk'上調用'release'來釋放資源。爲了只需要這樣做一次,調用ObjectReader reader = repo.newObjectReader()並將其傳遞給Revwalk和Treewalk,而不是存儲庫。然後在finally塊中調用'reader.release()'。 – robinst 2013-08-16 13:03:35

+0

@robinst:非常感謝您指出 - 修復它。 – creinig 2013-09-03 11:07:57

+0

RevWalk也需要發佈,將調用移至'newObjectReader'並改爲使用'new RevWalk(reader)'。 – robinst 2013-09-04 11:02:56