| 721 | enum { GI_OWNED_CAP = 64 }; |
| 722 | |
| 723 | static void walk_dir(const char *dir_path, const char *rel_prefix, const cbm_discover_opts_t *opts, |
| 724 | const cbm_gitignore_t *gitignore, const cbm_gitignore_t *global_gi, |
| 725 | const cbm_gitignore_t *cbmignore, file_list_t *out) { |
| 726 | walk_frame_t *stack = calloc(WALK_STACK_CAP, sizeof(walk_frame_t)); |
| 727 | if (!stack) { |
| 728 | return; |
| 729 | } |
| 730 | /* Collect all owned gitignores — freed at the end because child frames |
| 731 | * on the stack hold borrowed pointers to them. */ |
| 732 | cbm_gitignore_t *owned_gis[GI_OWNED_CAP]; |
| 733 | int owned_count = 0; |
| 734 | |
| 735 | int top = 0; |
| 736 | snprintf(stack[top].dir, CBM_SZ_4K, "%s", dir_path); |
| 737 | snprintf(stack[top].prefix, CBM_SZ_4K, "%s", rel_prefix); |
| 738 | top++; |
| 739 | |
| 740 | while (top > 0) { |
| 741 | walk_frame_t frame = stack[--top]; |
| 742 | |
| 743 | cbm_gitignore_t *loaded = try_load_nested_gitignore(&frame); |
| 744 | if (loaded) { |
| 745 | frame.local_gi = loaded; |
| 746 | snprintf(frame.local_gi_prefix, sizeof(frame.local_gi_prefix), "%s", frame.prefix); |
| 747 | if (owned_count < GI_OWNED_CAP) { |
| 748 | owned_gis[owned_count++] = loaded; |
| 749 | } |
| 750 | } |
| 751 | |
| 752 | cbm_dir_t *d = cbm_opendir(frame.dir); |
| 753 | if (!d) { |
| 754 | continue; |
| 755 | } |
| 756 | |
| 757 | cbm_dirent_t *entry; |
| 758 | while ((entry = cbm_readdir(d)) != NULL) { |
| 759 | walk_dir_process_entry(entry, &frame, opts, gitignore, global_gi, cbmignore, stack, |
| 760 | &top, out); |
| 761 | } |
| 762 | cbm_closedir(d); |
| 763 | } |
| 764 | for (int i = 0; i < owned_count; i++) { |
| 765 | cbm_gitignore_free(owned_gis[i]); |
| 766 | } |
| 767 | free(stack); |
| 768 | } |
| 769 | |
| 770 | /* ── Public API ───────────────────────────────── */ |
| 771 |
no test coverage detected