diff --git a/deno.json b/deno.json index 5b0f989..e6d5329 100644 --- a/deno.json +++ b/deno.json @@ -26,7 +26,7 @@ }, "imports": { "is-what": "https://deno.land/x/is_what@v4.1.15/src/index.ts", - "deno/": "https://deno.land/std@0.196.0/", + "deno/": "https://deno.land/std@0.204.0/", "outdent": "https://deno.land/x/outdent@v0.8.0/mod.ts" } } diff --git a/src/deps.ts b/src/deps.ts index 2a732f0..08c54fa 100644 --- a/src/deps.ts +++ b/src/deps.ts @@ -8,16 +8,17 @@ import * as outdent from "https://deno.land/x/outdent@v0.8.0/mod.ts" export { outdent } // importing super specifically to reduce final npm bundle size -import * as crypto from "https://deno.land/std@0.196.0/crypto/mod.ts" -import { moveSync } from "https://deno.land/std@0.196.0/fs/move.ts" -import { readLines } from "https://deno.land/std@0.196.0/io/read_lines.ts" -import { writeAll } from "https://deno.land/std@0.196.0/streams/write_all.ts" -import { parse as parseYaml } from "https://deno.land/std@0.196.0/yaml/parse.ts" -import { SEP } from "https://deno.land/std@0.196.0/path/mod.ts" +import * as crypto from "https://deno.land/std@0.204.0/crypto/mod.ts" +import { moveSync } from "https://deno.land/std@0.204.0/fs/move.ts" +import { readLines } from "https://deno.land/std@0.204.0/io/read_lines.ts" +import { writeAll } from "https://deno.land/std@0.204.0/streams/write_all.ts" +import { parse as parseYaml } from "https://deno.land/std@0.204.0/yaml/parse.ts" +import { SEP } from "https://deno.land/std@0.204.0/path/mod.ts" +import { fromFileUrl } from "https://deno.land/std@0.204.0/path/from_file_url.ts" const streams = { writeAll } const io = { readLines } const fs = { moveSync } -const deno = { readLines, crypto, fs, io, streams, parseYaml, SEP } +const deno = { readLines, crypto, fs, io, streams, parseYaml, SEP, fromFileUrl } export { deno } diff --git a/src/hooks/useConfig.ts b/src/hooks/useConfig.ts index c551248..bc04698 100644 --- a/src/hooks/useConfig.ts +++ b/src/hooks/useConfig.ts @@ -1,4 +1,5 @@ import { flatmap } from "../utils/misc.ts" +import { deno } from "../deps.ts" import host from "../utils/host.ts" import Path from "../utils/Path.ts" @@ -64,8 +65,7 @@ export function ConfigDefault(env = Deno.env.toObject()): Config { function getv(): string | undefined { if (typeof Deno === 'undefined') { - const url = new URL(import.meta.url) - const path = new Path(url.pathname).parent().parent().parent().join("package.json") + const path = new Path(deno.fromFileUrl(import.meta.url)).parent().parent().parent().join("package.json") const blob = Deno.readFileSync(path.string) const txt = new TextDecoder().decode(blob) const { version } = JSON.parse(txt) diff --git a/src/hooks/useTestConfig.ts b/src/hooks/useTestConfig.ts index e627318..9d827f8 100644 --- a/src/hooks/useTestConfig.ts +++ b/src/hooks/useTestConfig.ts @@ -1,4 +1,5 @@ import useConfig, { ConfigDefault } from "./useConfig.ts" +import { fromFileUrl } from "deno/path/from_file_url.ts" import Path from "../utils/Path.ts" export function useBaseTestConfig(env?: Record) { @@ -31,11 +32,7 @@ export const srcroot = (() => { if (Path.cwd().parent().parent().join("fixtures").isDirectory()) { return Path.cwd().parent().parent() } else { - let path = new URL(import.meta.url).pathname - if (Deno.build.os == 'windows') { - path = path.slice(1) // /D:/foo/bar -> D:/foo/bar - } - return new Path(path).parent().parent().parent() + return new Path(fromFileUrl(import.meta.url)).parent().parent().parent() } })() diff --git a/src/utils/Path.test.ts b/src/utils/Path.test.ts index 62fcf1f..ac84569 100644 --- a/src/utils/Path.test.ts +++ b/src/utils/Path.test.ts @@ -240,6 +240,12 @@ Deno.test({ assertEquals(p.string, "Y:\\") assertEquals(p.parent().string, "Y:\\") assertEquals(p.parent().parent().parent().string, "Y:\\") + + const q = new Path("\\\\bar\\foo\\baz") + + assertEquals(q.string, "\\\\bar\\foo\\baz") + assertEquals(q.parent().string, "\\\\bar\\foo") + assertEquals(q.parent().parent().parent().string, "\\\\bar\\foo") // the first path after the hostname is actually a root } }) @@ -247,6 +253,9 @@ Deno.test("join roots", () => { if (Deno.build.os == "windows") { assertEquals(new Path("C:\\foo").join("D:\\bar").string, "D:\\bar") assertEquals(new Path("C:").join("D:\\bar\baz").string, "D:\\bar\baz") + + assertEquals(new Path("c:\\foo\bar").join("\\\\bar\\baz").string, "\\\\bar\\baz") + } else { assertEquals(new Path("/foo").join("/bar").string, "/bar") } diff --git a/src/utils/Path.ts b/src/utils/Path.ts index c06d85f..d1acd5e 100644 --- a/src/utils/Path.ts +++ b/src/utils/Path.ts @@ -59,10 +59,14 @@ export default class Path { if (!input.startsWith("/") && !input.startsWith("\\")) { throw new Error(`invalid absolute path: ${input}`) } - //TODO shouldn’t be C: necessarily - // should it be based on PWD or system default drive? - // NOTE also: maybe we shouldn't do this anyway? - input = `C:\\${input}` + if (!input.startsWith('\\\\')) { + // ^^ \\network\drive is valid path notation on windows + + //TODO shouldn’t be C: necessarily + // should it be based on PWD or system default drive? + // NOTE also: maybe we shouldn't do this anyway? + input = `C:\\${input}` + } } input = input.replace(/\//g, '\\') } else if (input[0] != '/') { @@ -72,10 +76,10 @@ export default class Path { this.string = normalize(input) function normalize(path: string): string { - const segments = path.split(SEP); - const result = []; + const segments = path.split(SEP) + const result = [] - const start = Deno.build.os == 'windows' ? (segments.shift() ?? 'C:') + '\\' : '/' + const start = Deno.build.os == 'windows' ? (segments.shift() || '\\') + '\\' : '/' for (const segment of segments) { if (segment === '..') { @@ -151,7 +155,7 @@ export default class Path { return this } function isAbsolute(part: string) { - if (Deno.build.os == 'windows' && part?.match(/^[a-zA-Z]:/)) { + if (Deno.build.os == 'windows' && (part?.match(/^[a-zA-Z]:/) || part?.startsWith("\\\\"))) { return true } else { return part.startsWith('/')