1414#include "resolve-undo.h"
1515#include "string-list.h"
1616#include "pathspec.h"
17+ #include "run-command.h"
1718
1819static int abbrev ;
1920static int show_deleted ;
@@ -28,8 +29,10 @@ static int show_valid_bit;
2829static int line_terminator = '\n' ;
2930static int debug_mode ;
3031static int show_eol ;
32+ static int recurse_submodules ;
3133
3234static const char * prefix ;
35+ static const char * super_prefix ;
3336static int max_prefix_len ;
3437static int prefix_len ;
3538static struct pathspec pathspec ;
@@ -67,12 +70,25 @@ static void write_eolinfo(const struct cache_entry *ce, const char *path)
6770
6871static void write_name (const char * name )
6972{
73+ /*
74+ * Prepend the super_prefix to name to construct the full_name to be
75+ * written.
76+ */
77+ struct strbuf full_name = STRBUF_INIT ;
78+ if (super_prefix ) {
79+ strbuf_addstr (& full_name , super_prefix );
80+ strbuf_addstr (& full_name , name );
81+ name = full_name .buf ;
82+ }
83+
7084 /*
7185 * With "--full-name", prefix_len=0; this caller needs to pass
7286 * an empty string in that case (a NULL is good for "").
7387 */
7488 write_name_quoted_relative (name , prefix_len ? prefix : NULL ,
7589 stdout , line_terminator );
90+
91+ strbuf_release (& full_name );
7692}
7793
7894static void show_dir_entry (const char * tag , struct dir_entry * ent )
@@ -152,55 +168,84 @@ static void show_killed_files(struct dir_struct *dir)
152168 }
153169}
154170
171+ /**
172+ * Recursively call ls-files on a submodule
173+ */
174+ static void show_gitlink (const struct cache_entry * ce )
175+ {
176+ struct child_process cp = CHILD_PROCESS_INIT ;
177+ int status ;
178+
179+ argv_array_pushf (& cp .args , "--super-prefix=%s%s/" ,
180+ super_prefix ? super_prefix : "" ,
181+ ce -> name );
182+ argv_array_push (& cp .args , "ls-files" );
183+ argv_array_push (& cp .args , "--recurse-submodules" );
184+
185+ cp .git_cmd = 1 ;
186+ cp .dir = ce -> name ;
187+ status = run_command (& cp );
188+ if (status )
189+ exit (status );
190+ }
191+
155192static void show_ce_entry (const char * tag , const struct cache_entry * ce )
156193{
194+ struct strbuf name = STRBUF_INIT ;
157195 int len = max_prefix_len ;
196+ if (super_prefix )
197+ strbuf_addstr (& name , super_prefix );
198+ strbuf_addstr (& name , ce -> name );
158199
159200 if (len >= ce_namelen (ce ))
160201 die ("git ls-files: internal error - cache entry not superset of prefix" );
161202
162- if (!match_pathspec (& pathspec , ce -> name , ce_namelen (ce ),
163- len , ps_matched ,
164- S_ISDIR (ce -> ce_mode ) || S_ISGITLINK (ce -> ce_mode )))
165- return ;
203+ if (recurse_submodules && S_ISGITLINK (ce -> ce_mode )) {
204+ show_gitlink (ce );
205+ } else if (match_pathspec (& pathspec , name .buf , name .len ,
206+ len , ps_matched ,
207+ S_ISDIR (ce -> ce_mode ) ||
208+ S_ISGITLINK (ce -> ce_mode ))) {
209+ if (tag && * tag && show_valid_bit &&
210+ (ce -> ce_flags & CE_VALID )) {
211+ static char alttag [4 ];
212+ memcpy (alttag , tag , 3 );
213+ if (isalpha (tag [0 ]))
214+ alttag [0 ] = tolower (tag [0 ]);
215+ else if (tag [0 ] == '?' )
216+ alttag [0 ] = '!' ;
217+ else {
218+ alttag [0 ] = 'v' ;
219+ alttag [1 ] = tag [0 ];
220+ alttag [2 ] = ' ' ;
221+ alttag [3 ] = 0 ;
222+ }
223+ tag = alttag ;
224+ }
166225
167- if (tag && * tag && show_valid_bit &&
168- (ce -> ce_flags & CE_VALID )) {
169- static char alttag [4 ];
170- memcpy (alttag , tag , 3 );
171- if (isalpha (tag [0 ]))
172- alttag [0 ] = tolower (tag [0 ]);
173- else if (tag [0 ] == '?' )
174- alttag [0 ] = '!' ;
175- else {
176- alttag [0 ] = 'v' ;
177- alttag [1 ] = tag [0 ];
178- alttag [2 ] = ' ' ;
179- alttag [3 ] = 0 ;
226+ if (!show_stage ) {
227+ fputs (tag , stdout );
228+ } else {
229+ printf ("%s%06o %s %d\t" ,
230+ tag ,
231+ ce -> ce_mode ,
232+ find_unique_abbrev (ce -> sha1 ,abbrev ),
233+ ce_stage (ce ));
234+ }
235+ write_eolinfo (ce , ce -> name );
236+ write_name (ce -> name );
237+ if (debug_mode ) {
238+ const struct stat_data * sd = & ce -> ce_stat_data ;
239+
240+ printf (" ctime: %d:%d\n" , sd -> sd_ctime .sec , sd -> sd_ctime .nsec );
241+ printf (" mtime: %d:%d\n" , sd -> sd_mtime .sec , sd -> sd_mtime .nsec );
242+ printf (" dev: %d\tino: %d\n" , sd -> sd_dev , sd -> sd_ino );
243+ printf (" uid: %d\tgid: %d\n" , sd -> sd_uid , sd -> sd_gid );
244+ printf (" size: %d\tflags: %x\n" , sd -> sd_size , ce -> ce_flags );
180245 }
181- tag = alttag ;
182246 }
183247
184- if (!show_stage ) {
185- fputs (tag , stdout );
186- } else {
187- printf ("%s%06o %s %d\t" ,
188- tag ,
189- ce -> ce_mode ,
190- find_unique_abbrev (ce -> sha1 ,abbrev ),
191- ce_stage (ce ));
192- }
193- write_eolinfo (ce , ce -> name );
194- write_name (ce -> name );
195- if (debug_mode ) {
196- const struct stat_data * sd = & ce -> ce_stat_data ;
197-
198- printf (" ctime: %d:%d\n" , sd -> sd_ctime .sec , sd -> sd_ctime .nsec );
199- printf (" mtime: %d:%d\n" , sd -> sd_mtime .sec , sd -> sd_mtime .nsec );
200- printf (" dev: %d\tino: %d\n" , sd -> sd_dev , sd -> sd_ino );
201- printf (" uid: %d\tgid: %d\n" , sd -> sd_uid , sd -> sd_gid );
202- printf (" size: %d\tflags: %x\n" , sd -> sd_size , ce -> ce_flags );
203- }
248+ strbuf_release (& name );
204249}
205250
206251static void show_ru_info (void )
@@ -468,6 +513,8 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
468513 { OPTION_SET_INT , 0 , "full-name" , & prefix_len , NULL ,
469514 N_ ("make the output relative to the project top directory" ),
470515 PARSE_OPT_NOARG | PARSE_OPT_NONEG , NULL },
516+ OPT_BOOL (0 , "recurse-submodules" , & recurse_submodules ,
517+ N_ ("recurse through submodules" )),
471518 OPT_BOOL (0 , "error-unmatch" , & error_unmatch ,
472519 N_ ("if any <file> is not in the index, treat this as an error" )),
473520 OPT_STRING (0 , "with-tree" , & with_tree , N_ ("tree-ish" ),
@@ -484,6 +531,7 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
484531 prefix = cmd_prefix ;
485532 if (prefix )
486533 prefix_len = strlen (prefix );
534+ super_prefix = get_super_prefix ();
487535 git_config (git_default_config , NULL );
488536
489537 if (read_cache () < 0 )
@@ -519,6 +567,20 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
519567 if (require_work_tree && !is_inside_work_tree ())
520568 setup_work_tree ();
521569
570+ if (recurse_submodules &&
571+ (show_stage || show_deleted || show_others || show_unmerged ||
572+ show_killed || show_modified || show_resolve_undo ||
573+ show_valid_bit || show_tag || show_eol || with_tree ||
574+ (line_terminator == '\0' )))
575+ die ("ls-files --recurse-submodules unsupported mode" );
576+
577+ if (recurse_submodules && error_unmatch )
578+ die ("ls-files --recurse-submodules does not support "
579+ "--error-unmatch" );
580+
581+ if (recurse_submodules && argc )
582+ die ("ls-files --recurse-submodules does not support pathspec" );
583+
522584 parse_pathspec (& pathspec , 0 ,
523585 PATHSPEC_PREFER_CWD |
524586 PATHSPEC_STRIP_SUBMODULE_SLASH_CHEAP ,
0 commit comments