@azure-tools/async-io
Version:
Asynchronous IO (for Azure Open Source Projects)
197 lines • 7.19 kB
JavaScript
;
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.rmFile = exports.rmdir = exports.isFile = exports.readBinaryFile = exports.readFile = exports.mkdir = exports.isDirectory = exports.lstat = exports.writeFile = exports.close = exports.readdir = exports.exists = exports.filePath = exports.UnableToMakeDirectoryException = exports.UnableToRemoveException = exports.PathIsNotDirectoryException = exports.PathIsNotFileException = exports.PathNotFoundException = void 0;
const tasks_1 = require("@azure-tools/tasks");
const fs = require("fs");
const path = require("path");
const url_1 = require("url");
class PathNotFoundException extends tasks_1.Exception {
constructor(path, exitCode = 1) {
super(`File '${path}' not found.`, exitCode);
this.exitCode = exitCode;
Object.setPrototypeOf(this, PathNotFoundException.prototype);
}
}
exports.PathNotFoundException = PathNotFoundException;
class PathIsNotFileException extends tasks_1.Exception {
constructor(path, exitCode = 1) {
super(`File '${path}' is not a file.`, exitCode);
this.exitCode = exitCode;
Object.setPrototypeOf(this, PathIsNotFileException.prototype);
}
}
exports.PathIsNotFileException = PathIsNotFileException;
class PathIsNotDirectoryException extends tasks_1.Exception {
constructor(path, exitCode = 1) {
super(`File '${path}' is not a directory.`, exitCode);
this.exitCode = exitCode;
Object.setPrototypeOf(this, PathIsNotFileException.prototype);
}
}
exports.PathIsNotDirectoryException = PathIsNotDirectoryException;
class UnableToRemoveException extends tasks_1.Exception {
constructor(path, exitCode = 1) {
super(`Unable to remove '${path}'.`, exitCode);
this.exitCode = exitCode;
Object.setPrototypeOf(this, UnableToRemoveException.prototype);
}
}
exports.UnableToRemoveException = UnableToRemoveException;
class UnableToMakeDirectoryException extends tasks_1.Exception {
constructor(path, exitCode = 1) {
super(`Unable to create directory '${path}'.`, exitCode);
this.exitCode = exitCode;
Object.setPrototypeOf(this, UnableToMakeDirectoryException.prototype);
}
}
exports.UnableToMakeDirectoryException = UnableToMakeDirectoryException;
function filePath(path) {
path = path.toString();
return path.startsWith('file:///') ? url_1.fileURLToPath(path) : path;
}
exports.filePath = filePath;
exports.exists = tasks_1.promisify(fs.exists);
exports.readdir = tasks_1.promisify(fs.readdir);
exports.close = tasks_1.promisify(fs.close);
exports.writeFile = tasks_1.promisify(fs.writeFile);
exports.lstat = tasks_1.promisify(fs.lstat);
const rmdirInternal = tasks_1.promisify(fs.rmdir);
const unlinkInternal = tasks_1.promisify(fs.unlink);
const mkdirInternal = tasks_1.promisify(fs.mkdir);
const openInternal = tasks_1.promisify(fs.open);
const closeInternal = tasks_1.promisify(fs.close);
async function isDirectory(dirPath) {
try {
if (await exports.exists(dirPath)) {
return (await exports.lstat(dirPath)).isDirectory();
}
}
catch (e) {
// don't throw!
}
return false;
}
exports.isDirectory = isDirectory;
async function mkdir(dirPath) {
if (!await isDirectory(dirPath)) {
const p = path.normalize(dirPath + '/');
const parent = path.dirname(dirPath);
if (!await isDirectory(parent)) {
if (p != parent) {
await mkdir(parent);
}
}
try {
await mkdirInternal(p);
}
catch (e) {
if (!await isDirectory(p)) {
throw new UnableToMakeDirectoryException(p);
}
}
}
}
exports.mkdir = mkdir;
const readFileInternal = tasks_1.promisify(fs.readFile);
async function readFile(filename) {
return readFileInternal(filename, 'utf-8');
}
exports.readFile = readFile;
async function readBinaryFile(filename) {
return readFileInternal(filename, 'base64');
}
exports.readBinaryFile = readBinaryFile;
async function isFile(filePath) {
try {
return await exports.exists(filePath) && !await isDirectory(filePath);
}
catch (e) {
// don't throw!
}
return false;
}
exports.isFile = isFile;
async function rmdir(dirPath, exceptions) {
// if it's not there, do nothing.
if (!await exports.exists(dirPath)) {
return;
}
exceptions = exceptions || new Set();
// if it's not a directory, that's bad.
if (!await isDirectory(dirPath)) {
throw new PathIsNotDirectoryException(dirPath);
}
// make sure this isn't the current directory.
if (process.cwd() === path.normalize(dirPath)) {
process.chdir(`${dirPath}/..`);
}
// make sure the folder is empty first.
const files = await exports.readdir(dirPath);
if (files.length) {
const awaiter = new tasks_1.OutstandingTaskAwaiter();
try {
for (const file of files) {
try {
const p = path.join(dirPath, file);
if (exceptions.has(p.toLowerCase())) {
continue;
}
if (await isDirectory(p)) {
// folders are recursively rmdir'd
awaiter.Await(rmdir(p, exceptions));
}
else {
// files and symlinks are unlink'd
awaiter.Await(unlinkInternal(p).catch(() => { }));
}
}
catch (e) {
// uh... can't.. ok.
}
}
}
finally {
// after all the entries are done
await awaiter.Wait();
}
}
try {
// if this fails for some reason, check if it's important.
await rmdirInternal(dirPath);
}
catch (e) {
// is it gone? that's all we really care about.
if (await isDirectory(dirPath)) {
// directory did not delete
//throw new UnableToRemoveException(dirPath);
}
}
}
exports.rmdir = rmdir;
async function rmFile(filePath) {
// not there? no problem
if (!exports.exists(filePath)) {
return;
}
// not a file? that's not cool.
if (await isDirectory(filePath)) {
throw new PathIsNotFileException(filePath);
}
try {
// files and symlinks are unlink'd
await unlinkInternal(filePath);
}
catch (e) {
// is it gone? that's all we really care about.
if (await exports.exists(filePath)) {
// directory did not delete
throw new UnableToRemoveException(filePath);
}
}
}
exports.rmFile = rmFile;
//# sourceMappingURL=file-io.js.map