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