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 b4d1690df1 (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>
This commit is contained in:
Johannes Schindelin 2019-10-30 10:49:37 +00:00 коммит произвёл Junio C Hamano
Родитель 5fa0f5238b
Коммит 8dfb04ae96
3 изменённых файлов: 26 добавлений и 1 удалений

Просмотреть файл

@ -16,6 +16,7 @@ SYNOPSIS
[--chmod=(+|-)x] [--chmod=(+|-)x]
[--[no-]assume-unchanged] [--[no-]assume-unchanged]
[--[no-]skip-worktree] [--[no-]skip-worktree]
[--[no-]ignore-skip-worktree-entries]
[--[no-]fsmonitor-valid] [--[no-]fsmonitor-valid]
[--ignore-submodules] [--ignore-submodules]
[--[no-]split-index] [--[no-]split-index]
@ -113,6 +114,11 @@ you will need to handle the situation manually.
set and unset the "skip-worktree" bit for the paths. See set and unset the "skip-worktree" bit for the paths. See
section "Skip-worktree bit" below for more information. section "Skip-worktree bit" below for more information.
--[no-]ignore-skip-worktree-entries::
Do not remove skip-worktree (AKA "index-only") entries even when
the `--remove` option was specified.
--[no-]fsmonitor-valid:: --[no-]fsmonitor-valid::
When one of these flags is specified, the object name recorded When one of these flags is specified, the object name recorded
for the paths are not updated. Instead, these options for the paths are not updated. Instead, these options

Просмотреть файл

@ -35,6 +35,7 @@ static int verbose;
static int mark_valid_only; static int mark_valid_only;
static int mark_skip_worktree_only; static int mark_skip_worktree_only;
static int mark_fsmonitor_only; static int mark_fsmonitor_only;
static int ignore_skip_worktree_entries;
#define MARK_FLAG 1 #define MARK_FLAG 1
#define UNMARK_FLAG 2 #define UNMARK_FLAG 2
static struct strbuf mtime_dir = STRBUF_INIT; static struct strbuf mtime_dir = STRBUF_INIT;
@ -381,7 +382,8 @@ static int process_path(const char *path, struct stat *st, int stat_errno)
* so updating it does not make sense. * so updating it does not make sense.
* On the other hand, removing it from index should work * 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 error("%s: cannot remove from the index", path);
return 0; return 0;
} }
@ -1013,6 +1015,8 @@ int cmd_update_index(int argc, const char **argv, const char *prefix)
{OPTION_SET_INT, 0, "no-skip-worktree", &mark_skip_worktree_only, NULL, {OPTION_SET_INT, 0, "no-skip-worktree", &mark_skip_worktree_only, NULL,
N_("clear skip-worktree bit"), N_("clear skip-worktree bit"),
PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL, UNMARK_FLAG}, 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, OPT_SET_INT(0, "info-only", &info_only,
N_("add to index only; do not add content to object database"), 1), N_("add to index only; do not add content to object database"), 1),
OPT_SET_INT(0, "force-remove", &force_remove, OPT_SET_INT(0, "force-remove", &force_remove,

Просмотреть файл

@ -134,6 +134,21 @@ test_expect_success 'git-clean, dirty case' '
test_i18ncmp expected result test_i18ncmp expected result
' '
test_expect_success '--ignore-skip-worktree-entries leaves worktree alone' '
test_commit keep-me &&
git update-index --skip-worktree keep-me.t &&
rm keep-me.t &&
: ignoring the worktree &&
git update-index --remove --ignore-skip-worktree-entries keep-me.t &&
git diff-index --cached --exit-code HEAD &&
: not ignoring the worktree, a deletion is staged &&
git update-index --remove keep-me.t &&
test_must_fail git diff-index --cached --exit-code HEAD \
--diff-filter=D -- keep-me.t
'
#TODO test_expect_failure 'git-apply adds file' false #TODO test_expect_failure 'git-apply adds file' false
#TODO test_expect_failure 'git-apply updates file' false #TODO test_expect_failure 'git-apply updates file' false
#TODO test_expect_failure 'git-apply removes file' false #TODO test_expect_failure 'git-apply removes file' false