libgit2 icon indicating copy to clipboard operation
libgit2 copied to clipboard

Tree lookup fails with "fake" repositories since 1.6.1

Open oreiche opened this issue 2 years ago • 1 comments

Reproduction steps

The following C code passes with libgit2 <=1.5.2 and fails with >= 1.6.1

#include <git2.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(int argc, const char *argv[]) {
  char template[] = "/tmp/tmpdir.XXXXXX";
  char *tmpdir = mkdtemp(template);

  git_libgit2_init();

  git_oid blob_id;
  git_oid tree_id;
  git_odb *odb = NULL;
  { // create test repo and obtain odb
    git_repository *repo = NULL;
    if (git_repository_init(&repo, tmpdir, /*bare does not matter*/0) != 0) {
      fprintf(stderr, "Could not initialize repository: %s\n",
              git_error_last()->message);
      return 1;
    }
    if (git_repository_odb(&odb, repo) != 0) {
      fprintf(stderr, "Could not open ODB: %s\n", git_error_last()->message);
      return 1;
    }
    if (git_odb_write(&blob_id, odb, "foo", 3, GIT_OBJECT_BLOB) != 0) {
       fprintf(stderr, "Could not write blob: %s\n",
               git_error_last()->message);
       return 1;
    }
    git_treebuilder *tb = NULL;
    if (git_treebuilder_new(&tb, repo, NULL) != 0) {
      fprintf(stderr, "Could not create tree builder: %s\n",
              git_error_last()->message);
      return 1;
    }
    if (git_treebuilder_insert(NULL, tb, "foo", &blob_id, GIT_FILEMODE_BLOB) !=
        0) {
      fprintf(stderr, "Could not insert blob foo: %s\n",
              git_error_last()->message);
      return 1;
    }
    if (git_treebuilder_write(&tree_id, tb) != 0) {
      fprintf(stderr, "Could not write tree: %s\n", git_error_last()->message);
      return 1;
    }
    git_treebuilder_free(tb);
    git_repository_free(repo);
  }

  git_repository *repo = NULL;
  //if (git_repository_open(&repo, tmpdir) != 0) { // "real" repo works
  if (git_repository_wrap_odb(&repo, odb) != 0) {  // "fake" repo fails
    fprintf(stderr, "Could not create \"fake\" repository: %s\n",
            git_error_last()->message);
    return 1;
  }

  git_blob *blob = NULL;
  int retb = git_blob_lookup(&blob, repo, &blob_id);
  printf("Blob lookup: %s\n", retb == 0 ? "success" : "failed");
  if (retb != 0) {
    fprintf(stderr, "Could not lookup blob: %s\n", git_error_last()->message);
  }

  git_tree *tree = NULL;
  int rett = git_tree_lookup(&tree, repo, &tree_id);
  printf("Tree lookup: %s\n", rett == 0 ? "success" : "failed");
  if (rett != 0) {
    fprintf(stderr, "Could not lookup tree: %s\n", git_error_last()->message);
  }

  git_tree_free(tree);
  git_blob_free(blob);
  git_odb_free(odb);
  git_repository_free(repo);

  git_libgit2_shutdown();

  return 0;
}
Could not lookup tree: failed to parse tree: can't parse filemode

When using git_repository_open() instead of git_repository_wrap_odb() everything works as expected. Only trees are affected, blob lookup works fine in both cases. Possibly related to https://github.com/libgit2/libgit2/issues/6543.

Expected behavior

The tree lookup should succeed.

Actual behavior

The tree is not found, although present.

Version of libgit2 (release number or SHA1)

1.6.1 - 1.6.4

Operating system(s) tested

Ubuntu 22.04, Debian 11, ArchLinux

oreiche avatar May 03 '23 09:05 oreiche

Created pull request https://github.com/libgit2/libgit2/pull/6554 to fix the issue.

oreiche avatar May 03 '23 11:05 oreiche

Fixed via #6554

ethomson avatar Feb 20 '24 10:02 ethomson