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

Function merge_update_existing

src/graph_buffer/graph_buffer.c:1182–1270  ·  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

1180/* Handle QN collision: update dst node fields (src wins), record remap if IDs differ.
1181 * label/file_path are re-interned into dst's pool (sn's pointers belong to src). */
1182static void merge_update_existing(cbm_gbuf_t *dst, cbm_gbuf_node_t *existing,
1183 const cbm_gbuf_node_t *sn, CBMHashTable **remap) {
1184 /* Same guard as cbm_gbuf_upsert_node: a per-file "Module" def coming from a
1185 * worker-local gbuf must not touch the structural directory node ("Project"
1186 * root or "Folder") that shares its QN in a directory-based-module language
1187 * (Java/Go). pass_structure seeds Folder/Project nodes on the MAIN gbuf
1188 * before the parallel extract, so every worker's always-emitted Module def
1189 * for that package collides here; unconditional "src wins" relabelled the
1190 * directory node to Module and set its file_path to whichever worker merged
1191 * LAST — the nondeterministic USAGE-source misattribution of #787. Keep the
1192 * structural node intact; the ID remap below still redirects the worker's
1193 * edges onto the canonical node. */
1194 bool module_on_container =
1195 existing->label && sn->label && strcmp(sn->label, "Module") == 0 &&
1196 (strcmp(existing->label, "Project") == 0 || strcmp(existing->label, "Folder") == 0);
1197 if (!module_on_container) {
1198 /* Canonical collision winner (determinism) — mirrors
1199 * cbm_gbuf_upsert_node exactly. Distinct source entities can share a
1200 * QN (C: struct/function/macro with one name); unconditional "src
1201 * wins" made the survivor depend on worker merge order, flickering
1202 * the node set (and every downstream consumer) run to run. Winner =
1203 * smallest file_path, then LARGEST start_line, then largest
1204 * name/label — one total order, commutative, scheduling-free; a full
1205 * tie is the same entity → refresh from src. */
1206 int c = strcmp(sn->file_path ? sn->file_path : "",
1207 existing->file_path ? existing->file_path : "");
1208 if (c == 0) {
1209 c = existing->start_line - sn->start_line;
1210 }
1211 if (c == 0) {
1212 c = strcmp(existing->name ? existing->name : "", sn->name ? sn->name : "");
1213 }
1214 if (c == 0) {
1215 c = strcmp(existing->label ? existing->label : "", sn->label ? sn->label : "");
1216 }
1217 bool sn_wins = c <= 0;
1218 if (sn_wins) {
1219 /* Keep the secondary indexes consistent when the surviving
1220 * label/name changes (the old code left the node listed under its
1221 * original label/name, so find_by_label/name mis-listed it). */
1222 const char *new_label = gb_intern(dst, sn->label);
1223 bool label_changed =
1224 !existing->label || !new_label || strcmp(existing->label, new_label) != 0;
1225 bool name_changed =
1226 !existing->name || !sn->name || strcmp(existing->name, sn->name) != 0;
1227 if (label_changed) {
1228 remove_node_from_ptr_array(
1229 cbm_ht_get(dst->nodes_by_label, existing->label ? existing->label : ""),
1230 existing->id);
1231 }
1232 if (name_changed) {
1233 remove_node_from_ptr_array(
1234 cbm_ht_get(dst->nodes_by_name, existing->name ? existing->name : ""),
1235 existing->id);
1236 }
1237 existing->label = (char *)new_label;
1238 free(existing->name);
1239 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