True if a CALLS edge exists whose source QN ends with `src_suffix` and * target QN ends with `tgt_suffix`. */
| 1371 | /* True if a CALLS edge exists whose source QN ends with `src_suffix` and |
| 1372 | * target QN ends with `tgt_suffix`. */ |
| 1373 | static int calls_edge_between(cbm_store_t *store, const char *project, const char *src_suffix, |
| 1374 | const char *tgt_suffix) { |
| 1375 | cbm_edge_t *edges = NULL; |
| 1376 | int n = 0; |
| 1377 | if (cbm_store_find_edges_by_type(store, project, "CALLS", &edges, &n) != CBM_STORE_OK) |
| 1378 | return 0; |
| 1379 | int found = 0; |
| 1380 | size_t ssl = strlen(src_suffix); |
| 1381 | size_t tsl = strlen(tgt_suffix); |
| 1382 | for (int i = 0; i < n && !found; i++) { |
| 1383 | cbm_node_t s, t; |
| 1384 | if (cbm_store_find_node_by_id(store, edges[i].source_id, &s) != CBM_STORE_OK) |
| 1385 | continue; |
| 1386 | if (cbm_store_find_node_by_id(store, edges[i].target_id, &t) != CBM_STORE_OK) { |
| 1387 | cbm_node_free_fields(&s); |
| 1388 | continue; |
| 1389 | } |
| 1390 | const char *sq = s.qualified_name; |
| 1391 | const char *tq = t.qualified_name; |
| 1392 | if (sq && tq) { |
| 1393 | size_t sql = strlen(sq); |
| 1394 | size_t tql = strlen(tq); |
| 1395 | if (sql >= ssl && strcmp(sq + sql - ssl, src_suffix) == 0 && tql >= tsl && |
| 1396 | strcmp(tq + tql - tsl, tgt_suffix) == 0) |
| 1397 | found = 1; |
| 1398 | } |
| 1399 | cbm_node_free_fields(&s); |
| 1400 | cbm_node_free_fields(&t); |
| 1401 | } |
| 1402 | cbm_store_free_edges(edges, n); |
| 1403 | return found; |
| 1404 | } |
| 1405 | |
| 1406 | /* #999: URLs in CI/tooling configs (.pre-commit-config.yaml, .github/ |
| 1407 | * workflows) are repository references for TOOLING, not endpoints this |
no test coverage detected