From: Junio C Hamano Date: Sun, 10 Nov 2019 09:02:16 +0000 (+0900) Subject: Merge branch 'js/update-index-ignore-removal-for-skip-worktree' X-Git-Tag: v2.25.0-rc0~136 X-Git-Url: http://git.ipfire.org/?p=thirdparty%2Fgit.git;a=commitdiff_plain;h=57b530125e022de79f5f0b208bc0a5ee67c18b77;hp=-c Merge branch 'js/update-index-ignore-removal-for-skip-worktree' "git stash save" in a working tree that is sparsely checked out mistakenly removed paths that are outside the area of interest. * js/update-index-ignore-removal-for-skip-worktree: stash: handle staged changes in skip-worktree files correctly update-index: optionally leave skip-worktree entries alone --- 57b530125e022de79f5f0b208bc0a5ee67c18b77 diff --combined builtin/stash.c index 4e806176b0,56f3b551e4..d913487a43 --- a/builtin/stash.c +++ b/builtin/stash.c @@@ -396,7 -396,7 +396,7 @@@ static int do_apply_stash(const char *p const struct object_id *bases[1]; read_cache_preload(NULL); - if (refresh_cache(REFRESH_QUIET)) + if (refresh_and_write_cache(REFRESH_QUIET, 0, 0)) return -1; if (write_cache_as_tree(&c_tree, 0, NULL)) @@@ -427,8 -427,6 +427,8 @@@ return error(_("could not save index tree")); reset_head(); + discard_cache(); + read_cache(); } } @@@ -487,7 -485,7 +487,7 @@@ } if (quiet) { - if (refresh_cache(REFRESH_QUIET)) + if (refresh_and_write_cache(REFRESH_QUIET, 0, 0)) warning("could not refresh index"); } else { struct child_process cp = CHILD_PROCESS_INIT; @@@ -499,10 -497,6 +499,10 @@@ */ cp.git_cmd = 1; cp.dir = prefix; + argv_array_pushf(&cp.env_array, GIT_WORK_TREE_ENVIRONMENT"=%s", + absolute_path(get_git_work_tree())); + argv_array_pushf(&cp.env_array, GIT_DIR_ENVIRONMENT"=%s", + absolute_path(get_git_dir())); argv_array_push(&cp.args, "status"); run_command(&cp); } @@@ -1088,8 -1082,9 +1088,9 @@@ static int stash_working_tree(struct st } cp_upd_index.git_cmd = 1; - argv_array_pushl(&cp_upd_index.args, "update-index", "-z", "--add", - "--remove", "--stdin", NULL); + argv_array_pushl(&cp_upd_index.args, "update-index", + "--ignore-skip-worktree-entries", + "-z", "--add", "--remove", "--stdin", NULL); argv_array_pushf(&cp_upd_index.env_array, "GIT_INDEX_FILE=%s", stash_index_path.buf); @@@ -1135,10 -1130,7 +1136,10 @@@ static int do_create_stash(const struc prepare_fallback_ident("git stash", "git@stash"); read_cache_preload(NULL); - refresh_cache(REFRESH_QUIET); + if (refresh_and_write_cache(REFRESH_QUIET, 0, 0) < 0) { + ret = -1; + goto done; + } if (get_oid("HEAD", &info->b_commit)) { if (!quiet) @@@ -1299,7 -1291,7 +1300,7 @@@ static int do_push_stash(const struct p free(ps_matched); } - if (refresh_cache(REFRESH_QUIET)) { + if (refresh_and_write_cache(REFRESH_QUIET, 0, 0)) { ret = -1; goto done; } @@@ -1392,7 -1384,7 +1393,7 @@@ struct child_process cp = CHILD_PROCESS_INIT; cp.git_cmd = 1; argv_array_pushl(&cp.args, "reset", "--hard", "-q", - NULL); + "--no-recurse-submodules", NULL); if (run_command(&cp)) { ret = -1; goto done; diff --combined builtin/update-index.c index 49302d98c5,074d563df0..d527b8f106 --- a/builtin/update-index.c +++ b/builtin/update-index.c @@@ -35,6 -35,7 +35,7 @@@ static int verbose static int mark_valid_only; static int mark_skip_worktree_only; static int mark_fsmonitor_only; + static int ignore_skip_worktree_entries; #define MARK_FLAG 1 #define UNMARK_FLAG 2 static struct strbuf mtime_dir = STRBUF_INIT; @@@ -381,7 -382,8 +382,8 @@@ static int process_path(const char *pat * so updating it does not make sense. * On the other hand, removing it from index should work */ - if (allow_remove && remove_file_from_cache(path)) + if (!ignore_skip_worktree_entries && allow_remove && + remove_file_from_cache(path)) return error("%s: cannot remove from the index", path); return 0; } @@@ -966,7 -968,6 +968,7 @@@ int cmd_update_index(int argc, const ch struct parse_opt_ctx_t ctx; strbuf_getline_fn getline_fn; int parseopt_state = PARSE_OPT_UNKNOWN; + struct repository *r = the_repository; struct option options[] = { OPT_BIT('q', NULL, &refresh_args.flags, N_("continue refresh even when index needs update"), @@@ -1014,6 -1015,8 +1016,8 @@@ {OPTION_SET_INT, 0, "no-skip-worktree", &mark_skip_worktree_only, NULL, N_("clear skip-worktree bit"), PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL, UNMARK_FLAG}, + OPT_BOOL(0, "ignore-skip-worktree-entries", &ignore_skip_worktree_entries, + N_("do not touch index-only entries")), OPT_SET_INT(0, "info-only", &info_only, N_("add to index only; do not add content to object database"), 1), OPT_SET_INT(0, "force-remove", &force_remove, @@@ -1181,12 -1184,11 +1185,12 @@@ remove_split_index(&the_index); } + prepare_repo_settings(r); switch (untracked_cache) { case UC_UNSPECIFIED: break; case UC_DISABLE: - if (git_config_get_untracked_cache() == 1) + if (r->settings.core_untracked_cache == UNTRACKED_CACHE_WRITE) warning(_("core.untrackedCache is set to true; " "remove or change it, if you really want to " "disable the untracked cache")); @@@ -1198,7 -1200,7 +1202,7 @@@ return !test_if_untracked_cache_is_supported(); case UC_ENABLE: case UC_FORCE: - if (git_config_get_untracked_cache() == 0) + if (r->settings.core_untracked_cache == UNTRACKED_CACHE_REMOVE) warning(_("core.untrackedCache is set to false; " "remove or change it, if you really want to " "enable the untracked cache")); diff --combined git-legacy-stash.sh index 07ad4a5459,5398a5161d..53fa574301 --- a/git-legacy-stash.sh +++ b/git-legacy-stash.sh @@@ -193,7 -193,8 +193,8 @@@ create_stash () GIT_INDEX_FILE="$TMPindex" && export GIT_INDEX_FILE && git diff-index --name-only -z HEAD -- "$@" >"$TMP-stagenames" && - git update-index -z --add --remove --stdin <"$TMP-stagenames" && + git update-index --ignore-skip-worktree-entries \ + -z --add --remove --stdin <"$TMP-stagenames" && git write-tree && rm -f "$TMPindex" ) ) || @@@ -370,7 -371,7 +371,7 @@@ push_stash () git diff-index -p --cached --binary HEAD -- "$@" | git apply --index -R else - git reset --hard -q + git reset --hard -q --no-recurse-submodules fi if test "$keep_index" = "t" && test -n "$i_tree" diff --combined t/t3903-stash.sh index 580bfbdc23,1e977145b8..a4da72f0ab --- a/t/t3903-stash.sh +++ b/t/t3903-stash.sh @@@ -7,18 -7,6 +7,18 @@@ test_description='Test git stash . ./test-lib.sh +diff_cmp () { + for i in "$1" "$2" + do + sed -e 's/^index 0000000\.\.[0-9a-f]*/index 0000000..1234567/' \ + -e 's/^index [0-9a-f]*\.\.[0-9a-f]*/index 1234567..89abcde/' \ + -e 's/^index [0-9a-f]*,[0-9a-f]*\.\.[0-9a-f]*/index 1234567,7654321..89abcde/' \ + "$i" >"$i.compare" || return 1 + done && + test_cmp "$1.compare" "$2.compare" && + rm -f "$1.compare" "$2.compare" +} + test_expect_success 'stash some dirty working directory' ' echo 1 >file && git add file && @@@ -48,7 -36,7 +48,7 @@@ EO test_expect_success 'parents of stash' ' test $(git rev-parse stash^) = $(git rev-parse HEAD) && git diff stash^2..stash >output && - test_cmp expect output + diff_cmp expect output ' test_expect_success 'applying bogus stash does nothing' ' @@@ -222,13 -210,13 +222,13 @@@ test_expect_success 'stash branch' test refs/heads/stashbranch = $(git symbolic-ref HEAD) && test $(git rev-parse HEAD) = $(git rev-parse master^) && git diff --cached >output && - test_cmp expect output && + diff_cmp expect output && git diff >output && - test_cmp expect1 output && + diff_cmp expect1 output && git add file && git commit -m alternate\ second && git diff master..stashbranch >output && - test_cmp output expect2 && + diff_cmp output expect2 && test 0 = $(git stash list | wc -l) ' @@@ -589,7 -577,7 +589,7 @@@ test_expect_success 'stash show -p - st +bar EOF git stash show -p ${STASH_ID} >actual && - test_cmp expected actual + diff_cmp expected actual ' test_expect_success 'stash show - no stashes on stack, stash-like argument' ' @@@ -621,7 -609,7 +621,7 @@@ test_expect_success 'stash show -p - n +foo EOF git stash show -p ${STASH_ID} >actual && - test_cmp expected actual + diff_cmp expected actual ' test_expect_success 'stash show --patience shows diff' ' @@@ -639,7 -627,7 +639,7 @@@ +foo EOF git stash show --patience ${STASH_ID} >actual && - test_cmp expected actual + diff_cmp expected actual ' test_expect_success 'drop: fail early if specified stash is not a stash ref' ' @@@ -803,7 -791,7 +803,7 @@@ test_expect_success 'stash where workin git diff-index --cached --quiet HEAD && test "$(git rev-parse stash^)" = "$(git rev-parse HEAD)" && git diff stash^..stash >output && - test_cmp expect output + diff_cmp expect output ' test_expect_success 'store called with invalid commit' ' @@@ -859,7 -847,7 +859,7 @@@ test_expect_success 'stash list implie +working EOF git stash list --format=%gd -p >actual && - test_cmp expect actual + diff_cmp expect actual ' test_expect_success 'stash list --cc shows combined diff' ' @@@ -876,7 -864,7 +876,7 @@@ ++working EOF git stash list --format=%gd -p --cc >actual && - test_cmp expect actual + diff_cmp expect actual ' test_expect_success 'stash is not confused by partial renames' ' @@@ -1253,20 -1241,15 +1253,31 @@@ test_expect_success 'stash --keep-inde test_path_is_missing to-remove ' +test_expect_success 'stash apply should succeed with unmodified file' ' + echo base >file && + git add file && + git commit -m base && + + # now stash a modification + echo modified >file && + git stash && + + # make the file stat dirty + cp file other && + mv other file && + + git stash apply +' + + test_expect_success 'stash handles skip-worktree entries nicely' ' + test_commit A && + echo changed >A.t && + git add A.t && + git update-index --skip-worktree A.t && + rm A.t && + git stash && + + git rev-parse --verify refs/stash:A.t + ' + test_done