commit e51d7b55a3d7fcd307ad6f65fa793a52a24dd697 from: Stefan Sperling date: Sat Jan 04 08:35:17 2020 UTC prevent rebase with an out-of-date work tree 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