unpack_trees(): apply $GIT_DIR/info/sparse-checkout to the final index
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:47 UTC
e800ec9d72a0fafbc323c41e90f7757062c2680e
2 files changed
+83
-1
unpack-trees.c
+81
-1
@@ -32,6 +32,12 @@ static struct unpack_trees_error_msgs unpack_plumbing_errors = {
32
33
/* bind_overlap */
34
"Entry '%s' overlaps with '%s'. Cannot bind.",
35
+
36
+ /* sparse_not_uptodate_file */
37
+ "Entry '%s' not uptodate. Cannot update sparse checkout.",
38
+
39
+ /* would_lose_orphaned */
40
+ "Working tree file '%s' would be %s by sparse checkout update.",
41
};
42
43
#define ERRORMSG(o,fld) \
@@ -125,6 +131,57 @@ static int check_updates(struct unpack_trees_options *o)
131
return errs != 0;
132
}
133
134
+static int verify_uptodate_sparse(struct cache_entry *ce, struct unpack_trees_options *o);
135
+static int verify_absent_sparse(struct cache_entry *ce, const char *action, struct unpack_trees_options *o);
136
+
137
+static int will_have_skip_worktree(const struct cache_entry *ce, struct unpack_trees_options *o)
138
+{
139
+ const char *basename;
140
+
141
+ if (ce_stage(ce))
142
+ return 0;
143
+
144
+ basename = strrchr(ce->name, '/');
145
+ basename = basename ? basename+1 : ce->name;
146
+ return excluded_from_list(ce->name, ce_namelen(ce), basename, NULL, o->el) <= 0;
147
+}
148
+
149
+static int apply_sparse_checkout(struct cache_entry *ce, struct unpack_trees_options *o)
150
+{
151
+ int was_skip_worktree = ce_skip_worktree(ce);
152
+
153
+ if (will_have_skip_worktree(ce, o))
154
+ ce->ce_flags |= CE_SKIP_WORKTREE;
155
+ else
156
+ ce->ce_flags &= ~CE_SKIP_WORKTREE;
157
+
158
+ /*
159
+ * We only care about files getting into the checkout area
160
+ * If merge strategies want to remove some, go ahead, this
161
+ * flag will be removed eventually in unpack_trees() if it's
162
+ * outside checkout area.
163
+ */
164
+ if (ce->ce_flags & CE_REMOVE)
165
+ return 0;
166
+
167
+ if (!was_skip_worktree && ce_skip_worktree(ce)) {
168
+ /*
169
+ * If CE_UPDATE is set, verify_uptodate() must be called already
170
+ * also stat info may have lost after merged_entry() so calling
171
+ * verify_uptodate() again may fail
172
+ */
173
+ if (!(ce->ce_flags & CE_UPDATE) && verify_uptodate_sparse(ce, o))
174
+ return -1;
175
+ ce->ce_flags |= CE_WT_REMOVE;
176
+ }
177
+ if (was_skip_worktree && !ce_skip_worktree(ce)) {
178
+ if (verify_absent_sparse(ce, "overwritten", o))
179
+ return -1;
180
+ ce->ce_flags |= CE_UPDATE;
181
+ }
182
+ return 0;
183
+}
184
+
185
static inline int call_unpack_fn(struct cache_entry **src, struct unpack_trees_options *o)
186
{
187
int ret = o->fn(src, o);
@@ -376,7 +433,7 @@ static int unpack_failed(struct unpack_trees_options *o, const char *message)
433
*/
434
int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options *o)
435
{
379
- int ret;
436
+ int i, ret;
437
static struct cache_entry *dfc;
438
struct exclude_list el;
439
@@ -440,6 +497,17 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options
497
goto done;
498
}
499
500
+ if (!o->skip_sparse_checkout) {
501
+ for (i = 0;i < o->result.cache_nr;i++) {
502
+ struct cache_entry *ce = o->result.cache[i];
503
+
504
+ if (apply_sparse_checkout(ce, o)) {
505
+ ret = -1;
506
+ goto done;
507
+ }
508
+ }
509
+ }
510
+
511
o->src_index = NULL;
512
ret = check_updates(o) ? (-2) : 0;
513
if (o->dst_index)
@@ -512,6 +580,12 @@ static int verify_uptodate(struct cache_entry *ce,
580
return verify_uptodate_1(ce, o, ERRORMSG(o, not_uptodate_file));
581
}
582
583
+static int verify_uptodate_sparse(struct cache_entry *ce,
584
+ struct unpack_trees_options *o)
585
+{
586
+ return verify_uptodate_1(ce, o, ERRORMSG(o, sparse_not_uptodate_file));
587
+}
588
+
589
static void invalidate_ce_path(struct cache_entry *ce, struct unpack_trees_options *o)
590
{
591
if (ce)
@@ -705,6 +779,12 @@ static int verify_absent(struct cache_entry *ce, const char *action,
779
return verify_absent_1(ce, action, o, ERRORMSG(o, would_lose_untracked));
780
}
781
782
+static int verify_absent_sparse(struct cache_entry *ce, const char *action,
783
+ struct unpack_trees_options *o)
784
+{
785
+ return verify_absent_1(ce, action, o, ERRORMSG(o, would_lose_orphaned));
786
+}
787
+
788
static int merged_entry(struct cache_entry *merge, struct cache_entry *old,
789
struct unpack_trees_options *o)
790
{
unpack-trees.h
+2
@@ -15,6 +15,8 @@ struct unpack_trees_error_msgs {
15
const char *not_uptodate_dir;
16
const char *would_lose_untracked;
17
const char *bind_overlap;
18
+ const char *sparse_not_uptodate_file;
19
+ const char *would_lose_orphaned;
20
};
21
22
struct unpack_trees_options {