@@ -126,10 +126,13 @@ static size_t common_prefix_len(const struct pathspec *pathspec)
126126 PATHSPEC_MAXDEPTH |
127127 PATHSPEC_LITERAL |
128128 PATHSPEC_GLOB |
129- PATHSPEC_ICASE );
129+ PATHSPEC_ICASE |
130+ PATHSPEC_EXCLUDE );
130131
131132 for (n = 0 ; n < pathspec -> nr ; n ++ ) {
132133 size_t i = 0 , len = 0 , item_len ;
134+ if (pathspec -> items [n ].magic & PATHSPEC_EXCLUDE )
135+ continue ;
133136 if (pathspec -> items [n ].magic & PATHSPEC_ICASE )
134137 item_len = pathspec -> items [n ].prefix ;
135138 else
@@ -279,9 +282,10 @@ static int match_pathspec_item(const struct pathspec_item *item, int prefix,
279282 * pathspec did not match any names, which could indicate that the
280283 * user mistyped the nth pathspec.
281284 */
282- int match_pathspec_depth (const struct pathspec * ps ,
283- const char * name , int namelen ,
284- int prefix , char * seen )
285+ static int match_pathspec_depth_1 (const struct pathspec * ps ,
286+ const char * name , int namelen ,
287+ int prefix , char * seen ,
288+ int exclude )
285289{
286290 int i , retval = 0 ;
287291
@@ -290,7 +294,8 @@ int match_pathspec_depth(const struct pathspec *ps,
290294 PATHSPEC_MAXDEPTH |
291295 PATHSPEC_LITERAL |
292296 PATHSPEC_GLOB |
293- PATHSPEC_ICASE );
297+ PATHSPEC_ICASE |
298+ PATHSPEC_EXCLUDE );
294299
295300 if (!ps -> nr ) {
296301 if (!ps -> recursive ||
@@ -309,8 +314,19 @@ int match_pathspec_depth(const struct pathspec *ps,
309314
310315 for (i = ps -> nr - 1 ; i >= 0 ; i -- ) {
311316 int how ;
317+
318+ if ((!exclude && ps -> items [i ].magic & PATHSPEC_EXCLUDE ) ||
319+ ( exclude && !(ps -> items [i ].magic & PATHSPEC_EXCLUDE )))
320+ continue ;
321+
312322 if (seen && seen [i ] == MATCHED_EXACTLY )
313323 continue ;
324+ /*
325+ * Make exclude patterns optional and never report
326+ * "pathspec ':(exclude)foo' matches no files"
327+ */
328+ if (seen && ps -> items [i ].magic & PATHSPEC_EXCLUDE )
329+ seen [i ] = MATCHED_FNMATCH ;
314330 how = match_pathspec_item (ps -> items + i , prefix , name , namelen );
315331 if (ps -> recursive &&
316332 (ps -> magic & PATHSPEC_MAXDEPTH ) &&
@@ -334,6 +350,18 @@ int match_pathspec_depth(const struct pathspec *ps,
334350 return retval ;
335351}
336352
353+ int match_pathspec_depth (const struct pathspec * ps ,
354+ const char * name , int namelen ,
355+ int prefix , char * seen )
356+ {
357+ int positive , negative ;
358+ positive = match_pathspec_depth_1 (ps , name , namelen , prefix , seen , 0 );
359+ if (!(ps -> magic & PATHSPEC_EXCLUDE ) || !positive )
360+ return positive ;
361+ negative = match_pathspec_depth_1 (ps , name , namelen , prefix , seen , 1 );
362+ return negative ? 0 : positive ;
363+ }
364+
337365/*
338366 * Return the length of the "simple" part of a path match limiter.
339367 */
@@ -1375,11 +1403,18 @@ int read_directory(struct dir_struct *dir, const char *path, int len, const stru
13751403 PATHSPEC_MAXDEPTH |
13761404 PATHSPEC_LITERAL |
13771405 PATHSPEC_GLOB |
1378- PATHSPEC_ICASE );
1406+ PATHSPEC_ICASE |
1407+ PATHSPEC_EXCLUDE );
13791408
13801409 if (has_symlink_leading_path (path , len ))
13811410 return dir -> nr ;
13821411
1412+ /*
1413+ * exclude patterns are treated like positive ones in
1414+ * create_simplify. Usually exclude patterns should be a
1415+ * subset of positive ones, which has no impacts on
1416+ * create_simplify().
1417+ */
13831418 simplify = create_simplify (pathspec ? pathspec -> _raw : NULL );
13841419 if (!len || treat_leading_path (dir , path , len , simplify ))
13851420 read_directory_recursive (dir , path , len , 0 , simplify );
0 commit comments