mirror of
https://github.com/denoland/deno.git
synced 2024-12-22 23:34:47 -05:00
std: Move fs/path to the top-level (#3100)
This commit is contained in:
parent
99d8ac70db
commit
f51dcc12d7
57 changed files with 323 additions and 305 deletions
|
@ -11,8 +11,8 @@
|
|||
import { test, runIfMain } from "../testing/mod.ts";
|
||||
import { assertEquals } from "../testing/asserts.ts";
|
||||
|
||||
import { resolve } from "../path/mod.ts";
|
||||
import { Tar, Untar } from "./tar.ts";
|
||||
import { resolve } from "../fs/path/mod.ts";
|
||||
|
||||
const filePath = resolve("archive", "testdata", "example.txt");
|
||||
|
||||
|
|
|
@ -3,8 +3,8 @@ import { runIfMain, test } from "../testing/mod.ts";
|
|||
import { assertEquals } from "../testing/asserts.ts";
|
||||
import { existsSync } from "../fs/exists.ts";
|
||||
import { readFileStrSync } from "../fs/read_file_str.ts";
|
||||
import * as path from "../path/mod.ts";
|
||||
import { parse, stringify } from "./toml.ts";
|
||||
import * as path from "../fs/path/mod.ts";
|
||||
|
||||
const testFilesDir = path.resolve("encoding", "testdata");
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
|
||||
import * as path from "./path/mod.ts";
|
||||
import * as path from "../path/mod.ts";
|
||||
import { ensureDir, ensureDirSync } from "./ensure_dir.ts";
|
||||
import { isSubdir, getFileInfoType } from "./utils.ts";
|
||||
|
||||
|
|
|
@ -6,9 +6,9 @@ import {
|
|||
assertThrowsAsync,
|
||||
assert
|
||||
} from "../testing/asserts.ts";
|
||||
import * as path from "../path/mod.ts";
|
||||
import { copy, copySync } from "./copy.ts";
|
||||
import { exists, existsSync } from "./exists.ts";
|
||||
import * as path from "./path/mod.ts";
|
||||
import { ensureDir, ensureDirSync } from "./ensure_dir.ts";
|
||||
import { ensureFile, ensureFileSync } from "./ensure_file.ts";
|
||||
import { ensureSymlink, ensureSymlinkSync } from "./ensure_symlink.ts";
|
||||
|
|
|
@ -5,8 +5,8 @@ import {
|
|||
assertThrows,
|
||||
assertThrowsAsync
|
||||
} from "../testing/asserts.ts";
|
||||
import * as path from "../path/mod.ts";
|
||||
import { emptyDir, emptyDirSync } from "./empty_dir.ts";
|
||||
import * as path from "./path/mod.ts";
|
||||
|
||||
const testdataDir = path.resolve("fs", "testdata");
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
|
||||
import { test } from "../testing/mod.ts";
|
||||
import { assertThrows, assertThrowsAsync } from "../testing/asserts.ts";
|
||||
import * as path from "../path/mod.ts";
|
||||
import { ensureDir, ensureDirSync } from "./ensure_dir.ts";
|
||||
import * as path from "./path/mod.ts";
|
||||
import { ensureFile, ensureFileSync } from "./ensure_file.ts";
|
||||
|
||||
const testdataDir = path.resolve("fs", "testdata");
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
|
||||
import * as path from "./path/mod.ts";
|
||||
import * as path from "../path/mod.ts";
|
||||
import { ensureDir, ensureDirSync } from "./ensure_dir.ts";
|
||||
import { getFileInfoType } from "./utils.ts";
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
|
||||
import { test } from "../testing/mod.ts";
|
||||
import { assertThrows, assertThrowsAsync } from "../testing/asserts.ts";
|
||||
import * as path from "../path/mod.ts";
|
||||
import { ensureFile, ensureFileSync } from "./ensure_file.ts";
|
||||
import * as path from "./path/mod.ts";
|
||||
|
||||
const testdataDir = path.resolve("fs", "testdata");
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
|
||||
import * as path from "./path/mod.ts";
|
||||
import * as path from "../path/mod.ts";
|
||||
import { ensureDir, ensureDirSync } from "./ensure_dir.ts";
|
||||
import { exists, existsSync } from "./exists.ts";
|
||||
import { getFileInfoType } from "./utils.ts";
|
||||
|
|
|
@ -6,8 +6,8 @@ import {
|
|||
assertThrows,
|
||||
assertThrowsAsync
|
||||
} from "../testing/asserts.ts";
|
||||
import * as path from "../path/mod.ts";
|
||||
import { ensureLink, ensureLinkSync } from "./ensure_link.ts";
|
||||
import * as path from "./path/mod.ts";
|
||||
|
||||
const testdataDir = path.resolve("fs", "testdata");
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
|
||||
import * as path from "./path/mod.ts";
|
||||
import * as path from "../path/mod.ts";
|
||||
import { ensureDir, ensureDirSync } from "./ensure_dir.ts";
|
||||
import { exists, existsSync } from "./exists.ts";
|
||||
import { getFileInfoType } from "./utils.ts";
|
||||
|
|
|
@ -6,8 +6,8 @@ import {
|
|||
assertThrows,
|
||||
assertThrowsAsync
|
||||
} from "../testing/asserts.ts";
|
||||
import * as path from "../path/mod.ts";
|
||||
import { ensureSymlink, ensureSymlinkSync } from "./ensure_symlink.ts";
|
||||
import * as path from "./path/mod.ts";
|
||||
|
||||
const testdataDir = path.resolve("fs", "testdata");
|
||||
const isWindows = Deno.build.os === "win";
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
|
||||
import { test } from "../testing/mod.ts";
|
||||
import { assertEquals } from "../testing/asserts.ts";
|
||||
import * as path from "../path/mod.ts";
|
||||
import { exists, existsSync } from "./exists.ts";
|
||||
import * as path from "./path/mod.ts";
|
||||
|
||||
const testdataDir = path.resolve("fs", "testdata");
|
||||
|
||||
|
|
|
@ -1,127 +1,17 @@
|
|||
import { globrex } from "./globrex.ts";
|
||||
import { SEP, SEP_PATTERN, isWindows } from "./path/constants.ts";
|
||||
import { isAbsolute, join, normalize } from "./path/mod.ts";
|
||||
import {
|
||||
GlobOptions,
|
||||
SEP_PATTERN,
|
||||
globToRegExp,
|
||||
isAbsolute,
|
||||
isGlob,
|
||||
isWindows,
|
||||
joinGlobs,
|
||||
normalize
|
||||
} from "../path/mod.ts";
|
||||
import { WalkInfo, walk, walkSync } from "./walk.ts";
|
||||
const { DenoError, ErrorKind, cwd, stat, statSync } = Deno;
|
||||
const { cwd, stat, statSync } = Deno;
|
||||
type FileInfo = Deno.FileInfo;
|
||||
|
||||
export interface GlobOptions {
|
||||
extended?: boolean;
|
||||
globstar?: boolean;
|
||||
}
|
||||
|
||||
export interface GlobToRegExpOptions extends GlobOptions {
|
||||
flags?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a regex based on glob pattern and options
|
||||
* This was meant to be using the the `fs.walk` function
|
||||
* but can be used anywhere else.
|
||||
* Examples:
|
||||
*
|
||||
* Looking for all the `ts` files:
|
||||
* walkSync(".", {
|
||||
* match: [globToRegExp("*.ts")]
|
||||
* })
|
||||
*
|
||||
* Looking for all the `.json` files in any subfolder:
|
||||
* walkSync(".", {
|
||||
* match: [globToRegExp(join("a", "**", "*.json"),{
|
||||
* flags: "g",
|
||||
* extended: true,
|
||||
* globstar: true
|
||||
* })]
|
||||
* })
|
||||
*
|
||||
* @param glob - Glob pattern to be used
|
||||
* @param options - Specific options for the glob pattern
|
||||
* @returns A RegExp for the glob pattern
|
||||
*/
|
||||
export function globToRegExp(
|
||||
glob: string,
|
||||
options: GlobToRegExpOptions = {}
|
||||
): RegExp {
|
||||
const result = globrex(glob, { ...options, strict: false, filepath: true });
|
||||
return result.path!.regex;
|
||||
}
|
||||
|
||||
/** Test whether the given string is a glob */
|
||||
export function isGlob(str: string): boolean {
|
||||
const chars: Record<string, string> = { "{": "}", "(": ")", "[": "]" };
|
||||
/* eslint-disable-next-line max-len */
|
||||
const regex = /\\(.)|(^!|\*|[\].+)]\?|\[[^\\\]]+\]|\{[^\\}]+\}|\(\?[:!=][^\\)]+\)|\([^|]+\|[^\\)]+\))/;
|
||||
|
||||
if (str === "") {
|
||||
return false;
|
||||
}
|
||||
|
||||
let match: RegExpExecArray | null;
|
||||
|
||||
while ((match = regex.exec(str))) {
|
||||
if (match[2]) return true;
|
||||
let idx = match.index + match[0].length;
|
||||
|
||||
// if an open bracket/brace/paren is escaped,
|
||||
// set the index to the next closing character
|
||||
const open = match[1];
|
||||
const close = open ? chars[open] : null;
|
||||
if (open && close) {
|
||||
const n = str.indexOf(close, idx);
|
||||
if (n !== -1) {
|
||||
idx = n + 1;
|
||||
}
|
||||
}
|
||||
|
||||
str = str.slice(idx);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Like normalize(), but doesn't collapse "**\/.." when `globstar` is true. */
|
||||
export function normalizeGlob(
|
||||
glob: string,
|
||||
{ globstar = false }: GlobOptions = {}
|
||||
): string {
|
||||
if (!!glob.match(/\0/g)) {
|
||||
throw new DenoError(
|
||||
ErrorKind.InvalidPath,
|
||||
`Glob contains invalid characters: "${glob}"`
|
||||
);
|
||||
}
|
||||
if (!globstar) {
|
||||
return normalize(glob);
|
||||
}
|
||||
const s = SEP_PATTERN.source;
|
||||
const badParentPattern = new RegExp(
|
||||
`(?<=(${s}|^)\\*\\*${s})\\.\\.(?=${s}|$)`,
|
||||
"g"
|
||||
);
|
||||
return normalize(glob.replace(badParentPattern, "\0")).replace(/\0/g, "..");
|
||||
}
|
||||
|
||||
/** Like join(), but doesn't collapse "**\/.." when `globstar` is true. */
|
||||
export function joinGlobs(
|
||||
globs: string[],
|
||||
{ extended = false, globstar = false }: GlobOptions = {}
|
||||
): string {
|
||||
if (!globstar || globs.length == 0) {
|
||||
return join(...globs);
|
||||
}
|
||||
if (globs.length === 0) return ".";
|
||||
let joined: string | undefined;
|
||||
for (const glob of globs) {
|
||||
const path = glob;
|
||||
if (path.length > 0) {
|
||||
if (!joined) joined = path;
|
||||
else joined += `${SEP}${path}`;
|
||||
}
|
||||
}
|
||||
if (!joined) return ".";
|
||||
return normalizeGlob(joined, { extended, globstar });
|
||||
}
|
||||
|
||||
export interface ExpandGlobOptions extends GlobOptions {
|
||||
root?: string;
|
||||
exclude?: string[];
|
120
std/fs/expand_glob_test.ts
Normal file
120
std/fs/expand_glob_test.ts
Normal file
|
@ -0,0 +1,120 @@
|
|||
const { cwd } = Deno;
|
||||
import { test, runIfMain } from "../testing/mod.ts";
|
||||
import { assert, assertEquals } from "../testing/asserts.ts";
|
||||
import {
|
||||
isWindows,
|
||||
join,
|
||||
joinGlobs,
|
||||
normalize,
|
||||
relative
|
||||
} from "../path/mod.ts";
|
||||
import {
|
||||
ExpandGlobOptions,
|
||||
expandGlob,
|
||||
expandGlobSync
|
||||
} from "./expand_glob.ts";
|
||||
|
||||
async function expandGlobArray(
|
||||
globString: string,
|
||||
options: ExpandGlobOptions
|
||||
): Promise<string[]> {
|
||||
const paths: string[] = [];
|
||||
for await (const { filename } of expandGlob(globString, options)) {
|
||||
paths.push(filename);
|
||||
}
|
||||
paths.sort();
|
||||
const pathsSync = [...expandGlobSync(globString, options)].map(
|
||||
({ filename }): string => filename
|
||||
);
|
||||
pathsSync.sort();
|
||||
assertEquals(paths, pathsSync);
|
||||
const root = normalize(options.root || cwd());
|
||||
for (const path of paths) {
|
||||
assert(path.startsWith(root));
|
||||
}
|
||||
const relativePaths = paths.map(
|
||||
(path: string): string => relative(root, path) || "."
|
||||
);
|
||||
relativePaths.sort();
|
||||
return relativePaths;
|
||||
}
|
||||
|
||||
function urlToFilePath(url: URL): string {
|
||||
// Since `new URL('file:///C:/a').pathname` is `/C:/a`, remove leading slash.
|
||||
return url.pathname.slice(url.protocol == "file:" && isWindows ? 1 : 0);
|
||||
}
|
||||
|
||||
const EG_OPTIONS: ExpandGlobOptions = {
|
||||
root: urlToFilePath(new URL(join("testdata", "glob"), import.meta.url)),
|
||||
includeDirs: true,
|
||||
extended: false,
|
||||
globstar: false
|
||||
};
|
||||
|
||||
test(async function expandGlobWildcard(): Promise<void> {
|
||||
const options = EG_OPTIONS;
|
||||
assertEquals(await expandGlobArray("*", options), [
|
||||
"abc",
|
||||
"abcdef",
|
||||
"abcdefghi",
|
||||
"subdir"
|
||||
]);
|
||||
});
|
||||
|
||||
test(async function expandGlobTrailingSeparator(): Promise<void> {
|
||||
const options = EG_OPTIONS;
|
||||
assertEquals(await expandGlobArray("*/", options), ["subdir"]);
|
||||
});
|
||||
|
||||
test(async function expandGlobParent(): Promise<void> {
|
||||
const options = EG_OPTIONS;
|
||||
assertEquals(await expandGlobArray("subdir/../*", options), [
|
||||
"abc",
|
||||
"abcdef",
|
||||
"abcdefghi",
|
||||
"subdir"
|
||||
]);
|
||||
});
|
||||
|
||||
test(async function expandGlobExt(): Promise<void> {
|
||||
const options = { ...EG_OPTIONS, extended: true };
|
||||
assertEquals(await expandGlobArray("abc?(def|ghi)", options), [
|
||||
"abc",
|
||||
"abcdef"
|
||||
]);
|
||||
assertEquals(await expandGlobArray("abc*(def|ghi)", options), [
|
||||
"abc",
|
||||
"abcdef",
|
||||
"abcdefghi"
|
||||
]);
|
||||
assertEquals(await expandGlobArray("abc+(def|ghi)", options), [
|
||||
"abcdef",
|
||||
"abcdefghi"
|
||||
]);
|
||||
assertEquals(await expandGlobArray("abc@(def|ghi)", options), ["abcdef"]);
|
||||
assertEquals(await expandGlobArray("abc{def,ghi}", options), ["abcdef"]);
|
||||
assertEquals(await expandGlobArray("abc!(def|ghi)", options), ["abc"]);
|
||||
});
|
||||
|
||||
test(async function expandGlobGlobstar(): Promise<void> {
|
||||
const options = { ...EG_OPTIONS, globstar: true };
|
||||
assertEquals(
|
||||
await expandGlobArray(joinGlobs(["**", "abc"], options), options),
|
||||
["abc", join("subdir", "abc")]
|
||||
);
|
||||
});
|
||||
|
||||
test(async function expandGlobGlobstarParent(): Promise<void> {
|
||||
const options = { ...EG_OPTIONS, globstar: true };
|
||||
assertEquals(
|
||||
await expandGlobArray(joinGlobs(["subdir", "**", ".."], options), options),
|
||||
["."]
|
||||
);
|
||||
});
|
||||
|
||||
test(async function expandGlobIncludeDirs(): Promise<void> {
|
||||
const options = { ...EG_OPTIONS, includeDirs: false };
|
||||
assertEquals(await expandGlobArray("subdir", options), []);
|
||||
});
|
||||
|
||||
runIfMain(import.meta);
|
|
@ -5,8 +5,7 @@ export * from "./ensure_file.ts";
|
|||
export * from "./ensure_link.ts";
|
||||
export * from "./ensure_symlink.ts";
|
||||
export * from "./exists.ts";
|
||||
export * from "./glob.ts";
|
||||
export * from "./globrex.ts";
|
||||
export * from "./expand_glob.ts";
|
||||
export * from "./move.ts";
|
||||
export * from "./copy.ts";
|
||||
export * from "./read_file_str.ts";
|
||||
|
|
|
@ -5,11 +5,11 @@ import {
|
|||
assertThrows,
|
||||
assertThrowsAsync
|
||||
} from "../testing/asserts.ts";
|
||||
import * as path from "../path/mod.ts";
|
||||
import { move, moveSync } from "./move.ts";
|
||||
import { ensureFile, ensureFileSync } from "./ensure_file.ts";
|
||||
import { ensureDir, ensureDirSync } from "./ensure_dir.ts";
|
||||
import { exists, existsSync } from "./exists.ts";
|
||||
import * as path from "./path/mod.ts";
|
||||
|
||||
const testdataDir = path.resolve("fs", "testdata");
|
||||
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
|
||||
export * from "./path/mod.ts";
|
||||
export * from "./path/interface.ts";
|
|
@ -1,7 +0,0 @@
|
|||
# Deno Path Manipulation Libraries
|
||||
|
||||
Usage:
|
||||
|
||||
```ts
|
||||
import * as path from "https://deno.land/std/fs/path.ts";
|
||||
```
|
|
@ -1,7 +1,7 @@
|
|||
import { test } from "../testing/mod.ts";
|
||||
import { assert } from "../testing/asserts.ts";
|
||||
import * as path from "../path/mod.ts";
|
||||
import { readFileStrSync, readFileStr } from "./read_file_str.ts";
|
||||
import * as path from "./path/mod.ts";
|
||||
|
||||
const testdataDir = path.resolve("fs", "testdata");
|
||||
|
||||
|
|
|
@ -5,8 +5,8 @@ import {
|
|||
assertThrowsAsync,
|
||||
assertThrows
|
||||
} from "../testing/asserts.ts";
|
||||
import * as path from "../path/mod.ts";
|
||||
import { readJson, readJsonSync } from "./read_json.ts";
|
||||
import * as path from "./path/mod.ts";
|
||||
|
||||
const testdataDir = path.resolve("fs", "testdata");
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import * as path from "./path/mod.ts";
|
||||
import * as path from "../path/mod.ts";
|
||||
|
||||
/**
|
||||
* Test whether or not `dest` is a sub-directory of `src`
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
|
||||
import { test } from "../testing/mod.ts";
|
||||
import { assertEquals } from "../testing/asserts.ts";
|
||||
import * as path from "../path/mod.ts";
|
||||
import { isSubdir, getFileInfoType, PathType } from "./utils.ts";
|
||||
import * as path from "./path/mod.ts";
|
||||
import { ensureFileSync } from "./ensure_file.ts";
|
||||
import { ensureDirSync } from "./ensure_dir.ts";
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
// https://golang.org/pkg/path/filepath/#Walk
|
||||
// Copyright 2009 The Go Authors. All rights reserved. BSD license.
|
||||
import { unimplemented } from "../testing/asserts.ts";
|
||||
import { join } from "./path/mod.ts";
|
||||
import { join } from "../path/mod.ts";
|
||||
const { readDir, readDirSync, stat, statSync } = Deno;
|
||||
type FileInfo = Deno.FileInfo;
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { test } from "../testing/mod.ts";
|
||||
import { assertEquals } from "../testing/asserts.ts";
|
||||
import * as path from "../path/mod.ts";
|
||||
import { writeFileStr, writeFileStrSync } from "./write_file_str.ts";
|
||||
import * as path from "./path/mod.ts";
|
||||
|
||||
const testdataDir = path.resolve("fs", "testdata");
|
||||
|
||||
|
|
|
@ -5,8 +5,8 @@ import {
|
|||
assertThrowsAsync,
|
||||
assertThrows
|
||||
} from "../testing/asserts.ts";
|
||||
import * as path from "../path/mod.ts";
|
||||
import { writeJson, writeJsonSync } from "./write_json.ts";
|
||||
import * as path from "./path/mod.ts";
|
||||
|
||||
const testdataDir = path.resolve("fs", "testdata");
|
||||
|
||||
|
|
|
@ -7,14 +7,14 @@
|
|||
// https://github.com/indexzero/http-server/blob/master/test/http-server-test.js
|
||||
|
||||
const { ErrorKind, cwd, args, stat, readDir, open } = Deno;
|
||||
import { contentType } from "../media_types/mod.ts";
|
||||
import { extname, posix } from "../path/mod.ts";
|
||||
import {
|
||||
listenAndServe,
|
||||
ServerRequest,
|
||||
setContentLength,
|
||||
Response
|
||||
} from "./server.ts";
|
||||
import { extname, posix } from "../fs/path.ts";
|
||||
import { contentType } from "../media_types/mod.ts";
|
||||
|
||||
const dirViewerTemplate = `
|
||||
<!DOCTYPE html>
|
||||
|
|
|
@ -2,9 +2,9 @@
|
|||
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
|
||||
const { env, stdin, args, exit, writeFile, chmod, run } = Deno;
|
||||
import { parse } from "../flags/mod.ts";
|
||||
import * as path from "../fs/path.ts";
|
||||
import { exists } from "../fs/exists.ts";
|
||||
import { ensureDir } from "../fs/ensure_dir.ts";
|
||||
import * as path from "../path/mod.ts";
|
||||
|
||||
const encoder = new TextEncoder();
|
||||
const decoder = new TextDecoder("utf-8");
|
||||
|
|
|
@ -2,8 +2,9 @@
|
|||
const { Buffer, mkdir, open } = Deno;
|
||||
type File = Deno.File;
|
||||
type Reader = Deno.Reader;
|
||||
import * as path from "../path/mod.ts";
|
||||
import { encode } from "../strings/mod.ts";
|
||||
import * as path from "../fs/path.ts";
|
||||
|
||||
// `off` is the offset into `dst` where it will at which to begin writing values
|
||||
// from `src`.
|
||||
// Returns the number of bytes copied.
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
const { remove } = Deno;
|
||||
import { test } from "../testing/mod.ts";
|
||||
import { assert, assertEquals } from "../testing/asserts.ts";
|
||||
import * as path from "../path/mod.ts";
|
||||
import { copyBytes, tempFile } from "./util.ts";
|
||||
import * as path from "../fs/path.ts";
|
||||
|
||||
test(function testCopyBytes(): void {
|
||||
const dst = new Uint8Array(4);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
|
||||
|
||||
export { extname } from "../fs/path.ts";
|
||||
export { extname } from "../path/mod.ts";
|
||||
|
||||
interface DB {
|
||||
[mediaType: string]: {
|
||||
|
|
|
@ -5,11 +5,11 @@ const { min, max } = Math;
|
|||
type Closer = Deno.Closer;
|
||||
type Reader = Deno.Reader;
|
||||
type Writer = Deno.Writer;
|
||||
import { FormFile } from "../multipart/formfile.ts";
|
||||
import { equal, findIndex, findLastIndex, hasPrefix } from "../bytes/mod.ts";
|
||||
import { extname } from "../fs/path.ts";
|
||||
import { copyN } from "../io/ioutil.ts";
|
||||
import { MultiReader } from "../io/readers.ts";
|
||||
import { FormFile } from "../multipart/formfile.ts";
|
||||
import { extname } from "../path/mod.ts";
|
||||
import { tempFile } from "../io/util.ts";
|
||||
import { BufReader, BufWriter, UnexpectedEOFError } from "../io/bufio.ts";
|
||||
import { encoder } from "../strings/mod.ts";
|
||||
|
|
|
@ -8,13 +8,13 @@ import {
|
|||
assertThrowsAsync
|
||||
} from "../testing/asserts.ts";
|
||||
import { test, runIfMain } from "../testing/mod.ts";
|
||||
import * as path from "../path/mod.ts";
|
||||
import {
|
||||
matchAfterPrefix,
|
||||
MultipartReader,
|
||||
MultipartWriter,
|
||||
scanUntilBoundary
|
||||
} from "./multipart.ts";
|
||||
import * as path from "../fs/path.ts";
|
||||
import { FormFile, isFormFile } from "../multipart/formfile.ts";
|
||||
import { StringWriter } from "../io/writers.ts";
|
||||
|
||||
|
|
7
std/path/README.md
Normal file
7
std/path/README.md
Normal file
|
@ -0,0 +1,7 @@
|
|||
# Deno Path Manipulation Libraries
|
||||
|
||||
Usage:
|
||||
|
||||
```ts
|
||||
import * as path from "https://deno.land/std/path/mod.ts";
|
||||
```
|
|
@ -1,8 +1,8 @@
|
|||
// Copyright the Browserify authors. MIT License.
|
||||
// Ported from https://github.com/browserify/path-browserify/
|
||||
|
||||
import { test } from "../../testing/mod.ts";
|
||||
import { assertEquals } from "../../testing/asserts.ts";
|
||||
import { test } from "../testing/mod.ts";
|
||||
import { assertEquals } from "../testing/asserts.ts";
|
||||
import * as path from "./mod.ts";
|
||||
|
||||
test(function basename() {
|
|
@ -1,8 +1,8 @@
|
|||
// Copyright the Browserify authors. MIT License.
|
||||
// Ported from https://github.com/browserify/path-browserify/
|
||||
|
||||
import { test } from "../../testing/mod.ts";
|
||||
import { assertEquals } from "../../testing/asserts.ts";
|
||||
import { test } from "../testing/mod.ts";
|
||||
import { assertEquals } from "../testing/asserts.ts";
|
||||
import * as path from "./mod.ts";
|
||||
|
||||
test(function dirname() {
|
|
@ -1,8 +1,8 @@
|
|||
// Copyright the Browserify authors. MIT License.
|
||||
// Ported from https://github.com/browserify/path-browserify/
|
||||
|
||||
import { test } from "../../testing/mod.ts";
|
||||
import { assertEquals } from "../../testing/asserts.ts";
|
||||
import { test } from "../testing/mod.ts";
|
||||
import { assertEquals } from "../testing/asserts.ts";
|
||||
import * as path from "./mod.ts";
|
||||
|
||||
const slashRE = /\//g;
|
121
std/path/glob.ts
Normal file
121
std/path/glob.ts
Normal file
|
@ -0,0 +1,121 @@
|
|||
import { SEP, SEP_PATTERN } from "./constants.ts";
|
||||
import { globrex } from "./globrex.ts";
|
||||
import { join, normalize } from "./mod.ts";
|
||||
const { DenoError, ErrorKind } = Deno;
|
||||
|
||||
export interface GlobOptions {
|
||||
extended?: boolean;
|
||||
globstar?: boolean;
|
||||
}
|
||||
|
||||
export interface GlobToRegExpOptions extends GlobOptions {
|
||||
flags?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a regex based on glob pattern and options
|
||||
* This was meant to be using the the `fs.walk` function
|
||||
* but can be used anywhere else.
|
||||
* Examples:
|
||||
*
|
||||
* Looking for all the `ts` files:
|
||||
* walkSync(".", {
|
||||
* match: [globToRegExp("*.ts")]
|
||||
* })
|
||||
*
|
||||
* Looking for all the `.json` files in any subfolder:
|
||||
* walkSync(".", {
|
||||
* match: [globToRegExp(join("a", "**", "*.json"),{
|
||||
* flags: "g",
|
||||
* extended: true,
|
||||
* globstar: true
|
||||
* })]
|
||||
* })
|
||||
*
|
||||
* @param glob - Glob pattern to be used
|
||||
* @param options - Specific options for the glob pattern
|
||||
* @returns A RegExp for the glob pattern
|
||||
*/
|
||||
export function globToRegExp(
|
||||
glob: string,
|
||||
options: GlobToRegExpOptions = {}
|
||||
): RegExp {
|
||||
const result = globrex(glob, { ...options, strict: false, filepath: true });
|
||||
return result.path!.regex;
|
||||
}
|
||||
|
||||
/** Test whether the given string is a glob */
|
||||
export function isGlob(str: string): boolean {
|
||||
const chars: Record<string, string> = { "{": "}", "(": ")", "[": "]" };
|
||||
/* eslint-disable-next-line max-len */
|
||||
const regex = /\\(.)|(^!|\*|[\].+)]\?|\[[^\\\]]+\]|\{[^\\}]+\}|\(\?[:!=][^\\)]+\)|\([^|]+\|[^\\)]+\))/;
|
||||
|
||||
if (str === "") {
|
||||
return false;
|
||||
}
|
||||
|
||||
let match: RegExpExecArray | null;
|
||||
|
||||
while ((match = regex.exec(str))) {
|
||||
if (match[2]) return true;
|
||||
let idx = match.index + match[0].length;
|
||||
|
||||
// if an open bracket/brace/paren is escaped,
|
||||
// set the index to the next closing character
|
||||
const open = match[1];
|
||||
const close = open ? chars[open] : null;
|
||||
if (open && close) {
|
||||
const n = str.indexOf(close, idx);
|
||||
if (n !== -1) {
|
||||
idx = n + 1;
|
||||
}
|
||||
}
|
||||
|
||||
str = str.slice(idx);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Like normalize(), but doesn't collapse "**\/.." when `globstar` is true. */
|
||||
export function normalizeGlob(
|
||||
glob: string,
|
||||
{ globstar = false }: GlobOptions = {}
|
||||
): string {
|
||||
if (!!glob.match(/\0/g)) {
|
||||
throw new DenoError(
|
||||
ErrorKind.InvalidPath,
|
||||
`Glob contains invalid characters: "${glob}"`
|
||||
);
|
||||
}
|
||||
if (!globstar) {
|
||||
return normalize(glob);
|
||||
}
|
||||
const s = SEP_PATTERN.source;
|
||||
const badParentPattern = new RegExp(
|
||||
`(?<=(${s}|^)\\*\\*${s})\\.\\.(?=${s}|$)`,
|
||||
"g"
|
||||
);
|
||||
return normalize(glob.replace(badParentPattern, "\0")).replace(/\0/g, "..");
|
||||
}
|
||||
|
||||
/** Like join(), but doesn't collapse "**\/.." when `globstar` is true. */
|
||||
export function joinGlobs(
|
||||
globs: string[],
|
||||
{ extended = false, globstar = false }: GlobOptions = {}
|
||||
): string {
|
||||
if (!globstar || globs.length == 0) {
|
||||
return join(...globs);
|
||||
}
|
||||
if (globs.length === 0) return ".";
|
||||
let joined: string | undefined;
|
||||
for (const glob of globs) {
|
||||
const path = glob;
|
||||
if (path.length > 0) {
|
||||
if (!joined) joined = path;
|
||||
else joined += `${SEP}${path}`;
|
||||
}
|
||||
}
|
||||
if (!joined) return ".";
|
||||
return normalizeGlob(joined, { extended, globstar });
|
||||
}
|
|
@ -1,19 +1,9 @@
|
|||
const { cwd, mkdir } = Deno;
|
||||
const { mkdir } = Deno;
|
||||
import { test, runIfMain } from "../testing/mod.ts";
|
||||
import { assert, assertEquals } from "../testing/asserts.ts";
|
||||
import { SEP, isWindows } from "./path/constants.ts";
|
||||
import {
|
||||
ExpandGlobOptions,
|
||||
expandGlob,
|
||||
expandGlobSync,
|
||||
globToRegExp,
|
||||
isGlob,
|
||||
joinGlobs,
|
||||
normalizeGlob
|
||||
} from "./glob.ts";
|
||||
import { join, normalize, relative } from "./path.ts";
|
||||
import { testWalk } from "./walk_test.ts";
|
||||
import { touch, walkArray } from "./walk_test.ts";
|
||||
import { testWalk, touch, walkArray } from "../fs/walk_test.ts";
|
||||
import { globToRegExp, isGlob, joinGlobs, normalizeGlob } from "./glob.ts";
|
||||
import { SEP, join } from "./mod.ts";
|
||||
|
||||
test({
|
||||
name: "glob: glob to regex",
|
||||
|
@ -268,107 +258,4 @@ test(function joinGlobsGlobstar(): void {
|
|||
assertEquals(joinGlobs(["**", ".."], { globstar: true }), `**${SEP}..`);
|
||||
});
|
||||
|
||||
async function expandGlobArray(
|
||||
globString: string,
|
||||
options: ExpandGlobOptions
|
||||
): Promise<string[]> {
|
||||
const paths: string[] = [];
|
||||
for await (const { filename } of expandGlob(globString, options)) {
|
||||
paths.push(filename);
|
||||
}
|
||||
paths.sort();
|
||||
const pathsSync = [...expandGlobSync(globString, options)].map(
|
||||
({ filename }): string => filename
|
||||
);
|
||||
pathsSync.sort();
|
||||
assertEquals(paths, pathsSync);
|
||||
const root = normalize(options.root || cwd());
|
||||
for (const path of paths) {
|
||||
assert(path.startsWith(root));
|
||||
}
|
||||
const relativePaths = paths.map(
|
||||
(path: string): string => relative(root, path) || "."
|
||||
);
|
||||
relativePaths.sort();
|
||||
return relativePaths;
|
||||
}
|
||||
|
||||
function urlToFilePath(url: URL): string {
|
||||
// Since `new URL('file:///C:/a').pathname` is `/C:/a`, remove leading slash.
|
||||
return url.pathname.slice(url.protocol == "file:" && isWindows ? 1 : 0);
|
||||
}
|
||||
|
||||
const EG_OPTIONS: ExpandGlobOptions = {
|
||||
root: urlToFilePath(new URL(join("testdata", "glob"), import.meta.url)),
|
||||
includeDirs: true,
|
||||
extended: false,
|
||||
globstar: false
|
||||
};
|
||||
|
||||
test(async function expandGlobWildcard(): Promise<void> {
|
||||
const options = EG_OPTIONS;
|
||||
assertEquals(await expandGlobArray("*", options), [
|
||||
"abc",
|
||||
"abcdef",
|
||||
"abcdefghi",
|
||||
"subdir"
|
||||
]);
|
||||
});
|
||||
|
||||
test(async function expandGlobTrailingSeparator(): Promise<void> {
|
||||
const options = EG_OPTIONS;
|
||||
assertEquals(await expandGlobArray("*/", options), ["subdir"]);
|
||||
});
|
||||
|
||||
test(async function expandGlobParent(): Promise<void> {
|
||||
const options = EG_OPTIONS;
|
||||
assertEquals(await expandGlobArray("subdir/../*", options), [
|
||||
"abc",
|
||||
"abcdef",
|
||||
"abcdefghi",
|
||||
"subdir"
|
||||
]);
|
||||
});
|
||||
|
||||
test(async function expandGlobExt(): Promise<void> {
|
||||
const options = { ...EG_OPTIONS, extended: true };
|
||||
assertEquals(await expandGlobArray("abc?(def|ghi)", options), [
|
||||
"abc",
|
||||
"abcdef"
|
||||
]);
|
||||
assertEquals(await expandGlobArray("abc*(def|ghi)", options), [
|
||||
"abc",
|
||||
"abcdef",
|
||||
"abcdefghi"
|
||||
]);
|
||||
assertEquals(await expandGlobArray("abc+(def|ghi)", options), [
|
||||
"abcdef",
|
||||
"abcdefghi"
|
||||
]);
|
||||
assertEquals(await expandGlobArray("abc@(def|ghi)", options), ["abcdef"]);
|
||||
assertEquals(await expandGlobArray("abc{def,ghi}", options), ["abcdef"]);
|
||||
assertEquals(await expandGlobArray("abc!(def|ghi)", options), ["abc"]);
|
||||
});
|
||||
|
||||
test(async function expandGlobGlobstar(): Promise<void> {
|
||||
const options = { ...EG_OPTIONS, globstar: true };
|
||||
assertEquals(
|
||||
await expandGlobArray(joinGlobs(["**", "abc"], options), options),
|
||||
["abc", join("subdir", "abc")]
|
||||
);
|
||||
});
|
||||
|
||||
test(async function expandGlobGlobstarParent(): Promise<void> {
|
||||
const options = { ...EG_OPTIONS, globstar: true };
|
||||
assertEquals(
|
||||
await expandGlobArray(joinGlobs(["subdir", "**", ".."], options), options),
|
||||
["."]
|
||||
);
|
||||
});
|
||||
|
||||
test(async function expandGlobIncludeDirs(): Promise<void> {
|
||||
const options = { ...EG_OPTIONS, includeDirs: false };
|
||||
assertEquals(await expandGlobArray("subdir", options), []);
|
||||
});
|
||||
|
||||
runIfMain(import.meta);
|
|
@ -1,8 +1,8 @@
|
|||
// Copyright the Browserify authors. MIT License.
|
||||
// Ported from https://github.com/browserify/path-browserify/
|
||||
|
||||
import { test } from "../../testing/mod.ts";
|
||||
import { assertEquals } from "../../testing/asserts.ts";
|
||||
import { test } from "../testing/mod.ts";
|
||||
import { assertEquals } from "../testing/asserts.ts";
|
||||
import * as path from "./mod.ts";
|
||||
|
||||
test(function isAbsolute() {
|
|
@ -1,5 +1,5 @@
|
|||
import { test } from "../../testing/mod.ts";
|
||||
import { assertEquals } from "../../testing/asserts.ts";
|
||||
import { test } from "../testing/mod.ts";
|
||||
import { assertEquals } from "../testing/asserts.ts";
|
||||
import * as path from "./mod.ts";
|
||||
|
||||
const backslashRE = /\\/g;
|
|
@ -23,3 +23,8 @@ export const format = path.format;
|
|||
export const parse = path.parse;
|
||||
export const sep = path.sep;
|
||||
export const delimiter = path.delimiter;
|
||||
|
||||
export { EOL, SEP, SEP_PATTERN, isWindows } from "./constants.ts";
|
||||
export * from "./interface.ts";
|
||||
export * from "./glob.ts";
|
||||
export * from "./globrex.ts";
|
|
@ -3,8 +3,8 @@
|
|||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
// TODO(kt3k): fix any types in this file
|
||||
|
||||
import { test } from "../../testing/mod.ts";
|
||||
import { assertEquals } from "../../testing/asserts.ts";
|
||||
import { test } from "../testing/mod.ts";
|
||||
import { assertEquals } from "../testing/asserts.ts";
|
||||
import * as path from "./mod.ts";
|
||||
|
||||
const winPaths = [
|
|
@ -1,8 +1,8 @@
|
|||
// Copyright the Browserify authors. MIT License.
|
||||
// Ported from https://github.com/browserify/path-browserify/
|
||||
|
||||
import { test } from "../../testing/mod.ts";
|
||||
import { assertEquals } from "../../testing/asserts.ts";
|
||||
import { test } from "../testing/mod.ts";
|
||||
import { assertEquals } from "../testing/asserts.ts";
|
||||
import * as path from "./mod.ts";
|
||||
|
||||
const relativeTests = {
|
|
@ -2,8 +2,8 @@
|
|||
// Ported from https://github.com/browserify/path-browserify/
|
||||
|
||||
const { cwd } = Deno;
|
||||
import { test } from "../../testing/mod.ts";
|
||||
import { assertEquals } from "../../testing/asserts.ts";
|
||||
import { test } from "../testing/mod.ts";
|
||||
import { assertEquals } from "../testing/asserts.ts";
|
||||
import * as path from "./mod.ts";
|
||||
|
||||
const windowsTests =
|
|
@ -2,8 +2,8 @@
|
|||
// Ported from https://github.com/browserify/path-browserify/
|
||||
|
||||
const { cwd } = Deno;
|
||||
import { test } from "../../testing/mod.ts";
|
||||
import { assertEquals } from "../../testing/asserts.ts";
|
||||
import { test } from "../testing/mod.ts";
|
||||
import { assertEquals } from "../testing/asserts.ts";
|
||||
import * as path from "./mod.ts";
|
||||
|
||||
const pwd = cwd();
|
|
@ -1,10 +1,9 @@
|
|||
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
|
||||
import { join } from "../fs/path.ts";
|
||||
import { EOL } from "../fs/path/constants.ts";
|
||||
import { assertEquals } from "../testing/asserts.ts";
|
||||
import { test, runIfMain } from "../testing/mod.ts";
|
||||
import { xrun } from "./util.ts";
|
||||
import { copy, emptyDir } from "../fs/mod.ts";
|
||||
import { EOL, join } from "../path/mod.ts";
|
||||
import { xrun } from "./util.ts";
|
||||
const { readAll, execPath } = Deno;
|
||||
|
||||
const decoder = new TextDecoder();
|
||||
|
|
|
@ -2,8 +2,7 @@
|
|||
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
|
||||
import { parse } from "../flags/mod.ts";
|
||||
import { ExpandGlobOptions, expandGlob } from "../fs/mod.ts";
|
||||
import { isWindows } from "../fs/path/constants.ts";
|
||||
import { join } from "../fs/path/mod.ts";
|
||||
import { isWindows, join } from "../path/mod.ts";
|
||||
import { RunTestsOptions, runTests } from "./mod.ts";
|
||||
const { DenoError, ErrorKind, args, cwd, exit } = Deno;
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
|
||||
import { assertEquals } from "../testing/asserts.ts";
|
||||
import { isWindows } from "../path/mod.ts";
|
||||
import { test } from "./mod.ts";
|
||||
import { findTestModules } from "./runner.ts";
|
||||
import { isWindows } from "../fs/path/constants.ts";
|
||||
import { assertEquals } from "../testing/asserts.ts";
|
||||
const { cwd } = Deno;
|
||||
|
||||
function urlToFilePath(url: URL): string {
|
||||
|
|
Loading…
Reference in a new issue