java - jgit documentation
¿Cómo “cat” un archivo en JGit? (7)
Aquí hay una versión más simple de la respuesta de @morisil, utilizando algunos de los conceptos de @directed laugh''s y probados con 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
es un objeto Repository como se crea en las otras respuestas.
Hace un tiempo, estaba buscando un sistema de control de versiones distribuido y JGit en Java , y creo que lo he encontrado en JGit , que es una implementación Java de git. Sin embargo, no hay mucho en el código de ejemplo o tutoriales.
¿Cómo puedo usar JGit para recuperar la versión HEAD de un determinado archivo (como svn cat
o hg cat
)?
Supongo que esto implica algo de rev-tree-walking y estoy buscando un ejemplo de código.
Comencé a escribir una biblioteca llamada gitective que contiene muchos ayudantes para trabajar con blobs, confirmaciones y árboles usando JGit y tiene licencia MIT y está disponible en GitHub.
Obtener el contenido del archivo en HEAD commit
Repository repo = new FileRepository("/repos/project/.git");
String content = BlobUtils.getHeadContent(repo, "src/Buffer.java");
Obtener el contenido de un archivo en una rama
Repository repo = new FileRepository("/repos/project/.git");
String content = BlobUtils.getContent(repo, "master", "src/Buffer.java");
Diferencia dos archivos
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);
Más ejemplos de las utilidades proporcionadas se detallan en el README .
Desafortunadamente, la respuesta de Thilo no funciona con la última API de JGit. Aquí está la solución que encontré:
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)
Ojalá fuera más sencillo.
Hay algo de información en JGit Tutorial (pero eso tampoco es realmente útil ni completo y probablemente está desactualizado, ya que cambiaron a JGit donde aún no hay documentación disponible).
Lo descubrí por mí mismo. La API es bastante baja, pero no está tan 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();
Puede leer el contenido de una ruta de archivo determinada de la siguiente manera. Tenga en cuenta que TreeWalk puede ser nulo si no se encontró una ruta en el árbol dado. Por lo que requiere un manejo específico.
public String readFile(RevCommit commit, String filepath) throws IOException {
try (TreeWalk walk = TreeWalk.forPath(repo, filepath, commit.getTree())) {
if (walk != null) {
byte[] bytes = repo.open(walk.getObjectId(0)).getBytes();
return new String(bytes, StandardCharsets.UTF_8);
} else {
throw new IllegalArgumentException("No path found.");
}
}
}
Por ejemplo:
ObjectId head = repo.resolve(Constants.HEAD);
RevCommit last = repo.parseCommit(head);
readFile(last, "docs/README.md")
Esta respuesta está escrita con JGit 4.8.0.
Seguí la respuesta de @ Thilo y @ morisil para obtener esto, compatible con 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();
No probé la versión de Java pero debería funcionar. Se traduce de
(.getBytes (.open repo (.getObjectId (TreeWalk/forPath repo "b/test.txt" tree) 0)))
en clojure (siguiendo la misma configuración que la sección superior), que funciona.