git/builtin/diff-index.c
Derrick Stolee b44c926c9f diff-index: integrate with the sparse index
The sparse index allows focusing the index data structure on the files
present in the sparse-checkout, leaving only tree entries for
directories not within the sparse-checkout. Each builtin needs a
repository setting to indicate that it has been tested with the sparse
index before Git will allow the index to be loaded into memory in its
sparse form. This is a safety precaution.

There are still some builtins that haven't been integrated due to the
complexity of the integration and the lack of significant use. However,
'git diff-index' was neglected only because of initial data showing low
usage. The diff machinery was already integrated and there is no more
work to be done there but add some tests to be sure 'git diff-index'
behaves as expected.

For this purpose, we can follow the testing pattern used in 51ba65b5c3
(diff: enable and test the sparse index, 2021-12-06). One difference
here is that we only verify that the sparse index case agrees with the
full index case, but do not generate the expected output. The 'git diff'
tests use the '--name-status' option to ease the creation of the
expected output, but that's not an option for 'diff-index'. Since the
underlying diff machinery is the same, a simple comparison is sufficient
to give some coverage.

Signed-off-by: Derrick Stolee <stolee@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-08-22 09:29:14 -07:00

82 lines
2.1 KiB
C

#include "builtin.h"
#include "config.h"
#include "diff.h"
#include "diff-merges.h"
#include "commit.h"
#include "preload-index.h"
#include "repository.h"
#include "revision.h"
#include "setup.h"
static const char diff_cache_usage[] =
"git diff-index [-m] [--cached] [--merge-base] "
"[<common-diff-options>] <tree-ish> [<path>...]"
"\n"
COMMON_DIFF_OPTIONS_HELP;
int cmd_diff_index(int argc, const char **argv, const char *prefix)
{
struct rev_info rev;
unsigned int option = 0;
int i;
int result;
if (argc == 2 && !strcmp(argv[1], "-h"))
usage(diff_cache_usage);
git_config(git_diff_basic_config, NULL); /* no "diff" UI options */
prepare_repo_settings(the_repository);
the_repository->settings.command_requires_full_index = 0;
repo_init_revisions(the_repository, &rev, prefix);
rev.abbrev = 0;
prefix = precompose_argv_prefix(argc, argv, prefix);
/*
* We need (some of) diff for merges options (e.g., --cc), and we need
* to avoid conflict with our own meaning of "-m".
*/
diff_merges_suppress_m_parsing();
argc = setup_revisions(argc, argv, &rev, NULL);
for (i = 1; i < argc; i++) {
const char *arg = argv[i];
if (!strcmp(arg, "--cached"))
option |= DIFF_INDEX_CACHED;
else if (!strcmp(arg, "--merge-base"))
option |= DIFF_INDEX_MERGE_BASE;
else if (!strcmp(arg, "-m"))
rev.match_missing = 1;
else
usage(diff_cache_usage);
}
if (!rev.diffopt.output_format)
rev.diffopt.output_format = DIFF_FORMAT_RAW;
rev.diffopt.rotate_to_strict = 1;
/*
* Make sure there is one revision (i.e. pending object),
* and there is no revision filtering parameters.
*/
if (rev.pending.nr != 1 ||
rev.max_count != -1 || rev.min_age != -1 || rev.max_age != -1)
usage(diff_cache_usage);
if (!(option & DIFF_INDEX_CACHED)) {
setup_work_tree();
if (repo_read_index_preload(the_repository, &rev.diffopt.pathspec, 0) < 0) {
perror("repo_read_index_preload");
return -1;
}
} else if (repo_read_index(the_repository) < 0) {
perror("repo_read_index");
return -1;
}
run_diff_index(&rev, option);
result = diff_result_code(&rev.diffopt);
release_revisions(&rev);
return result;
}