test(lint-once): follow a short file flag with its value attached
All checks were successful
check / check (push) Successful in 14s
All checks were successful
check / check (push) Successful in 14s
`docker build -fDockerfile.lint .` is a plain `-f` naming a literal file — the flag parser reads the attached value for any shorthand — but the resolver's `[=\s]+` required a separator, so the invocation fell through to the default `Dockerfile` edge. Mutating the `check` recipe to that spelling left the suite 52/52 green while `-f Dockerfile.lint` was caught. The header already promised this form was followed: it claimed the file named by `-f` is resolved wherever the flag sits, and disclosed only a bundled short cluster (`-qf <file>`) as unfollowed. Overclaiming is the defect, so the resolver is taught the form rather than the claim narrowed. The attached form is allowed only for the short flag, keeping `--force-rm` out of it; `--file` still requires `=` or whitespace. The `-qf` cluster limitation is untouched and still pinned.
This commit is contained in:
@@ -39,11 +39,12 @@
|
||||
// one pass over literals, so a value that itself names another variable, a
|
||||
// value built by a make function (`$(shell ...)`, `$(addprefix ...)`), and the
|
||||
// body of a `define`/`endef` block are not expanded and not followed. A
|
||||
// `docker build` resolves to the file named by `-f`, `-f=`, `--file` or
|
||||
// `--file=`, wherever in the invocation that flag sits, and to `Dockerfile`
|
||||
// when it names none; a Dockerfile chosen some other way — a bundled short
|
||||
// flag cluster (`-qf <file>`), a value this walk cannot expand to a literal —
|
||||
// resolves to the default rather than to the real file. Within those edges, a
|
||||
// `docker build` resolves to the file named by `-f`, `-f=`, `-f<file>` with
|
||||
// the value attached to the flag, `--file` or `--file=`, wherever in the
|
||||
// invocation that flag sits, and to `Dockerfile` when it names none; a
|
||||
// Dockerfile chosen some other way — a bundled short flag cluster
|
||||
// (`-qf <file>`), a value this walk cannot expand to a literal — resolves to
|
||||
// the default rather than to the real file. Within those edges, a
|
||||
// prettier call is caught wherever it is added.
|
||||
//
|
||||
// Two entrypoints are walked, because they cover different graphs: `make check`
|
||||
@@ -437,16 +438,19 @@ const edgesOf = (line: string): string[] => {
|
||||
// it the count would miss the one invocation that is supposed to survive.
|
||||
//
|
||||
// Every spelling of the file flag is read, not just `-f <file>`. Docker
|
||||
// accepts `--file <file>`, `--file=<file>` and `-f=<file>` for the same
|
||||
// thing, and matching `-f ` alone resolved all of them to the default
|
||||
// accepts `--file <file>`, `--file=<file>`, `-f=<file>` and the value
|
||||
// attached to the short flag as one token (`-f<file>`) for the same thing,
|
||||
// and matching `-f ` alone resolved all of them to the default
|
||||
// `Dockerfile` edge — so `docker build --file=Dockerfile.lint .` in a
|
||||
// recipe was followed into the wrong file, counted nothing, and reported
|
||||
// green. The flag is searched for anywhere in the invocation, as `-f`
|
||||
// already was, because a real build line wraps it in `--build-arg` and
|
||||
// other flags. A leading `\s` is required so that a longer flag ending in
|
||||
// the same letters cannot supply the match.
|
||||
// the same letters cannot supply the match, and the attached form is
|
||||
// allowed only for the short flag, so that `--force-rm` — a long flag that
|
||||
// merely starts with the same letters — still does not read as one.
|
||||
if (/\bdocker\s+build\b/.test(line)) {
|
||||
const file = /\s(?:-f|--file)[=\s]+(\S+)/.exec(line);
|
||||
const file = /\s(?:--file[=\s]+|-f=?\s*)(\S+)/.exec(line);
|
||||
edges.push(`docker:${file === null ? "Dockerfile" : file[1]}`);
|
||||
}
|
||||
|
||||
@@ -1021,6 +1025,21 @@ describe("the resolver reads what the shell would run", () => {
|
||||
]);
|
||||
});
|
||||
|
||||
// The value may be attached to the short flag with no separator at all:
|
||||
// `-fDockerfile.lint` is a single token, and the flag parser reads it as
|
||||
// `-f` naming that file, exactly as `-f Dockerfile.lint` does. Requiring a
|
||||
// separator sent it to the default `Dockerfile` edge instead — the same
|
||||
// false green as the long spellings above, and one the header promised was
|
||||
// followed: a second prettier pass added as `docker build
|
||||
// -fDockerfile.lint .` was resolved into the wrong file, counted nothing,
|
||||
// and left the build green. `-fFILE` is an ordinary thing for a human to
|
||||
// write, so it is followed rather than merely documented as unfollowed.
|
||||
it("follows a short file flag with its value attached", () => {
|
||||
expect(edgesOf("docker build -fDockerfile.lint .")).toEqual([
|
||||
"docker:Dockerfile.lint",
|
||||
]);
|
||||
});
|
||||
|
||||
// The flag is found anywhere in the invocation rather than at a fixed
|
||||
// position, matching how `-f` was already read, since a real build line
|
||||
// carries `--build-arg` and friends around it.
|
||||
|
||||
Reference in New Issue
Block a user