MCPcopy Create free account
hub / github.com/DeusData/codebase-memory-mcp / resolve_project_tail

Function resolve_project_tail

src/mcp/mcp.c:1443–1489  ·  view source on GitHub ↗

#1025: agents naturally pass the repo FOLDER name ("codebase-memory-mcp"), * but indexed project names derive from the full path * (E:\project\graph\x -> "E-project-graph-x"), so the exact lookup fails * while list_projects clearly shows the project. When no .db exists, * scan cache-dir FILENAMES for a segment-aligned tail match ("- .db"): * exactly one match adopts the full

Source from the content-addressed store, hash-verified

1441 * the existing not-found error (which lists all candidates) fires. Filename-
1442 * level only — internal-name drift stays #704's fallback in resolve_store. */
1443static char *resolve_project_tail(char *project) {
1444 if (!project || !cbm_validate_project_name(project)) {
1445 return project;
1446 }
1447 char dir[CBM_SZ_1K];
1448 cache_dir(dir, sizeof(dir));
1449 char exact[CBM_SZ_2K];
1450 snprintf(exact, sizeof(exact), "%s/%s.db", dir, project);
1451 if (cbm_file_exists(exact)) {
1452 return project; /* exact name — untouched fast path */
1453 }
1454 size_t plen = strlen(project);
1455 char match[CBM_SZ_1K] = "";
1456 int matches = 0;
1457 cbm_dir_t *d = cbm_opendir(dir);
1458 if (!d) {
1459 return project;
1460 }
1461 cbm_dirent_t *entry;
1462 while ((entry = cbm_readdir(d)) != NULL) {
1463 const char *n = entry->name;
1464 size_t len = strlen(n);
1465 if (!is_project_db_file(n, len)) {
1466 continue;
1467 }
1468 size_t stem_len = len - MCP_DB_EXT; /* strip ".db" */
1469 if (stem_len <= plen + 1 || stem_len >= sizeof(match)) {
1470 continue;
1471 }
1472 if (n[stem_len - plen - 1] != '-' || strncmp(n + stem_len - plen, project, plen) != 0) {
1473 continue;
1474 }
1475 matches++;
1476 if (matches > 1) {
1477 break; /* ambiguous — keep the original name */
1478 }
1479 memcpy(match, n, stem_len);
1480 match[stem_len] = '\0';
1481 }
1482 cbm_closedir(d);
1483 if (matches == 1) {
1484 cbm_log_info("mcp.project_tail_resolved", "passed", project, "resolved", match);
1485 free(project);
1486 return heap_strdup(match);
1487 }
1488 return project;
1489}
1490
1491/* Resolve the project argument, accepting the canonical "project" key plus the
1492 * aliases a caller naturally reaches for (#640): list_projects surfaces the

Callers 1

get_project_argFunction · 0.85

Calls 8

cache_dirFunction · 0.85
cbm_file_existsFunction · 0.85
cbm_opendirFunction · 0.85
cbm_readdirFunction · 0.85
is_project_db_fileFunction · 0.85
cbm_closedirFunction · 0.85
heap_strdupFunction · 0.70

Tested by

no test coverage detected