Merge branch 'ds/fetch-pull-with-sparse-index'

"git fetch" and "git pull" are now declared sparse-index clean.
Also "git ls-files" learns the "--sparse" option to help debugging.

* ds/fetch-pull-with-sparse-index:
  test-read-cache: remove --table, --expand options
  t1091/t3705: remove 'test-tool read-cache --table'
  t1092: replace 'read-cache --table' with 'ls-files --sparse'
  ls-files: add --sparse option
  fetch/pull: use the sparse index
This commit is contained in:
Junio C Hamano 2022-01-10 11:52:50 -08:00
commit 3c0e417827
8 changed files with 168 additions and 82 deletions

View file

@ -187,6 +187,11 @@ Both the <eolinfo> in the index ("i/<eolinfo>")
and in the working tree ("w/<eolinfo>") are shown for regular files,
followed by the ("attr/<eolattr>").
--sparse::
If the index is sparse, show the sparse directories without expanding
to the contained files. Sparse directories will be shown with a
trailing slash, such as "x/" for a sparse directory "x".
\--::
Do not interpret any more arguments as options.

View file

@ -2009,6 +2009,8 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
}
git_config(git_fetch_config, NULL);
prepare_repo_settings(the_repository);
the_repository->settings.command_requires_full_index = 0;
argc = parse_options(argc, argv, prefix,
builtin_fetch_options, builtin_fetch_usage, 0);

View file

@ -37,6 +37,7 @@ static int debug_mode;
static int show_eol;
static int recurse_submodules;
static int skipping_duplicates;
static int show_sparse_dirs;
static const char *prefix;
static int max_prefix_len;
@ -315,8 +316,10 @@ static void show_files(struct repository *repo, struct dir_struct *dir)
if (!(show_cached || show_stage || show_deleted || show_modified))
return;
/* TODO: audit for interaction with sparse-index. */
ensure_full_index(repo->index);
if (!show_sparse_dirs)
ensure_full_index(repo->index);
for (i = 0; i < repo->index->cache_nr; i++) {
const struct cache_entry *ce = repo->index->cache[i];
struct stat st;
@ -670,6 +673,8 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
OPT_BOOL(0, "debug", &debug_mode, N_("show debugging data")),
OPT_BOOL(0, "deduplicate", &skipping_duplicates,
N_("suppress duplicate entries")),
OPT_BOOL(0, "sparse", &show_sparse_dirs,
N_("show sparse directories in the presence of a sparse index")),
OPT_END()
};
int ret = 0;
@ -677,6 +682,9 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
if (argc == 2 && !strcmp(argv[1], "-h"))
usage_with_options(ls_files_usage, builtin_ls_files_options);
prepare_repo_settings(the_repository);
the_repository->settings.command_requires_full_index = 0;
prefix = cmd_prefix;
if (prefix)
prefix_len = strlen(prefix);

View file

@ -994,6 +994,8 @@ int cmd_pull(int argc, const char **argv, const char *prefix)
set_reflog_message(argc, argv);
git_config(git_pull_config, NULL);
prepare_repo_settings(the_repository);
the_repository->settings.command_requires_full_index = 0;
argc = parse_options(argc, argv, prefix, pull_options, pull_usage, 0);

View file

