1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2025-01-10 16:11:13 -05:00

std: Move fs/path to the top-level (#3100)

This commit is contained in:
Nayeem Rahman 2019-10-16 19:39:33 +01:00 committed by Ryan Dahl
parent 99d8ac70db
commit f51dcc12d7
57 changed files with 323 additions and 305 deletions

View file

@ -11,8 +11,8 @@
import { test, runIfMain } from "../testing/mod.ts"; import { test, runIfMain } from "../testing/mod.ts";
import { assertEquals } from "../testing/asserts.ts"; import { assertEquals } from "../testing/asserts.ts";
import { resolve } from "../path/mod.ts";
import { Tar, Untar } from "./tar.ts"; import { Tar, Untar } from "./tar.ts";
import { resolve } from "../fs/path/mod.ts";
const filePath = resolve("archive", "testdata", "example.txt"); const filePath = resolve("archive", "testdata", "example.txt");

View file

@ -3,8 +3,8 @@ import { runIfMain, test } from "../testing/mod.ts";
import { assertEquals } from "../testing/asserts.ts"; import { assertEquals } from "../testing/asserts.ts";
import { existsSync } from "../fs/exists.ts"; import { existsSync } from "../fs/exists.ts";
import { readFileStrSync } from "../fs/read_file_str.ts"; import { readFileStrSync } from "../fs/read_file_str.ts";
import * as path from "../path/mod.ts";
import { parse, stringify } from "./toml.ts"; import { parse, stringify } from "./toml.ts";
import * as path from "../fs/path/mod.ts";
const testFilesDir = path.resolve("encoding", "testdata"); const testFilesDir = path.resolve("encoding", "testdata");

View file

@ -1,5 +1,5 @@
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license. // 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 { ensureDir, ensureDirSync } from "./ensure_dir.ts";
import { isSubdir, getFileInfoType } from "./utils.ts"; import { isSubdir, getFileInfoType } from "./utils.ts";

View file

@ -6,9 +6,9 @@ import {
assertThrowsAsync, assertThrowsAsync,
assert assert
} from "../testing/asserts.ts"; } from "../testing/asserts.ts";
import * as path from "../path/mod.ts";
import { copy, copySync } from "./copy.ts"; import { copy, copySync } from "./copy.ts";
import { exists, existsSync } from "./exists.ts"; import { exists, existsSync } from "./exists.ts";
import * as path from "./path/mod.ts";
import { ensureDir, ensureDirSync } from "./ensure_dir.ts"; import { ensureDir, ensureDirSync } from "./ensure_dir.ts";
import { ensureFile, ensureFileSync } from "./ensure_file.ts"; import { ensureFile, ensureFileSync } from "./ensure_file.ts";
import { ensureSymlink, ensureSymlinkSync } from "./ensure_symlink.ts"; import { ensureSymlink, ensureSymlinkSync } from "./ensure_symlink.ts";

View file

@ -5,8 +5,8 @@ import {
assertThrows, assertThrows,
assertThrowsAsync assertThrowsAsync
} from "../testing/asserts.ts"; } from "../testing/asserts.ts";
import * as path from "../path/mod.ts";
import { emptyDir, emptyDirSync } from "./empty_dir.ts"; import { emptyDir, emptyDirSync } from "./empty_dir.ts";
import * as path from "./path/mod.ts";
const testdataDir = path.resolve("fs", "testdata"); const testdataDir = path.resolve("fs", "testdata");

View file

@ -1,8 +1,8 @@
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
import { test } from "../testing/mod.ts"; import { test } from "../testing/mod.ts";
import { assertThrows, assertThrowsAsync } from "../testing/asserts.ts"; import { assertThrows, assertThrowsAsync } from "../testing/asserts.ts";
import * as path from "../path/mod.ts";
import { ensureDir, ensureDirSync } from "./ensure_dir.ts"; import { ensureDir, ensureDirSync } from "./ensure_dir.ts";
import * as path from "./path/mod.ts";
import { ensureFile, ensureFileSync } from "./ensure_file.ts"; import { ensureFile, ensureFileSync } from "./ensure_file.ts";
const testdataDir = path.resolve("fs", "testdata"); const testdataDir = path.resolve("fs", "testdata");

View file

@ -1,5 +1,5 @@
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license. // 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 { ensureDir, ensureDirSync } from "./ensure_dir.ts";
import { getFileInfoType } from "./utils.ts"; import { getFileInfoType } from "./utils.ts";

