Skip to content

Commit

Permalink
Merge pull request #424 from vdye/sparse-index/checkout-index
Browse files Browse the repository at this point in the history
Sparse index: `checkout-index`
  • Loading branch information
vdye authored and derrickstolee committed Nov 15, 2021
2 parents 599ee75 + e82fdce commit a188f45
Show file tree
Hide file tree
Showing 5 changed files with 95 additions and 7 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]
[--sparse]
[-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, excluding those outside
any specified sparse checkout patterns (see `--sparse`).
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.

--sparse::
Refresh files outside of the sparse checkout boundary. May
only be used in conjunction with `--all`.

--stdin::
Instead of taking list of paths from the command line,
read list of paths from the standard input. Paths are
Expand Down
26 changes: 22 additions & 4 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 Down Expand Up @@ -65,6 +66,7 @@ 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 did_checkout = 0;
int errs = 0;

Expand All @@ -78,6 +80,9 @@ 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 (ce_stage(ce) != checkout_stage
&& (CHECKOUT_ALL != checkout_stage || !ce_stage(ce)))
continue;
Expand Down Expand Up @@ -106,6 +111,8 @@ 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 (checkout_stage)
fprintf(stderr, "does not exist at stage %d",
checkout_stage);
Expand All @@ -116,15 +123,18 @@ static int checkout_file(const char *name, const char *prefix)
return -1;
}

static int checkout_all(const char *prefix, int prefix_length)
static int checkout_all(const char *prefix, int prefix_length, int include_sparse)
{
int i, errs = 0;
struct cache_entry *last_ce = NULL;

/* TODO: audit for interaction with sparse-index. */
ensure_full_index(&the_index);
if (include_sparse)
ensure_full_index(&the_index);

for (i = 0; i < active_nr ; i++) {
struct cache_entry *ce = active_cache[i];
if (!include_sparse && !path_in_sparse_checkout(ce->name, &the_index))
continue;
if (ce_stage(ce) != checkout_stage
&& (CHECKOUT_ALL != checkout_stage || !ce_stage(ce)))
continue;
Expand Down Expand Up @@ -176,6 +186,7 @@ int cmd_checkout_index(int argc, const char **argv, const char *prefix)
int i;
struct lock_file lock_file = LOCK_INIT;
int all = 0;
int include_sparse = 0;
int read_from_stdin = 0;
int prefix_length;
int force = 0, quiet = 0, not_new = 0;
Expand All @@ -185,6 +196,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, "sparse", &include_sparse,
N_("do not skip files outside the sparse checkout boundary")),
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 +225,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 Expand Up @@ -247,6 +263,8 @@ int cmd_checkout_index(int argc, const char **argv, const char *prefix)

if (all)
die("git checkout-index: don't mix '--all' and explicit filenames");
if (include_sparse)
die("git checkout-index: don't mix '--sparse' and explicit filenames");
if (read_from_stdin)
die("git checkout-index: don't mix '--stdin' and explicit filenames");
p = prefix_path(prefix, prefix_length, arg);
Expand Down Expand Up @@ -280,7 +298,7 @@ int cmd_checkout_index(int argc, const char **argv, const char *prefix)
}

if (all)
err |= checkout_all(prefix, prefix_length);
err |= checkout_all(prefix, prefix_length, include_sparse);

if (pc_workers > 1)
err |= run_parallel_checkout(&state, pc_workers, pc_threshold,
Expand Down
2 changes: 1 addition & 1 deletion builtin/stash.c
Original file line number Diff line number Diff line change
Expand Up @@ -365,7 +365,7 @@ static int restore_untracked(struct object_id *u_tree)

child_process_init(&cp);
cp.git_cmd = 1;
strvec_pushl(&cp.args, "checkout-index", "--all", NULL);
strvec_pushl(&cp.args, "checkout-index", "--all", "--sparse", NULL);
strvec_pushf(&cp.env_array, "GIT_INDEX_FILE=%s",
stash_index_path.buf);

Expand Down
1 change: 1 addition & 0 deletions t/perf/p2000-sparse-operations.sh
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ test_perf_on_all git checkout -f -
test_perf_on_all git reset
test_perf_on_all git reset --hard
test_perf_on_all git reset -- does-not-exist
test_perf_on_all git checkout-index -f --all
test_perf_on_all git update-index --add --remove
test_perf_on_all git diff
test_perf_on_all git diff --staged
Expand Down
63 changes: 63 additions & 0 deletions t/t1092-sparse-checkout-compatibility.sh
Original file line number Diff line number Diff line change
Expand Up @@ -930,6 +930,67 @@ test_expect_success 'cherry-pick with conflicts' '
test_all_match test_must_fail git cherry-pick to-cherry-pick
'

test_expect_success 'checkout-index inside sparse definition' '
init_repos &&
run_on_all rm -f deep/a &&
test_all_match git checkout-index -- deep/a &&
test_all_match git status --porcelain=v2 &&
echo test >>new-a &&
run_on_all cp ../new-a a &&
test_all_match test_must_fail git checkout-index -- a &&
test_all_match git checkout-index -f -- a &&
test_all_match git status --porcelain=v2
'

test_expect_success 'checkout-index outside sparse definition' '
init_repos &&
# File does not exist on disk yet for sparse checkouts, so checkout-index
# succeeds without -f
test_sparse_match git checkout-index -- folder1/a &&
test_cmp sparse-checkout/folder1/a sparse-index/folder1/a &&
test_cmp sparse-checkout/folder1/a full-checkout/folder1/a &&
run_on_sparse rm -rf folder1 &&
echo test >new-a &&
run_on_sparse mkdir -p folder1 &&
run_on_all cp ../new-a folder1/a &&
test_all_match test_must_fail git checkout-index -- folder1/a &&
test_all_match git checkout-index -f -- folder1/a &&
test_cmp sparse-checkout/folder1/a sparse-index/folder1/a &&
test_cmp sparse-checkout/folder1/a full-checkout/folder1/a
'

test_expect_success 'checkout-index with folders' '
init_repos &&
# Inside checkout definition
test_all_match test_must_fail git checkout-index -f -- deep/ &&
# Outside checkout definition
# Note: although all tests fail (as expected), the messaging differs. For
# non-sparse index checkouts, the error is that the "file" does not appear
# in the index; for sparse checkouts, the error is explicitly that the
# entry is a sparse directory.
run_on_all test_must_fail git checkout-index -f -- folder1/ &&
test_cmp full-checkout-err sparse-checkout-err &&
! test_cmp full-checkout-err sparse-index-err &&
grep "is a sparse directory" sparse-index-err
'

test_expect_success 'checkout-index --all' '
init_repos &&
test_all_match git checkout-index --all &&
test_sparse_match test_path_is_missing folder1 &&
test_all_match git checkout-index --sparse --all &&
test_all_match test_path_exists folder1
'

test_expect_success 'clean' '
init_repos &&
Expand Down Expand Up @@ -1036,6 +1097,8 @@ test_expect_success 'sparse-index is not expanded' '
echo >>sparse-index/untracked.txt &&
ensure_not_expanded add . &&
ensure_not_expanded checkout-index -f a &&
ensure_not_expanded checkout-index -f --all &&
for ref in update-deep update-folder1 update-folder2 update-deep
do
echo >>sparse-index/README.md &&
Expand Down

0 comments on commit a188f45

Please sign in to comment.