@@ -35,6 +35,7 @@ static int line_terminator = '\n';
35
35
static int debug_mode ;
36
36
static int show_eol ;
37
37
static int recurse_submodules ;
38
+ static int skipping_duplicates ;
38
39
39
40
static const char * prefix ;
40
41
static int max_prefix_len ;
@@ -312,45 +313,59 @@ static void show_files(struct repository *repo, struct dir_struct *dir)
312
313
if (show_killed )
313
314
show_killed_files (repo -> index , dir );
314
315
}
315
- if (show_cached || show_stage ) {
316
- for (i = 0 ; i < repo -> index -> cache_nr ; i ++ ) {
317
- const struct cache_entry * ce = repo -> index -> cache [i ];
318
316
319
- construct_fullname (& fullname , repo , ce );
317
+ if (!(show_cached || show_stage || show_deleted || show_modified ))
318
+ return ;
319
+ for (i = 0 ; i < repo -> index -> cache_nr ; i ++ ) {
320
+ const struct cache_entry * ce = repo -> index -> cache [i ];
321
+ struct stat st ;
322
+ int stat_err ;
320
323
321
- if ((dir -> flags & DIR_SHOW_IGNORED ) &&
322
- !ce_excluded (dir , repo -> index , fullname .buf , ce ))
323
- continue ;
324
- if (show_unmerged && !ce_stage (ce ))
325
- continue ;
326
- if (ce -> ce_flags & CE_UPDATE )
327
- continue ;
324
+ construct_fullname (& fullname , repo , ce );
325
+
326
+ if ((dir -> flags & DIR_SHOW_IGNORED ) &&
327
+ !ce_excluded (dir , repo -> index , fullname .buf , ce ))
328
+ continue ;
329
+ if (ce -> ce_flags & CE_UPDATE )
330
+ continue ;
331
+ if ((show_cached || show_stage ) &&
332
+ (!show_unmerged || ce_stage (ce ))) {
328
333
show_ce (repo , dir , ce , fullname .buf ,
329
334
ce_stage (ce ) ? tag_unmerged :
330
335
(ce_skip_worktree (ce ) ? tag_skip_worktree :
331
336
tag_cached ));
337
+ if (skipping_duplicates )
338
+ goto skip_to_next_name ;
332
339
}
333
- }
334
- if (show_deleted || show_modified ) {
335
- for (i = 0 ; i < repo -> index -> cache_nr ; i ++ ) {
336
- const struct cache_entry * ce = repo -> index -> cache [i ];
337
- struct stat st ;
338
- int err ;
339
340
340
- construct_fullname (& fullname , repo , ce );
341
-
342
- if ((dir -> flags & DIR_SHOW_IGNORED ) &&
343
- !ce_excluded (dir , repo -> index , fullname .buf , ce ))
344
- continue ;
345
- if (ce -> ce_flags & CE_UPDATE )
346
- continue ;
347
- if (ce_skip_worktree (ce ))
348
- continue ;
349
- err = lstat (fullname .buf , & st );
350
- if (show_deleted && err )
351
- show_ce (repo , dir , ce , fullname .buf , tag_removed );
352
- if (show_modified && ie_modified (repo -> index , ce , & st , 0 ))
353
- show_ce (repo , dir , ce , fullname .buf , tag_modified );
341
+ if (!(show_deleted || show_modified ))
342
+ continue ;
343
+ if (ce_skip_worktree (ce ))
344
+ continue ;
345
+ stat_err = lstat (fullname .buf , & st );
346
+ if (stat_err && (errno != ENOENT && errno != ENOTDIR ))
347
+ error_errno ("cannot lstat '%s'" , fullname .buf );
348
+ if (stat_err && show_deleted ) {
349
+ show_ce (repo , dir , ce , fullname .buf , tag_removed );
350
+ if (skipping_duplicates )
351
+ goto skip_to_next_name ;
352
+ }
353
+ if (show_modified &&
354
+ (stat_err || ie_modified (repo -> index , ce , & st , 0 ))) {
355
+ show_ce (repo , dir , ce , fullname .buf , tag_modified );
356
+ if (skipping_duplicates )
357
+ goto skip_to_next_name ;
358
+ }
359
+ continue ;
360
+
361
+ skip_to_next_name :
362
+ {
363
+ int j ;
364
+ struct cache_entry * * cache = repo -> index -> cache ;
365
+ for (j = i + 1 ; j < repo -> index -> cache_nr ; j ++ )
366
+ if (strcmp (ce -> name , cache [j ]-> name ))
367
+ break ;
368
+ i = j - 1 ; /* compensate for the for loop */
354
369
}
355
370
}
356
371
@@ -578,6 +593,8 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
578
593
N_ ("pretend that paths removed since <tree-ish> are still present" )),
579
594
OPT__ABBREV (& abbrev ),
580
595
OPT_BOOL (0 , "debug" , & debug_mode , N_ ("show debugging data" )),
596
+ OPT_BOOL (0 , "deduplicate" , & skipping_duplicates ,
597
+ N_ ("suppress duplicate entries" )),
581
598
OPT_END ()
582
599
};
583
600
@@ -617,6 +634,8 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
617
634
* you also show the stage information.
618
635
*/
619
636
show_stage = 1 ;
637
+ if (show_tag || show_stage )
638
+ skipping_duplicates = 0 ;
620
639
if (dir .exclude_per_dir )
621
640
exc_given = 1 ;
622
641
0 commit comments