"GOT", but the "O" is a cute, smiling pufferfish. Index | Thread | Search

From:
Stefan Sperling <stsp@stsp.name>
Subject:
make got status show interrupted operations
To:
gameoftrees@openbsd.org
Date:
Thu, 28 Mar 2024 14:59:07 +0100

Download raw body.

Thread
This small UI tweak makes it easier to users to identify whether
a work tree is currently in an interrupted operation. ok?

-----------------------------------------------
 
 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 states.
 
diff a854b8c994a1381e4c6f2ba45bef9c22da0ec956 96a6a00dbe4a094394ebc2d7c77082c01c9850e1
commit - a854b8c994a1381e4c6f2ba45bef9c22da0ec956
commit + 96a6a00dbe4a094394ebc2d7c77082c01c9850e1
blob - ee41732e49ededaf4c54218c0d0b9deb2c1feff9
blob + 24c38ee62b98e9ab39fdf9d2f67d3b4b3502a98c
--- got/got.1
+++ got/got.1
@@ -823,6 +823,12 @@ Changes created on top of staged changes are indicated
 .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
 are as follows:
blob - 5775865ce9bc5a0a9f5d8638ed832cf4ef970d67
blob + f7503f5f1f6ae825fc05d3dfc22e2c43d67b1afd
--- got/got.c
+++ got/got.c
@@ -6424,6 +6424,56 @@ print:
 }
 
 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;
