From: Stefan Sperling Subject: fix cherrypick into added file To: gameoftrees@openbsd.org Date: Thu, 2 Sep 2021 00:04:26 +0200 Another cherrypick issue found by naddy: Picking changes in sequence such that a locally added file gets modified again results in a bogus error: "work tree contains files from multiple base commits; the entire work tree must be updated first" This happens because check_merge_ok() compares the base commit's ID to the zero ID. Added files do not yet have base commit and should thus be excluded from this check. I am also updating the test suite to cover this bug. If you only apply the cherrypick.sh change the test will fail. ok? diff dae2a678dfc5685c0f121fd205f62439f417dcc5 /home/stsp/src/got blob - 9dcec45509bd829020e987bf5dec3635512ee62f file + lib/worktree.c --- lib/worktree.c +++ lib/worktree.c @@ -3133,7 +3133,8 @@ check_merge_ok(void *arg, struct got_fileindex_entry * char *ondisk_path; /* Reject merges into a work tree with mixed base commits. */ - if (memcmp(ie->commit_sha1, a->worktree->base_commit_id->sha1, + if (got_fileindex_entry_has_commit(ie) && + memcmp(ie->commit_sha1, a->worktree->base_commit_id->sha1, SHA1_DIGEST_LENGTH)) return got_error(GOT_ERR_MIXED_COMMITS); blob - 5bfd952f5935c646f1b615cefc0ffb3b07d24e4a file + regress/cmdline/cherrypick.sh --- regress/cmdline/cherrypick.sh +++ regress/cmdline/cherrypick.sh @@ -38,6 +38,10 @@ test_cherrypick_basic() { local branch_rev=`git_show_head $testroot/repo` + echo "modified new file on branch" > $testroot/repo/epsilon/new + git_commit $testroot/repo -m "committing more changes on newbranch" + local branch_rev2=`git_show_head $testroot/repo` + (cd $testroot/wt && got cherrypick $branch_rev > $testroot/stdout) echo "G alpha" > $testroot/stdout.expected @@ -89,7 +93,34 @@ test_cherrypick_basic() { ret="$?" if [ "$ret" != "0" ]; then diff -u $testroot/stdout.expected $testroot/stdout + test_done "$testroot" "$ret" + return 1 fi + + (cd $testroot/wt && got cherrypick $branch_rev2 > $testroot/stdout) + + echo "G epsilon/new" > $testroot/stdout.expected + echo "Merged commit $branch_rev2" >> $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 'M alpha' > $testroot/stdout.expected + echo 'D beta' >> $testroot/stdout.expected + echo 'A epsilon/new' >> $testroot/stdout.expected + + (cd $testroot/wt && got status > $testroot/stdout) + + cmp -s $testroot/stdout.expected $testroot/stdout + ret="$?" + if [ "$ret" != "0" ]; then + diff -u $testroot/stdout.expected $testroot/stdout + fi test_done "$testroot" "$ret" }