commit 2f1457c6ccfe722888511926c09af843da3bee0d from: Stefan Sperling date: Fri Aug 27 16:48:53 2021 UTC allow deletion of refs/remotes/ branches with got branch -d Also, make requirements for branch name arguments more flexible. Absolute reference names are now accepted. ok naddy@ commit - a099809f2873564368fcd20d3d7be32ce4a5bc12 commit + 2f1457c6ccfe722888511926c09af843da3bee0d blob - 6cbbf9b01db61e8aab969ebcb566b2c29f7940a4 blob + 0dcc266a93cd2bf21804499b69922111b8658e0a --- got/got.1 +++ got/got.1 @@ -1014,7 +1014,16 @@ Local branches are managed via references which live i reference namespace. The .Cm got branch -command creates or deletes references in this namespace only. +command creates references in this namespace only. +.Pp +When deleting branches the specified +.Ar name +is searched in the +.Dq refs/heads +reference namespace first. +If no corresponding branch is found the +.Dq refs/remotes +namespace will be searched next. .Pp If invoked in a work tree without any arguments, print the name of the work tree's current branch. @@ -1073,7 +1082,14 @@ with one the following annotations: .It \(a~ Ta work tree's base commit is out-of-date .El .It Fl d Ar name -Delete the branch with the specified name from the repository. +Delete the branch with the specified +.Ar name +from the +.Dq refs/heads +or +.Dq refs/remotes +reference namespace. +.Pp Only the branch reference is deleted. Any commit, tree, and blob objects belonging to the branch remain in the repository and may be removed separately with blob - 5f57676c71bfe6ae726a39f6cba1b9fb3dafb730 blob + eaabe5b6cd871e178683532ded10fc75eb8f864d --- got/got.c +++ got/got.c @@ -5732,15 +5732,40 @@ delete_branch(struct got_repository *repo, struct got_ { const struct got_error *err = NULL; struct got_reference *ref = NULL; - char *refname; + char *refname, *remote_refname = NULL; + if (strncmp(branch_name, "refs/", 5) == 0) + branch_name += 5; + if (strncmp(branch_name, "heads/", 6) == 0) + branch_name += 6; + else if (strncmp(branch_name, "remotes/", 8) == 0) + branch_name += 8; + if (asprintf(&refname, "refs/heads/%s", branch_name) == -1) return got_error_from_errno("asprintf"); - err = got_ref_open(&ref, repo, refname, 0); - if (err) + if (asprintf(&remote_refname, "refs/remotes/%s", + branch_name) == -1) { + err = got_error_from_errno("asprintf"); goto done; + } + err = got_ref_open(&ref, repo, refname, 0); + if (err) { + const struct got_error *err2; + if (err->code != GOT_ERR_NOT_REF) + goto done; + /* + * Keep 'err' intact such that if neither branch exists + * we report "refs/heads" rather than "refs/remotes" in + * our error message. + */ + err2 = got_ref_open(&ref, repo, remote_refname, 0); + if (err2) + goto done; + err = NULL; + } + if (worktree && strcmp(got_worktree_get_head_ref_name(worktree), got_ref_get_name(ref)) == 0) { @@ -5754,6 +5779,7 @@ done: if (ref) got_ref_close(ref); free(refname); + free(remote_refname); return err; } @@ -5772,6 +5798,9 @@ add_branch(struct got_repository *repo, const char *br */ if (branch_name[0] == '-') return got_error_path(branch_name, GOT_ERR_REF_NAME_MINUS); + + if (strncmp(branch_name, "refs/heads/", 11) == 0) + branch_name += 11; if (asprintf(&refname, "refs/heads/%s", branch_name) == -1) { err = got_error_from_errno("asprintf"); blob - a766241048c3ca1094a34b2c4977c80ec15d69e5 blob + fd9564bb22907b2388e1e98c18ad7bce29eb6417 --- regress/cmdline/branch.sh +++ regress/cmdline/branch.sh @@ -59,7 +59,7 @@ test_branch_create() { fi # Create a branch based on the work tree's branch - (cd $testroot/wt && got branch -n anotherbranch) + (cd $testroot/wt && got branch -n refs/heads/anotherbranch) ret="$?" if [ "$ret" != "0" ]; then test_done "$testroot" "$ret" @@ -250,7 +250,7 @@ test_branch_delete() { got branch -d branch2 -r $testroot/repo > $testroot/stdout ret="$?" if [ "$ret" != "0" ]; then - echo "got update command failed unexpectedly" + echo "got branch command failed unexpectedly" test_done "$testroot" "$ret" return 1 fi @@ -284,7 +284,7 @@ test_branch_delete() { > $testroot/stdout 2> $testroot/stderr ret="$?" if [ "$ret" = "0" ]; then - echo "got update succeeded unexpectedly" + echo "got branch succeeded unexpectedly" test_done "$testroot" "$ret" return 1 fi @@ -295,7 +295,62 @@ test_branch_delete() { ret="$?" if [ "$ret" != "0" ]; then diff -u $testroot/stderr.expected $testroot/stderr + test_done "$testroot" "$ret" + return 1 fi + + got ref -r $testroot/repo -c master refs/remotes/origin/master + got ref -r $testroot/repo -c branch1 refs/remotes/origin/branch1 + got ref -r $testroot/repo -c branch3 refs/remotes/origin/branch3 + + got ref -l -r $testroot/repo > $testroot/stdout + echo "HEAD: refs/heads/master" > $testroot/stdout.expected + echo "refs/heads/branch1: $commit_id" >> $testroot/stdout.expected + echo "refs/heads/branch3: $commit_id" >> $testroot/stdout.expected + echo "refs/heads/master: $commit_id" >> $testroot/stdout.expected + echo "refs/remotes/origin/branch1: $commit_id" \ + >> $testroot/stdout.expected + echo "refs/remotes/origin/branch3: $commit_id" \ + >> $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 branch -d origin/branch1 -r $testroot/repo > $testroot/stdout + ret="$?" + if [ "$ret" != "0" ]; then + echo "got branch command failed unexpectedly" + test_done "$testroot" "$ret" + return 1 + fi + + got branch -d refs/remotes/origin/branch3 -r $testroot/repo \ + > $testroot/stdout + ret="$?" + if [ "$ret" != "0" ]; then + echo "got branch command failed unexpectedly" + test_done "$testroot" "$ret" + return 1 + fi + + got ref -l -r $testroot/repo > $testroot/stdout + echo "HEAD: refs/heads/master" > $testroot/stdout.expected + echo "refs/heads/branch1: $commit_id" >> $testroot/stdout.expected + echo "refs/heads/branch3: $commit_id" >> $testroot/stdout.expected + echo "refs/heads/master: $commit_id" >> $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" } @@ -340,7 +395,7 @@ test_branch_delete_packed() { (cd $testroot/repo && git pack-refs --all) - got branch -d branch2 -r $testroot/repo > $testroot/stdout + got branch -d refs/heads/branch2 -r $testroot/repo > $testroot/stdout ret="$?" if [ "$ret" != "0" ]; then echo "got update command failed unexpectedly"