2009-11-06 8 views
23

Il ya quelque temps je cherchais un embeddable distributed version control system in Java, et je pense que je l'ai trouvé dans JGit, qui est une implémentation Java pure de git. Cependant, il n'y a pas beaucoup d'exemples de code ou de tutoriels. Comment puis-je utiliser JGit pour récupérer la version HEAD d'un fichier donné (comme svn cat ou hg cat)?Comment "chatter" un fichier dans JGit?

Je suppose que cela implique un peu de marche sur arbre et que je cherche un échantillon de code.

+1

Les développeurs sont assez rapides pour répondre sur la liste de diffusion: https://dev.eclipse.org/mailman/listinfo/egit-dev. Je vous suggère de l'essayer. –

Répondre

18

Malheureusement la réponse de Thilo ne fonctionne pas avec la dernière API JGit. Voici la solution que j'ai trouvée:

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) 

J'aimerais que ce soit plus simple.

+28

Qui dans le monde a conçu cette API? – Jochen

+1

Savez-vous ce que fait la nième valeur de treeWalk.getObjectId (nth)? (c'est-à-dire quels sont les cas où nous passons une valeur à treeWalk.getObjectId plus grand que 0?) –

+0

@DinisCruz 'TreeWalk' peut marcher sur plus d'un arbre (en appelant' addTree' plusieurs fois). Dans ce cas, vous pouvez utiliser 'getObjectId (N)' pour obtenir l'ID d'objet de l'arbre N (qui peut être le même ou différent, selon les arbres). – robinst

3

Il y a quelques informations à JGit Tutorial (mais cela n'est aussi vraiment utile ni complet et probablement périmé puisqu'ils sont passés à eclipse où aucune documentation n'est encore disponible).

5

Compris par moi-même. L'API est assez bas niveau, mais il est pas trop mal:

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

Cela semble être un exemple désuet avec la version actuelle de JGit. L'API a un peu changé, attention. –

+1

@Jonathan Dumaine: S'il vous plaît mettre à jour le poste si nécessaire (et vous savez comment) – Thilo

4

J'ai commencé à écrire une bibliothèque appelée gitective qui contient de nombreux helpers pour travailler avec les blobs, les validations et les arbres en utilisant JGit et qui est sous licence MIT et disponible sur GitHub.

Obtenir le contenu du fichier dans la tête commit

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

obtenir le contenu d'un fichier sur une branche

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

Diff deux fichiers

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); 

D'autres exemples d'utilitaires fournis sont détaillés dans le README.

+0

Ça a l'air sympa. Si je n'avais pas déjà écrit mon projet jGit, je l'aurais certainement utilisé. –

11

J'ai suivi @ et de Thilo @ réponse de morisil pour obtenir cela, compatible avec 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(); 

Je n'ai pas testé la version Java, mais il devrait fonctionner. Il se traduit par

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

dans clojure (en suivant la même configuration que la section supérieure), ce qui fonctionne.

+0

Fonctionne bien! Je suis allé directement au fichier: 'FileOutputStream fileOS = new FileOutputStream (chemin); if (treewalk! = Null) {repo.open (treewalk.getObjectId (0)). CopyTo (fileOS);} 'then' fileOS.close; ' –

+0

Plus de questions Java doivent être répondues dans Clojure. – user12341234

15

est ici une version simplifiée de la réponse de @ morisil, en utilisant certains des concepts de Rions @directed et testé avec 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 est un objet de référentiel tel que créé dans les autres réponses.

+1

Cela semble bon, sauf pour renvoyer getBytes() alors que le type de retour est String. Notez que vous devez également appeler 'release' sur' walk' et 'treeWalk' pour libérer des ressources. Pour ne le faire qu'une seule fois, appelez 'ObjectReader reader = repo.newObjectReader()' et passez-le à Revwalk et Treewalk au lieu du référentiel. Puis appelez 'reader.release()' dans un bloc finally. – robinst

+0

@robinst: Merci beaucoup de l'avoir signalé - corrigé. – creinig

+0

RevWalk doit également être libéré, déplacer l'appel à 'newObjectReader' et utiliser' new RevWalk (reader) 'à la place. – robinst

Questions connexes