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