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
;
43 static inline char GetStatusChar(int nStatus
)
47 case WGFS_Normal
: return 'N';
48 case WGFS_Modified
: return 'M';
49 //case WGFS_Staged: return 'S';
50 //case WGFS_Added: return 'A';
51 case WGFS_Conflicted
: return 'C';
52 case WGFS_Deleted
: return 'D';
54 case WGFS_Unknown
: return '?';
55 case WGFS_Empty
: return 'E';
56 //case WGFS_Unversioned: return 'U';
64 static BOOL
enum_ce_entry(struct cache_entry
*ce
, struct stat
*st
)
66 // is this of any use (ce->ce_flags & CE_VALID) ?
72 sFileName
= ce
->name
+ prefix_offset
;
76 strcpy(l_lpszFileName
, ce
->name
);
77 sFileName
= l_sFullPathBuf
;
80 const int nStage
= ce_stage(ce
);
82 int nStatus
= WGFS_Unknown
;
84 nStatus
= WGFS_Deleted
;
86 nStatus
= WGFS_Conflicted
;
87 else if ( ce_modified(ce
, st
, 0) )
88 nStatus
= WGFS_Modified
;
90 nStatus
= WGFS_Normal
;
91 l_nLastStatus
= nStatus
;
93 // output format: "F status sha1 filename"
96 fputc(GetStatusChar(nStatus
), stdout
);
98 fputsha1(ce
->sha1
, stdout
);
100 fputs(sFileName
, stdout
);
106 // same as enum except it skips enumeration and just determines status (used for recursive folder status)
107 // returns TRUE if file was processed
108 static BOOL
process_ce_entry_status(struct cache_entry
*ce
, struct stat
*st
)
110 // is this of any use (ce->ce_flags & CE_VALID) ?
114 ef.sFileName = ce->name + offset;
118 strcpy(l_lpszFileName, ce->name);
119 ef.sFileName = l_sFullPathBuf;
122 const int nStage
= ce_stage(ce
);
124 UINT nStatus
= WGFS_Unknown
;
126 nStatus
= WGFS_Deleted
;
128 nStatus
= WGFS_Conflicted
;
129 else if ( ce_modified(ce
, st
, 0) )
130 nStatus
= WGFS_Modified
;
132 nStatus
= WGFS_Normal
;
133 l_nLastStatus
= nStatus
;
135 //ef.nStage = st ? ce_stage(ce) : 0;
137 //ef.sha1 = ce->sha1;
143 static inline BOOL
enum_dir(struct DirStatus
*dir
, LPCSTR lpszPathName
)
145 if (dir
->nStatus
== WGFS_Normal
&& l_bSkipNormalDirs
)
148 // output format: "D status pathname"
151 fputc(GetStatusChar(dir
->nStatus
), stdout
);
153 fputs(lpszPathName
, stdout
);
159 static BOOL
enum_dirs(struct DirStatus
*dir
, LPSTR sPathNameBuf
)
161 const int len
= strlen(dir
->lpszName
);
162 memcpy(sPathNameBuf
, dir
->lpszName
, len
);
166 if ( enum_dir(dir
, l_bFullPath
? l_sFullPathBuf
: l_sFullPathBuf
+prefix_offset
) )
169 if (!l_bNoRecurse
&& dir
->children
)
173 *sPathNameBuf
++ = '/';
180 if ( enum_dirs(dir
, sPathNameBuf
) )
191 static struct DirStatus
* GetSubDir(struct DirStatus
*dir
, LPCSTR lpszName
, int nNameLenInclTerminator
)
193 // check for cached access
194 if (dir
->pLastAccessedChild
195 && !strcmp(dir
->pLastAccessedChild
->lpszName
, lpszName
))
197 return dir
->pLastAccessedChild
;
201 struct DirStatus
*p
= dir
->children
;
202 struct DirStatus
*last
= NULL
;
205 if ( !strcmp(p
->lpszName
, lpszName
) )
206 return (dir
->pLastAccessedChild
= p
);
212 // dir not accessed before, create new entry
213 // TODO: do more efficient allocator (allocate larger pools, they can still be fire and forget and let our garbage collector clean up)
214 p
= dir
->pLastAccessedChild
= (struct DirStatus
*) malloc(sizeof(struct DirStatus
) + ((nNameLenInclTerminator
+3)&~3));
216 p
->pLastAccessedChild
= NULL
;
217 p
->lpszName
= (char*)p
+ sizeof(struct DirStatus
);
221 p
->nStatus
= l_nEmptyDirStatus
;
230 memcpy((char*)p
->lpszName
, lpszName
, nNameLenInclTerminator
);
236 static inline BOOL
IsStatusRelevantForDirs(int nStatus
)
238 return nStatus
>= l_nMinStatusRelevantForDirs
&& nStatus
!= WGFS_Deleted
;
242 static void update_dirs_rec(LPCSTR lpszFileName
, UINT nDirLen
, struct cache_entry
*ce
, BOOL bStatusCached
, struct DirStatus
*parentDir
)
244 const int nDirLen1
= nDirLen
+1;
246 memcpy(s
, lpszFileName
, nDirLen
);
249 struct DirStatus
*dir
= GetSubDir(parentDir
, s
, nDirLen1
);
250 //ASSERT(dir != NULL);
252 // TODO: if 'conflicted' status is added then need to check for that as highest prio
253 if (dir
->nStatus
>= WGFS_Modified
&& l_bNoRecurse
)
255 // no further processing needed
259 // process next subdir in lpszFileName
261 lpszFileName
+= nDirLen1
;
263 LPCSTR p
= strchr(lpszFileName
, '/');
266 // no more dirs in pathname (ie we are in the dir the file is located)
270 // file status not determined yet, do it now
272 int err
= lstat(ce
->name
, &st
);
273 if (!process_ce_entry_status(ce
, err
? NULL
: &st
) || !IsStatusRelevantForDirs(l_nLastStatus
))
276 const int nFileStatus
= l_nLastStatus
;
278 if (nFileStatus
> dir
->nStatus
)
280 // update status on dir and all parents
283 if (nFileStatus
> dir
->nStatus
)
284 dir
->nStatus
= nFileStatus
;
286 while ( (dir
= dir
->parent
) );
289 else if (lpszFileName
!= p
) // quick check to make sure we're not left with a "/" filename
291 update_dirs_rec(lpszFileName
, (UINT
)(p
-lpszFileName
), ce
, bStatusCached
, dir
);
295 static void update_dirs(struct cache_entry
*ce
, int nPathNameOffset
, BOOL bStatusCached
)
297 // filename relative to enumerated path
298 LPCSTR lpszFileName
= ce
->name
+ nPathNameOffset
;
300 LPCSTR p
= strchr(lpszFileName
, '/');
301 if (p
<= lpszFileName
)
303 // file is not in sub-dir
307 // file status not determined yet, do it now
309 int err
= lstat(ce
->name
, &st
);
310 if (!process_ce_entry_status(ce
, err
? NULL
: &st
) || !IsStatusRelevantForDirs(l_nLastStatus
))
313 const int nFileStatus
= l_nLastStatus
;
315 if (nFileStatus
> l_dirTree
.nStatus
)
316 l_dirTree
.nStatus
= nFileStatus
;
321 if (!l_bNoRecurseDir
)
323 update_dirs_rec(lpszFileName
, (UINT
)(p
-lpszFileName
), ce
, bStatusCached
, &l_dirTree
);
328 static inline BOOL
is_subpath(const char *sPath
, int nPathLen
, const char *sFile
)
330 return strchr(sFile
+ nPathLen
, '/') != NULL
;
333 static BOOL
is_dir(const char *sProjectPath
, const char *sSubPath
)
337 strcpy(s
, sProjectPath
);
346 // make sure it ends with a slash
350 // backslashify sub-path
359 int err
= lstat(s
, &st
);
361 return (!err
&& S_ISDIR(st
.st_mode
));
364 static inline BOOL
is_ce_name_eq(struct cache_entry
*ce1
, struct cache_entry
*ce2
)
366 const size_t len1
= ce1
->ce_flags
& CE_NAMEMASK
;
367 const size_t len2
= ce2
->ce_flags
& CE_NAMEMASK
;
369 return (len1
== len2
) ? !strcmp(ce1
->name
, ce2
->name
) : FALSE
;
373 BOOL
ig_enum_files(const char *pszProjectPath
, const char *pszSubPath
, const char *prefix
, unsigned int nFlags
)
375 // reset all local vars of builtin-ls-files.c to default
385 line_terminator
= '\n';
400 //int exc_given = 0, require_work_tree = 0;
401 struct dir_struct _dir
;
403 memset(&_dir
, 0, sizeof(_dir
));
405 memset(&l_dirTree
, 0, sizeof(l_dirTree
));
406 l_dirTree
.nStatus
= WGFS_Normal
; // root dir is always at least WGFS_Normal even if empty
407 if (pszSubPath
&& !(nFlags
& WGEFF_EmptyAsNormal
))
408 l_dirTree
.nStatus
= WGFS_Empty
;
410 // NOTE: to force names to be relative to project root dir (no mater what current dir is) set prefix_offset to 0
412 prefix_offset
= strlen(prefix
);
413 git_config(git_default_config
, NULL
);
415 struct dir_struct
*dir
= &_dir
;
418 argv
[0] = pszSubPath
;
421 pathspec
= get_pathspec(prefix
, argv
);
423 // Verify that the pathspec matches the prefix
425 prefix
= verify_pathspec(prefix
);
427 // Treat unmatching pathspec elements as errors
428 if (pathspec
&& error_unmatch
)
431 for (num
= 0; pathspec
[num
]; num
++)
433 ps_matched
= xcalloc(1, num
);
436 // vars used for path recursion check
437 int pathspec_len
= 0;
438 if (pathspec
&& *pathspec
)
440 // calc length of pathspec plus 1 for a / (unless it already ends with a slash)
441 pathspec_len
= strlen(*pathspec
);
442 if ((*pathspec
)[pathspec_len
-1] != '/' && (*pathspec
)[pathspec_len
-1] != '\\')
445 const char *refpath
= (pathspec
&& *pathspec
) ? *pathspec
: "";
451 l_bNoRecurseDir
= FALSE
;
453 BOOL single_dir
= (nFlags
& WGEFF_SingleFile
) && (!pszSubPath
|| is_dir(pszProjectPath
, pszSubPath
));
454 // adjust other flags for best performance / correct results when WGEFF_SingleFile is set
455 if (single_dir
&& (nFlags
& WGEFF_NoRecurse
))
456 l_bNoRecurseDir
= TRUE
;
457 if (nFlags
& WGEFF_SingleFile
)
459 nFlags
|= WGEFF_NoRecurse
;
461 nFlags
&= ~(WGEFF_DirStatusAll
|WGEFF_DirStatusDelta
);
465 nFlags
= (nFlags
& ~WGEFF_DirStatusAll
) | WGEFF_DirStatusDelta
;
467 if ( !(nFlags
& WGEFF_EmptyAsNormal
) )
468 l_dirTree
.nStatus
= WGFS_Empty
;
471 BOOL no_recurse
= nFlags
& WGEFF_NoRecurse
;
472 l_bNoRecurse
= no_recurse
;
473 l_bFullPath
= nFlags
& WGEFF_FullPath
;
474 l_bDirStatus
= nFlags
& (WGEFF_DirStatusDelta
|WGEFF_DirStatusAll
);
476 // when all dirs should be enumerated we need IsStatusRelevantForDirs to report files of normal status as relevant
477 // otherwise only above normal are considered, which is slightly more efficient
478 l_nMinStatusRelevantForDirs
= (nFlags
& WGEFF_DirStatusAll
) ? WGFS_Normal
: (WGFS_Normal
+1);
480 // initial status of dirs
481 l_nEmptyDirStatus
= (nFlags
& WGEFF_EmptyAsNormal
) ? WGFS_Normal
: WGFS_Empty
;
483 l_bSkipNormalDirs
= ((nFlags
& (WGEFF_DirStatusDelta
|WGEFF_DirStatusAll
)) == WGEFF_DirStatusDelta
);
486 l_lpszFileName
= NULL
;
489 strcpy(l_sFullPathBuf
, pszProjectPath
);
491 LPSTR q
= l_sFullPathBuf
;
498 // make sure it ends with a slash
504 // save pointer to where file paths, with project-relative names, can be concatenated
508 // shouldn't have any effect but set them to reflect what we want listed
518 //if (pathspec && *pathspec) OutputDebugString(*pathspec);OutputDebugString(" (1)\r\n");
519 //if (prefix) OutputDebugString(prefix);OutputDebugString(" (2)\r\n");
525 for (i
=0; i
<active_nr
; i
++)
527 struct cache_entry
*ce
= active_cache
[i
];
531 int dtype
= ce_to_dtype(ce
);
533 if (excluded(dir
, ce
->name
, &dtype
) != dir
->show_ignored
)
535 if (ce
->ce_flags
& CE_UPDATE
)
538 // skip file if not inside specified sub-path
539 // this test was originally done in enum_ce_entry but in order to avoid unecessery lstat calls it was moved
540 if (prefix_len
>= ce_namelen(ce
))
541 die("git ls-files: internal error - cache entry not superset of prefix");
542 if (pathspec
&& !pathspec_match(pathspec
, ps_matched
, ce
->name
, prefix_len
))
545 if (single_dir
|| (no_recurse
&& is_subpath(refpath
, pathspec_len
, ce
->name
)))
548 // this file would normally be skipped, but in order to determine correct dir status we need to process it
549 update_dirs(ce
, pathspec_len
, FALSE
);
554 err
= lstat(ce
->name
, &st
);
556 if ( enum_ce_entry(ce
, err
? NULL
: &st
) )
559 // normally (always?) conflicted/unmerged files will have 3 entries in a row (one in stage 1, one in 2 and one in 3)
560 // skip redundant entries here
565 for (j
=i
+1; j
<active_nr
; j
++)
567 struct cache_entry
*nextce
= active_cache
[j
];
569 if ( !is_ce_name_eq(ce
, nextce
) )
576 if (l_bDirStatus
&& IsStatusRelevantForDirs(l_nLastStatus
))
577 update_dirs(ce
, pathspec_len
, TRUE
);
584 LPCSTR lpszRootDir
="/";
587 lpszRootDir
= l_sFullPathBuf
;
590 strcpy(l_lpszFileName
, *pathspec
);
591 l_lpszFileName
+= pathspec_len
;
595 // remove trailng slash
596 l_lpszFileName
[-1] = 0;
598 else if (pathspec_len
)
600 lpszRootDir
= *pathspec
;
602 strcpy(l_sFullPathBuf
, *pathspec
);
603 l_sFullPathBuf
[pathspec_len
-1] = '/';
604 l_sFullPathBuf
[pathspec_len
] = 0;
605 l_lpszFileName
= l_sFullPathBuf
;
611 l_lpszFileName
= l_sFullPathBuf
;
616 // enumerate single dir
617 l_bSkipNormalDirs
= FALSE
;
618 enum_dir(&l_dirTree
, lpszRootDir
);
620 else if (!enum_dir(&l_dirTree
, lpszRootDir
) && l_dirTree
.children
)
623 // re-add trailing slash
624 l_lpszFileName
[-1] = '/';
626 struct DirStatus
*p
= l_dirTree
.children
;
630 if ( enum_dirs(p
, l_lpszFileName
) )
633 while ( (p
= p
->next
) );
644 * This merges the file listing in the directory cache index
645 * with the actual working directory list, and shows different
646 * combinations of the two.
648 * Copyright (C) Linus Torvalds, 2005
657 static int show_deleted
;
658 static int show_cached
;
659 static int show_others
;
660 static int show_stage
;
661 static int show_unmerged
;
662 static int show_modified
;
663 static int show_killed
;
664 static int show_valid_bit
;
665 static int line_terminator
= '\n';
667 static int prefix_len
;
668 static int prefix_offset
;
669 static const char **pathspec
;
670 static int error_unmatch
;
671 static char *ps_matched
;
672 static const char *with_tree
;
674 static const char *tag_cached
= "";
675 static const char *tag_unmerged
= "";
676 static const char *tag_removed
= "";
677 static const char *tag_other
= "";
678 static const char *tag_killed
= "";
679 static const char *tag_modified
= "";
683 * Match a pathspec against a filename. The first "skiplen" characters
684 * are the common prefix
686 int pathspec_match(const char **spec
, char *ps_matched
,
687 const char *filename
, int skiplen
)
691 while ((m
= *spec
++) != NULL
) {
692 int matchlen
= strlen(m
+ skiplen
);
696 if (!strncmp(m
+ skiplen
, filename
+ skiplen
, matchlen
)) {
697 if (m
[skiplen
+ matchlen
- 1] == '/')
699 switch (filename
[skiplen
+ matchlen
]) {
704 if (!fnmatch(m
+ skiplen
, filename
+ skiplen
, 0))
717 static void show_dir_entry(const char *tag
, struct dir_entry
*ent
)
719 int len
= prefix_len
;
720 int offset
= prefix_offset
;
723 die("git ls-files: internal error - directory entry not superset of prefix");
725 if (pathspec
&& !pathspec_match(pathspec
, ps_matched
, ent
->name
, len
))
729 write_name_quoted(ent
->name
+ offset
, stdout
, line_terminator
);
732 static void show_other_files(struct dir_struct
*dir
)
736 for (i
= 0; i
< dir
->nr
; i
++) {
737 struct dir_entry
*ent
= dir
->entries
[i
];
738 if (!cache_name_is_other(ent
->name
, ent
->len
))
740 show_dir_entry(tag_other
, ent
);
744 static void show_killed_files(struct dir_struct
*dir
)
747 for (i
= 0; i
< dir
->nr
; i
++) {
748 struct dir_entry
*ent
= dir
->entries
[i
];
750 int pos
, len
, killed
= 0;
752 for (cp
= ent
->name
; cp
- ent
->name
< ent
->len
; cp
= sp
+ 1) {
753 sp
= strchr(cp
, '/');
755 /* If ent->name is prefix of an entry in the
756 * cache, it will be killed.
758 pos
= cache_name_pos(ent
->name
, ent
->len
);
760 die("bug in show-killed-files");
762 while (pos
< active_nr
&&
763 ce_stage(active_cache
[pos
]))
764 pos
++; /* skip unmerged */
765 if (active_nr
<= pos
)
767 /* pos points at a name immediately after
768 * ent->name in the cache. Does it expect
769 * ent->name to be a directory?
771 len
= ce_namelen(active_cache
[pos
]);
772 if ((ent
->len
< len
) &&
773 !strncmp(active_cache
[pos
]->name
,
774 ent
->name
, ent
->len
) &&
775 active_cache
[pos
]->name
[ent
->len
] == '/')
779 if (0 <= cache_name_pos(ent
->name
, sp
- ent
->name
)) {
780 /* If any of the leading directories in
781 * ent->name is registered in the cache,
782 * ent->name will be killed.
789 show_dir_entry(tag_killed
, dir
->entries
[i
]);
793 static void show_ce_entry(const char *tag
, struct cache_entry
*ce
)
795 int len
= prefix_len
;
796 int offset
= prefix_offset
;
798 if (len
>= ce_namelen(ce
))
799 die("git ls-files: internal error - cache entry not superset of prefix");
801 if (pathspec
&& !pathspec_match(pathspec
, ps_matched
, ce
->name
, len
))
804 if (tag
&& *tag
&& show_valid_bit
&&
805 (ce
->ce_flags
& CE_VALID
)) {
806 static char alttag
[4];
807 memcpy(alttag
, tag
, 3);
809 alttag
[0] = tolower(tag
[0]);
810 else if (tag
[0] == '?')
824 printf("%s%06o %s %d\t",
827 abbrev
? find_unique_abbrev(ce
->sha1
,abbrev
)
828 : sha1_to_hex(ce
->sha1
),
831 write_name_quoted(ce
->name
+ offset
, stdout
, line_terminator
);
834 static void show_files(struct dir_struct
*dir
, const char *prefix
)
838 /* For cached/deleted files we don't need to even do the readdir */
839 if (show_others
|| show_killed
) {
840 const char *path
= ".", *base
= "";
841 int baselen
= prefix_len
;
844 path
= base
= prefix
;
845 read_directory(dir
, path
, base
, baselen
, pathspec
);
847 show_other_files(dir
);
849 show_killed_files(dir
);
851 if (show_cached
| show_stage
) {
852 for (i
= 0; i
< active_nr
; i
++) {
853 struct cache_entry
*ce
= active_cache
[i
];
854 int dtype
= ce_to_dtype(ce
);
855 if (excluded(dir
, ce
->name
, &dtype
) != dir
->show_ignored
)
857 if (show_unmerged
&& !ce_stage(ce
))
859 if (ce
->ce_flags
& CE_UPDATE
)
861 show_ce_entry(ce_stage(ce
) ? tag_unmerged
: tag_cached
, ce
);
864 if (show_deleted
| show_modified
) {
865 for (i
= 0; i
< active_nr
; i
++) {
866 struct cache_entry
*ce
= active_cache
[i
];
869 int dtype
= ce_to_dtype(ce
);
870 if (excluded(dir
, ce
->name
, &dtype
) != dir
->show_ignored
)
872 if (ce
->ce_flags
& CE_UPDATE
)
874 err
= lstat(ce
->name
, &st
);
875 if (show_deleted
&& err
)
876 show_ce_entry(tag_removed
, ce
);
877 if (show_modified
&& ce_modified(ce
, &st
, 0))
878 show_ce_entry(tag_modified
, ce
);
884 * Prune the index to only contain stuff starting with "prefix"
886 static void prune_cache(const char *prefix
)
888 int pos
= cache_name_pos(prefix
, prefix_len
);
889 unsigned int first
, last
;
893 memmove(active_cache
, active_cache
+ pos
,
894 (active_nr
- pos
) * sizeof(struct cache_entry
*));
898 while (last
> first
) {
899 int next
= (last
+ first
) >> 1;
900 struct cache_entry
*ce
= active_cache
[next
];
901 if (!strncmp(ce
->name
, prefix
, prefix_len
)) {
910 static const char *verify_pathspec(const char *prefix
)
912 const char **p
, *n
, *prev
;
917 for (p
= pathspec
; (n
= *p
) != NULL
; p
++) {
919 for (i
= 0; i
< max
; i
++) {
921 if (prev
&& prev
[i
] != c
)
923 if (!c
|| c
== '*' || c
== '?')
936 if (prefix_offset
> max
|| memcmp(prev
, prefix
, prefix_offset
))
937 die("git ls-files: cannot generate relative filenames containing '..'");
940 return max
? xmemdupz(prev
, max
) : NULL
;
944 * Read the tree specified with --with-tree option
945 * (typically, HEAD) into stage #1 and then
946 * squash them down to stage #0. This is used for
947 * --error-unmatch to list and check the path patterns
948 * that were given from the command line. We are not
949 * going to write this index out.
951 void overlay_tree_on_cache(const char *tree_name
, const char *prefix
)
954 unsigned char sha1
[20];
956 struct cache_entry
*last_stage0
= NULL
;
959 if (get_sha1(tree_name
, sha1
))
960 die("tree-ish %s not found.", tree_name
);
961 tree
= parse_tree_indirect(sha1
);
963 die("bad tree-ish %s", tree_name
);
965 /* Hoist the unmerged entries up to stage #3 to make room */
966 for (i
= 0; i
< active_nr
; i
++) {
967 struct cache_entry
*ce
= active_cache
[i
];
970 ce
->ce_flags
|= CE_STAGEMASK
;
974 static const char *(matchbuf
[2]);
975 matchbuf
[0] = prefix
;
980 if (read_tree(tree
, 1, match
))
981 die("unable to read tree entries %s", tree_name
);
983 for (i
= 0; i
< active_nr
; i
++) {
984 struct cache_entry
*ce
= active_cache
[i
];
985 switch (ce_stage(ce
)) {
993 * If there is stage #0 entry for this, we do not
994 * need to show it. We use CE_UPDATE bit to mark
998 !strcmp(last_stage0
->name
, ce
->name
))
999 ce
->ce_flags
|= CE_UPDATE
;
1004 int report_path_error(const char *ps_matched
, const char **pathspec
, int prefix_offset
)
1007 * Make sure all pathspec matched; otherwise it is an error.
1009 int num
, errors
= 0;
1010 for (num
= 0; pathspec
[num
]; num
++) {
1011 int other
, found_dup
;
1013 if (ps_matched
[num
])
1016 * The caller might have fed identical pathspec
1017 * twice. Do not barf on such a mistake.
1019 for (found_dup
= other
= 0;
1020 !found_dup
&& pathspec
[other
];
1022 if (other
== num
|| !ps_matched
[other
])
1024 if (!strcmp(pathspec
[other
], pathspec
[num
]))
1026 * Ok, we have a match already.
1033 error("pathspec '%s' did not match any file(s) known to git.",
1034 pathspec
[num
] + prefix_offset
);
1040 static const char ls_files_usage
[] =
1041 "git ls-files [-z] [-t] [-v] (--[cached|deleted|others|stage|unmerged|killed|modified])* "
1042 "[ --ignored ] [--exclude=<pattern>] [--exclude-from=<file>] "
1043 "[ --exclude-per-directory=<filename> ] [--exclude-standard] "
1044 "[--full-name] [--abbrev] [--] [<file>]*";
1046 int cmd_ls_files(int argc
, const char **argv
, const char *prefix
)
1049 int exc_given
= 0, require_work_tree
= 0;
1050 struct dir_struct dir
;
1052 memset(&dir
, 0, sizeof(dir
));
1054 prefix_offset
= strlen(prefix
);
1055 git_config(git_default_config
, NULL
);
1057 for (i
= 1; i
< argc
; i
++) {
1058 const char *arg
= argv
[i
];
1060 if (!strcmp(arg
, "--")) {
1064 if (!strcmp(arg
, "-z")) {
1065 line_terminator
= 0;
1068 if (!strcmp(arg
, "-t") || !strcmp(arg
, "-v")) {
1070 tag_unmerged
= "M ";
1072 tag_modified
= "C ";
1079 if (!strcmp(arg
, "-c") || !strcmp(arg
, "--cached")) {
1083 if (!strcmp(arg
, "-d") || !strcmp(arg
, "--deleted")) {
1087 if (!strcmp(arg
, "-m") || !strcmp(arg
, "--modified")) {
1089 require_work_tree
= 1;
1092 if (!strcmp(arg
, "-o") || !strcmp(arg
, "--others")) {
1094 require_work_tree
= 1;
1097 if (!strcmp(arg
, "-i") || !strcmp(arg
, "--ignored")) {
1098 dir
.show_ignored
= 1;
1099 require_work_tree
= 1;
1102 if (!strcmp(arg
, "-s") || !strcmp(arg
, "--stage")) {
1106 if (!strcmp(arg
, "-k") || !strcmp(arg
, "--killed")) {
1108 require_work_tree
= 1;
1111 if (!strcmp(arg
, "--directory")) {
1112 dir
.show_other_directories
= 1;
1115 if (!strcmp(arg
, "--no-empty-directory")) {
1116 dir
.hide_empty_directories
= 1;
1119 if (!strcmp(arg
, "-u") || !strcmp(arg
, "--unmerged")) {
1120 /* There's no point in showing unmerged unless
1121 * you also show the stage information.
1127 if (!strcmp(arg
, "-x") && i
+1 < argc
) {
1129 add_exclude(argv
[++i
], "", 0, &dir
.exclude_list
[EXC_CMDL
]);
1132 if (!prefixcmp(arg
, "--exclude=")) {
1134 add_exclude(arg
+10, "", 0, &dir
.exclude_list
[EXC_CMDL
]);
1137 if (!strcmp(arg
, "-X") && i
+1 < argc
) {
1139 add_excludes_from_file(&dir
, argv
[++i
]);
1142 if (!prefixcmp(arg
, "--exclude-from=")) {
1144 add_excludes_from_file(&dir
, arg
+15);
1147 if (!prefixcmp(arg
, "--exclude-per-directory=")) {
1149 dir
.exclude_per_dir
= arg
+ 24;
1152 if (!strcmp(arg
, "--exclude-standard")) {
1154 setup_standard_excludes(&dir
);
1157 if (!strcmp(arg
, "--full-name")) {
1161 if (!strcmp(arg
, "--error-unmatch")) {
1165 if (!prefixcmp(arg
, "--with-tree=")) {
1166 with_tree
= arg
+ 12;
1169 if (!prefixcmp(arg
, "--abbrev=")) {
1170 abbrev
= strtoul(arg
+9, NULL
, 10);
1171 if (abbrev
&& abbrev
< MINIMUM_ABBREV
)
1172 abbrev
= MINIMUM_ABBREV
;
1173 else if (abbrev
> 40)
1177 if (!strcmp(arg
, "--abbrev")) {
1178 abbrev
= DEFAULT_ABBREV
;
1182 usage(ls_files_usage
);
1186 if (require_work_tree
&& !is_inside_work_tree())
1189 pathspec
= get_pathspec(prefix
, argv
+ i
);
1191 /* Verify that the pathspec matches the prefix */
1193 prefix
= verify_pathspec(prefix
);
1195 /* Treat unmatching pathspec elements as errors */
1196 if (pathspec
&& error_unmatch
) {
1198 for (num
= 0; pathspec
[num
]; num
++)
1200 ps_matched
= xcalloc(1, num
);
1203 if (dir
.show_ignored
&& !exc_given
) {
1204 fprintf(stderr
, "%s: --ignored needs some exclude pattern\n",
1209 /* With no flags, we default to showing the cached files */
1210 if (!(show_stage
| show_deleted
| show_others
| show_unmerged
|
1211 show_killed
| show_modified
))
1216 prune_cache(prefix
);
1219 * Basic sanity check; show-stages and show-unmerged
1220 * would not make any sense with this option.
1222 if (show_stage
|| show_unmerged
)
1223 die("ls-files --with-tree is incompatible with -s or -u");
1224 overlay_tree_on_cache(with_tree
, prefix
);
1226 show_files(&dir
, prefix
);
1230 bad
= report_path_error(ps_matched
, pathspec
, prefix_offset
);
1232 fprintf(stderr
, "Did you forget to 'git add'?\n");