View file

@ -1,8 +1,8 @@
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
import { test } from "../testing/mod.ts"; import { test } from "../testing/mod.ts";
import { assertThrows, assertThrowsAsync } from "../testing/asserts.ts"; import { assertThrows, assertThrowsAsync } from "../testing/asserts.ts";
import * as path from "../path/mod.ts";
import { ensureFile, ensureFileSync } from "./ensure_file.ts"; import { ensureFile, ensureFileSync } from "./ensure_file.ts";
import * as path from "./path/mod.ts";
const testdataDir = path.resolve("fs", "testdata"); const testdataDir = path.resolve("fs", "testdata");

View file

@ -1,5 +1,5 @@
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license. // 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 { ensureDir, ensureDirSync } from "./ensure_dir.ts";
import { exists, existsSync } from "./exists.ts"; import { exists, existsSync } from "./exists.ts";
import { getFileInfoType } from "./utils.ts"; import { getFileInfoType } from "./utils.ts";

View file

@ -6,8 +6,8 @@ import {
assertThrows, assertThrows,
assertThrowsAsync assertThrowsAsync
} from "../testing/asserts.ts"; } from "../testing/asserts.ts";
import * as path from "../path/mod.ts";
import { ensureLink, ensureLinkSync } from "./ensure_link.ts"; import { ensureLink, ensureLinkSync } from "./ensure_link.ts";
import * as path from "./path/mod.ts";
const testdataDir = path.resolve("fs", "testdata"); const testdataDir = path.resolve("fs", "testdata");

View file

@ -1,5 +1,5 @@
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license. // 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 { ensureDir, ensureDirSync } from "./ensure_dir.ts";
import { exists, existsSync } from "./exists.ts"; import { exists, existsSync } from "./exists.ts";
import { getFileInfoType } from "./utils.ts"; import { getFileInfoType } from "./utils.ts";

View file

@ -6,8 +6,8 @@ import {
assertThrows, assertThrows,
assertThrowsAsync assertThrowsAsync
} from "../testing/asserts.ts"; } from "../testing/asserts.ts";
import * as path from "../path/mod.ts";
import { ensureSymlink, ensureSymlinkSync } from "./ensure_symlink.ts"; import { ensureSymlink, ensureSymlinkSync } from "./ensure_symlink.ts";
import * as path from "./path/mod.ts";
const testdataDir = path.resolve("fs", "testdata"); const testdataDir = path.resolve("fs", "testdata");
const isWindows = Deno.build.os === "win"; const isWindows = Deno.build.os === "win";

View file

@ -1,8 +1,8 @@
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
import { test } from "../testing/mod.ts"; import { test } from "../testing/mod.ts";
import { assertEquals } from "../testing/asserts.ts"; import { assertEquals } from "../testing/asserts.ts";
import * as path from "../path/mod.ts";
import { exists, existsSync } from "./exists.ts"; import { exists, existsSync } from "./exists.ts";
import * as path from "./path/mod.ts";
const testdataDir = path.resolve("fs", "testdata"); const testdataDir = path.resolve("fs", "testdata");

View file

@ -1,127 +1,17 @@
import { globrex } from "./globrex.ts"; import {
import { SEP, SEP_PATTERN, isWindows } from "./path/constants.ts"; GlobOptions,
import { isAbsolute, join, normalize } from "./path/mod.ts"; SEP_PATTERN,
globToRegExp,
isAbsolute,
isGlob,
isWindows,
joinGlobs,
normalize
} from "../path/mod.ts";
import { WalkInfo, walk, walkSync } from "./walk.ts"; import { WalkInfo, walk, walkSync } from "./walk.ts";
const { DenoError, ErrorKind, cwd, stat, statSync } = Deno; const { cwd, stat, statSync } = Deno;
type FileInfo = Deno.FileInfo; 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 { export interface ExpandGlobOptions extends GlobOptions {
root?: string; root?: string;
exclude?: string[]; exclude?: string[];

120
std/fs/expand_glob_test.ts Normal file
View 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);

View file

@ -5,8 +5,7 @@ export * from "./ensure_file.ts";
export * from "./ensure_link.ts"; export * from "./ensure_link.ts";
export * from "./ensure_symlink.ts"; export * from "./ensure_symlink.ts";
export * from "./exists.ts"; export * from "./exists.ts";
export * from "./glob.ts"; export * from "./expand_glob.ts";
export * from "./globrex.ts";
export * from "./move.ts"; export * from "./move.ts";
export * from "./copy.ts"; export * from "./copy.ts";
export * from "./read_file_str.ts"; export * from "./read_file_str.ts";

View file

@ -5,11 +5,11 @@ import {
assertThrows, assertThrows,
assertThrowsAsync assertThrowsAsync
} from "../testing/asserts.ts"; } from "../testing/asserts.ts";
import * as path from "../path/mod.ts";
import { move, moveSync } from "./move.ts"; import { move, moveSync } from "./move.ts";
import { ensureFile, ensureFileSync } from "./ensure_file.ts"; import { ensureFile, ensureFileSync } from "./ensure_file.ts";
import { ensureDir, ensureDirSync } from "./ensure_dir.ts"; import { ensureDir, ensureDirSync } from "./ensure_dir.ts";
import { exists, existsSync } from "./exists.ts"; import { exists, existsSync } from "./exists.ts";
import * as path from "./path/mod.ts";
const testdataDir = path.resolve("fs", "testdata"); const testdataDir = path.resolve("fs", "testdata");

