22 * This handles recursive filename detection with exclude
33 * files, index knowledge etc..
44 *
5+ * See Documentation/technical/api-directory-listing.txt
6+ *
57 * Copyright (C) Linus Torvalds, 2005-2006
68 * Junio Hamano, 2005-2006
79 */
@@ -377,7 +379,7 @@ void parse_exclude_pattern(const char **pattern,
377379}
378380
379381void add_exclude (const char * string , const char * base ,
380- int baselen , struct exclude_list * which )
382+ int baselen , struct exclude_list * el )
381383{
382384 struct exclude * x ;
383385 int patternlen ;
@@ -401,8 +403,8 @@ void add_exclude(const char *string, const char *base,
401403 x -> base = base ;
402404 x -> baselen = baselen ;
403405 x -> flags = flags ;
404- ALLOC_GROW (which -> excludes , which -> nr + 1 , which -> alloc );
405- which -> excludes [which -> nr ++ ] = x ;
406+ ALLOC_GROW (el -> excludes , el -> nr + 1 , el -> alloc );
407+ el -> excludes [el -> nr ++ ] = x ;
406408}
407409
408410static void * read_skip_worktree_file_from_index (const char * path , size_t * size )
@@ -428,7 +430,11 @@ static void *read_skip_worktree_file_from_index(const char *path, size_t *size)
428430 return data ;
429431}
430432
431- void free_excludes (struct exclude_list * el )
433+ /*
434+ * Frees memory within el which was allocated for exclude patterns and
435+ * the file buffer. Does not free el itself.
436+ */
437+ void clear_exclude_list (struct exclude_list * el )
432438{
433439 int i ;
434440
@@ -444,7 +450,7 @@ int add_excludes_from_file_to_list(const char *fname,
444450 const char * base ,
445451 int baselen ,
446452 char * * buf_p ,
447- struct exclude_list * which ,
453+ struct exclude_list * el ,
448454 int check_index )
449455{
450456 struct stat st ;
@@ -493,7 +499,7 @@ int add_excludes_from_file_to_list(const char *fname,
493499 if (buf [i ] == '\n' ) {
494500 if (entry != buf + i && entry [0 ] != '#' ) {
495501 buf [i - (i && buf [i - 1 ] == '\r' )] = 0 ;
496- add_exclude (entry , base , baselen , which );
502+ add_exclude (entry , base , baselen , el );
497503 }
498504 entry = buf + i + 1 ;
499505 }
@@ -508,6 +514,10 @@ void add_excludes_from_file(struct dir_struct *dir, const char *fname)
508514 die ("cannot use %s as an exclude file" , fname );
509515}
510516
517+ /*
518+ * Loads the per-directory exclude list for the substring of base
519+ * which has a char length of baselen.
520+ */
511521static void prep_exclude (struct dir_struct * dir , const char * base , int baselen )
512522{
513523 struct exclude_list * el ;
@@ -518,7 +528,7 @@ static void prep_exclude(struct dir_struct *dir, const char *base, int baselen)
518528 (baselen + strlen (dir -> exclude_per_dir ) >= PATH_MAX ))
519529 return ; /* too long a path -- ignore */
520530
521- /* Pop the ones that are not the prefix of the path being checked. */
531+ /* Pop the directories that are not the prefix of the path being checked. */
522532 el = & dir -> exclude_list [EXC_DIRS ];
523533 while ((stk = dir -> exclude_stack ) != NULL ) {
524534 if (stk -> baselen <= baselen &&
@@ -629,22 +639,26 @@ int match_pathname(const char *pathname, int pathlen,
629639 ignore_case ? FNM_CASEFOLD : 0 ) == 0 ;
630640}
631641
632- /* Scan the list and let the last match determine the fate.
633- * Return 1 for exclude, 0 for include and -1 for undecided.
642+ /*
643+ * Scan the given exclude list in reverse to see whether pathname
644+ * should be ignored. The first match (i.e. the last on the list), if
645+ * any, determines the fate. Returns the exclude_list element which
646+ * matched, or NULL for undecided.
634647 */
635- int excluded_from_list (const char * pathname ,
636- int pathlen , const char * basename , int * dtype ,
637- struct exclude_list * el )
648+ static struct exclude * last_exclude_matching_from_list (const char * pathname ,
649+ int pathlen ,
650+ const char * basename ,
651+ int * dtype ,
652+ struct exclude_list * el )
638653{
639654 int i ;
640655
641656 if (!el -> nr )
642- return -1 ; /* undefined */
657+ return NULL ; /* undefined */
643658
644659 for (i = el -> nr - 1 ; 0 <= i ; i -- ) {
645660 struct exclude * x = el -> excludes [i ];
646661 const char * exclude = x -> pattern ;
647- int to_exclude = x -> flags & EXC_FLAG_NEGATIVE ? 0 : 1 ;
648662 int prefix = x -> nowildcardlen ;
649663
650664 if (x -> flags & EXC_FLAG_MUSTBEDIR ) {
@@ -659,43 +673,80 @@ int excluded_from_list(const char *pathname,
659673 pathlen - (basename - pathname ),
660674 exclude , prefix , x -> patternlen ,
661675 x -> flags ))
662- return to_exclude ;
676+ return x ;
663677 continue ;
664678 }
665679
666680 assert (x -> baselen == 0 || x -> base [x -> baselen - 1 ] == '/' );
667681 if (match_pathname (pathname , pathlen ,
668682 x -> base , x -> baselen ? x -> baselen - 1 : 0 ,
669683 exclude , prefix , x -> patternlen , x -> flags ))
670- return to_exclude ;
684+ return x ;
671685 }
686+ return NULL ; /* undecided */
687+ }
688+
689+ /*
690+ * Scan the list and let the last match determine the fate.
691+ * Return 1 for exclude, 0 for include and -1 for undecided.
692+ */
693+ int is_excluded_from_list (const char * pathname ,
694+ int pathlen , const char * basename , int * dtype ,
695+ struct exclude_list * el )
696+ {
697+ struct exclude * exclude ;
698+ exclude = last_exclude_matching_from_list (pathname , pathlen , basename , dtype , el );
699+ if (exclude )
700+ return exclude -> flags & EXC_FLAG_NEGATIVE ? 0 : 1 ;
672701 return -1 ; /* undecided */
673702}
674703
675- static int excluded (struct dir_struct * dir , const char * pathname , int * dtype_p )
704+ /*
705+ * Loads the exclude lists for the directory containing pathname, then
706+ * scans all exclude lists to determine whether pathname is excluded.
707+ * Returns the exclude_list element which matched, or NULL for
708+ * undecided.
709+ */
710+ static struct exclude * last_exclude_matching (struct dir_struct * dir ,
711+ const char * pathname ,
712+ int * dtype_p )
676713{
677714 int pathlen = strlen (pathname );
678715 int st ;
716+ struct exclude * exclude ;
679717 const char * basename = strrchr (pathname , '/' );
680718 basename = (basename ) ? basename + 1 : pathname ;
681719
682720 prep_exclude (dir , pathname , basename - pathname );
683721 for (st = EXC_CMDL ; st <= EXC_FILE ; st ++ ) {
684- switch (excluded_from_list (pathname , pathlen , basename ,
685- dtype_p , & dir -> exclude_list [st ])) {
686- case 0 :
687- return 0 ;
688- case 1 :
689- return 1 ;
690- }
722+ exclude = last_exclude_matching_from_list (
723+ pathname , pathlen , basename , dtype_p ,
724+ & dir -> exclude_list [st ]);
725+ if (exclude )
726+ return exclude ;
691727 }
728+ return NULL ;
729+ }
730+
731+ /*
732+ * Loads the exclude lists for the directory containing pathname, then
733+ * scans all exclude lists to determine whether pathname is excluded.
734+ * Returns 1 if true, otherwise 0.
735+ */
736+ static int is_excluded (struct dir_struct * dir , const char * pathname , int * dtype_p )
737+ {
738+ struct exclude * exclude =
739+ last_exclude_matching (dir , pathname , dtype_p );
740+ if (exclude )
741+ return exclude -> flags & EXC_FLAG_NEGATIVE ? 0 : 1 ;
692742 return 0 ;
693743}
694744
695745void path_exclude_check_init (struct path_exclude_check * check ,
696746 struct dir_struct * dir )
697747{
698748 check -> dir = dir ;
749+ check -> exclude = NULL ;
699750 strbuf_init (& check -> path , 256 );
700751}
701752
@@ -705,49 +756,77 @@ void path_exclude_check_clear(struct path_exclude_check *check)
705756}
706757
707758/*
708- * Is this name excluded? This is for a caller like show_files() that
709- * do not honor directory hierarchy and iterate through paths that are
710- * possibly in an ignored directory.
759+ * For each subdirectory in name, starting with the top-most, checks
760+ * to see if that subdirectory is excluded, and if so, returns the
761+ * corresponding exclude structure. Otherwise, checks whether name
762+ * itself (which is presumably a file) is excluded.
711763 *
712764 * A path to a directory known to be excluded is left in check->path to
713765 * optimize for repeated checks for files in the same excluded directory.
714766 */
715- int path_excluded (struct path_exclude_check * check ,
716- const char * name , int namelen , int * dtype )
767+ struct exclude * last_exclude_matching_path (struct path_exclude_check * check ,
768+ const char * name , int namelen ,
769+ int * dtype )
717770{
718771 int i ;
719772 struct strbuf * path = & check -> path ;
773+ struct exclude * exclude ;
720774
721775 /*
722776 * we allow the caller to pass namelen as an optimization; it
723777 * must match the length of the name, as we eventually call
724- * excluded () on the whole name string.
778+ * is_excluded () on the whole name string.
725779 */
726780 if (namelen < 0 )
727781 namelen = strlen (name );
728782
783+ /*
784+ * If path is non-empty, and name is equal to path or a
785+ * subdirectory of path, name should be excluded, because
786+ * it's inside a directory which is already known to be
787+ * excluded and was previously left in check->path.
788+ */
729789 if (path -> len &&
730790 path -> len <= namelen &&
731791 !memcmp (name , path -> buf , path -> len ) &&
732792 (!name [path -> len ] || name [path -> len ] == '/' ))
733- return 1 ;
793+ return check -> exclude ;
734794
735795 strbuf_setlen (path , 0 );
736796 for (i = 0 ; name [i ]; i ++ ) {
737797 int ch = name [i ];
738798
739799 if (ch == '/' ) {
740800 int dt = DT_DIR ;
741- if (excluded (check -> dir , path -> buf , & dt ))
742- return 1 ;
801+ exclude = last_exclude_matching (check -> dir ,
802+ path -> buf , & dt );
803+ if (exclude ) {
804+ check -> exclude = exclude ;
805+ return exclude ;
806+ }
743807 }
744808 strbuf_addch (path , ch );
745809 }
746810
747811 /* An entry in the index; cannot be a directory with subentries */
748812 strbuf_setlen (path , 0 );
749813
750- return excluded (check -> dir , name , dtype );
814+ return last_exclude_matching (check -> dir , name , dtype );
815+ }
816+
817+ /*
818+ * Is this name excluded? This is for a caller like show_files() that
819+ * do not honor directory hierarchy and iterate through paths that are
820+ * possibly in an ignored directory.
821+ */
822+ int is_path_excluded (struct path_exclude_check * check ,
823+ const char * name , int namelen , int * dtype )
824+ {
825+ struct exclude * exclude =
826+ last_exclude_matching_path (check , name , namelen , dtype );
827+ if (exclude )
828+ return exclude -> flags & EXC_FLAG_NEGATIVE ? 0 : 1 ;
829+ return 0 ;
751830}
752831
753832static struct dir_entry * dir_entry_new (const char * pathname , int len )
@@ -1047,7 +1126,7 @@ static enum path_treatment treat_one_path(struct dir_struct *dir,
10471126 const struct path_simplify * simplify ,
10481127 int dtype , struct dirent * de )
10491128{
1050- int exclude = excluded (dir , path -> buf , & dtype );
1129+ int exclude = is_excluded (dir , path -> buf , & dtype );
10511130 if (exclude && (dir -> flags & DIR_COLLECT_IGNORED )
10521131 && exclude_matches_pathspec (path -> buf , path -> len , simplify ))
10531132 dir_add_ignored (dir , path -> buf , path -> len );
0 commit comments