Skip to content

Commit

Permalink
Introduce "skip-worktree" bit in index, teach Git to get/set this bit
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Nguyễn Thái Ngọc Duy authored and Junio C Hamano committed Aug 24, 2009
1 parent dbd57f9 commit 44a3691
Show file tree
Hide file tree
Showing 6 changed files with 109 additions and 3 deletions.
1 change: 1 addition & 0 deletions Documentation/git-ls-files.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
29 changes: 29 additions & 0 deletions Documentation/git-update-index.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
-------------

Expand Down
5 changes: 4 additions & 1 deletion builtin-ls-files.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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;
Expand Down
16 changes: 15 additions & 1 deletion builtin-update-index.c
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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))
Expand Down Expand Up @@ -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];
Expand Down Expand Up @@ -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;
Expand Down
4 changes: 3 additions & 1 deletion cache.h
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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)
Expand Down
57 changes: 57 additions & 0 deletions t/t2104-update-index-skip-worktree.sh
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit 44a3691

Please sign in to comment.