|
7 | 7 |
|
8 | 8 | #include "iterator.h" |
9 | 9 |
|
| 10 | +#include <dirent.h> |
| 11 | +#include <sys/stat.h> |
| 12 | +#include <sys/types.h> |
| 13 | +#include <unistd.h> |
| 14 | + |
10 | 15 | #include "tree.h" |
11 | 16 | #include "index.h" |
12 | 17 |
|
@@ -1337,7 +1342,8 @@ static int filesystem_iterator_frame_push( |
1337 | 1342 | filesystem_iterator_entry *entry; |
1338 | 1343 | struct stat statbuf; |
1339 | 1344 | size_t path_len; |
1340 | | - int error; |
| 1345 | + int error = 0; |
| 1346 | + bool submodule = false; |
1341 | 1347 |
|
1342 | 1348 | if (iter->frames.size == FILESYSTEM_MAX_DEPTH) { |
1343 | 1349 | git_error_set(GIT_ERROR_REPOSITORY, |
@@ -1402,52 +1408,53 @@ static int filesystem_iterator_frame_push( |
1402 | 1408 | iter, frame_entry, path, path_len)) |
1403 | 1409 | continue; |
1404 | 1410 |
|
| 1411 | + if (filesystem_iterator_is_dot_git(iter, path, path_len)) |
| 1412 | + continue; |
| 1413 | + |
1405 | 1414 | /* TODO: don't need to stat if assume unchanged for this path and |
1406 | 1415 | * we have an index, we can just copy the data out of it. |
1407 | 1416 | */ |
1408 | 1417 |
|
1409 | | - if ((error = git_path_diriter_stat(&statbuf, &diriter)) < 0) { |
1410 | | - /* file was removed between readdir and lstat */ |
1411 | | - if (error == GIT_ENOTFOUND) |
1412 | | - continue; |
1413 | | - |
1414 | | - /* treat the file as unreadable */ |
1415 | | - memset(&statbuf, 0, sizeof(statbuf)); |
1416 | | - statbuf.st_mode = GIT_FILEMODE_UNREADABLE; |
1417 | | - |
1418 | | - error = 0; |
1419 | | - } |
| 1418 | + if (diriter.d_type == DT_DIR && |
| 1419 | + !(error = filesystem_iterator_is_submodule(&submodule, iter, path, path_len)) && |
| 1420 | + !submodule) { |
| 1421 | + // It's a directory, no need to lstat it. |
| 1422 | + statbuf.st_mode = S_IFDIR; |
| 1423 | + } else if (error < 0) { |
| 1424 | + goto done; |
| 1425 | + } else { |
| 1426 | + if ((error = git_path_diriter_stat(&statbuf, &diriter)) < 0) { |
| 1427 | + /* file was removed between readdir and lstat */ |
| 1428 | + if (error == GIT_ENOTFOUND) continue; |
1420 | 1429 |
|
1421 | | - iter->base.stat_calls++; |
| 1430 | + /* treat the file as unreadable */ |
| 1431 | + memset(&statbuf, 0, sizeof(statbuf)); |
| 1432 | + statbuf.st_mode = GIT_FILEMODE_UNREADABLE; |
1422 | 1433 |
|
1423 | | - /* Ignore wacky things in the filesystem */ |
1424 | | - if (!S_ISDIR(statbuf.st_mode) && |
1425 | | - !S_ISREG(statbuf.st_mode) && |
1426 | | - !S_ISLNK(statbuf.st_mode) && |
1427 | | - statbuf.st_mode != GIT_FILEMODE_UNREADABLE) |
1428 | | - continue; |
1429 | | - |
1430 | | - if (filesystem_iterator_is_dot_git(iter, path, path_len)) |
1431 | | - continue; |
| 1434 | + error = 0; |
| 1435 | + } |
| 1436 | + iter->base.stat_calls++; |
1432 | 1437 |
|
1433 | | - /* convert submodules to GITLINK and remove trailing slashes */ |
1434 | | - if (S_ISDIR(statbuf.st_mode)) { |
1435 | | - bool submodule = false; |
| 1438 | + /* Ignore wacky things in the filesystem */ |
| 1439 | + if (!S_ISDIR(statbuf.st_mode) && !S_ISREG(statbuf.st_mode) && !S_ISLNK(statbuf.st_mode) && |
| 1440 | + statbuf.st_mode != GIT_FILEMODE_UNREADABLE) |
| 1441 | + continue; |
1436 | 1442 |
|
1437 | | - if ((error = filesystem_iterator_is_submodule(&submodule, |
1438 | | - iter, path, path_len)) < 0) |
1439 | | - goto done; |
| 1443 | + /* Ensure that the pathlist entry lines up with what we expected */ |
| 1444 | + if (dir_expected && !S_ISDIR(statbuf.st_mode)) continue; |
1440 | 1445 |
|
1441 | | - if (submodule) |
1442 | | - statbuf.st_mode = GIT_FILEMODE_COMMIT; |
| 1446 | + /* convert submodules to GITLINK and remove trailing slashes */ |
| 1447 | + if (S_ISDIR(statbuf.st_mode)) { |
| 1448 | + if (!submodule) { |
| 1449 | + if ((error = filesystem_iterator_is_submodule(&submodule, iter, path, path_len)) < 0) |
| 1450 | + goto done; |
| 1451 | + } |
| 1452 | + if (submodule) statbuf.st_mode = GIT_FILEMODE_COMMIT; |
| 1453 | + } |
1443 | 1454 | } |
1444 | 1455 |
|
1445 | | - /* Ensure that the pathlist entry lines up with what we expected */ |
1446 | | - else if (dir_expected) |
1447 | | - continue; |
1448 | | - |
1449 | | - if ((error = filesystem_iterator_entry_init(&entry, |
1450 | | - iter, new_frame, path, path_len, &statbuf, pathlist_match)) < 0) |
| 1456 | + if ((error = filesystem_iterator_entry_init(&entry, iter, new_frame, path, path_len, &statbuf, |
| 1457 | + pathlist_match)) < 0) |
1451 | 1458 | goto done; |
1452 | 1459 |
|
1453 | 1460 | git_vector_insert(&new_frame->entries, entry); |
|
0 commit comments