"GOT", but the "O" is a cute, smiling pufferfish. Index | Thread | Search

From:
Stefan Sperling <stsp@stsp.name>
Subject:
fix 'gotadmin pack' when only tags are given
To:
gameoftrees@openbsd.org
Date:
Sat, 28 Aug 2021 18:46:14 +0200

Download raw body.

Thread
Fix 'gotadmin pack' not packing any objects if all arguments are tags.

Found while looking for a possible cause for naddy's problem with
a blob missing from the packfile during 'got send'. This is likely
an unrelated issue though.

ok?
 
diff 6378bdf19a77839e7225c8c6286fc27107d5e727 b79fa35cbeeb48aad417ec3185e8a8d3028aac66
blob - 1455b6df378eb19d397ce2e3d3588af5a0256490
blob + cbb0aacfeab41c254c9cbdd3d7c206b9db2e081e
--- lib/pack_create.c
+++ lib/pack_create.c
@@ -527,9 +527,10 @@ load_tag(struct got_pack_metavec *v, struct got_object
 
 	switch (got_object_tag_get_object_type(tag)) {
 	case GOT_OBJ_TYPE_COMMIT:
-		err = load_commit(NULL, idset,
-		    got_object_tag_get_object_id(tag), repo,
-		    loose_obj_only, cancel_cb, cancel_arg);
+		/*
+		 * Commits should already be loaded since findtwixt()
+		 * adds them to the object ID list.
+		 */
 		break;
 	case GOT_OBJ_TYPE_TREE:
 		err = load_tree(v, idset, got_object_tag_get_object_id(tag),
@@ -689,11 +690,29 @@ findtwixt(struct got_object_id ***res, int *nres,
 		err = got_object_get_type(&obj_type, repo, id);
 		if (err)
 			return err;
-		if (obj_type != GOT_OBJ_TYPE_COMMIT)
-			continue;
-		err = queue_commit_id(&ids, id, COLOR_KEEP, repo);
-		if (err)
-			goto done;
+		if (obj_type == GOT_OBJ_TYPE_TAG) {
+			struct got_tag_object *tag;
+			err = got_object_open_as_tag(&tag, repo, id);
+			if (err)
+				return err;
+			if (got_object_tag_get_object_type(tag) !=
+			    GOT_OBJ_TYPE_COMMIT) {
+				got_object_tag_close(tag);
+				continue;
+			}
+			err = queue_commit_id(&ids,
+			    got_object_tag_get_object_id(tag),
+			    COLOR_KEEP, repo);
+			got_object_tag_close(tag);
+			if (err)
+				goto done;
+		} else {
+			if (obj_type != GOT_OBJ_TYPE_COMMIT)
+				continue;
+			err = queue_commit_id(&ids, id, COLOR_KEEP, repo);
+			if (err)
+				goto done;
+		}
 	}		
 	for (i = 0; i < ntail; i++) {
 		struct got_object_id *id = tail[i];
@@ -702,11 +721,29 @@ findtwixt(struct got_object_id ***res, int *nres,
 		err = got_object_get_type(&obj_type, repo, id);
 		if (err)
 			return err;
-		if (obj_type != GOT_OBJ_TYPE_COMMIT)
-			continue;
-		err = queue_commit_id(&ids, id, COLOR_DROP, repo);
-		if (err)
-			goto done;
+		if (obj_type == GOT_OBJ_TYPE_TAG) {
+			struct got_tag_object *tag;
+			err = got_object_open_as_tag(&tag, repo, id);
+			if (err)
+				return err;
+			if (got_object_tag_get_object_type(tag) !=
+			    GOT_OBJ_TYPE_COMMIT) {
+				got_object_tag_close(tag);
+				continue;
+			}
+			err = queue_commit_id(&ids,
+			    got_object_tag_get_object_id(tag),
+			    COLOR_DROP, repo);
+			got_object_tag_close(tag);
+			if (err)
+				goto done;
+		} else {
+			if (obj_type != GOT_OBJ_TYPE_COMMIT)
+				continue;
+			err = queue_commit_id(&ids, id, COLOR_DROP, repo);
+			if (err)
+				goto done;
+		}
 	}
 
 	while (!STAILQ_EMPTY(&ids)) {
blob - 597e601e0fefb3fbe64e77e4c05e3ae7103dd8b3
blob + 0b3cf21479c89fe8f08a52f82b87f75a1cba8425
--- regress/cmdline/pack.sh
+++ regress/cmdline/pack.sh
@@ -579,6 +579,104 @@ test_pack_bad_ref() {
 	test_done "$testroot" "$ret"
 }
 
+test_pack_tags_only() {
+	local testroot=`test_init pack_tags_only`
+	local commit0=`git_show_head $testroot/repo`
+
+	got tag -r $testroot/repo -m 1.0 1.0 >/dev/null
+
+	# no pack files should exist yet
+	ls $testroot/repo/.git/objects/pack/ > $testroot/stdout
+	ret="$?"
+	if [ "$ret" != "0" ]; then
+		test_done "$testroot" "$ret"
+		return 1
+	fi
+	echo -n > $testroot/stdout.expected
+	cmp -s $testroot/stdout.expected $testroot/stdout
+	ret="$?"
+	if [ "$ret" != "0" ]; then
+		diff -u $testroot/stdout.expected $testroot/stdout
+		test_done "$testroot" "$ret"
+		return 1
+	fi
+
+	got branch -r $testroot/repo mybranch
+	ret="$?"
+	if [ "$ret" != "0" ]; then
+		test_done "$testroot" "$ret"
+		return 1
+	fi
+
+	got checkout -b mybranch $testroot/repo $testroot/wt > /dev/null
+	ret="$?"
+	if [ "$ret" != "0" ]; then
+		test_done "$testroot" "$ret"
+		return 1
+	fi
+
+	echo a new line >> $testroot/wt/alpha
+	(cd $testroot/wt && got commit -m "edit alpha" >/dev/null)
+	local commit1=`git_show_branch_head $testroot/repo mybranch`
+
+	gotadmin pack -r $testroot/repo 1.0 > $testroot/stdout
+	ret="$?"
+	if [ "$ret" != "0" ]; then
+		echo "gotadmin pack failed unexpectedly" >&2
+		test_done "$testroot" "$ret"
+		return 1
+	fi
+	packname=`grep ^Wrote $testroot/stdout | cut -d ' ' -f2`
+	gotadmin listpack $testroot/repo/.git/objects/pack/pack-$packname \
+		> $testroot/stdout
+
+	tree1=`got cat -r $testroot/repo $commit1 | grep ^tree | \
+		cut -d ' ' -f2`
+	alpha1=`got tree -r $testroot/repo -i -c $commit1 | \
+		grep "[0-9a-f] alpha$" | cut -d' ' -f 1`
+	excluded_ids="$alpha1 $commit1 $tree1"
+	for id in $excluded_ids; do
+		ret=0
+		if grep -q ^$id $testroot/stdout; then
+			echo "found excluded object $id in pack file" >&2
+			ret=1
+		fi
+		if [ "$ret" = "1" ]; then
+			break
+		fi
+	done
+	if [ "$ret" = "1" ]; then
+		test_done "$testroot" "$ret"
+		return 1
+	fi
+
+	tree0=`got cat -r $testroot/repo $commit0 | grep ^tree | \
+		cut -d ' ' -f2`
+	included_ids=`got tree -r $testroot/repo -c $commit0 -R -i | \
+		cut -d ' ' -f 1`
+	included_ids="$included_ids $commit0 $tree0"
+	for obj_id in $included_ids; do
+		for id in $excluded_ids; do
+			if [ "$obj_id" = "$id" ]; then
+				excluded=1
+				break
+			fi
+		done
+		if [ "$excluded" = "1" ]; then
+			continue
+		fi
+		if grep -q ^$obj_id $testroot/stdout; then
+			continue
+		fi
+		echo "included object $obj_id was not packed" >&2
+		ret=1
+		break
+	done
+
+	test_done "$testroot" "$ret"
+}
+
+
 test_parseargs "$@"
 run_test test_pack_all_loose_objects
 run_test test_pack_exclude
@@ -587,3 +685,4 @@ run_test test_pack_ambiguous_arg
 run_test test_pack_loose_only
 run_test test_pack_all_objects
 run_test test_pack_bad_ref
+run_test test_pack_tags_only