Skip to content

Commit

Permalink
Merge branch 'vd/sparse-clean-etc' into en/present-despite-skipped
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
gitster committed Jan 13, 2022
2 parents 1ffcbaa + b9ca5e2 commit 48609de
Show file tree
Hide file tree
Showing 8 changed files with 360 additions and 17 deletions.
10 changes: 8 additions & 2 deletions Documentation/git-checkout-index.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ SYNOPSIS
'git checkout-index' [-u] [-q] [-a] [-f] [-n] [--prefix=<string>]
[--stage=<number>|all]
[--temp]
[--ignore-skip-worktree-bits]
[-z] [--stdin]
[--] [<file>...]

Expand All @@ -37,8 +38,9 @@ OPTIONS

-a::
--all::
checks out all files in the index. Cannot be used
together with explicit filenames.
checks out all files in the index except for those with the
skip-worktree bit set (see `--ignore-skip-worktree-bits`).
Cannot be used together with explicit filenames.

-n::
--no-create::
Expand All @@ -59,6 +61,10 @@ OPTIONS
write the content to temporary files. The temporary name
associations will be written to stdout.

--ignore-skip-worktree-bits::
Check out all files, including those with the skip-worktree bit
set.

--stdin::
Instead of taking list of paths from the command line,
read list of paths from the standard input. Paths are
Expand Down
41 changes: 39 additions & 2 deletions builtin/checkout-index.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#define USE_THE_INDEX_COMPATIBILITY_MACROS
#include "builtin.h"
#include "config.h"
#include "dir.h"
#include "lockfile.h"
#include "quote.h"
#include "cache-tree.h"
Expand All @@ -17,6 +18,7 @@
#define CHECKOUT_ALL 4
static int nul_term_line;
static int checkout_stage; /* default to checkout stage0 */
static int ignore_skip_worktree; /* default to 0 */
static int to_tempfile;
static char topath[4][TEMPORARY_FILENAME_LENGTH + 1];

Expand Down Expand Up @@ -65,6 +67,8 @@ static int checkout_file(const char *name, const char *prefix)
int namelen = strlen(name);
int pos = cache_name_pos(name, namelen);
int has_same_name = 0;
int is_file = 0;
int is_skipped = 1;
int did_checkout = 0;
int errs = 0;

Expand All @@ -78,6 +82,12 @@ static int checkout_file(const char *name, const char *prefix)
break;
has_same_name = 1;
pos++;
if (S_ISSPARSEDIR(ce->ce_mode))
break;
is_file = 1;
if (!ignore_skip_worktree && ce_skip_worktree(ce))
break;
is_skipped = 0;
if (ce_stage(ce) != checkout_stage
&& (CHECKOUT_ALL != checkout_stage || !ce_stage(ce)))
continue;
Expand Down Expand Up @@ -106,6 +116,11 @@ static int checkout_file(const char *name, const char *prefix)
fprintf(stderr, "git checkout-index: %s ", name);
if (!has_same_name)
fprintf(stderr, "is not in the cache");
else if (!is_file)
fprintf(stderr, "is a sparse directory");
else if (is_skipped)
fprintf(stderr, "has skip-worktree enabled; "
"use '--ignore-skip-worktree-bits' to checkout");
else if (checkout_stage)
fprintf(stderr, "does not exist at stage %d",
checkout_stage);
Expand All @@ -121,10 +136,27 @@ static int checkout_all(const char *prefix, int prefix_length)
int i, errs = 0;
struct cache_entry *last_ce = NULL;

