UNPKG

@azure-tools/async-io

Version:

Asynchronous IO (for Azure Open Source Projects)

197 lines 7.19 kB
"use strict"; /*--------------------------------------------------------------------------------------------- * 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