| 3926 | } |
| 3927 | |
| 3928 | int cbm_store_get_dependent_files(cbm_store_t *s, const char *project, |
| 3929 | const char *const *target_files, int target_count, char ***out, |
| 3930 | int *out_count) { |
| 3931 | *out = NULL; |
| 3932 | *out_count = 0; |
| 3933 | if (!s || !project || target_count <= 0) { |
| 3934 | return target_count == 0 ? CBM_STORE_OK : CBM_STORE_ERR; |
| 3935 | } |
| 3936 | /* Exclude the targets themselves up front: an edge between two files of |
| 3937 | * the closure adds nothing, and the caller wants "who ELSE consumed". */ |
| 3938 | CBMHashTable *seen = cbm_ht_create((size_t)target_count * PAIR_LEN); |
| 3939 | if (!seen) { |
| 3940 | return CBM_STORE_ERR; |
| 3941 | } |
| 3942 | for (int i = 0; i < target_count; i++) { |
| 3943 | cbm_ht_set(seen, target_files[i], (void *)target_files[i]); |
| 3944 | } |
| 3945 | char **files = NULL; |
| 3946 | int count = 0; |
| 3947 | int cap = 0; |
| 3948 | int rc = CBM_STORE_OK; |
| 3949 | for (int off = 0; off < target_count && rc == CBM_STORE_OK; off += DEPFILE_CHUNK) { |
| 3950 | int chunk = target_count - off; |
| 3951 | if (chunk > DEPFILE_CHUNK) { |
| 3952 | chunk = DEPFILE_CHUNK; |
| 3953 | } |
| 3954 | rc = dependent_files_chunk(s, project, target_files + off, chunk, seen, &files, &count, |
| 3955 | &cap); |
| 3956 | } |
| 3957 | cbm_ht_free(seen); |
| 3958 | if (rc != CBM_STORE_OK) { |
| 3959 | cbm_store_free_dependent_files(files, count); |
| 3960 | return rc; |
| 3961 | } |
| 3962 | *out = files; |
| 3963 | *out_count = count; |
| 3964 | return CBM_STORE_OK; |
| 3965 | } |
| 3966 | |
| 3967 | void cbm_store_free_dependent_files(char **files, int count) { |
| 3968 | if (!files) { |
no test coverage detected