commit 03415a1a67d78f2decd6e46d82288a224bd4454d from: Stefan Sperling date: Sun Jun 02 18:31:34 2019 UTC allow 'got cherrypick' with a root commit (adds all files in commit) commit - a8db5ed88e635d83d1cf9b7e9bbe48eea50c192c commit + 03415a1a67d78f2decd6e46d82288a224bd4454d blob - bf12b60a1d19c91b549c6e2ef57d10957d4ca0f6 blob + 19de68852ed6874ce2254f35bf04bb2454d29ae6 --- got/got.c +++ got/got.c @@ -2699,12 +2699,9 @@ cmd_cherrypick(int argc, char *argv[]) if (error) goto done; pid = SIMPLEQ_FIRST(got_object_commit_get_parent_ids(commit)); - if (pid == NULL) { - error = got_error(GOT_ERR_ROOT_COMMIT); - goto done; - } - error = got_worktree_merge_files(worktree, pid->id, commit_id, - repo, update_progress, &did_something, check_cancelled, NULL); + error = got_worktree_merge_files(worktree, pid ? pid->id : NULL, + commit_id, repo, update_progress, &did_something, check_cancelled, + NULL); if (error != NULL) goto done; blob - 0186e720548b6da8fde30b6fd002a9076c3adc16 blob + e19e3956f955247d86d4c8d6910b38709f202a31 --- include/got_error.h +++ include/got_error.h @@ -93,7 +93,7 @@ #define GOT_ERR_BRANCH_MOVED 77 #define GOT_ERR_OBJ_TOO_LARGE 78 #define GOT_ERR_SAME_BRANCH 79 -#define GOT_ERR_ROOT_COMMIT 80 +/* 80 is currently free for re-use */ #define GOT_ERR_MIXED_COMMITS 81 #define GOT_ERR_CONFLICTS 82 @@ -182,7 +182,7 @@ static const struct got_error { "different branch; new head reference and/or update -b required" }, { GOT_ERR_OBJ_TOO_LARGE, "object too large" }, { GOT_ERR_SAME_BRANCH, "commit is already contained in this branch" }, - { GOT_ERR_ROOT_COMMIT, "specified commit has no parent commit" }, + { 80, "unused error code" }, { GOT_ERR_MIXED_COMMITS,"work tree contains files from multiple " "base commits; the entire work tree must be updated first" }, { GOT_ERR_CONFLICTS, "work tree contains conflicted files; these " blob - 12aa9ccd65fa883e13a40a4a99de19bcb48a12dd blob + ca87d48087173582492bf1fbb809c2e55b333e27 --- lib/worktree.c +++ lib/worktree.c @@ -1881,17 +1881,19 @@ got_worktree_merge_files(struct got_worktree *worktree if (err) goto done; - err = got_object_id_by_path(&tree_id1, repo, commit_id1, - worktree->path_prefix); - if (err) - goto done; + if (commit_id1) { + err = got_object_id_by_path(&tree_id1, repo, commit_id1, + worktree->path_prefix); + if (err) + goto done; + + err = got_object_open_as_tree(&tree1, repo, tree_id1); + if (err) + goto done; + } err = got_object_id_by_path(&tree_id2, repo, commit_id2, worktree->path_prefix); - if (err) - goto done; - - err = got_object_open_as_tree(&tree1, repo, tree_id1); if (err) goto done; blob - 4aa318fad89c144214430910ededa9950ba25d64 blob + 3562e9126cc0de852853d37ca03d9b6d6ccb92d5 --- regress/cmdline/cherrypick.sh +++ regress/cmdline/cherrypick.sh @@ -93,4 +93,67 @@ function test_cherrypick_basic { test_done "$testroot" "$ret" } +function test_cherrypick_root_commit { + local testroot=`test_init cherrypick_root_commit` + + got checkout $testroot/repo $testroot/wt > /dev/null + ret="$?" + if [ "$ret" != "0" ]; then + test_done "$testroot" "$ret" + return 1 + fi + + (cd $testroot/repo && git checkout -q -b newbranch) + (cd $testroot/repo && git rm -q alpha) + (cd $testroot/repo && git rm -q beta) + (cd $testroot/repo && git rm -q epsilon/zeta) + (cd $testroot/repo && git rm -q gamma/delta) + mkdir -p $testroot/repo/epsilon + echo "new file on branch" > $testroot/repo/epsilon/new + (cd $testroot/repo && git add epsilon/new) + git_commit $testroot/repo -m "committing on newbranch" + + echo "modified new file on branch" >> $testroot/repo/epsilon/new + git_commit $testroot/repo -m "committing on newbranch again" + + tree=`git_show_tree $testroot/repo` + root_commit=`git_commit_tree $testroot/repo "new root commit" $tree` + + (cd $testroot/wt && got cherrypick $root_commit > $testroot/stdout) + + echo "A epsilon/new" > $testroot/stdout.expected + echo "merged commit $root_commit" >> $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 "new file on branch" > $testroot/content.expected + echo "modified new file on branch" >> $testroot/content.expected + cat $testroot/wt/epsilon/new > $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 + + 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" +} + run_test test_cherrypick_basic +run_test test_cherrypick_root_commit blob - 61ec8447fb8409a99d4916fd8fd5da60068a7a18 blob + 4135c2b665cb9eaecfe1d9ed4d76cd51551b0d01 --- regress/cmdline/common.sh +++ regress/cmdline/common.sh @@ -44,6 +44,20 @@ function git_show_head (cd $repo && git show --no-patch --pretty='format:%H') } +function git_show_tree +{ + local repo="$1" + (cd $repo && git show --no-patch --pretty='format:%T') +} + +function git_commit_tree +{ + local repo="$1" + local msg="$2" + local tree="$3" + (cd $repo && git commit-tree -m "$msg" "$tree") +} + function make_test_tree { repo="$1"