Commit 29e0594f3da103f1ece51fe40ba09faa1c691972

Stefan Sperling 2022-04-09T17:34:51

make gotadmin pack -x option work with tag arguments

diff --git a/lib/pack_create.c b/lib/pack_create.c
index 2367bba..63e8791 100644
--- a/lib/pack_create.c
+++ b/lib/pack_create.c
@@ -1217,6 +1217,37 @@ append_id(struct got_object_id *id, void *data, void *arg)
 }
 
 static const struct got_error *
+queue_commit_or_tag_id(struct got_object_id *id, int color,
+    struct got_object_id_queue *ids, struct got_repository *repo)
+{
+	const struct got_error *err;
+	struct got_tag_object *tag = NULL;
+	int obj_type;
+
+	err = got_object_get_type(&obj_type, repo, id);
+	if (err)
+		return err;
+
+	if (obj_type == GOT_OBJ_TYPE_TAG) {
+		err = got_object_open_as_tag(&tag, repo, id);
+		if (err)
+			return err;
+		obj_type = got_object_tag_get_object_type(tag);
+		id = got_object_tag_get_object_id(tag);
+	}
+
+	if (obj_type == GOT_OBJ_TYPE_COMMIT) {
+		err = queue_commit_id(ids, id, color, repo);
+		if (err)
+			goto done;
+	}
+done:
+	if (tag)
+		got_object_tag_close(tag);
+	return err;
+}
+
+static const struct got_error *
 findtwixt(struct got_object_id ***res, int *nres, int *ncolored,
     struct got_object_id **head, int nhead,
     struct got_object_id **tail, int ntail,
@@ -1228,7 +1259,7 @@ findtwixt(struct got_object_id ***res, int *nres, int *ncolored,
 	struct got_object_id_queue ids;
 	struct got_object_idset *keep, *drop;
 	struct got_object_qid *qid;
-	int i, ncolor, nkeep, obj_type;
+	int i, ncolor, nkeep;
 
 	STAILQ_INIT(&ids);
 	*res = NULL;
@@ -1249,25 +1280,16 @@ findtwixt(struct got_object_id ***res, int *nres, int *ncolored,
 		struct got_object_id *id = head[i];
 		if (id == NULL)
 			continue;
-		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);
+		err = queue_commit_or_tag_id(id, COLOR_KEEP, &ids, repo);
 		if (err)
 			goto done;
 	}		
+
 	for (i = 0; i < ntail; i++) {
 		struct got_object_id *id = tail[i];
 		if (id == NULL)
 			continue;
-		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);
+		err = queue_commit_or_tag_id(id, COLOR_DROP, &ids, repo);
 		if (err)
 			goto done;
 	}
diff --git a/regress/cmdline/pack.sh b/regress/cmdline/pack.sh
index 3f911d5..943365b 100755
--- a/regress/cmdline/pack.sh
+++ b/regress/cmdline/pack.sh
@@ -170,6 +170,112 @@ test_pack_exclude() {
 	test_done "$testroot" "$ret"
 }
 
+test_pack_exclude_tag() {
+	local testroot=`test_init pack_exclude_tag`
+	local commit0=`git_show_head $testroot/repo`
+
+	# no pack files should exist yet
+	ls $testroot/repo/.git/objects/pack/ > $testroot/stdout
+	ret=$?
+	if [ $ret -ne 0 ]; then
+		test_done "$testroot" "$ret"
+		return 1
+	fi
+	echo -n > $testroot/stdout.expected
+	cmp -s $testroot/stdout.expected $testroot/stdout
+	ret=$?
+	if [ $ret -ne 0 ]; then
+		diff -u $testroot/stdout.expected $testroot/stdout
+		test_done "$testroot" "$ret"
+		return 1
+	fi
+
+	got tag -r $testroot/repo -m 1.0 -c master 1.0 > /dev/null
+	ret=$?
+	if [ $ret -ne 0 ]; then
+		test_done "$testroot" "$ret"
+		return 1
+	fi
+
+	got branch -r $testroot/repo mybranch
+	ret=$?
+	if [ $ret -ne 0 ]; then
+		test_done "$testroot" "$ret"
+		return 1
+	fi
+
+	got checkout -b mybranch $testroot/repo $testroot/wt > /dev/null
+	ret=$?
+	if [ $ret -ne 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)
+
+	gotadmin pack -r $testroot/repo -x refs/tags/1.0 > $testroot/stdout
+	ret=$?
+	if [ $ret -ne 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
+
+	tree0=`got cat -r $testroot/repo $commit0 | grep ^tree | \
+		cut -d ' ' -f2`
+	tag0=`got tag -l -r $testroot/repo | grep ^tag | cut -d ' ' -f3`
+	excluded_ids=`got tree -r $testroot/repo -c $commit0 -R -i | \
+		cut -d ' ' -f 1`
+	excluded_ids="$excluded_ids $commit0 $tree0 $tag0"
+	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 -eq 1 ]; then
+			break
+		fi
+	done
+	if [ $ret -eq 1 ]; then
+		test_done "$testroot" "$ret"
+		return 1
+	fi
+
+	for d in $testroot/repo/.git/objects/[0-9a-f][0-9a-f]; do
+		id0=`basename $d`
+		ret=0
+		for e in `ls $d`; do
+			obj_id=${id0}${e}
+			excluded=0
+			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 "loose object $obj_id was not packed" >&2
+			ret=1
+			break
+		done
+		if [ $ret -eq 1 ]; then
+			break
+		fi
+	done
+
+	test_done "$testroot" "$ret"
+}
+
 test_pack_include() {
 	local testroot=`test_init pack_include`
 	local commit0=`git_show_head $testroot/repo`
@@ -573,6 +679,7 @@ test_pack_bad_ref() {
 test_parseargs "$@"
 run_test test_pack_all_loose_objects
 run_test test_pack_exclude
+run_test test_pack_exclude_tag
 run_test test_pack_include
 run_test test_pack_ambiguous_arg
 run_test test_pack_loose_only