lang migration: rename signed integer types sN -> iN
Mechanical sweep of all .sx sources and plan docs (PLAN.md, current/, .agents/) for the sx language rename (s8/s16/s32/s64 -> i8/i16/i32/i64). Verified: make build + make test, 14/14.
This commit is contained in:
@@ -35,7 +35,7 @@ srv :: #import "server/distd.sx";
|
|||||||
// Direct stderr writer (fd 2), so human help/usage/progress never lands on
|
// Direct stderr writer (fd 2), so human help/usage/progress never lands on
|
||||||
// stdout's data stream. `out` (std builtin) targets stdout (fd 1).
|
// stdout's data stream. `out` (std builtin) targets stdout (fd 1).
|
||||||
cstdlib :: #library "c";
|
cstdlib :: #library "c";
|
||||||
fd_write :: (fd: s32, buf: [*]u8, count: usize) -> isize #foreign cstdlib "write";
|
fd_write :: (fd: i32, buf: [*]u8, count: usize) -> isize #foreign cstdlib "write";
|
||||||
|
|
||||||
eputs :: (s: string) { if s.len > 0 { fd_write(2, s.ptr, xx s.len); } }
|
eputs :: (s: string) { if s.len > 0 { fd_write(2, s.ptr, xx s.len); } }
|
||||||
|
|
||||||
@@ -187,7 +187,7 @@ handle_release_rollback :: (p: *Parsed, json_mode: bool) {
|
|||||||
// `report_failure` like every other command.
|
// `report_failure` like every other command.
|
||||||
handle_server_run :: (p: *Parsed, json_mode: bool) {
|
handle_server_run :: (p: *Parsed, json_mode: bool) {
|
||||||
store_dir := p.value_of("local-store");
|
store_dir := p.value_of("local-store");
|
||||||
port : s64 = 8787;
|
port : i64 = 8787;
|
||||||
if p.is_set("port") {
|
if p.is_set("port") {
|
||||||
pq := parse_port(p.value_of("port"));
|
pq := parse_port(p.value_of("port"));
|
||||||
if pq == null {
|
if pq == null {
|
||||||
@@ -210,9 +210,9 @@ handle_server_run :: (p: *Parsed, json_mode: bool) {
|
|||||||
|
|
||||||
// Decimal port in 1..65535; anything else (empty, non-digits, out of
|
// Decimal port in 1..65535; anything else (empty, non-digits, out of
|
||||||
// range) is null — a usage error at the call site.
|
// range) is null — a usage error at the call site.
|
||||||
parse_port :: (s: string) -> ?s64 {
|
parse_port :: (s: string) -> ?i64 {
|
||||||
if s.len == 0 or s.len > 5 { return null; }
|
if s.len == 0 or s.len > 5 { return null; }
|
||||||
v : s64 = 0;
|
v : i64 = 0;
|
||||||
i := 0;
|
i := 0;
|
||||||
while i < s.len {
|
while i < s.len {
|
||||||
c := s[i];
|
c := s[i];
|
||||||
|
|||||||
@@ -26,6 +26,6 @@ App :: struct {
|
|||||||
bundle_ids: List(BundleId);
|
bundle_ids: List(BundleId);
|
||||||
owner: string;
|
owner: string;
|
||||||
visibility: Visibility = .private;
|
visibility: Visibility = .private;
|
||||||
created_at: s64;
|
created_at: i64;
|
||||||
updated_at: s64;
|
updated_at: i64;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ Artifact :: struct {
|
|||||||
platform: Platform;
|
platform: Platform;
|
||||||
filename: string;
|
filename: string;
|
||||||
content_type: string;
|
content_type: string;
|
||||||
size_bytes: s64;
|
size_bytes: i64;
|
||||||
sha256: string;
|
sha256: string;
|
||||||
storage_key: string;
|
storage_key: string;
|
||||||
metadata: string;
|
metadata: string;
|
||||||
|
|||||||
@@ -11,5 +11,5 @@ AuditEvent :: struct {
|
|||||||
target_type: string;
|
target_type: string;
|
||||||
target_id: string;
|
target_id: string;
|
||||||
metadata: string;
|
metadata: string;
|
||||||
created_at: s64;
|
created_at: i64;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,5 +15,5 @@ Channel :: struct {
|
|||||||
name: string;
|
name: string;
|
||||||
current_release_id: string;
|
current_release_id: string;
|
||||||
policy: RolloutPolicy = .manual;
|
policy: RolloutPolicy = .manual;
|
||||||
rollout_percent: s64 = 100;
|
rollout_percent: i64 = 100;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,10 +8,10 @@ Release :: struct {
|
|||||||
id: string;
|
id: string;
|
||||||
app_id: string;
|
app_id: string;
|
||||||
version: string;
|
version: string;
|
||||||
build: s64;
|
build: i64;
|
||||||
channel: string;
|
channel: string;
|
||||||
notes: string;
|
notes: string;
|
||||||
created_by: string;
|
created_by: string;
|
||||||
created_at: s64;
|
created_at: i64;
|
||||||
published_at: s64;
|
published_at: i64;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ CliFailure :: struct {
|
|||||||
// "error": { "code": <code>, "message": <message> } }` — into the
|
// "error": { "code": <code>, "message": <message> } }` — into the
|
||||||
// caller-owned `dst`, returning the bytes written. Overflow surfaces on
|
// caller-owned `dst`, returning the bytes written. Overflow surfaces on
|
||||||
// the error channel.
|
// the error channel.
|
||||||
write_error :: (f: CliFailure, dst: []u8) -> (s64, !JsonError) {
|
write_error :: (f: CliFailure, dst: []u8) -> (i64, !JsonError) {
|
||||||
gpa := GPA.init();
|
gpa := GPA.init();
|
||||||
obj : Object = .{};
|
obj : Object = .{};
|
||||||
obj.put("status", .str("error"), xx gpa);
|
obj.put("status", .str("error"), xx gpa);
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ ManifestArtifact :: struct {
|
|||||||
filename: string;
|
filename: string;
|
||||||
content_type: string;
|
content_type: string;
|
||||||
metadata: string;
|
metadata: string;
|
||||||
size: s64 = -1;
|
size: i64 = -1;
|
||||||
sha256: string = "";
|
sha256: string = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,7 +121,7 @@ opt_str :: (o: Object, key: string, alloc: Allocator) -> (string, !ManifestErr)
|
|||||||
|
|
||||||
// Optional integer field. Absent -> `default` (a documented default, not a
|
// Optional integer field. Absent -> `default` (a documented default, not a
|
||||||
// silent one); present-but-not-an-integer -> WrongType.
|
// silent one); present-but-not-an-integer -> WrongType.
|
||||||
opt_int :: (o: Object, key: string, default: s64) -> (s64, !ManifestErr) {
|
opt_int :: (o: Object, key: string, default: i64) -> (i64, !ManifestErr) {
|
||||||
v := obj_find(o, key);
|
v := obj_find(o, key);
|
||||||
if v == null { return default; }
|
if v == null { return default; }
|
||||||
val := v!;
|
val := v!;
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ jout :: #import "../json_out.sx";
|
|||||||
// time stamped onto the release / audit events, and the process cwd used to
|
// time stamped onto the release / audit events, and the process cwd used to
|
||||||
// absolutize a relative `--local-store` into the download URL.
|
// absolutize a relative `--local-store` into the download URL.
|
||||||
cstd :: #library "c";
|
cstd :: #library "c";
|
||||||
c_time :: (tloc: *s64) -> s64 #foreign cstd "time";
|
c_time :: (tloc: *i64) -> i64 #foreign cstd "time";
|
||||||
c_getcwd :: (buf: [*]u8, size: usize) -> *u8 #foreign cstd "getcwd";
|
c_getcwd :: (buf: [*]u8, size: usize) -> *u8 #foreign cstd "getcwd";
|
||||||
|
|
||||||
// Failure classes for the publish pipeline. One distinct tag per stage so
|
// Failure classes for the publish pipeline. One distinct tag per stage so
|
||||||
@@ -80,7 +80,7 @@ PublishError :: error {
|
|||||||
PublishedArtifact :: struct {
|
PublishedArtifact :: struct {
|
||||||
id: string;
|
id: string;
|
||||||
platform_name: string;
|
platform_name: string;
|
||||||
size_bytes: s64;
|
size_bytes: i64;
|
||||||
sha256: string;
|
sha256: string;
|
||||||
url: string;
|
url: string;
|
||||||
}
|
}
|
||||||
@@ -99,8 +99,8 @@ PublishOutcome :: struct {
|
|||||||
|
|
||||||
// Current wall-clock time as unix epoch seconds (time(2) via a local slot,
|
// Current wall-clock time as unix epoch seconds (time(2) via a local slot,
|
||||||
// so no null pointer is needed).
|
// so no null pointer is needed).
|
||||||
now_secs :: () -> s64 {
|
now_secs :: () -> i64 {
|
||||||
t : s64 = 0;
|
t : i64 = 0;
|
||||||
return c_time(@t);
|
return c_time(@t);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -111,7 +111,7 @@ abs_store :: (dir: string) -> string {
|
|||||||
if dir.len > 0 and dir[0] == 47 { return dir; } // 47='/' already absolute
|
if dir.len > 0 and dir[0] == 47 { return dir; } // 47='/' already absolute
|
||||||
buf : [4096]u8 = ---;
|
buf : [4096]u8 = ---;
|
||||||
r := c_getcwd(@buf[0], 4096);
|
r := c_getcwd(@buf[0], 4096);
|
||||||
if cast(s64) r == 0 { return dir; }
|
if cast(i64) r == 0 { return dir; }
|
||||||
n := 0;
|
n := 0;
|
||||||
while buf[n] != 0 { n += 1; }
|
while buf[n] != 0 { n += 1; }
|
||||||
cwd := string.{ ptr = @buf[0], len = n };
|
cwd := string.{ ptr = @buf[0], len = n };
|
||||||
@@ -360,7 +360,7 @@ run_publish :: (manifest_path: string, store_dir: string, fail_out: *jout.CliFai
|
|||||||
// release{id,app_id,version,channel}, artifacts[]{id,platform,size_bytes,
|
// release{id,app_id,version,channel}, artifacts[]{id,platform,size_bytes,
|
||||||
// sha256,url}) by `std.json`'s insertion-order guarantee. Overflow surfaces
|
// sha256,url}) by `std.json`'s insertion-order guarantee. Overflow surfaces
|
||||||
// on the error channel.
|
// on the error channel.
|
||||||
write_json :: (o: *PublishOutcome, dst: []u8) -> (s64, !JsonError) {
|
write_json :: (o: *PublishOutcome, dst: []u8) -> (i64, !JsonError) {
|
||||||
gpa := GPA.init();
|
gpa := GPA.init();
|
||||||
root : Object = .{};
|
root : Object = .{};
|
||||||
root.put("status", .str("published"), xx gpa);
|
root.put("status", .str("published"), xx gpa);
|
||||||
|
|||||||
@@ -245,7 +245,7 @@ run_rollback :: (store_dir: string, app_slug: string, channel_name: string, fail
|
|||||||
// `{"status":"promoted","app_id":...,"channel":...,"release":{"id":...,
|
// `{"status":"promoted","app_id":...,"channel":...,"release":{"id":...,
|
||||||
// "version":...},"previous_release_id":...}` — member order fixed by
|
// "version":...},"previous_release_id":...}` — member order fixed by
|
||||||
// `std.json`'s insertion-order guarantee.
|
// `std.json`'s insertion-order guarantee.
|
||||||
write_promote_json :: (o: *PromoteOutcome, dst: []u8) -> (s64, !JsonError) {
|
write_promote_json :: (o: *PromoteOutcome, dst: []u8) -> (i64, !JsonError) {
|
||||||
gpa := GPA.init();
|
gpa := GPA.init();
|
||||||
root : Object = .{};
|
root : Object = .{};
|
||||||
root.put("status", .str("promoted"), xx gpa);
|
root.put("status", .str("promoted"), xx gpa);
|
||||||
@@ -263,7 +263,7 @@ write_promote_json :: (o: *PromoteOutcome, dst: []u8) -> (s64, !JsonError) {
|
|||||||
|
|
||||||
// `{"status":"rolled_back","app_id":...,"channel":...,"from_release_id":...,
|
// `{"status":"rolled_back","app_id":...,"channel":...,"from_release_id":...,
|
||||||
// "to":{"id":...,"version":...}}`.
|
// "to":{"id":...,"version":...}}`.
|
||||||
write_rollback_json :: (o: *RollbackOutcome, dst: []u8) -> (s64, !JsonError) {
|
write_rollback_json :: (o: *RollbackOutcome, dst: []u8) -> (i64, !JsonError) {
|
||||||
gpa := GPA.init();
|
gpa := GPA.init();
|
||||||
root : Object = .{};
|
root : Object = .{};
|
||||||
root.put("status", .str("rolled_back"), xx gpa);
|
root.put("status", .str("rolled_back"), xx gpa);
|
||||||
|
|||||||
@@ -271,7 +271,7 @@ req_str_view :: (o: Object, key: string) -> (string, !LoadErr) {
|
|||||||
return val.str;
|
return val.str;
|
||||||
}
|
}
|
||||||
|
|
||||||
req_int :: (o: Object, key: string) -> (s64, !LoadErr) {
|
req_int :: (o: Object, key: string) -> (i64, !LoadErr) {
|
||||||
v := db_obj_find(o, key);
|
v := db_obj_find(o, key);
|
||||||
if v == null { raise error.BadShape; }
|
if v == null { raise error.BadShape; }
|
||||||
val := v!;
|
val := v!;
|
||||||
|
|||||||
@@ -146,7 +146,7 @@ Repo :: struct {
|
|||||||
self.channels.append(c, self.own_allocator);
|
self.channels.append(c, self.own_allocator);
|
||||||
}
|
}
|
||||||
// Channels are keyed by (app_id, name) — there is no separate id.
|
// Channels are keyed by (app_id, name) — there is no separate id.
|
||||||
channel_index :: (self: *Repo, app_id: string, name: string) -> s64 {
|
channel_index :: (self: *Repo, app_id: string, name: string) -> i64 {
|
||||||
i := 0;
|
i := 0;
|
||||||
while i < self.channels.len {
|
while i < self.channels.len {
|
||||||
c := self.channels.items[i];
|
c := self.channels.items[i];
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ render_buf :: () -> string {
|
|||||||
// ── responses ─────────────────────────────────────────────────────────
|
// ── responses ─────────────────────────────────────────────────────────
|
||||||
|
|
||||||
// JSON error body in the CLI's error shape, sent with the HTTP status.
|
// JSON error body in the CLI's error shape, sent with the HTTP status.
|
||||||
respond_error :: (client: s32, code: s64, fail_code: string, fail_message: string) {
|
respond_error :: (client: i32, code: i64, fail_code: string, fail_message: string) {
|
||||||
f : jout.CliFailure = .{ code = fail_code, message = fail_message };
|
f : jout.CliFailure = .{ code = fail_code, message = fail_message };
|
||||||
raw : [4096]u8 = ---;
|
raw : [4096]u8 = ---;
|
||||||
werr := false;
|
werr := false;
|
||||||
@@ -110,7 +110,7 @@ respond_error :: (client: s32, code: s64, fail_code: string, fail_message: strin
|
|||||||
|
|
||||||
// Reload the persisted model. Null means the store has no readable
|
// Reload the persisted model. Null means the store has no readable
|
||||||
// db.json — the 503 error response has already been sent.
|
// db.json — the 503 error response has already been sent.
|
||||||
load_or_503 :: (client: s32, store_dir: string) -> ?Repo {
|
load_or_503 :: (client: i32, store_dir: string) -> ?Repo {
|
||||||
if !exists(path_join(store_dir, "db.json")) {
|
if !exists(path_join(store_dir, "db.json")) {
|
||||||
respond_error(client, 503, "store.load",
|
respond_error(client, 503, "store.load",
|
||||||
concat("no db.json under the store (nothing published yet): ", store_dir));
|
concat("no db.json under the store (nothing published yet): ", store_dir));
|
||||||
@@ -126,7 +126,7 @@ load_or_503 :: (client: s32, store_dir: string) -> ?Repo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// `{"apps":[...]}` into `dst`, returning the bytes written.
|
// `{"apps":[...]}` into `dst`, returning the bytes written.
|
||||||
render_apps_json :: (repo: *Repo, dst: []u8) -> (s64, !JsonError) {
|
render_apps_json :: (repo: *Repo, dst: []u8) -> (i64, !JsonError) {
|
||||||
alloc := context.allocator;
|
alloc := context.allocator;
|
||||||
root : Object = .{};
|
root : Object = .{};
|
||||||
arr : Array = .{};
|
arr : Array = .{};
|
||||||
@@ -142,7 +142,7 @@ render_apps_json :: (repo: *Repo, dst: []u8) -> (s64, !JsonError) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// `{"app":..,"releases":[..],"channels":[..]}` for `app` into `dst`.
|
// `{"app":..,"releases":[..],"channels":[..]}` for `app` into `dst`.
|
||||||
render_app_detail_json :: (repo: *Repo, app: App, dst: []u8) -> (s64, !JsonError) {
|
render_app_detail_json :: (repo: *Repo, app: App, dst: []u8) -> (i64, !JsonError) {
|
||||||
alloc := context.allocator;
|
alloc := context.allocator;
|
||||||
root : Object = .{};
|
root : Object = .{};
|
||||||
root.put("app", db.app_to_json(app, alloc), alloc);
|
root.put("app", db.app_to_json(app, alloc), alloc);
|
||||||
@@ -172,7 +172,7 @@ render_app_detail_json :: (repo: *Repo, app: App, dst: []u8) -> (s64, !JsonError
|
|||||||
|
|
||||||
// Send `n` rendered bytes of `buf` as 200 JSON — or the overflow error
|
// Send `n` rendered bytes of `buf` as 200 JSON — or the overflow error
|
||||||
// when the render didn't fit RENDER_CAP.
|
// when the render didn't fit RENDER_CAP.
|
||||||
respond_render :: (client: s32, buf: string, n: s64, overflowed: bool) {
|
respond_render :: (client: i32, buf: string, n: i64, overflowed: bool) {
|
||||||
if overflowed {
|
if overflowed {
|
||||||
respond_error(client, 500, "http.response_overflow",
|
respond_error(client, 500, "http.response_overflow",
|
||||||
"response exceeded the server's render buffer");
|
"response exceeded the server's render buffer");
|
||||||
@@ -271,7 +271,7 @@ render_index :: (repo: *Repo) -> string {
|
|||||||
return concat(page, INDEX_FOOT);
|
return concat(page, INDEX_FOOT);
|
||||||
}
|
}
|
||||||
|
|
||||||
handle_index :: (client: s32, store_dir: string) {
|
handle_index :: (client: i32, store_dir: string) {
|
||||||
rq := load_or_503(client, store_dir);
|
rq := load_or_503(client, store_dir);
|
||||||
if rq == null { return; }
|
if rq == null { return; }
|
||||||
repo := rq!;
|
repo := rq!;
|
||||||
@@ -280,7 +280,7 @@ handle_index :: (client: s32, store_dir: string) {
|
|||||||
|
|
||||||
// ── routes ────────────────────────────────────────────────────────────
|
// ── routes ────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
handle_apps_index :: (client: s32, store_dir: string) {
|
handle_apps_index :: (client: i32, store_dir: string) {
|
||||||
rq := load_or_503(client, store_dir);
|
rq := load_or_503(client, store_dir);
|
||||||
if rq == null { return; }
|
if rq == null { return; }
|
||||||
repo := rq!;
|
repo := rq!;
|
||||||
@@ -291,7 +291,7 @@ handle_apps_index :: (client: s32, store_dir: string) {
|
|||||||
respond_render(client, buf, n, werr);
|
respond_render(client, buf, n, werr);
|
||||||
}
|
}
|
||||||
|
|
||||||
handle_app_detail :: (client: s32, store_dir: string, slug: string) {
|
handle_app_detail :: (client: i32, store_dir: string, slug: string) {
|
||||||
rq := load_or_503(client, store_dir);
|
rq := load_or_503(client, store_dir);
|
||||||
if rq == null { return; }
|
if rq == null { return; }
|
||||||
repo := rq!;
|
repo := rq!;
|
||||||
@@ -309,7 +309,7 @@ handle_app_detail :: (client: s32, store_dir: string, slug: string) {
|
|||||||
respond_render(client, buf, n, werr);
|
respond_render(client, buf, n, werr);
|
||||||
}
|
}
|
||||||
|
|
||||||
handle_download :: (client: s32, store_dir: string, sha: string) {
|
handle_download :: (client: i32, store_dir: string, sha: string) {
|
||||||
if !is_hex64(sha) {
|
if !is_hex64(sha) {
|
||||||
respond_error(client, 404, "download.bad_key",
|
respond_error(client, 404, "download.bad_key",
|
||||||
"download key must be a 64-char lowercase-hex sha256");
|
"download key must be a 64-char lowercase-hex sha256");
|
||||||
@@ -327,7 +327,7 @@ handle_download :: (client: s32, store_dir: string, sha: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Route one parsed request. GET only; the path decides the handler.
|
// Route one parsed request. GET only; the path decides the handler.
|
||||||
route :: (client: s32, store_dir: string, method: string, path: string) -> s64 {
|
route :: (client: i32, store_dir: string, method: string, path: string) -> i64 {
|
||||||
if method != "GET" {
|
if method != "GET" {
|
||||||
respond_error(client, 405, "http.method_not_allowed",
|
respond_error(client, 405, "http.method_not_allowed",
|
||||||
"every distd route is GET for now (writes go through the dist CLI)");
|
"every distd route is GET for now (writes go through the dist CLI)");
|
||||||
@@ -362,7 +362,7 @@ route :: (client: s32, store_dir: string, method: string, path: string) -> s64 {
|
|||||||
|
|
||||||
// Read one request off `client`, route it, log the result line. All
|
// Read one request off `client`, route it, log the result line. All
|
||||||
// allocations land in the pushed per-request context allocator.
|
// allocations land in the pushed per-request context allocator.
|
||||||
serve_one :: (client: s32, store_dir: string) {
|
serve_one :: (client: i32, store_dir: string) {
|
||||||
buf : [8192]u8 = ---;
|
buf : [8192]u8 = ---;
|
||||||
n := sock.read(client, @buf[0], 8192);
|
n := sock.read(client, @buf[0], 8192);
|
||||||
if n <= 0 { return; }
|
if n <= 0 { return; }
|
||||||
@@ -383,7 +383,7 @@ serve_one :: (client: s32, store_dir: string) {
|
|||||||
// time — the deployment story is LAN/NAS-scale). Returns only when the
|
// time — the deployment story is LAN/NAS-scale). Returns only when the
|
||||||
// socket can't be opened. Per-request allocations live in an arena that
|
// socket can't be opened. Per-request allocations live in an arena that
|
||||||
// dies with the request.
|
// dies with the request.
|
||||||
run_server :: (store_dir: string, port: s64) -> !ServeErr {
|
run_server :: (store_dir: string, port: i64) -> !ServeErr {
|
||||||
fd, fe := http.listen_on(port);
|
fd, fe := http.listen_on(port);
|
||||||
if fe { raise error.Bind; }
|
if fe { raise error.Bind; }
|
||||||
|
|
||||||
|
|||||||
@@ -35,10 +35,10 @@ Request :: struct {
|
|||||||
|
|
||||||
// Open a listening socket on 0.0.0.0:<port>. SO_REUSEADDR so a restarted
|
// Open a listening socket on 0.0.0.0:<port>. SO_REUSEADDR so a restarted
|
||||||
// server can re-bind without waiting out TIME_WAIT.
|
// server can re-bind without waiting out TIME_WAIT.
|
||||||
listen_on :: (port: s64) -> (s32, !HttpError) {
|
listen_on :: (port: i64) -> (i32, !HttpError) {
|
||||||
fd := sock.socket(sock.AF_INET, sock.SOCK_STREAM, 0);
|
fd := sock.socket(sock.AF_INET, sock.SOCK_STREAM, 0);
|
||||||
if fd < 0 { raise error.Socket; }
|
if fd < 0 { raise error.Socket; }
|
||||||
opt : s32 = 1;
|
opt : i32 = 1;
|
||||||
sock.setsockopt(fd, sock.SOL_SOCKET, sock.SO_REUSEADDR, @opt, 4);
|
sock.setsockopt(fd, sock.SOL_SOCKET, sock.SO_REUSEADDR, @opt, 4);
|
||||||
addr : sock.SockAddr = .{ sin_len = 16, sin_family = 2, sin_port = sock.htons(port) };
|
addr : sock.SockAddr = .{ sin_len = 16, sin_family = 2, sin_port = sock.htons(port) };
|
||||||
if sock.bind(fd, @addr, 16) < 0 { sock.close(fd); raise error.Bind; }
|
if sock.bind(fd, @addr, 16) < 0 { sock.close(fd); raise error.Bind; }
|
||||||
@@ -46,20 +46,20 @@ listen_on :: (port: s64) -> (s32, !HttpError) {
|
|||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
SO_RCVTIMEO :s32: 0x1006; // macOS
|
SO_RCVTIMEO :i32: 0x1006; // macOS
|
||||||
|
|
||||||
// macOS struct timeval (padded to 16 for the setsockopt copy).
|
// macOS struct timeval (padded to 16 for the setsockopt copy).
|
||||||
Timeval :: struct {
|
Timeval :: struct {
|
||||||
tv_sec: s64;
|
tv_sec: i64;
|
||||||
tv_usec: s32 = 0;
|
tv_usec: i32 = 0;
|
||||||
pad: s32 = 0;
|
pad: i32 = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bound blocking reads on `fd` to `secs` seconds. A sequential accept
|
// Bound blocking reads on `fd` to `secs` seconds. A sequential accept
|
||||||
// loop needs this: browsers open speculative preconnections that never
|
// loop needs this: browsers open speculative preconnections that never
|
||||||
// send bytes, and an unbounded read on one of those wedges the whole
|
// send bytes, and an unbounded read on one of those wedges the whole
|
||||||
// server while real requests sit in the backlog.
|
// server while real requests sit in the backlog.
|
||||||
set_read_timeout :: (fd: s32, secs: s64) {
|
set_read_timeout :: (fd: i32, secs: i64) {
|
||||||
tv : Timeval = .{ tv_sec = secs };
|
tv : Timeval = .{ tv_sec = secs };
|
||||||
sock.setsockopt(fd, sock.SOL_SOCKET, SO_RCVTIMEO, xx @tv, 16);
|
sock.setsockopt(fd, sock.SOL_SOCKET, SO_RCVTIMEO, xx @tv, 16);
|
||||||
}
|
}
|
||||||
@@ -81,7 +81,7 @@ parse_request :: (raw: string, req: *Request) -> bool {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
status_text :: (code: s64) -> string {
|
status_text :: (code: i64) -> string {
|
||||||
if code == 200 { return "OK"; }
|
if code == 200 { return "OK"; }
|
||||||
if code == 400 { return "Bad Request"; }
|
if code == 400 { return "Bad Request"; }
|
||||||
if code == 404 { return "Not Found"; }
|
if code == 404 { return "Not Found"; }
|
||||||
@@ -93,7 +93,7 @@ status_text :: (code: s64) -> string {
|
|||||||
// Write one complete response and leave the connection for the caller to
|
// Write one complete response and leave the connection for the caller to
|
||||||
// close. `extra` is zero or more pre-formatted header lines, each ending
|
// close. `extra` is zero or more pre-formatted header lines, each ending
|
||||||
// in `\r\n` ("" for none).
|
// in `\r\n` ("" for none).
|
||||||
respond :: (client: s32, code: s64, content_type: string, extra: string, body: string) {
|
respond :: (client: i32, code: i64, content_type: string, extra: string, body: string) {
|
||||||
h := concat("HTTP/1.1 ", concat(int_to_string(code), concat(" ", status_text(code))));
|
h := concat("HTTP/1.1 ", concat(int_to_string(code), concat(" ", status_text(code))));
|
||||||
h = concat(h, "\r\n");
|
h = concat(h, "\r\n");
|
||||||
h = concat(h, concat("Content-Type: ", concat(content_type, "\r\n")));
|
h = concat(h, concat("Content-Type: ", concat(content_type, "\r\n")));
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ Store :: struct {
|
|||||||
root: string;
|
root: string;
|
||||||
// Monotonic per-store counter naming `put_file`'s provisional staging
|
// Monotonic per-store counter naming `put_file`'s provisional staging
|
||||||
// files, so concurrent file puts don't clobber each other's temp copy.
|
// files, so concurrent file puts don't clobber each other's temp copy.
|
||||||
seq: s64;
|
seq: i64;
|
||||||
|
|
||||||
init :: (root: string) -> Store {
|
init :: (root: string) -> Store {
|
||||||
return Store.{ root = root, seq = 0 };
|
return Store.{ root = root, seq = 0 };
|
||||||
|
|||||||
@@ -120,7 +120,7 @@ ext_matches_platform :: (path: string, p: Platform) -> bool {
|
|||||||
// the first failing check (see the check order at the top of the file).
|
// the first failing check (see the check order at the top of the file).
|
||||||
validate_artifact_file :: (
|
validate_artifact_file :: (
|
||||||
path: string,
|
path: string,
|
||||||
expected_size: s64,
|
expected_size: i64,
|
||||||
expected_sha256: string,
|
expected_sha256: string,
|
||||||
platform: Platform,
|
platform: Platform,
|
||||||
content_type: string,
|
content_type: string,
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ contains :: (hay: string, needle: string) -> bool {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
main :: () -> s32 {
|
main :: () -> i32 {
|
||||||
gpa := GPA.init();
|
gpa := GPA.init();
|
||||||
|
|
||||||
// ── 1. No command → readable usage on stderr, EX_USAGE (64) ───────
|
// ── 1. No command → readable usage on stderr, EX_USAGE (64) ───────
|
||||||
|
|||||||
@@ -178,14 +178,14 @@ check_artifact_metadata :: () -> bool {
|
|||||||
return a.metadata == "{\"min_os\":\"14\"}";
|
return a.metadata == "{\"min_os\":\"14\"}";
|
||||||
}
|
}
|
||||||
|
|
||||||
run_case :: (label: string, ok: bool) -> s32 {
|
run_case :: (label: string, ok: bool) -> i32 {
|
||||||
if ok { print(" PASS {}\n", label); return 0; }
|
if ok { print(" PASS {}\n", label); return 0; }
|
||||||
print(" FAIL {}\n", label);
|
print(" FAIL {}\n", label);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
main :: () -> s32 {
|
main :: () -> i32 {
|
||||||
failures : s32 = 0;
|
failures : i32 = 0;
|
||||||
failures += run_case("accept: valid app", check_accepts_app());
|
failures += run_case("accept: valid app", check_accepts_app());
|
||||||
failures += run_case("accept: valid release", check_accepts_release());
|
failures += run_case("accept: valid release", check_accepts_release());
|
||||||
failures += run_case("accept: valid artifact", check_accepts_artifact());
|
failures += run_case("accept: valid artifact", check_accepts_artifact());
|
||||||
|
|||||||
@@ -64,18 +64,18 @@ check_missing_artifact_path :: (alloc: Allocator) -> bool {
|
|||||||
return raised and matched;
|
return raised and matched;
|
||||||
}
|
}
|
||||||
|
|
||||||
run_case :: (label: string, ok: bool) -> s32 {
|
run_case :: (label: string, ok: bool) -> i32 {
|
||||||
if ok { print(" PASS {}\n", label); return 0; }
|
if ok { print(" PASS {}\n", label); return 0; }
|
||||||
print(" FAIL {}\n", label);
|
print(" FAIL {}\n", label);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
main :: () -> s32 {
|
main :: () -> i32 {
|
||||||
gpa := GPA.init();
|
gpa := GPA.init();
|
||||||
arena := Arena.init(xx gpa, 65536);
|
arena := Arena.init(xx gpa, 65536);
|
||||||
defer arena.deinit();
|
defer arena.deinit();
|
||||||
|
|
||||||
failures : s32 = 0;
|
failures : i32 = 0;
|
||||||
failures += run_case("parse valid dist.json -> fields", check_parse_valid(xx arena));
|
failures += run_case("parse valid dist.json -> fields", check_parse_valid(xx arena));
|
||||||
failures += run_case("missing version -> MissingField", check_missing_version(xx arena));
|
failures += run_case("missing version -> MissingField", check_missing_version(xx arena));
|
||||||
failures += run_case("unknown platform 'psvita' -> UnknownPlatform", check_unknown_platform(xx arena));
|
failures += run_case("unknown platform 'psvita' -> UnknownPlatform", check_unknown_platform(xx arena));
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ assert_fails :: (label: string, mpath: string, store: string, want_code: string,
|
|||||||
out(concat(concat(" ", label), ": exit 1 + JSON error ok\n"));
|
out(concat(concat(" ", label), ": exit 1 + JSON error ok\n"));
|
||||||
}
|
}
|
||||||
|
|
||||||
main :: () -> s32 {
|
main :: () -> i32 {
|
||||||
gpa := GPA.init();
|
gpa := GPA.init();
|
||||||
arena := Arena.init(xx gpa, 1 << 20);
|
arena := Arena.init(xx gpa, 1 << 20);
|
||||||
defer arena.deinit();
|
defer arena.deinit();
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ STORE_REL :: ".sx-tmp/publish_happy";
|
|||||||
cwd :: () -> string {
|
cwd :: () -> string {
|
||||||
buf : [4096]u8 = ---;
|
buf : [4096]u8 = ---;
|
||||||
r := c_getcwd(@buf[0], 4096);
|
r := c_getcwd(@buf[0], 4096);
|
||||||
process.assert(cast(s64) r != 0, "getcwd must succeed");
|
process.assert(cast(i64) r != 0, "getcwd must succeed");
|
||||||
n := 0;
|
n := 0;
|
||||||
while buf[n] != 0 { n += 1; }
|
while buf[n] != 0 { n += 1; }
|
||||||
return substr(string.{ ptr = @buf[0], len = n }, 0, n);
|
return substr(string.{ ptr = @buf[0], len = n }, 0, n);
|
||||||
@@ -65,8 +65,8 @@ rehashes_to :: (path: string, want: string) -> bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Count audit events whose "action" equals `action`.
|
// Count audit events whose "action" equals `action`.
|
||||||
count_action :: (events: Array, action: string) -> s64 {
|
count_action :: (events: Array, action: string) -> i64 {
|
||||||
c : s64 = 0;
|
c : i64 = 0;
|
||||||
i := 0;
|
i := 0;
|
||||||
while i < events.len {
|
while i < events.len {
|
||||||
eo := events.items[i].object;
|
eo := events.items[i].object;
|
||||||
@@ -76,7 +76,7 @@ count_action :: (events: Array, action: string) -> s64 {
|
|||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
main :: () -> s32 {
|
main :: () -> i32 {
|
||||||
gpa := GPA.init();
|
gpa := GPA.init();
|
||||||
arena := Arena.init(xx gpa, 1 << 20);
|
arena := Arena.init(xx gpa, 1 << 20);
|
||||||
defer arena.deinit();
|
defer arena.deinit();
|
||||||
|
|||||||
@@ -53,8 +53,8 @@ get_obj :: (o: Object, key: string) -> Object { return get(o, key).object; }
|
|||||||
get_arr :: (o: Object, key: string) -> Array { return get(o, key).array; }
|
get_arr :: (o: Object, key: string) -> Array { return get(o, key).array; }
|
||||||
|
|
||||||
// Count audit events whose "action" equals `action`.
|
// Count audit events whose "action" equals `action`.
|
||||||
count_action :: (events: Array, action: string) -> s64 {
|
count_action :: (events: Array, action: string) -> i64 {
|
||||||
c : s64 = 0;
|
c : i64 = 0;
|
||||||
i := 0;
|
i := 0;
|
||||||
while i < events.len {
|
while i < events.len {
|
||||||
eo := events.items[i].object;
|
eo := events.items[i].object;
|
||||||
@@ -98,7 +98,7 @@ load_db :: (scratch: Allocator) -> Object {
|
|||||||
return dv.object;
|
return dv.object;
|
||||||
}
|
}
|
||||||
|
|
||||||
main :: () -> s32 {
|
main :: () -> i32 {
|
||||||
gpa := GPA.init();
|
gpa := GPA.init();
|
||||||
arena := Arena.init(xx gpa, 1 << 20);
|
arena := Arena.init(xx gpa, 1 << 20);
|
||||||
defer arena.deinit();
|
defer arena.deinit();
|
||||||
|
|||||||
@@ -48,8 +48,8 @@ get_arr :: (o: Object, key: string) -> Array { return get(o, key).array; }
|
|||||||
|
|
||||||
// Count audit events matching (actor, action) — distinguishes the CLI's
|
// Count audit events matching (actor, action) — distinguishes the CLI's
|
||||||
// channel events from the publish pipeline's "ci" ones.
|
// channel events from the publish pipeline's "ci" ones.
|
||||||
count_actor_action :: (events: Array, actor: string, action: string) -> s64 {
|
count_actor_action :: (events: Array, actor: string, action: string) -> i64 {
|
||||||
c : s64 = 0;
|
c : i64 = 0;
|
||||||
i := 0;
|
i := 0;
|
||||||
while i < events.len {
|
while i < events.len {
|
||||||
eo := events.items[i].object;
|
eo := events.items[i].object;
|
||||||
@@ -94,7 +94,7 @@ promote_cmd :: (release_id: string) -> string {
|
|||||||
|
|
||||||
ROLLBACK_CMD :: "build/dist release rollback --app acme-app --channel beta --local-store .sx-tmp/release_ops --json 2>/dev/null";
|
ROLLBACK_CMD :: "build/dist release rollback --app acme-app --channel beta --local-store .sx-tmp/release_ops --json 2>/dev/null";
|
||||||
|
|
||||||
main :: () -> s32 {
|
main :: () -> i32 {
|
||||||
gpa := GPA.init();
|
gpa := GPA.init();
|
||||||
arena := Arena.init(xx gpa, 1 << 20);
|
arena := Arena.init(xx gpa, 1 << 20);
|
||||||
defer arena.deinit();
|
defer arena.deinit();
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ process :: #import "modules/std/process.sx";
|
|||||||
#import "../src/domain/audit.sx";
|
#import "../src/domain/audit.sx";
|
||||||
#import "../src/repo/repo.sx";
|
#import "../src/repo/repo.sx";
|
||||||
|
|
||||||
main :: () -> s32 {
|
main :: () -> i32 {
|
||||||
gpa := GPA.init();
|
gpa := GPA.init();
|
||||||
|
|
||||||
// Construct the repo under the tracked allocator, then leave the scope.
|
// Construct the repo under the tracked allocator, then leave the scope.
|
||||||
|
|||||||
@@ -118,7 +118,7 @@ the_event :: () -> AuditEvent {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
main :: () -> s32 {
|
main :: () -> i32 {
|
||||||
root := ".sx-tmp/repo-roundtrip";
|
root := ".sx-tmp/repo-roundtrip";
|
||||||
root2 := ".sx-tmp/repo-roundtrip-2";
|
root2 := ".sx-tmp/repo-roundtrip-2";
|
||||||
process.run(concat("rm -rf ", root));
|
process.run(concat("rm -rf ", root));
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ mk_named_channel :: (app_id: string, name: string) -> Channel {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
main :: () -> s32 {
|
main :: () -> i32 {
|
||||||
root := ".sx-tmp/repo-transaction";
|
root := ".sx-tmp/repo-transaction";
|
||||||
process.run(concat("rm -rf ", root));
|
process.run(concat("rm -rf ", root));
|
||||||
|
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ publish_cmd :: (mpath: string) -> string {
|
|||||||
return concat(c, " --json 2>/dev/null >/dev/null");
|
return concat(c, " --json 2>/dev/null >/dev/null");
|
||||||
}
|
}
|
||||||
|
|
||||||
main :: () -> s32 {
|
main :: () -> i32 {
|
||||||
gpa := GPA.init();
|
gpa := GPA.init();
|
||||||
arena := Arena.init(xx gpa, 1 << 20);
|
arena := Arena.init(xx gpa, 1 << 20);
|
||||||
defer arena.deinit();
|
defer arena.deinit();
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
// The runner (tests/run.sh) treats a clean exit as `ok`.
|
// The runner (tests/run.sh) treats a clean exit as `ok`.
|
||||||
#import "modules/std.sx";
|
#import "modules/std.sx";
|
||||||
|
|
||||||
main :: () -> s32 {
|
main :: () -> i32 {
|
||||||
print("distribution smoke test: toolchain ok\n");
|
print("distribution smoke test: toolchain ok\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ incoming_count :: (dir: string) -> string {
|
|||||||
return res.stdout;
|
return res.stdout;
|
||||||
}
|
}
|
||||||
|
|
||||||
main :: () -> s32 {
|
main :: () -> i32 {
|
||||||
root := ".sx-tmp/store-cas";
|
root := ".sx-tmp/store-cas";
|
||||||
process.run(concat("rm -rf ", root)); // fresh root, even after a crashed prior run
|
process.run(concat("rm -rf ", root)); // fresh root, even after a crashed prior run
|
||||||
|
|
||||||
|
|||||||
@@ -83,14 +83,14 @@ check_missing_file :: () -> bool {
|
|||||||
return failed_with(o, .missing_file);
|
return failed_with(o, .missing_file);
|
||||||
}
|
}
|
||||||
|
|
||||||
run_case :: (label: string, ok: bool) -> s32 {
|
run_case :: (label: string, ok: bool) -> i32 {
|
||||||
if ok { print(" PASS {}\n", label); return 0; }
|
if ok { print(" PASS {}\n", label); return 0; }
|
||||||
print(" FAIL {}\n", label);
|
print(" FAIL {}\n", label);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
main :: () -> s32 {
|
main :: () -> i32 {
|
||||||
failures : s32 = 0;
|
failures : i32 = 0;
|
||||||
failures += run_case("good .apk/android_apk -> valid/ok", check_good_apk());
|
failures += run_case("good .apk/android_apk -> valid/ok", check_good_apk());
|
||||||
failures += run_case("good .ipa/ios -> valid/ok", check_good_ipa());
|
failures += run_case("good .ipa/ios -> valid/ok", check_good_ipa());
|
||||||
failures += run_case("wrong size -> size_mismatch", check_size_mismatch());
|
failures += run_case("wrong size -> size_mismatch", check_size_mismatch());
|
||||||
|
|||||||
Reference in New Issue
Block a user