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

Function merge_update_existing

src/graph_buffer/graph_buffer.c:1232–1320  ·  view source on GitHub ↗

Handle QN collision: update dst node fields (src wins), record remap if IDs differ. * label/file_path are re-interned into dst's pool (sn's pointers belong to src). */

Source from the content-addressed store, hash-verified

1230/* Handle QN collision: update dst node fields (src wins), record remap if IDs differ.
1231 * label/file_path are re-interned into dst's pool (sn's pointers belong to src). */
1232static void merge_update_existing(cbm_gbuf_t *dst, cbm_gbuf_node_t *existing,
1233 const cbm_gbuf_node_t *sn, CBMHashTable **remap) {
1234 /* Same guard as cbm_gbuf_upsert_node: a per-file "Module" def coming from a
1235 * worker-local gbuf must not touch the structural directory node ("Project"
1236 * root or "Folder") that shares its QN in a directory-based-module language
1237 * (Java/Go). pass_structure seeds Folder/Project nodes on the MAIN gbuf
1238 * before the parallel extract, so every worker's always-emitted Module def
1239 * for that package collides here; unconditional "src wins" relabelled the
1240 * directory node to Module and set its file_path to whichever worker merged
1241 * LAST — the nondeterministic USAGE-source misattribution of #787. Keep the
1242 * structural node intact; the ID remap below still redirects the worker's
1243 * edges onto the canonical node. */
1244 bool module_on_container =
1245 existing->label && sn->label && strcmp(sn->label, "Module") == 0 &&
1246 (strcmp(existing->label, "Project") == 0 || strcmp(existing->label, "Folder") == 0);
1247 if (!module_on_container) {
1248 /* Canonical collision winner (determinism) — mirrors
1249 * cbm_gbuf_upsert_node exactly. Distinct source entities can share a
1250 * QN (C: struct/function/macro with one name); unconditional "src
1251 * wins" made the survivor depend on worker merge order, flickering
1252 * the node set (and every downstream consumer) run to run. Winner =
1253 * smallest file_path, then LARGEST start_line, then largest
1254 * name/label — one total order, commutative, scheduling-free; a full
1255 * tie is the same entity → refresh from src. */
1256 int c = strcmp(sn->file_path ? sn->file_path : "",
1257 existing->file_path ? existing->file_path : "");
1258 if (c == 0) {
1259 c = existing->start_line - sn->start_line;
1260 }
1261 if (c == 0) {
1262 c = strcmp(existing->name ? existing->name : "", sn->name ? sn->name : "");
1263 }
1264 if (c == 0) {
1265 c = strcmp(existing->label ? existing->label : "", sn->label ? sn->label : "");
1266 }
1267 bool sn_wins = c <= 0;
1268 if (sn_wins) {
1269 /* Keep the secondary indexes consistent when the surviving
1270 * label/name changes (the old code left the node listed under its
1271 * original label/name, so find_by_label/name mis-listed it). */
1272 const char *new_label = gb_intern(dst, sn->label);
1273 bool label_changed =
1274 !existing->label || !new_label || strcmp(existing->label, new_label) != 0;
1275 bool name_changed =
1276 !existing->name || !sn->name || strcmp(existing->name, sn->name) != 0;
1277 if (label_changed) {
1278 remove_node_from_ptr_array(
1279 cbm_ht_get(dst->nodes_by_label, existing->label ? existing->label : ""),
1280 existing->id);
1281 }
1282 if (name_changed) {
1283 remove_node_from_ptr_array(
1284 cbm_ht_get(dst->nodes_by_name, existing->name ? existing->name : ""),
1285 existing->id);
1286 }
1287 existing->label = (char *)new_label;
1288 free(existing->name);
1289 existing->name = heap_strdup(sn->name);

Callers 1

cbm_gbuf_mergeFunction · 0.85

Calls 8

gb_internFunction · 0.85
cbm_ht_getFunction · 0.85
get_or_create_node_arrayFunction · 0.85
cbm_ht_createFunction · 0.85
make_id_keyFunction · 0.85
cbm_ht_setFunction · 0.85
heap_strdupFunction · 0.70

Tested by

no test coverage detected