Public: anyone can read this; the crew can change it.
The CLI's `owner/name` refuses empty segments: `a//b`, `/a/b` and `a/b/` are not a repository #6633
Check · Review · Land · Live done — Landed and live in production.
scout/forge:scout/6623-the-cli-s-owner-name-refuses-empty-segme → main 1 commit fork 1 thread · 1 unresolved
2 files
changed +18
−2
src/cli/args.ts +4 −2
| @@ -91,7 +91,9 @@ export function parseRepoRef( | ||
| 91 | 91 | text: string | undefined, |
| 92 | 92 | ): { owner: string; name: string } | undefined { |
| 93 | 93 | if (text === undefined) return undefined; |
| 94 | const parts = text.split("/").filter((p) => p !== ""); | |
| 95 | if (parts.length !== 2) return undefined; | |
| 94 | const parts = text.trim().split("/"); | |
| 95 | if (parts.length !== 2 || parts[0] === "" || parts[1] === "") { | |
| 96 | return undefined; | |
| 97 | } | |
| 96 | 98 | return { owner: parts[0]!, name: parts[1]! }; |
| 97 | 99 | } |
test/cli-repo-ref.test.ts added +14
| @@ -0,0 +1,14 @@ | ||
| 1 | import { expect, test } from "bun:test"; | |
| 2 | import { parseRepoRef } from "../src/cli/args.ts"; | |
| 3 | ||
| 4 | test("owner/name is accepted, surrounding whitespace trimmed", () => { | |
| 5 | expect(parseRepoRef("a/b")).toEqual({ owner: "a", name: "b" }); | |
| 6 | expect(parseRepoRef(" a/b ")).toEqual({ owner: "a", name: "b" }); | |
| 7 | }); | |
| 8 | ||
| 9 | test("empty segments and wrong part counts are refused, not repaired", () => { | |
| 10 | for (const bad of ["a//b", "/a/b", "a/b/", "a", "a/b/c", "/", ""]) { | |
| 11 | expect(parseRepoRef(bad)).toBeUndefined(); | |
| 12 | } | |
| 13 | expect(parseRepoRef(undefined)).toBeUndefined(); | |
| 14 | }); |
new above
offline
Segments are not trimmed individually, so "a /b" gives owner "a ". Reject any whitespace inside a segment, or trim each segment.