+}
+
+static const struct got_error *
 cmd_status(int argc, char *argv[])
 {
 	const struct got_error *close_err, *error = NULL;
@@ -6522,6 +6572,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 - f3dd65c0798d2e84fb8a2d174be5c350115e06a1
blob + 860d8c6d46a8db026e455591d706160d86c7f3fe
--- lib/worktree.c
+++ lib/worktree.c
@@ -7011,6 +7011,70 @@ got_worktree_rebase_in_progress(int *in_progress, stru
 	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 *
 collect_rebase_commit_msg(struct got_pathlist_head *commitable_paths,
     const char *diff_path, char **logmsg, void *arg)
@@ -8037,6 +8101,47 @@ done:
 	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;
+}
+
 static const struct got_error *
 delete_histedit_refs(struct got_worktree *worktree, struct got_repository *repo)
 {
@@ -8861,6 +8966,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 <<EOF
+M  zeta
+Work tree is editing the history of refs/heads/master
+EOF
 	cmp -s $testroot/stdout.expected $testroot/stdout
 	ret=$?
 	if [ $ret -ne 0 ]; then
blob - dbe3024c2ef524f9153d2084c07158bbf936910e
blob + cd6a8a4afe865e1846927b4aa4b6ef571c40bee8
--- regress/cmdline/merge.sh
+++ regress/cmdline/merge.sh
@@ -713,10 +713,13 @@ test_merge_continue() {
 
 	(cd $testroot/wt && got status > $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 <<EOF
+C  alpha
+D  beta
+A  epsilon/new
+M  gamma/delta
+Work tree is merging refs/heads/newbranch into refs/heads/master
+EOF
 	cmp -s $testroot/stdout.expected $testroot/stdout
 	ret=$?
 	if [ $ret -ne 0 ]; then
@@ -1005,13 +1008,16 @@ test_merge_abort() {
 
 	(cd $testroot/wt && got status > $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 <<EOF
+A  added-file
+C  alpha
+D  beta
+A  epsilon/new
+M  gamma/delta
+A  symlink
+?  unversioned-file
+Work tree is merging refs/heads/newbranch into refs/heads/master
+EOF
 	cmp -s $testroot/stdout.expected $testroot/stdout
 	ret=$?
 	if [ $ret -ne 0 ]; then
@@ -1186,7 +1192,10 @@ test_merge_in_progress() {
 
 	(cd $testroot/wt && got status > $testroot/stdout)
 
-	echo "C  alpha" > $testroot/stdout.expected
+	cat > $testroot/stdout.expected <<EOF
+C  alpha
+Work tree is merging refs/heads/newbranch into refs/heads/master
+EOF
 	cmp -s $testroot/stdout.expected $testroot/stdout
 	ret=$?
 	if [ $ret -ne 0 ]; then
@@ -1357,7 +1366,10 @@ test_merge_missing_file() {
 
 	(cd $testroot/wt && got status > $testroot/stdout)
 
-	echo "M  gamma/delta" > $testroot/stdout.expected
+	cat > $testroot/stdout.expected <<EOF
+M  gamma/delta
+Work tree is merging refs/heads/newbranch into refs/heads/master
+EOF
 	cmp -s $testroot/stdout.expected $testroot/stdout
 	ret=$?
 	if [ $ret -ne 0 ]; then
@@ -1433,7 +1445,10 @@ test_merge_no_op() {
 
 	(cd $testroot/wt && got status > $testroot/stdout)
 
-	echo "C  alpha" > $testroot/stdout.expected
+	cat > $testroot/stdout.expected <<EOF
+C  alpha
+Work tree is merging refs/heads/newbranch into refs/heads/master
+EOF
 	cmp -s $testroot/stdout.expected $testroot/stdout
 	ret=$?
 	if [ $ret -ne 0 ]; then
@@ -1666,7 +1681,10 @@ test_merge_interrupt() {
 
 	(cd $testroot/wt && got status > $testroot/stdout)
 
-	echo "M  alpha" > $testroot/stdout.expected
+	cat > $testroot/stdout.expected <<EOF
+M  alpha
+Work tree is merging refs/heads/newbranch into refs/heads/master
+EOF
 	cmp -s $testroot/stdout.expected $testroot/stdout
 	ret=$?
 	if [ $ret -ne 0 ]; then
blob - 0239e75d3e0b84aa67d95700219ecda8782265ef
blob + ee6fefa31ac2365004dd760838761c9cba5e07a1
--- regress/cmdline/rebase.sh
+++ regress/cmdline/rebase.sh
@@ -340,7 +340,10 @@ test_rebase_continue() {
 
 	(cd $testroot/wt && got status > $testroot/stdout)
 
-	echo "C  alpha" > $testroot/stdout.expected
+	cat > $testroot/stdout.expected <<EOF
+C  alpha
+Work tree is rebasing refs/heads/newbranch onto refs/heads/master
+EOF
 	cmp -s $testroot/stdout.expected $testroot/stdout
 	ret=$?
 	if [ $ret -ne 0 ]; then
@@ -501,10 +504,13 @@ test_rebase_abort() {
 
 	(cd $testroot/wt && got status > $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 <<EOF
+A  added-file
+C  alpha
+A  epsilon/new
+?  unversioned-file
+Work tree is rebasing refs/heads/newbranch onto refs/heads/master
+EOF
 	cmp -s $testroot/stdout.expected $testroot/stdout
 	ret=$?
 	if [ $ret -ne 0 ]; then
@@ -669,7 +675,10 @@ test_rebase_no_op_change() {
 
 	(cd $testroot/wt && got status > $testroot/stdout)
 
-	echo "C  alpha" > $testroot/stdout.expected
+	cat > $testroot/stdout.expected <<EOF
+C  alpha
+Work tree is rebasing refs/heads/newbranch onto refs/heads/master
+EOF
 	cmp -s $testroot/stdout.expected $testroot/stdout
 	ret=$?
 	if [ $ret -ne 0 ]; then
@@ -781,7 +790,10 @@ test_rebase_in_progress() {
 
 	(cd $testroot/wt && got status > $testroot/stdout)
 
-	echo "C  alpha" > $testroot/stdout.expected
+	cat > $testroot/stdout.expected <<EOF
+C  alpha
+Work tree is rebasing refs/heads/newbranch onto refs/heads/master
+EOF
 	cmp -s $testroot/stdout.expected $testroot/stdout
 	ret=$?
 	if [ $ret -ne 0 ]; then