Introduce "skip-worktree" bit in index, teach Git to get/set this bit
Detail about this bit is in Documentation/git-update-index.txt. Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
parent
dbd57f9968
commit
44a3691362
@ -107,6 +107,7 @@ OPTIONS
|
||||
Identify the file status with the following tags (followed by
|
||||
a space) at the start of each line:
|
||||
H:: cached
|
||||
S:: skip-worktree
|
||||
M:: unmerged
|
||||
R:: removed/deleted
|
||||
C:: modified/changed
|
||||
|
@ -15,6 +15,7 @@ SYNOPSIS
|
||||
[--cacheinfo <mode> <object> <file>]\*
|
||||
[--chmod=(+|-)x]
|
||||
[--assume-unchanged | --no-assume-unchanged]
|
||||
[--skip-worktree | --no-skip-worktree]
|
||||
[--ignore-submodules]
|
||||
[--really-refresh] [--unresolve] [--again | -g]
|
||||
[--info-only] [--index-info]
|
||||
@ -99,6 +100,13 @@ in the index e.g. when merging in a commit;
|
||||
thus, in case the assumed-untracked file is changed upstream,
|
||||
you will need to handle the situation manually.
|
||||
|
||||
--skip-worktree::
|
||||
--no-skip-worktree::
|
||||
When one of these flags is specified, the object name recorded
|
||||
for the paths are not updated. Instead, these options
|
||||
set and unset the "skip-worktree" bit for the paths. See
|
||||
section "Skip-worktree bit" below for more information.
|
||||
|
||||
-g::
|
||||
--again::
|
||||
Runs 'git-update-index' itself on the paths whose index
|
||||
@ -304,6 +312,27 @@ M foo.c
|
||||
<9> now it checks with lstat(2) and finds it has been changed.
|
||||
|
||||
|
||||
Skip-worktree bit
|
||||
-----------------
|
||||
|
||||
Skip-worktree bit can be defined in one (long) sentence: When reading
|
||||
an entry, if it is marked as skip-worktree, then Git pretends its
|
||||
working directory version is up to date and read the index version
|
||||
instead.
|
||||
|
||||
To elaborate, "reading" means checking for file existence, reading
|
||||
file attributes or file content. The working directory version may be
|
||||
present or absent. If present, its content may match against the index
|
||||
version or not. Writing is not affected by this bit, content safety
|
||||
is still first priority. Note that Git _can_ update working directory
|
||||
file, that is marked skip-worktree, if it is safe to do so (i.e.
|
||||
working directory version matches index version)
|
||||
|
||||
Although this bit looks similar to assume-unchanged bit, its goal is
|
||||
different from assume-unchanged bit's. Skip-worktree also takes
|
||||
precedence over assume-unchanged bit when both are set.
|
||||
|
||||
|
||||
Configuration
|
||||
-------------
|
||||
|
||||
|
@ -37,6 +37,7 @@ static const char *tag_removed = "";
|
||||
static const char *tag_other = "";
|
||||
static const char *tag_killed = "";
|
||||
static const char *tag_modified = "";
|
||||
static const char *tag_skip_worktree = "";
|
||||
|
||||
static void show_dir_entry(const char *tag, struct dir_entry *ent)
|
||||
{
|
||||
@ -178,7 +179,8 @@ static void show_files(struct dir_struct *dir, const char *prefix)
|
||||
continue;
|
||||
if (ce->ce_flags & CE_UPDATE)
|
||||
continue;
|
||||
show_ce_entry(ce_stage(ce) ? tag_unmerged : tag_cached, ce);
|
||||
show_ce_entry(ce_stage(ce) ? tag_unmerged :
|
||||
(ce_skip_worktree(ce) ? tag_skip_worktree : tag_cached), ce);
|
||||
}
|
||||
}
|
||||
if (show_deleted | show_modified) {
|
||||
@ -490,6 +492,7 @@ int cmd_ls_files(int argc, const char **argv, const char *prefix)
|
||||
tag_modified = "C ";
|
||||
tag_other = "? ";
|
||||
tag_killed = "K ";
|
||||
tag_skip_worktree = "S ";
|
||||
}
|
||||
if (show_modified || show_others || show_deleted || (dir.flags & DIR_SHOW_IGNORED) || show_killed)
|
||||
require_work_tree = 1;
|
||||
|
@ -24,6 +24,7 @@ static int info_only;
|
||||
static int force_remove;
|
||||
static int verbose;
|
||||
static int mark_valid_only;
|
||||
static int mark_skip_worktree_only;
|
||||
#define MARK_FLAG 1
|
||||
#define UNMARK_FLAG 2
|
||||
|
||||
@ -276,6 +277,11 @@ static void update_one(const char *path, const char *prefix, int prefix_length)
|
||||
die("Unable to mark file %s", path);
|
||||
goto free_return;
|
||||
}
|
||||
if (mark_skip_worktree_only) {
|
||||
if (mark_ce_flags(p, CE_SKIP_WORKTREE, mark_skip_worktree_only == MARK_FLAG))
|
||||
die("Unable to mark file %s", path);
|
||||
goto free_return;
|
||||
}
|
||||
|
||||
if (force_remove) {
|
||||
if (remove_file_from_cache(p))
|
||||
@ -384,7 +390,7 @@ static void read_index_info(int line_termination)
|
||||
}
|
||||
|
||||
static const char update_index_usage[] =
|
||||
"git update-index [-q] [--add] [--replace] [--remove] [--unmerged] [--refresh] [--really-refresh] [--cacheinfo] [--chmod=(+|-)x] [--assume-unchanged] [--info-only] [--force-remove] [--stdin] [--index-info] [--unresolve] [--again | -g] [--ignore-missing] [-z] [--verbose] [--] <file>...";
|
||||
"git update-index [-q] [--add] [--replace] [--remove] [--unmerged] [--refresh] [--really-refresh] [--cacheinfo] [--chmod=(+|-)x] [--assume-unchanged] [--skip-worktree|--no-skip-worktree] [--info-only] [--force-remove] [--stdin] [--index-info] [--unresolve] [--again | -g] [--ignore-missing] [-z] [--verbose] [--] <file>...";
|
||||
|
||||
static unsigned char head_sha1[20];
|
||||
static unsigned char merge_head_sha1[20];
|
||||
@ -650,6 +656,14 @@ int cmd_update_index(int argc, const char **argv, const char *prefix)
|
||||
mark_valid_only = UNMARK_FLAG;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(path, "--no-skip-worktree")) {
|
||||
mark_skip_worktree_only = UNMARK_FLAG;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(path, "--skip-worktree")) {
|
||||
mark_skip_worktree_only = MARK_FLAG;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(path, "--info-only")) {
|
||||
info_only = 1;
|
||||
continue;
|
||||
|
4
cache.h
4
cache.h
@ -181,10 +181,11 @@ struct cache_entry {
|
||||
* Extended on-disk flags
|
||||
*/
|
||||
#define CE_INTENT_TO_ADD 0x20000000
|
||||
#define CE_SKIP_WORKTREE 0x40000000
|
||||
/* CE_EXTENDED2 is for future extension */
|
||||
#define CE_EXTENDED2 0x80000000
|
||||
|
||||
#define CE_EXTENDED_FLAGS (CE_INTENT_TO_ADD)
|
||||
#define CE_EXTENDED_FLAGS (CE_INTENT_TO_ADD | CE_SKIP_WORKTREE)
|
||||
|
||||
/*
|
||||
* Safeguard to avoid saving wrong flags:
|
||||
@ -233,6 +234,7 @@ static inline size_t ce_namelen(const struct cache_entry *ce)
|
||||
ondisk_cache_entry_size(ce_namelen(ce)))
|
||||
#define ce_stage(ce) ((CE_STAGEMASK & (ce)->ce_flags) >> CE_STAGESHIFT)
|
||||
#define ce_uptodate(ce) ((ce)->ce_flags & CE_UPTODATE)
|
||||
#define ce_skip_worktree(ce) ((ce)->ce_flags & CE_SKIP_WORKTREE)
|
||||
#define ce_mark_uptodate(ce) ((ce)->ce_flags |= CE_UPTODATE)
|
||||
|
||||
#define ce_permissions(mode) (((mode) & 0100) ? 0755 : 0644)
|
||||
|
57
t/t2104-update-index-skip-worktree.sh
Executable file
57
t/t2104-update-index-skip-worktree.sh
Executable file
@ -0,0 +1,57 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Copyright (c) 2008 Nguyễn Thái Ngọc Duy
|
||||
#
|
||||
|
||||
test_description='skip-worktree bit test'
|
||||
|
||||
. ./test-lib.sh
|
||||
|
||||
cat >expect.full <<EOF
|
||||
H 1
|
||||
H 2
|
||||
H sub/1
|
||||
H sub/2
|
||||
EOF
|
||||
|
||||
cat >expect.skip <<EOF
|
||||
S 1
|
||||
H 2
|
||||
S sub/1
|
||||
H sub/2
|
||||
EOF
|
||||
|
||||
test_expect_success 'setup' '
|
||||
mkdir sub &&
|
||||
touch ./1 ./2 sub/1 sub/2 &&
|
||||
git add 1 2 sub/1 sub/2 &&
|
||||
git ls-files -t | test_cmp expect.full -
|
||||
'
|
||||
|
||||
test_expect_success 'index is at version 2' '
|
||||
test "$(test-index-version < .git/index)" = 2
|
||||
'
|
||||
|
||||
test_expect_success 'update-index --skip-worktree' '
|
||||
git update-index --skip-worktree 1 sub/1 &&
|
||||
git ls-files -t | test_cmp expect.skip -
|
||||
'
|
||||
|
||||
test_expect_success 'index is at version 3 after having some skip-worktree entries' '
|
||||
test "$(test-index-version < .git/index)" = 3
|
||||
'
|
||||
|
||||
test_expect_success 'ls-files -t' '
|
||||
git ls-files -t | test_cmp expect.skip -
|
||||
'
|
||||
|
||||
test_expect_success 'update-index --no-skip-worktree' '
|
||||
git update-index --no-skip-worktree 1 sub/1 &&
|
||||
git ls-files -t | test_cmp expect.full -
|
||||
'
|
||||
|
||||
test_expect_success 'index version is back to 2 when there is no skip-worktree entry' '
|
||||
test "$(test-index-version < .git/index)" = 2
|
||||
'
|
||||
|
||||
test_done
|
Loading…
Reference in New Issue
Block a user