Skip to content

Commit 48609de

Browse files
committed
Merge branch 'vd/sparse-clean-etc' into en/present-despite-skipped
* vd/sparse-clean-etc: update-index: reduce scope of index expansion in do_reupdate update-index: integrate with sparse index update-index: add tests for sparse-checkout compatibility checkout-index: integrate with sparse index checkout-index: add --ignore-skip-worktree-bits option checkout-index: expand sparse checkout compatibility tests clean: integrate with sparse index reset: reorder wildcard pathspec conditions reset: fix validation in sparse index test
2 parents 1ffcbaa + b9ca5e2 commit 48609de

8 files changed

+360
-17
lines changed

Documentation/git-checkout-index.txt

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ SYNOPSIS
1212
'git checkout-index' [-u] [-q] [-a] [-f] [-n] [--prefix=<string>]
1313
[--stage=<number>|all]
1414
[--temp]
15+
[--ignore-skip-worktree-bits]
1516
[-z] [--stdin]
1617
[--] [<file>...]
1718

@@ -37,8 +38,9 @@ OPTIONS
3738

3839
-a::
3940
--all::
40-
checks out all files in the index. Cannot be used
41-
together with explicit filenames.
41+
checks out all files in the index except for those with the
42+
skip-worktree bit set (see `--ignore-skip-worktree-bits`).
43+
Cannot be used together with explicit filenames.
4244

4345
-n::
4446
--no-create::
@@ -59,6 +61,10 @@ OPTIONS
5961
write the content to temporary files. The temporary name
6062
associations will be written to stdout.
6163

64+
--ignore-skip-worktree-bits::
65+
Check out all files, including those with the skip-worktree bit
66+
set.
67+
6268
--stdin::
6369
Instead of taking list of paths from the command line,
6470
read list of paths from the standard input. Paths are

builtin/checkout-index.c

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#define USE_THE_INDEX_COMPATIBILITY_MACROS
88
#include "builtin.h"
99
#include "config.h"
10+
#include "dir.h"
1011
#include "lockfile.h"
1112
#include "quote.h"
1213
#include "cache-tree.h"
@@ -17,6 +18,7 @@
1718
#define CHECKOUT_ALL 4
1819
static int nul_term_line;
1920
static int checkout_stage; /* default to checkout stage0 */
21+
static int ignore_skip_worktree; /* default to 0 */
2022
static int to_tempfile;
2123
static char topath[4][TEMPORARY_FILENAME_LENGTH + 1];
2224

@@ -65,6 +67,8 @@ static int checkout_file(const char *name, const char *prefix)
6567
int namelen = strlen(name);
6668
int pos = cache_name_pos(name, namelen);
6769
int has_same_name = 0;
70+
int is_file = 0;
71+
int is_skipped = 1;
6872
int did_checkout = 0;
6973
int errs = 0;
7074

@@ -78,6 +82,12 @@ static int checkout_file(const char *name, const char *prefix)
7882
break;
7983
has_same_name = 1;
8084
pos++;
85+
if (S_ISSPARSEDIR(ce->ce_mode))
86+
break;
87+
is_file = 1;
88+
if (!ignore_skip_worktree && ce_skip_worktree(ce))
89+
break;
90+
is_skipped = 0;
8191
if (ce_stage(ce) != checkout_stage
8292
&& (CHECKOUT_ALL != checkout_stage || !ce_stage(ce)))
8393
continue;
@@ -106,6 +116,11 @@ static int checkout_file(const char *name, const char *prefix)
106116
fprintf(stderr, "git checkout-index: %s ", name);
107117
if (!has_same_name)
108118
fprintf(stderr, "is not in the cache");
119+
else if (!is_file)
120+
fprintf(stderr, "is a sparse directory");
121+
else if (is_skipped)
122+
fprintf(stderr, "has skip-worktree enabled; "
123+
"use '--ignore-skip-worktree-bits' to checkout");
109124
else if (checkout_stage)
110125
fprintf(stderr, "does not exist at stage %d",
111126
checkout_stage);
@@ -121,10 +136,27 @@ static int checkout_all(const char *prefix, int prefix_length)
121136
int i, errs = 0;
122137
struct cache_entry *last_ce = NULL;
123138

