@@ -31,6 +31,15 @@ enum path_treatment {
31
31
path_untracked
32
32
};
33
33
34
+ /*
35
+ * Support data structure for our opendir/readdir/closedir wrappers
36
+ */
37
+ struct cached_dir {
38
+ DIR * fdir ;
39
+ struct untracked_cache_dir * untracked ;
40
+ struct dirent * de ;
41
+ };
42
+
34
43
static enum path_treatment read_directory_recursive (struct dir_struct * dir ,
35
44
const char * path , int len , struct untracked_cache_dir * untracked ,
36
45
int check_only , const struct path_simplify * simplify );
@@ -1418,12 +1427,13 @@ static enum path_treatment treat_one_path(struct dir_struct *dir,
1418
1427
1419
1428
static enum path_treatment treat_path (struct dir_struct * dir ,
1420
1429
struct untracked_cache_dir * untracked ,
1421
- struct dirent * de ,
1430
+ struct cached_dir * cdir ,
1422
1431
struct strbuf * path ,
1423
1432
int baselen ,
1424
1433
const struct path_simplify * simplify )
1425
1434
{
1426
1435
int dtype ;
1436
+ struct dirent * de = cdir -> de ;
1427
1437
1428
1438
if (is_dot_or_dotdot (de -> d_name ) || !strcmp (de -> d_name , ".git" ))
1429
1439
return path_none ;
@@ -1445,6 +1455,37 @@ static void add_untracked(struct untracked_cache_dir *dir, const char *name)
1445
1455
dir -> untracked [dir -> untracked_nr ++ ] = xstrdup (name );
1446
1456
}
1447
1457
1458
+ static int open_cached_dir (struct cached_dir * cdir ,
1459
+ struct dir_struct * dir ,
1460
+ struct untracked_cache_dir * untracked ,
1461
+ struct strbuf * path ,
1462
+ int check_only )
1463
+ {
1464
+ memset (cdir , 0 , sizeof (* cdir ));
1465
+ cdir -> untracked = untracked ;
1466
+ cdir -> fdir = opendir (path -> len ? path -> buf : "." );
1467
+ if (!cdir -> fdir )
1468
+ return -1 ;
1469
+ return 0 ;
1470
+ }
1471
+
1472
+ static int read_cached_dir (struct cached_dir * cdir )
1473
+ {
1474
+ if (cdir -> fdir ) {
1475
+ cdir -> de = readdir (cdir -> fdir );
1476
+ if (!cdir -> de )
1477
+ return -1 ;
1478
+ return 0 ;
1479
+ }
1480
+ return -1 ;
1481
+ }
1482
+
1483
+ static void close_cached_dir (struct cached_dir * cdir )
1484
+ {
1485
+ if (cdir -> fdir )
1486
+ closedir (cdir -> fdir );
1487
+ }
1488
+
1448
1489
/*
1449
1490
* Read a directory tree. We currently ignore anything but
1450
1491
* directories, regular files and symlinks. That's because git
@@ -1461,23 +1502,21 @@ static enum path_treatment read_directory_recursive(struct dir_struct *dir,
1461
1502
struct untracked_cache_dir * untracked , int check_only ,
1462
1503
const struct path_simplify * simplify )
1463
1504
{
1464
- DIR * fdir ;
1505
+ struct cached_dir cdir ;
1465
1506
enum path_treatment state , subdir_state , dir_state = path_none ;
1466
- struct dirent * de ;
1467
1507
struct strbuf path = STRBUF_INIT ;
1468
1508
1469
1509
strbuf_add (& path , base , baselen );
1470
1510
1471
- fdir = opendir (path .len ? path .buf : "." );
1472
- if (!fdir )
1511
+ if (open_cached_dir (& cdir , dir , untracked , & path , check_only ))
1473
1512
goto out ;
1474
1513
1475
1514
if (untracked )
1476
1515
untracked -> check_only = !!check_only ;
1477
1516
1478
- while (( de = readdir ( fdir )) != NULL ) {
1517
+ while (! read_cached_dir ( & cdir ) ) {
1479
1518
/* check how the file or directory should be treated */
1480
- state = treat_path (dir , untracked , de , & path , baselen , simplify );
1519
+ state = treat_path (dir , untracked , & cdir , & path , baselen , simplify );
1481
1520
1482
1521
if (state > dir_state )
1483
1522
dir_state = state ;
@@ -1530,7 +1569,7 @@ static enum path_treatment read_directory_recursive(struct dir_struct *dir,
1530
1569
break ;
1531
1570
}
1532
1571
}
1533
- closedir ( fdir );
1572
+ close_cached_dir ( & cdir );
1534
1573
out :
1535
1574
strbuf_release (& path );
1536
1575
0 commit comments