14
14
#include "resolve-undo.h"
15
15
#include "string-list.h"
16
16
#include "pathspec.h"
17
+ #include "run-command.h"
17
18
18
19
static int abbrev ;
19
20
static int show_deleted ;
@@ -28,8 +29,10 @@ static int show_valid_bit;
28
29
static int line_terminator = '\n' ;
29
30
static int debug_mode ;
30
31
static int show_eol ;
32
+ static int recurse_submodules ;
31
33
32
34
static const char * prefix ;
35
+ static const char * super_prefix ;
33
36
static int max_prefix_len ;
34
37
static int prefix_len ;
35
38
static struct pathspec pathspec ;
@@ -67,12 +70,25 @@ static void write_eolinfo(const struct cache_entry *ce, const char *path)
67
70
68
71
static void write_name (const char * name )
69
72
{
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
+
70
84
/*
71
85
* With "--full-name", prefix_len=0; this caller needs to pass
72
86
* an empty string in that case (a NULL is good for "").
73
87
*/
74
88
write_name_quoted_relative (name , prefix_len ? prefix : NULL ,
75
89
stdout , line_terminator );
90
+
91
+ strbuf_release (& full_name );
76
92
}
77
93
78
94
static void show_dir_entry (const char * tag , struct dir_entry * ent )
@@ -152,55 +168,84 @@ static void show_killed_files(struct dir_struct *dir)
152
168
}
153
169
}
154
170
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
+
155
192
static void show_ce_entry (const char * tag , const struct cache_entry * ce )
156
193
{
194
+ struct strbuf name = STRBUF_INIT ;
157
195
int len = max_prefix_len ;
196
+ if (super_prefix )
197
+ strbuf_addstr (& name , super_prefix );
198
+ strbuf_addstr (& name , ce -> name );
158
199
159
200
if (len >= ce_namelen (ce ))
160
201
die ("git ls-files: internal error - cache entry not superset of prefix" );
161
202
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
+ }
166
225
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 );
180
245
}
181
- tag = alttag ;
182
246
}
183
247
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 );
204
249
}
205
250
206
251
static void show_ru_info (void )
@@ -468,6 +513,8 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
468
513
{ OPTION_SET_INT , 0 , "full-name" , & prefix_len , NULL ,
469
514
N_ ("make the output relative to the project top directory" ),
470
515
PARSE_OPT_NOARG | PARSE_OPT_NONEG , NULL },
516
+ OPT_BOOL (0 , "recurse-submodules" , & recurse_submodules ,
517
+ N_ ("recurse through submodules" )),
471
518
OPT_BOOL (0 , "error-unmatch" , & error_unmatch ,
472
519
N_ ("if any <file> is not in the index, treat this as an error" )),
473
520
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)
484
531
prefix = cmd_prefix ;
485
532
if (prefix )
486
533
prefix_len = strlen (prefix );
534
+ super_prefix = get_super_prefix ();
487
535
git_config (git_default_config , NULL );
488
536
489
537
if (read_cache () < 0 )
@@ -519,6 +567,20 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
519
567
if (require_work_tree && !is_inside_work_tree ())
520
568
setup_work_tree ();
521
569
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
+
522
584
parse_pathspec (& pathspec , 0 ,
523
585
PATHSPEC_PREFER_CWD |
524
586
PATHSPEC_STRIP_SUBMODULE_SLASH_CHEAP ,
0 commit comments