@ -1,83 +1,39 @@
#include "test-tool.h"
#include "cache.h"
#include "config.h"
#include "blob.h"
#include "commit.h"
#include "tree.h"
#include "sparse-index.h"
static void print_cache_entry(struct cache_entry *ce)
{
const char *type;
printf("%06o ", ce->ce_mode & 0177777);
if (S_ISSPARSEDIR(ce->ce_mode))
type = tree_type;
else if (S_ISGITLINK(ce->ce_mode))
type = commit_type;
else
type = blob_type;
printf("%s %s\t%s\n",
type,
oid_to_hex(&ce->oid),
ce->name);
}
static void print_cache(struct index_state *istate)
{
int i;
for (i = 0; i < istate->cache_nr; i++)
print_cache_entry(istate->cache[i]);
}
int cmd__read_cache(int argc, const char **argv)
{
struct repository *r = the_repository;
int i, cnt = 1;
const char *name = NULL;
int table = 0, expand = 0;
initialize_the_repository();
for (++argv, --argc; *argv && starts_with(*argv, "--"); ++argv, --argc) {
if (skip_prefix(*argv, "--print-and-refresh=", &name))
continue;
if (!strcmp(*argv, "--table"))
table = 1;
else if (!strcmp(*argv, "--expand"))
expand = 1;
if (argc > 1 && skip_prefix(argv[1], "--print-and-refresh=", &name)) {
argc--;
argv++;
}
if (argc == 1)
cnt = strtol(argv[0], NULL, 0);
if (argc == 2)
cnt = strtol(argv[1], NULL, 0);
setup_git_directory();
git_config(git_default_config, NULL);
prepare_repo_settings(r);
r->settings.command_requires_full_index = 0;
for (i = 0; i < cnt; i++) {
repo_read_index(r);
if (expand)
ensure_full_index(r->index);
read_cache();
if (name) {
int pos;
refresh_index(r->index, REFRESH_QUIET,
refresh_index(&the_index, REFRESH_QUIET,
NULL, NULL, NULL);
pos = index_name_pos(r->index, name, strlen(name));
pos = index_name_pos(&the_index, name, strlen(name));
if (pos < 0)
die("%s not in index", name);
printf("%s is%s up to date\n", name,
ce_uptodate(r->index->cache[pos]) ? "" : " not");
ce_uptodate(the_index.cache[pos]) ? "" : " not");
write_file(name, "%d\n", i);
}
if (table)
print_cache(r->index);
discard_index(r->index);
discard_cache();
}
return 0;
}

View file

@ -234,12 +234,27 @@ test_expect_success 'sparse-index enabled and disabled' '
git -C repo sparse-checkout init --cone --sparse-index &&
test_cmp_config -C repo true index.sparse &&
test-tool -C repo read-cache --table >cache &&
grep " tree " cache &&
git -C repo ls-files --sparse >sparse &&
git -C repo sparse-checkout disable &&
test-tool -C repo read-cache --table >cache &&
! grep " tree " cache &&
git -C repo ls-files --sparse >full &&
cat >expect <<-\EOF &&
@@ -1,4 +1,7 @@
a
-deep/
-folder1/
-folder2/
+deep/a
+deep/deeper1/a
+deep/deeper1/deepest/a
+deep/deeper2/a
+folder1/a
+folder2/a
EOF
diff -u sparse full | tail -n +3 >actual &&
test_cmp expect actual &&
git -C repo config --list >config &&
! grep index.sparse config
)

View file

