| 601 | } |
| 602 | |
| 603 | static bool should_skip_directory(const char *entry_name, const char *rel_path, |
| 604 | const cbm_discover_opts_t *opts, const cbm_gitignore_t *gitignore, |
| 605 | const cbm_gitignore_t *global_gi, |
| 606 | const cbm_gitignore_t *cbmignore, const cbm_gitignore_t *local_gi, |
| 607 | const char *local_gi_prefix) { |
| 608 | if (cbm_should_skip_dir(entry_name, opts ? opts->mode : CBM_MODE_FULL)) { |
| 609 | /* #500: a .cbmignore negation (e.g. "!obj/") whose rule is the last |
| 610 | * match for this dir un-skips a built-in skip-list dir — except the |
| 611 | * non-negatable safety core. Fall through so .gitignore/global/local |
| 612 | * rules still apply to the un-skipped dir. */ |
| 613 | bool unskipped = cbmignore && !is_safety_core_dir(entry_name) && |
| 614 | cbm_gitignore_match_result(cbmignore, rel_path, true) < 0; |
| 615 | if (!unskipped) { |
| 616 | return true; |
| 617 | } |
| 618 | } |
| 619 | if (gitignore && cbm_gitignore_matches(gitignore, rel_path, true)) { |
| 620 | return true; |
| 621 | } |
| 622 | bool global_ignored = global_gi && cbm_gitignore_matches(global_gi, rel_path, true); |
| 623 | if (local_gi) { |
| 624 | const char *lrel = local_rel_path(rel_path, local_gi_prefix); |
| 625 | if (cbm_gitignore_matches(local_gi, lrel, true)) { |
| 626 | return true; |
| 627 | } |
| 628 | } |
| 629 | if (cbmignore) { |
| 630 | int cbm_result = cbm_gitignore_match_result(cbmignore, rel_path, true); |
| 631 | if (cbm_result > 0) { |
| 632 | return true; |
| 633 | } |
| 634 | if (cbm_result < 0 && global_ignored) { |
| 635 | return false; |
| 636 | } |
| 637 | } |
| 638 | return global_ignored; |
| 639 | } |
| 640 | |
| 641 | /* Check if a regular file should be skipped (filters + gitignore + size). */ |
| 642 | /* Classify why a file is skipped. Returns a static reason string (the #963 |
no test coverage detected