commit a1fb16d88f6904f90545c864be8d12c6ea9753b0 from: Stefan Sperling date: Fri May 24 12:51:46 2019 UTC make moved branch head references easier to deal with commit - 7ccf82596168ce763ab082e181aae83836ebdc23 commit + a1fb16d88f6904f90545c864be8d12c6ea9753b0 blob - ebb4bbf8fb93d5fdded2331a037f242e4bb76119 blob + f18db31b991c8c0ff10fc8f0d7545aa15e6ce2d2 --- got/got.1 +++ got/got.1 @@ -469,24 +469,12 @@ This step currently requires .Dl $ git checkout unified-buffer-cache .Dl $ git rebase master .Dl $ git push -f -.Pp -Create a new branch reference for a work tree which has lost -linear ancestry with its recorded branch reference and thus -can no longer be updated: -.Pp -.Dl $ got ref refs/heads/old-branch $(cat .got/base-commit) -.Dl $ got update -b old-branch .Pp Update the work tree to the newly rebased .Dq unified-buffer-cache branch: .Pp .Dl $ got update -b unified-buffer-cache -.Pp -Delete a reference which is no longer needed: -.Pp -.Dl $ got ref -d refs/heads/old-branch -.Pp .Sh SEE ALSO .Xr git-repository 5 .Xr got-worktree 5 blob - 4d034c8af70fd54a7de2623002e97255dca49eaf blob + 16eef0039dc6d2261b9556a71753ea90319564b7 --- got/got.c +++ got/got.c @@ -565,6 +565,46 @@ update_progress(void *arg, unsigned char status, const } static const struct got_error * +switch_head_ref(struct got_reference *head_ref, + struct got_object_id *commit_id, struct got_worktree *worktree, + struct got_repository *repo) +{ + const struct got_error *err = NULL; + char *base_id_str; + int ref_has_moved = 0; + + /* Trivial case: switching between two different references. */ + if (strcmp(got_ref_get_name(head_ref), + got_worktree_get_head_ref_name(worktree)) != 0) { + printf("Switching work tree from %s to %s\n", + got_worktree_get_head_ref_name(worktree), + got_ref_get_name(head_ref)); + return got_worktree_set_head_ref(worktree, head_ref); + } + + err = check_linear_ancestry(commit_id, + got_worktree_get_base_commit_id(worktree), repo); + if (err) { + if (err->code != GOT_ERR_ANCESTRY) + return err; + ref_has_moved = 1; + } + if (!ref_has_moved) + return NULL; + + /* Switching to a rebased branch with the same reference name. */ + err = got_object_id_str(&base_id_str, + got_worktree_get_base_commit_id(worktree)); + if (err) + return err; + printf("Reference %s now points at a different branch\n", + got_worktree_get_head_ref_name(worktree)); + printf("Switching work tree from %s to %s\n", base_id_str, + got_worktree_get_head_ref_name(worktree)); + return NULL; +} + +static const struct got_error * cmd_update(int argc, char *argv[]) { const struct got_error *error = NULL; @@ -632,9 +672,8 @@ cmd_update(int argc, char *argv[]) if (error) goto done; - if (branch_name == NULL) - branch_name = got_worktree_get_head_ref_name(worktree); - error = got_ref_open(&head_ref, repo, branch_name, 0); + error = got_ref_open(&head_ref, repo, branch_name ? branch_name : + got_worktree_get_head_ref_name(worktree), 0); if (error != NULL) goto done; if (commit_id_str == NULL) { @@ -651,12 +690,11 @@ cmd_update(int argc, char *argv[]) goto done; } - if (strcmp(got_ref_get_name(head_ref), - got_worktree_get_head_ref_name(worktree)) != 0) { + if (branch_name) { struct got_object_id *head_commit_id; if (strlen(path) != 0) { - fprintf(stderr, "%s: switching to a different " - "branch requires that the entire work tree " + fprintf(stderr, "%s: switching between branches " + "requires that the entire work tree " "gets updated, not just '%s'\n", getprogname(), path); error = got_error(GOT_ERR_BAD_PATH); @@ -672,10 +710,7 @@ cmd_update(int argc, char *argv[]) error = check_same_branch(commit_id, head_ref, repo); if (error) goto done; - printf("Switching work tree from %s to %s\n", - got_worktree_get_head_ref_name(worktree), - got_ref_get_name(head_ref)); - error = got_worktree_set_head_ref(worktree, head_ref); + error = switch_head_ref(head_ref, commit_id, worktree, repo); if (error) goto done; } else { blob - 21b84dec550e11df0837e1b7f9dc20217e2463d3 blob + b5d808017aca17881058fa3c0276cc3ec7ed3381 --- include/got_error.h +++ include/got_error.h @@ -174,8 +174,8 @@ static const struct got_error { { GOT_ERR_COMMIT_MSG_EMPTY, "commit message cannot be empty" }, { GOT_ERR_DIR_NOT_EMPTY, "directory exists and is not empty" }, { GOT_ERR_COMMIT_NO_CHANGES, "no changes to commit" }, - { GOT_ERR_BRANCH_MOVED, "work tree's branch reference has moved; " - "new branch reference or rebase required" }, + { GOT_ERR_BRANCH_MOVED, "work tree's head reference now points to a " + "different branch; new head reference and/or update -b required" }, { GOT_ERR_OBJ_TOO_LARGE, "object too large" }, }; blob - 1e92b37d93b14ff994cbfaf3cf87b14e5ff846c5 blob + ab518679ea7cb4197f1beebbdeb2d17ff873976f --- regress/cmdline/update.sh +++ regress/cmdline/update.sh @@ -1291,9 +1291,10 @@ function test_update_moved_branch_ref { (cd $testroot/repo2 && git fetch -q --all) echo -n > $testroot/stdout.expected - echo -n "got: work tree's branch reference has moved; " \ + echo -n "got: work tree's head reference now points to a different " \ > $testroot/stderr.expected - echo "new branch reference or rebase required" >> $testroot/stderr.expected + echo "branch; new head reference and/or update -b required" \ + >> $testroot/stderr.expected (cd $testroot/wt && got update > $testroot/stdout 2> $testroot/stderr)