Skip to content

Commit e800ec9

Browse files
pcloudsgitster
authored andcommitted
unpack_trees(): apply $GIT_DIR/info/sparse-checkout to the final index
Signed-off-by: Nguyễn Thái Ngọc Duy <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 08aefc9 commit e800ec9

File tree

2 files changed

+83
-1
lines changed

2 files changed

+83
-1
lines changed

unpack-trees.c

Lines changed: 81 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,12 @@ static struct unpack_trees_error_msgs unpack_plumbing_errors = {
3232

3333
/* bind_overlap */
3434
"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.",
3541
};
3642

3743
#define ERRORMSG(o,fld) \
@@ -125,6 +131,57 @@ static int check_updates(struct unpack_trees_options *o)
125131
return errs != 0;
126132
}
127133

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+
128185
static inline int call_unpack_fn(struct cache_entry **src, struct unpack_trees_options *o)
129186
{
130187
int ret = o->fn(src, o);
@@ -376,7 +433,7 @@ static int unpack_failed(struct unpack_trees_options *o, const char *message)
376433
*/
377434
int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options *o)
378435
{
379-
int ret;
436+
int i, ret;
380437
static struct cache_entry *dfc;
381438
struct exclude_list el;
382439

@@ -440,6 +497,17 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options
440497
goto done;
441498
}
442499

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+
443511
o->src_index = NULL;
444512
ret = check_updates(o) ? (-2) : 0;
445513
if (o->dst_index)
@@ -512,6 +580,12 @@ static int verify_uptodate(struct cache_entry *ce,
512580
return verify_uptodate_1(ce, o, ERRORMSG(o, not_uptodate_file));
513581
}
514582

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+
515589
static void invalidate_ce_path(struct cache_entry *ce, struct unpack_trees_options *o)
516590
{
517591
if (ce)
@@ -705,6 +779,12 @@ static int verify_absent(struct cache_entry *ce, const char *action,
705779
return verify_absent_1(ce, action, o, ERRORMSG(o, would_lose_untracked));
706780
}
707781

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+
708788
static int merged_entry(struct cache_entry *merge, struct cache_entry *old,
709789
struct unpack_trees_options *o)
710790
{

unpack-trees.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ struct unpack_trees_error_msgs {
1515
const char *not_uptodate_dir;
1616
const char *would_lose_untracked;
1717
const char *bind_overlap;
18+
const char *sparse_not_uptodate_file;
19+
const char *would_lose_orphaned;
1820
};
1921

2022
struct unpack_trees_options {

0 commit comments

Comments
 (0)