@matheusbsbs / matheus-bagliano / commits / 8dfb04ae96
Fork 0

update-index: optionally leave skip-worktree entries alone

While `git update-index` mostly ignores paths referring to index entries whose skip-worktree bit is set, in b4d1690df11 (Teach Git to respect skip-worktree bit (reading part), 2009-08-20), for reasons that are not entirely obvious, the `--remove` option was made special: it _does_ remove index entries even if their skip-worktree bit is set. Seeing as this behavior has been in place for a decade now, it does not make sense to change it. However, in preparation for fixing a bug in `git stash` where it pretends that skip-worktree entries have actually been removed, we need a mode where `git update-index` leaves all skip-worktree entries alone, even if the `--remove` option was passed. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Johannes Schindelin committed Oct 30, 2019 at 10:49 UTC 8dfb04ae964868dda758997e5e7da29edff6164b
3 files changed +26 -1
Documentation/git-update-index.txt
+6
@@ -16,6 +16,7 @@ SYNOPSIS
16 [--chmod=(+|-)x]
17 [--[no-]assume-unchanged]
18 [--[no-]skip-worktree]
19 + [--[no-]ignore-skip-worktree-entries]
20 [--[no-]fsmonitor-valid]
21 [--ignore-submodules]
22 [--[no-]split-index]
@@ -113,6 +114,11 @@ you will need to handle the situation manually.
114 set and unset the "skip-worktree" bit for the paths. See
115 section "Skip-worktree bit" below for more information.
116
117 +
118 +--[no-]ignore-skip-worktree-entries::
119 + Do not remove skip-worktree (AKA "index-only") entries even when
120 + the `--remove` option was specified.
121 +
122 --[no-]fsmonitor-valid::
123 When one of these flags is specified, the object name recorded
124 for the paths are not updated. Instead, these options
builtin/update-index.c
+5 -1
@@ -35,6 +35,7 @@ static int verbose;
35 static int mark_valid_only;
36 static int mark_skip_worktree_only;
37 static int mark_fsmonitor_only;
38 +static int ignore_skip_worktree_entries;
39 #define MARK_FLAG 1
40 #define UNMARK_FLAG 2
41 static struct strbuf mtime_dir = STRBUF_INIT;
@@ -381,7 +382,8 @@ static int process_path(const char *path, struct stat *st, int stat_errno)
382 * so updating it does not make sense.
383 * On the other hand, removing it from index should work
384 */
384 - if (allow_remove && remove_file_from_cache(path))
385 + if (!ignore_skip_worktree_entries && allow_remove &&
386 + remove_file_from_cache(path))
387 return error("%s: cannot remove from the index", path);
388 return 0;
389 }
@@ -1013,6 +1015,8 @@ int cmd_update_index(int argc, const char **argv, const char *prefix)
1015 {OPTION_SET_INT, 0, "no-skip-worktree", &mark_skip_worktree_only, NULL,
1016 N_("clear skip-worktree bit"),
1017 PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL, UNMARK_FLAG},
1018 + OPT_BOOL(0, "ignore-skip-worktree-entries", &ignore_skip_worktree_entries,
1019 + N_("do not touch index-only entries")),
1020 OPT_SET_INT(0, "info-only", &info_only,
1021 N_("add to index only; do not add content to object database"), 1),
1022 OPT_SET_INT(0, "force-remove", &force_remove,
t/t7012-skip-worktree-writing.sh
+15
@@ -134,6 +134,21 @@ test_expect_success 'git-clean, dirty case' '
134 test_i18ncmp expected result
135 '
136
137 +test_expect_success '--ignore-skip-worktree-entries leaves worktree alone' '
138 + test_commit keep-me &&
139 + git update-index --skip-worktree keep-me.t &&
140 + rm keep-me.t &&
141 +
142 + : ignoring the worktree &&
143 + git update-index --remove --ignore-skip-worktree-entries keep-me.t &&
144 + git diff-index --cached --exit-code HEAD &&
145 +
146 + : not ignoring the worktree, a deletion is staged &&
147 + git update-index --remove keep-me.t &&
148 + test_must_fail git diff-index --cached --exit-code HEAD \
149 + --diff-filter=D -- keep-me.t
150 +'
151 +
152 #TODO test_expect_failure 'git-apply adds file' false
153 #TODO test_expect_failure 'git-apply updates file' false
154 #TODO test_expect_failure 'git-apply removes file' false