From: Stefan Sperling Subject: fix cloning of repositories with dangling head reference To: gameoftrees@openbsd.org Date: Mon, 7 Nov 2022 20:53:52 +0100 Make 'got clone -b' work for repositories which lack a HEAD reference that points to an existing branch. Regression test which reproduces the problem is included. Patch fixes this error: got-fetch-pack: could not find any branches to fetch Also ensures that default config files get created in this case. ok? diff ca7cfae029f0cbca1f65f326025744f627b69d92 593af7bd3baeb8314b7ef9a11fe0559a6ba9557d commit - ca7cfae029f0cbca1f65f326025744f627b69d92 commit + 593af7bd3baeb8314b7ef9a11fe0559a6ba9557d blob - c0c38ea47dfbd657ee0c14d0e8829767ad691ae6 blob + 1e29e64a3d1e97b5787efdf1754a70fe1615d190 --- got/got.c +++ got/got.c @@ -1856,6 +1856,7 @@ cmd_clone(int argc, char *argv[]) goto done; } if (pe == NULL) { + struct got_reference *target_ref = NULL; /* * We failed to set the HEAD reference. If we asked for * a set of wanted branches use the first of one of those @@ -1863,12 +1864,12 @@ cmd_clone(int argc, char *argv[]) */ TAILQ_FOREACH(pe, &wanted_branches, entry) { const char *target = pe->path; - struct got_reference *target_ref; error = got_ref_open(&target_ref, repo, target, 0); if (error) { if (error->code == GOT_ERR_NOT_REF) { error = NULL; + target_ref = NULL; continue; } goto done; @@ -1881,6 +1882,20 @@ cmd_clone(int argc, char *argv[]) goto done; break; } + + if (!fpa.configs_created && target_ref) { + error = create_config_files(fpa.config_info.proto, + fpa.config_info.host, fpa.config_info.port, + fpa.config_info.remote_repo_path, + fpa.config_info.git_url, + fpa.config_info.fetch_all_branches, + fpa.config_info.mirror_references, + fpa.config_info.symrefs, + fpa.config_info.wanted_branches, + fpa.config_info.wanted_refs, fpa.repo); + if (error) + goto done; + } } if (verbosity >= 0) blob - 6cac7e61e2407f2c053f4cf8256c67ae466489a6 blob + 4fa55782d6cfa72a92ffedfb310e3ac0e508e55c --- libexec/got-fetch-pack/got-fetch-pack.c +++ libexec/got-fetch-pack/got-fetch-pack.c @@ -373,7 +373,8 @@ fetch_pack(int fd, int packfd, uint8_t *pack_sha1, break; } } - continue; + if (default_branch) + continue; } if (strstr(refname, "^{}")) { if (chattygot) { blob - 35d7c0ba41e646078b5beea834a05d4d28891363 blob + 58ef8f4044adf772026d09c3bfc6ee1dc2e947ef --- regress/cmdline/clone.sh +++ regress/cmdline/clone.sh @@ -754,6 +754,79 @@ test_parseargs "$@" test_done "$testroot" "$ret" } +test_clone_dangling_headref() { + local testroot=`test_init clone_dangling_headref` + local testurl=ssh://127.0.0.1/$testroot + local commit_id=`git_show_head $testroot/repo` + + got branch -r $testroot/repo -d master > /dev/null + got branch -r $testroot/repo -c $commit_id foo + + got ref -l -r $testroot/repo > $testroot/stdout + + echo "HEAD: refs/heads/master" > $testroot/stdout.expected + echo "refs/heads/foo: $commit_id" >> $testroot/stdout.expected + # refs/heads/master is missing because it was deleted above + + cmp -s $testroot/stdout $testroot/stdout.expected + ret=$? + if [ $ret -ne 0 ]; then + diff -u $testroot/stdout.expected $testroot/stdout + test_done "$testroot" "$ret" + return 1 + fi + + got clone -q -b foo $testurl/repo $testroot/repo-clone + ret=$? + if [ $ret -ne 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/foo: $commit_id" >> $testroot/stdout.expected + echo "refs/remotes/origin/foo: $commit_id" >> $testroot/stdout.expected + + cat > $testroot/got.conf.expected < $testroot/config.expected <