@@ -32,7 +32,7 @@ enum path_treatment {
32
32
};
33
33
34
34
static enum path_treatment read_directory_recursive (struct dir_struct * dir ,
35
- const char * path , int len ,
35
+ const char * path , int len , struct untracked_cache_dir * untracked ,
36
36
int check_only , const struct path_simplify * simplify );
37
37
static int get_dtype (struct dirent * de , const char * path , int len );
38
38
@@ -534,6 +534,54 @@ static void trim_trailing_spaces(char *buf)
534
534
* last_space = '\0' ;
535
535
}
536
536
537
+ /*
538
+ * Given a subdirectory name and "dir" of the current directory,
539
+ * search the subdir in "dir" and return it, or create a new one if it
540
+ * does not exist in "dir".
541
+ *
542
+ * If "name" has the trailing slash, it'll be excluded in the search.
543
+ */
544
+ static struct untracked_cache_dir * lookup_untracked (struct untracked_cache * uc ,
545
+ struct untracked_cache_dir * dir ,
546
+ const char * name , int len )
547
+ {
548
+ int first , last ;
549
+ struct untracked_cache_dir * d ;
550
+ if (!dir )
551
+ return NULL ;
552
+ if (len && name [len - 1 ] == '/' )
553
+ len -- ;
554
+ first = 0 ;
555
+ last = dir -> dirs_nr ;
556
+ while (last > first ) {
557
+ int cmp , next = (last + first ) >> 1 ;
558
+ d = dir -> dirs [next ];
559
+ cmp = strncmp (name , d -> name , len );
560
+ if (!cmp && strlen (d -> name ) > len )
561
+ cmp = -1 ;
562
+ if (!cmp )
563
+ return d ;
564
+ if (cmp < 0 ) {
565
+ last = next ;
566
+ continue ;
567
+ }
568
+ first = next + 1 ;
569
+ }
570
+
571
+ uc -> dir_created ++ ;
572
+ d = xmalloc (sizeof (* d ) + len + 1 );
573
+ memset (d , 0 , sizeof (* d ));
574
+ memcpy (d -> name , name , len );
575
+ d -> name [len ] = '\0' ;
576
+
577
+ ALLOC_GROW (dir -> dirs , dir -> dirs_nr + 1 , dir -> dirs_alloc );
578
+ memmove (dir -> dirs + first + 1 , dir -> dirs + first ,
579
+ (dir -> dirs_nr - first ) * sizeof (* dir -> dirs ));
580
+ dir -> dirs_nr ++ ;
581
+ dir -> dirs [first ] = d ;
582
+ return d ;
583
+ }
584
+
537
585
/*
538
586
* Given a file with name "fname", read it (either from disk, or from
539
587
* the index if "check_index" is non-zero), parse it and store the
@@ -646,14 +694,20 @@ struct exclude_list *add_exclude_list(struct dir_struct *dir,
646
694
/*
647
695
* Used to set up core.excludesfile and .git/info/exclude lists.
648
696
*/
649
- void add_excludes_from_file (struct dir_struct * dir , const char * fname )
697
+ static void add_excludes_from_file_1 (struct dir_struct * dir , const char * fname ,
698
+ struct sha1_stat * sha1_stat )
650
699
{
651
700
struct exclude_list * el ;
652
701
el = add_exclude_list (dir , EXC_FILE , fname );
653
- if (add_excludes_from_file_to_list (fname , "" , 0 , el , 0 ) < 0 )
702
+ if (add_excludes (fname , "" , 0 , el , 0 , sha1_stat ) < 0 )
654
703
die ("cannot use %s as an exclude file" , fname );
655
704
}
656
705
706
+ void add_excludes_from_file (struct dir_struct * dir , const char * fname )
707
+ {
708
+ add_excludes_from_file_1 (dir , fname , NULL );
709
+ }
710
+
657
711
int match_basename (const char * basename , int basenamelen ,
658
712
const char * pattern , int prefix , int patternlen ,
659
713
int flags )
@@ -828,6 +882,7 @@ static void prep_exclude(struct dir_struct *dir, const char *base, int baselen)
828
882
struct exclude_list_group * group ;
829
883
struct exclude_list * el ;
830
884
struct exclude_stack * stk = NULL ;
885
+ struct untracked_cache_dir * untracked ;
831
886
int current ;
832
887
833
888
group = & dir -> exclude_list_group [EXC_DIRS ];
@@ -865,8 +920,14 @@ static void prep_exclude(struct dir_struct *dir, const char *base, int baselen)
865
920
/* Read from the parent directories and push them down. */
866
921
current = stk ? stk -> baselen : -1 ;
867
922
strbuf_setlen (& dir -> basebuf , current < 0 ? 0 : current );
923
+ if (dir -> untracked )
924
+ untracked = stk ? stk -> ucd : dir -> untracked -> root ;
925
+ else
926
+ untracked = NULL ;
927
+
868
928
while (current < baselen ) {
869
929
const char * cp ;
930
+ struct sha1_stat sha1_stat ;
870
931
871
932
stk = xcalloc (1 , sizeof (* stk ));
872
933
if (current < 0 ) {
@@ -877,10 +938,15 @@ static void prep_exclude(struct dir_struct *dir, const char *base, int baselen)
877
938
if (!cp )
878
939
die ("oops in prep_exclude" );
879
940
cp ++ ;
941
+ untracked =
942
+ lookup_untracked (dir -> untracked , untracked ,
943
+ base + current ,
944
+ cp - base - current );
880
945
}
881
946
stk -> prev = dir -> exclude_stack ;
882
947
stk -> baselen = cp - base ;
883
948
stk -> exclude_ix = group -> nr ;
949
+ stk -> ucd = untracked ;
884
950
el = add_exclude_list (dir , EXC_DIRS , NULL );
885
951
strbuf_add (& dir -> basebuf , base + current , stk -> baselen - current );
886
952
assert (stk -> baselen == dir -> basebuf .len );
@@ -903,6 +969,8 @@ static void prep_exclude(struct dir_struct *dir, const char *base, int baselen)
903
969
}
904
970
905
971
/* Try to read per-directory file */
972
+ hashclr (sha1_stat .sha1 );
973
+ sha1_stat .valid = 0 ;
906
974
if (dir -> exclude_per_dir ) {
907
975
/*
908
976
* dir->basebuf gets reused by the traversal, but we
@@ -916,8 +984,11 @@ static void prep_exclude(struct dir_struct *dir, const char *base, int baselen)
916
984
strbuf_addbuf (& sb , & dir -> basebuf );
917
985
strbuf_addstr (& sb , dir -> exclude_per_dir );
918
986
el -> src = strbuf_detach (& sb , NULL );
919
- add_excludes_from_file_to_list (el -> src , el -> src ,
920
- stk -> baselen , el , 1 );
987
+ add_excludes (el -> src , el -> src , stk -> baselen , el , 1 ,
988
+ untracked ? & sha1_stat : NULL );
989
+ }
990
+ if (untracked ) {
991
+ hashcpy (untracked -> exclude_sha1 , sha1_stat .sha1 );
921
992
}
922
993
dir -> exclude_stack = stk ;
923
994
current = stk -> baselen ;
@@ -1098,6 +1169,7 @@ static enum exist_status directory_exists_in_index(const char *dirname, int len)
1098
1169
* (c) otherwise, we recurse into it.
1099
1170
*/
1100
1171
static enum path_treatment treat_directory (struct dir_struct * dir ,
1172
+ struct untracked_cache_dir * untracked ,
1101
1173
const char * dirname , int len , int exclude ,
1102
1174
const struct path_simplify * simplify )
1103
1175
{
@@ -1125,7 +1197,9 @@ static enum path_treatment treat_directory(struct dir_struct *dir,
1125
1197
if (!(dir -> flags & DIR_HIDE_EMPTY_DIRECTORIES ))
1126
1198
return exclude ? path_excluded : path_untracked ;
1127
1199
1128
- return read_directory_recursive (dir , dirname , len , 1 , simplify );
1200
+ untracked = lookup_untracked (dir -> untracked , untracked , dirname , len );
1201
+ return read_directory_recursive (dir , dirname , len ,
1202
+ untracked , 1 , simplify );
1129
1203
}
1130
1204
1131
1205
/*
@@ -1241,6 +1315,7 @@ static int get_dtype(struct dirent *de, const char *path, int len)
1241
1315
}
1242
1316
1243
1317
static enum path_treatment treat_one_path (struct dir_struct * dir ,
1318
+ struct untracked_cache_dir * untracked ,
1244
1319
struct strbuf * path ,
1245
1320
const struct path_simplify * simplify ,
1246
1321
int dtype , struct dirent * de )
@@ -1293,7 +1368,7 @@ static enum path_treatment treat_one_path(struct dir_struct *dir,
1293
1368
return path_none ;
1294
1369
case DT_DIR :
1295
1370
strbuf_addch (path , '/' );
1296
- return treat_directory (dir , path -> buf , path -> len , exclude ,
1371
+ return treat_directory (dir , untracked , path -> buf , path -> len , exclude ,
1297
1372
simplify );
1298
1373
case DT_REG :
1299
1374
case DT_LNK :
@@ -1302,6 +1377,7 @@ static enum path_treatment treat_one_path(struct dir_struct *dir,
1302
1377
}
1303
1378
1304
1379
static enum path_treatment treat_path (struct dir_struct * dir ,
1380
+ struct untracked_cache_dir * untracked ,
1305
1381
struct dirent * de ,
1306
1382
struct strbuf * path ,
1307
1383
int baselen ,
@@ -1317,7 +1393,16 @@ static enum path_treatment treat_path(struct dir_struct *dir,
1317
1393
return path_none ;
1318
1394
1319
1395
dtype = DTYPE (de );
1320
- return treat_one_path (dir , path , simplify , dtype , de );
1396
+ return treat_one_path (dir , untracked , path , simplify , dtype , de );
1397
+ }
1398
+
1399
+ static void add_untracked (struct untracked_cache_dir * dir , const char * name )
1400
+ {
1401
+ if (!dir )
1402
+ return ;
1403
+ ALLOC_GROW (dir -> untracked , dir -> untracked_nr + 1 ,
1404
+ dir -> untracked_alloc );
1405
+ dir -> untracked [dir -> untracked_nr ++ ] = xstrdup (name );
1321
1406
}
1322
1407
1323
1408
/*
@@ -1333,7 +1418,7 @@ static enum path_treatment treat_path(struct dir_struct *dir,
1333
1418
*/
1334
1419
static enum path_treatment read_directory_recursive (struct dir_struct * dir ,
1335
1420
const char * base , int baselen ,
1336
- int check_only ,
1421
+ struct untracked_cache_dir * untracked , int check_only ,
1337
1422
const struct path_simplify * simplify )
1338
1423
{
1339
1424
DIR * fdir ;
@@ -1347,24 +1432,36 @@ static enum path_treatment read_directory_recursive(struct dir_struct *dir,
1347
1432
if (!fdir )
1348
1433
goto out ;
1349
1434
1435
+ if (untracked )
1436
+ untracked -> check_only = !!check_only ;
1437
+
1350
1438
while ((de = readdir (fdir )) != NULL ) {
1351
1439
/* check how the file or directory should be treated */
1352
- state = treat_path (dir , de , & path , baselen , simplify );
1440
+ state = treat_path (dir , untracked , de , & path , baselen , simplify );
1441
+
1353
1442
if (state > dir_state )
1354
1443
dir_state = state ;
1355
1444
1356
1445
/* recurse into subdir if instructed by treat_path */
1357
1446
if (state == path_recurse ) {
1358
- subdir_state = read_directory_recursive (dir , path .buf ,
1359
- path .len , check_only , simplify );
1447
+ struct untracked_cache_dir * ud ;
1448
+ ud = lookup_untracked (dir -> untracked , untracked ,
1449
+ path .buf + baselen ,
1450
+ path .len - baselen );
1451
+ subdir_state =
1452
+ read_directory_recursive (dir , path .buf , path .len ,
1453
+ ud , check_only , simplify );
1360
1454
if (subdir_state > dir_state )
1361
1455
dir_state = subdir_state ;
1362
1456
}
1363
1457
1364
1458
if (check_only ) {
1365
1459
/* abort early if maximum state has been reached */
1366
- if (dir_state == path_untracked )
1460
+ if (dir_state == path_untracked ) {
1461
+ if (untracked )
1462
+ add_untracked (untracked , path .buf + baselen );
1367
1463
break ;
1464
+ }
1368
1465
/* skip the dir_add_* part */
1369
1466
continue ;
1370
1467
}
@@ -1382,8 +1479,11 @@ static enum path_treatment read_directory_recursive(struct dir_struct *dir,
1382
1479
break ;
1383
1480
1384
1481
case path_untracked :
1385
- if (!(dir -> flags & DIR_SHOW_IGNORED ))
1386
- dir_add_name (dir , path .buf , path .len );
1482
+ if (dir -> flags & DIR_SHOW_IGNORED )
1483
+ break ;
1484
+ dir_add_name (dir , path .buf , path .len );
1485
+ if (untracked )
1486
+ add_untracked (untracked , path .buf + baselen );
1387
1487
break ;
1388
1488
1389
1489
default :
@@ -1460,7 +1560,7 @@ static int treat_leading_path(struct dir_struct *dir,
1460
1560
break ;
1461
1561
if (simplify_away (sb .buf , sb .len , simplify ))
1462
1562
break ;
1463
- if (treat_one_path (dir , & sb , simplify ,
1563
+ if (treat_one_path (dir , NULL , & sb , simplify ,
1464
1564
DT_DIR , NULL ) == path_none )
1465
1565
break ; /* do not recurse into it */
1466
1566
if (len <= baselen ) {
@@ -1500,7 +1600,9 @@ int read_directory(struct dir_struct *dir, const char *path, int len, const stru
1500
1600
*/
1501
1601
simplify = create_simplify (pathspec ? pathspec -> _raw : NULL );
1502
1602
if (!len || treat_leading_path (dir , path , len , simplify ))
1503
- read_directory_recursive (dir , path , len , 0 , simplify );
1603
+ read_directory_recursive (dir , path , len ,
1604
+ dir -> untracked ? dir -> untracked -> root : NULL ,
1605
+ 0 , simplify );
1504
1606
free_simplify (simplify );
1505
1607
qsort (dir -> entries , dir -> nr , sizeof (struct dir_entry * ), cmp_name );
1506
1608
qsort (dir -> ignored , dir -> ignored_nr , sizeof (struct dir_entry * ), cmp_name );
@@ -1671,9 +1773,11 @@ void setup_standard_excludes(struct dir_struct *dir)
1671
1773
excludes_file = xdg_path ;
1672
1774
}
1673
1775
if (!access_or_warn (path , R_OK , 0 ))
1674
- add_excludes_from_file (dir , path );
1776
+ add_excludes_from_file_1 (dir , path ,
1777
+ dir -> untracked ? & dir -> ss_info_exclude : NULL );
1675
1778
if (excludes_file && !access_or_warn (excludes_file , R_OK , 0 ))
1676
- add_excludes_from_file (dir , excludes_file );
1779
+ add_excludes_from_file_1 (dir , excludes_file ,
1780
+ dir -> untracked ? & dir -> ss_excludes_file : NULL );
1677
1781
}
1678
1782
1679
1783
int remove_path (const char * name )
0 commit comments