True if a CALLS edge exists whose source QN ends with `src_suffix` and * target QN ends with `tgt_suffix`. */
| 1233 | /* True if a CALLS edge exists whose source QN ends with `src_suffix` and |
| 1234 | * target QN ends with `tgt_suffix`. */ |
| 1235 | static int calls_edge_between(cbm_store_t *store, const char *project, const char *src_suffix, |
| 1236 | const char *tgt_suffix) { |
| 1237 | cbm_edge_t *edges = NULL; |
| 1238 | int n = 0; |
| 1239 | if (cbm_store_find_edges_by_type(store, project, "CALLS", &edges, &n) != CBM_STORE_OK) |
| 1240 | return 0; |
| 1241 | int found = 0; |
| 1242 | size_t ssl = strlen(src_suffix); |
| 1243 | size_t tsl = strlen(tgt_suffix); |
| 1244 | for (int i = 0; i < n && !found; i++) { |
| 1245 | cbm_node_t s, t; |
| 1246 | if (cbm_store_find_node_by_id(store, edges[i].source_id, &s) != CBM_STORE_OK) |
| 1247 | continue; |
| 1248 | if (cbm_store_find_node_by_id(store, edges[i].target_id, &t) != CBM_STORE_OK) { |
| 1249 | cbm_node_free_fields(&s); |
| 1250 | continue; |
| 1251 | } |
| 1252 | const char *sq = s.qualified_name; |
| 1253 | const char *tq = t.qualified_name; |
| 1254 | if (sq && tq) { |
| 1255 | size_t sql = strlen(sq); |
| 1256 | size_t tql = strlen(tq); |
| 1257 | if (sql >= ssl && strcmp(sq + sql - ssl, src_suffix) == 0 && tql >= tsl && |
| 1258 | strcmp(tq + tql - tsl, tgt_suffix) == 0) |
| 1259 | found = 1; |
| 1260 | } |
| 1261 | cbm_node_free_fields(&s); |
| 1262 | cbm_node_free_fields(&t); |
| 1263 | } |
| 1264 | cbm_store_free_edges(edges, n); |
| 1265 | return found; |
| 1266 | } |
| 1267 | |
| 1268 | /* #999: URLs in CI/tooling configs (.pre-commit-config.yaml, .github/ |
| 1269 | * workflows) are repository references for TOOLING, not endpoints this |
no test coverage detected