sparse-checkout: 'set' subcommand

The 'git sparse-checkout set' subcommand takes a list of patterns
as arguments and writes them to the sparse-checkout file. Then, it
updates the working directory using 'git read-tree -mu HEAD'.

The 'set' subcommand will replace the entire contents of the
sparse-checkout file. The write_patterns_and_update() method is
extracted from cmd_sparse_checkout() to make it easier to implement
'add' and/or 'remove' subcommands in the future.

If the core.sparseCheckout config setting is disabled, then enable
the config setting in the worktree config. If we set the config
this way and the sparse-checkout fails, then re-disable the config
setting.

Signed-off-by: Derrick Stolee <dstolee@microsoft.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Derrick Stolee 2019-11-21 22:04:36 +00:00 committed by Junio C Hamano
parent d89f09c828
commit f6039a9423
3 changed files with 84 additions and 2 deletions

View File

@ -42,6 +42,12 @@ To avoid interfering with other worktrees, it first enables the
`extensions.worktreeConfig` setting and makes sure to set the `extensions.worktreeConfig` setting and makes sure to set the
`core.sparseCheckout` setting in the worktree-specific config file. `core.sparseCheckout` setting in the worktree-specific config file.
'set'::
Write a set of patterns to the sparse-checkout file, as given as
a list of arguments following the 'set' subcommand. Update the
working directory to match the new patterns. Enable the
core.sparseCheckout config setting if it is not already enabled.
SPARSE CHECKOUT SPARSE CHECKOUT
--------------- ---------------

View File

@ -8,7 +8,7 @@
#include "strbuf.h" #include "strbuf.h"
static char const * const builtin_sparse_checkout_usage[] = { static char const * const builtin_sparse_checkout_usage[] = {
N_("git sparse-checkout (init|list)"), N_("git sparse-checkout (init|list|set) <options>"),
NULL NULL
}; };
@ -66,7 +66,7 @@ static int update_working_directory(void)
argv_array_pushl(&argv, "read-tree", "-m", "-u", "HEAD", NULL); argv_array_pushl(&argv, "read-tree", "-m", "-u", "HEAD", NULL);
if (run_command_v_opt(argv.argv, RUN_GIT_CMD)) { if (run_command_v_opt(argv.argv, RUN_GIT_CMD)) {
error(_("failed to update index with new sparse-checkout paths")); error(_("failed to update index with new sparse-checkout patterns"));
result = 1; result = 1;
} }
@ -136,6 +136,47 @@ reset_dir:
return update_working_directory(); return update_working_directory();
} }
static int write_patterns_and_update(struct pattern_list *pl)
{
char *sparse_filename;
FILE *fp;
sparse_filename = get_sparse_checkout_filename();
fp = fopen(sparse_filename, "w");
write_patterns_to_file(fp, pl);
fclose(fp);
free(sparse_filename);
return update_working_directory();
}
static int sparse_checkout_set(int argc, const char **argv, const char *prefix)
{
static const char *empty_base = "";
int i;
struct pattern_list pl;
int result;
int changed_config = 0;
memset(&pl, 0, sizeof(pl));
for (i = 1; i < argc; i++)
add_pattern(argv[i], empty_base, 0, &pl, 0);
if (!core_apply_sparse_checkout) {
set_config(MODE_ALL_PATTERNS);
core_apply_sparse_checkout = 1;
changed_config = 1;
}
result = write_patterns_and_update(&pl);
if (result && changed_config)
set_config(MODE_NO_PATTERNS);
clear_pattern_list(&pl);
return result;
}
int cmd_sparse_checkout(int argc, const char **argv, const char *prefix) int cmd_sparse_checkout(int argc, const char **argv, const char *prefix)
{ {
static struct option builtin_sparse_checkout_options[] = { static struct option builtin_sparse_checkout_options[] = {
@ -158,6 +199,8 @@ int cmd_sparse_checkout(int argc, const char **argv, const char *prefix)
return sparse_checkout_list(argc, argv); return sparse_checkout_list(argc, argv);
if (!strcmp(argv[0], "init")) if (!strcmp(argv[0], "init"))
return sparse_checkout_init(argc, argv); return sparse_checkout_init(argc, argv);
if (!strcmp(argv[0], "set"))
return sparse_checkout_set(argc, argv, prefix);
} }
usage_with_options(builtin_sparse_checkout_usage, usage_with_options(builtin_sparse_checkout_usage,

View File

@ -95,4 +95,37 @@ test_expect_success 'clone --sparse' '
test_cmp expect dir test_cmp expect dir
' '
test_expect_success 'set enables config' '
git init empty-config &&
(
cd empty-config &&
test_commit test file &&
test_path_is_missing .git/config.worktree &&
test_must_fail git sparse-checkout set nothing &&
test_path_is_file .git/config.worktree &&
test_must_fail git config core.sparseCheckout &&
git sparse-checkout set "/*" &&
test_cmp_config true core.sparseCheckout
)
'
test_expect_success 'set sparse-checkout using builtin' '
git -C repo sparse-checkout set "/*" "!/*/" "*folder*" &&
cat >expect <<-EOF &&
/*
!/*/
*folder*
EOF
git -C repo sparse-checkout list >actual &&
test_cmp expect actual &&
test_cmp expect repo/.git/info/sparse-checkout &&
ls repo >dir &&
cat >expect <<-EOF &&
a
folder1
folder2
EOF
test_cmp expect dir
'
test_done test_done