ww: resolve root argv0 and retire stale help paths
This commit is contained in:
@@ -20,13 +20,12 @@ static const char *usage =
|
||||
" build [-S] [-w DIR] [-o FILE] [path] compile module; -S stops after package asm\n"
|
||||
" run [path] ... build then exec, passing extra args to the program\n"
|
||||
" test [-S -o STEM] [-w DIR] [options] [path] build/run tests; -S emits package asm\n"
|
||||
" fmt <path> reformat ww source\n"
|
||||
" version print version and exit\n"
|
||||
"\n"
|
||||
" path forms:\n"
|
||||
" foo.ww literal file\n"
|
||||
" foo search cwd, -I dirs, then $WW_LIB for foo.ww or foo/foo.ww\n"
|
||||
" lib/foo directory: build lib/foo/foo.ww\n"
|
||||
" foo search cwd, -I dirs, then the source library for foo.ww or foo/\n"
|
||||
" lib/foo directory: build its package sources\n"
|
||||
" lib/... every package under lib, recursively (test only)\n"
|
||||
" . build the cwd's <basename>.ww\n";
|
||||
|
||||
@@ -1865,14 +1864,6 @@ do_test(int argc, char **argv)
|
||||
return exec_package_tests(argc, argv, src, NULL, src == NULL);
|
||||
}
|
||||
|
||||
static int
|
||||
do_fmt(int argc, char **argv)
|
||||
{
|
||||
(void)argc; (void)argv;
|
||||
fputs("ww: fmt: not implemented in this phase\n", stderr);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
@@ -1891,7 +1882,6 @@ main(int argc, char **argv)
|
||||
if (strcmp(cmd, "build") == 0) return do_build(argc - 2, argv + 2);
|
||||
if (strcmp(cmd, "run") == 0) return do_run(argc - 2, argv + 2);
|
||||
if (strcmp(cmd, "test") == 0) return do_test(argc - 2, argv + 2);
|
||||
if (strcmp(cmd, "fmt") == 0) return do_fmt(argc - 2, argv + 2);
|
||||
fprintf(stderr, "ww: unknown subcommand: %s\n", cmd);
|
||||
fputs(usage, stderr);
|
||||
return 2;
|
||||
|
||||
@@ -96,17 +96,18 @@ fn cstrseal(dst: *u8, off: u64) void = {
|
||||
|
||||
fn selfdirinto(dst: *u8, dstsz: u64, argv0: *u8) void = {
|
||||
let n: u64 = cstrlen(argv0);
|
||||
let cut: u64 = 0u64;
|
||||
let cut: u64 = n;
|
||||
let i: u64 = 0u64;
|
||||
for (i < n) {
|
||||
if (argv0[i] == 47u8) { cut = i; }; // '/'
|
||||
if (argv0[i] == 47u8) { cut = i; };
|
||||
i += 1u64;
|
||||
};
|
||||
if (cut == 0u64) {
|
||||
dst[0u64] = 46u8; // '.'
|
||||
if (cut == n) {
|
||||
dst[0u64] = 46u8;
|
||||
dst[1u64] = 0u8;
|
||||
return;
|
||||
};
|
||||
if (cut == 0u64) { cut = 1u64; };
|
||||
if (cut + 1u64 >= dstsz) { cut = dstsz - 2u64; };
|
||||
bytecpy(dst, argv0, cut);
|
||||
dst[cut] = 0u8;
|
||||
@@ -2000,7 +2001,7 @@ fn resolvemodule(selfdir: *u8, name: *u8, incs: *u8, isdir: *i32) *u8 = {
|
||||
};
|
||||
|
||||
fn writeusage(fd: i32) void = {
|
||||
let s: str = "usage: ww [-V] <subcommand> [args...]\n -V print version and exit\n build [-S] [-w DIR] [-o FILE] [path] compile module; -S stops after package asm\n run [path] ... build then exec, passing extra args to the program\n test [-S -o STEM] [-w DIR] [options] [path] build/run tests; -S emits package asm\n version print version and exit\n\n path forms:\n foo.ww literal file\n foo search cwd, -I dirs, then $WW_LIB-equiv for foo.ww or foo/foo.ww\n lib/foo directory: build lib/foo/foo.ww\n lib/... every package under lib, recursively (test only)\n . build the cwd's <basename>.ww\n";
|
||||
let s: str = "usage: ww [-V] <subcommand> [args...]\n -V print version and exit\n build [-S] [-w DIR] [-o FILE] [path] compile module; -S stops after package asm\n run [path] ... build then exec, passing extra args to the program\n test [-S -o STEM] [-w DIR] [options] [path] build/run tests; -S emits package asm\n version print version and exit\n\n path forms:\n foo.ww literal file\n foo search cwd, -I dirs, then the source library for foo.ww or foo/\n lib/foo directory: build its package sources\n lib/... every package under lib, recursively (test only)\n . build the cwd's <basename>.ww\n";
|
||||
os.write(fd, s.ptr, s.len: u64);
|
||||
};
|
||||
|
||||
@@ -2733,7 +2734,9 @@ export fn main(argc: i32, argv: **u8) i32 = {
|
||||
if (cstreqlit(cmd, "test")) {
|
||||
return dotest(selfdir.ptr, argv, argc, 2);
|
||||
};
|
||||
cerr("ww: unknown subcommand\n");
|
||||
cerr("ww: unknown subcommand: ");
|
||||
os.write(2, cmd, cstrlen(cmd));
|
||||
cerr("\n");
|
||||
writeusage(2);
|
||||
return 2;
|
||||
};
|
||||
|
||||
@@ -73,6 +73,28 @@ fn rundrv(root: str, name: str, drv: str, argv: []str,
|
||||
assert(out.termination == exec.termination.EXIT);
|
||||
};
|
||||
|
||||
fn runrootargv(dir: str, root: str, name: str, drv: str,
|
||||
out: *testenv.commandout) void = {
|
||||
let av: []str = ["/ww", "build", "rootprobe"];
|
||||
let env: []str = ["PATH=/usr/bin:/bin", "LC_ALL=C"];
|
||||
let c: exec.command;
|
||||
c.path = testenv.driver(drv);
|
||||
c.argv = av;
|
||||
c.env = env;
|
||||
c.dir = dir;
|
||||
c.stdoutpath = strings.concat(root, "/", name, ".stdout");
|
||||
c.stderrpath = strings.concat(root, "/", name, ".stderr");
|
||||
c.deadline = time.add(time.now(time.clock.monotonic), tmo());
|
||||
c.grace = (100i64 * (time.millisecond: i64)): time.duration;
|
||||
let r: exec.result;
|
||||
exec.run(&c, &r);
|
||||
assert(r.errno == 0 && r.cleanuperrno == 0);
|
||||
out.termination = r.termination;
|
||||
out.code = r.code;
|
||||
out.stdout = testenv.readfile(c.stdoutpath);
|
||||
out.stderr = testenv.readfile(c.stderrpath);
|
||||
};
|
||||
|
||||
@test fn version() void = {
|
||||
let td: str = testenv.fresh();
|
||||
let want: str = strings.concat("ww ", wwversion(), "\n");
|
||||
@@ -92,6 +114,56 @@ fn rundrv(root: str, name: str, drv: str, argv: []str,
|
||||
testenv.clean(td);
|
||||
};
|
||||
|
||||
@test fn help() void = {
|
||||
let td: str = testenv.fresh();
|
||||
let tail: []str = ["-h"];
|
||||
let co: testenv.commandout;
|
||||
let wo: testenv.commandout;
|
||||
rundrv(td, "help_c", "ww", tail, &co);
|
||||
rundrv(td, "help_w", "ww_ww", tail, &wo);
|
||||
if (co.code != 0 || wo.code != 0
|
||||
|| !testenv.same(co.stdout, wo.stdout)
|
||||
|| co.stderr.len != 0 || wo.stderr.len != 0) {
|
||||
fail("help", "driver help is not byte-identical on stdout");
|
||||
};
|
||||
if (testenv.has(co.stdout, "foo/foo.ww")
|
||||
|| testenv.has(co.stdout, "fmt <path>")) {
|
||||
fail("help", "driver help advertises a retired path or command");
|
||||
};
|
||||
let fmttail: []str = ["fmt"];
|
||||
rundrv(td, "fmt_c", "ww", fmttail, &co);
|
||||
rundrv(td, "fmt_w", "ww_ww", fmttail, &wo);
|
||||
if (co.code != 2 || wo.code != co.code
|
||||
|| !testenv.same(co.stdout, wo.stdout)
|
||||
|| !testenv.same(co.stderr, wo.stderr)
|
||||
|| !testenv.has(co.stderr, "unknown subcommand: fmt")) {
|
||||
fail("help", "retired fmt command is not an identical unknown command");
|
||||
};
|
||||
testenv.clean(td);
|
||||
};
|
||||
|
||||
@test fn rootargv0() void = {
|
||||
let td: str = testenv.fresh();
|
||||
let lib: str = strings.concat(td, "/lib");
|
||||
let a: str = strings.concat(td, "/a");
|
||||
let wd: str = strings.concat(a, "/b");
|
||||
assert(os.mkdir(lib, 448i32) == 0);
|
||||
assert(os.mkdir(a, 448i32) == 0);
|
||||
assert(os.mkdir(wd, 448i32) == 0);
|
||||
testenv.writefile(strings.concat(lib, "/rootprobe.ww"),
|
||||
"package main;\nexport fn main() i32 = { return 0; };\n");
|
||||
let co: testenv.commandout;
|
||||
let wo: testenv.commandout;
|
||||
runrootargv(wd, td, "rootargv_c", "ww", &co);
|
||||
runrootargv(wd, td, "rootargv_w", "ww_ww", &wo);
|
||||
if (co.code == 0 || wo.code == 0
|
||||
|| !testenv.has(co.stderr, "cannot find module")
|
||||
|| !testenv.has(wo.stderr, "cannot find module")) {
|
||||
fail("rootargv0", "argv0 /ww did not resolve selfdir as /");
|
||||
};
|
||||
testenv.clean(td);
|
||||
};
|
||||
|
||||
// a3 == "" means a two-token argv tail; no row passes a literal "".
|
||||
@test fn flagargs() void = {
|
||||
let a1: []str = ["build", "build", "build", "build", "build",
|
||||
|
||||
Reference in New Issue
Block a user