Sparse clones will be created by specifying rev-list args to clone in order to limit what is downloaded. In order to avoid accessing unavailable objects, these limiting rev-list args are recorded in $GIT_DIR/sparse-limit so that other operations can make use of them. Signed-off-by: Elijah Newren <newren@xxxxxxxxx> --- Makefile | 2 + cache.h | 3 ++ environment.c | 2 + setup.c | 2 + sparse-repo.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ sparse-repo.h | 3 ++ tree-diff.c | 2 + 7 files changed, 78 insertions(+), 0 deletions(-) create mode 100644 sparse-repo.c create mode 100644 sparse-repo.h diff --git a/Makefile b/Makefile index d3db459..ba4b9bf 100644 --- a/Makefile +++ b/Makefile @@ -548,6 +548,7 @@ LIB_H += run-command.h LIB_H += sha1-lookup.h LIB_H += sideband.h LIB_H += sigchain.h +LIB_H += sparse-repo.h LIB_H += strbuf.h LIB_H += string-list.h LIB_H += submodule.h @@ -657,6 +658,7 @@ LIB_OBJS += sha1_name.o LIB_OBJS += shallow.o LIB_OBJS += sideband.o LIB_OBJS += sigchain.o +LIB_OBJS += sparse-repo.o LIB_OBJS += strbuf.o LIB_OBJS += string-list.o LIB_OBJS += submodule.o diff --git a/cache.h b/cache.h index ce7bdd1..6f88dbb 100644 --- a/cache.h +++ b/cache.h @@ -403,6 +403,9 @@ extern const char *const local_repo_env[LOCAL_REPO_ENV_SIZE + 1]; extern int is_bare_repository_cfg; extern int is_bare_repository(void); extern int is_inside_git_dir(void); +extern const char **git_sparse_limits; +extern const char **git_sparse_pathspecs; +extern struct diff_options git_sparse_diffopts; extern char *git_work_tree_cfg; extern int is_inside_work_tree(void); extern int have_git_dir(void); diff --git a/environment.c b/environment.c index cc097b7..fc9d21d 100644 --- a/environment.c +++ b/environment.c @@ -61,6 +61,8 @@ struct startup_info *startup_info; int core_preload_index = 0; /* This is set by setup_git_dir_gently() and/or git_default_config() */ +const char **git_sparse_limits = NULL; +const char **git_sparse_pathspecs = NULL; char *git_work_tree_cfg; static char *work_tree; diff --git a/setup.c b/setup.c index a3b76de..92f4385 100644 --- a/setup.c +++ b/setup.c @@ -1,5 +1,6 @@ #include "cache.h" #include "dir.h" +#include "sparse-repo.h" static int inside_git_dir = -1; static int inside_work_tree = -1; @@ -256,6 +257,7 @@ static int check_repository_format_gently(int *nongit_ok) *nongit_ok = -1; return -1; } + check_sparse_repo(); return 0; } diff --git a/sparse-repo.c b/sparse-repo.c new file mode 100644 index 0000000..18ea976 --- /dev/null +++ b/sparse-repo.c @@ -0,0 +1,64 @@ +#include "sparse-repo.h" +#include "cache.h" +#include "diff.h" +#include "quote.h" + +#define SPARSE_FILE "sparse-limits" + +void register_sparse_limits(const char **revlist_argv) +{ + if (revlist_argv != git_sparse_limits) { + free(git_sparse_limits); + git_sparse_limits = revlist_argv; + } + + git_sparse_pathspecs = git_sparse_limits; + for (; *git_sparse_pathspecs; git_sparse_pathspecs++) + /* + * Sparse limiting args must always have a double dash before + * any paths, since users will likely fetch/pull from bare + * repositories. That makes it easy to find the pathspec + * portion of the sparse limits. + */ + if (strcmp(*git_sparse_pathspecs, "--") == 0) { + /* + * Make git_sparse_limits provide quick access + * to non-pathspec rev-list arguments, and + * git_sparse_pathspec provide access to the + * rest. + */ + *git_sparse_pathspecs = NULL; + git_sparse_pathspecs++; + break; + } + diff_tree_setup_paths(git_sparse_pathspecs, &git_sparse_diffopts); +} + +void register_quoted_sparse_limits(char *quoted_argv) +{ + int nr = 0, alloc = 0; + + sq_dequote_to_argv(strdup(quoted_argv), &git_sparse_limits, &nr, &alloc); + ALLOC_GROW(git_sparse_limits, nr+1, alloc); + git_sparse_limits[nr] = NULL; + + register_sparse_limits(git_sparse_limits); +} + +void check_sparse_repo(void) +{ + struct stat statbuf; + struct strbuf buffer = STRBUF_INIT; + + char *sparse_file = git_path(SPARSE_FILE); + if (stat(sparse_file, &statbuf)) + return; + + if (git_sparse_limits) + die("tried to initialize sparse limits twice!\n"); + + if (strbuf_read_file(&buffer, sparse_file, statbuf.st_size) < 0) + die_errno("could not read %s", sparse_file); + register_quoted_sparse_limits(buffer.buf); + strbuf_release(&buffer); +} diff --git a/sparse-repo.h b/sparse-repo.h new file mode 100644 index 0000000..ed9018a --- /dev/null +++ b/sparse-repo.h @@ -0,0 +1,3 @@ +void register_sparse_limits(const char **revlist_argv); +void register_quoted_sparse_limits(char *quoted_argv); +void check_sparse_repo(void); diff --git a/tree-diff.c b/tree-diff.c index d976bdf..951b53b 100644 --- a/tree-diff.c +++ b/tree-diff.c @@ -6,6 +6,8 @@ #include "diffcore.h" #include "tree.h" +struct diff_options git_sparse_diffopts; + static char *malloc_base(const char *base, int baselen, const char *path, int pathlen) { char *newbase = xmalloc(baselen + pathlen + 2); -- 1.7.2.2.140.gd06af -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html