Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 5fdc9fb15e | |||
| 8967fa404e | |||
| a7e6fbf2d2 | |||
| 1f4b594ae7 | |||
| cff7ce072d |
@@ -272,8 +272,9 @@ jobs:
|
|||||||
gcloud config set project neuron-785695
|
gcloud config set project neuron-785695
|
||||||
gcloud auth configure-docker us-central1-docker.pkg.dev --quiet
|
gcloud auth configure-docker us-central1-docker.pkg.dev --quiet
|
||||||
|
|
||||||
# Pull existing ci-base:dev (system deps stay cached in the base layer)
|
# Pull existing ci-base:dev (or fall back to :latest on first run)
|
||||||
docker pull "${CI_BASE}:dev" || docker pull "${CI_BASE}:latest"
|
BASE_TAG="dev"
|
||||||
|
docker pull "${CI_BASE}:dev" || { docker pull "${CI_BASE}:latest" && BASE_TAG="latest"; }
|
||||||
|
|
||||||
# Inline Dockerfile — only replaces the El SDK layer
|
# Inline Dockerfile — only replaces the El SDK layer
|
||||||
cat > /tmp/Dockerfile.ci-base-patch << 'EOF'
|
cat > /tmp/Dockerfile.ci-base-patch << 'EOF'
|
||||||
@@ -288,7 +289,7 @@ jobs:
|
|||||||
EOF
|
EOF
|
||||||
|
|
||||||
docker build \
|
docker build \
|
||||||
--build-arg BASE="${CI_BASE}:dev" \
|
--build-arg BASE="${CI_BASE}:${BASE_TAG}" \
|
||||||
--build-arg BUILDKIT_INLINE_CACHE=1 \
|
--build-arg BUILDKIT_INLINE_CACHE=1 \
|
||||||
-f /tmp/Dockerfile.ci-base-patch \
|
-f /tmp/Dockerfile.ci-base-patch \
|
||||||
-t "${CI_BASE}:dev" \
|
-t "${CI_BASE}:dev" \
|
||||||
|
|||||||
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
@@ -2242,6 +2242,43 @@ el_val_t url_decode(el_val_t sv) {
|
|||||||
return el_wrap_str(out);
|
return el_wrap_str(out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ── html_raw ────────────────────────────────────────────────────────────────
|
||||||
|
* Identity passthrough for raw HTML template interpolation.
|
||||||
|
* El's {raw(expr)} compiles to html_raw(expr) — the value is output as-is
|
||||||
|
* without any escaping. The caller is responsible for safety.
|
||||||
|
*/
|
||||||
|
el_val_t html_raw(el_val_t s) {
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ── html_escape ─────────────────────────────────────────────────────────────
|
||||||
|
* Escape < > " ' & for safe HTML text interpolation.
|
||||||
|
* El's {expr} in HTML templates compiles to html_escape(expr).
|
||||||
|
*/
|
||||||
|
el_val_t html_escape(el_val_t sv) {
|
||||||
|
const char* src = EL_CSTR(sv);
|
||||||
|
if (!src) return EL_STR("");
|
||||||
|
size_t len = strlen(src);
|
||||||
|
/* Worst case: every byte → 6 chars (") */
|
||||||
|
char* out = (char*)malloc(len * 6 + 1);
|
||||||
|
if (!out) return sv;
|
||||||
|
el_arena_track(out);
|
||||||
|
char* p = out;
|
||||||
|
for (size_t i = 0; i < len; i++) {
|
||||||
|
unsigned char c = (unsigned char)src[i];
|
||||||
|
switch (c) {
|
||||||
|
case '&': memcpy(p, "&", 5); p += 5; break;
|
||||||
|
case '<': memcpy(p, "<", 4); p += 4; break;
|
||||||
|
case '>': memcpy(p, ">", 4); p += 4; break;
|
||||||
|
case '"': memcpy(p, """, 6); p += 6; break;
|
||||||
|
case '\'': memcpy(p, "'", 5); p += 5; break;
|
||||||
|
default: *p++ = (char)c; break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*p = '\0';
|
||||||
|
return el_wrap_str(out);
|
||||||
|
}
|
||||||
|
|
||||||
/* ── HTML allowlist sanitizer ────────────────────────────────────────────────
|
/* ── HTML allowlist sanitizer ────────────────────────────────────────────────
|
||||||
* el_html_sanitize(input, allowlist_json)
|
* el_html_sanitize(input, allowlist_json)
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -227,6 +227,8 @@ el_val_t url_decode(el_val_t s); /* '+' → space, %XX → byte */
|
|||||||
* {"p":[],"a":["href","title"],"strong":[],...}
|
* {"p":[],"a":["href","title"],"strong":[],...}
|
||||||
* where each value is the array of attribute names allowed for that tag. */
|
* where each value is the array of attribute names allowed for that tag. */
|
||||||
el_val_t el_html_sanitize(el_val_t input_html, el_val_t allowlist_json);
|
el_val_t el_html_sanitize(el_val_t input_html, el_val_t allowlist_json);
|
||||||
|
el_val_t html_raw(el_val_t s);
|
||||||
|
el_val_t html_escape(el_val_t s);
|
||||||
|
|
||||||
/* ── Filesystem ──────────────────────────────────────────────────────────── */
|
/* ── Filesystem ──────────────────────────────────────────────────────────── */
|
||||||
|
|
||||||
|
|||||||
+43
-2
@@ -77,6 +77,33 @@ fn parse_manifest_entry(src: String) -> String {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// parse_manifest_c_sources - collect all `c_source "path"` lines from the
|
||||||
|
// build block. Returns a flat list of path strings.
|
||||||
|
fn parse_manifest_c_sources(src: String) -> [String] {
|
||||||
|
let result: [String] = native_list_empty()
|
||||||
|
let lines: [String] = str_split(src, "\n")
|
||||||
|
let n: Int = native_list_len(lines)
|
||||||
|
let i = 0
|
||||||
|
while i < n {
|
||||||
|
let line: String = native_list_get(lines, i)
|
||||||
|
let t: String = str_trim(line)
|
||||||
|
if str_starts_with(t, "c_source ") {
|
||||||
|
let after: String = str_slice(t, 9, str_len(t))
|
||||||
|
let trimmed: String = str_trim(after)
|
||||||
|
if str_starts_with(trimmed, "\"") {
|
||||||
|
let inner: String = str_slice(trimmed, 1, str_len(trimmed))
|
||||||
|
let q: Int = str_index_of(inner, "\"")
|
||||||
|
if q >= 0 {
|
||||||
|
let path: String = str_slice(inner, 0, q)
|
||||||
|
let result = native_list_append(result, path)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let i = i + 1
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
fn parse_manifest_name(src: String) -> String {
|
fn parse_manifest_name(src: String) -> String {
|
||||||
let lines: [String] = str_split(src, "\n")
|
let lines: [String] = str_split(src, "\n")
|
||||||
let n: Int = native_list_len(lines)
|
let n: Int = native_list_len(lines)
|
||||||
@@ -274,7 +301,11 @@ fn link_binary(c_files: [String], out_bin: String, runtime_path: String, out_dir
|
|||||||
// Detect clang vs gcc: -fbracket-depth is clang-only; silently ignored
|
// Detect clang vs gcc: -fbracket-depth is clang-only; silently ignored
|
||||||
// if unsupported but gcc rejects it with an error.
|
// if unsupported but gcc rejects it with an error.
|
||||||
let bracket_flag: String = "$(cc --version 2>&1 | grep -q clang && printf -- '-fbracket-depth=1024' || true)"
|
let bracket_flag: String = "$(cc --version 2>&1 | grep -q clang && printf -- '-fbracket-depth=1024' || true)"
|
||||||
let parts = native_list_append(parts, "cc -O2 " + bracket_flag + " -I " + dirname_of(runtime_path) + " -I " + out_dir)
|
// On macOS, OpenSSL is not on the default linker path. Detect homebrew
|
||||||
|
// prefix and add it if present (no-op on Linux where libssl is in /usr/lib).
|
||||||
|
let ossl_lib_flag: String = "$(brew --prefix openssl 2>/dev/null | xargs -I{} printf -- '-L{}/lib' 2>/dev/null || true)"
|
||||||
|
let ossl_inc_flag: String = "$(brew --prefix openssl 2>/dev/null | xargs -I{} printf -- '-I{}/include' 2>/dev/null || true)"
|
||||||
|
let parts = native_list_append(parts, "cc -O2 " + bracket_flag + " " + ossl_inc_flag + " -I " + dirname_of(runtime_path) + " -I " + out_dir)
|
||||||
let i = 0
|
let i = 0
|
||||||
while i < n {
|
while i < n {
|
||||||
let f: String = native_list_get(c_files, i)
|
let f: String = native_list_get(c_files, i)
|
||||||
@@ -282,7 +313,7 @@ fn link_binary(c_files: [String], out_bin: String, runtime_path: String, out_dir
|
|||||||
let i = i + 1
|
let i = i + 1
|
||||||
}
|
}
|
||||||
let parts = native_list_append(parts, runtime_path)
|
let parts = native_list_append(parts, runtime_path)
|
||||||
let parts = native_list_append(parts, "-lcurl -lssl -lcrypto -lpthread -lm")
|
let parts = native_list_append(parts, ossl_lib_flag + " -lcurl -lssl -lcrypto -lpthread -lm")
|
||||||
let parts = native_list_append(parts, "-o " + out_bin)
|
let parts = native_list_append(parts, "-o " + out_bin)
|
||||||
let cmd: String = str_join(parts, " ")
|
let cmd: String = str_join(parts, " ")
|
||||||
println(" link " + out_bin)
|
println(" link " + out_bin)
|
||||||
@@ -315,6 +346,7 @@ fn main() -> Void {
|
|||||||
|
|
||||||
let pkg_name: String = parse_manifest_name(manifest_src)
|
let pkg_name: String = parse_manifest_name(manifest_src)
|
||||||
let entry: String = parse_manifest_entry(manifest_src)
|
let entry: String = parse_manifest_entry(manifest_src)
|
||||||
|
let extra_c: [String] = parse_manifest_c_sources(manifest_src)
|
||||||
if str_eq(entry, "") {
|
if str_eq(entry, "") {
|
||||||
println("elb: manifest.el has no 'entry' declaration")
|
println("elb: manifest.el has no 'entry' declaration")
|
||||||
exit(1)
|
exit(1)
|
||||||
@@ -393,6 +425,15 @@ fn main() -> Void {
|
|||||||
exit(1)
|
exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Append any extra C sources declared in the manifest (e.g. platform stubs)
|
||||||
|
let ei = 0
|
||||||
|
let en: Int = native_list_len(extra_c)
|
||||||
|
while ei < en {
|
||||||
|
let ec: String = native_list_get(extra_c, ei)
|
||||||
|
let c_files = native_list_append(c_files, ec)
|
||||||
|
let ei = ei + 1
|
||||||
|
}
|
||||||
|
|
||||||
// Link
|
// Link
|
||||||
let out_bin: String = out_dir + "/" + pkg_name
|
let out_bin: String = out_dir + "/" + pkg_name
|
||||||
let linked: Bool = link_binary(c_files, out_bin, runtime_path, out_dir, dry_run)
|
let linked: Bool = link_binary(c_files, out_bin, runtime_path, out_dir, dry_run)
|
||||||
|
|||||||
+10062
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user