refs: Fix issue when packing weak tags Weak tags (e.g. tags that point directly to a normal object instead of a tag object) were failing to be packed.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
diff --git a/src/refs.c b/src/refs.c
index 9661988..00b9ff6 100644
--- a/src/refs.c
+++ b/src/refs.c
@@ -746,7 +746,7 @@ static int packed_write_ref(reference_oid *ref, git_filebuf *file)
*/
static int packed_find_peel(reference_oid *ref)
{
- git_tag *tag;
+ git_object *object;
int error;
if (ref->ref.type & GIT_REF_HAS_PEEL)
@@ -760,25 +760,32 @@ static int packed_find_peel(reference_oid *ref)
return GIT_SUCCESS;
/*
- * Find the tag in the repository. The tag must exist,
- * otherwise this reference is broken and we shouldn't
- * pack it.
+ * Find the tagged object in the repository
*/
- error = git_tag_lookup(&tag, ref->ref.owner, &ref->oid);
+ error = git_object_lookup(&object, ref->ref.owner, &ref->oid, GIT_OBJ_ANY);
if (error < GIT_SUCCESS)
return GIT_EOBJCORRUPTED;
/*
- * Find the object pointed at by this tag
+ * If the tagged object is a Tag object, we need to resolve it;
+ * if the ref is actually a 'weak' ref, we don't need to resolve
+ * anything.
*/
- git_oid_cpy(&ref->peel_target, git_tag_target_oid(tag));
- ref->ref.type |= GIT_REF_HAS_PEEL;
+ if (git_object_type(object) == GIT_OBJ_TAG) {
+ git_tag *tag = (git_tag *)object;
- /*
- * The reference has now cached the resolved OID, and is
- * marked at such. When written to the packfile, it'll be
- * accompanied by this resolved oid
- */
+ /*
+ * Find the object pointed at by this tag
+ */
+ git_oid_cpy(&ref->peel_target, git_tag_target_oid(tag));
+ ref->ref.type |= GIT_REF_HAS_PEEL;
+
+ /*
+ * The reference has now cached the resolved OID, and is
+ * marked at such. When written to the packfile, it'll be
+ * accompanied by this resolved oid
+ */
+ }
return GIT_SUCCESS;
}
@@ -1419,6 +1426,10 @@ int git_reference_delete(git_reference *ref)
assert(ref);
if (ref->type & GIT_REF_PACKED) {
+ /* load the existing packfile */
+ if ((error = packed_load(ref->owner)) < GIT_SUCCESS)
+ return error;
+
git_hashtable_remove(ref->owner->references.packfile, ref->name);
error = packed_write(ref->owner);
} else {
diff --git a/tests/resources/testrepo.git/refs/tags/point_to_blob b/tests/resources/testrepo.git/refs/tags/point_to_blob
new file mode 100644
index 0000000..f874a3f
--- /dev/null
+++ b/tests/resources/testrepo.git/refs/tags/point_to_blob
@@ -0,0 +1 @@
+1385f264afb75a56a5bec74243be9b367ba4ca08
diff --git a/tests/t10-refs.c b/tests/t10-refs.c
index 2797cd8..a6a5601 100644
--- a/tests/t10-refs.c
+++ b/tests/t10-refs.c
@@ -456,6 +456,11 @@ BEGIN_TEST(pack1, "create a packfile from all the loose rn a repo")
must_be_true((reference->type & GIT_REF_PACKED) == 0);
must_be_true(strcmp(reference->name, loose_tag_ref_name) == 0);
+ /*
+ * We are now trying to pack also a loose reference
+ * called `points_to_blob`, to make sure we can properly
+ * pack weak tags
+ */
must_pass(git_reference_packall(repo));
/* Ensure the packed-refs file exists */
@@ -877,10 +882,10 @@ BEGIN_TEST(list0, "try to list all the references in our test repo")
printf("# %s\n", ref_list.strings[i]);
}*/
- /* We have exactly 7 refs in total if we include the packed ones:
+ /* We have exactly 8 refs in total if we include the packed ones:
* there is a reference that exists both in the packfile and as
* loose, but we only list it once */
- must_be_true(ref_list.count == 7);
+ must_be_true(ref_list.count == 8);
git_strarray_free(&ref_list);
git_repository_free(repo);