release: Bux v1.0.0 language freeze
ci / build (ubuntu) (push) Has been cancelled
ci / unit + fmt (push) Has been cancelled
ci / examples (push) Has been cancelled
ci / goldens + tools (push) Has been cancelled
ci / apps (push) Has been cancelled
ci / selfhost smoke (push) Has been cancelled
ci / macos smoke (push) Has been cancelled
ci / windows smoke (push) Has been cancelled
ci / CI gate (push) Has been cancelled
selfhost-loop / bootstrap determinism (push) Has been cancelled
ci / build (ubuntu) (push) Has been cancelled
ci / unit + fmt (push) Has been cancelled
ci / examples (push) Has been cancelled
ci / goldens + tools (push) Has been cancelled
ci / apps (push) Has been cancelled
ci / selfhost smoke (push) Has been cancelled
ci / macos smoke (push) Has been cancelled
ci / windows smoke (push) Has been cancelled
ci / CI gate (push) Has been cancelled
selfhost-loop / bootstrap determinism (push) Has been cancelled
Bump compiler banners and package version to 1.0.0, activate SEMVER policy, and add RELEASE_v1.0.0 notes. Fix closure auto-Drop leaking outer Array drops into nested capture bodies (iter_hof). Fmt-clean examples/src for CI.
This commit is contained in:
+12
-12
@@ -59,8 +59,8 @@ module Cli {
|
||||
return "rt/runtime_win.c";
|
||||
}
|
||||
if String_Eq(env, "minimal") || String_Eq(env, "thin") ||
|
||||
String_Eq(env, "embed") || String_Eq(env, "embedded") ||
|
||||
String_Eq(env, "freestanding") {
|
||||
String_Eq(env, "embed") || String_Eq(env, "embedded") ||
|
||||
String_Eq(env, "freestanding") {
|
||||
return "rt/runtime_minimal.c";
|
||||
}
|
||||
if String_Eq(env, "full") || String_Eq(env, "posix") {
|
||||
@@ -141,7 +141,7 @@ module Cli {
|
||||
}
|
||||
|
||||
func Cli_LinkProgram(cFile: String, outBin: String, projectDir: String,
|
||||
targetTriple: String, isRelease: bool, isStatic: bool) -> int {
|
||||
targetTriple: String, isRelease: bool, isStatic: bool) -> int {
|
||||
let relRt: String = Cli_RuntimeRel(isStatic, targetTriple);
|
||||
let rtPath: String = Cli_FindRtFile(projectDir, relRt);
|
||||
let ioPath: String = Cli_FindRtFile(projectDir, "rt/io.c");
|
||||
@@ -1179,8 +1179,8 @@ func Cli_PackageChecksum(dir: String) -> String {
|
||||
return "";
|
||||
}
|
||||
let cmd: String = String_Concat(
|
||||
"find \"",
|
||||
String_Concat(dir, "\" -name '*.bux' -type f 2>/dev/null | LC_ALL=C sort | xargs cat 2>/dev/null | sha1sum | awk '{print $1}'")
|
||||
"find \"",
|
||||
String_Concat(dir, "\" -name '*.bux' -type f 2>/dev/null | LC_ALL=C sort | xargs cat 2>/dev/null | sha1sum | awk '{print $1}'")
|
||||
);
|
||||
let out: String = bux_process_output(cmd);
|
||||
if out == null as String { return ""; }
|
||||
@@ -1205,7 +1205,7 @@ func Cli_DepResolvedPath(projectDir: String, depName: String, depUrl: String) ->
|
||||
return depUrl;
|
||||
}
|
||||
if String_StartsWith(depUrl, "http://") || String_StartsWith(depUrl, "https://") ||
|
||||
String_EndsWith(depUrl, ".git") {
|
||||
String_EndsWith(depUrl, ".git") {
|
||||
return bux_path_join(bux_path_join(projectDir, "deps"), depName);
|
||||
}
|
||||
// relative path
|
||||
@@ -1245,7 +1245,7 @@ func Cli_InstallLocked(projectDir: String) -> int {
|
||||
path = bux_path_join(projectDir, source);
|
||||
}
|
||||
if String_StartsWith(source, "http://") || String_StartsWith(source, "https://") ||
|
||||
String_EndsWith(source, ".git") {
|
||||
String_EndsWith(source, ".git") {
|
||||
path = bux_path_join(bux_path_join(projectDir, "deps"), name);
|
||||
}
|
||||
if !DirExists(path) {
|
||||
@@ -1342,7 +1342,7 @@ func Cli_Install(projectDir: String, lockedOnly: bool) -> int {
|
||||
|
||||
// Fetch git deps into deps/<name> when missing
|
||||
if String_StartsWith(depUrl, "http://") || String_StartsWith(depUrl, "https://") ||
|
||||
String_EndsWith(depUrl, ".git") {
|
||||
String_EndsWith(depUrl, ".git") {
|
||||
let depsDir: String = bux_path_join(projectDir, "deps");
|
||||
discard bux_mkdir_if_needed(depsDir);
|
||||
let depPath: String = bux_path_join(depsDir, depName);
|
||||
@@ -2254,7 +2254,7 @@ func Cli_Run(args: *String, argCount: int) -> int {
|
||||
}
|
||||
|
||||
if argCount < 2 {
|
||||
PrintLine("Bux Self-Hosting Compiler v0.2.0");
|
||||
PrintLine("Bux Self-Hosting Compiler v1.0.0");
|
||||
PrintLine("Usage: buxc <command> [args]");
|
||||
PrintLine("Commands: build, check, new, init, add, remove, fetch, install, search, fmt, doc, test, run, project, help, version");
|
||||
PrintLine(" test --filter <name> Only run tests/*.bux whose name contains <name>");
|
||||
@@ -2272,12 +2272,12 @@ func Cli_Run(args: *String, argCount: int) -> int {
|
||||
|
||||
let cmd: String = args[1];
|
||||
if String_Eq(cmd, "version") || String_Eq(cmd, "--version") || String_Eq(cmd, "-v") {
|
||||
PrintLine("Bux 0.2.0 (self-hosting bootstrap)");
|
||||
PrintLine("Bux 1.0.0 (self-hosting)");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if String_Eq(cmd, "help") || String_Eq(cmd, "--help") || String_Eq(cmd, "-h") {
|
||||
PrintLine("Bux Self-Hosting Compiler v0.2.0");
|
||||
PrintLine("Bux Self-Hosting Compiler v1.0.0");
|
||||
PrintLine("Usage: buxc <command> [args]");
|
||||
PrintLine("Commands: build, check, new, init, add, remove, fetch, install, search, fmt, doc, test, run, project, help, version");
|
||||
PrintLine(" test --filter <name> Only run tests/*.bux whose name contains <name>");
|
||||
@@ -2330,7 +2330,7 @@ func Cli_Run(args: *String, argCount: int) -> int {
|
||||
if argCount >= 4 {
|
||||
let a3: String = args[3];
|
||||
if !String_Contains(a3, "/") && !String_StartsWith(a3, "http") &&
|
||||
!String_EndsWith(a3, ".git") {
|
||||
!String_EndsWith(a3, ".git") {
|
||||
return Cli_AddFromRegistry(args[2], a3);
|
||||
}
|
||||
return Cli_Add(args[2], a3);
|
||||
|
||||
+6
-6
@@ -467,7 +467,7 @@ module MacroExpand {
|
||||
wrap.child1 = aexp;
|
||||
// group flag: tuple or non-empty slice lit
|
||||
wrap.boolValue = aexp.kind == ekTuple ||
|
||||
(aexp.kind == ekSlice && aexp.callArgCount > 0);
|
||||
(aexp.kind == ekSlice && aexp.callArgCount > 0);
|
||||
return wrap;
|
||||
}
|
||||
// type — session 87: named / pointer type from call-site expr shape
|
||||
@@ -845,7 +845,7 @@ module MacroExpand {
|
||||
|
||||
// Build callArgs for a call/macro-call, flattening MacroRep and MacroTt groups.
|
||||
func Macro_SubstCallArgs(oldArgs: *ExprList, env: *MacroEnv, file: String, line: uint32, col: uint32,
|
||||
outCount: *int) -> *ExprList {
|
||||
outCount: *int) -> *ExprList {
|
||||
var first: *ExprList = null as *ExprList;
|
||||
var last: *ExprList = null as *ExprList;
|
||||
var count: int = 0;
|
||||
@@ -895,8 +895,8 @@ module MacroExpand {
|
||||
let bound: *Expr = Env_Lookup(env, a.strValue);
|
||||
// Bare `$args:tt` group → flatten tuple/slice elements as call args
|
||||
if bound != null as *Expr && bound.kind == ekMacroTt && bound.boolValue &&
|
||||
bound.child1 != null as *Expr &&
|
||||
(bound.child1.kind == ekTuple || bound.child1.kind == ekSlice) {
|
||||
bound.child1 != null as *Expr &&
|
||||
(bound.child1.kind == ekTuple || bound.child1.kind == ekSlice) {
|
||||
var tel: *ExprList = bound.child1.callArgs;
|
||||
while tel != null as *ExprList {
|
||||
let ce: *Expr = Ast_CloneExpr(tel.expr);
|
||||
@@ -1197,8 +1197,8 @@ module MacroExpand {
|
||||
let k1: String = Macro_KindAt(kinds, 1);
|
||||
let only: *Expr = expArgs.expr;
|
||||
if String_Eq(k0, "ident") && String_Eq(k1, "tt") &&
|
||||
only != null as *Expr && only.kind == ekCall &&
|
||||
only.child1 != null as *Expr && only.child1.kind == ekIdent {
|
||||
only != null as *Expr && only.kind == ekCall &&
|
||||
only.child1 != null as *Expr && only.child1.kind == ekIdent {
|
||||
let callee: *Expr = only.child1;
|
||||
// Build MacroTt group from call args (tuple of elements)
|
||||
let inner: *Expr = bux_alloc(sizeof(Expr)) as *Expr;
|
||||
|
||||
+1
-1
@@ -92,7 +92,7 @@ module Manifest {
|
||||
while pi + 4 < pl {
|
||||
// match ASCII 'P','a','t','h'
|
||||
if line[pi] == 80 as char8 && line[pi + 1] == 97 as char8 &&
|
||||
line[pi + 2] == 116 as char8 && line[pi + 3] == 104 as char8 {
|
||||
line[pi + 2] == 116 as char8 && line[pi + 3] == 104 as char8 {
|
||||
var q1: int = -1;
|
||||
var qj: uint = pi;
|
||||
while qj < pl {
|
||||
|
||||
+4
-4
@@ -2465,8 +2465,8 @@ module Parser {
|
||||
if String_Eq(kname, "lit") { kname = "literal"; }
|
||||
if String_Eq(kname, "pattern") { kname = "pat"; }
|
||||
if !(String_Eq(kname, "expr") || String_Eq(kname, "ident") || String_Eq(kname, "tt")
|
||||
|| String_Eq(kname, "literal") || String_Eq(kname, "block")
|
||||
|| String_Eq(kname, "stmt") || String_Eq(kname, "pat") || String_Eq(kname, "type")) {
|
||||
|| String_Eq(kname, "literal") || String_Eq(kname, "block")
|
||||
|| String_Eq(kname, "stmt") || String_Eq(kname, "pat") || String_Eq(kname, "type")) {
|
||||
kname = "expr";
|
||||
}
|
||||
if nIn == 0 {
|
||||
@@ -2519,8 +2519,8 @@ module Parser {
|
||||
if String_Eq(kname, "lit") { kname = "literal"; }
|
||||
if String_Eq(kname, "pattern") { kname = "pat"; }
|
||||
if !(String_Eq(kname, "expr") || String_Eq(kname, "ident") || String_Eq(kname, "tt")
|
||||
|| String_Eq(kname, "literal") || String_Eq(kname, "block")
|
||||
|| String_Eq(kname, "stmt") || String_Eq(kname, "pat") || String_Eq(kname, "type")) {
|
||||
|| String_Eq(kname, "literal") || String_Eq(kname, "block")
|
||||
|| String_Eq(kname, "stmt") || String_Eq(kname, "pat") || String_Eq(kname, "type")) {
|
||||
kname = "expr";
|
||||
}
|
||||
if rule.paramCount < 9 {
|
||||
|
||||
+237
-237
@@ -100,8 +100,8 @@ module Registry {
|
||||
}
|
||||
// prefer curl
|
||||
let curlCmd: String = String_Concat(
|
||||
"curl -fsSL",
|
||||
String_Concat(kflag, String_Concat(" --max-time 30 -o \"", String_Concat(cachePath, String_Concat("\" \"", String_Concat(url, "\"")))))
|
||||
"curl -fsSL",
|
||||
String_Concat(kflag, String_Concat(" --max-time 30 -o \"", String_Concat(cachePath, String_Concat("\" \"", String_Concat(url, "\"")))))
|
||||
);
|
||||
var ok: bool = false;
|
||||
if bux_system("command -v curl >/dev/null 2>&1") == 0 {
|
||||
@@ -112,8 +112,8 @@ module Registry {
|
||||
nflag = " --no-check-certificate";
|
||||
}
|
||||
let wgetCmd: String = String_Concat(
|
||||
"wget -q",
|
||||
String_Concat(nflag, String_Concat(" -T 30 -O \"", String_Concat(cachePath, String_Concat("\" \"", String_Concat(url, "\"")))))
|
||||
"wget -q",
|
||||
String_Concat(nflag, String_Concat(" -T 30 -O \"", String_Concat(cachePath, String_Concat("\" \"", String_Concat(url, "\"")))))
|
||||
);
|
||||
ok = bux_system(wgetCmd) == 0 && Reg_FileExists(cachePath);
|
||||
}
|
||||
@@ -141,240 +141,240 @@ module Registry {
|
||||
if String_StartsWith(src, "file:") {
|
||||
p = String_Slice(src, 5, bux_strlen(src) - 5);
|
||||
if String_StartsWith(p, "//") {
|
||||
p = String_Slice(p, 2, bux_strlen(p) - 2);
|
||||
}
|
||||
} else if String_StartsWith(src, "path:") {
|
||||
p = String_Slice(src, 5, bux_strlen(src) - 5);
|
||||
} else {
|
||||
return "";
|
||||
p = String_Slice(p, 2, bux_strlen(p) - 2);
|
||||
}
|
||||
if String_StartsWith(p, "/") {
|
||||
return p;
|
||||
}
|
||||
return bux_path_join(indexDir, p);
|
||||
} else if String_StartsWith(src, "path:") {
|
||||
p = String_Slice(src, 5, bux_strlen(src) - 5);
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
|
||||
func Reg_SetPkg(reg: *Registry, idx: int, pkg: RegistryPackage) {
|
||||
if idx == 0 { reg.p0 = pkg; }
|
||||
else if idx == 1 { reg.p1 = pkg; }
|
||||
else if idx == 2 { reg.p2 = pkg; }
|
||||
else if idx == 3 { reg.p3 = pkg; }
|
||||
else if idx == 4 { reg.p4 = pkg; }
|
||||
else if idx == 5 { reg.p5 = pkg; }
|
||||
else if idx == 6 { reg.p6 = pkg; }
|
||||
else if idx == 7 { reg.p7 = pkg; }
|
||||
else if idx == 8 { reg.p8 = pkg; }
|
||||
else if idx == 9 { reg.p9 = pkg; }
|
||||
else if idx == 10 { reg.p10 = pkg; }
|
||||
else if idx == 11 { reg.p11 = pkg; }
|
||||
else if idx == 12 { reg.p12 = pkg; }
|
||||
else if idx == 13 { reg.p13 = pkg; }
|
||||
else if idx == 14 { reg.p14 = pkg; }
|
||||
else if idx == 15 { reg.p15 = pkg; }
|
||||
}
|
||||
|
||||
func Reg_GetPkg(reg: Registry, idx: int) -> RegistryPackage {
|
||||
if idx == 0 { return reg.p0; }
|
||||
if idx == 1 { return reg.p1; }
|
||||
if idx == 2 { return reg.p2; }
|
||||
if idx == 3 { return reg.p3; }
|
||||
if idx == 4 { return reg.p4; }
|
||||
if idx == 5 { return reg.p5; }
|
||||
if idx == 6 { return reg.p6; }
|
||||
if idx == 7 { return reg.p7; }
|
||||
if idx == 8 { return reg.p8; }
|
||||
if idx == 9 { return reg.p9; }
|
||||
if idx == 10 { return reg.p10; }
|
||||
if idx == 11 { return reg.p11; }
|
||||
if idx == 12 { return reg.p12; }
|
||||
if idx == 13 { return reg.p13; }
|
||||
if idx == 14 { return reg.p14; }
|
||||
return reg.p15;
|
||||
}
|
||||
|
||||
func Reg_ParseContent(content: String, indexPath: String) -> Registry {
|
||||
var reg: Registry;
|
||||
reg.path = indexPath;
|
||||
reg.sourceUrl = "";
|
||||
reg.count = 0;
|
||||
let indexDir: String = bux_path_parent(indexPath);
|
||||
var cur: RegistryPackage;
|
||||
var inPkg: bool = false;
|
||||
let nlines: uint = String_SplitCount(content, "\n");
|
||||
var i: uint = 0;
|
||||
while i <= nlines {
|
||||
var line: String = "";
|
||||
if i < nlines {
|
||||
line = String_Trim(String_SplitPart(content, "\n", i));
|
||||
}
|
||||
let flush: bool = (i == nlines) || String_Eq(line, "[[package]]") || String_Eq(line, "[[Package]]");
|
||||
if flush && inPkg && !String_Eq(cur.name, "") {
|
||||
cur.resolvedPath = Reg_ResolveSource(cur.source, indexDir);
|
||||
if reg.count < 16 {
|
||||
Reg_SetPkg(®, reg.count, cur);
|
||||
reg.count = reg.count + 1;
|
||||
}
|
||||
cur.name = "";
|
||||
cur.version = "";
|
||||
cur.source = "";
|
||||
cur.description = "";
|
||||
cur.resolvedPath = "";
|
||||
}
|
||||
if i == nlines { break; }
|
||||
if String_Eq(line, "") || String_StartsWith(line, "#") {
|
||||
i = i + 1;
|
||||
continue;
|
||||
}
|
||||
if String_Eq(line, "[[package]]") || String_Eq(line, "[[Package]]") {
|
||||
inPkg = true;
|
||||
i = i + 1;
|
||||
continue;
|
||||
}
|
||||
if !inPkg {
|
||||
i = i + 1;
|
||||
continue;
|
||||
}
|
||||
let eqc: uint = String_SplitCount(line, "=");
|
||||
if eqc >= 2 {
|
||||
let key: String = String_Trim(String_SplitPart(line, "=", 0));
|
||||
let val: String = Reg_StripQuotes(String_SplitPart(line, "=", 1));
|
||||
// lowercase-ish compare for common keys
|
||||
if String_Eq(key, "name") || String_Eq(key, "Name") {
|
||||
cur.name = val;
|
||||
} else if String_Eq(key, "version") || String_Eq(key, "Version") {
|
||||
cur.version = val;
|
||||
} else if String_Eq(key, "source") || String_Eq(key, "Source") {
|
||||
cur.source = val;
|
||||
} else if String_Eq(key, "description") || String_Eq(key, "Description") {
|
||||
cur.description = val;
|
||||
}
|
||||
}
|
||||
i = i + 1;
|
||||
}
|
||||
return reg;
|
||||
}
|
||||
|
||||
func Reg_FindIndex() -> Registry {
|
||||
var reg: Registry;
|
||||
reg.path = "";
|
||||
reg.sourceUrl = "";
|
||||
reg.count = 0;
|
||||
let env: String = bux_getenv("BUX_REGISTRY");
|
||||
if env != null as String && !String_Eq(env, "") {
|
||||
if Reg_IsHttpUrl(env) {
|
||||
let local: String = Reg_FetchHttp(env);
|
||||
if String_Eq(local, "") {
|
||||
reg.sourceUrl = env;
|
||||
return reg;
|
||||
}
|
||||
let content: String = bux_read_file(local);
|
||||
reg = Reg_ParseContent(content, local);
|
||||
reg.sourceUrl = env;
|
||||
reg.path = local;
|
||||
return reg;
|
||||
}
|
||||
if Reg_FileExists(env) {
|
||||
let content: String = bux_read_file(env);
|
||||
reg = Reg_ParseContent(content, env);
|
||||
reg.path = env;
|
||||
return reg;
|
||||
}
|
||||
}
|
||||
let home: String = bux_getenv("HOME");
|
||||
if home != null as String && !String_Eq(home, "") {
|
||||
let homeIdx: String = bux_path_join(bux_path_join(home, ".bux"), "registry.toml");
|
||||
if Reg_FileExists(homeIdx) {
|
||||
let content: String = bux_read_file(homeIdx);
|
||||
reg = Reg_ParseContent(content, homeIdx);
|
||||
reg.path = homeIdx;
|
||||
return reg;
|
||||
}
|
||||
}
|
||||
// cwd-relative candidates
|
||||
let cwd: String = bux_getcwd();
|
||||
var c0: String = bux_path_join(cwd, "config/registry.toml");
|
||||
if Reg_FileExists(c0) {
|
||||
let content: String = bux_read_file(c0);
|
||||
reg = Reg_ParseContent(content, c0);
|
||||
reg.path = c0;
|
||||
return reg;
|
||||
}
|
||||
c0 = bux_path_join(cwd, "../config/registry.toml");
|
||||
if Reg_FileExists(c0) {
|
||||
let content: String = bux_read_file(c0);
|
||||
reg = Reg_ParseContent(content, c0);
|
||||
reg.path = c0;
|
||||
return reg;
|
||||
}
|
||||
c0 = bux_path_join(cwd, "../../config/registry.toml");
|
||||
if Reg_FileExists(c0) {
|
||||
let content: String = bux_read_file(c0);
|
||||
reg = Reg_ParseContent(content, c0);
|
||||
reg.path = c0;
|
||||
return reg;
|
||||
}
|
||||
return reg;
|
||||
}
|
||||
|
||||
func Reg_VersionOk(have: String, req: String) -> bool {
|
||||
if String_Eq(req, "") || String_Eq(req, "*") { return true; }
|
||||
return String_Eq(have, req);
|
||||
}
|
||||
|
||||
// Lookup by name; versionReq "*" = last matching entry (highest listed last).
|
||||
func Reg_Lookup(reg: Registry, name: String, versionReq: String) -> RegistryPackage {
|
||||
var found: RegistryPackage;
|
||||
found.name = "";
|
||||
var i: int = 0;
|
||||
while i < reg.count {
|
||||
let p: RegistryPackage = Reg_GetPkg(reg, i);
|
||||
if String_Eq(p.name, name) && Reg_VersionOk(p.version, versionReq) {
|
||||
found = p;
|
||||
}
|
||||
i = i + 1;
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
func Reg_Search(reg: Registry, query: String) -> int {
|
||||
// print hits; return count
|
||||
var hits: int = 0;
|
||||
// Dedupe by name: keep last version
|
||||
// Simple O(n^2): for each pkg, if last occurrence of name, print
|
||||
var i: int = 0;
|
||||
while i < reg.count {
|
||||
let p: RegistryPackage = Reg_GetPkg(reg, i);
|
||||
var isLast: bool = true;
|
||||
var j: int = i + 1;
|
||||
while j < reg.count {
|
||||
let q: RegistryPackage = Reg_GetPkg(reg, j);
|
||||
if String_Eq(q.name, p.name) {
|
||||
isLast = false;
|
||||
break;
|
||||
}
|
||||
j = j + 1;
|
||||
}
|
||||
if isLast {
|
||||
var ok: bool = true;
|
||||
if !String_Eq(query, "") {
|
||||
ok = String_Contains(p.name, query) || String_Contains(p.description, query);
|
||||
}
|
||||
if ok {
|
||||
Print(" ");
|
||||
Print(p.name);
|
||||
Print(" ");
|
||||
Print(p.version);
|
||||
Print(" — ");
|
||||
if !String_Eq(p.description, "") {
|
||||
PrintLine(p.description);
|
||||
} else {
|
||||
PrintLine(p.source);
|
||||
}
|
||||
hits = hits + 1;
|
||||
}
|
||||
}
|
||||
i = i + 1;
|
||||
}
|
||||
return hits;
|
||||
if String_StartsWith(p, "/") {
|
||||
return p;
|
||||
}
|
||||
return bux_path_join(indexDir, p);
|
||||
}
|
||||
|
||||
func Reg_SetPkg(reg: *Registry, idx: int, pkg: RegistryPackage) {
|
||||
if idx == 0 { reg.p0 = pkg; }
|
||||
else if idx == 1 { reg.p1 = pkg; }
|
||||
else if idx == 2 { reg.p2 = pkg; }
|
||||
else if idx == 3 { reg.p3 = pkg; }
|
||||
else if idx == 4 { reg.p4 = pkg; }
|
||||
else if idx == 5 { reg.p5 = pkg; }
|
||||
else if idx == 6 { reg.p6 = pkg; }
|
||||
else if idx == 7 { reg.p7 = pkg; }
|
||||
else if idx == 8 { reg.p8 = pkg; }
|
||||
else if idx == 9 { reg.p9 = pkg; }
|
||||
else if idx == 10 { reg.p10 = pkg; }
|
||||
else if idx == 11 { reg.p11 = pkg; }
|
||||
else if idx == 12 { reg.p12 = pkg; }
|
||||
else if idx == 13 { reg.p13 = pkg; }
|
||||
else if idx == 14 { reg.p14 = pkg; }
|
||||
else if idx == 15 { reg.p15 = pkg; }
|
||||
}
|
||||
|
||||
func Reg_GetPkg(reg: Registry, idx: int) -> RegistryPackage {
|
||||
if idx == 0 { return reg.p0; }
|
||||
if idx == 1 { return reg.p1; }
|
||||
if idx == 2 { return reg.p2; }
|
||||
if idx == 3 { return reg.p3; }
|
||||
if idx == 4 { return reg.p4; }
|
||||
if idx == 5 { return reg.p5; }
|
||||
if idx == 6 { return reg.p6; }
|
||||
if idx == 7 { return reg.p7; }
|
||||
if idx == 8 { return reg.p8; }
|
||||
if idx == 9 { return reg.p9; }
|
||||
if idx == 10 { return reg.p10; }
|
||||
if idx == 11 { return reg.p11; }
|
||||
if idx == 12 { return reg.p12; }
|
||||
if idx == 13 { return reg.p13; }
|
||||
if idx == 14 { return reg.p14; }
|
||||
return reg.p15;
|
||||
}
|
||||
|
||||
func Reg_ParseContent(content: String, indexPath: String) -> Registry {
|
||||
var reg: Registry;
|
||||
reg.path = indexPath;
|
||||
reg.sourceUrl = "";
|
||||
reg.count = 0;
|
||||
let indexDir: String = bux_path_parent(indexPath);
|
||||
var cur: RegistryPackage;
|
||||
var inPkg: bool = false;
|
||||
let nlines: uint = String_SplitCount(content, "\n");
|
||||
var i: uint = 0;
|
||||
while i <= nlines {
|
||||
var line: String = "";
|
||||
if i < nlines {
|
||||
line = String_Trim(String_SplitPart(content, "\n", i));
|
||||
}
|
||||
let flush: bool = (i == nlines) || String_Eq(line, "[[package]]") || String_Eq(line, "[[Package]]");
|
||||
if flush && inPkg && !String_Eq(cur.name, "") {
|
||||
cur.resolvedPath = Reg_ResolveSource(cur.source, indexDir);
|
||||
if reg.count < 16 {
|
||||
Reg_SetPkg(®, reg.count, cur);
|
||||
reg.count = reg.count + 1;
|
||||
}
|
||||
cur.name = "";
|
||||
cur.version = "";
|
||||
cur.source = "";
|
||||
cur.description = "";
|
||||
cur.resolvedPath = "";
|
||||
}
|
||||
if i == nlines { break; }
|
||||
if String_Eq(line, "") || String_StartsWith(line, "#") {
|
||||
i = i + 1;
|
||||
continue;
|
||||
}
|
||||
if String_Eq(line, "[[package]]") || String_Eq(line, "[[Package]]") {
|
||||
inPkg = true;
|
||||
i = i + 1;
|
||||
continue;
|
||||
}
|
||||
if !inPkg {
|
||||
i = i + 1;
|
||||
continue;
|
||||
}
|
||||
let eqc: uint = String_SplitCount(line, "=");
|
||||
if eqc >= 2 {
|
||||
let key: String = String_Trim(String_SplitPart(line, "=", 0));
|
||||
let val: String = Reg_StripQuotes(String_SplitPart(line, "=", 1));
|
||||
// lowercase-ish compare for common keys
|
||||
if String_Eq(key, "name") || String_Eq(key, "Name") {
|
||||
cur.name = val;
|
||||
} else if String_Eq(key, "version") || String_Eq(key, "Version") {
|
||||
cur.version = val;
|
||||
} else if String_Eq(key, "source") || String_Eq(key, "Source") {
|
||||
cur.source = val;
|
||||
} else if String_Eq(key, "description") || String_Eq(key, "Description") {
|
||||
cur.description = val;
|
||||
}
|
||||
}
|
||||
i = i + 1;
|
||||
}
|
||||
return reg;
|
||||
}
|
||||
|
||||
func Reg_FindIndex() -> Registry {
|
||||
var reg: Registry;
|
||||
reg.path = "";
|
||||
reg.sourceUrl = "";
|
||||
reg.count = 0;
|
||||
let env: String = bux_getenv("BUX_REGISTRY");
|
||||
if env != null as String && !String_Eq(env, "") {
|
||||
if Reg_IsHttpUrl(env) {
|
||||
let local: String = Reg_FetchHttp(env);
|
||||
if String_Eq(local, "") {
|
||||
reg.sourceUrl = env;
|
||||
return reg;
|
||||
}
|
||||
let content: String = bux_read_file(local);
|
||||
reg = Reg_ParseContent(content, local);
|
||||
reg.sourceUrl = env;
|
||||
reg.path = local;
|
||||
return reg;
|
||||
}
|
||||
if Reg_FileExists(env) {
|
||||
let content: String = bux_read_file(env);
|
||||
reg = Reg_ParseContent(content, env);
|
||||
reg.path = env;
|
||||
return reg;
|
||||
}
|
||||
}
|
||||
let home: String = bux_getenv("HOME");
|
||||
if home != null as String && !String_Eq(home, "") {
|
||||
let homeIdx: String = bux_path_join(bux_path_join(home, ".bux"), "registry.toml");
|
||||
if Reg_FileExists(homeIdx) {
|
||||
let content: String = bux_read_file(homeIdx);
|
||||
reg = Reg_ParseContent(content, homeIdx);
|
||||
reg.path = homeIdx;
|
||||
return reg;
|
||||
}
|
||||
}
|
||||
// cwd-relative candidates
|
||||
let cwd: String = bux_getcwd();
|
||||
var c0: String = bux_path_join(cwd, "config/registry.toml");
|
||||
if Reg_FileExists(c0) {
|
||||
let content: String = bux_read_file(c0);
|
||||
reg = Reg_ParseContent(content, c0);
|
||||
reg.path = c0;
|
||||
return reg;
|
||||
}
|
||||
c0 = bux_path_join(cwd, "../config/registry.toml");
|
||||
if Reg_FileExists(c0) {
|
||||
let content: String = bux_read_file(c0);
|
||||
reg = Reg_ParseContent(content, c0);
|
||||
reg.path = c0;
|
||||
return reg;
|
||||
}
|
||||
c0 = bux_path_join(cwd, "../../config/registry.toml");
|
||||
if Reg_FileExists(c0) {
|
||||
let content: String = bux_read_file(c0);
|
||||
reg = Reg_ParseContent(content, c0);
|
||||
reg.path = c0;
|
||||
return reg;
|
||||
}
|
||||
return reg;
|
||||
}
|
||||
|
||||
func Reg_VersionOk(have: String, req: String) -> bool {
|
||||
if String_Eq(req, "") || String_Eq(req, "*") { return true; }
|
||||
return String_Eq(have, req);
|
||||
}
|
||||
|
||||
// Lookup by name; versionReq "*" = last matching entry (highest listed last).
|
||||
func Reg_Lookup(reg: Registry, name: String, versionReq: String) -> RegistryPackage {
|
||||
var found: RegistryPackage;
|
||||
found.name = "";
|
||||
var i: int = 0;
|
||||
while i < reg.count {
|
||||
let p: RegistryPackage = Reg_GetPkg(reg, i);
|
||||
if String_Eq(p.name, name) && Reg_VersionOk(p.version, versionReq) {
|
||||
found = p;
|
||||
}
|
||||
i = i + 1;
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
func Reg_Search(reg: Registry, query: String) -> int {
|
||||
// print hits; return count
|
||||
var hits: int = 0;
|
||||
// Dedupe by name: keep last version
|
||||
// Simple O(n^2): for each pkg, if last occurrence of name, print
|
||||
var i: int = 0;
|
||||
while i < reg.count {
|
||||
let p: RegistryPackage = Reg_GetPkg(reg, i);
|
||||
var isLast: bool = true;
|
||||
var j: int = i + 1;
|
||||
while j < reg.count {
|
||||
let q: RegistryPackage = Reg_GetPkg(reg, j);
|
||||
if String_Eq(q.name, p.name) {
|
||||
isLast = false;
|
||||
break;
|
||||
}
|
||||
j = j + 1;
|
||||
}
|
||||
if isLast {
|
||||
var ok: bool = true;
|
||||
if !String_Eq(query, "") {
|
||||
ok = String_Contains(p.name, query) || String_Contains(p.description, query);
|
||||
}
|
||||
if ok {
|
||||
Print(" ");
|
||||
Print(p.name);
|
||||
Print(" ");
|
||||
Print(p.version);
|
||||
Print(" — ");
|
||||
if !String_Eq(p.description, "") {
|
||||
PrintLine(p.description);
|
||||
} else {
|
||||
PrintLine(p.source);
|
||||
}
|
||||
hits = hits + 1;
|
||||
}
|
||||
}
|
||||
i = i + 1;
|
||||
}
|
||||
return hits;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user