code wiki / _hdl_build / nx_decollide.nx

nx_decollide.nx source

↩ module page · 161 lines · 8750 B

1// nx_decollide.nx -- NAME-COLLISION resolver: two DIFFERENT libraries share a basename in two dirs (0 2// shared functions -- NOT versions of one lib; converging would delete a real module). Keep the CANONICAL 3// copy's name (e.g. the one that is a build target, or the majority), and rename ONLY the other copy to a 4// distinct semantic name + repoint ONLY the importers that resolve it. Sound + FULL-SCALE by construction: 5// the renamed copy keeps its exact bytes (just a new name), so lib-importers are behaviour-preserved and 6// their transitive dependents are provably unaffected -- only the DIRECT importers can change, so we 7// rebuild EVERY buildable direct importer and require byte-identical. Commit iff all match, else restore 8// every source + rename back (never-brick). Handles the build-target case (keep the target's name) and 9// third-dir importers (they resolve the kept copy -> untouched) that nx_split_resolve cannot. 10// argv: <lib> <keepdir> <rndir> <newname> <buildonly-elf> <direct-importer-srcpath>... 11// e.g. nx_decollide nx_debt runtime/_hdl_build runtime nx_debt_strategy _offc/nx_buildonly.elf <importers> 12// (keep the _hdl_build tool as nx_debt; rename the runtime strategy-lib to nx_debt_strategy) 13// exit: 0 DECOLLIDED | 1 REFUSED (all restored) | 2 usage/precondition | 3 filesystem move error 14// license_tier: ORIGINAL No hw writes (Rule 26): edits .nx source + rebuilds only. 15import "nx_resolve_lib.nx" 16import "nx_seat_drive_lib.nx" 17import "nx_seg_store.nx" 18import "nx_syscalls.nx" 19 20const DC_MAXC: i64 = 256 21 22func main(argc: i64, argv: *i64) -> i64 { 23 if argc < 7 { 24 sd_w("usage: nx_decollide <lib> <keepdir> <rndir> <newname> <buildonly-elf> <direct-importer-srcpath>...\n" as *u8) 25 sys_exit(2); return 2 26 } 27 let lib: *u8 = argv[1] as *u8 28 let keepdir: *u8 = argv[2] as *u8 29 let rndir: *u8 = argv[3] as *u8 30 let newname: *u8 = argv[4] as *u8 31 let buildelf: *u8 = argv[5] as *u8 32 let nc: i64 = argc - 6 33 if nc > DC_MAXC { sd_w("NX-DECOLLIDE verdict=ABORTED reason=too-many-importers fix=raise-DC_MAXC-or-batch. NOTHING-CHANGED\n" as *u8); sys_exit(2); return 2 } 34 35 let keepp: *u8 = sys_mmap(512) 36 let rnp: *u8 = sys_mmap(512) 37 let newp: *u8 = sys_mmap(512) 38 var o: i64 = 0 39 o = sd_cat(keepp, 0, keepdir); o = sd_cat(keepp, o, "/" as *u8); o = sd_cat(keepp, o, lib); o = sd_cat(keepp, o, ".nx" as *u8) 40 o = sd_cat(rnp, 0, rndir); o = sd_cat(rnp, o, "/" as *u8); o = sd_cat(rnp, o, lib); o = sd_cat(rnp, o, ".nx" as *u8) 41 o = sd_cat(newp, 0, rndir); o = sd_cat(newp, o, "/" as *u8); o = sd_cat(newp, o, newname); o = sd_cat(newp, o, ".nx" as *u8) 42 43 let oldtok: *u8 = sys_mmap(256) 44 let newtok: *u8 = sys_mmap(256) 45 rl_mktok_name(oldtok, lib) 46 rl_mktok_name(newtok, newname) 47 let oll: i64 = rl_strlen(oldtok) 48 let nll: i64 = rl_strlen(newtok) 49 50 let srcbuf: *u8 = sys_mmap(RL_CAP) 51 let outbuf: *u8 = sys_mmap(RL_CAP) 52 let artbuf: *u8 = sys_mmap(RL_CAP) 53 let befbuf: *u8 = sys_mmap(RL_CAP) 54 let base: *u8 = sys_mmap(256) 55 let idir: *u8 = sys_mmap(512) 56 let artp: *u8 = sys_mmap(512) 57 let dcsrc: *u8 = sys_mmap(512) 58 let dcbef: *u8 = sys_mmap(512) 59 let blt: *i64 = sys_mmap(8 * DC_MAXC) as *i64 60 let rept: *i64 = sys_mmap(8 * DC_MAXC) as *i64 61 62 // preconditions: both copies exist + genuinely DIFFER; newname target must not already exist. 63 let l1: i64 = rl_read(keepp, srcbuf, RL_CAP) 64 let l2: i64 = rl_read(rnp, outbuf, RL_CAP) 65 if l1 <= 0 { sd_w("NX-DECOLLIDE verdict=ABORTED reason=keep-copy-not-found:" as *u8); sd_w(keepp); sd_w(" fix=check-keepdir/lib. NOTHING-CHANGED\n" as *u8); sys_exit(2); return 2 } 66 if l2 <= 0 { sd_w("NX-DECOLLIDE verdict=ABORTED reason=rename-copy-not-found:" as *u8); sd_w(rnp); sd_w(" fix=check-rndir/lib. NOTHING-CHANGED\n" as *u8); sys_exit(2); return 2 } 67 if rl_eq(srcbuf, l1, outbuf, l2) == 1 { 68 sd_w("NX-DECOLLIDE verdict=ABORTED reason=the-two-copies-are-BYTE-IDENTICAL(not-a-collision) fix=this-is-a-DEAD-shadow:-use-nx_consol_apply_mc-to-retire-one-copy. NOTHING-CHANGED\n" as *u8) 69 sys_exit(2); return 2 70 } 71 let fd: i64 = sys_openat_rd(newp) 72 if fd >= 0 { sys_close(fd); sd_w("NX-DECOLLIDE verdict=ABORTED reason=newname-target-already-exists:" as *u8); sd_w(newp); sd_w(" fix=choose-a-different-newname. NOTHING-CHANGED\n" as *u8); sys_exit(2); return 2 } 73 74 // PHASE 1: snapshot each importer's source; build+snapshot buildables; classify repoint-target = dir==rndir. 75 var nbuild: i64 = 0 76 var nrep: i64 = 0 77 var c: i64 = 0 78 while c < nc { 79 let srcpath: *u8 = argv[6 + c] as *u8 80 rl_basename(srcpath, base) 81 rl_tmpp(artp, base, ".sov.elf" as *u8) 82 rl_tmpp(dcsrc, base, ".dcsrc" as *u8) 83 rl_tmpp(dcbef, base, ".dcbefore" as *u8) 84 let sn: i64 = rl_read(srcpath, srcbuf, RL_CAP) 85 if sn <= 0 { sd_w("NX-DECOLLIDE verdict=ABORTED reason=importer-source-unreadable:" as *u8); sd_w(srcpath); sd_w(" fix=check-the-srcpath. NOTHING-CHANGED\n" as *u8); sys_exit(2); return 2 } 86 ss_writefile(dcsrc, srcbuf, sn) 87 rl_dirname(srcpath, idir) 88 if rl_streq(idir, rndir) == 1 { rept[c] = 1; nrep = nrep + 1 } else { rept[c] = 0 } 89 let bn: i64 = rl_build(buildelf, base, artp, artbuf) 90 if bn > 0 { blt[c] = 1; ss_writefile(dcbef, artbuf, bn); nbuild = nbuild + 1 } else { blt[c] = 0 } 91 c = c + 1 92 } 93 if nbuild == 0 { 94 sd_w("NX-DECOLLIDE verdict=ABORTED reason=no-importer-builds-standalone(nothing-to-verify-against) fix=list-the-full-direct-importer-set-incl-a-buildable-organ. NOTHING-CHANGED\n" as *u8) 95 sys_exit(2); return 2 96 } 97 if nrep == 0 { 98 sd_w("NX-DECOLLIDE verdict=ABORTED reason=no-importer-lives-in-rndir(none-to-repoint;-are-they-all-resolving-the-KEEP-copy?) fix=verify-rndir-is-the-dir-of-the-copy-to-rename-and-that-its-importers-are-listed. NOTHING-CHANGED\n" as *u8) 99 sys_exit(2); return 2 100 } 101 102 // PHASE 2: rename ONLY the rndir copy. 103 if sys_renameat(rnp, newp) != 0 { sd_w("NX-DECOLLIDE verdict=ABORTED reason=rename-failed(filesystem) fix=check-write-perms-on-rndir. NOTHING-CHANGED\n" as *u8); sys_exit(3); return 3 } 104 105 // PHASE 3: repoint every rndir importer "lib.nx" -> "newname.nx" (from its original source). 106 c = 0 107 while c < nc { 108 if rept[c] == 1 { 109 let srcpath: *u8 = argv[6 + c] as *u8 110 rl_basename(srcpath, base) 111 rl_tmpp(dcsrc, base, ".dcsrc" as *u8) 112 let sn: i64 = rl_read(dcsrc, srcbuf, RL_CAP) 113 let el: i64 = rl_replace(srcbuf, sn, oldtok, oll, newtok, nll, outbuf) 114 if el > 0 { ss_writefile(srcpath, outbuf, el) } 115 } 116 c = c + 1 117 } 118 119 // PHASE 4: rebuild EVERY buildable importer, require byte-identical to its pre-change build. 120 var fail: i64 = 0 121 c = 0 122 while c < nc { 123 if blt[c] == 1 { 124 let srcpath: *u8 = argv[6 + c] as *u8 125 rl_basename(srcpath, base) 126 rl_tmpp(artp, base, ".sov.elf" as *u8) 127 rl_tmpp(dcbef, base, ".dcbefore" as *u8) 128 let bn: i64 = rl_read(dcbef, befbuf, RL_CAP) 129 let an: i64 = rl_build(buildelf, base, artp, artbuf) 130 if an <= 0 { fail = fail + 1; sd_w("DC-CHANGED(build-broke) " as *u8); sd_w(base); sd_w("\n" as *u8) } else { 131 if rl_eq(artbuf, an, befbuf, bn) == 0 { fail = fail + 1; sd_w("DC-CHANGED " as *u8); sd_w(base); sd_w("\n" as *u8) } 132 } 133 } 134 c = c + 1 135 } 136 137 if fail == 0 { 138 sd_w("NX-DECOLLIDE verdict=DECOLLIDED reason=" as *u8) 139 let ob: *u8 = sys_mmap(32); sd_num(ob, 0, nrep); sd_w(ob) 140 sd_w("-rndir-importer(s)-repointed;-all-" as *u8) 141 sd_num(ob, 0, nbuild); sd_w(ob) 142 sd_w("-buildable-importer(s)-byte-identical;-collision-eliminated kept=" as *u8) 143 sd_w(keepp); sd_w(" renamed=" as *u8); sd_w(newp); sd_w("\n" as *u8) 144 sys_exit(0); return 0 145 } 146 // REVERT: restore every source, rename back. 147 c = 0 148 while c < nc { 149 let srcpath: *u8 = argv[6 + c] as *u8 150 rl_basename(srcpath, base) 151 rl_tmpp(dcsrc, base, ".dcsrc" as *u8) 152 let sn: i64 = rl_read(dcsrc, srcbuf, RL_CAP) 153 if sn > 0 { ss_writefile(srcpath, srcbuf, sn) } 154 c = c + 1 155 } 156 sys_renameat(newp, rnp) 157 sd_w("NX-DECOLLIDE verdict=REFUSED reason=" as *u8) 158 let ob2: *u8 = sys_mmap(32); sd_num(ob2, 0, fail); sd_w(ob2) 159 sd_w("-buildable-importer(s)-changed(see-DC-CHANGED):-a-KEEP-dir-importer-actually-resolved-the-renamed-copy,-or-the-importer-set-is-incomplete fix=include-ALL-direct-importers(grep-import-\"lib.nx\");-ALL-sources+name-RESTORED(safe)\n" as *u8) 160 sys_exit(1); return 1 161}