driver: ignore wrong-suffix files as named sources
This commit is contained in:
@@ -7241,6 +7241,13 @@ basename_no_ext(const char *path, char *out, size_t outsz)
|
|||||||
if (dot && strcmp(dot, ".ww") == 0) *dot = '\0';
|
if (dot && strcmp(dot, ".ww") == 0) *dot = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
source_operand_named(const char *path)
|
||||||
|
{
|
||||||
|
size_t n = strlen(path);
|
||||||
|
return n >= 3 && strcmp(path + n - 3, ".ww") == 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Go's named-file package still applies matchFile's unconditional basename
|
/* Go's named-file package still applies matchFile's unconditional basename
|
||||||
* exclusion before UseAllFiles, platform suffixes, source parsing, or test-file
|
* exclusion before UseAllFiles, platform suffixes, source parsing, or test-file
|
||||||
* classification. Keep this predicate on the public operand spelling: a
|
* classification. Keep this predicate on the public operand spelling: a
|
||||||
@@ -7250,8 +7257,7 @@ static int
|
|||||||
source_operand_ignored(const char *path)
|
source_operand_ignored(const char *path)
|
||||||
{
|
{
|
||||||
struct stat st;
|
struct stat st;
|
||||||
size_t n = strlen(path);
|
if (!source_operand_named(path)) return 0;
|
||||||
if (n < 3 || strcmp(path + n - 3, ".ww") != 0) return 0;
|
|
||||||
if (stat(path, &st) != 0 || S_ISDIR(st.st_mode)) return 0;
|
if (stat(path, &st) != 0 || S_ISDIR(st.st_mode)) return 0;
|
||||||
const char *base = strrchr(path, '/');
|
const char *base = strrchr(path, '/');
|
||||||
base = base ? base + 1 : path;
|
base = base ? base + 1 : path;
|
||||||
@@ -7342,7 +7348,7 @@ resolve_module(const char *name, const char *incs, char *out, size_t outsz,
|
|||||||
{
|
{
|
||||||
struct stat st;
|
struct stat st;
|
||||||
if (stat(name, &st) == 0) {
|
if (stat(name, &st) == 0) {
|
||||||
if (S_ISREG(st.st_mode)) {
|
if (S_ISREG(st.st_mode) && source_operand_named(name)) {
|
||||||
if (strlen(name) + 1 > outsz) return 0;
|
if (strlen(name) + 1 > outsz) return 0;
|
||||||
memcpy(out, name, strlen(name) + 1);
|
memcpy(out, name, strlen(name) + 1);
|
||||||
*is_dir = 0;
|
*is_dir = 0;
|
||||||
@@ -7578,7 +7584,9 @@ do_build(int argc, char **argv)
|
|||||||
return exec_package_command(argc, argv, src, NULL, NULL, 0, 1);
|
return exec_package_command(argc, argv, src, NULL, NULL, 0, 1);
|
||||||
}
|
}
|
||||||
struct stat requested;
|
struct stat requested;
|
||||||
int literal = stat(src, &requested) == 0;
|
int literal = stat(src, &requested) == 0
|
||||||
|
&& (S_ISDIR(requested.st_mode)
|
||||||
|
|| source_operand_named(src));
|
||||||
int requested_nondirectory = literal && !S_ISDIR(requested.st_mode);
|
int requested_nondirectory = literal && !S_ISDIR(requested.st_mode);
|
||||||
if (source_operand_ignored(src)) {
|
if (source_operand_ignored(src)) {
|
||||||
source_operand_no_sources(src);
|
source_operand_no_sources(src);
|
||||||
@@ -7705,10 +7713,12 @@ do_run(int argc, char **argv)
|
|||||||
if (next < 0) { free(incs); return 2; }
|
if (next < 0) { free(incs); return 2; }
|
||||||
if (src == NULL) src = ".";
|
if (src == NULL) src = ".";
|
||||||
struct stat requested;
|
struct stat requested;
|
||||||
int literal = stat(src, &requested) == 0;
|
int literal = stat(src, &requested) == 0
|
||||||
|
&& (S_ISDIR(requested.st_mode)
|
||||||
|
|| source_operand_named(src));
|
||||||
if (literal && S_ISDIR(requested.st_mode)) {
|
if (literal && S_ISDIR(requested.st_mode)) {
|
||||||
size_t n = strlen(src);
|
size_t n = strlen(src);
|
||||||
if (n >= 3 && strcmp(src + n - 3, ".ww") == 0) {
|
if (source_operand_named(src)) {
|
||||||
if (n >= 8 && strcmp(src + n - 8, "_test.ww") == 0)
|
if (n >= 8 && strcmp(src + n - 8, "_test.ww") == 0)
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"ww: cannot run *_test.ww files (%s)\n", src);
|
"ww: cannot run *_test.ww files (%s)\n", src);
|
||||||
@@ -8188,10 +8198,14 @@ do_test(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
if (pattern != NULL) {
|
if (pattern != NULL) {
|
||||||
struct stat first;
|
struct stat first;
|
||||||
if (stat(target, &first) != 0 || !S_ISREG(first.st_mode)) {
|
int first_found = stat(target, &first) == 0;
|
||||||
|
int first_logical = !first_found
|
||||||
|
|| (!S_ISDIR(first.st_mode) && !source_operand_named(target));
|
||||||
|
if (!first_found || !S_ISREG(first.st_mode)
|
||||||
|
|| !source_operand_named(target)) {
|
||||||
char first_resolved[PATH_MAX];
|
char first_resolved[PATH_MAX];
|
||||||
int first_is_dir = 0;
|
int first_is_dir = 0;
|
||||||
if (stat(target, &first) == 0
|
if (!first_logical
|
||||||
|| !resolve_module(target, incs, first_resolved,
|
|| !resolve_module(target, incs, first_resolved,
|
||||||
sizeof first_resolved, &first_is_dir)
|
sizeof first_resolved, &first_is_dir)
|
||||||
|| first_is_dir) {
|
|| first_is_dir) {
|
||||||
@@ -8229,7 +8243,8 @@ do_test(int argc, char **argv)
|
|||||||
return exec_package_command(argc, argv, src, NULL, NULL, 0, 0);
|
return exec_package_command(argc, argv, src, NULL, NULL, 0, 0);
|
||||||
}
|
}
|
||||||
struct stat st;
|
struct stat st;
|
||||||
if (stat(target, &st) != 0) {
|
if (stat(target, &st) != 0
|
||||||
|
|| (!S_ISDIR(st.st_mode) && !source_operand_named(target))) {
|
||||||
/* not a literal path — try module resolution and run as
|
/* not a literal path — try module resolution and run as
|
||||||
* a single test program. */
|
* a single test program. */
|
||||||
char resolved[PATH_MAX];
|
char resolved[PATH_MAX];
|
||||||
@@ -8349,7 +8364,7 @@ do_test(int argc, char **argv)
|
|||||||
if (test_failed) fputs("FAIL\n", stdout);
|
if (test_failed) fputs("FAIL\n", stdout);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
if (S_ISREG(st.st_mode)) {
|
if (S_ISREG(st.st_mode) && source_operand_named(target)) {
|
||||||
if (nproducts != 0) {
|
if (nproducts != 0) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"ww test: package-test variant needs one directory\n");
|
"ww test: package-test variant needs one directory\n");
|
||||||
|
|||||||
@@ -10511,6 +10511,150 @@ serialized representation changes: build workdir format remains `18`, test
|
|||||||
workdir format remains `19`, semantic storage format remains `3`, and no cache
|
workdir format remains `19`, semantic storage format remains `3`, and no cache
|
||||||
or result record is added.
|
or result record is added.
|
||||||
|
|
||||||
|
### 11.54 Implemented wrong-suffix physical-source exclusion
|
||||||
|
|
||||||
|
One public operand is a local named source only when its exact requested
|
||||||
|
spelling ends `.ww` and the command's existing file-kind rule admits it. An
|
||||||
|
existing non-directory object with any other suffix does not become source and
|
||||||
|
does not preempt the same operand's ordinary dotted lookup. Thus a physical
|
||||||
|
`foo.bar` is ignored as a source while request `foo.bar` continues to
|
||||||
|
`foo/bar.ww` or `foo/bar/`. An existing directory, including a symlink whose
|
||||||
|
target is a directory, remains a stat-first directory package regardless of
|
||||||
|
suffix.
|
||||||
|
|
||||||
|
#### Pinned authority and applicability
|
||||||
|
|
||||||
|
- **behavior directly implemented or asserted by pinned Go** — official Go
|
||||||
|
1.26.5 commit `c19862e5f8415b4f24b189d065ed739517c548ba` enters named-file
|
||||||
|
mode in `cmd/go/internal/load/pkg.go:2887–2932`, especially 2903–2918,
|
||||||
|
only when a requested spelling ends `.go`, `Stat` succeeds, and the result
|
||||||
|
is not a directory. `GoFilesPackage` independently rejects every non-`.go`
|
||||||
|
member at `pkg.go:3244–3318` before constructing its synthetic package.
|
||||||
|
Build and test call that loader at
|
||||||
|
`cmd/go/internal/work/build.go:459–477` and
|
||||||
|
`cmd/go/internal/test/test.go:684–719`. Run independently consumes only
|
||||||
|
leading `.go` spellings at `cmd/go/internal/run/run.go:73–145`, especially
|
||||||
|
96–123.
|
||||||
|
- **behavior directly implemented or asserted by pinned Go** — official
|
||||||
|
`cmd/go/testdata/script/list_test_non_go_files.txt:1–13` directly tests a
|
||||||
|
mixed named-file list: after a `.go` member selects named-file mode,
|
||||||
|
`GoFilesPackage` rejects the non-`.go` member. Official `run_hello.txt:1–10`
|
||||||
|
and `run_set_executable_name.txt:4–17` anchor ordinary named-file and package
|
||||||
|
run fronts. None directly tests one existing wrong-suffix object colliding
|
||||||
|
with a package request, and the official tree contains no such singular
|
||||||
|
build/run/test script.
|
||||||
|
- **behavior derived from the pinned implementation** — the singular
|
||||||
|
collision result follows from the pinned suffix-before-`Stat` build/test
|
||||||
|
gate and run's suffix-only scan. WW's honest local adaptation applies the
|
||||||
|
same positive spelling decision to `.ww` named sources before its existing
|
||||||
|
dotted search. It requires no module, manifest, registry, network lookup,
|
||||||
|
generalized import syntax, cache, database, CAS, lock, or source expression.
|
||||||
|
|
||||||
|
#### Ownership, selection, and identity
|
||||||
|
|
||||||
|
- **directly measured WW behavior** — before this change, both stages adopted
|
||||||
|
an existing physical `foo.bar` as a raw source. Build and run therefore used
|
||||||
|
its package, imports, main, and runtime status instead of `foo/bar.ww`;
|
||||||
|
raw, compile-only, and assembly-only test used its test descriptors and
|
||||||
|
retained its semantic/public bytes. Removing only `foo.bar` selected the
|
||||||
|
logical provider and changed all of those observations.
|
||||||
|
- **behavior derived from the pinned implementation** — the true shared
|
||||||
|
owners are `cmd/ww/main.c::resolve_module` and
|
||||||
|
`selfhost/cmd/ww/main.ww::resolvemodule`. Their direct non-directory adoption
|
||||||
|
now requires the exact `.ww` requested spelling. The mirrored spelling
|
||||||
|
predicate also owns build/run requested-literal bookkeeping and raw test's
|
||||||
|
second-positional classifier plus main stat/resolution branch. These command
|
||||||
|
fronts distinguish direct directory, eligible direct source, and logical
|
||||||
|
resolution without moving the rule into the compiler, enumerator, graph,
|
||||||
|
coordinator, producer, or runtime.
|
||||||
|
- **directly measured WW behavior** — a resolved logical single-file provider
|
||||||
|
retains the established command-line-file root family `__root.*`; selection
|
||||||
|
by a dotted request does not invent a dotted storage identity. A resolved
|
||||||
|
logical directory retains its dotted package/import/action family such as
|
||||||
|
`foo.bar.*`. The ignored physical pathname, object kind, containing
|
||||||
|
directory, bytes, mode, and timestamp create no package member, qualifier,
|
||||||
|
graph node or edge, action, symbol, `.wwi`, initializer, artifact,
|
||||||
|
publication destination, or persistence key. The logical requested spelling
|
||||||
|
remains canonical request identity where the existing directory route uses
|
||||||
|
it.
|
||||||
|
- **directly measured WW behavior** — requested suffix, not a symlink target's
|
||||||
|
basename, owns the positive gate. A wrong-suffix symlink to a regular or
|
||||||
|
non-directory special object is ignored as source; a wrong-suffix symlink to
|
||||||
|
a directory follows ordinary directory routing. A visible `.ww` symlink to a
|
||||||
|
regular source remains eligible. Each stage retains its prior visible `.ww`
|
||||||
|
special-file kind handling; this slice does not make FIFO/device loading a
|
||||||
|
shared new contract.
|
||||||
|
|
||||||
|
#### Build, test, package, and import effects
|
||||||
|
|
||||||
|
- **directly measured WW behavior** — with a logical provider, build produces
|
||||||
|
the same source set, import closure, initializer graph, producer calls,
|
||||||
|
runtime result, public output, and persistent artifacts whether the
|
||||||
|
wrong-suffix object is absent or present. Run executes that same provider.
|
||||||
|
Raw/running test, the historical second-positional test-name filter,
|
||||||
|
`test -c`, and `test -S` select the same logical test package, descriptors,
|
||||||
|
support closure, binary, and assembly. Cstage and WWstage outputs and every
|
||||||
|
comparable semantic artifact are byte-identical.
|
||||||
|
- **directly measured WW behavior** — the ignored object's package clause,
|
||||||
|
imports, malformed bytes, checker failures, abort/nonzero behavior, and
|
||||||
|
timestamps are not source input and cannot displace logical-provider
|
||||||
|
diagnostics. Package membership and import edges are exactly those of the
|
||||||
|
provider. A logical directory retains its dotted identity and a logical file
|
||||||
|
retains `__root`; physical collision state supplies neither.
|
||||||
|
- **directly measured WW behavior** — when no logical provider exists, a
|
||||||
|
collision matches the absent-physical control. An ordinary build or run
|
||||||
|
emits its existing `cannot find module` diagnostic; raw test emits its
|
||||||
|
existing `cannot find` diagnostic plus `FAIL` only when running; `-c` and
|
||||||
|
`-S` omit that marker. A second positional deliberately retains the historic
|
||||||
|
package-coordinator route and its exact canonicalization or usage result,
|
||||||
|
rather than being silently redefined as a direct cannot-find path. Existing
|
||||||
|
flag, output, tree, package-option, hidden-source, named `_test.ww`, and
|
||||||
|
`.ww` run-directory precedence remains unchanged.
|
||||||
|
- **behavior derived from the pinned implementation** — all four permanent
|
||||||
|
axes meet at this one source-eligibility decision. Build no longer constructs
|
||||||
|
or publishes the wrong action; test no longer constructs or runs the wrong
|
||||||
|
test package; package membership is not stolen by an ineligible physical
|
||||||
|
filename; and import binding/initialization comes only from the logical
|
||||||
|
provider. No axis receives a compatibility bypass or new identity model.
|
||||||
|
|
||||||
|
#### Lifecycle, parity, formats, and scope
|
||||||
|
|
||||||
|
- **directly measured WW behavior** — changing the collision among absent and
|
||||||
|
stat-successful non-directory states does not invalidate semantic actions or
|
||||||
|
alter semantic bytes or producer inputs. An unchanged warm command still
|
||||||
|
performs the established final link and success publication, producing the
|
||||||
|
same public bytes while its inode and mtime may change. Replacing the
|
||||||
|
collision with a directory, or retargeting a symlink to a directory, leaves
|
||||||
|
this case and follows ordinary stat-first directory behavior; no new atomic
|
||||||
|
snapshot promise is made for a concurrent kind change.
|
||||||
|
- **directly measured WW behavior** — logical producer failure preserves the
|
||||||
|
prior public and semantic generation. A retained running-test runtime failure
|
||||||
|
occurs after the complete logical build generation commits: deferred public
|
||||||
|
installation is skipped, so prior retained public bytes survive while the
|
||||||
|
newly built semantic generation remains committed and reusable. Restoring the
|
||||||
|
prior source requires a later successful rebuild and commit, not rollback of
|
||||||
|
the runtime-failing generation. Normal completion and controlled failures
|
||||||
|
remove request-owned scratch and transaction fragments. The spelling gate is
|
||||||
|
request-local and allocates no state before logical action or coordinator
|
||||||
|
start; concurrent requests use separate destinations and the existing
|
||||||
|
logical-action synchronization.
|
||||||
|
- **directly measured WW behavior** — external signal interruption after an
|
||||||
|
action starts is unchanged. In particular, the verified direct-driver fixed
|
||||||
|
`.new` leakage and later persistent-request poisoning remain open. This
|
||||||
|
source classifier neither prevents nor recovers that residue and makes no
|
||||||
|
signal-cleanup claim.
|
||||||
|
- **behavior derived from the pinned implementation** — the rule does not
|
||||||
|
complete the remaining suffix-first run front, multiple named sources,
|
||||||
|
finite `.ww` FIFO capture, shared test-process state/failure topology,
|
||||||
|
Go-compatible `-run` regular expressions, or `package documentation`
|
||||||
|
suppression. Existing `.ww` directory slices, hidden-source exclusion,
|
||||||
|
named `_test.ww` build omission, recursive/multiple-root coordination,
|
||||||
|
package syntax, and import syntax remain intact.
|
||||||
|
|
||||||
|
Build workdir format remains `18`, test workdir format remains `19`, and
|
||||||
|
semantic storage format remains `3`. No schema, action descriptor, cache/result
|
||||||
|
record, manifest, transaction protocol, or lock changes.
|
||||||
|
|
||||||
## 12. Candidate architectures and hard-gate decision
|
## 12. Candidate architectures and hard-gate decision
|
||||||
|
|
||||||
Five candidates were developed as coherent systems, not as feature bins.
|
Five candidates were developed as coherent systems, not as feature bins.
|
||||||
|
|||||||
46
docs/spec.md
46
docs/spec.md
@@ -395,6 +395,52 @@ ImportPath = ident { "." ident } .
|
|||||||
persistence, process, or filesystem owner. Build and all test forms retain
|
persistence, process, or filesystem owner. Build and all test forms retain
|
||||||
their distinct stat-first directory behavior. Build workdir format remains
|
their distinct stat-first directory behavior. Build workdir format remains
|
||||||
18, test workdir format remains 19, and semantic storage format remains 3.
|
18, test workdir format remains 19, and semantic storage format remains 3.
|
||||||
|
- A public operand is eligible for direct named-source adoption only when its
|
||||||
|
exact requested spelling ends `.ww` and that command's existing file-kind
|
||||||
|
rule admits it. An existing non-directory object with another suffix is not
|
||||||
|
source: its bytes, package clause, imports, syntax, test declarations,
|
||||||
|
runtime behavior, mode, and timestamp are not read as source, and ordinary
|
||||||
|
dotted resolution continues exactly as though the colliding object were
|
||||||
|
absent. Thus request `foo.bar` may resolve `foo/bar.ww` or `foo/bar/` even
|
||||||
|
while a physical non-directory `foo.bar` exists. A wrong-suffix symlink to a
|
||||||
|
non-directory is the same ignored collision; a symlink to a directory remains
|
||||||
|
an ordinary stat-first directory request. A visible `.ww` symlink to a
|
||||||
|
regular source remains eligible, and the established stage-specific handling
|
||||||
|
of visible `.ww` special files is not broadened by this rule.
|
||||||
|
|
||||||
|
A resolved logical single file retains the established `__root` command-line
|
||||||
|
package/action/artifact identity. A resolved logical directory retains its
|
||||||
|
dotted package, import, graph, action, symbol, `.wwi`, initializer, artifact,
|
||||||
|
publication, and persistence identity. The ignored physical pathname/object
|
||||||
|
creates no membership, binding, edge, action, key, or alternate identity.
|
||||||
|
Build and run use only the logical provider's production/import/initializer
|
||||||
|
closure and runtime. Raw running test, its historical second-positional
|
||||||
|
test-name filter, `test -c`, and `test -S` use only the provider's test
|
||||||
|
package, descriptors, support closure, binary, and assembly.
|
||||||
|
|
||||||
|
When no provider exists, collision-present behavior is byte-for-byte the
|
||||||
|
existing collision-absent behavior. An ordinary single target retains its
|
||||||
|
direct build/run/test cannot-find result and creates no producer action. A
|
||||||
|
second positional retains the established package-coordinator route,
|
||||||
|
diagnostics, status, selection lifecycle, and cleanup; this source gate does
|
||||||
|
not reinterpret that positional form. Mutation invariance covers only absent
|
||||||
|
and stat-successful non-directory collision states. A transition to a
|
||||||
|
directory leaves this rule and follows ordinary directory routing, with no
|
||||||
|
new atomic-snapshot guarantee for concurrent kind changes.
|
||||||
|
|
||||||
|
Provider compilation failure preserves the prior public and semantic
|
||||||
|
generation. A retained running-test runtime failure occurs after the complete
|
||||||
|
logical build generation commits: it preserves prior retained public bytes by
|
||||||
|
skipping deferred installation, while that semantic generation remains
|
||||||
|
committed and reusable. Restoring prior source bytes requires a later
|
||||||
|
successful rebuild and commit, not runtime-failure rollback. Controlled-
|
||||||
|
failure cleanup otherwise remains unchanged. External signal
|
||||||
|
interruption after action start is unchanged, including the verified-open
|
||||||
|
fixed `.new` residue and later persistent-request poisoning. Multiple named
|
||||||
|
sources, remaining suffix-first run behavior, finite `.ww` FIFOs, test
|
||||||
|
process topology, and `-run` regular expressions are not completed here.
|
||||||
|
Build workdir format remains 18, test workdir format remains 19, and semantic
|
||||||
|
storage format remains 3.
|
||||||
- `import acme.codec;` loads the canonical package `acme.codec`. If that
|
- `import acme.codec;` loads the canonical package `acme.codec`. If that
|
||||||
package declares `package wire;`, the importing file sees its exported names
|
package declares `package wire;`, the importing file sees its exported names
|
||||||
as `wire.Name`; `codec.Name` is not an additional binding. An explicit alias
|
as `wire.Name`; `codec.Name` is not an additional binding. An explicit alias
|
||||||
|
|||||||
@@ -302,6 +302,53 @@ multiple named sources, finite FIFOs, and hidden regular sources are not
|
|||||||
claimed by this existing-directory slice. The general direct-driver `.new`
|
claimed by this existing-directory slice. The general direct-driver `.new`
|
||||||
interruption residue also remains open.
|
interruption residue also remains open.
|
||||||
|
|
||||||
|
The raw source front also applies one positive requested-spelling gate before
|
||||||
|
physical adoption. An existing non-directory operand whose exact requested
|
||||||
|
spelling does not end `.ww` is not a raw source and cannot hijack its ordinary
|
||||||
|
dotted provider. Build, run, raw test, the historical second-positional raw
|
||||||
|
test filter, `test -c`, and `test -S` therefore resolve and consume the same
|
||||||
|
logical file or directory they consume when the collision is absent. Logical
|
||||||
|
files keep the existing `__root` action/artifact family; logical directories
|
||||||
|
keep dotted package/import/action identity. The ignored object's bytes,
|
||||||
|
package, imports, tests, runtime status, mode, and timestamp supply no package
|
||||||
|
membership, edge, producer input, artifact, publication, or persistence key.
|
||||||
|
|
||||||
|
Requested suffix owns the gate through symlinks. Wrong-suffix links to regular
|
||||||
|
or special non-directories remain logical requests, while a link to a directory
|
||||||
|
retains stat-first direct-directory routing; a visible `.ww` link to a regular
|
||||||
|
source remains raw source. Each stage's existing visible `.ww` special-file
|
||||||
|
handling is outside this slice. Mutation/reuse invariance is limited to absent
|
||||||
|
or stat-successful non-directory collision states. A transition to a directory
|
||||||
|
uses the directory owner and receives no new concurrent-kind snapshot promise.
|
||||||
|
|
||||||
|
No-provider rows deliberately separate the ordinary single-target path from
|
||||||
|
the second-positional compatibility path. The first retains direct cannot-find
|
||||||
|
diagnostics, running-test `FAIL`, and producer/artifact absence. The second
|
||||||
|
retains the existing package-coordinator process, canonicalization or usage
|
||||||
|
diagnostic, status, selection state, and cleanup; the gate does not turn that
|
||||||
|
route into a direct raw-file error. Logical producer failure preserves prior
|
||||||
|
public and semantic bytes. A retained running-test runtime failure instead
|
||||||
|
keeps the complete newly built semantic generation committed and reusable but
|
||||||
|
skips deferred installation, preserving prior retained public bytes; restoring
|
||||||
|
the old source requires a later successful rebuild and commit. Normal and
|
||||||
|
controlled-failure cleanup is unchanged. External driver signals after action
|
||||||
|
start retain the open fixed
|
||||||
|
`.new` leakage and later-request poisoning behavior.
|
||||||
|
|
||||||
|
The focused `wrong_suffix_physical_files_do_not_hijack_dotted_requests`
|
||||||
|
package observer owns this boundary for both driver stages. It compares absent
|
||||||
|
controls with regular, symlinked-regular, and symlinked-special collisions;
|
||||||
|
checks build, run, raw/filter test, `-c`, and `-S` streams, statuses, runtime,
|
||||||
|
public bytes, complete comparable semantic artifacts, `__root` file identity,
|
||||||
|
and dotted directory identity; separates direct and coordinator no-provider
|
||||||
|
rows; exercises warm non-directory mutation, producer-failure rollback,
|
||||||
|
retained-runtime-failure public-byte preservation with committed semantic-
|
||||||
|
generation reuse and later successful restoration, request-local concurrent
|
||||||
|
builds, positive `.ww` and direct-directory controls, and normal residue
|
||||||
|
cleanup. It makes no finite-FIFO or signal-recovery claim.
|
||||||
|
The rule changes no package coordinator, test harness/process topology,
|
||||||
|
test-result caching, or build/test/semantic format (18/19/3).
|
||||||
|
|
||||||
List mode uses that same product process and initialization boundary but starts
|
List mode uses that same product process and initialization boundary but starts
|
||||||
no per-test child. The shared language harness emits only selected qualified
|
no per-test child. The shared language harness emits only selected qualified
|
||||||
test names, one per line in descriptor order. A valid filter selecting no tests
|
test names, one per line in descriptor order. A valid filter selecting no tests
|
||||||
|
|||||||
@@ -8660,13 +8660,17 @@ fn basenameoff(p: *u8, plen: u64) u64 = {
|
|||||||
return start;
|
return start;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
fn sourceoperandnamed(path: *u8) bool = {
|
||||||
|
return cstrendswithlit(path, ".ww");
|
||||||
|
};
|
||||||
|
|
||||||
// A named Go source still passes through matchFile's leading-dot/underscore
|
// A named Go source still passes through matchFile's leading-dot/underscore
|
||||||
// exclusion even when UseAllFiles bypasses platform suffixes and build tags.
|
// exclusion even when UseAllFiles bypasses platform suffixes and build tags.
|
||||||
// Inspect the public operand spelling so a hidden parent is not source identity
|
// Inspect the public operand spelling so a hidden parent is not source identity
|
||||||
// and a hidden symlink spelling cannot be resurrected by a non-directory
|
// and a hidden symlink spelling cannot be resurrected by a non-directory
|
||||||
// target's name or file kind.
|
// target's name or file kind.
|
||||||
fn sourceoperandignored(path: *u8) bool = {
|
fn sourceoperandignored(path: *u8) bool = {
|
||||||
if (!cstrendswithlit(path, ".ww")) { return false; };
|
if (!sourceoperandnamed(path)) { return false; };
|
||||||
let fi: os.filestat;
|
let fi: os.filestat;
|
||||||
match (os.stat(&fi, pathstr(path))) {
|
match (os.stat(&fi, pathstr(path))) {
|
||||||
case void => {
|
case void => {
|
||||||
@@ -8741,13 +8745,6 @@ fn buildsearchpath(selfdir: *u8, incs: *u8) *u8 = {
|
|||||||
fn resolvemodule(selfdir: *u8, name: *u8, incs: *u8, isdir: *i32) *u8 = {
|
fn resolvemodule(selfdir: *u8, name: *u8, incs: *u8, isdir: *i32) *u8 = {
|
||||||
let nlen: u64 = cstrlen(name);
|
let nlen: u64 = cstrlen(name);
|
||||||
|
|
||||||
if (cstrendswithlit(name, ".ww")) {
|
|
||||||
if (os.access(pathstr(name), 0i32) == 0) {
|
|
||||||
*isdir = 0;
|
|
||||||
return arenadupcstr(name, nlen);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
let fi: os.filestat;
|
let fi: os.filestat;
|
||||||
let sr: (void | os.oserror) = os.stat(&fi, pathstr(name));
|
let sr: (void | os.oserror) = os.stat(&fi, pathstr(name));
|
||||||
let found: bool = false;
|
let found: bool = false;
|
||||||
@@ -8760,10 +8757,16 @@ fn resolvemodule(selfdir: *u8, name: *u8, incs: *u8, isdir: *i32) *u8 = {
|
|||||||
};
|
};
|
||||||
case let e: os.oserror => void;
|
case let e: os.oserror => void;
|
||||||
};
|
};
|
||||||
if (found) {
|
if (foundisdir != 0) {
|
||||||
*isdir = foundisdir;
|
*isdir = foundisdir;
|
||||||
return arenadupcstr(name, nlen);
|
return arenadupcstr(name, nlen);
|
||||||
};
|
};
|
||||||
|
if (sourceoperandnamed(name)) {
|
||||||
|
if (os.access(pathstr(name), 0i32) == 0 || found) {
|
||||||
|
*isdir = 0;
|
||||||
|
return arenadupcstr(name, nlen);
|
||||||
|
};
|
||||||
|
};
|
||||||
if (reservedimportpath(name)) { return nil; };
|
if (reservedimportpath(name)) { return nil; };
|
||||||
|
|
||||||
let search: *u8 = buildsearchpath(selfdir, incs);
|
let search: *u8 = buildsearchpath(selfdir, incs);
|
||||||
@@ -9043,9 +9046,11 @@ fn dobuild(selfdir: *u8, argv: **u8, argc: i32, start: i32) i32 = {
|
|||||||
let requestedstat: os.filestat;
|
let requestedstat: os.filestat;
|
||||||
match (os.stat(&requestedstat, pathstr(src))) {
|
match (os.stat(&requestedstat, pathstr(src))) {
|
||||||
case void => {
|
case void => {
|
||||||
requestedliteral = true;
|
|
||||||
let typ: u32 = (requestedstat.mode: u32) & 61440u32;
|
let typ: u32 = (requestedstat.mode: u32) & 61440u32;
|
||||||
requestednondirectory = typ != os.mode.DIR: u32;
|
requestedliteral = typ == os.mode.DIR: u32
|
||||||
|
|| sourceoperandnamed(src);
|
||||||
|
requestednondirectory = requestedliteral
|
||||||
|
&& typ != os.mode.DIR: u32;
|
||||||
};
|
};
|
||||||
case let e: os.oserror => void;
|
case let e: os.oserror => void;
|
||||||
};
|
};
|
||||||
@@ -9071,7 +9076,7 @@ fn dobuild(selfdir: *u8, argv: **u8, argc: i32, start: i32) i32 = {
|
|||||||
let isdir: i32 = 0;
|
let isdir: i32 = 0;
|
||||||
let resolved: *u8 = nil;
|
let resolved: *u8 = nil;
|
||||||
if (requestedliteral && !requestednondirectory
|
if (requestedliteral && !requestednondirectory
|
||||||
&& cstrendswithlit(src, ".ww")) {
|
&& sourceoperandnamed(src)) {
|
||||||
isdir = 1;
|
isdir = 1;
|
||||||
resolved = src;
|
resolved = src;
|
||||||
} else {
|
} else {
|
||||||
@@ -9318,12 +9323,16 @@ fn dorun(selfdir: *u8, argv: **u8, argc: i32, start: i32) i32 = {
|
|||||||
let requestedliteral: bool = false;
|
let requestedliteral: bool = false;
|
||||||
let requestedstat: os.filestat;
|
let requestedstat: os.filestat;
|
||||||
match (os.stat(&requestedstat, pathstr(src))) {
|
match (os.stat(&requestedstat, pathstr(src))) {
|
||||||
case void => requestedliteral = true;
|
case void => {
|
||||||
|
let typ: u32 = (requestedstat.mode: u32) & 61440u32;
|
||||||
|
requestedliteral = typ == os.mode.DIR: u32
|
||||||
|
|| sourceoperandnamed(src);
|
||||||
|
};
|
||||||
case let e: os.oserror => void;
|
case let e: os.oserror => void;
|
||||||
};
|
};
|
||||||
if (requestedliteral
|
if (requestedliteral
|
||||||
&& ((requestedstat.mode: u32) & 61440u32) == os.mode.DIR: u32
|
&& ((requestedstat.mode: u32) & 61440u32) == os.mode.DIR: u32
|
||||||
&& cstrendswithlit(src, ".ww")) {
|
&& sourceoperandnamed(src)) {
|
||||||
if (cstrendswithlit(src, "_test.ww")) {
|
if (cstrendswithlit(src, "_test.ww")) {
|
||||||
cerrpath("ww: cannot run *_test.ww files (", src, ")\n");
|
cerrpath("ww: cannot run *_test.ww files (", src, ")\n");
|
||||||
} else {
|
} else {
|
||||||
@@ -9987,22 +9996,27 @@ fn dotest(selfdir: *u8, argv: **u8, argc: i32, start: i32) i32 = {
|
|||||||
let first: os.filestat;
|
let first: os.filestat;
|
||||||
let firstregular: bool = false;
|
let firstregular: bool = false;
|
||||||
let firstfound: bool = false;
|
let firstfound: bool = false;
|
||||||
|
let firstisdirphysical: bool = false;
|
||||||
match (os.stat(&first, pathstr(target))) {
|
match (os.stat(&first, pathstr(target))) {
|
||||||
case void => {
|
case void => {
|
||||||
firstfound = true;
|
firstfound = true;
|
||||||
|
firstisdirphysical = ((first.mode: u32) & 61440u32)
|
||||||
|
== os.mode.DIR: u32;
|
||||||
firstregular = (((first.mode: u32) & 61440u32)
|
firstregular = (((first.mode: u32) & 61440u32)
|
||||||
== (os.mode.REG: u32));
|
== (os.mode.REG: u32)) && sourceoperandnamed(target);
|
||||||
};
|
};
|
||||||
case let e: os.oserror => void;
|
case let e: os.oserror => void;
|
||||||
};
|
};
|
||||||
if (!firstregular) {
|
if (!firstregular) {
|
||||||
let firstresolved: *u8 = nil;
|
let firstresolved: *u8 = nil;
|
||||||
let firstisdir: i32 = 0;
|
let firstisdir: i32 = 0;
|
||||||
if (!firstfound) {
|
let firstlogical: bool = !firstfound
|
||||||
|
|| (!firstisdirphysical && !sourceoperandnamed(target));
|
||||||
|
if (firstlogical) {
|
||||||
firstresolved = resolvemodule(selfdir, target, incs.ptr,
|
firstresolved = resolvemodule(selfdir, target, incs.ptr,
|
||||||
&firstisdir);
|
&firstisdir);
|
||||||
};
|
};
|
||||||
if (firstfound || firstresolved == nil || firstisdir != 0) {
|
if (!firstlogical || firstresolved == nil || firstisdir != 0) {
|
||||||
let replacement: *u8 = nil;
|
let replacement: *u8 = nil;
|
||||||
let identity: *u8 = requestidentity;
|
let identity: *u8 = requestidentity;
|
||||||
if (firstisdir != 0) {
|
if (firstisdir != 0) {
|
||||||
@@ -10049,7 +10063,9 @@ fn dotest(selfdir: *u8, argv: **u8, argc: i32, start: i32) i32 = {
|
|||||||
case void => {
|
case void => {
|
||||||
let t: u32 = (fi.mode: u32) & 61440u32;
|
let t: u32 = (fi.mode: u32) & 61440u32;
|
||||||
if (t == os.mode.DIR: u32) { isdir = 1; found = true; }
|
if (t == os.mode.DIR: u32) { isdir = 1; found = true; }
|
||||||
else { if (t == os.mode.REG: u32) { found = true; }; };
|
else { if (t == os.mode.REG: u32 && sourceoperandnamed(target)) {
|
||||||
|
found = true;
|
||||||
|
}; };
|
||||||
};
|
};
|
||||||
case let e: os.oserror => void;
|
case let e: os.oserror => void;
|
||||||
};
|
};
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user