Commit Diff


commit - 7f47418fd49bc98fe4570c139767c057cd066409
commit + e51d7b55a3d7fcd307ad6f65fa793a52a24dd697
blob - d0df1255deadae95cebcf18a88340a0d87666d46
blob + 577bc08aea231c5c5521837f99004a21cfb18a53
--- include/got_error.h
+++ include/got_error.h
@@ -128,6 +128,7 @@
 #define GOT_ERR_REGEX		112
 #define GOT_ERR_REF_NAME_MINUS	113
 #define GOT_ERR_GITCONFIG_SYNTAX 114
+#define GOT_ERR_REBASE_OUT_OF_DATE 115
 
 static const struct got_error {
 	int code;
@@ -262,6 +263,8 @@ static const struct got_error {
 	{ GOT_ERR_REGEX, "regular expression error" },
 	{ GOT_ERR_REF_NAME_MINUS, "reference name may not start with '-'" },
 	{ GOT_ERR_GITCONFIG_SYNTAX, "gitconfig syntax error" },
+	{ GOT_ERR_REBASE_OUT_OF_DATE, "work tree must be updated before it "
+	    "can be used to rebase a branch" },
 };
 
 /*
blob - ba58428f5804dfcea39d26b7c33082de42e28ab5
blob + 3f75e03052883cff13564972267cb911ae876573
--- lib/worktree.c
+++ lib/worktree.c
@@ -4679,6 +4679,7 @@ got_worktree_rebase_prepare(struct got_reference **new
 	char *fileindex_path = NULL;
 	struct check_rebase_ok_arg ok_arg;
 	struct got_reference *wt_branch = NULL, *branch_ref = NULL;
+	struct got_object_id *wt_branch_tip = NULL;
 
 	*new_base_branch_ref = NULL;
 	*tmp_branch = NULL;
@@ -4713,8 +4714,16 @@ got_worktree_rebase_prepare(struct got_reference **new
 
 	err = got_ref_open(&wt_branch, repo, worktree->head_ref_name,
 	    0);
+	if (err)
+		goto done;
+
+	err = got_ref_resolve(&wt_branch_tip, repo, wt_branch);
 	if (err)
 		goto done;
+	if (got_object_id_cmp(worktree->base_commit_id, wt_branch_tip) != 0) {
+		err = got_error(GOT_ERR_REBASE_OUT_OF_DATE);
+		goto done;
+	}
 
 	err = got_ref_alloc_symref(new_base_branch_ref,
 	    new_base_branch_ref_name, wt_branch);
@@ -4754,6 +4763,7 @@ done:
 		got_ref_close(branch_ref);
 	if (wt_branch)
 		got_ref_close(wt_branch);
+	free(wt_branch_tip);
 	if (err) {
 		if (*new_base_branch_ref) {
 			got_ref_close(*new_base_branch_ref);
blob - e504cd7a19d54a0fb8ebb30ff394991576a092da
blob + 57da5dfa8ca8bac8507955c4a6ca27984b70dc5f
--- regress/cmdline/rebase.sh
+++ regress/cmdline/rebase.sh
@@ -869,7 +869,77 @@ function test_rebase_forward {
 	fi
 	test_done "$testroot" "$ret"
 }
+
+function test_rebase_out_of_date {
+	local testroot=`test_init rebase_out_of_date`
+	local initial_commit=`git_show_head $testroot/repo`
+
+	(cd $testroot/repo && git checkout -q -b newbranch)
+	echo "modified delta on branch" > $testroot/repo/gamma/delta
+	git_commit $testroot/repo -m "committing to delta on newbranch"
 
+	echo "modified alpha on branch" > $testroot/repo/alpha
+	(cd $testroot/repo && git rm -q beta)
+	echo "new file on branch" > $testroot/repo/epsilon/new
+	(cd $testroot/repo && git add epsilon/new)
+	git_commit $testroot/repo -m "committing more changes on newbranch"
+
+	local orig_commit1=`git_show_parent_commit $testroot/repo`
+	local orig_commit2=`git_show_head $testroot/repo`
+
+	(cd $testroot/repo && git checkout -q master)
+	echo "modified zeta on master" > $testroot/repo/epsilon/zeta
+	git_commit $testroot/repo -m "committing to zeta on master"
+	local master_commit1=`git_show_head $testroot/repo`
+
+	(cd $testroot/repo && git checkout -q master)
+	echo "modified beta on master" > $testroot/repo/beta
+	git_commit $testroot/repo -m "committing to beta on master"
+	local master_commit2=`git_show_head $testroot/repo`
+
+	got checkout -c $master_commit1 $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 -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: work tree must be updated before it can be " \
+		> $testroot/stderr.expected
+	echo "used to rebase a branch" >> $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
+
+	(cd $testroot/wt && got log -l3 | grep ^commit > $testroot/stdout)
+	echo "commit $master_commit2 (master)" > $testroot/stdout.expected
+	echo "commit $master_commit1" >> $testroot/stdout.expected
+	echo "commit $initial_commit" >> $testroot/stdout.expected
+	cmp -s $testroot/stdout.expected $testroot/stdout
+	ret="$?"
+	if [ "$ret" != "0" ]; then
+		diff -u $testroot/stdout.expected $testroot/stdout
+	fi
+	test_done "$testroot" "$ret"
+}
+
 run_test test_rebase_basic
 run_test test_rebase_ancestry_check
 run_test test_rebase_continue
@@ -880,3 +950,4 @@ run_test test_rebase_path_prefix
 run_test test_rebase_preserves_logmsg
 run_test test_rebase_no_commits_to_rebase
 run_test test_rebase_forward
+run_test test_rebase_out_of_date