commit bcf34b0ec978d055514a2759ed37d7b8a5f4ea08 from: Stefan Sperling date: Thu Mar 26 17:10:59 2020 UTC make 'got fetch' restore our copy of the remote HEAD if the copy was deleted commit - 3789fd730ae3acb3dd47ddf9f5da50d1453afd71 commit + bcf34b0ec978d055514a2759ed37d7b8a5f4ea08 blob - 8c3efa9c087f5a9d3b959c3a6a8a27f3b3d73264 blob + 69c9927afc8fdb351891da171a6ce68595a56e05 --- got/got.c +++ got/got.c @@ -1508,33 +1508,54 @@ update_symref(const char *refname, struct got_referenc { const struct got_error *err = NULL, *unlock_err; struct got_reference *symref; + int symref_is_locked = 0; err = got_ref_open(&symref, repo, refname, 1); - if (err) - return err; - - if (strcmp(got_ref_get_symref_target(symref), - got_ref_get_name(target_ref)) == 0) - goto done; + if (err) { + if (err->code != GOT_ERR_NOT_REF) + return err; + err = got_ref_alloc_symref(&symref, refname, target_ref); + if (err) + goto done; - err = got_ref_change_symref(symref, got_ref_get_name(target_ref)); - if (err) - goto done; + err = got_ref_write(symref, repo); + if (err) + goto done; - err = got_ref_write(symref, repo); - if (err) - goto done; + if (verbosity >= 0) + printf("Created reference %s: %s\n", + got_ref_get_name(symref), + got_ref_get_symref_target(symref)); + } else { + symref_is_locked = 1; - if (verbosity >= 0) - printf("Updated reference %s: %s\n", got_ref_get_name(symref), - got_ref_get_symref_target(symref)); + if (strcmp(got_ref_get_symref_target(symref), + got_ref_get_name(target_ref)) == 0) + goto done; + + err = got_ref_change_symref(symref, + got_ref_get_name(target_ref)); + if (err) + goto done; + + err = got_ref_write(symref, repo); + if (err) + goto done; + + if (verbosity >= 0) + printf("Updated reference %s: %s\n", + got_ref_get_name(symref), + got_ref_get_symref_target(symref)); + + } done: - unlock_err = got_ref_unlock(symref); - if (unlock_err && err == NULL) - err = unlock_err; + if (symref_is_locked) { + unlock_err = got_ref_unlock(symref); + if (unlock_err && err == NULL) + err = unlock_err; + } got_ref_close(symref); return err; - return NULL; } __dead static void @@ -1912,13 +1933,7 @@ cmd_fetch(int argc, char *argv[]) if (pack_hash == NULL) { if (verbosity >= 0) printf("Already up-to-date\n"); - if (delete_refs) - error = delete_missing_refs(&refs, &symrefs, - remote, verbosity, repo); - goto done; - } - - if (verbosity >= 0) { + } else if (verbosity >= 0) { error = got_object_id_str(&id_str, pack_hash); if (error) goto done; blob - 4efa1f083052561dedf24eac5bef0786bc66a4bb blob + d46a15108d913f2686fdf20a1cf6fbe75e121e1e --- regress/cmdline/fetch.sh +++ regress/cmdline/fetch.sh @@ -889,7 +889,63 @@ function test_fetch_update_headref { diff -u $testroot/stdout.expected $testroot/stdout fi test_done "$testroot" "$ret" +} + +function test_fetch_headref_deleted_locally { + local testroot=`test_init fetch_headref_deleted_locally` + 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 + + got ref -l -r $testroot/repo-clone > $testroot/stdout + echo "HEAD: refs/heads/master" > $testroot/stdout.expected + echo "refs/heads/master: $commit_id" >> $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 + + 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 -r $testroot/repo-clone -d refs/remotes/origin/HEAD + + got fetch -q -r $testroot/repo-clone + ret="$?" + if [ "$ret" != "0" ]; then + echo "got fetch command failed unexpectedly" >&2 + test_done "$testroot" "$ret" + return 1 + fi + got ref -l -r $testroot/repo-clone > $testroot/stdout + + echo "HEAD: refs/heads/master" > $testroot/stdout.expected + echo "refs/heads/master: $commit_id" >> $testroot/stdout.expected + # refs/remotes/origin/HEAD has been restored: + echo "refs/remotes/origin/HEAD: refs/remotes/origin/master" \ + >> $testroot/stdout.expected + echo "refs/remotes/origin/master: $commit_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" } run_test test_fetch_basic @@ -902,3 +958,4 @@ run_test test_fetch_update_tag run_test test_fetch_reference run_test test_fetch_replace_symref run_test test_fetch_update_headref +run_test test_fetch_headref_deleted_locally