/* TODO: audit for interaction with sparse-index. */
ensure_full_index(&the_index);
for (i = 0; i < active_nr ; i++) {
struct cache_entry *ce = active_cache[i];

if (S_ISSPARSEDIR(ce->ce_mode)) {
if (!ce_skip_worktree(ce))
BUG("sparse directory '%s' does not have skip-worktree set", ce->name);

/*
* If the current entry is a sparse directory and skip-worktree
* entries are being checked out, expand the index and continue
* the loop on the current index position (now pointing to the
* first entry inside the expanded sparse directory).
*/
if (ignore_skip_worktree) {
ensure_full_index(&the_index);
ce = active_cache[i];
}
}

if (!ignore_skip_worktree && ce_skip_worktree(ce))
continue;
if (ce_stage(ce) != checkout_stage
&& (CHECKOUT_ALL != checkout_stage || !ce_stage(ce)))
continue;
Expand Down Expand Up @@ -185,6 +217,8 @@ int cmd_checkout_index(int argc, const char **argv, const char *prefix)
struct option builtin_checkout_index_options[] = {
OPT_BOOL('a', "all", &all,
N_("check out all files in the index")),
OPT_BOOL(0, "ignore-skip-worktree-bits", &ignore_skip_worktree,
N_("do not skip files with skip-worktree set")),
OPT__FORCE(&force, N_("force overwrite of existing files"), 0),
OPT__QUIET(&quiet,
N_("no warning for existing files and files not in index")),
Expand Down Expand Up @@ -212,6 +246,9 @@ int cmd_checkout_index(int argc, const char **argv, const char *prefix)
git_config(git_default_config, NULL);
prefix_length = prefix ? strlen(prefix) : 0;

prepare_repo_settings(the_repository);
the_repository->settings.command_requires_full_index = 0;

if (read_cache() < 0) {
die("invalid cache");
}
Expand Down
3 changes: 3 additions & 0 deletions builtin/clean.c
Original file line number Diff line number Diff line change
Expand Up @@ -1009,6 +1009,9 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
dir.flags |= DIR_KEEP_UNTRACKED_CONTENTS;
}

prepare_repo_settings(the_repository);
the_repository->settings.command_requires_full_index = 0;

if (read_cache() < 0)
die(_("index file corrupt"));

Expand Down
12 changes: 9 additions & 3 deletions builtin/reset.c
Original file line number Diff line number Diff line change
Expand Up @@ -204,10 +204,16 @@ static int pathspec_needs_expanded_index(const struct pathspec *pathspec)
/*
* Special case: if the pattern is a path inside the cone
* followed by only wildcards, the pattern cannot match
* partial sparse directories, so we don't expand the index.
* partial sparse directories, so we know we don't need to
* expand the index.
*
* Examples:
* - in-cone/foo***: doesn't need expanded index
* - not-in-cone/bar*: may need expanded index
* - **.c: may need expanded index
*/
if (path_in_cone_mode_sparse_checkout(item.original, &the_index) &&
strspn(item.original + item.nowildcard_len, "*") == item.len - item.nowildcard_len)
if (strspn(item.original + item.nowildcard_len, "*") == item.len - item.nowildcard_len &&
path_in_cone_mode_sparse_checkout(item.original, &the_index))
continue;

for (pos = 0; pos < active_nr; pos++) {
Expand Down
17 changes: 14 additions & 3 deletions builtin/update-index.c
Original file line number Diff line number Diff line change
Expand Up @@ -606,7 +606,7 @@ static struct cache_entry *read_one_ent(const char *which,
error("%s: not in %s branch.", path, which);
return NULL;
}
if (mode == S_IFDIR) {
if (!the_index.sparse_index && mode == S_IFDIR) {
if (which)
error("%s: not a blob in %s branch.", path, which);
return NULL;
Expand Down Expand Up @@ -743,8 +743,6 @@ static int do_reupdate(int ac, const char **av,
*/
has_head = 0;
redo:
/* TODO: audit for interaction with sparse-index. */
ensure_full_index(&the_index);
for (pos = 0; pos < active_nr; pos++) {
const struct cache_entry *ce = active_cache[pos];
struct cache_entry *old = NULL;
Expand All @@ -761,6 +759,16 @@ static int do_reupdate(int ac, const char **av,
discard_cache_entry(old);
continue; /* unchanged */
}

/* At this point, we know the contents of the sparse directory are
* modified with respect to HEAD, so we expand the index and restart
* to process each path individually
*/
if (S_ISSPARSEDIR(ce->ce_mode)) {
ensure_full_index(&the_index);
goto redo;
}

/* Be careful. The working tree may not have the
* path anymore, in which case, under 'allow_remove',
* or worse yet 'allow_replace', active_nr may decrease.
Expand Down Expand Up @@ -1077,6 +1085,9 @@ int cmd_update_index(int argc, const char **argv, const char *prefix)

git_config(git_default_config, NULL);

prepare_repo_settings(r);
the_repository->settings.command_requires_full_index = 0;

/* we will diagnose later if it turns out that we need to update it */
newfd = hold_locked_index(&lock_file, 0);
if (newfd < 0)
Expand Down
10 changes: 7 additions & 3 deletions read-cache.c
Original file line number Diff line number Diff line change
Expand Up @@ -1339,9 +1339,6 @@ static int add_index_entry_with_check(struct index_state *istate, struct cache_e
int skip_df_check = option & ADD_CACHE_SKIP_DFCHECK;
int new_only = option & ADD_CACHE_NEW_ONLY;

if (!(option & ADD_CACHE_KEEP_CACHE_TREE))
cache_tree_invalidate_path(istate, ce->name);

/*
* If this entry's path sorts after the last entry in the index,
* we can avoid searching for it.
Expand All @@ -1352,6 +1349,13 @@ static int add_index_entry_with_check(struct index_state *istate, struct cache_e
else
pos = index_name_stage_pos(istate, ce->name, ce_namelen(ce), ce_stage(ce), EXPAND_SPARSE);

/*
* Cache tree path should be invalidated only after index_name_stage_pos,
* in case it expands a sparse index.
*/
if (!(option & ADD_CACHE_KEEP_CACHE_TREE))
cache_tree_invalidate_path(istate, ce->name);

/* existing match? Just replace it. */
if (pos >= 0) {
if (!new_only)
Expand Down
2 changes: 2 additions & 0 deletions t/perf/p2000-sparse-operations.sh
Original file line number Diff line number Diff line change
Expand Up @@ -117,5 +117,7 @@ test_perf_on_all git diff
test_perf_on_all git diff --cached
test_perf_on_all git blame $SPARSE_CONE/a
test_perf_on_all git blame $SPARSE_CONE/f3/a
test_perf_on_all git checkout-index -f --all
test_perf_on_all git update-index --add --remove $SPARSE_CONE/a

test_done
Loading

0 comments on commit 48609de

Please sign in to comment.