| 1463 | #define CODEX_CMM_SECTION "[mcp_servers.codebase-memory-mcp]" |
| 1464 | |
| 1465 | int cbm_upsert_codex_mcp(const char *binary_path, const char *config_path) { |
| 1466 | if (!binary_path || !config_path) { |
| 1467 | return CLI_ERR; |
| 1468 | } |
| 1469 | |
| 1470 | size_t len = 0; |
| 1471 | char *content = read_file_str(config_path, &len); |
| 1472 | |
| 1473 | /* Build our TOML section */ |
| 1474 | char section[CLI_BUF_1K]; |
| 1475 | snprintf(section, sizeof(section), "%s\ncommand = \"%s\"\n", CODEX_CMM_SECTION, binary_path); |
| 1476 | |
| 1477 | if (!content) { |
| 1478 | /* No file — create fresh */ |
| 1479 | return write_file_str(config_path, section); |
| 1480 | } |
| 1481 | |
| 1482 | /* Check if our section already exists */ |
| 1483 | char *existing = strstr(content, CODEX_CMM_SECTION); |
| 1484 | if (existing) { |
| 1485 | /* Remove old section: from [mcp_servers.codebase-memory-mcp] to next [section] or EOF */ |
| 1486 | char *section_end = existing + strlen(CODEX_CMM_SECTION); |
| 1487 | /* Find next [section] header */ |
| 1488 | char *next_section = strstr(section_end, "\n["); |
| 1489 | if (next_section) { |
| 1490 | next_section++; /* keep the newline before next section */ |
| 1491 | } |
| 1492 | |
| 1493 | size_t prefix_len = (size_t)(existing - content); |
| 1494 | const char *suffix = next_section ? next_section : ""; |
| 1495 | size_t suffix_len = strlen(suffix); |
| 1496 | size_t new_len = prefix_len + strlen(section) + CLI_SKIP_ONE + suffix_len; |
| 1497 | char *result = malloc(new_len + CLI_SKIP_ONE); |
| 1498 | if (!result) { |
| 1499 | free(content); |
| 1500 | return CLI_ERR; |
| 1501 | } |
| 1502 | memcpy(result, content, prefix_len); |
| 1503 | memcpy(result + prefix_len, section, strlen(section)); |
| 1504 | result[prefix_len + strlen(section)] = '\n'; |
| 1505 | memcpy(result + prefix_len + strlen(section) + CLI_SKIP_ONE, suffix, suffix_len); |
| 1506 | result[new_len] = '\0'; |
| 1507 | |
| 1508 | int rc = write_file_str(config_path, result); |
| 1509 | free(content); |
| 1510 | free(result); |
| 1511 | return rc; |
| 1512 | } |
| 1513 | |
| 1514 | /* Append our section */ |
| 1515 | size_t new_len = len + CLI_SKIP_ONE + strlen(section); |
| 1516 | char *result = malloc(new_len + CLI_SKIP_ONE); |
| 1517 | if (!result) { |
| 1518 | free(content); |
| 1519 | return CLI_ERR; |
| 1520 | } |
| 1521 | memcpy(result, content, len); |
| 1522 | result[len] = '\n'; |
no test coverage detected