Download raw body.
send "unreachable" tags fails
Stefan Sperling <stsp@stsp.name> writes: > On Tue, Sep 14, 2021 at 09:45:49AM +0200, Omar Polo wrote: >> Hello, >> >> `got send' fails to send tags that were tagged on deleted branches. I >> don't know how widespread it is but for a couple of projects I'm used to >> tag bugfix releases by branching off the last release, cherrypicking the >> changes, tag the minor release and delete the branch. I understand that >> probably is not a workflow intended for got, and that I'm not in the >> targeted audience, but anyway. >> >> Here's how to reproduce. I'm using a "testing" repo over at my site, >> but any repository would do > > Thank you, Omar! Below is a regression test for this issue, and a fix. Can confirm it works, thanks! > There was an error in the load_tag() function: It didn't load any commits > associated with the tag. So commits which were only reachable via a tag > were never sent to the server. The server refused the pack file because > the objects the tag was pointing at were missing. Any referenced objects > are required to either already exist server-side or be shipped along in > the pack file. > > diff 824d5f776c8195a3faa8c0b167888dbb99542482 /home/stsp/src/got > blob - 4ab44ac470c99d3b1842ebaef994127428153e04 > file + lib/pack_create.c > --- lib/pack_create.c > +++ lib/pack_create.c > @@ -527,7 +527,7 @@ 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, > + err = load_commit(v, idset, > got_object_tag_get_object_id(tag), repo, > loose_obj_only, cancel_cb, cancel_arg); > break; > blob - ce7b085beed403260f19800f8e25f6d484e5e1d5 > file + regress/cmdline/send.sh > --- regress/cmdline/send.sh > +++ regress/cmdline/send.sh > @@ -723,6 +723,124 @@ EOF > test_done "$testroot" "$ret" > } > > +test_send_tag_of_deleted_branch() { > + local testroot=`test_init send_tag_of_deleted_branch` > + local testurl=ssh://127.0.0.1/$testroot > + local commit_id=`git_show_head $testroot/repo` > + > + got clone -q $testurl/repo $testroot/repo-clone > + ret="$?" > + if [ "$ret" != "0" ]; then > + echo "got clone command failed unexpectedly" >&2 > + test_done "$testroot" "$ret" > + return 1 > + fi > + cat > $testroot/repo/.git/got.conf <<EOF > +remote "origin" { > + protocol ssh > + server 127.0.0.1 > + repository "$testroot/repo-clone" > +} > +EOF > + got branch -r $testroot/repo foo > + > + # modify alpha on branch foo > + got checkout -b foo $testroot/repo $testroot/wt > /dev/null > + echo boo >> $testroot/wt/beta > + (cd $testroot/wt && got commit -m 'changed beta on branch foo' \ > + > /dev/null) > + local commit_id2=`git_show_branch_head $testroot/repo foo` > + > + # tag HEAD commit of branch foo > + got tag -r $testroot/repo -c foo -m '1.0' 1.0 > /dev/null > + tag_id=`got ref -r $testroot/repo -l | grep "^refs/tags/1.0" \ > + | tr -d ' ' | cut -d: -f2` > + > + # delete the branch; commit is now only reachable via tags/1.0 > + got branch -r $testroot/repo -d foo > /dev/null > + > + # unrelated change on master branch, then try sending this branch > + # and the tag > + echo "modified alpha" > $testroot/repo/alpha > + git_commit $testroot/repo -m "modified alpha" > + local commit_id3=`git_show_head $testroot/repo` > + > + got send -q -r $testroot/repo -T > $testroot/stdout 2> $testroot/stderr > + ret="$?" > + if [ "$ret" != "0" ]; then > + echo "got send command failed unexpectedly" >&2 > + test_done "$testroot" "$ret" > + return 1 > + fi > + > + echo -n > $testroot/stdout.expected > + cmp -s $testroot/stdout $testroot/stdout.expected > + ret="$?" > + if [ "$ret" != "0" ]; then > + diff -u $testroot/stdout.expected $testroot/stdout > + test_done "$testroot" "$ret" > + return 1 > + fi > + > + got ref -l -r $testroot/repo > $testroot/stdout > + if [ "$ret" != "0" ]; then > + echo "got ref command failed unexpectedly" >&2 > + test_done "$testroot" "$ret" > + return 1 > + fi > + > + wt_uuid=`(cd $testroot/wt && got info | grep 'UUID:' | \ > + cut -d ':' -f 2 | tr -d ' ')` > + echo "HEAD: refs/heads/master" > $testroot/stdout.expected > + echo "refs/got/worktree/base-$wt_uuid: $commit_id2" \ > + >> $testroot/stdout.expected > + echo "refs/heads/master: $commit_id3" >> $testroot/stdout.expected > + echo "refs/remotes/origin/master: $commit_id3" \ > + >> $testroot/stdout.expected > + echo "refs/tags/1.0: $tag_id" >> $testroot/stdout.expected > + > + cmp -s $testroot/stdout $testroot/stdout.expected > + ret="$?" > + if [ "$ret" != "0" ]; then > + diff -u $testroot/stdout.expected $testroot/stdout > + test_done "$testroot" "$ret" > + return 1 > + fi > + > + got ref -l -r $testroot/repo-clone > $testroot/stdout > + if [ "$ret" != "0" ]; then > + echo "got ref command failed unexpectedly" >&2 > + test_done "$testroot" "$ret" > + return 1 > + fi > + > + echo "HEAD: refs/heads/master" > $testroot/stdout.expected > + echo "refs/heads/master: $commit_id3" >> $testroot/stdout.expected > + echo "refs/remotes/origin/HEAD: refs/remotes/origin/master" \ > + >> $testroot/stdout.expected > + echo "refs/remotes/origin/master: $commit_id" \ > + >> $testroot/stdout.expected > + echo "refs/tags/1.0: $tag_id" >> $testroot/stdout.expected > + > + cmp -s $testroot/stdout $testroot/stdout.expected > + ret="$?" > + if [ "$ret" != "0" ]; then > + diff -u $testroot/stdout.expected $testroot/stdout > + test_done "$testroot" "$ret" > + return 1 > + fi > + > + got tag -l -r $testroot/repo-clone | grep ^tag | sort > $testroot/stdout > + echo "tag 1.0 $tag_id" > $testroot/stdout.expected > + > + cmp -s $testroot/stdout $testroot/stdout.expected > + ret="$?" > + if [ "$ret" != "0" ]; then > + diff -u $testroot/stdout.expected $testroot/stdout > + fi > + test_done "$testroot" "$ret" > +} > + > test_send_new_branch() { > local testroot=`test_init send_new_branch` > local testurl=ssh://127.0.0.1/$testroot > @@ -1241,6 +1359,7 @@ run_test test_send_rebase_required_overwrite > run_test test_send_delete > run_test test_send_clone_and_send > run_test test_send_tags > +run_test test_send_tag_of_deleted_branch > run_test test_send_new_branch > run_test test_send_all_branches > run_test test_send_to_empty_repo
send "unreachable" tags fails