View file

@ -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";

View file

@ -1,7 +0,0 @@
# Deno Path Manipulation Libraries
Usage:
```ts
import * as path from "https://deno.land/std/fs/path.ts";
```

View file

@ -1,7 +1,7 @@
import { test } from "../testing/mod.ts"; import { test } from "../testing/mod.ts";
import { assert } from "../testing/asserts.ts"; import { assert } from "../testing/asserts.ts";
import * as path from "../path/mod.ts";
import { readFileStrSync, readFileStr } from "./read_file_str.ts"; import { readFileStrSync, readFileStr } from "./read_file_str.ts";
import * as path from "./path/mod.ts";
const testdataDir = path.resolve("fs", "testdata"); const testdataDir = path.resolve("fs", "testdata");

View file

@ -5,8 +5,8 @@ import {
assertThrowsAsync, assertThrowsAsync,
assertThrows assertThrows
} from "../testing/asserts.ts"; } from "../testing/asserts.ts";
import * as path from "../path/mod.ts";
import { readJson, readJsonSync } from "./read_json.ts"; import { readJson, readJsonSync } from "./read_json.ts";
import * as path from "./path/mod.ts";
const testdataDir = path.resolve("fs", "testdata"); const testdataDir = path.resolve("fs", "testdata");

View file

