mirror of
https://github.com/DeusData/codebase-memory-mcp.git
synced 2026-11-04 10:48:20 +00:00
Merge pull request #2318 from DeusData/fix/issue-1133
fix(cross-repo): fail explicitly when zero target projects resolve (#1133)
This commit is contained in:
5 files changed
+103
-3
No files matched your search
+8
-2
@@ -9947,10 +9947,16 @@ static char *handle_cross_repo_mode(cbm_mcp_server_t *srv, const char *repo_path
|
||||
free(lease_keys);
|
||||
yyjson_doc_free(jdoc);
|
||||
|
||||
if (result.failed) {
|
||||
if (result.no_targets || result.failed) {
|
||||
free(project);
|
||||
return cbm_mcp_text_result(
|
||||
"cross-repo source or target project is missing, invalid, or not indexed", true);
|
||||
result.no_targets
|
||||
? "cross-repo-intelligence resolved zero target projects: no indexed project "
|
||||
"other than the source matched target_projects. Index the other service first "
|
||||
"(run list_projects to see what is indexed); existing cross-repo edges were "
|
||||
"left unchanged."
|
||||
: "cross-repo source or target project is missing, invalid, or not indexed",
|
||||
true);
|
||||
}
|
||||
|
||||
int total = result.http_edges + result.async_edges + result.channel_edges + result.grpc_edges +
|
||||
|
||||
@@ -1239,17 +1239,33 @@ cbm_cross_repo_result_t cbm_cross_repo_match_cancellable(const char *project,
|
||||
result.failed = !result.cancelled;
|
||||
return result;
|
||||
}
|
||||
int other_targets = 0;
|
||||
for (int i = 0; i < resolved_count; i++) {
|
||||
if (cr_cancel_requested(&run)) {
|
||||
result.cancelled = true;
|
||||
free_project_list(resolved, resolved_count);
|
||||
return result;
|
||||
}
|
||||
if (strcmp(resolved[i], project) != 0 && !cr_project_exists(resolved[i])) {
|
||||
if (strcmp(resolved[i], project) == 0) {
|
||||
continue;
|
||||
}
|
||||
if (!cr_project_exists(resolved[i])) {
|
||||
result.failed = true;
|
||||
free_project_list(resolved, resolved_count);
|
||||
return result;
|
||||
}
|
||||
other_targets++;
|
||||
}
|
||||
/* Nothing but the source itself to match against (a self-only list, or
|
||||
* ["*"] in a store holding only the source). Reporting that as success
|
||||
* with projects_scanned:0 is indistinguishable from "these services share
|
||||
* no routes", and the source's existing CROSS_* edges would be wiped below
|
||||
* with nothing to rebuild them. Fail before any write. (#1133) */
|
||||
if (other_targets == 0) {
|
||||
result.failed = true;
|
||||
result.no_targets = true;
|
||||
free_project_list(resolved, resolved_count);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Every input is known to exist before destructive source cleanup. The
|
||||
|
||||
@@ -20,6 +20,7 @@ typedef struct {
|
||||
int projects_scanned;
|
||||
double elapsed_ms;
|
||||
bool failed; /* source/target validation, open, or allocation failed */
|
||||
bool no_targets; /* failed: nothing but the source project resolved (#1133) */
|
||||
bool cancelled; /* stopped at a bounded cancellation checkpoint */
|
||||
bool partial_results; /* committed writes before cancellation were retained */
|
||||
} cbm_cross_repo_result_t;
|
||||
|
||||
@@ -15501,6 +15501,28 @@ TEST(cli_build_args_json_array_flag_accepts_json_literal) {
|
||||
PASS();
|
||||
}
|
||||
|
||||
/* #1133: `index_repository --target-projects '["*"]'` (the form the help
|
||||
* documents) must reach the cross-repo matcher as a one-element array, not as
|
||||
* a single string holding the literal text -- that shape resolved to zero
|
||||
* targets and returned a silent "success" with projects_scanned:0. */
|
||||
TEST(cli_build_args_json_target_projects_literal_issue1133) {
|
||||
char *err = NULL;
|
||||
char *argv[] = {"--repo-path", "/r", "--mode", "cross-repo-intelligence",
|
||||
"--target-projects", "[\"*\"]"};
|
||||
char *json = cbm_cli_build_args_json("index_repository", 6, argv, &err);
|
||||
ASSERT_NOT_NULL(json);
|
||||
ASSERT_NULL(err);
|
||||
ASSERT(strstr(json, "\"target_projects\":[\"*\"]") != NULL);
|
||||
free(json);
|
||||
|
||||
char *argv2[] = {"--repo-path", "/r", "--target-projects", "[\"svc-a\",\"svc-b\"]"};
|
||||
json = cbm_cli_build_args_json("index_repository", 4, argv2, &err);
|
||||
ASSERT_NOT_NULL(json);
|
||||
ASSERT(strstr(json, "\"target_projects\":[\"svc-a\",\"svc-b\"]") != NULL);
|
||||
free(json);
|
||||
PASS();
|
||||
}
|
||||
|
||||
/* An unknown flag for a KNOWN tool must be rejected loudly, not silently
|
||||
* typed as a string and dropped server-side (#997). GF1 eval: `trace_path
|
||||
* --max-depth 1` was accepted, the real --depth stayed at default 3, and
|
||||
@@ -16738,6 +16760,7 @@ SUITE(cli) {
|
||||
RUN_TEST(cli_build_args_json_integer_flag_issue680);
|
||||
RUN_TEST(cli_build_args_json_bare_boolean_issue680);
|
||||
RUN_TEST(cli_build_args_json_array_flag_accepts_json_literal);
|
||||
RUN_TEST(cli_build_args_json_target_projects_literal_issue1133);
|
||||
RUN_TEST(cli_build_args_json_unknown_flag_rejected);
|
||||
RUN_TEST(cli_build_args_json_repeated_array_issue680);
|
||||
RUN_TEST(cli_build_args_json_array_literal);
|
||||
|
||||
@@ -469,6 +469,58 @@ TEST(cross_repo_pre_cancel_preserves_existing_cross_edges) {
|
||||
PASS();
|
||||
}
|
||||
|
||||
/* #1133: a run whose targets resolve to nothing but the source project must
|
||||
* fail explicitly. It used to report "success" with projects_scanned:0 --
|
||||
* indistinguishable from "these services share no routes" -- and, worse, it
|
||||
* had already wiped the source's existing CROSS_* edges before noticing there
|
||||
* was nothing to match against. */
|
||||
TEST(cross_repo_self_only_target_fails_and_keeps_edges_issue1133) {
|
||||
cross_repo_fixture_t fixture;
|
||||
bool setup =
|
||||
cross_repo_fixture_begin(&fixture) &&
|
||||
cross_repo_seed_http_pair(&fixture, "self-source", "self-target", "/self-only", "self");
|
||||
if (!setup) {
|
||||
cross_repo_fixture_end(&fixture);
|
||||
FAIL("failed to seed self-only fixture");
|
||||
}
|
||||
|
||||
const char *target = "self-target";
|
||||
cbm_cross_repo_result_t initial = cbm_cross_repo_match("self-source", &target, 1);
|
||||
int before = cross_repo_count_edges(&fixture, "self-source", "CROSS_HTTP_CALLS");
|
||||
const char *self = "self-source";
|
||||
cbm_cross_repo_result_t result = cbm_cross_repo_match("self-source", &self, 1);
|
||||
int after = cross_repo_count_edges(&fixture, "self-source", "CROSS_HTTP_CALLS");
|
||||
cross_repo_fixture_end(&fixture);
|
||||
|
||||
ASSERT_FALSE(initial.failed);
|
||||
ASSERT_TRUE(before > 0);
|
||||
ASSERT_TRUE(result.failed);
|
||||
ASSERT_TRUE(result.no_targets);
|
||||
ASSERT_EQ(result.projects_scanned, 0);
|
||||
ASSERT_EQ(after, before);
|
||||
PASS();
|
||||
}
|
||||
|
||||
/* #1133: ["*"] in a store that holds only the source project resolves to zero
|
||||
* targets -- same contract as an explicit self-only list. */
|
||||
TEST(cross_repo_wildcard_with_no_other_project_fails_issue1133) {
|
||||
cross_repo_fixture_t fixture;
|
||||
if (!cross_repo_fixture_begin(&fixture) ||
|
||||
!cross_repo_create_project(&fixture, "lonely-source")) {
|
||||
cross_repo_fixture_end(&fixture);
|
||||
FAIL("failed to create isolated source project");
|
||||
}
|
||||
|
||||
const char *targets[] = {"*"};
|
||||
cbm_cross_repo_result_t result = cbm_cross_repo_match("lonely-source", targets, 1);
|
||||
cross_repo_fixture_end(&fixture);
|
||||
|
||||
ASSERT_TRUE(result.failed);
|
||||
ASSERT_TRUE(result.no_targets);
|
||||
ASSERT_EQ(result.projects_scanned, 0);
|
||||
PASS();
|
||||
}
|
||||
|
||||
/* Add the internal "<name>::missed" miss-graph row that indexing writes into
|
||||
* the SAME db whenever a file parses partially. */
|
||||
static bool cross_repo_add_missed_shadow(const cross_repo_fixture_t *fixture, const char *project) {
|
||||
@@ -528,4 +580,6 @@ SUITE(cross_repo) {
|
||||
RUN_TEST(cross_repo_failed_bidirectional_insert_is_not_counted);
|
||||
RUN_TEST(cross_repo_cancel_mid_run_keeps_completed_target_and_stops_before_later_target);
|
||||
RUN_TEST(cross_repo_pre_cancel_preserves_existing_cross_edges);
|
||||
RUN_TEST(cross_repo_self_only_target_fails_and_keeps_edges_issue1133);
|
||||
RUN_TEST(cross_repo_wildcard_with_no_other_project_fails_issue1133);
|
||||
}
|
||||
Reference in new issue
Block a user