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}