Public: anyone can read this; the crew can change it.
Origin browsing's file-or-directory sentences live in one module, read by every provider #5606
Check · Review · Land · Live done — Landed and live in production.
mason/forge:mason/5586-origin-browsing-s-file-or-directory-sent → main 1 commit fork
4 files
changed +45
−4
src/origins/providers/forgejo.ts +3 −2
| @@ -74,6 +74,7 @@ import { | ||
| 74 | 74 | toCommit, |
| 75 | 75 | toTreeEntry, |
| 76 | 76 | } from "./http.ts"; |
| 77 | import { PATH_IS_DIRECTORY, PATH_IS_FILE } from "../words.ts"; | |
| 77 | 78 | |
| 78 | 79 | /** What we ask for before the instance tells us its own ceiling. */ |
| 79 | 80 | const DEFAULT_LIMIT = 50; |
| @@ -250,7 +251,7 @@ export class ForgejoProvider implements Provider { | ||
| 250 | 251 | }); |
| 251 | 252 | if (!result.ok) return result; |
| 252 | 253 | if (!Array.isArray(result.value.data)) |
| 253 | return fail("not_found", "that path is a file, not a directory"); | |
| 254 | return fail("not_found", PATH_IS_FILE); | |
| 254 | 255 | return succeed( |
| 255 | 256 | sortEntries(result.value.data.map((r) => toTreeEntry(r, path))), |
| 256 | 257 | ); |
| @@ -271,7 +272,7 @@ export class ForgejoProvider implements Provider { | ||
| 271 | 272 | }); |
| 272 | 273 | if (!result.ok) return result; |
| 273 | 274 | if (Array.isArray(result.value.data)) |
| 274 | return fail("not_found", "that path is a directory, not a file"); | |
| 275 | return fail("not_found", PATH_IS_DIRECTORY); | |
| 275 | 276 | return succeed(toBlob(result.value.data)); |
| 276 | 277 | } |
| 277 | 278 |
src/origins/providers/github.ts +3 −2
| @@ -62,6 +62,7 @@ import { | ||
| 62 | 62 | toCommit, |
| 63 | 63 | toTreeEntry, |
| 64 | 64 | } from "./http.ts"; |
| 65 | import { PATH_IS_DIRECTORY, PATH_IS_FILE } from "../words.ts"; | |
| 65 | 66 | |
| 66 | 67 | const PER_PAGE = 100; |
| 67 | 68 | /** A page walk we drive ourselves (labels, reviews) stops here regardless. */ |
| @@ -194,7 +195,7 @@ export class GitHubProvider implements Provider { | ||
| 194 | 195 | }); |
| 195 | 196 | if (!result.ok) return result; |
| 196 | 197 | if (!Array.isArray(result.value.data)) |
| 197 | return fail("not_found", "that path is a file, not a directory"); | |
| 198 | return fail("not_found", PATH_IS_FILE); | |
| 198 | 199 | return succeed( |
| 199 | 200 | sortEntries(result.value.data.map((r) => toTreeEntry(r, path))), |
| 200 | 201 | ); |
| @@ -215,7 +216,7 @@ export class GitHubProvider implements Provider { | ||
| 215 | 216 | }); |
| 216 | 217 | if (!result.ok) return result; |
| 217 | 218 | if (Array.isArray(result.value.data)) |
| 218 | return fail("not_found", "that path is a directory, not a file"); | |
| 219 | return fail("not_found", PATH_IS_DIRECTORY); | |
| 219 | 220 | return succeed(toBlob(result.value.data)); |
| 220 | 221 | } |
| 221 | 222 |
src/origins/words.ts added +10
| @@ -0,0 +1,10 @@ | ||
| 1 | /** | |
| 2 | * The sentences origin browsing answers with when a path names the wrong | |
| 3 | * kind of thing, said from one place so every provider reads the same. | |
| 4 | */ | |
| 5 | ||
| 6 | /** A directory listing was asked of a path that is a file. */ | |
| 7 | export const PATH_IS_FILE = "that path is a file, not a directory"; | |
| 8 | ||
| 9 | /** A file was asked of a path that is a directory. */ | |
| 10 | export const PATH_IS_DIRECTORY = "that path is a directory, not a file"; |
test/origin-words.test.ts added +29
| @@ -0,0 +1,29 @@ | ||
| 1 | /** | |
| 2 | * Origin browsing's file-or-directory sentences are said from one module | |
| 3 | * (#5586); a copy typed back into a provider fails here. | |
| 4 | */ | |
| 5 | ||
| 6 | import { expect, test } from "bun:test"; | |
| 7 | import { readFileSync } from "node:fs"; | |
| 8 | import * as words from "../src/origins/words.ts"; | |
| 9 | ||
| 10 | const PROVIDERS = [ | |
| 11 | "src/origins/providers/forgejo.ts", | |
| 12 | "src/origins/providers/github.ts", | |
| 13 | ]; | |
| 14 | ||
| 15 | const sentences = Object.entries(words) as [string, string][]; | |
| 16 | ||
| 17 | test("each sentence is non-empty", () => { | |
| 18 | expect(sentences.length).toBe(2); | |
| 19 | for (const [, s] of sentences) expect(s.trim().length).toBeGreaterThan(0); | |
| 20 | }); | |
| 21 | ||
| 22 | test("no provider types a sentence out itself", () => { | |
| 23 | for (const file of PROVIDERS) { | |
| 24 | const source = readFileSync(new URL(`../${file}`, import.meta.url), "utf8"); | |
| 25 | for (const [name, s] of sentences) { | |
| 26 | expect({ file, name, typed: source.includes(s) }).toEqual({ file, name, typed: false }); | |
| 27 | } | |
| 28 | } | |
| 29 | }); |
new above
offline