sparse-checkout: create builtin with 'list' subcommand
The sparse-checkout feature is mostly hidden to users, as its only documentation is supplementary information in the docs for 'git read-tree'. In addition, users need to know how to edit the .git/info/sparse-checkout file with the right patterns, then run the appropriate 'git read-tree -mu HEAD' command. Keeping the working directory in sync with the sparse-checkout file requires care. Begin an effort to make the sparse-checkout feature a porcelain feature by creating a new 'git sparse-checkout' builtin. This builtin will be the preferred mechanism for manipulating the sparse-checkout file and syncing the working directory. The documentation provided is adapted from the "git read-tree" documentation with a few edits for clarity in the new context. Extra sections are added to hint toward a future change to a more restricted pattern set. Helped-by: Elijah Newren <newren@gmail.com> Signed-off-by: Derrick Stolee <dstolee@microsoft.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
parent
d9f6f3b619
commit
94c0956b60
1
.gitignore
vendored
1
.gitignore
vendored
@ -158,6 +158,7 @@
|
||||
/git-show-branch
|
||||
/git-show-index
|
||||
/git-show-ref
|
||||
/git-sparse-checkout
|
||||
/git-stage
|
||||
/git-stash
|
||||
/git-status
|
||||
|
@ -436,7 +436,7 @@ support.
|
||||
SEE ALSO
|
||||
--------
|
||||
linkgit:git-write-tree[1]; linkgit:git-ls-files[1];
|
||||
linkgit:gitignore[5]
|
||||
linkgit:gitignore[5]; linkgit:git-sparse-checkout[1];
|
||||
|
||||
GIT
|
||||
---
|
||||
|
89
Documentation/git-sparse-checkout.txt
Normal file
89
Documentation/git-sparse-checkout.txt
Normal file
@ -0,0 +1,89 @@
|
||||
git-sparse-checkout(1)
|
||||
======================
|
||||
|
||||
NAME
|
||||
----
|
||||
git-sparse-checkout - Initialize and modify the sparse-checkout
|
||||
configuration, which reduces the checkout to a set of paths
|
||||
given by a list of atterns.
|
||||
|
||||
|
||||
SYNOPSIS
|
||||
--------
|
||||
[verse]
|
||||
'git sparse-checkout <subcommand> [options]'
|
||||
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
|
||||
Initialize and modify the sparse-checkout configuration, which reduces
|
||||
the checkout to a set of paths given by a list of patterns.
|
||||
|
||||
THIS COMMAND IS EXPERIMENTAL. ITS BEHAVIOR, AND THE BEHAVIOR OF OTHER
|
||||
COMMANDS IN THE PRESENCE OF SPARSE-CHECKOUTS, WILL LIKELY CHANGE IN
|
||||
THE FUTURE.
|
||||
|
||||
|
||||
COMMANDS
|
||||
--------
|
||||
'list'::
|
||||
Provide a list of the contents in the sparse-checkout file.
|
||||
|
||||
|
||||
SPARSE CHECKOUT
|
||||
---------------
|
||||
|
||||
"Sparse checkout" allows populating the working directory sparsely.
|
||||
It uses the skip-worktree bit (see linkgit:git-update-index[1]) to tell
|
||||
Git whether a file in the working directory is worth looking at. If
|
||||
the skip-worktree bit is set, then the file is ignored in the working
|
||||
directory. Git will not populate the contents of those files, which
|
||||
makes a sparse checkout helpful when working in a repository with many
|
||||
files, but only a few are important to the current user.
|
||||
|
||||
The `$GIT_DIR/info/sparse-checkout` file is used to define the
|
||||
skip-worktree reference bitmap. When Git updates the working
|
||||
directory, it updates the skip-worktree bits in the index based
|
||||
on this file. The files matching the patterns in the file will
|
||||
appear in the working directory, and the rest will not.
|
||||
|
||||
## FULL PATTERN SET
|
||||
|
||||
By default, the sparse-checkout file uses the same syntax as `.gitignore`
|
||||
files.
|
||||
|
||||
While `$GIT_DIR/info/sparse-checkout` is usually used to specify what
|
||||
files are included, you can also specify what files are _not_ included,
|
||||
using negative patterns. For example, to remove the file `unwanted`:
|
||||
|
||||
----------------
|
||||
/*
|
||||
!unwanted
|
||||
----------------
|
||||
|
||||
Another tricky thing is fully repopulating the working directory when you
|
||||
no longer want sparse checkout. You cannot just disable "sparse
|
||||
checkout" because skip-worktree bits are still in the index and your working
|
||||
directory is still sparsely populated. You should re-populate the working
|
||||
directory with the `$GIT_DIR/info/sparse-checkout` file content as
|
||||
follows:
|
||||
|
||||
----------------
|
||||
/*
|
||||
----------------
|
||||
|
||||
Then you can disable sparse checkout. Sparse checkout support in 'git
|
||||
checkout' and similar commands is disabled by default. You need to
|
||||
set `core.sparseCheckout` to `true` in order to have sparse checkout
|
||||
support.
|
||||
|
||||
SEE ALSO
|
||||
--------
|
||||
|
||||
linkgit:git-read-tree[1]
|
||||
linkgit:gitignore[5]
|
||||
|
||||
GIT
|
||||
---
|
||||
Part of the linkgit:git[1] suite
|
1
Makefile
1
Makefile
@ -1125,6 +1125,7 @@ BUILTIN_OBJS += builtin/shortlog.o
|
||||
BUILTIN_OBJS += builtin/show-branch.o
|
||||
BUILTIN_OBJS += builtin/show-index.o
|
||||
BUILTIN_OBJS += builtin/show-ref.o
|
||||
BUILTIN_OBJS += builtin/sparse-checkout.o
|
||||
BUILTIN_OBJS += builtin/stash.o
|
||||
BUILTIN_OBJS += builtin/stripspace.o
|
||||
BUILTIN_OBJS += builtin/submodule--helper.o
|
||||
|
@ -225,6 +225,7 @@ int cmd_shortlog(int argc, const char **argv, const char *prefix);
|
||||
int cmd_show(int argc, const char **argv, const char *prefix);
|
||||
int cmd_show_branch(int argc, const char **argv, const char *prefix);
|
||||
int cmd_show_index(int argc, const char **argv, const char *prefix);
|
||||
int cmd_sparse_checkout(int argc, const char **argv, const char *prefix);
|
||||
int cmd_status(int argc, const char **argv, const char *prefix);
|
||||
int cmd_stash(int argc, const char **argv, const char *prefix);
|
||||
int cmd_stripspace(int argc, const char **argv, const char *prefix);
|
||||
|
86
builtin/sparse-checkout.c
Normal file
86
builtin/sparse-checkout.c
Normal file
@ -0,0 +1,86 @@
|
||||
#include "builtin.h"
|
||||
#include "config.h"
|
||||
#include "dir.h"
|
||||
#include "parse-options.h"
|
||||
#include "pathspec.h"
|
||||
#include "repository.h"
|
||||
#include "run-command.h"
|
||||
#include "strbuf.h"
|
||||
|
||||
static char const * const builtin_sparse_checkout_usage[] = {
|
||||
N_("git sparse-checkout list"),
|
||||
NULL
|
||||
};
|
||||
|
||||
static char *get_sparse_checkout_filename(void)
|
||||
{
|
||||
return git_pathdup("info/sparse-checkout");
|
||||
}
|
||||
|
||||
static void write_patterns_to_file(FILE *fp, struct pattern_list *pl)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < pl->nr; i++) {
|
||||
struct path_pattern *p = pl->patterns[i];
|
||||
|
||||
if (p->flags & PATTERN_FLAG_NEGATIVE)
|
||||
fprintf(fp, "!");
|
||||
|
||||
fprintf(fp, "%s", p->pattern);
|
||||
|
||||
if (p->flags & PATTERN_FLAG_MUSTBEDIR)
|
||||
fprintf(fp, "/");
|
||||
|
||||
fprintf(fp, "\n");
|
||||
}
|
||||
}
|
||||
|
||||
static int sparse_checkout_list(int argc, const char **argv)
|
||||
{
|
||||
struct pattern_list pl;
|
||||
char *sparse_filename;
|
||||
int res;
|
||||
|
||||
memset(&pl, 0, sizeof(pl));
|
||||
|
||||
sparse_filename = get_sparse_checkout_filename();
|
||||
res = add_patterns_from_file_to_list(sparse_filename, "", 0, &pl, NULL);
|
||||
free(sparse_filename);
|
||||
|
||||
if (res < 0) {
|
||||
warning(_("this worktree is not sparse (sparse-checkout file may not exist)"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
write_patterns_to_file(stdout, &pl);
|
||||
clear_pattern_list(&pl);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cmd_sparse_checkout(int argc, const char **argv, const char *prefix)
|
||||
{
|
||||
static struct option builtin_sparse_checkout_options[] = {
|
||||
OPT_END(),
|
||||
};
|
||||
|
||||
if (argc == 2 && !strcmp(argv[1], "-h"))
|
||||
usage_with_options(builtin_sparse_checkout_usage,
|
||||
builtin_sparse_checkout_options);
|
||||
|
||||
argc = parse_options(argc, argv, prefix,
|
||||
builtin_sparse_checkout_options,
|
||||
builtin_sparse_checkout_usage,
|
||||
PARSE_OPT_STOP_AT_NON_OPTION);
|
||||
|
||||
git_config(git_default_config, NULL);
|
||||
|
||||
if (argc > 0) {
|
||||
if (!strcmp(argv[0], "list"))
|
||||
return sparse_checkout_list(argc, argv);
|
||||
}
|
||||
|
||||
usage_with_options(builtin_sparse_checkout_usage,
|
||||
builtin_sparse_checkout_options);
|
||||
}
|
@ -166,6 +166,7 @@ git-show-index plumbinginterrogators
|
||||
git-show-ref plumbinginterrogators
|
||||
git-sh-i18n purehelpers
|
||||
git-sh-setup purehelpers
|
||||
git-sparse-checkout mainporcelain worktree
|
||||
git-stash mainporcelain
|
||||
git-stage complete
|
||||
git-status mainporcelain info
|
||||
|
1
git.c
1
git.c
@ -572,6 +572,7 @@ static struct cmd_struct commands[] = {
|
||||
{ "show-branch", cmd_show_branch, RUN_SETUP },
|
||||
{ "show-index", cmd_show_index },
|
||||
{ "show-ref", cmd_show_ref, RUN_SETUP },
|
||||
{ "sparse-checkout", cmd_sparse_checkout, RUN_SETUP | NEED_WORK_TREE },
|
||||
{ "stage", cmd_add, RUN_SETUP | NEED_WORK_TREE },
|
||||
/*
|
||||
* NEEDSWORK: Until the builtin stash is thoroughly robust and no
|
||||
|
45
t/t1091-sparse-checkout-builtin.sh
Executable file
45
t/t1091-sparse-checkout-builtin.sh
Executable file
@ -0,0 +1,45 @@
|
||||
#!/bin/sh
|
||||
|
||||
test_description='sparse checkout builtin tests'
|
||||
|
||||
. ./test-lib.sh
|
||||
|
||||
test_expect_success 'setup' '
|
||||
git init repo &&
|
||||
(
|
||||
cd repo &&
|
||||
echo "initial" >a &&
|
||||
mkdir folder1 folder2 deep &&
|
||||
mkdir deep/deeper1 deep/deeper2 &&
|
||||
mkdir deep/deeper1/deepest &&
|
||||
cp a folder1 &&
|
||||
cp a folder2 &&
|
||||
cp a deep &&
|
||||
cp a deep/deeper1 &&
|
||||
cp a deep/deeper2 &&
|
||||
cp a deep/deeper1/deepest &&
|
||||
git add . &&
|
||||
git commit -m "initial commit"
|
||||
)
|
||||
'
|
||||
|
||||
test_expect_success 'git sparse-checkout list (empty)' '
|
||||
git -C repo sparse-checkout list >list 2>err &&
|
||||
test_must_be_empty list &&
|
||||
test_i18ngrep "this worktree is not sparse (sparse-checkout file may not exist)" err
|
||||
'
|
||||
|
||||
test_expect_success 'git sparse-checkout list (populated)' '
|
||||
test_when_finished rm -f repo/.git/info/sparse-checkout &&
|
||||
cat >repo/.git/info/sparse-checkout <<-EOF &&
|
||||
/folder1/*
|
||||
/deep/
|
||||
**/a
|
||||
!*bin*
|
||||
EOF
|
||||
cp repo/.git/info/sparse-checkout expect &&
|
||||
git -C repo sparse-checkout list >list &&
|
||||
test_cmp expect list
|
||||
'
|
||||
|
||||
test_done
|
Loading…
Reference in New Issue
Block a user