77#define USE_THE_INDEX_COMPATIBILITY_MACROS
88#include "builtin.h"
99#include "config.h"
10+ #include "dir.h"
1011#include "lockfile.h"
1112#include "quote.h"
1213#include "cache-tree.h"
1718#define CHECKOUT_ALL 4
1819static int nul_term_line ;
1920static int checkout_stage ; /* default to checkout stage0 */
21+ static int ignore_skip_worktree ; /* default to 0 */
2022static int to_tempfile ;
2123static char topath [4 ][TEMPORARY_FILENAME_LENGTH + 1 ];
2224
@@ -65,6 +67,8 @@ static int checkout_file(const char *name, const char *prefix)
6567 int namelen = strlen (name );
6668 int pos = cache_name_pos (name , namelen );
6769 int has_same_name = 0 ;
70+ int is_file = 0 ;
71+ int is_skipped = 1 ;
6872 int did_checkout = 0 ;
6973 int errs = 0 ;
7074
@@ -78,6 +82,12 @@ static int checkout_file(const char *name, const char *prefix)
7882 break ;
7983 has_same_name = 1 ;
8084 pos ++ ;
85+ if (S_ISSPARSEDIR (ce -> ce_mode ))
86+ break ;
87+ is_file = 1 ;
88+ if (!ignore_skip_worktree && ce_skip_worktree (ce ))
89+ break ;
90+ is_skipped = 0 ;
8191 if (ce_stage (ce ) != checkout_stage
8292 && (CHECKOUT_ALL != checkout_stage || !ce_stage (ce )))
8393 continue ;
@@ -106,6 +116,11 @@ static int checkout_file(const char *name, const char *prefix)
106116 fprintf (stderr , "git checkout-index: %s " , name );
107117 if (!has_same_name )
108118 fprintf (stderr , "is not in the cache" );
119+ else if (!is_file )
120+ fprintf (stderr , "is a sparse directory" );
121+ else if (is_skipped )
122+ fprintf (stderr , "has skip-worktree enabled; "
123+ "use '--ignore-skip-worktree-bits' to checkout" );
109124 else if (checkout_stage )
110125 fprintf (stderr , "does not exist at stage %d" ,
111126 checkout_stage );
@@ -121,10 +136,27 @@ static int checkout_all(const char *prefix, int prefix_length)
121136 int i , errs = 0 ;
122137 struct cache_entry * last_ce = NULL ;
123138
124- /* TODO: audit for interaction with sparse-index. */
125- ensure_full_index (& the_index );
126139 for (i = 0 ; i < active_nr ; i ++ ) {
127140 struct cache_entry * ce = active_cache [i ];
141+
142+ if (S_ISSPARSEDIR (ce -> ce_mode )) {
143+ if (!ce_skip_worktree (ce ))
144+ BUG ("sparse directory '%s' does not have skip-worktree set" , ce -> name );
145+
146+ /*
147+ * If the current entry is a sparse directory and skip-worktree
148+ * entries are being checked out, expand the index and continue
149+ * the loop on the current index position (now pointing to the
150+ * first entry inside the expanded sparse directory).
151+ */
152+ if (ignore_skip_worktree ) {
153+ ensure_full_index (& the_index );
154+ ce = active_cache [i ];
155+ }
156+ }
157+
158+ if (!ignore_skip_worktree && ce_skip_worktree (ce ))
159+ continue ;
128160 if (ce_stage (ce ) != checkout_stage
129161 && (CHECKOUT_ALL != checkout_stage || !ce_stage (ce )))
130162 continue ;
@@ -185,6 +217,8 @@ int cmd_checkout_index(int argc, const char **argv, const char *prefix)
185217 struct option builtin_checkout_index_options [] = {
186218 OPT_BOOL ('a' , "all" , & all ,
187219 N_ ("check out all files in the index" )),
220+ OPT_BOOL (0 , "ignore-skip-worktree-bits" , & ignore_skip_worktree ,
221+ N_ ("do not skip files with skip-worktree set" )),
188222 OPT__FORCE (& force , N_ ("force overwrite of existing files" ), 0 ),
189223 OPT__QUIET (& quiet ,
190224 N_ ("no warning for existing files and files not in index" )),
@@ -212,6 +246,9 @@ int cmd_checkout_index(int argc, const char **argv, const char *prefix)
212246 git_config (git_default_config , NULL );
213247 prefix_length = prefix ? strlen (prefix ) : 0 ;
214248
249+ prepare_repo_settings (the_repository );
250+ the_repository -> settings .command_requires_full_index = 0 ;
251+
215252 if (read_cache () < 0 ) {
216253 die ("invalid cache" );
217254 }
0 commit comments