nx_pushback_publish.nx source
↩ module page · 145 lines · 8072 B
1// nx_pushback_publish.nx -- THE COMMUNITY PUSH-BACK COMMAND (/compare/modding MD23 pushback_publish, 2026-09-06). A thin caller
2// of nx_pushback_lib: one sovereign manifest, N community targets from knowledge/modding_communities.conf, one bundle per
3// community (the byte-identical manifest, the estate-written 7z, the content id, magnet, download url and index row, and the
4// publish row carrying the licence row and the referee grade). Every refusal is NAMED on its own line and the summary
5// partition sums (requested = published + refused).
6// usage: nx_pushback_publish publish <pkg-root> <manifest.nxmod> <community[,community...]> [outdir=<dir>] [grade=<file>] [conf=<path>] [jrnl=<path>]
7// nx_pushback_publish communities [conf=<path>]
8// outdir defaults to <pkg-root>/pushback; grade defaults to <pkg-root>/referee.grade (no grade file = UNGRADED, and an
9// ungraded package never publishes); conf defaults to knowledge/modding_communities.conf; jrnl to the ONE asset journal.
10// exits: 0 every requested community published (GREEN) - 2 usage - 3 at least one community refused (RED, each named) -
11// 4 the request refused before any community was tried (conf or manifest unreadable)
12// license_tier: ORIGINAL No hw writes (Rule 26).
13import "nx_syscalls.nx"
14import "nx_pushback_lib.nx"
15
16const PP_EXIT_OK: i64 = 0
17const PP_EXIT_USAGE: i64 = 2
18const PP_EXIT_REFUSED: i64 = 3
19const PP_EXIT_REQUEST: i64 = 4
20const PP_ARGC_PUBLISH: i64 = 5
21const PP_ARG_ROOT: i64 = 2
22const PP_ARG_MANIFEST: i64 = 3
23const PP_ARG_IDS: i64 = 4
24const PP_KEY_OUTDIR: *u8 = "outdir="
25const PP_KEY_GRADE: *u8 = "grade="
26const PP_KEY_CONF: *u8 = "conf="
27const PP_KEY_JRNL: *u8 = "jrnl="
28const PP_VERB_PUBLISH: *u8 = "publish"
29const PP_VERB_COMMUNITIES: *u8 = "communities"
30
31func pp_usage() -> i64 {
32 pv_puts("usage: nx_pushback_publish publish <pkg-root> <manifest.nxmod> <community[,community...]> [outdir=<dir>] [grade=<file>] [conf=<path>] [jrnl=<path>]\n" as *u8)
33 pv_puts(" nx_pushback_publish communities [conf=<path>]\n" as *u8)
34 return PP_EXIT_USAGE
35}
36func pp_prefix(s: *u8, pfx: *u8) -> i64 {
37 var i: i64 = 0
38 while pfx[i] != (0 as u8) { if s[i] != pfx[i] { return 0 } i = i + 1 }
39 return 1
40}
41func pp_arg(argc: i64, argv: *i64, key: *u8) -> *u8 {
42 var i: i64 = 2
43 while i < argc {
44 let a: *u8 = argv[i] as *u8
45 if pp_prefix(a, key) == 1 { return a + mm_len(key) }
46 i = i + 1
47 }
48 return 0 as *u8
49}
50func pp_kv(k: *u8, v: *u8) -> i64 { pv_puts(" " as *u8); pv_puts(k); pv_puts("=" as *u8); pv_puts(v); return 0 }
51func pp_kvn(k: *u8, v: i64) -> i64 { pv_puts(" " as *u8); pv_puts(k); pv_puts("=" as *u8); pv_putn(v); return 0 }
52func pp_under(root: *u8, name: *u8) -> *u8 { let o: *u8 = sys_mmap(PB_PATH_CAP); mm_join_path(root, name, o); return o }
53
54func main(argc: i64, argv: *i64) -> i64 {
55 if argc < 2 { return pp_usage() }
56 let verb: *u8 = argv[1] as *u8
57 if mm_streq(verb, PP_VERB_COMMUNITIES) == 1 {
58 var conf: *u8 = pp_arg(argc, argv, PP_KEY_CONF)
59 if (conf as i64) == 0 { conf = PB_CONF_DEFAULT }
60 let tbl: *i64 = sys_mmap(8 * PB_C_SLOTS * PB_MAX_COMMUNITIES) as *i64
61 let n: i64 = pb_conf_load(conf, tbl, PB_MAX_COMMUNITIES)
62 if n < 0 {
63 pv_puts("COMMUNITIES-REFUSED rule=CONF-UNREADABLE" as *u8); pp_kv("conf" as *u8, conf); pv_puts("\n" as *u8)
64 return PP_EXIT_REQUEST
65 }
66 var i: i64 = 0
67 while i < n {
68 let b: i64 = i * PB_C_SLOTS
69 pv_puts("COMMUNITY" as *u8)
70 pp_kv("id" as *u8, tbl[b + PB_C_ID] as *u8)
71 pp_kv("kind" as *u8, tbl[b + PB_C_KIND] as *u8)
72 pp_kv("endpoint" as *u8, tbl[b + PB_C_ENDPOINT] as *u8)
73 pp_kvn("minredist" as *u8, tbl[b + PB_C_MINREDIST])
74 pp_kv("note" as *u8, tbl[b + PB_C_NOTE] as *u8)
75 pv_puts("\n" as *u8)
76 i = i + 1
77 }
78 pv_puts("COMMUNITIES" as *u8); pp_kvn("rows" as *u8, n); pp_kv("conf" as *u8, conf); pv_puts(" verdict=GREEN\n" as *u8)
79 return PP_EXIT_OK
80 }
81 if mm_streq(verb, PP_VERB_PUBLISH) == 0 { return pp_usage() }
82 if argc < PP_ARGC_PUBLISH {
83 pv_puts("PUSHBACK-USAGE publish needs <pkg-root> <manifest.nxmod> <community[,community...]>\n" as *u8)
84 return pp_usage()
85 }
86 let root: *u8 = argv[PP_ARG_ROOT] as *u8
87 let mpath: *u8 = argv[PP_ARG_MANIFEST] as *u8
88 let ids: *u8 = argv[PP_ARG_IDS] as *u8
89 var outdir: *u8 = pp_arg(argc, argv, PP_KEY_OUTDIR)
90 if (outdir as i64) == 0 { outdir = pp_under(root, PB_OUTDIR_DEFAULT_NAME) }
91 var grade: *u8 = pp_arg(argc, argv, PP_KEY_GRADE)
92 if (grade as i64) == 0 { grade = pp_under(root, PB_GRADE_DEFAULT_NAME) }
93 var conf: *u8 = pp_arg(argc, argv, PP_KEY_CONF)
94 if (conf as i64) == 0 { conf = PB_CONF_DEFAULT }
95 var jrnl: *u8 = pp_arg(argc, argv, PP_KEY_JRNL)
96 if (jrnl as i64) == 0 { jrnl = PV_JRNL_DEFAULT }
97 let sum: *i64 = sys_mmap(8 * PB_S_N) as *i64
98 let rows: *i64 = sys_mmap(8 * PB_R_N * PB_MAX_IDS) as *i64
99 let got: i64 = pushback_publish(root, mpath, ids, outdir, grade, conf, jrnl, sum, rows)
100 if got < 0 {
101 pv_puts("PUSHBACK-REFUSED rule=" as *u8); pv_puts(pb_err_name(got))
102 pp_kv("manifest" as *u8, mpath); pp_kv("conf" as *u8, conf); pv_puts("\n" as *u8)
103 pv_puts("PUSHBACK" as *u8); pp_kvn("requested" as *u8, sum[PB_S_REQUESTED]); pp_kvn("published" as *u8, 0)
104 pp_kvn("refused" as *u8, sum[PB_S_REQUESTED]); pp_kvn("identical_manifests" as *u8, 0); pv_puts(" verdict=RED\n" as *u8)
105 return PP_EXIT_REQUEST
106 }
107 // the member paths, for naming the member that refused
108 let lp: *i64 = sys_mmap(16) as *i64
109 let mb: *u8 = sys_read_file(mpath, lp)
110 let m: *i64 = sys_mmap(8 * MM_M_N_SLOTS) as *i64
111 var paths: *i64 = 0 as *i64
112 if (mb as i64) != 0 { if mm_parse(mb, lp[0], m) == MM_OK { paths = m[MM_M_PATHS] as *i64 } }
113 let parts: *i64 = sys_mmap(8 * PB_MAX_IDS) as *i64
114 let k: i64 = mm_split_csv(ids, parts, PB_MAX_IDS)
115 var j: i64 = 0
116 while j < k {
117 let r: *i64 = ((rows as i64) + j * PB_R_N * 8) as *i64
118 let id: *u8 = parts[j] as *u8
119 if r[PB_R_RC] == PB_OK {
120 pv_puts("PUSHBACK" as *u8); pp_kv("community" as *u8, id); pp_kv("kind" as *u8, pb_kind_name(r[PB_R_KIND]))
121 pv_puts(" verdict=PUBLISHED" as *u8); pp_kv("dir" as *u8, r[PB_R_OUTDIR] as *u8)
122 pp_kvn("archive_bytes" as *u8, r[PB_R_ARCHIVE_BYTES]); pp_kv("cid" as *u8, r[PB_R_CID] as *u8)
123 pp_kv("manifest_sha" as *u8, r[PB_R_MANIFEST_SHA] as *u8); pp_kvn("referee_permil" as *u8, sum[PB_S_PERMIL])
124 pp_kv("transport" as *u8, pb_transport_name(r[PB_R_KIND])); pv_puts("\n" as *u8)
125 } else {
126 let rc: i64 = r[PB_R_RC]
127 pv_puts("PUSHBACK-REFUSED" as *u8); pp_kv("community" as *u8, id); pp_kv("rule" as *u8, pb_err_name(rc))
128 let mi: i64 = r[PB_R_MEMBER_IDX]
129 if mi >= 0 { if (paths as i64) != 0 { pp_kv("member" as *u8, paths[mi] as *u8) } else { pp_kvn("member" as *u8, mi) } }
130 else { pp_kv("member" as *u8, PB_DASH_S) }
131 if rc == PB_ERR_PROVENANCE { pp_kv("reason" as *u8, pv_reason_name(r[PB_R_REASON])) }
132 else { if rc == PB_ERR_MANIFEST_REFUSED { pp_kv("reason" as *u8, mm_verdict_name(r[PB_R_REASON])) }
133 else { if rc == PB_ERR_NON_REDISTRIBUTABLE { pp_kvn("redist" as *u8, r[PB_R_REASON]) }
134 else { pp_kv("reason" as *u8, PB_DASH_S) } } }
135 pv_puts("\n" as *u8)
136 }
137 j = j + 1
138 }
139 pv_puts("PUSHBACK" as *u8); pp_kvn("requested" as *u8, sum[PB_S_REQUESTED]); pp_kvn("published" as *u8, sum[PB_S_PUBLISHED])
140 pp_kvn("refused" as *u8, sum[PB_S_REFUSED]); pp_kvn("identical_manifests" as *u8, sum[PB_S_IDENTICAL])
141 pp_kvn("members" as *u8, sum[PB_S_MEMBERS]); pp_kvn("referee_permil" as *u8, sum[PB_S_PERMIL])
142 if sum[PB_S_REFUSED] == 0 { pv_puts(" verdict=GREEN\n" as *u8); return PP_EXIT_OK }
143 pv_puts(" verdict=RED\n" as *u8)
144 return PP_EXIT_REFUSED
145}