124-
/* TODO: audit for interaction with sparse-index. */
125-
ensure_full_index(&the_index);
126139
for (i = 0; i < active_nr ; i++) {
127140
struct cache_entry *ce = active_cache[i];
141+
142+
if (S_ISSPARSEDIR(ce->ce_mode)) {
143+
if (!ce_skip_worktree(ce))
144+
BUG("sparse directory '%s' does not have skip-worktree set", ce->name);
145+
146+
/*
147+
* If the current entry is a sparse directory and skip-worktree
148+
* entries are being checked out, expand the index and continue
149+
* the loop on the current index position (now pointing to the
150+
* first entry inside the expanded sparse directory).
151+
*/
152+
if (ignore_skip_worktree) {
153+
ensure_full_index(&the_index);
154+
ce = active_cache[i];
155+
}
156+
}
157+
158+
if (!ignore_skip_worktree && ce_skip_worktree(ce))
159+
continue;
128160
if (ce_stage(ce) != checkout_stage
129161
&& (CHECKOUT_ALL != checkout_stage || !ce_stage(ce)))
130162
continue;
@@ -185,6 +217,8 @@ int cmd_checkout_index(int argc, const char **argv, const char *prefix)
185217
struct option builtin_checkout_index_options[] = {
186218
OPT_BOOL('a', "all", &all,
187219
N_("check out all files in the index")),
220+
OPT_BOOL(0, "ignore-skip-worktree-bits", &ignore_skip_worktree,
221+
N_("do not skip files with skip-worktree set")),
188222
OPT__FORCE(&force, N_("force overwrite of existing files"), 0),
189223
OPT__QUIET(&quiet,
190224
N_("no warning for existing files and files not in index")),
@@ -212,6 +246,9 @@ int cmd_checkout_index(int argc, const char **argv, const char *prefix)
212246
git_config(git_default_config, NULL);
213247
prefix_length = prefix ? strlen(prefix) : 0;
214248

249+
prepare_repo_settings(the_repository);
250+
the_repository->settings.command_requires_full_index = 0;
251+
215252
if (read_cache() < 0) {
216253
die("invalid cache");
217254
}

builtin/clean.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1009,6 +1009,9 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
10091009
dir.flags |= DIR_KEEP_UNTRACKED_CONTENTS;
10101010
}
10111011

1012+
prepare_repo_settings(the_repository);
1013+
the_repository->settings.command_requires_full_index = 0;
1014+
10121015
if (read_cache() < 0)
10131016
die(_("index file corrupt"));
10141017

builtin/reset.c

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -204,10 +204,16 @@ static int pathspec_needs_expanded_index(const struct pathspec *pathspec)
204204
/*
205205
* Special case: if the pattern is a path inside the cone
206206
* followed by only wildcards, the pattern cannot match
207-
* partial sparse directories, so we don't expand the index.
207+
* partial sparse directories, so we know we don't need to
208+
* expand the index.
209+
*
210+
* Examples:
211+
* - in-cone/foo***: doesn't need expanded index
212+
* - not-in-cone/bar*: may need expanded index
213+
* - **.c: may need expanded index
208214
*/
209-
if (path_in_cone_mode_sparse_checkout(item.original, &the_index) &&
210-
strspn(item.original + item.nowildcard_len, "*") == item.len - item.nowildcard_len)
215+
if (strspn(item.original + item.nowildcard_len, "*") == item.len - item.nowildcard_len &&
216+
path_in_cone_mode_sparse_checkout(item.original, &the_index))
211217
continue;
212218

213219
for (pos = 0; pos < active_nr; pos++) {

builtin/update-index.c

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -606,7 +606,7 @@ static struct cache_entry *read_one_ent(const char *which,
606606
error("%s: not in %s branch.", path, which);
607607
return NULL;
608608
}
609-
if (mode == S_IFDIR) {
609+
if (!the_index.sparse_index && mode == S_IFDIR) {
610610
if (which)
611611
error("%s: not a blob in %s branch.", path, which);
612612
return NULL;
@@ -743,8 +743,6 @@ static int do_reupdate(int ac, const char **av,
743743
*/
744744
has_head = 0;
745745
redo:
746-
/* TODO: audit for interaction with sparse-index. */
747-
ensure_full_index(&the_index);
748746
for (pos = 0; pos < active_nr; pos++) {
749747
const struct cache_entry *ce = active_cache[pos];
750748
struct cache_entry *old = NULL;
@@ -761,6 +759,16 @@ static int do_reupdate(int ac, const char **av,
761759
discard_cache_entry(old);
762760
continue; /* unchanged */
763761
}
762+
763+
/* At this point, we know the contents of the sparse directory are
764+
* modified with respect to HEAD, so we expand the index and restart
765+
* to process each path individually
766+
*/
767+
if (S_ISSPARSEDIR(ce->ce_mode)) {
768+
ensure_full_index(&the_index);
769+
goto redo;
770+
}
771+
764772
/* Be careful. The working tree may not have the
765773
* path anymore, in which case, under 'allow_remove',
766774
* or worse yet 'allow_replace', active_nr may decrease.
@@ -1077,6 +1085,9 @@ int cmd_update_index(int argc, const char **argv, const char *prefix)
10771085

10781086
git_config(git_default_config, NULL);
10791087

1088+
prepare_repo_settings(r);
1089+
the_repository->settings.command_requires_full_index = 0;
1090+
10801091
/* we will diagnose later if it turns out that we need to update it */
10811092
newfd = hold_locked_index(&lock_file, 0);
10821093
if (newfd < 0)

read-cache.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1339,9 +1339,6 @@ static int add_index_entry_with_check(struct index_state *istate, struct cache_e
13391339
int skip_df_check = option & ADD_CACHE_SKIP_DFCHECK;
13401340
int new_only = option & ADD_CACHE_NEW_ONLY;
13411341

1342-
if (!(option & ADD_CACHE_KEEP_CACHE_TREE))
1343-
cache_tree_invalidate_path(istate, ce->name);
1344-
13451342
/*
13461343
* If this entry's path sorts after the last entry in the index,
13471344
* we can avoid searching for it.
@@ -1352,6 +1349,13 @@ static int add_index_entry_with_check(struct index_state *istate, struct cache_e
13521349
else
13531350
pos = index_name_stage_pos(istate, ce->name, ce_namelen(ce), ce_stage(ce), EXPAND_SPARSE);
13541351

1352+
/*
1353+
* Cache tree path should be invalidated only after index_name_stage_pos,
1354+
* in case it expands a sparse index.
1355+
*/
1356+
if (!(option & ADD_CACHE_KEEP_CACHE_TREE))
1357+
cache_tree_invalidate_path(istate, ce->name);
1358+
13551359
/* existing match? Just replace it. */
13561360
if (pos >= 0) {
13571361
if (!new_only)

t/perf/p2000-sparse-operations.sh

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,5 +117,7 @@ test_perf_on_all git diff
117117
test_perf_on_all git diff --cached
118118
test_perf_on_all git blame $SPARSE_CONE/a
119119
test_perf_on_all git blame $SPARSE_CONE/f3/a
120+
test_perf_on_all git checkout-index -f --all
121+
test_perf_on_all git update-index --add --remove $SPARSE_CONE/a
120122

121123
test_done

0 commit comments

Comments
 (0)