Teach Git to respect skip-worktree bit (writing part)
This part is mainly to remove CE_VALID shortcuts (and as a consequence, ce_uptodate() shortcuts as it may be turned on by CE_VALID) in writing code path if skip-worktree is used. Various tests are added to avoid future breakages. Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Nguyễn Thái Ngọc Duy committed
Aug 20, 2009 at 20:46 UTC
52030836943c0d28d8be4202762ede28e921dc21
2 files changed
+148
-2
t/t7012-skip-worktree-writing.sh
new
+146
@@ -0,0 +1,146 @@
1
+#!/bin/sh
2
+#
3
+# Copyright (c) 2008 Nguyễn Thái Ngọc Duy
4
+#
5
+
6
+test_description='test worktree writing operations when skip-worktree is used'
7
+
8
+. ./test-lib.sh
9
+
10
+test_expect_success 'setup' '
11
+ test_commit init &&
12
+ echo modified >> init.t &&
13
+ touch added &&
14
+ git add init.t added &&
15
+ git commit -m "modified and added" &&
16
+ git tag top
17
+'
18
+
19
+test_expect_success 'read-tree updates worktree, absent case' '
20
+ git checkout -f top &&
21
+ git update-index --skip-worktree init.t &&
22
+ rm init.t &&
23
+ git read-tree -m -u HEAD^ &&
24
+ echo init > expected &&
25
+ test_cmp expected init.t
26
+'
27
+
28
+test_expect_success 'read-tree updates worktree, dirty case' '
29
+ git checkout -f top &&
30
+ git update-index --skip-worktree init.t &&
31
+ echo dirty >> init.t &&
32
+ test_must_fail git read-tree -m -u HEAD^ &&
33
+ grep -q dirty init.t &&
34
+ test "$(git ls-files -t init.t)" = "S init.t" &&
35
+ git update-index --no-skip-worktree init.t
36
+'
37
+
38
+test_expect_success 'read-tree removes worktree, absent case' '
39
+ git checkout -f top &&
40
+ git update-index --skip-worktree added &&
41
+ rm added &&
42
+ git read-tree -m -u HEAD^ &&
43
+ test ! -f added
44
+'
45
+
46
+test_expect_success 'read-tree removes worktree, dirty case' '
47
+ git checkout -f top &&
48
+ git update-index --skip-worktree added &&
49
+ echo dirty >> added &&
50
+ test_must_fail git read-tree -m -u HEAD^ &&
51
+ grep -q dirty added &&
52
+ test "$(git ls-files -t added)" = "S added" &&
53
+ git update-index --no-skip-worktree added
54
+'
55
+
56
+NULL_SHA1=e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
57
+ZERO_SHA0=0000000000000000000000000000000000000000
58
+setup_absent() {
59
+ test -f 1 && rm 1
60
+ git update-index --remove 1 &&
61
+ git update-index --add --cacheinfo 100644 $NULL_SHA1 1 &&
62
+ git update-index --skip-worktree 1
63
+}
64
+
65
+test_absent() {
66
+ echo "100644 $NULL_SHA1 0 1" > expected &&
67
+ git ls-files --stage 1 > result &&
68
+ test_cmp expected result &&
69
+ test ! -f 1
70
+}
71
+
72
+setup_dirty() {
73
+ git update-index --force-remove 1 &&
74
+ echo dirty > 1 &&
75
+ git update-index --add --cacheinfo 100644 $NULL_SHA1 1 &&
76
+ git update-index --skip-worktree 1
77
+}
78
+
79
+test_dirty() {
80
+ echo "100644 $NULL_SHA1 0 1" > expected &&
81
+ git ls-files --stage 1 > result &&
82
+ test_cmp expected result &&
83
+ echo dirty > expected
84
+ test_cmp expected 1
85
+}
86
+
87
+cat >expected <<EOF
88
+S 1
89
+H 2
90
+H init.t
91
+S sub/1
92
+H sub/2
93
+EOF
94
+
95
+test_expect_success 'index setup' '
96
+ git checkout -f init &&
97
+ mkdir sub &&
98
+ touch ./1 ./2 sub/1 sub/2 &&
99
+ git add 1 2 sub/1 sub/2 &&
100
+ git update-index --skip-worktree 1 sub/1 &&
101
+ git ls-files -t > result &&
102
+ test_cmp expected result
103
+'
104
+
105
+test_expect_success 'git-add ignores worktree content' '
106
+ setup_absent &&
107
+ git add 1 &&
108
+ test_absent
109
+'
110
+
111
+test_expect_success 'git-add ignores worktree content' '
112
+ setup_dirty &&
113
+ git add 1 &&
114
+ test_dirty
115
+'
116
+
117
+test_expect_success 'git-rm fails if worktree is dirty' '
118
+ setup_dirty &&
119
+ test_must_fail git rm 1 &&
120
+ test_dirty
121
+'
122
+
123
+cat >expected <<EOF
124
+Would remove expected
125
+Would remove result
126
+EOF
127
+test_expect_success 'git-clean, absent case' '
128
+ setup_absent &&
129
+ git clean -n > result &&
130
+ test_cmp expected result
131
+'
132
+
133
+test_expect_success 'git-clean, dirty case' '
134
+ setup_dirty &&
135
+ git clean -n > result &&
136
+ test_cmp expected result
137
+'
138
+
139
+test_expect_failure 'git-apply adds file' false
140
+test_expect_failure 'git-apply updates file' false
141
+test_expect_failure 'git-apply removes file' false
142
+test_expect_failure 'git-mv to skip-worktree' false
143
+test_expect_failure 'git-mv from skip-worktree' false
144
+test_expect_failure 'git-checkout' false
145
+
146
+test_done
unpack-trees.c
+2
-2
@@ -450,7 +450,7 @@ static int verify_uptodate(struct cache_entry *ce,
450
{
451
struct stat st;
452
453
- if (o->index_only || o->reset || ce_uptodate(ce))
453
+ if (o->index_only || (!ce_skip_worktree(ce) && (o->reset || ce_uptodate(ce))))
454
return 0;
455
456
if (!lstat(ce->name, &st)) {
@@ -1004,7 +1004,7 @@ int oneway_merge(struct cache_entry **src, struct unpack_trees_options *o)
1004
1005
if (old && same(old, a)) {
1006
int update = 0;
1007
- if (o->reset && !ce_uptodate(old)) {
1007
+ if (o->reset && !ce_uptodate(old) && !ce_skip_worktree(old)) {
1008
struct stat st;
1009
if (lstat(old->name, &st) ||
1010
ie_match_stat(o->src_index, old, &st, CE_MATCH_IGNORE_VALID))