Commit d79f1da65ac83145e2e2b7fb246f2485a0a0156d

Vicent Marti 2011-04-08T12:14:33

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.

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