@@ -26,8 +26,9 @@ static int show_killed;
26
26
static int show_valid_bit ;
27
27
static int line_terminator = '\n' ;
28
28
29
+ static const char * prefix ;
30
+ static int max_prefix_len ;
29
31
static int prefix_len ;
30
- static int prefix_offset ;
31
32
static const char * * pathspec ;
32
33
static int error_unmatch ;
33
34
static char * ps_matched ;
@@ -43,10 +44,15 @@ static const char *tag_modified = "";
43
44
static const char * tag_skip_worktree = "" ;
44
45
static const char * tag_resolve_undo = "" ;
45
46
47
+ static void write_name (const char * name , size_t len )
48
+ {
49
+ write_name_quoted_relative (name , len , prefix , prefix_len , stdout ,
50
+ line_terminator );
51
+ }
52
+
46
53
static void show_dir_entry (const char * tag , struct dir_entry * ent )
47
54
{
48
- int len = prefix_len ;
49
- int offset = prefix_offset ;
55
+ int len = max_prefix_len ;
50
56
51
57
if (len >= ent -> len )
52
58
die ("git ls-files: internal error - directory entry not superset of prefix" );
@@ -55,7 +61,7 @@ static void show_dir_entry(const char *tag, struct dir_entry *ent)
55
61
return ;
56
62
57
63
fputs (tag , stdout );
58
- write_name_quoted (ent -> name + offset , stdout , line_terminator );
64
+ write_name (ent -> name , ent -> len );
59
65
}
60
66
61
67
static void show_other_files (struct dir_struct * dir )
@@ -121,8 +127,7 @@ static void show_killed_files(struct dir_struct *dir)
121
127
122
128
static void show_ce_entry (const char * tag , struct cache_entry * ce )
123
129
{
124
- int len = prefix_len ;
125
- int offset = prefix_offset ;
130
+ int len = max_prefix_len ;
126
131
127
132
if (len >= ce_namelen (ce ))
128
133
die ("git ls-files: internal error - cache entry not superset of prefix" );
@@ -156,40 +161,39 @@ static void show_ce_entry(const char *tag, struct cache_entry *ce)
156
161
find_unique_abbrev (ce -> sha1 ,abbrev ),
157
162
ce_stage (ce ));
158
163
}
159
- write_name_quoted (ce -> name + offset , stdout , line_terminator );
164
+ write_name (ce -> name , ce_namelen ( ce ) );
160
165
}
161
166
162
167
static int show_one_ru (struct string_list_item * item , void * cbdata )
163
168
{
164
- int offset = prefix_offset ;
165
169
const char * path = item -> string ;
166
170
struct resolve_undo_info * ui = item -> util ;
167
171
int i , len ;
168
172
169
173
len = strlen (path );
170
- if (len < prefix_len )
174
+ if (len < max_prefix_len )
171
175
return 0 ; /* outside of the prefix */
172
- if (!match_pathspec (pathspec , path , len , prefix_len , ps_matched ))
176
+ if (!match_pathspec (pathspec , path , len , max_prefix_len , ps_matched ))
173
177
return 0 ; /* uninterested */
174
178
for (i = 0 ; i < 3 ; i ++ ) {
175
179
if (!ui -> mode [i ])
176
180
continue ;
177
181
printf ("%s%06o %s %d\t" , tag_resolve_undo , ui -> mode [i ],
178
182
find_unique_abbrev (ui -> sha1 [i ], abbrev ),
179
183
i + 1 );
180
- write_name_quoted (path + offset , stdout , line_terminator );
184
+ write_name (path , len );
181
185
}
182
186
return 0 ;
183
187
}
184
188
185
- static void show_ru_info (const char * prefix )
189
+ static void show_ru_info (void )
186
190
{
187
191
if (!the_index .resolve_undo )
188
192
return ;
189
193
for_each_string_list (show_one_ru , the_index .resolve_undo , NULL );
190
194
}
191
195
192
- static void show_files (struct dir_struct * dir , const char * prefix )
196
+ static void show_files (struct dir_struct * dir )
193
197
{
194
198
int i ;
195
199
@@ -243,7 +247,7 @@ static void show_files(struct dir_struct *dir, const char *prefix)
243
247
*/
244
248
static void prune_cache (const char * prefix )
245
249
{
246
- int pos = cache_name_pos (prefix , prefix_len );
250
+ int pos = cache_name_pos (prefix , max_prefix_len );
247
251
unsigned int first , last ;
248
252
249
253
if (pos < 0 )
@@ -256,7 +260,7 @@ static void prune_cache(const char *prefix)
256
260
while (last > first ) {
257
261
int next = (last + first ) >> 1 ;
258
262
struct cache_entry * ce = active_cache [next ];
259
- if (!strncmp (ce -> name , prefix , prefix_len )) {
263
+ if (!strncmp (ce -> name , prefix , max_prefix_len )) {
260
264
first = next + 1 ;
261
265
continue ;
262
266
}
@@ -265,11 +269,16 @@ static void prune_cache(const char *prefix)
265
269
active_nr = last ;
266
270
}
267
271
268
- static const char * verify_pathspec (const char * prefix )
272
+ static const char * pathspec_prefix (const char * prefix )
269
273
{
270
274
const char * * p , * n , * prev ;
271
275
unsigned long max ;
272
276
277
+ if (!pathspec ) {
278
+ max_prefix_len = prefix ? strlen (prefix ) : 0 ;
279
+ return prefix ;
280
+ }
281
+
273
282
prev = NULL ;
274
283
max = PATH_MAX ;
275
284
for (p = pathspec ; (n = * p ) != NULL ; p ++ ) {
@@ -291,10 +300,7 @@ static const char *verify_pathspec(const char *prefix)
291
300
}
292
301
}
293
302
294
- if (prefix_offset > max || memcmp (prev , prefix , prefix_offset ))
295
- die ("git ls-files: cannot generate relative filenames containing '..'" );
296
-
297
- prefix_len = max ;
303
+ max_prefix_len = max ;
298
304
return max ? xmemdupz (prev , max ) : NULL ;
299
305
}
300
306
@@ -374,7 +380,7 @@ void overlay_tree_on_cache(const char *tree_name, const char *prefix)
374
380
}
375
381
}
376
382
377
- int report_path_error (const char * ps_matched , const char * * pathspec , int prefix_offset )
383
+ int report_path_error (const char * ps_matched , const char * * pathspec , int prefix_len )
378
384
{
379
385
/*
380
386
* Make sure all pathspec matched; otherwise it is an error.
@@ -404,7 +410,7 @@ int report_path_error(const char *ps_matched, const char **pathspec, int prefix_
404
410
continue ;
405
411
406
412
error ("pathspec '%s' did not match any file(s) known to git." ,
407
- pathspec [num ] + prefix_offset );
413
+ pathspec [num ] + prefix_len );
408
414
errors ++ ;
409
415
}
410
416
return errors ;
@@ -456,9 +462,10 @@ static int option_parse_exclude_standard(const struct option *opt,
456
462
return 0 ;
457
463
}
458
464
459
- int cmd_ls_files (int argc , const char * * argv , const char * prefix )
465
+ int cmd_ls_files (int argc , const char * * argv , const char * cmd_prefix )
460
466
{
461
467
int require_work_tree = 0 , show_tag = 0 ;
468
+ const char * max_prefix ;
462
469
struct dir_struct dir ;
463
470
struct option builtin_ls_files_options [] = {
464
471
{ OPTION_CALLBACK , 'z' , NULL , NULL , NULL ,
@@ -504,7 +511,7 @@ int cmd_ls_files(int argc, const char **argv, const char *prefix)
504
511
{ OPTION_CALLBACK , 0 , "exclude-standard" , & dir , NULL ,
505
512
"add the standard git exclusions" ,
506
513
PARSE_OPT_NOARG , option_parse_exclude_standard },
507
- { OPTION_SET_INT , 0 , "full-name" , & prefix_offset , NULL ,
514
+ { OPTION_SET_INT , 0 , "full-name" , & prefix_len , NULL ,
508
515
"make the output relative to the project top directory" ,
509
516
PARSE_OPT_NOARG | PARSE_OPT_NONEG , NULL },
510
517
OPT_BOOLEAN (0 , "error-unmatch" , & error_unmatch ,
@@ -516,8 +523,9 @@ int cmd_ls_files(int argc, const char **argv, const char *prefix)
516
523
};
517
524
518
525
memset (& dir , 0 , sizeof (dir ));
526
+ prefix = cmd_prefix ;
519
527
if (prefix )
520
- prefix_offset = strlen (prefix );
528
+ prefix_len = strlen (prefix );
521
529
git_config (git_default_config , NULL );
522
530
523
531
if (read_cache () < 0 )
@@ -555,9 +563,8 @@ int cmd_ls_files(int argc, const char **argv, const char *prefix)
555
563
if (pathspec )
556
564
strip_trailing_slash_from_submodules ();
557
565
558
- /* Verify that the pathspec matches the prefix */
559
- if (pathspec )
560
- prefix = verify_pathspec (prefix );
566
+ /* Find common prefix for all pathspec's */
567
+ max_prefix = pathspec_prefix (prefix );
561
568
562
569
/* Treat unmatching pathspec elements as errors */
563
570
if (pathspec && error_unmatch ) {
@@ -575,24 +582,24 @@ int cmd_ls_files(int argc, const char **argv, const char *prefix)
575
582
show_killed | show_modified | show_resolve_undo ))
576
583
show_cached = 1 ;
577
584
578
- if (prefix )
579
- prune_cache (prefix );
585
+ if (max_prefix )
586
+ prune_cache (max_prefix );
580
587
if (with_tree ) {
581
588
/*
582
589
* Basic sanity check; show-stages and show-unmerged
583
590
* would not make any sense with this option.
584
591
*/
585
592
if (show_stage || show_unmerged )
586
593
die ("ls-files --with-tree is incompatible with -s or -u" );
587
- overlay_tree_on_cache (with_tree , prefix );
594
+ overlay_tree_on_cache (with_tree , max_prefix );
588
595
}
589
- show_files (& dir , prefix );
596
+ show_files (& dir );
590
597
if (show_resolve_undo )
591
- show_ru_info (prefix );
598
+ show_ru_info ();
592
599
593
600
if (ps_matched ) {
594
601
int bad ;
595
- bad = report_path_error (ps_matched , pathspec , prefix_offset );
602
+ bad = report_path_error (ps_matched , pathspec , prefix_len );
596
603
if (bad )
597
604
fprintf (stderr , "Did you forget to 'git add'?\n" );
598
605
0 commit comments