1 #define USE_THE_REPOSITORY_VARIABLE
2 #define DISABLE_SIGN_COMPARE_WARNINGS
7 #include "environment.h"
9 #include "object-file.h"
10 #include "object-name.h"
11 #include "parse-options.h"
15 #include "string-list.h"
17 #include "unpack-trees.h"
20 #include "sparse-index.h"
23 static const char *empty_base
= "";
25 static char const * const builtin_sparse_checkout_usage
[] = {
26 N_("git sparse-checkout (init | list | set | add | reapply | disable | check-rules) [<options>]"),
30 static void write_patterns_to_file(FILE *fp
, struct pattern_list
*pl
)
34 for (i
= 0; i
< pl
->nr
; i
++) {
35 struct path_pattern
*p
= pl
->patterns
[i
];
37 if (p
->flags
& PATTERN_FLAG_NEGATIVE
)
40 fprintf(fp
, "%s", p
->pattern
);
42 if (p
->flags
& PATTERN_FLAG_MUSTBEDIR
)
49 static char const * const builtin_sparse_checkout_list_usage
[] = {
50 "git sparse-checkout list",
54 static int sparse_checkout_list(int argc
, const char **argv
, const char *prefix
,
55 struct repository
*repo UNUSED
)
57 static struct option builtin_sparse_checkout_list_options
[] = {
60 struct pattern_list pl
;
61 char *sparse_filename
;
65 if (!core_apply_sparse_checkout
)
66 die(_("this worktree is not sparse"));
68 argc
= parse_options(argc
, argv
, prefix
,
69 builtin_sparse_checkout_list_options
,
70 builtin_sparse_checkout_list_usage
, 0);
72 memset(&pl
, 0, sizeof(pl
));
74 pl
.use_cone_patterns
= core_sparse_checkout_cone
;
76 sparse_filename
= get_sparse_checkout_filename();
77 res
= add_patterns_from_file_to_list(sparse_filename
, "", 0, &pl
, NULL
, 0);
78 free(sparse_filename
);
81 warning(_("this worktree is not sparse (sparse-checkout file may not exist)"));
85 if (pl
.use_cone_patterns
) {
87 struct pattern_entry
*pe
;
88 struct hashmap_iter iter
;
89 struct string_list sl
= STRING_LIST_INIT_DUP
;
91 hashmap_for_each_entry(&pl
.recursive_hashmap
, &iter
, pe
, ent
) {
92 /* pe->pattern starts with "/", skip it */
93 string_list_insert(&sl
, pe
->pattern
+ 1);
96 string_list_sort(&sl
);
98 for (i
= 0; i
< sl
.nr
; i
++) {
99 quote_c_style(sl
.items
[i
].string
, NULL
, stdout
, 0);
103 string_list_clear(&sl
, 0);
105 write_patterns_to_file(stdout
, &pl
);
108 clear_pattern_list(&pl
);
113 static void clean_tracked_sparse_directories(struct repository
*r
)
116 struct strbuf path
= STRBUF_INIT
;
118 struct string_list_item
*item
;
119 struct string_list sparse_dirs
= STRING_LIST_INIT_DUP
;
122 * If we are not using cone mode patterns, then we cannot
123 * delete directories outside of the sparse cone.
125 if (!r
|| !r
->index
|| !r
->worktree
)
127 if (init_sparse_checkout_patterns(r
->index
) ||
128 !r
->index
->sparse_checkout_patterns
->use_cone_patterns
)
132 * Use the sparse index as a data structure to assist finding
133 * directories that are safe to delete. This conversion to a
134 * sparse index will not delete directories that contain
135 * conflicted entries or submodules.
137 if (r
->index
->sparse_index
== INDEX_EXPANDED
) {
139 * If something, such as a merge conflict or other concern,
140 * prevents us from converting to a sparse index, then do
141 * not try deleting files.
143 if (convert_to_sparse(r
->index
, SPARSE_INDEX_MEMORY_ONLY
))
148 strbuf_addstr(&path
, r
->worktree
);
149 strbuf_complete(&path
, '/');
153 * Collect directories that have gone out of scope but also
154 * exist on disk, so there is some work to be done. We need to
155 * store the entries in a list before exploring, since that might
156 * expand the sparse-index again.
158 for (i
= 0; i
< r
->index
->cache_nr
; i
++) {
159 struct cache_entry
*ce
= r
->index
->cache
[i
];
161 if (S_ISSPARSEDIR(ce
->ce_mode
) &&
162 repo_file_exists(r
, ce
->name
))
163 string_list_append(&sparse_dirs
, ce
->name
);
166 for_each_string_list_item(item
, &sparse_dirs
) {
167 struct dir_struct dir
= DIR_INIT
;
168 struct pathspec p
= { 0 };
169 struct strvec s
= STRVEC_INIT
;
171 strbuf_setlen(&path
, pathlen
);
172 strbuf_addstr(&path
, item
->string
);
174 dir
.flags
|= DIR_SHOW_IGNORED_TOO
;
176 setup_standard_excludes(&dir
);
177 strvec_push(&s
, path
.buf
);
179 parse_pathspec(&p
, PATHSPEC_GLOB
, 0, NULL
, s
.v
);
180 fill_directory(&dir
, r
->index
, &p
);
183 warning(_("directory '%s' contains untracked files,"
184 " but is not in the sparse-checkout cone"),
186 } else if (remove_dir_recursively(&path
, 0)) {
188 * Removal is "best effort". If something blocks
189 * the deletion, then continue with a warning.
191 warning(_("failed to remove directory '%s'"),
200 string_list_clear(&sparse_dirs
, 0);
201 strbuf_release(&path
);
204 ensure_full_index(r
->index
);
207 static int update_working_directory(struct pattern_list
*pl
)
209 enum update_sparsity_result result
;
210 struct unpack_trees_options o
;
211 struct lock_file lock_file
= LOCK_INIT
;
212 struct repository
*r
= the_repository
;
213 struct pattern_list
*old_pl
;
215 /* If no branch has been checked out, there are no updates to make. */
216 if (is_index_unborn(r
->index
))
217 return UPDATE_SPARSITY_SUCCESS
;
219 old_pl
= r
->index
->sparse_checkout_patterns
;
220 r
->index
->sparse_checkout_patterns
= pl
;
222 memset(&o
, 0, sizeof(o
));
223 o
.verbose_update
= isatty(2);
226 o
.src_index
= r
->index
;
227 o
.dst_index
= r
->index
;
228 o
.skip_sparse_checkout
= 0;
232 repo_hold_locked_index(r
, &lock_file
, LOCK_DIE_ON_ERROR
);
234 setup_unpack_trees_porcelain(&o
, "sparse-checkout");
235 result
= update_sparsity(&o
, pl
);
236 clear_unpack_trees_porcelain(&o
);
238 if (result
== UPDATE_SPARSITY_WARNINGS
)
240 * We don't do any special handling of warnings from untracked
241 * files in the way or dirty entries that can't be removed.
243 result
= UPDATE_SPARSITY_SUCCESS
;
244 if (result
== UPDATE_SPARSITY_SUCCESS
)
245 write_locked_index(r
->index
, &lock_file
, COMMIT_LOCK
);
247 rollback_lock_file(&lock_file
);
249 clean_tracked_sparse_directories(r
);
251 if (r
->index
->sparse_checkout_patterns
!= pl
) {
252 clear_pattern_list(r
->index
->sparse_checkout_patterns
);
253 FREE_AND_NULL(r
->index
->sparse_checkout_patterns
);
255 r
->index
->sparse_checkout_patterns
= old_pl
;
260 static char *escaped_pattern(char *pattern
)
263 struct strbuf final
= STRBUF_INIT
;
266 if (is_glob_special(*p
))
267 strbuf_addch(&final
, '\\');
269 strbuf_addch(&final
, *p
);
273 return strbuf_detach(&final
, NULL
);
276 static void write_cone_to_file(FILE *fp
, struct pattern_list
*pl
)
279 struct pattern_entry
*pe
;
280 struct hashmap_iter iter
;
281 struct string_list sl
= STRING_LIST_INIT_DUP
;
282 struct strbuf parent_pattern
= STRBUF_INIT
;
284 hashmap_for_each_entry(&pl
->parent_hashmap
, &iter
, pe
, ent
) {
285 if (hashmap_get_entry(&pl
->recursive_hashmap
, pe
, ent
, NULL
))
288 if (!hashmap_contains_parent(&pl
->recursive_hashmap
,
291 string_list_insert(&sl
, pe
->pattern
);
294 string_list_sort(&sl
);
295 string_list_remove_duplicates(&sl
, 0);
297 fprintf(fp
, "/*\n!/*/\n");
299 for (i
= 0; i
< sl
.nr
; i
++) {
300 char *pattern
= escaped_pattern(sl
.items
[i
].string
);
303 fprintf(fp
, "%s/\n!%s/*/\n", pattern
, pattern
);
307 string_list_clear(&sl
, 0);
309 hashmap_for_each_entry(&pl
->recursive_hashmap
, &iter
, pe
, ent
) {
310 if (!hashmap_contains_parent(&pl
->recursive_hashmap
,
313 string_list_insert(&sl
, pe
->pattern
);
316 strbuf_release(&parent_pattern
);
318 string_list_sort(&sl
);
319 string_list_remove_duplicates(&sl
, 0);
321 for (i
= 0; i
< sl
.nr
; i
++) {
322 char *pattern
= escaped_pattern(sl
.items
[i
].string
);
323 fprintf(fp
, "%s/\n", pattern
);
327 string_list_clear(&sl
, 0);
330 static int write_patterns_and_update(struct pattern_list
*pl
)
332 char *sparse_filename
;
334 struct lock_file lk
= LOCK_INIT
;
337 sparse_filename
= get_sparse_checkout_filename();
339 if (safe_create_leading_directories(the_repository
, sparse_filename
))
340 die(_("failed to create directory for sparse-checkout file"));
342 hold_lock_file_for_update(&lk
, sparse_filename
, LOCK_DIE_ON_ERROR
);
344 result
= update_working_directory(pl
);
346 rollback_lock_file(&lk
);
347 update_working_directory(NULL
);
351 fp
= fdopen_lock_file(&lk
, "w");
353 die_errno(_("unable to fdopen %s"), get_lock_file_path(&lk
));
355 if (core_sparse_checkout_cone
)
356 write_cone_to_file(fp
, pl
);
358 write_patterns_to_file(fp
, pl
);
360 if (commit_lock_file(&lk
))
361 die_errno(_("unable to write %s"), sparse_filename
);
364 clear_pattern_list(pl
);
365 free(sparse_filename
);
369 enum sparse_checkout_mode
{
370 MODE_NO_PATTERNS
= 0,
371 MODE_ALL_PATTERNS
= 1,
372 MODE_CONE_PATTERNS
= 2,
375 static int set_config(enum sparse_checkout_mode mode
)
377 /* Update to use worktree config, if not already. */
378 if (init_worktree_config(the_repository
)) {
379 error(_("failed to initialize worktree config"));
383 if (repo_config_set_worktree_gently(the_repository
,
384 "core.sparseCheckout",
385 mode
? "true" : "false") ||
386 repo_config_set_worktree_gently(the_repository
,
387 "core.sparseCheckoutCone",
388 mode
== MODE_CONE_PATTERNS
?
392 if (mode
== MODE_NO_PATTERNS
)
393 return set_sparse_index_config(the_repository
, 0);
398 static enum sparse_checkout_mode
update_cone_mode(int *cone_mode
) {
399 /* If not specified, use previous definition of cone mode */
400 if (*cone_mode
== -1 && core_apply_sparse_checkout
)
401 *cone_mode
= core_sparse_checkout_cone
;
403 /* Set cone/non-cone mode appropriately */
404 core_apply_sparse_checkout
= 1;
405 if (*cone_mode
== 1 || *cone_mode
== -1) {
406 core_sparse_checkout_cone
= 1;
407 return MODE_CONE_PATTERNS
;
409 core_sparse_checkout_cone
= 0;
410 return MODE_ALL_PATTERNS
;
413 static int update_modes(int *cone_mode
, int *sparse_index
)
415 int mode
, record_mode
;
417 /* Determine if we need to record the mode; ensure sparse checkout on */
418 record_mode
= (*cone_mode
!= -1) || !core_apply_sparse_checkout
;
420 mode
= update_cone_mode(cone_mode
);
421 if (record_mode
&& set_config(mode
))
424 /* Set sparse-index/non-sparse-index mode if specified */
425 if (*sparse_index
>= 0) {
426 if (set_sparse_index_config(the_repository
, *sparse_index
) < 0)
427 die(_("failed to modify sparse-index config"));
429 /* force an index rewrite */
430 repo_read_index(the_repository
);
431 the_repository
->index
->updated_workdir
= 1;
434 ensure_full_index(the_repository
->index
);
440 static char const * const builtin_sparse_checkout_init_usage
[] = {
441 "git sparse-checkout init [--cone] [--[no-]sparse-index]",
445 static struct sparse_checkout_init_opts
{
450 static int sparse_checkout_init(int argc
, const char **argv
, const char *prefix
,
451 struct repository
*repo UNUSED
)
453 struct pattern_list pl
;
454 char *sparse_filename
;
456 struct object_id oid
;
458 static struct option builtin_sparse_checkout_init_options
[] = {
459 OPT_BOOL(0, "cone", &init_opts
.cone_mode
,
460 N_("initialize the sparse-checkout in cone mode")),
461 OPT_BOOL(0, "sparse-index", &init_opts
.sparse_index
,
462 N_("toggle the use of a sparse index")),
467 repo_read_index(the_repository
);
469 init_opts
.cone_mode
= -1;
470 init_opts
.sparse_index
= -1;
472 argc
= parse_options(argc
, argv
, prefix
,
473 builtin_sparse_checkout_init_options
,
474 builtin_sparse_checkout_init_usage
, 0);
476 if (update_modes(&init_opts
.cone_mode
, &init_opts
.sparse_index
))
479 memset(&pl
, 0, sizeof(pl
));
481 sparse_filename
= get_sparse_checkout_filename();
482 res
= add_patterns_from_file_to_list(sparse_filename
, "", 0, &pl
, NULL
, 0);
484 /* If we already have a sparse-checkout file, use it. */
486 free(sparse_filename
);
487 clear_pattern_list(&pl
);
488 return update_working_directory(NULL
);
491 if (repo_get_oid(the_repository
, "HEAD", &oid
)) {
494 /* assume we are in a fresh repo, but update the sparse-checkout file */
495 if (safe_create_leading_directories(the_repository
, sparse_filename
))
496 die(_("unable to create leading directories of %s"),
498 fp
= xfopen(sparse_filename
, "w");
500 die(_("failed to open '%s'"), sparse_filename
);
502 free(sparse_filename
);
503 fprintf(fp
, "/*\n!/*/\n");
508 free(sparse_filename
);
510 add_pattern("/*", empty_base
, 0, &pl
, 0);
511 add_pattern("!/*/", empty_base
, 0, &pl
, 0);
512 pl
.use_cone_patterns
= init_opts
.cone_mode
;
514 return write_patterns_and_update(&pl
);
517 static void insert_recursive_pattern(struct pattern_list
*pl
, struct strbuf
*path
)
519 struct pattern_entry
*e
= xmalloc(sizeof(*e
));
520 e
->patternlen
= path
->len
;
521 e
->pattern
= strbuf_detach(path
, NULL
);
522 hashmap_entry_init(&e
->ent
, fspathhash(e
->pattern
));
524 hashmap_add(&pl
->recursive_hashmap
, &e
->ent
);
526 while (e
->patternlen
) {
527 char *slash
= strrchr(e
->pattern
, '/');
528 char *oldpattern
= e
->pattern
;
530 struct pattern_entry
*dup
;
532 if (!slash
|| slash
== e
->pattern
)
535 newlen
= slash
- e
->pattern
;
536 e
= xmalloc(sizeof(struct pattern_entry
));
537 e
->patternlen
= newlen
;
538 e
->pattern
= xstrndup(oldpattern
, newlen
);
539 hashmap_entry_init(&e
->ent
, fspathhash(e
->pattern
));
541 dup
= hashmap_get_entry(&pl
->parent_hashmap
, e
, ent
, NULL
);
543 hashmap_add(&pl
->parent_hashmap
, &e
->ent
);
552 static void strbuf_to_cone_pattern(struct strbuf
*line
, struct pattern_list
*pl
)
556 strbuf_trim_trailing_dir_sep(line
);
558 if (strbuf_normalize_path(line
))
559 die(_("could not normalize path %s"), line
->buf
);
564 if (line
->buf
[0] != '/')
565 strbuf_insertstr(line
, 0, "/");
567 insert_recursive_pattern(pl
, line
);
570 static void add_patterns_from_input(struct pattern_list
*pl
,
571 int argc
, const char **argv
,
575 if (core_sparse_checkout_cone
) {
576 struct strbuf line
= STRBUF_INIT
;
578 hashmap_init(&pl
->recursive_hashmap
, pl_hashmap_cmp
, NULL
, 0);
579 hashmap_init(&pl
->parent_hashmap
, pl_hashmap_cmp
, NULL
, 0);
580 pl
->use_cone_patterns
= 1;
583 struct strbuf unquoted
= STRBUF_INIT
;
584 while (!strbuf_getline(&line
, file
)) {
585 if (line
.buf
[0] == '"') {
586 strbuf_reset(&unquoted
);
587 if (unquote_c_style(&unquoted
, line
.buf
, NULL
))
588 die(_("unable to unquote C-style string '%s'"),
591 strbuf_swap(&unquoted
, &line
);
594 strbuf_to_cone_pattern(&line
, pl
);
597 strbuf_release(&unquoted
);
599 for (i
= 0; i
< argc
; i
++) {
600 strbuf_setlen(&line
, 0);
601 strbuf_addstr(&line
, argv
[i
]);
602 strbuf_to_cone_pattern(&line
, pl
);
605 strbuf_release(&line
);
608 struct strbuf line
= STRBUF_INIT
;
610 while (!strbuf_getline(&line
, file
))
611 add_pattern(line
.buf
, empty_base
, 0, pl
, 0);
613 strbuf_release(&line
);
615 for (i
= 0; i
< argc
; i
++)
616 add_pattern(argv
[i
], empty_base
, 0, pl
, 0);
626 static void add_patterns_cone_mode(int argc
, const char **argv
,
627 struct pattern_list
*pl
,
630 struct strbuf buffer
= STRBUF_INIT
;
631 struct pattern_entry
*pe
;
632 struct hashmap_iter iter
;
633 struct pattern_list existing
;
634 char *sparse_filename
= get_sparse_checkout_filename();
636 add_patterns_from_input(pl
, argc
, argv
,
637 use_stdin
? stdin
: NULL
);
639 memset(&existing
, 0, sizeof(existing
));
640 existing
.use_cone_patterns
= core_sparse_checkout_cone
;
642 if (add_patterns_from_file_to_list(sparse_filename
, "", 0,
644 die(_("unable to load existing sparse-checkout patterns"));
645 free(sparse_filename
);
647 if (!existing
.use_cone_patterns
)
648 die(_("existing sparse-checkout patterns do not use cone mode"));
650 hashmap_for_each_entry(&existing
.recursive_hashmap
, &iter
, pe
, ent
) {
651 if (!hashmap_contains_parent(&pl
->recursive_hashmap
,
652 pe
->pattern
, &buffer
) ||
653 !hashmap_contains_parent(&pl
->parent_hashmap
,
654 pe
->pattern
, &buffer
)) {
655 strbuf_reset(&buffer
);
656 strbuf_addstr(&buffer
, pe
->pattern
);
657 insert_recursive_pattern(pl
, &buffer
);
661 clear_pattern_list(&existing
);
662 strbuf_release(&buffer
);
665 static void add_patterns_literal(int argc
, const char **argv
,
666 struct pattern_list
*pl
,
669 char *sparse_filename
= get_sparse_checkout_filename();
670 if (add_patterns_from_file_to_list(sparse_filename
, "", 0,
672 die(_("unable to load existing sparse-checkout patterns"));
673 free(sparse_filename
);
674 add_patterns_from_input(pl
, argc
, argv
, use_stdin
? stdin
: NULL
);
677 static int modify_pattern_list(struct strvec
*args
, int use_stdin
,
681 int changed_config
= 0;
682 struct pattern_list
*pl
= xcalloc(1, sizeof(*pl
));
686 if (core_sparse_checkout_cone
)
687 add_patterns_cone_mode(args
->nr
, args
->v
, pl
, use_stdin
);
689 add_patterns_literal(args
->nr
, args
->v
, pl
, use_stdin
);
693 add_patterns_from_input(pl
, args
->nr
, args
->v
,
694 use_stdin
? stdin
: NULL
);
698 if (!core_apply_sparse_checkout
) {
699 set_config(MODE_ALL_PATTERNS
);
700 core_apply_sparse_checkout
= 1;
704 result
= write_patterns_and_update(pl
);
706 if (result
&& changed_config
)
707 set_config(MODE_NO_PATTERNS
);
709 clear_pattern_list(pl
);
714 static void sanitize_paths(struct strvec
*args
,
715 const char *prefix
, int skip_checks
)
722 if (prefix
&& *prefix
&& core_sparse_checkout_cone
) {
724 * The args are not pathspecs, so unfortunately we
725 * cannot imitate how cmd_add() uses parse_pathspec().
727 int prefix_len
= strlen(prefix
);
729 for (i
= 0; i
< args
->nr
; i
++) {
730 char *prefixed_path
= prefix_path(prefix
, prefix_len
, args
->v
[i
]);
731 strvec_replace(args
, i
, prefixed_path
);
739 if (prefix
&& *prefix
&& !core_sparse_checkout_cone
)
740 die(_("please run from the toplevel directory in non-cone mode"));
742 if (core_sparse_checkout_cone
) {
743 for (i
= 0; i
< args
->nr
; i
++) {
744 if (args
->v
[i
][0] == '/')
745 die(_("specify directories rather than patterns (no leading slash)"));
746 if (args
->v
[i
][0] == '!')
747 die(_("specify directories rather than patterns. If your directory starts with a '!', pass --skip-checks"));
748 if (strpbrk(args
->v
[i
], "*?[]"))
749 die(_("specify directories rather than patterns. If your directory really has any of '*?[]\\' in it, pass --skip-checks"));
753 for (i
= 0; i
< args
->nr
; i
++) {
754 struct cache_entry
*ce
;
755 struct index_state
*index
= the_repository
->index
;
756 int pos
= index_name_pos(index
, args
->v
[i
], strlen(args
->v
[i
]));
760 ce
= index
->cache
[pos
];
761 if (S_ISSPARSEDIR(ce
->ce_mode
))
764 if (core_sparse_checkout_cone
)
765 die(_("'%s' is not a directory; to treat it as a directory anyway, rerun with --skip-checks"), args
->v
[i
]);
767 warning(_("pass a leading slash before paths such as '%s' if you want a single file (see NON-CONE PROBLEMS in the git-sparse-checkout manual)."), args
->v
[i
]);
771 static char const * const builtin_sparse_checkout_add_usage
[] = {
772 N_("git sparse-checkout add [--skip-checks] (--stdin | <patterns>)"),
776 static struct sparse_checkout_add_opts
{
781 static int sparse_checkout_add(int argc
, const char **argv
, const char *prefix
,
782 struct repository
*repo UNUSED
)
784 static struct option builtin_sparse_checkout_add_options
[] = {
785 OPT_BOOL_F(0, "skip-checks", &add_opts
.skip_checks
,
786 N_("skip some sanity checks on the given paths that might give false positives"),
788 OPT_BOOL(0, "stdin", &add_opts
.use_stdin
,
789 N_("read patterns from standard in")),
792 struct strvec patterns
= STRVEC_INIT
;
796 if (!core_apply_sparse_checkout
)
797 die(_("no sparse-checkout to add to"));
799 repo_read_index(the_repository
);
801 argc
= parse_options(argc
, argv
, prefix
,
802 builtin_sparse_checkout_add_options
,
803 builtin_sparse_checkout_add_usage
, 0);
805 for (int i
= 0; i
< argc
; i
++)
806 strvec_push(&patterns
, argv
[i
]);
807 sanitize_paths(&patterns
, prefix
, add_opts
.skip_checks
);
809 ret
= modify_pattern_list(&patterns
, add_opts
.use_stdin
, ADD
);
811 strvec_clear(&patterns
);
815 static char const * const builtin_sparse_checkout_set_usage
[] = {
816 N_("git sparse-checkout set [--[no-]cone] [--[no-]sparse-index] [--skip-checks] (--stdin | <patterns>)"),
820 static struct sparse_checkout_set_opts
{
827 static int sparse_checkout_set(int argc
, const char **argv
, const char *prefix
,
828 struct repository
*repo UNUSED
)
830 int default_patterns_nr
= 2;
831 const char *default_patterns
[] = {"/*", "!/*/", NULL
};
833 static struct option builtin_sparse_checkout_set_options
[] = {
834 OPT_BOOL(0, "cone", &set_opts
.cone_mode
,
835 N_("initialize the sparse-checkout in cone mode")),
836 OPT_BOOL(0, "sparse-index", &set_opts
.sparse_index
,
837 N_("toggle the use of a sparse index")),
838 OPT_BOOL_F(0, "skip-checks", &set_opts
.skip_checks
,
839 N_("skip some sanity checks on the given paths that might give false positives"),
841 OPT_BOOL_F(0, "stdin", &set_opts
.use_stdin
,
842 N_("read patterns from standard in"),
846 struct strvec patterns
= STRVEC_INIT
;
850 repo_read_index(the_repository
);
852 set_opts
.cone_mode
= -1;
853 set_opts
.sparse_index
= -1;
855 argc
= parse_options(argc
, argv
, prefix
,
856 builtin_sparse_checkout_set_options
,
857 builtin_sparse_checkout_set_usage
, 0);
859 if (update_modes(&set_opts
.cone_mode
, &set_opts
.sparse_index
))
863 * Cone mode automatically specifies the toplevel directory. For
864 * non-cone mode, if nothing is specified, manually select just the
865 * top-level directory (much as 'init' would do).
867 if (!core_sparse_checkout_cone
&& !set_opts
.use_stdin
&& argc
== 0) {
868 for (int i
= 0; i
< default_patterns_nr
; i
++)
869 strvec_push(&patterns
, default_patterns
[i
]);
871 for (int i
= 0; i
< argc
; i
++)
872 strvec_push(&patterns
, argv
[i
]);
873 sanitize_paths(&patterns
, prefix
, set_opts
.skip_checks
);
876 ret
= modify_pattern_list(&patterns
, set_opts
.use_stdin
, REPLACE
);
878 strvec_clear(&patterns
);
882 static char const * const builtin_sparse_checkout_reapply_usage
[] = {
883 "git sparse-checkout reapply [--[no-]cone] [--[no-]sparse-index]",
887 static struct sparse_checkout_reapply_opts
{
892 static int sparse_checkout_reapply(int argc
, const char **argv
,
894 struct repository
*repo UNUSED
)
896 static struct option builtin_sparse_checkout_reapply_options
[] = {
897 OPT_BOOL(0, "cone", &reapply_opts
.cone_mode
,
898 N_("initialize the sparse-checkout in cone mode")),
899 OPT_BOOL(0, "sparse-index", &reapply_opts
.sparse_index
,
900 N_("toggle the use of a sparse index")),
905 if (!core_apply_sparse_checkout
)
906 die(_("must be in a sparse-checkout to reapply sparsity patterns"));
908 reapply_opts
.cone_mode
= -1;
909 reapply_opts
.sparse_index
= -1;
911 argc
= parse_options(argc
, argv
, prefix
,
912 builtin_sparse_checkout_reapply_options
,
913 builtin_sparse_checkout_reapply_usage
, 0);
915 repo_read_index(the_repository
);
917 if (update_modes(&reapply_opts
.cone_mode
, &reapply_opts
.sparse_index
))
920 return update_working_directory(NULL
);
923 static char const * const builtin_sparse_checkout_disable_usage
[] = {
924 "git sparse-checkout disable",
928 static int sparse_checkout_disable(int argc
, const char **argv
,
930 struct repository
*repo UNUSED
)
932 static struct option builtin_sparse_checkout_disable_options
[] = {
935 struct pattern_list pl
;
938 * We do not exit early if !core_apply_sparse_checkout; due to the
939 * ability for users to manually muck things up between
940 * direct editing of .git/info/sparse-checkout
941 * running read-tree -m u HEAD or update-index --skip-worktree
942 * direct toggling of config options
943 * users might end up with an index with SKIP_WORKTREE bit set on
944 * some files and not know how to undo it. So, here we just
945 * forcibly return to a dense checkout regardless of initial state.
949 argc
= parse_options(argc
, argv
, prefix
,
950 builtin_sparse_checkout_disable_options
,
951 builtin_sparse_checkout_disable_usage
, 0);
954 * Disable the advice message for expanding a sparse index, as we
955 * are expecting to do that when disabling sparse-checkout.
957 give_advice_on_expansion
= 0;
958 repo_read_index(the_repository
);
960 memset(&pl
, 0, sizeof(pl
));
961 hashmap_init(&pl
.recursive_hashmap
, pl_hashmap_cmp
, NULL
, 0);
962 hashmap_init(&pl
.parent_hashmap
, pl_hashmap_cmp
, NULL
, 0);
963 pl
.use_cone_patterns
= 0;
964 core_apply_sparse_checkout
= 1;
966 add_pattern("/*", empty_base
, 0, &pl
, 0);
968 prepare_repo_settings(the_repository
);
969 the_repository
->settings
.sparse_index
= 0;
971 if (update_working_directory(&pl
))
972 die(_("error while refreshing working directory"));
974 clear_pattern_list(&pl
);
975 return set_config(MODE_NO_PATTERNS
);
978 static char const * const builtin_sparse_checkout_check_rules_usage
[] = {
979 N_("git sparse-checkout check-rules [-z] [--skip-checks]"
980 "[--[no-]cone] [--rules-file <file>]"),
984 static struct sparse_checkout_check_rules_opts
{
986 int null_termination
;
990 static int check_rules(struct pattern_list
*pl
, int null_terminated
) {
991 struct strbuf line
= STRBUF_INIT
;
992 struct strbuf unquoted
= STRBUF_INIT
;
994 int line_terminator
= null_terminated
? 0 : '\n';
995 strbuf_getline_fn getline_fn
= null_terminated
? strbuf_getline_nul
997 the_repository
->index
->sparse_checkout_patterns
= pl
;
998 while (!getline_fn(&line
, stdin
)) {
1000 if (!null_terminated
&& line
.buf
[0] == '"') {
1001 strbuf_reset(&unquoted
);
1002 if (unquote_c_style(&unquoted
, line
.buf
, NULL
))
1003 die(_("unable to unquote C-style string '%s'"),
1006 path
= unquoted
.buf
;
1009 if (path_in_sparse_checkout(path
, the_repository
->index
))
1010 write_name_quoted(path
, stdout
, line_terminator
);
1012 strbuf_release(&line
);
1013 strbuf_release(&unquoted
);
1018 static int sparse_checkout_check_rules(int argc
, const char **argv
, const char *prefix
,
1019 struct repository
*repo UNUSED
)
1021 static struct option builtin_sparse_checkout_check_rules_options
[] = {
1022 OPT_BOOL('z', NULL
, &check_rules_opts
.null_termination
,
1023 N_("terminate input and output files by a NUL character")),
1024 OPT_BOOL(0, "cone", &check_rules_opts
.cone_mode
,
1025 N_("when used with --rules-file interpret patterns as cone mode patterns")),
1026 OPT_FILENAME(0, "rules-file", &check_rules_opts
.rules_file
,
1027 N_("use patterns in <file> instead of the current ones.")),
1033 struct pattern_list pl
= {0};
1034 char *sparse_filename
;
1035 check_rules_opts
.cone_mode
= -1;
1037 argc
= parse_options(argc
, argv
, prefix
,
1038 builtin_sparse_checkout_check_rules_options
,
1039 builtin_sparse_checkout_check_rules_usage
, 0);
1041 if (check_rules_opts
.rules_file
&& check_rules_opts
.cone_mode
< 0)
1042 check_rules_opts
.cone_mode
= 1;
1044 update_cone_mode(&check_rules_opts
.cone_mode
);
1045 pl
.use_cone_patterns
= core_sparse_checkout_cone
;
1046 if (check_rules_opts
.rules_file
) {
1047 fp
= xfopen(check_rules_opts
.rules_file
, "r");
1048 add_patterns_from_input(&pl
, argc
, argv
, fp
);
1051 sparse_filename
= get_sparse_checkout_filename();
1052 if (add_patterns_from_file_to_list(sparse_filename
, "", 0, &pl
,
1054 die(_("unable to load existing sparse-checkout patterns"));
1055 free(sparse_filename
);
1058 ret
= check_rules(&pl
, check_rules_opts
.null_termination
);
1059 clear_pattern_list(&pl
);
1060 free(check_rules_opts
.rules_file
);
1064 int cmd_sparse_checkout(int argc
,
1067 struct repository
*repo
)
1069 parse_opt_subcommand_fn
*fn
= NULL
;
1070 struct option builtin_sparse_checkout_options
[] = {
1071 OPT_SUBCOMMAND("list", &fn
, sparse_checkout_list
),
1072 OPT_SUBCOMMAND("init", &fn
, sparse_checkout_init
),
1073 OPT_SUBCOMMAND("set", &fn
, sparse_checkout_set
),
1074 OPT_SUBCOMMAND("add", &fn
, sparse_checkout_add
),
1075 OPT_SUBCOMMAND("reapply", &fn
, sparse_checkout_reapply
),
1076 OPT_SUBCOMMAND("disable", &fn
, sparse_checkout_disable
),
1077 OPT_SUBCOMMAND("check-rules", &fn
, sparse_checkout_check_rules
),
1081 argc
= parse_options(argc
, argv
, prefix
,
1082 builtin_sparse_checkout_options
,
1083 builtin_sparse_checkout_usage
, 0);
1085 git_config(git_default_config
, NULL
);
1087 prepare_repo_settings(the_repository
);
1088 the_repository
->settings
.command_requires_full_index
= 0;
1090 return fn(argc
, argv
, prefix
, repo
);