@ -206,45 +206,42 @@ test_sparse_unstaged () {
test_expect_success 'sparse-index contents' '
init_repos &&
test-tool -C sparse-index read-cache --table >cache &&
git -C sparse-index ls-files --sparse --stage >cache &&
for dir in folder1 folder2 x
do
TREE=$(git -C sparse-index rev-parse HEAD:$dir) &&
grep "040000 tree $TREE $dir/" cache \
grep "040000 $TREE 0 $dir/" cache \
|| return 1
done &&
git -C sparse-index sparse-checkout set folder1 &&
test-tool -C sparse-index read-cache --table >cache &&
git -C sparse-index ls-files --sparse --stage >cache &&
for dir in deep folder2 x
do
TREE=$(git -C sparse-index rev-parse HEAD:$dir) &&
grep "040000 tree $TREE $dir/" cache \
grep "040000 $TREE 0 $dir/" cache \
|| return 1
done &&
git -C sparse-index sparse-checkout set deep/deeper1 &&
test-tool -C sparse-index read-cache --table >cache &&
git -C sparse-index ls-files --sparse --stage >cache &&
for dir in deep/deeper2 folder1 folder2 x
do
TREE=$(git -C sparse-index rev-parse HEAD:$dir) &&
grep "040000 tree $TREE $dir/" cache \
grep "040000 $TREE 0 $dir/" cache \
|| return 1
done &&
# Disabling the sparse-index removes tree entries with full ones
# Disabling the sparse-index replaces tree entries with full ones
git -C sparse-index sparse-checkout init --no-sparse-index &&
test-tool -C sparse-index read-cache --table >cache &&
! grep "040000 tree" cache &&
test_sparse_match test-tool read-cache --table
test_sparse_match git ls-files --stage --sparse
'
test_expect_success 'expanded in-memory index matches full index' '
init_repos &&
test_sparse_match test-tool read-cache --expand --table
test_sparse_match git ls-files --stage
'
test_expect_success 'status with options' '
@ -801,9 +798,9 @@ test_expect_success 'submodule handling' '
# having a submodule prevents "modules" from collapse
test_sparse_match git sparse-checkout set deep/deeper1 &&
test-tool -C sparse-index read-cache --table >cache &&
grep "100644 blob .* modules/a" cache &&
grep "160000 commit $(git -C initial-repo rev-parse HEAD) modules/sub" cache
git -C sparse-index ls-files --sparse --stage >cache &&
grep "100644 .* modules/a" cache &&
grep "160000 $(git -C initial-repo rev-parse HEAD) 0 modules/sub" cache
'
# When working with a sparse index, some commands will need to expand the
@ -816,6 +813,12 @@ test_expect_success 'sparse-index is expanded and converted back' '
GIT_TRACE2_EVENT="$(pwd)/trace2.txt" \
git -C sparse-index reset -- folder1/a &&
test_region index convert_to_sparse trace2.txt &&
test_region index ensure_full_index trace2.txt &&
# ls-files expands on read, but does not write.
rm trace2.txt &&
GIT_TRACE2_EVENT="$(pwd)/trace2.txt" GIT_TRACE2_EVENT_NESTING=10 \
git -C sparse-index ls-files &&
test_region index ensure_full_index trace2.txt
'
@ -871,6 +874,7 @@ test_expect_success 'sparse-index is not expanded' '
init_repos &&
ensure_not_expanded status &&
ensure_not_expanded ls-files --sparse &&
ensure_not_expanded commit --allow-empty -m empty &&
echo >>sparse-index/a &&
ensure_not_expanded commit -a -m a &&
@ -1009,6 +1013,100 @@ test_expect_success 'sparse index is not expanded: blame' '
done
'
test_expect_success 'sparse index is not expanded: fetch/pull' '
init_repos &&
git -C sparse-index remote add full "file://$(pwd)/full-checkout" &&
ensure_not_expanded fetch full &&
git -C full-checkout commit --allow-empty -m "for pull merge" &&
git -C sparse-index commit --allow-empty -m "for pull merge" &&
ensure_not_expanded pull full base
'
test_expect_success 'ls-files' '
init_repos &&
# Use a smaller sparse-checkout for reduced output
test_sparse_match git sparse-checkout set &&
# Behavior agrees by default. Sparse index is expanded.
test_all_match git ls-files &&
# With --sparse, the sparse index data changes behavior.
git -C sparse-index ls-files --sparse >actual &&
cat >expect <<-\EOF &&
a
deep/
e
folder1-
folder1.x
folder1/
folder10
folder2/
g
x/
z
EOF
test_cmp expect actual &&
# With --sparse and no sparse index, nothing changes.
git -C sparse-checkout ls-files >dense &&
git -C sparse-checkout ls-files --sparse >sparse &&
test_cmp dense sparse &&
# Set up a strange condition of having a file edit
# outside of the sparse-checkout cone. This is just
# to verify that sparse-checkout and sparse-index
# behave the same in this case.
write_script edit-content <<-\EOF &&
mkdir folder1 &&
echo content >>folder1/a
EOF
run_on_sparse ../edit-content &&
# ls-files does not currently notice modified files whose
# cache entries are marked SKIP_WORKTREE. This may change
# in the future, but here we test that sparse index does
# not accidentally create a change of behavior.
test_sparse_match git ls-files --modified &&
test_must_be_empty sparse-checkout-out &&
test_must_be_empty sparse-index-out &&
git -C sparse-index ls-files --sparse --modified >sparse-index-out &&
test_must_be_empty sparse-index-out &&
# Add folder1 to the sparse-checkout cone and
# check that ls-files shows the expanded files.
test_sparse_match git sparse-checkout add folder1 &&
test_sparse_match git ls-files --modified &&
test_all_match git ls-files &&
git -C sparse-index ls-files --sparse >actual &&
cat >expect <<-\EOF &&
a
deep/
e
folder1-
folder1.x
folder1/0/0/0
folder1/0/1
folder1/a
folder10
folder2/
g
x/
z
EOF
test_cmp expect actual &&
# Double-check index expansion is avoided
ensure_not_expanded ls-files --sparse
'
# NEEDSWORK: a sparse-checkout behaves differently from a full checkout
# in this scenario, but it shouldn't.
test_expect_success 'reset mixed and checkout orphan' '
@ -1024,13 +1122,13 @@ test_expect_success 'reset mixed and checkout orphan' '
# the sparse checkouts skip "adding" the other side of
# the conflict.
test_sparse_match git reset --mixed HEAD~1 &&
test_sparse_match test-tool read-cache --table --expand &&
test_sparse_match git ls-files --stage &&
test_sparse_match git status --porcelain=v2 &&
# At this point, sparse-checkouts behave differently
# from the full-checkout.
test_sparse_match git checkout --orphan new-branch &&
test_sparse_match test-tool read-cache --table --expand &&
test_sparse_match git ls-files --stage &&
test_sparse_match git status --porcelain=v2
'

View file

@ -181,13 +181,13 @@ test_expect_success 'git add fails outside of sparse-checkout definition' '
# Avoid munging CRLFs to avoid an error message
git -c core.autocrlf=input add --sparse sparse_entry 2>stderr &&
test_must_be_empty stderr &&
test-tool read-cache --table >actual &&
grep "^100644 blob.*sparse_entry\$" actual &&
git ls-files --stage >actual &&
grep "^100644 .*sparse_entry\$" actual &&
git add --sparse --chmod=+x sparse_entry 2>stderr &&
test_must_be_empty stderr &&
test-tool read-cache --table >actual &&
grep "^100755 blob.*sparse_entry\$" actual &&
git ls-files --stage >actual &&
grep "^100755 .*sparse_entry\$" actual &&
git reset &&