commit cd634f2d6d87577ed25d69f9b9a9d07c990a4223 from: Stefan Sperling via: Thomas Adam date: Sat Mar 30 17:21:23 2024 UTC make 'got status' display interrupted rebase, histedit, and merge operations When an operation is interrupted add a trailing message to status output which displays the operation and branches involved. This information will be useful when diagnosing problem reports and it helps new users with contextualizing multi-operation work tree state. ok op@ commit - 101257039ae01276572124264470185d2b9baaf0 commit + cd634f2d6d87577ed25d69f9b9a9d07c990a4223 blob - 8443d267c1f9a1e49d05b5258a78b6f9e247ae00 blob + 27fee027d191881e30323c0d8436d8803ffe5eca --- got/got.1 +++ got/got.1 @@ -822,6 +822,12 @@ Changes created on top of staged changes are indicated .It MM Ta file was modified after earlier changes have been staged .It MA Ta file was modified after having been staged for addition .El +.Pp +If the work tree contains the results of an interrupted +.Cm got rebase , +.Cm got histedit, or +.Cm got merge +operation then display a message which shows the branches involved. .Pp The options for .Cm got status blob - 9ca2cf86ca1bf61c712330d9933d9bf241a80846 blob + f64718c7a221e24d8bd87dc9cda7479193609c10 --- got/got.c +++ got/got.c @@ -6419,6 +6419,56 @@ print_status(void *arg, unsigned char status, unsigned } print: printf("%c%c %s\n", status, staged_status, path); + return NULL; +} + +static const struct got_error * +show_operation_in_progress(struct got_worktree *worktree, + struct got_repository *repo) +{ + const struct got_error *err; + char *new_base_branch_name = NULL; + char *branch_name = NULL; + int rebase_in_progress, histedit_in_progress, merge_in_progress; + + err = got_worktree_rebase_in_progress(&rebase_in_progress, worktree); + if (err) + return err; + if (rebase_in_progress) { + err = got_worktree_rebase_info(&new_base_branch_name, + &branch_name, worktree, repo); + if (err) + return err; + printf("Work tree is rebasing %s onto %s\n", + branch_name, new_base_branch_name); + } + + err = got_worktree_histedit_in_progress(&histedit_in_progress, + worktree); + if (err) + return err; + if (histedit_in_progress) { + err = got_worktree_histedit_info(&branch_name, worktree, repo); + if (err) + return err; + printf("Work tree is editing the history of %s\n", branch_name); + } + + err = got_worktree_merge_in_progress(&merge_in_progress, + worktree, repo); + if (err) + return err; + if (merge_in_progress) { + err = got_worktree_merge_info(&branch_name, worktree, + repo); + if (err) + return err; + printf("Work tree is merging %s into %s\n", branch_name, + got_worktree_get_head_ref_name(worktree)); + } + + free(new_base_branch_name); + free(branch_name); return NULL; } @@ -6521,6 +6571,10 @@ cmd_status(int argc, char *argv[]) error = got_worktree_status(worktree, &paths, repo, no_ignores, print_status, &st, check_cancelled, NULL); + if (error) + goto done; + + error = show_operation_in_progress(worktree, repo); done: if (pack_fds) { const struct got_error *pack_err = blob - e45d7096cd1e609bd13f07ec1c9dcfcaf5a6b508 blob + d2b62724acbc48c141e49a60bd36765fe2c58cad --- include/got_worktree.h +++ include/got_worktree.h @@ -319,6 +319,9 @@ const struct got_error *got_worktree_rebase_continue(s /* Check whether a, potentially interrupted, rebase operation is in progress. */ const struct got_error *got_worktree_rebase_in_progress(int *, struct got_worktree *); +/* Return information about an in-progress rebase operation. */ +const struct got_error *got_worktree_rebase_info(char **new_base_branch_name, + char **branch_name, struct got_worktree *, struct got_repository *); /* * Merge changes from the commit currently being rebased into the work tree. @@ -391,6 +394,10 @@ const struct got_error *got_worktree_histedit_continue /* Check whether a histedit operation is in progress. */ const struct got_error *got_worktree_histedit_in_progress(int *, struct got_worktree *); +/* Return information about an in-progress histedit operation. */ +const struct got_error *got_worktree_histedit_info( + char **branch_nane, struct got_worktree *, + struct got_repository *); /* * Merge changes from the commit currently being edited into the work tree. @@ -507,6 +514,10 @@ const struct got_error *got_worktree_merge_complete( /* Check whether a merge operation is in progress. */ const struct got_error *got_worktree_merge_in_progress(int *, struct got_worktree *, struct got_repository *); +/* Return information about an in-progress merge operation. */ +const struct got_error * +got_worktree_merge_info(char **branch_name, struct got_worktree *, + struct got_repository *); /* * Prepare for merging a branch into the work tree's current branch: lock the blob - 6d77ee58bbd3cfb9ef5c680a11dd856c3e64dff9 blob + 1e9dcbabbf610fad4051df25fb2ef9897b3ac524 --- lib/worktree.c +++ lib/worktree.c @@ -7006,6 +7006,70 @@ got_worktree_rebase_in_progress(int *in_progress, stru *in_progress = (strcmp(tmp_branch_name, worktree->head_ref_name) == 0); free(tmp_branch_name); return NULL; +} + +const struct got_error * +got_worktree_rebase_info(char **new_base_branch_name, char **branch_name, + struct got_worktree *worktree, struct got_repository *repo) +{ + const struct got_error *err; + char *new_base_branch_ref_name = NULL; + char *branch_ref_name = NULL; + struct got_reference *branch_ref = NULL, *branch = NULL; + struct got_reference *new_base_branch = NULL; + + *new_base_branch_name = NULL; + *branch_name = NULL; + + err = get_rebase_branch_symref_name(&branch_ref_name, worktree); + if (err) + goto done; + + err = get_newbase_symref_name(&new_base_branch_ref_name, worktree); + if (err) + goto done; + + err = got_ref_open(&branch_ref, repo, branch_ref_name, 0); + if (err) + goto done; + + err = got_ref_open(&branch, repo, + got_ref_get_symref_target(branch_ref), 0); + if (err) + goto done; + + err = got_ref_open(&new_base_branch, repo, + new_base_branch_ref_name, 0); + if (err) + goto done; + + if (!got_ref_is_symbolic(new_base_branch)) { + err = got_error_fmt(GOT_ERR_BAD_REF_TYPE, + "%s is not a symbolic reference", + got_ref_get_name(branch_ref)); + goto done; + } + + *new_base_branch_name = strdup(got_ref_get_symref_target( + new_base_branch)); + if (*new_base_branch_name == NULL) { + err = got_error_from_errno("strdup"); + goto done; + } + *branch_name = strdup(got_ref_get_name(branch)); + if (*branch_name == NULL) { + err = got_error_from_errno("strdup"); + goto done; + } +done: + free(branch_ref_name); + if (branch_ref) + got_ref_close(branch_ref); + if (new_base_branch) + got_ref_close(new_base_branch); + if (branch) + got_ref_close(branch); + return err; } static const struct got_error * @@ -8030,7 +8094,48 @@ done: *fileindex = NULL; } lock_worktree(worktree, LOCK_EX); + } + return err; +} + +const struct got_error * +got_worktree_histedit_info(char **branch_name, + struct got_worktree *worktree, struct got_repository *repo) +{ + const struct got_error *err; + struct got_reference *branch_ref = NULL; + char *branch_ref_name = NULL; + + *branch_name = NULL; + + err = get_histedit_branch_symref_name(&branch_ref_name, worktree); + if (err) + goto done; + + err = got_ref_open(&branch_ref, repo, branch_ref_name, 0); + if (err) + goto done; + + if (!got_ref_is_symbolic(branch_ref)) { + err = got_error_fmt(GOT_ERR_BAD_REF_TYPE, + "%s is not a symbolic reference", + got_ref_get_name(branch_ref)); + goto done; + } + + *branch_name = strdup(got_ref_get_symref_target(branch_ref)); + if (*branch_name == NULL) { + err = got_error_from_errno("strdup"); + goto done; } +done: + free(branch_ref_name); + if (branch_ref) + got_ref_close(branch_ref); + if (err) { + free(*branch_name); + *branch_name = NULL; + } return err; } @@ -8858,6 +8963,49 @@ done: } const struct got_error * +got_worktree_merge_info(char **branch_name, struct got_worktree *worktree, + struct got_repository *repo) +{ + const struct got_error *err; + char *branch_refname = NULL; + struct got_reference *branch_ref = NULL; + + *branch_name = NULL; + + err = get_merge_branch_ref_name(&branch_refname, worktree); + if (err) + goto done; + + err = got_ref_open(&branch_ref, repo, branch_refname, 0); + if (err) + goto done; + + if (!got_ref_is_symbolic(branch_ref)) { + err = got_error_fmt(GOT_ERR_BAD_REF_TYPE, + "%s is not a symbolic reference", + got_ref_get_name(branch_ref)); + goto done; + } + *branch_name = strdup(got_ref_get_symref_target(branch_ref)); + if (*branch_name == NULL) { + err = got_error_from_errno("strdup"); + goto done; + } + +done: + free(branch_refname); + if (branch_ref) + got_ref_close(branch_ref); + if (err) { + if (*branch_name) { + free(*branch_name); + *branch_name = NULL; + } + } + return err; +} + +const struct got_error * got_worktree_merge_abort(struct got_worktree *worktree, struct got_fileindex *fileindex, struct got_repository *repo, got_worktree_checkout_cb progress_cb, void *progress_arg) blob - 4540f35d9804387c36072d1da2829b2c460a5171 blob + 13dd31e4feec963e558e3e0eebbcfac22c15c741 --- regress/cmdline/histedit.sh +++ regress/cmdline/histedit.sh @@ -1186,7 +1186,10 @@ test_histedit_path_prefix_edit() { (cd $testroot/wt && got status > $testroot/stdout) - echo "M zeta"> $testroot/stdout.expected + cat > $testroot/stdout.expected < $testroot/stdout) - echo "C alpha" > $testroot/stdout.expected - echo "D beta" >> $testroot/stdout.expected - echo "A epsilon/new" >> $testroot/stdout.expected - echo "M gamma/delta" >> $testroot/stdout.expected + cat > $testroot/stdout.expected < $testroot/stdout) - echo "A added-file" > $testroot/stdout.expected - echo "C alpha" >> $testroot/stdout.expected - echo "D beta" >> $testroot/stdout.expected - echo "A epsilon/new" >> $testroot/stdout.expected - echo "M gamma/delta" >> $testroot/stdout.expected - echo "A symlink" >> $testroot/stdout.expected - echo "? unversioned-file" >> $testroot/stdout.expected + cat > $testroot/stdout.expected < $testroot/stdout) - echo "C alpha" > $testroot/stdout.expected + cat > $testroot/stdout.expected < $testroot/stdout) - echo "M gamma/delta" > $testroot/stdout.expected + cat > $testroot/stdout.expected < $testroot/stdout) - echo "C alpha" > $testroot/stdout.expected + cat > $testroot/stdout.expected < $testroot/stdout) - echo "M alpha" > $testroot/stdout.expected + cat > $testroot/stdout.expected < $testroot/stdout) - echo "C alpha" > $testroot/stdout.expected + cat > $testroot/stdout.expected < $testroot/stdout) - echo "A added-file" > $testroot/stdout.expected - echo "C alpha" >> $testroot/stdout.expected - echo "A epsilon/new" >> $testroot/stdout.expected - echo "? unversioned-file" >> $testroot/stdout.expected + cat > $testroot/stdout.expected < $testroot/stdout) - echo "C alpha" > $testroot/stdout.expected + cat > $testroot/stdout.expected < $testroot/stdout) - echo "C alpha" > $testroot/stdout.expected + cat > $testroot/stdout.expected <