fix permission errors are swallowed by fs.copy() (#3504)

This commit is contained in:
Axetroy 2019-12-18 22:45:19 +08:00 committed by Ry Dahl
parent 1c09cc63c8
commit ef30d376db
3 changed files with 70 additions and 62 deletions

View file

@ -23,21 +23,25 @@ async function ensureValidCopy(
options: CopyOptions,
isCopyFolder = false
): Promise<Deno.FileInfo> {
const destStat: Deno.FileInfo | null = await Deno.lstat(dest).catch(
(): Promise<null> => Promise.resolve(null)
);
let destStat: Deno.FileInfo | null;
if (destStat) {
if (isCopyFolder && !destStat.isDirectory()) {
throw new Error(
`Cannot overwrite non-directory '${dest}' with directory '${src}'.`
);
}
if (!options.overwrite) {
throw new Error(`'${dest}' already exists.`);
try {
destStat = await Deno.lstat(dest);
} catch (err) {
if (err instanceof Deno.DenoError && err.kind == Deno.ErrorKind.NotFound) {
return;
}
}
if (isCopyFolder && !destStat.isDirectory()) {
throw new Error(
`Cannot overwrite non-directory '${dest}' with directory '${src}'.`
);
}
if (!options.overwrite) {
throw new Error(`'${dest}' already exists.`);
}
return destStat!;
}
@ -51,19 +55,19 @@ function ensureValidCopySync(
try {
destStat = Deno.lstatSync(dest);
} catch {
// ignore error
} catch (err) {
if (err instanceof Deno.DenoError && err.kind == Deno.ErrorKind.NotFound) {
return;
}
}
if (destStat!) {
if (isCopyFolder && !destStat!.isDirectory()) {
throw new Error(
`Cannot overwrite non-directory '${dest}' with directory '${src}'.`
);
}
if (!options.overwrite) {
throw new Error(`'${dest}' already exists.`);
}
if (isCopyFolder && !destStat!.isDirectory()) {
throw new Error(
`Cannot overwrite non-directory '${dest}' with directory '${src}'.`
);
}
if (!options.overwrite) {
throw new Error(`'${dest}' already exists.`);
}
return destStat!;
@ -186,6 +190,7 @@ function copyDirSync(src: string, dest: string, options: CopyOptions): void {
/**
* Copy a file or directory. The directory can have contents. Like `cp -r`.
* Requires the `--allow-read` and `--alow-write` flag.
* @param src the file/directory path.
* Note that if `src` is a directory it will copy everything inside
* of this directory, not the entire directory itself
@ -224,6 +229,7 @@ export async function copy(
/**
* Copy a file or directory. The directory can have contents. Like `cp -r`.
* Requires the `--allow-read` and `--alow-write` flag.
* @param src the file/directory path.
* Note that if `src` is a directory it will copy everything inside
* of this directory, not the entire directory itself

View file

@ -1,49 +1,49 @@
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
import { getFileInfoType } from "./utils.ts";
const { lstat, lstatSync, mkdir, mkdirSync, ErrorKind } = Deno;
/**
* Ensures that the directory exists.
* If the directory structure does not exist, it is created. Like mkdir -p.
* Requires the `--allow-read` and `--alow-write` flag.
*/
export async function ensureDir(dir: string): Promise<void> {
let pathExists = false;
try {
// if dir exists
const stat = await Deno.stat(dir);
pathExists = true;
if (!stat.isDirectory()) {
const fileInfo = await lstat(dir);
if (!fileInfo.isDirectory()) {
throw new Error(
`Ensure path exists, expected 'dir', got '${getFileInfoType(stat)}'`
`Ensure path exists, expected 'dir', got '${getFileInfoType(fileInfo)}'`
);
}
} catch (err) {
if (pathExists) {
throw err;
if (err instanceof Deno.DenoError && err.kind === ErrorKind.NotFound) {
// if dir not exists. then create it.
await mkdir(dir, true);
return;
}
// if dir not exists. then create it.
await Deno.mkdir(dir, true);
throw err;
}
}
/**
* Ensures that the directory exists.
* If the directory structure does not exist, it is created. Like mkdir -p.
* Requires the `--allow-read` and `--alow-write` flag.
*/
export function ensureDirSync(dir: string): void {
let pathExists = false;
try {
// if dir exists
const stat = Deno.statSync(dir);
pathExists = true;
if (!stat.isDirectory()) {
const fileInfo = lstatSync(dir);
if (!fileInfo.isDirectory()) {
throw new Error(
`Ensure path exists, expected 'dir', got '${getFileInfoType(stat)}'`
`Ensure path exists, expected 'dir', got '${getFileInfoType(fileInfo)}'`
);
}
} catch (err) {
if (pathExists) {
throw err;
if (err instanceof Deno.DenoError && err.kind == ErrorKind.NotFound) {
// if dir not exists. then create it.
mkdirSync(dir, true);
return;
}
// if dir not exists. then create it.
Deno.mkdirSync(dir, true);
throw err;
}
}

View file

@ -2,6 +2,7 @@
import * as path from "../path/mod.ts";
import { ensureDir, ensureDirSync } from "./ensure_dir.ts";
import { getFileInfoType } from "./utils.ts";
const { lstat, lstatSync, writeFile, writeFileSync, ErrorKind } = Deno;
/**
* Ensures that the file exists.
@ -9,27 +10,28 @@ import { getFileInfoType } from "./utils.ts";
* exist.
* these directories are created. If the file already exists,
* it is NOTMODIFIED.
* Requires the `--allow-read` and `--alow-write` flag.
*/
export async function ensureFile(filePath: string): Promise<void> {
let pathExists = false;
try {
// if file exists
const stat = await Deno.lstat(filePath);
pathExists = true;
const stat = await lstat(filePath);
if (!stat.isFile()) {
throw new Error(
`Ensure path exists, expected 'file', got '${getFileInfoType(stat)}'`
);
}
} catch (err) {
if (pathExists) {
throw err;
}
// if file not exists
// ensure dir exists
await ensureDir(path.dirname(filePath));
// create file
await Deno.writeFile(filePath, new Uint8Array());
if (err instanceof Deno.DenoError && err.kind === ErrorKind.NotFound) {
// ensure dir exists
await ensureDir(path.dirname(filePath));
// create file
await writeFile(filePath, new Uint8Array());
return;
}
throw err;
}
}
@ -39,26 +41,26 @@ export async function ensureFile(filePath: string): Promise<void> {
* exist,
* these directories are created. If the file already exists,
* it is NOT MODIFIED.
* Requires the `--allow-read` and `--alow-write` flag.
*/
export function ensureFileSync(filePath: string): void {
let pathExists = false;
try {
// if file exists
const stat = Deno.statSync(filePath);
pathExists = true;
const stat = lstatSync(filePath);
if (!stat.isFile()) {
throw new Error(
`Ensure path exists, expected 'file', got '${getFileInfoType(stat)}'`
);
}
} catch (err) {
if (pathExists) {
throw err;
}
// if file not exists
// ensure dir exists
ensureDirSync(path.dirname(filePath));
// create file
Deno.writeFileSync(filePath, new Uint8Array());
if (err instanceof Deno.DenoError && err.kind === ErrorKind.NotFound) {
// ensure dir exists
ensureDirSync(path.dirname(filePath));
// create file
writeFileSync(filePath, new Uint8Array());
return;
}
throw err;
}
}