@ -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` * Test whether or not `dest` is a sub-directory of `src`

View file

@ -2,8 +2,8 @@
import { test } from "../testing/mod.ts"; import { test } from "../testing/mod.ts";
import { assertEquals } from "../testing/asserts.ts"; import { assertEquals } from "../testing/asserts.ts";
import * as path from "../path/mod.ts";
import { isSubdir, getFileInfoType, PathType } from "./utils.ts"; import { isSubdir, getFileInfoType, PathType } from "./utils.ts";
import * as path from "./path/mod.ts";
import { ensureFileSync } from "./ensure_file.ts"; import { ensureFileSync } from "./ensure_file.ts";
import { ensureDirSync } from "./ensure_dir.ts"; import { ensureDirSync } from "./ensure_dir.ts";

View file

@ -2,7 +2,7 @@
// https://golang.org/pkg/path/filepath/#Walk // https://golang.org/pkg/path/filepath/#Walk
// Copyright 2009 The Go Authors. All rights reserved. BSD license. // Copyright 2009 The Go Authors. All rights reserved. BSD license.
import { unimplemented } from "../testing/asserts.ts"; import { unimplemented } from "../testing/asserts.ts";
import { join } from "./path/mod.ts"; import { join } from "../path/mod.ts";
const { readDir, readDirSync, stat, statSync } = Deno; const { readDir, readDirSync, stat, statSync } = Deno;
type FileInfo = Deno.FileInfo; type FileInfo = Deno.FileInfo;

View file

@ -1,7 +1,7 @@
import { test } from "../testing/mod.ts"; import { test } from "../testing/mod.ts";
import { assertEquals } from "../testing/asserts.ts"; import { assertEquals } from "../testing/asserts.ts";
import * as path from "../path/mod.ts";
import { writeFileStr, writeFileStrSync } from "./write_file_str.ts"; import { writeFileStr, writeFileStrSync } from "./write_file_str.ts";
import * as path from "./path/mod.ts";
const testdataDir = path.resolve("fs", "testdata"); const testdataDir = path.resolve("fs", "testdata");

View file

@ -5,8 +5,8 @@ import {
assertThrowsAsync, assertThrowsAsync,
assertThrows assertThrows
} from "../testing/asserts.ts"; } from "../testing/asserts.ts";
import * as path from "../path/mod.ts";
import { writeJson, writeJsonSync } from "./write_json.ts"; import { writeJson, writeJsonSync } from "./write_json.ts";
import * as path from "./path/mod.ts";
const testdataDir = path.resolve("fs", "testdata"); const testdataDir = path.resolve("fs", "testdata");

View file

@ -7,14 +7,14 @@
// https://github.com/indexzero/http-server/blob/master/test/http-server-test.js // https://github.com/indexzero/http-server/blob/master/test/http-server-test.js
const { ErrorKind, cwd, args, stat, readDir, open } = Deno; const { ErrorKind, cwd, args, stat, readDir, open } = Deno;
import { contentType } from "../media_types/mod.ts";
import { extname, posix } from "../path/mod.ts";
import { import {
listenAndServe, listenAndServe,
ServerRequest, ServerRequest,
setContentLength, setContentLength,
Response Response
} from "./server.ts"; } from "./server.ts";
import { extname, posix } from "../fs/path.ts";
import { contentType } from "../media_types/mod.ts";
const dirViewerTemplate = ` const dirViewerTemplate = `
<!DOCTYPE html> <!DOCTYPE html>

View file

@ -2,9 +2,9 @@
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
const { env, stdin, args, exit, writeFile, chmod, run } = Deno; const { env, stdin, args, exit, writeFile, chmod, run } = Deno;
import { parse } from "../flags/mod.ts"; import { parse } from "../flags/mod.ts";
import * as path from "../fs/path.ts";
import { exists } from "../fs/exists.ts"; import { exists } from "../fs/exists.ts";
import { ensureDir } from "../fs/ensure_dir.ts"; import { ensureDir } from "../fs/ensure_dir.ts";
import * as path from "../path/mod.ts";
const encoder = new TextEncoder(); const encoder = new TextEncoder();
const decoder = new TextDecoder("utf-8"); const decoder = new TextDecoder("utf-8");

View file

@ -2,8 +2,9 @@
const { Buffer, mkdir, open } = Deno; const { Buffer, mkdir, open } = Deno;
type File = Deno.File; type File = Deno.File;
type Reader = Deno.Reader; type Reader = Deno.Reader;
import * as path from "../path/mod.ts";
import { encode } from "../strings/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 // `off` is the offset into `dst` where it will at which to begin writing values
// from `src`. // from `src`.
// Returns the number of bytes copied. // Returns the number of bytes copied.

View file

@ -2,8 +2,8 @@
const { remove } = Deno; const { remove } = Deno;
import { test } from "../testing/mod.ts"; import { test } from "../testing/mod.ts";
import { assert, assertEquals } from "../testing/asserts.ts"; import { assert, assertEquals } from "../testing/asserts.ts";
import * as path from "../path/mod.ts";
import { copyBytes, tempFile } from "./util.ts"; import { copyBytes, tempFile } from "./util.ts";
import * as path from "../fs/path.ts";
test(function testCopyBytes(): void { test(function testCopyBytes(): void {
const dst = new Uint8Array(4); const dst = new Uint8Array(4);

View file

@ -1,6 +1,6 @@
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license. // 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 { interface DB {
[mediaType: string]: { [mediaType: string]: {

View file

@ -5,11 +5,11 @@ const { min, max } = Math;
type Closer = Deno.Closer; type Closer = Deno.Closer;
type Reader = Deno.Reader; type Reader = Deno.Reader;
type Writer = Deno.Writer; type Writer = Deno.Writer;
import { FormFile } from "../multipart/formfile.ts";
import { equal, findIndex, findLastIndex, hasPrefix } from "../bytes/mod.ts"; import { equal, findIndex, findLastIndex, hasPrefix } from "../bytes/mod.ts";
import { extname } from "../fs/path.ts";
import { copyN } from "../io/ioutil.ts"; import { copyN } from "../io/ioutil.ts";
import { MultiReader } from "../io/readers.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 { tempFile } from "../io/util.ts";
import { BufReader, BufWriter, UnexpectedEOFError } from "../io/bufio.ts"; import { BufReader, BufWriter, UnexpectedEOFError } from "../io/bufio.ts";
import { encoder } from "../strings/mod.ts"; import { encoder } from "../strings/mod.ts";

View file

@ -8,13 +8,13 @@ import {
assertThrowsAsync assertThrowsAsync
} from "../testing/asserts.ts"; } from "../testing/asserts.ts";
import { test, runIfMain } from "../testing/mod.ts"; import { test, runIfMain } from "../testing/mod.ts";
import * as path from "../path/mod.ts";
import { import {
matchAfterPrefix, matchAfterPrefix,
MultipartReader, MultipartReader,
MultipartWriter, MultipartWriter,
scanUntilBoundary scanUntilBoundary
} from "./multipart.ts"; } from "./multipart.ts";
import * as path from "../fs/path.ts";
import { FormFile, isFormFile } from "../multipart/formfile.ts"; import { FormFile, isFormFile } from "../multipart/formfile.ts";
import { StringWriter } from "../io/writers.ts"; import { StringWriter } from "../io/writers.ts";

7
std/path/README.md Normal file
View file

@ -0,0 +1,7 @@
# Deno Path Manipulation Libraries
Usage:
```ts
import * as path from "https://deno.land/std/path/mod.ts";
```

View file

@ -1,8 +1,8 @@
// Copyright the Browserify authors. MIT License. // Copyright the Browserify authors. MIT License.
// Ported from https://github.com/browserify/path-browserify/ // Ported from https://github.com/browserify/path-browserify/
import { test } from "../../testing/mod.ts"; import { test } from "../testing/mod.ts";
import { assertEquals } from "../../testing/asserts.ts"; import { assertEquals } from "../testing/asserts.ts";
import * as path from "./mod.ts"; import * as path from "./mod.ts";
test(function basename() { test(function basename() {

View file

@ -1,8 +1,8 @@
// Copyright the Browserify authors. MIT License. // Copyright the Browserify authors. MIT License.
// Ported from https://github.com/browserify/path-browserify/ // Ported from https://github.com/browserify/path-browserify/
import { test } from "../../testing/mod.ts"; import { test } from "../testing/mod.ts";
import { assertEquals } from "../../testing/asserts.ts"; import { assertEquals } from "../testing/asserts.ts";
import * as path from "./mod.ts"; import * as path from "./mod.ts";
test(function dirname() { test(function dirname() {

View file

@ -1,8 +1,8 @@
// Copyright the Browserify authors. MIT License. // Copyright the Browserify authors. MIT License.
// Ported from https://github.com/browserify/path-browserify/ // Ported from https://github.com/browserify/path-browserify/
import { test } from "../../testing/mod.ts"; import { test } from "../testing/mod.ts";
import { assertEquals } from "../../testing/asserts.ts"; import { assertEquals } from "../testing/asserts.ts";
import * as path from "./mod.ts"; import * as path from "./mod.ts";
const slashRE = /\//g; const slashRE = /\//g;

121
std/path/glob.ts Normal file
View 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 });
}

View file

@ -1,19 +1,9 @@
const { cwd, mkdir } = Deno; const { mkdir } = Deno;
import { test, runIfMain } from "../testing/mod.ts"; import { test, runIfMain } from "../testing/mod.ts";
import { assert, assertEquals } from "../testing/asserts.ts"; import { assert, assertEquals } from "../testing/asserts.ts";
import { SEP, isWindows } from "./path/constants.ts"; import { testWalk, touch, walkArray } from "../fs/walk_test.ts";
import { import { globToRegExp, isGlob, joinGlobs, normalizeGlob } from "./glob.ts";
ExpandGlobOptions, import { SEP, join } from "./mod.ts";
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";
test({ test({
name: "glob: glob to regex", name: "glob: glob to regex",
@ -268,107 +258,4 @@ test(function joinGlobsGlobstar(): void {
assertEquals(joinGlobs(["**", ".."], { globstar: true }), `**${SEP}..`); 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); runIfMain(import.meta);

View file

@ -1,8 +1,8 @@
// Copyright the Browserify authors. MIT License. // Copyright the Browserify authors. MIT License.
// Ported from https://github.com/browserify/path-browserify/ // Ported from https://github.com/browserify/path-browserify/
import { test } from "../../testing/mod.ts"; import { test } from "../testing/mod.ts";
import { assertEquals } from "../../testing/asserts.ts"; import { assertEquals } from "../testing/asserts.ts";
import * as path from "./mod.ts"; import * as path from "./mod.ts";
test(function isAbsolute() { test(function isAbsolute() {

View file

@ -1,5 +1,5 @@
import { test } from "../../testing/mod.ts"; import { test } from "../testing/mod.ts";
import { assertEquals } from "../../testing/asserts.ts"; import { assertEquals } from "../testing/asserts.ts";
import * as path from "./mod.ts"; import * as path from "./mod.ts";
const backslashRE = /\\/g; const backslashRE = /\\/g;

View file

@ -23,3 +23,8 @@ export const format = path.format;
export const parse = path.parse; export const parse = path.parse;
export const sep = path.sep; export const sep = path.sep;
export const delimiter = path.delimiter; 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";

View file

@ -3,8 +3,8 @@
/* eslint-disable @typescript-eslint/no-explicit-any */ /* eslint-disable @typescript-eslint/no-explicit-any */
// TODO(kt3k): fix any types in this file // TODO(kt3k): fix any types in this file
import { test } from "../../testing/mod.ts"; import { test } from "../testing/mod.ts";
import { assertEquals } from "../../testing/asserts.ts"; import { assertEquals } from "../testing/asserts.ts";
import * as path from "./mod.ts"; import * as path from "./mod.ts";
const winPaths = [ const winPaths = [

View file

@ -1,8 +1,8 @@
// Copyright the Browserify authors. MIT License. // Copyright the Browserify authors. MIT License.
// Ported from https://github.com/browserify/path-browserify/ // Ported from https://github.com/browserify/path-browserify/
import { test } from "../../testing/mod.ts"; import { test } from "../testing/mod.ts";
import { assertEquals } from "../../testing/asserts.ts"; import { assertEquals } from "../testing/asserts.ts";
import * as path from "./mod.ts"; import * as path from "./mod.ts";
const relativeTests = { const relativeTests = {

View file

@ -2,8 +2,8 @@
// Ported from https://github.com/browserify/path-browserify/ // Ported from https://github.com/browserify/path-browserify/
const { cwd } = Deno; const { cwd } = Deno;
import { test } from "../../testing/mod.ts"; import { test } from "../testing/mod.ts";
import { assertEquals } from "../../testing/asserts.ts"; import { assertEquals } from "../testing/asserts.ts";
import * as path from "./mod.ts"; import * as path from "./mod.ts";
const windowsTests = const windowsTests =

View file

@ -2,8 +2,8 @@
// Ported from https://github.com/browserify/path-browserify/ // Ported from https://github.com/browserify/path-browserify/
const { cwd } = Deno; const { cwd } = Deno;
import { test } from "../../testing/mod.ts"; import { test } from "../testing/mod.ts";
import { assertEquals } from "../../testing/asserts.ts"; import { assertEquals } from "../testing/asserts.ts";
import * as path from "./mod.ts"; import * as path from "./mod.ts";
const pwd = cwd(); const pwd = cwd();

View file

@ -1,10 +1,9 @@
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license. // 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 { assertEquals } from "../testing/asserts.ts";
import { test, runIfMain } from "../testing/mod.ts"; import { test, runIfMain } from "../testing/mod.ts";
import { xrun } from "./util.ts";
import { copy, emptyDir } from "../fs/mod.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 { readAll, execPath } = Deno;
const decoder = new TextDecoder(); const decoder = new TextDecoder();

View file

@ -2,8 +2,7 @@
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
import { parse } from "../flags/mod.ts"; import { parse } from "../flags/mod.ts";
import { ExpandGlobOptions, expandGlob } from "../fs/mod.ts"; import { ExpandGlobOptions, expandGlob } from "../fs/mod.ts";
import { isWindows } from "../fs/path/constants.ts"; import { isWindows, join } from "../path/mod.ts";
import { join } from "../fs/path/mod.ts";
import { RunTestsOptions, runTests } from "./mod.ts"; import { RunTestsOptions, runTests } from "./mod.ts";
const { DenoError, ErrorKind, args, cwd, exit } = Deno; const { DenoError, ErrorKind, args, cwd, exit } = Deno;

View file

@ -1,8 +1,8 @@
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license. // 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 { test } from "./mod.ts";
import { findTestModules } from "./runner.ts"; import { findTestModules } from "./runner.ts";
import { isWindows } from "../fs/path/constants.ts";
import { assertEquals } from "../testing/asserts.ts";
const { cwd } = Deno; const { cwd } = Deno;
function urlToFilePath(url: URL): string { function urlToFilePath(url: URL): string {