Commit 7d5807f4517a76c30cd479340f6968ca7eecce0b

Stefan Sperling 2019-07-11T14:57:24

disallow 'got update' and 'got commit' while rebase is in progress

diff --git a/got/got.1 b/got/got.1
index c9f0107..1780abc 100644
--- a/got/got.1
+++ b/got/got.1
@@ -582,9 +582,13 @@ to a single base commit with
 If the work tree contains local changes, these changes must be committed
 or reverted first.
 .Pp
-Some
-.Nm
-commands may refuse to run while a rebase operation is in progress.
+The
+.Cm got update
+and
+.Cm got commit
+commands will refuse to run while a rebase operation is in progress.
+Other commands which manipulate the work tree may be used for
+conflict resolution purposes.
 .Pp
 The options for
 .Cm got rebase
diff --git a/got/got.c b/got/got.c
index 93c26bf..d0fbca4 100644
--- a/got/got.c
+++ b/got/got.c
@@ -694,7 +694,7 @@ cmd_update(int argc, char *argv[])
 	char *commit_id_str = NULL;
 	const char *branch_name = NULL;
 	struct got_reference *head_ref = NULL;
-	int ch, did_something = 0;
+	int ch, did_something = 0, rebase_in_progress;
 
 	while ((ch = getopt(argc, argv, "b:c:")) != -1) {
 		switch (ch) {
@@ -729,6 +729,14 @@ cmd_update(int argc, char *argv[])
 	if (error)
 		goto done;
 
+	error = got_worktree_rebase_in_progress(&rebase_in_progress, worktree);
+	if (error)
+		goto done;
+	if (rebase_in_progress) {
+		error = got_error(GOT_ERR_REBASING);
+		goto done;
+	}
+
 	if (argc == 0) {
 		path = strdup("");
 		if (path == NULL) {
@@ -2874,7 +2882,7 @@ cmd_commit(int argc, char *argv[])
 	const char *got_author = getenv("GOT_AUTHOR");
 	struct collect_commit_logmsg_arg cl_arg;
 	char *editor = NULL;
-	int ch;
+	int ch, rebase_in_progress;
 
 	while ((ch = getopt(argc, argv, "m:")) != -1) {
 		switch (ch) {
@@ -2915,6 +2923,14 @@ cmd_commit(int argc, char *argv[])
 	if (error)
 		goto done;
 
+	error = got_worktree_rebase_in_progress(&rebase_in_progress, worktree);
+	if (error)
+		goto done;
+	if (rebase_in_progress) {
+		error = got_error(GOT_ERR_REBASING);
+		goto done;
+	}
+
 	error = got_repo_open(&repo, got_worktree_get_repo_path(worktree));
 	if (error != NULL)
 		goto done;
diff --git a/include/got_error.h b/include/got_error.h
index 441dea9..4a4ef0b 100644
--- a/include/got_error.h
+++ b/include/got_error.h
@@ -101,6 +101,7 @@
 #define GOT_ERR_NOT_REBASING	85
 #define GOT_ERR_EMPTY_REBASE	86
 #define GOT_ERR_REBASE_COMMITID	87
+#define GOT_ERR_REBASING	88
 
 static const struct got_error {
 	int code;
@@ -198,6 +199,8 @@ static const struct got_error {
 	{ GOT_ERR_NOT_REBASING,	"rebase operation not in progress" },
 	{ GOT_ERR_EMPTY_REBASE,	"no commits to rebase" },
 	{ GOT_ERR_REBASE_COMMITID,"rebase commit ID mismatch" },
+	{ GOT_ERR_REBASING,	"a rebase operation is in progress in this "
+	    "work tree and must be continued or aborted first" },
 };
 
 /*
diff --git a/regress/cmdline/rebase.sh b/regress/cmdline/rebase.sh
index 1ea60f6..91b9ba8 100755
--- a/regress/cmdline/rebase.sh
+++ b/regress/cmdline/rebase.sh
@@ -492,8 +492,106 @@ function test_rebase_no_op_change {
 	test_done "$testroot" "$ret"
 }
 
+function test_rebase_in_progress {
+	local testroot=`test_init rebase_no_op_change`
+	local init_commit=`git_show_head $testroot/repo`
+
+	(cd $testroot/repo && git checkout -q -b newbranch)
+	echo "modified alpha on branch" > $testroot/repo/alpha
+	git_commit $testroot/repo -m "committing to alpha on newbranch"
+	local orig_commit1=`git_show_head $testroot/repo`
+
+	(cd $testroot/repo && git checkout -q master)
+	echo "modified alpha on master" > $testroot/repo/alpha
+	git_commit $testroot/repo -m "committing to alpha on master"
+	local master_commit=`git_show_head $testroot/repo`
+
+	got checkout $testroot/repo $testroot/wt > /dev/null
+	ret="$?"
+	if [ "$ret" != "0" ]; then
+		test_done "$testroot" "$ret"
+		return 1
+	fi
+
+	(cd $testroot/wt && got rebase newbranch > $testroot/stdout \
+		2> $testroot/stderr)
+
+	echo "C  alpha" > $testroot/stdout.expected
+	cmp -s $testroot/stdout.expected $testroot/stdout
+	ret="$?"
+	if [ "$ret" != "0" ]; then
+		diff -u $testroot/stdout.expected $testroot/stdout
+		test_done "$testroot" "$ret"
+		return 1
+	fi
+
+	echo "got: conflicts must be resolved before rebase can be resumed" \
+		> $testroot/stderr.expected
+	cmp -s $testroot/stderr.expected $testroot/stderr
+	ret="$?"
+	if [ "$ret" != "0" ]; then
+		diff -u $testroot/stderr.expected $testroot/stderr
+		test_done "$testroot" "$ret"
+		return 1
+	fi
+
+	echo "<<<<<<< commit $orig_commit1" > $testroot/content.expected
+	echo "modified alpha on branch" >> $testroot/content.expected
+	echo "=======" >> $testroot/content.expected
+	echo "modified alpha on master" >> $testroot/content.expected
+	echo '>>>>>>> alpha' >> $testroot/content.expected
+	cat $testroot/wt/alpha > $testroot/content
+	cmp -s $testroot/content.expected $testroot/content
+	ret="$?"
+	if [ "$ret" != "0" ]; then
+		diff -u $testroot/content.expected $testroot/content
+		test_done "$testroot" "$ret"
+		return 1
+	fi
+
+	(cd $testroot/wt && got status > $testroot/stdout)
+
+	echo "C  alpha" > $testroot/stdout.expected
+	cmp -s $testroot/stdout.expected $testroot/stdout
+	ret="$?"
+	if [ "$ret" != "0" ]; then
+		diff -u $testroot/stdout.expected $testroot/stdout
+		test_done "$testroot" "$ret"
+		return 1
+	fi
+
+	for cmd in update commit; do
+		(cd $testroot/wt && got $cmd > $testroot/stdout \
+			2> $testroot/stderr)
+
+		echo -n > $testroot/stdout.expected
+		cmp -s $testroot/stdout.expected $testroot/stdout
+		ret="$?"
+		if [ "$ret" != "0" ]; then
+			diff -u $testroot/stdout.expected $testroot/stdout
+			test_done "$testroot" "$ret"
+			return 1
+		fi
+
+		echo -n "got: a rebase operation is in progress in this " \
+			> $testroot/stderr.expected
+		echo "work tree and must be continued or aborted first" \
+			>> $testroot/stderr.expected
+		cmp -s $testroot/stderr.expected $testroot/stderr
+		ret="$?"
+		if [ "$ret" != "0" ]; then
+			diff -u $testroot/stderr.expected $testroot/stderr
+			test_done "$testroot" "$ret"
+			return 1
+		fi
+	done
+
+	test_done "$testroot" "$ret"
+}
+
 run_test test_rebase_basic
 run_test test_rebase_ancestry_check
 run_test test_rebase_continue
 run_test test_rebase_abort
 run_test test_rebase_no_op_change
+run_test test_rebase_in_progress