8 // uses the ls-files code
9 #include "builtin-ls-files.c"
14 // cached last access, to speed up searches (since we get a sorted list from git code)
15 struct DirStatus
*pLastAccessedChild
;
19 struct DirStatus
*next
;
20 struct DirStatus
*children
;
21 struct DirStatus
*parent
;
26 static struct DirStatus l_dirTree
;
29 static BOOL l_bNoRecurse
;
30 static int l_nMinStatusRelevantForDirs
;
31 static BOOL l_bSkipNormalDirs
;
32 static int l_nEmptyDirStatus
;
33 static BOOL l_bNoRecurseDir
;
35 static BOOL l_bFullPath
;
36 static char l_sFullPathBuf
[2048];
37 static LPSTR l_lpszFileName
;
39 static BOOL l_bDirStatus
;
40 static int l_nLastStatus
;
41 static int l_nEnumeratedCached
= 0;
44 static inline char GetStatusChar(int nStatus
)
48 case WGFS_Normal
: return 'N';
49 case WGFS_Modified
: return 'M';
50 case WGFS_Staged
: return 'S';
51 case WGFS_Added
: return 'A';
52 case WGFS_Conflicted
: return 'C';
53 case WGFS_Deleted
: return 'D';
55 case WGFS_Unversioned
: return 'U';
56 case WGFS_Ignored
: return 'I';
57 case WGFS_Unknown
: return '?';
58 case WGFS_Empty
: return 'E';
66 static BOOL
enum_ce_entry(struct cache_entry
*ce
, struct stat
*st
)
68 // is this of any use (ce->ce_flags & CE_VALID) ?
74 sFileName
= ce
->name
+ prefix_offset
;
78 strcpy(l_lpszFileName
, ce
->name
);
79 sFileName
= l_sFullPathBuf
;
82 const int nStage
= ce_stage(ce
);
84 int nStatus
= WGFS_Unknown
;
86 nStatus
= WGFS_Deleted
;
88 nStatus
= WGFS_Conflicted
;
89 else if ( ce_modified(ce
, st
, 0) )
90 nStatus
= WGFS_Modified
;
92 nStatus
= WGFS_Normal
;
93 l_nLastStatus
= nStatus
;
95 // output format: "F status sha1 filename"
98 fputc(GetStatusChar(nStatus
), stdout
);
100 fputsha1(ce
->sha1
, stdout
);
102 fputs(sFileName
, stdout
);
105 l_nEnumeratedCached
++;
110 // same as enum except it skips enumeration and just determines status (used for recursive folder status)
111 // returns TRUE if file was processed
112 static BOOL
process_ce_entry_status(struct cache_entry
*ce
, struct stat
*st
)
114 // is this of any use (ce->ce_flags & CE_VALID) ?
118 ef.sFileName = ce->name + offset;
122 strcpy(l_lpszFileName, ce->name);
123 ef.sFileName = l_sFullPathBuf;
126 const int nStage
= ce_stage(ce
);
128 UINT nStatus
= WGFS_Unknown
;
130 nStatus
= WGFS_Deleted
;
132 nStatus
= WGFS_Conflicted
;
133 else if ( ce_modified(ce
, st
, 0) )
134 nStatus
= WGFS_Modified
;
136 nStatus
= WGFS_Normal
;
137 l_nLastStatus
= nStatus
;
139 //ef.nStage = st ? ce_stage(ce) : 0;
141 //ef.sha1 = ce->sha1;
147 static void enum_unversioned(struct dir_entry
**files
, int nr
, BOOL bIgnored
)
152 struct dir_entry
*ent
= files
[i
];
154 // make sure to skip dirs
155 if (ent
->name
[ent
->len
-1] == '/')
158 if (!cache_name_is_other(ent
->name
, ent
->len
))
161 int len
= prefix_len
;
164 die("igit status: internal error - directory entry not superset of prefix");
166 if (pathspec
&& !pathspec_match(pathspec
, ps_matched
, ent
->name
, len
))
173 sFileName
= ent
->name
+ prefix_offset
;
177 strcpy(l_lpszFileName
, ent
->name
);
178 sFileName
= l_sFullPathBuf
;
182 fputs("F I 0000000000000000000000000000000000000000 ", stdout
);
184 fputs("F U 0000000000000000000000000000000000000000 ", stdout
);
185 fputs(sFileName
, stdout
);
191 static inline BOOL
enum_dir(struct DirStatus
*dir
, LPCSTR lpszPathName
)
193 if (dir
->nStatus
== WGFS_Normal
&& l_bSkipNormalDirs
)
196 // output format: "D status pathname"
199 fputc(GetStatusChar(dir
->nStatus
), stdout
);
201 fputs(lpszPathName
, stdout
);
207 static BOOL
enum_dirs(struct DirStatus
*dir
, LPSTR sPathNameBuf
)
209 const int len
= strlen(dir
->lpszName
);
210 memcpy(sPathNameBuf
, dir
->lpszName
, len
);
214 if ( enum_dir(dir
, l_bFullPath
? l_sFullPathBuf
: l_sFullPathBuf
+prefix_offset
) )
217 if (!l_bNoRecurse
&& dir
->children
)
221 *sPathNameBuf
++ = '/';
228 if ( enum_dirs(dir
, sPathNameBuf
) )
239 static struct DirStatus
* GetSubDir(struct DirStatus
*dir
, LPCSTR lpszName
, int nNameLenInclTerminator
)
241 // check for cached access
242 if (dir
->pLastAccessedChild
243 && !strcmp(dir
->pLastAccessedChild
->lpszName
, lpszName
))
245 return dir
->pLastAccessedChild
;
249 struct DirStatus
*p
= dir
->children
;
250 struct DirStatus
*last
= NULL
;
253 if ( !strcmp(p
->lpszName
, lpszName
) )
254 return (dir
->pLastAccessedChild
= p
);
260 // dir not accessed before, create new entry
261 // TODO: do more efficient allocator (allocate larger pools, they can still be fire and forget and let our garbage collector clean up)
262 p
= dir
->pLastAccessedChild
= (struct DirStatus
*) malloc(sizeof(struct DirStatus
) + ((nNameLenInclTerminator
+3)&~3));
264 p
->pLastAccessedChild
= NULL
;
265 p
->lpszName
= (char*)p
+ sizeof(struct DirStatus
);
269 p
->nStatus
= l_nEmptyDirStatus
;
278 memcpy((char*)p
->lpszName
, lpszName
, nNameLenInclTerminator
);
284 static inline BOOL
IsStatusRelevantForDirs(int nStatus
)
286 return nStatus
>= l_nMinStatusRelevantForDirs
&& nStatus
!= WGFS_Deleted
;
290 static void update_dirs_rec(LPCSTR lpszFileName
, UINT nDirLen
, struct cache_entry
*ce
, BOOL bStatusCached
, struct DirStatus
*parentDir
)
292 const int nDirLen1
= nDirLen
+1;
294 memcpy(s
, lpszFileName
, nDirLen
);
297 struct DirStatus
*dir
= GetSubDir(parentDir
, s
, nDirLen1
);
298 //ASSERT(dir != NULL);
300 // TODO: if 'conflicted' status is added then need to check for that as highest prio
301 if (dir
->nStatus
>= WGFS_Modified
&& l_bNoRecurse
)
303 // no further processing needed
307 // process next subdir in lpszFileName
309 lpszFileName
+= nDirLen1
;
311 LPCSTR p
= strchr(lpszFileName
, '/');
314 // no more dirs in pathname (ie we are in the dir the file is located)
318 // file status not determined yet, do it now
320 int err
= lstat(ce
->name
, &st
);
321 if (!process_ce_entry_status(ce
, err
? NULL
: &st
) || !IsStatusRelevantForDirs(l_nLastStatus
))
324 const int nFileStatus
= l_nLastStatus
;
326 if (nFileStatus
> dir
->nStatus
)
328 // update status on dir and all parents
331 if (nFileStatus
> dir
->nStatus
)
332 dir
->nStatus
= nFileStatus
;
334 while ( (dir
= dir
->parent
) );
337 else if (lpszFileName
!= p
) // quick check to make sure we're not left with a "/" filename
339 update_dirs_rec(lpszFileName
, (UINT
)(p
-lpszFileName
), ce
, bStatusCached
, dir
);
343 static void update_dirs(struct cache_entry
*ce
, int nPathNameOffset
, BOOL bStatusCached
)
345 // filename relative to enumerated path
346 LPCSTR lpszFileName
= ce
->name
+ nPathNameOffset
;
348 LPCSTR p
= strchr(lpszFileName
, '/');
349 if (p
<= lpszFileName
)
351 // file is not in sub-dir
355 // file status not determined yet, do it now
357 int err
= lstat(ce
->name
, &st
);
358 if (!process_ce_entry_status(ce
, err
? NULL
: &st
) || !IsStatusRelevantForDirs(l_nLastStatus
))
361 const int nFileStatus
= l_nLastStatus
;
363 if (nFileStatus
> l_dirTree
.nStatus
)
364 l_dirTree
.nStatus
= nFileStatus
;
369 if (!l_bNoRecurseDir
)
371 update_dirs_rec(lpszFileName
, (UINT
)(p
-lpszFileName
), ce
, bStatusCached
, &l_dirTree
);
376 static inline BOOL
is_subpath(const char *sPath
, int nPathLen
, const char *sFile
)
378 return strchr(sFile
+ nPathLen
, '/') != NULL
;
381 static BOOL
is_dir(const char *sProjectPath
, const char *sSubPath
)
385 strcpy(s
, sProjectPath
);
394 // make sure it ends with a slash
398 // backslashify sub-path
407 int err
= lstat(s
, &st
);
409 return (!err
&& S_ISDIR(st
.st_mode
));
412 static inline BOOL
is_ce_name_eq(struct cache_entry
*ce1
, struct cache_entry
*ce2
)
414 const size_t len1
= ce1
->ce_flags
& CE_NAMEMASK
;
415 const size_t len2
= ce2
->ce_flags
& CE_NAMEMASK
;
417 return (len1
== len2
) ? !strcmp(ce1
->name
, ce2
->name
) : FALSE
;
421 BOOL
ig_enum_files(const char *pszProjectPath
, const char *pszSubPath
, const char *prefix
, unsigned int nFlags
)
423 // reset all local vars of builtin-ls-files.c to default
433 line_terminator
= '\n';
447 const BOOL bSubDir
= pszSubPath
&& is_dir(pszProjectPath
, pszSubPath
);
449 LPCSTR pszSubPathSpec
= pszSubPath
;
450 if (bSubDir
&& !(nFlags
& WGEFF_SingleFile
))
452 int len
= strlen(pszSubPath
);
453 char *s
= (char*)malloc(len
+3);
454 strcpy(s
, pszSubPath
);
460 //int exc_given = 0, require_work_tree = 0;
461 struct dir_struct _dir
;
463 memset(&_dir
, 0, sizeof(_dir
));
465 memset(&l_dirTree
, 0, sizeof(l_dirTree
));
466 l_dirTree
.nStatus
= WGFS_Normal
; // root dir is always at least WGFS_Normal even if empty
467 if (pszSubPath
&& !(nFlags
& WGEFF_EmptyAsNormal
))
468 l_dirTree
.nStatus
= WGFS_Empty
;
470 // NOTE: to force names to be relative to project root dir (no mater what current dir is) set prefix_offset to 0
472 prefix_offset
= strlen(prefix
);
473 git_config(git_default_config
, NULL
);
475 struct dir_struct
*dir
= &_dir
;
478 argv
[0] = pszSubPathSpec
;
481 if (/*require_work_tree &&*/ !is_inside_work_tree())
484 pathspec
= get_pathspec(prefix
, argv
);
486 // Verify that the pathspec matches the prefix
488 prefix
= verify_pathspec(prefix
);
490 // Treat unmatching pathspec elements as errors
491 if (pathspec
&& error_unmatch
)
494 for (num
= 0; pathspec
[num
]; num
++)
496 ps_matched
= xcalloc(1, num
);
499 // vars used for path recursion check
500 int pathspec_len
= 0;
501 if (pathspec
&& *pathspec
)
503 // calc length of pathspec plus 1 for a / (unless it already ends with a slash)
504 pathspec_len
= strlen(*pathspec
);
505 if ((*pathspec
)[pathspec_len
-1] == '*')
507 if ((*pathspec
)[pathspec_len
-1] != '/')
510 const char *refpath
= (pathspec
&& *pathspec
) ? *pathspec
: "";
516 l_bNoRecurseDir
= FALSE
;
518 BOOL single_dir
= (nFlags
& WGEFF_SingleFile
) && (!pszSubPath
|| bSubDir
);
519 // adjust other flags for best performance / correct results when WGEFF_SingleFile is set
520 if (single_dir
&& (nFlags
& WGEFF_NoRecurse
))
521 l_bNoRecurseDir
= TRUE
;
522 if (nFlags
& WGEFF_SingleFile
)
524 nFlags
|= WGEFF_NoRecurse
;
526 nFlags
&= ~(WGEFF_DirStatusAll
|WGEFF_DirStatusDelta
);
530 nFlags
= (nFlags
& ~WGEFF_DirStatusAll
) | WGEFF_DirStatusDelta
;
532 if ( !(nFlags
& WGEFF_EmptyAsNormal
) )
533 l_dirTree
.nStatus
= WGFS_Empty
;
536 BOOL no_recurse
= nFlags
& WGEFF_NoRecurse
;
537 l_bNoRecurse
= no_recurse
;
538 l_bFullPath
= nFlags
& WGEFF_FullPath
;
539 l_bDirStatus
= nFlags
& (WGEFF_DirStatusDelta
|WGEFF_DirStatusAll
);
541 // when all dirs should be enumerated we need IsStatusRelevantForDirs to report files of normal status as relevant
542 // otherwise only above normal are considered, which is slightly more efficient
543 l_nMinStatusRelevantForDirs
= (nFlags
& WGEFF_DirStatusAll
) ? WGFS_Normal
: (WGFS_Normal
+1);
545 // initial status of dirs
546 l_nEmptyDirStatus
= (nFlags
& WGEFF_EmptyAsNormal
) ? WGFS_Normal
: WGFS_Empty
;
548 l_bSkipNormalDirs
= ((nFlags
& (WGEFF_DirStatusDelta
|WGEFF_DirStatusAll
)) == WGEFF_DirStatusDelta
);
551 l_lpszFileName
= NULL
;
554 strcpy(l_sFullPathBuf
, pszProjectPath
);
556 LPSTR q
= l_sFullPathBuf
;
563 // make sure it ends with a slash
569 // save pointer to where file paths, with project-relative names, can be concatenated
573 // shouldn't have any effect but set them to reflect what we want listed
583 //if (pathspec && *pathspec) OutputDebugString(*pathspec);OutputDebugString(" (1)\r\n");
584 //if (prefix) OutputDebugString(prefix);OutputDebugString(" (2)\r\n");
590 for (i
=0; i
<active_nr
; i
++)
592 struct cache_entry
*ce
= active_cache
[i
];
596 int dtype
= ce_to_dtype(ce
);
598 if (excluded(dir
, ce
->name
, &dtype
) != dir
->show_ignored
)
600 if (ce
->ce_flags
& CE_UPDATE
)
603 // skip file if not inside specified sub-path
604 // this test was originally done in enum_ce_entry but in order to avoid unecessery lstat calls it was moved
605 if (prefix_len
>= ce_namelen(ce
))
606 die("git ls-files: internal error - cache entry not superset of prefix");
607 if (pathspec
&& !pathspec_match(pathspec
, ps_matched
, ce
->name
, prefix_len
))
610 if (single_dir
|| (no_recurse
&& is_subpath(refpath
, pathspec_len
, ce
->name
)))
613 // this file would normally be skipped, but in order to determine correct dir status we need to process it
614 update_dirs(ce
, pathspec_len
, FALSE
);
619 err
= lstat(ce
->name
, &st
);
621 if ( enum_ce_entry(ce
, err
? NULL
: &st
) )
624 // normally (always?) conflicted/unmerged files will have 3 entries in a row (one in stage 1, one in 2 and one in 3)
625 // skip redundant entries here
630 for (j
=i
+1; j
<active_nr
; j
++)
632 struct cache_entry
*nextce
= active_cache
[j
];
634 if ( !is_ce_name_eq(ce
, nextce
) )
641 if (l_bDirStatus
&& IsStatusRelevantForDirs(l_nLastStatus
))
642 update_dirs(ce
, pathspec_len
, TRUE
);
645 // enumerate unversioned files
646 if ( !(nFlags
& WGEFF_SingleFile
) )
648 const char *path
= ".", *base
= "";
649 int baselen
= prefix_len
;
652 path
= base
= prefix
;
654 setup_standard_excludes(dir
);
655 dir
->collect_ignored
= 1;
656 dir
->show_ignored
= 0;
657 dir
->show_other_directories
= 0;
658 dir
->hide_empty_directories
= 0;
659 dir
->collect_all_ignored
= 1;
660 dir
->no_recurse_readdir
= no_recurse
? 1 : 0;
661 read_directory(dir
, path
, base
, baselen
, pathspec
);
663 enum_unversioned(dir
->entries
, dir
->nr
, FALSE
);
664 enum_unversioned(dir
->ignored
, dir
->ignored_nr
, TRUE
);
666 else if (!single_dir
&& !l_nEnumeratedCached
)
668 // get status of a single unversioned file
670 setup_standard_excludes(dir
);
676 sFileName
= pszSubPath
+ prefix_offset
;
680 strcpy(l_lpszFileName
, pszSubPath
);
681 sFileName
= l_sFullPathBuf
;
685 if ( excluded(dir
, pszSubPath
, &dtype
) )
686 fputs("F I 0000000000000000000000000000000000000000 ", stdout
);
688 fputs("F U 0000000000000000000000000000000000000000 ", stdout
);
689 fputs(sFileName
, stdout
);
697 LPCSTR lpszRootDir
="/";
700 lpszRootDir
= l_sFullPathBuf
;
703 strcpy(l_lpszFileName
, *pathspec
);
704 l_lpszFileName
+= pathspec_len
;
708 // remove trailng slash
709 l_lpszFileName
[-1] = 0;
711 else if (pathspec_len
)
713 lpszRootDir
= *pathspec
;
715 strcpy(l_sFullPathBuf
, *pathspec
);
716 l_sFullPathBuf
[pathspec_len
-1] = '/';
717 l_sFullPathBuf
[pathspec_len
] = 0;
718 l_lpszFileName
= l_sFullPathBuf
;
724 l_lpszFileName
= l_sFullPathBuf
;
729 // enumerate single dir
730 l_bSkipNormalDirs
= FALSE
;
731 enum_dir(&l_dirTree
, lpszRootDir
);
733 else if (!enum_dir(&l_dirTree
, lpszRootDir
) && l_dirTree
.children
)
736 // re-add trailing slash
737 l_lpszFileName
[-1] = '/';
739 struct DirStatus
*p
= l_dirTree
.children
;
743 if ( enum_dirs(p
, l_lpszFileName
) )
746 while ( (p
= p
->next
) );
757 * This merges the file listing in the directory cache index
758 * with the actual working directory list, and shows different
759 * combinations of the two.
761 * Copyright (C) Linus Torvalds, 2005
770 static int show_deleted
;
771 static int show_cached
;
772 static int show_others
;
773 static int show_stage
;
774 static int show_unmerged
;
775 static int show_modified
;
776 static int show_killed
;
777 static int show_valid_bit
;
778 static int line_terminator
= '\n';
780 static int prefix_len
;
781 static int prefix_offset
;
782 static const char **pathspec
;
783 static int error_unmatch
;
784 static char *ps_matched
;
785 static const char *with_tree
;
787 static const char *tag_cached
= "";
788 static const char *tag_unmerged
= "";
789 static const char *tag_removed
= "";
790 static const char *tag_other
= "";
791 static const char *tag_killed
= "";
792 static const char *tag_modified
= "";
796 * Match a pathspec against a filename. The first "skiplen" characters
797 * are the common prefix
799 int pathspec_match(const char **spec
, char *ps_matched
,
800 const char *filename
, int skiplen
)
804 while ((m
= *spec
++) != NULL
) {
805 int matchlen
= strlen(m
+ skiplen
);
809 if (!strncmp(m
+ skiplen
, filename
+ skiplen
, matchlen
)) {
810 if (m
[skiplen
+ matchlen
- 1] == '/')
812 switch (filename
[skiplen
+ matchlen
]) {
817 if (!fnmatch(m
+ skiplen
, filename
+ skiplen
, 0))
830 static void show_dir_entry(const char *tag
, struct dir_entry
*ent
)
832 int len
= prefix_len
;
833 int offset
= prefix_offset
;
836 die("git ls-files: internal error - directory entry not superset of prefix");
838 if (pathspec
&& !pathspec_match(pathspec
, ps_matched
, ent
->name
, len
))
842 write_name_quoted(ent
->name
+ offset
, stdout
, line_terminator
);
845 static void show_other_files(struct dir_struct
*dir
)
849 for (i
= 0; i
< dir
->nr
; i
++) {
850 struct dir_entry
*ent
= dir
->entries
[i
];
851 if (!cache_name_is_other(ent
->name
, ent
->len
))
853 show_dir_entry(tag_other
, ent
);
857 static void show_killed_files(struct dir_struct
*dir
)
860 for (i
= 0; i
< dir
->nr
; i
++) {
861 struct dir_entry
*ent
= dir
->entries
[i
];
863 int pos
, len
, killed
= 0;
865 for (cp
= ent
->name
; cp
- ent
->name
< ent
->len
; cp
= sp
+ 1) {
866 sp
= strchr(cp
, '/');
868 /* If ent->name is prefix of an entry in the
869 * cache, it will be killed.
871 pos
= cache_name_pos(ent
->name
, ent
->len
);
873 die("bug in show-killed-files");
875 while (pos
< active_nr
&&
876 ce_stage(active_cache
[pos
]))
877 pos
++; /* skip unmerged */
878 if (active_nr
<= pos
)
880 /* pos points at a name immediately after
881 * ent->name in the cache. Does it expect
882 * ent->name to be a directory?
884 len
= ce_namelen(active_cache
[pos
]);
885 if ((ent
->len
< len
) &&
886 !strncmp(active_cache
[pos
]->name
,
887 ent
->name
, ent
->len
) &&
888 active_cache
[pos
]->name
[ent
->len
] == '/')
892 if (0 <= cache_name_pos(ent
->name
, sp
- ent
->name
)) {
893 /* If any of the leading directories in
894 * ent->name is registered in the cache,
895 * ent->name will be killed.
902 show_dir_entry(tag_killed
, dir
->entries
[i
]);
906 static void show_ce_entry(const char *tag
, struct cache_entry
*ce
)
908 int len
= prefix_len
;
909 int offset
= prefix_offset
;
911 if (len
>= ce_namelen(ce
))
912 die("git ls-files: internal error - cache entry not superset of prefix");
914 if (pathspec
&& !pathspec_match(pathspec
, ps_matched
, ce
->name
, len
))
917 if (tag
&& *tag
&& show_valid_bit
&&
918 (ce
->ce_flags
& CE_VALID
)) {
919 static char alttag
[4];
920 memcpy(alttag
, tag
, 3);
922 alttag
[0] = tolower(tag
[0]);
923 else if (tag
[0] == '?')
937 printf("%s%06o %s %d\t",
940 abbrev
? find_unique_abbrev(ce
->sha1
,abbrev
)
941 : sha1_to_hex(ce
->sha1
),
944 write_name_quoted(ce
->name
+ offset
, stdout
, line_terminator
);
947 static void show_files(struct dir_struct
*dir
, const char *prefix
)
951 /* For cached/deleted files we don't need to even do the readdir */
952 if (show_others
|| show_killed
) {
953 const char *path
= ".", *base
= "";
954 int baselen
= prefix_len
;
957 path
= base
= prefix
;
958 read_directory(dir
, path
, base
, baselen
, pathspec
);
960 show_other_files(dir
);
962 show_killed_files(dir
);
964 if (show_cached
| show_stage
) {
965 for (i
= 0; i
< active_nr
; i
++) {
966 struct cache_entry
*ce
= active_cache
[i
];
967 int dtype
= ce_to_dtype(ce
);
968 if (excluded(dir
, ce
->name
, &dtype
) != dir
->show_ignored
)
970 if (show_unmerged
&& !ce_stage(ce
))
972 if (ce
->ce_flags
& CE_UPDATE
)
974 show_ce_entry(ce_stage(ce
) ? tag_unmerged
: tag_cached
, ce
);
977 if (show_deleted
| show_modified
) {
978 for (i
= 0; i
< active_nr
; i
++) {
979 struct cache_entry
*ce
= active_cache
[i
];
982 int dtype
= ce_to_dtype(ce
);
983 if (excluded(dir
, ce
->name
, &dtype
) != dir
->show_ignored
)
985 if (ce
->ce_flags
& CE_UPDATE
)
987 err
= lstat(ce
->name
, &st
);
988 if (show_deleted
&& err
)
989 show_ce_entry(tag_removed
, ce
);
990 if (show_modified
&& ce_modified(ce
, &st
, 0))
991 show_ce_entry(tag_modified
, ce
);
997 * Prune the index to only contain stuff starting with "prefix"
999 static void prune_cache(const char *prefix
)
1001 int pos
= cache_name_pos(prefix
, prefix_len
);
1002 unsigned int first
, last
;
1006 memmove(active_cache
, active_cache
+ pos
,
1007 (active_nr
- pos
) * sizeof(struct cache_entry
*));
1011 while (last
> first
) {
1012 int next
= (last
+ first
) >> 1;
1013 struct cache_entry
*ce
= active_cache
[next
];
1014 if (!strncmp(ce
->name
, prefix
, prefix_len
)) {
1023 static const char *verify_pathspec(const char *prefix
)
1025 const char **p
, *n
, *prev
;
1030 for (p
= pathspec
; (n
= *p
) != NULL
; p
++) {
1032 for (i
= 0; i
< max
; i
++) {
1034 if (prev
&& prev
[i
] != c
)
1036 if (!c
|| c
== '*' || c
== '?')
1049 if (prefix_offset
> max
|| memcmp(prev
, prefix
, prefix_offset
))
1050 die("git ls-files: cannot generate relative filenames containing '..'");
1053 return max
? xmemdupz(prev
, max
) : NULL
;
1057 * Read the tree specified with --with-tree option
1058 * (typically, HEAD) into stage #1 and then
1059 * squash them down to stage #0. This is used for
1060 * --error-unmatch to list and check the path patterns
1061 * that were given from the command line. We are not
1062 * going to write this index out.
1064 void overlay_tree_on_cache(const char *tree_name
, const char *prefix
)
1067 unsigned char sha1
[20];
1069 struct cache_entry
*last_stage0
= NULL
;
1072 if (get_sha1(tree_name
, sha1
))
1073 die("tree-ish %s not found.", tree_name
);
1074 tree
= parse_tree_indirect(sha1
);
1076 die("bad tree-ish %s", tree_name
);
1078 /* Hoist the unmerged entries up to stage #3 to make room */
1079 for (i
= 0; i
< active_nr
; i
++) {
1080 struct cache_entry
*ce
= active_cache
[i
];
1083 ce
->ce_flags
|= CE_STAGEMASK
;
1087 static const char *(matchbuf
[2]);
1088 matchbuf
[0] = prefix
;
1093 if (read_tree(tree
, 1, match
))
1094 die("unable to read tree entries %s", tree_name
);
1096 for (i
= 0; i
< active_nr
; i
++) {
1097 struct cache_entry
*ce
= active_cache
[i
];
1098 switch (ce_stage(ce
)) {
1106 * If there is stage #0 entry for this, we do not
1107 * need to show it. We use CE_UPDATE bit to mark
1111 !strcmp(last_stage0
->name
, ce
->name
))
1112 ce
->ce_flags
|= CE_UPDATE
;
1117 int report_path_error(const char *ps_matched
, const char **pathspec
, int prefix_offset
)
1120 * Make sure all pathspec matched; otherwise it is an error.
1122 int num
, errors
= 0;
1123 for (num
= 0; pathspec
[num
]; num
++) {
1124 int other
, found_dup
;
1126 if (ps_matched
[num
])
1129 * The caller might have fed identical pathspec
1130 * twice. Do not barf on such a mistake.
1132 for (found_dup
= other
= 0;
1133 !found_dup
&& pathspec
[other
];
1135 if (other
== num
|| !ps_matched
[other
])
1137 if (!strcmp(pathspec
[other
], pathspec
[num
]))
1139 * Ok, we have a match already.
1146 error("pathspec '%s' did not match any file(s) known to git.",
1147 pathspec
[num
] + prefix_offset
);
1153 static const char ls_files_usage
[] =
1154 "git ls-files [-z] [-t] [-v] (--[cached|deleted|others|stage|unmerged|killed|modified])* "
1155 "[ --ignored ] [--exclude=<pattern>] [--exclude-from=<file>] "
1156 "[ --exclude-per-directory=<filename> ] [--exclude-standard] "
1157 "[--full-name] [--abbrev] [--] [<file>]*";
1159 int cmd_ls_files(int argc
, const char **argv
, const char *prefix
)
1162 int exc_given
= 0, require_work_tree
= 0;
1163 struct dir_struct dir
;
1165 memset(&dir
, 0, sizeof(dir
));
1167 prefix_offset
= strlen(prefix
);
1168 git_config(git_default_config
, NULL
);
1170 for (i
= 1; i
< argc
; i
++) {
1171 const char *arg
= argv
[i
];
1173 if (!strcmp(arg
, "--")) {
1177 if (!strcmp(arg
, "-z")) {
1178 line_terminator
= 0;
1181 if (!strcmp(arg
, "-t") || !strcmp(arg
, "-v")) {
1183 tag_unmerged
= "M ";
1185 tag_modified
= "C ";
1192 if (!strcmp(arg
, "-c") || !strcmp(arg
, "--cached")) {
1196 if (!strcmp(arg
, "-d") || !strcmp(arg
, "--deleted")) {
1200 if (!strcmp(arg
, "-m") || !strcmp(arg
, "--modified")) {
1202 require_work_tree
= 1;
1205 if (!strcmp(arg
, "-o") || !strcmp(arg
, "--others")) {
1207 require_work_tree
= 1;
1210 if (!strcmp(arg
, "-i") || !strcmp(arg
, "--ignored")) {
1211 dir
.show_ignored
= 1;
1212 require_work_tree
= 1;
1215 if (!strcmp(arg
, "-s") || !strcmp(arg
, "--stage")) {
1219 if (!strcmp(arg
, "-k") || !strcmp(arg
, "--killed")) {
1221 require_work_tree
= 1;
1224 if (!strcmp(arg
, "--directory")) {
1225 dir
.show_other_directories
= 1;
1228 if (!strcmp(arg
, "--no-empty-directory")) {
1229 dir
.hide_empty_directories
= 1;
1232 if (!strcmp(arg
, "-u") || !strcmp(arg
, "--unmerged")) {
1233 /* There's no point in showing unmerged unless
1234 * you also show the stage information.
1240 if (!strcmp(arg
, "-x") && i
+1 < argc
) {
1242 add_exclude(argv
[++i
], "", 0, &dir
.exclude_list
[EXC_CMDL
]);
1245 if (!prefixcmp(arg
, "--exclude=")) {
1247 add_exclude(arg
+10, "", 0, &dir
.exclude_list
[EXC_CMDL
]);
1250 if (!strcmp(arg
, "-X") && i
+1 < argc
) {
1252 add_excludes_from_file(&dir
, argv
[++i
]);
1255 if (!prefixcmp(arg
, "--exclude-from=")) {
1257 add_excludes_from_file(&dir
, arg
+15);
1260 if (!prefixcmp(arg
, "--exclude-per-directory=")) {
1262 dir
.exclude_per_dir
= arg
+ 24;
1265 if (!strcmp(arg
, "--exclude-standard")) {
1267 setup_standard_excludes(&dir
);
1270 if (!strcmp(arg
, "--full-name")) {
1274 if (!strcmp(arg
, "--error-unmatch")) {
1278 if (!prefixcmp(arg
, "--with-tree=")) {
1279 with_tree
= arg
+ 12;
1282 if (!prefixcmp(arg
, "--abbrev=")) {
1283 abbrev
= strtoul(arg
+9, NULL
, 10);
1284 if (abbrev
&& abbrev
< MINIMUM_ABBREV
)
1285 abbrev
= MINIMUM_ABBREV
;
1286 else if (abbrev
> 40)
1290 if (!strcmp(arg
, "--abbrev")) {
1291 abbrev
= DEFAULT_ABBREV
;
1295 usage(ls_files_usage
);
1299 if (require_work_tree
&& !is_inside_work_tree())
1302 pathspec
= get_pathspec(prefix
, argv
+ i
);
1304 /* Verify that the pathspec matches the prefix */
1306 prefix
= verify_pathspec(prefix
);
1308 /* Treat unmatching pathspec elements as errors */
1309 if (pathspec
&& error_unmatch
) {
1311 for (num
= 0; pathspec
[num
]; num
++)
1313 ps_matched
= xcalloc(1, num
);
1316 if (dir
.show_ignored
&& !exc_given
) {
1317 fprintf(stderr
, "%s: --ignored needs some exclude pattern\n",
1322 /* With no flags, we default to showing the cached files */
1323 if (!(show_stage
| show_deleted
| show_others
| show_unmerged
|
1324 show_killed
| show_modified
))
1329 prune_cache(prefix
);
1332 * Basic sanity check; show-stages and show-unmerged
1333 * would not make any sense with this option.
1335 if (show_stage
|| show_unmerged
)
1336 die("ls-files --with-tree is incompatible with -s or -u");
1337 overlay_tree_on_cache(with_tree
, prefix
);
1339 show_files(&dir
, prefix
);
1343 bad
= report_path_error(ps_matched
, pathspec
, prefix_offset
);
1345 fprintf(stderr
, "Did you forget to 'git add'?\n");