Pregunta

Hace un tiempo que estaba buscando un sistema integrable distribuido de control de versiones en Java , y creo que lo he encontrado en JGit , que es una implementación Java pura de git. Sin embargo, no hay mucho en el camino de código de ejemplo o tutoriales.

¿Cómo puedo utilizar JGit para recuperar la versión de la cabeza de un determinado archivo (al igual que svn cat o hg cat whould hacer)?

supongo que esto implica algún rev-árbol-caminar y estoy buscando un ejemplo de código.

¿Fue útil?

Solución

Por desgracia, la respuesta de Thilo no funciona con la última API 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)

Me gustaría que fuera más simple.

Otros consejos

Esto es una versión más simple de la respuesta de @ morisil, el uso de algunos de los conceptos de la risa de @directed y probado 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 de repositorio como creado en las otras respuestas.

He seguido @ Thilo de respuesta y de @ morisil para conseguir 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 he probado la versión Java pero debería funcionar. Se traduce del

(.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 hace el trabajo.

lo descubrió por mí mismo. La API es bastante bajo nivel, pero no es tan malo:

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

He comenzado a escribir una biblioteca llamada gitective que contiene muchos ayudantes para trabajar con manchas, se compromete, y árboles utilizando JGit y es el MIT-licencia y está disponible en GitHub.

Obtener el contenido del archivo en la cabeza de cometer

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

Dif 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 utilidades proporcionadas se detallan en la README .

Hay algo de información en JGit Tutorial (pero que también no es ni muy útiles ni completa y probablemente obsoleta ya que cambiaron a Eclipse donde hay documentación está disponible).

Usted puede leer el contenido de una ruta de archivo de la forma siguiente. Por favor, tenga en cuenta que la TreeWalk puede ser nula si no se encontró ningún camino 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 se escribe con JGit 4.8.0.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top