2009-11-06 2 views
23

A a back назад Я искал embeddable distributed version control system in Java, , и я думаю, что нашел его в JGit, который является чистой реализацией Java git. Тем не менее, не так много примеров кода или учебников.Как «поместить» файл в JGit?

Как я могу использовать JGit для извлечения версии HEAD определенного файла (точно так же, как svn cat или hg cat whould do)?

Я предполагаю, что это связано с некоторой реверсивной ходьбой, и я ищу образец кода.

+1

Разработчики довольно быстро отвечают на список рассылки: https://dev.eclipse.org/mailman/listinfo/egit-dev. Я предлагаю вам попробовать. –

ответ

18

К сожалению, ответ Тил не работает с последним 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

+1

Знаете ли вы, что делает n-е значение из treeWalk.getObjectId (nth)? (то есть, в каких случаях мы передаем значение treeWalk.getObjectId больше 0?) –

+0

@DinisCruz 'TreeWalk' может перемещаться по нескольким деревьям (вызывая многократное использование' addTree'). В этом случае вы можете использовать 'getObjectId (N)', чтобы получить идентификатор объекта из дерева N (который может быть тем же или другим, в зависимости от деревьев). – robinst

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 немного изменился, остерегайтесь. –

+1

@Jonathan Dumaine: Пожалуйста, обновите сообщение, если необходимо (и знаете, как) – Thilo

4

Я начал писать библиотеку под названием gitective, которая содержит много помощников для работы с блобами, коммитами и деревьями с использованием JGit и лицензирована 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, я бы определенно использовал это. –

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

Отлично работает! Я сразу же записал файл: FileOutputStream fileOS = новый FileOutputStream (путь); if (treewalk! = Null) {repo.open (treewalk.getObjectId (0)). CopyTo (fileOS);} 'then' fileOS.close; ' –

+0

В Clojure необходимо ответить на другие вопросы Java. – user12341234

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 является Repository объекта, как созданные в других ответах.

+1

Выглядит хорошо, за исключением возврата getBytes(), в то время как тип возврата - String. Обратите внимание, что вы также должны вызывать 'release' на' walk' и 'treeWalk' для освобождения ресурсов. Чтобы сделать это только один раз, вызовите 'ObjectReader reader = repo.newObjectReader()' и передайте это в Revwalk и Treewalk вместо репозитория. Затем вызовите 'reader.release()' в блоке finally. – robinst

+0

@robinst: Большое спасибо за то, что указали, что это исправлено. – creinig

+0

Также необходимо освободить RevWalk, переместить вызов 'newObjectReader' вверх и использовать вместо него новый RevWalk (reader). – robinst

Смежные вопросы