"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); const childProcess = require("child_process"); const fs = require("fs"); const path = require("path"); const util_1 = require("util"); const ioUtil = require("./io-util"); const exec = util_1.promisify(childProcess.exec); /** * Copies a file or folder. * * @param source source path * @param dest destination path * @param options optional. See CopyOptions. */ function cp(source, dest, options = {}) { return __awaiter(this, void 0, void 0, function* () { yield move(source, dest, options, { deleteOriginal: false }); }); } exports.cp = cp; /** * Moves a path. * * @param source source path * @param dest destination path * @param options optional. See CopyOptions. */ function mv(source, dest, options = {}) { return __awaiter(this, void 0, void 0, function* () { yield move(source, dest, options, { deleteOriginal: true }); }); } exports.mv = mv; /** * Remove a path recursively with force * * @param inputPath path to remove */ function rmRF(inputPath) { return __awaiter(this, void 0, void 0, function* () { if (ioUtil.IS_WINDOWS) { // Node doesn't provide a delete operation, only an unlink function. This means that if the file is being used by another // program (e.g. antivirus), it won't be deleted. To address this, we shell out the work to rd/del. try { if (yield ioUtil.isDirectory(inputPath, true)) { yield exec(`rd /s /q "${inputPath}"`); } else { yield exec(`del /f /a "${inputPath}"`); } } catch (err) { // if you try to delete a file that doesn't exist, desired result is achieved // other errors are valid if (err.code !== 'ENOENT') throw err; } // Shelling out fails to remove a symlink folder with missing source, this unlink catches that try { yield ioUtil.unlink(inputPath); } catch (err) { // if you try to delete a file that doesn't exist, desired result is achieved // other errors are valid if (err.code !== 'ENOENT') throw err; } } else { let isDir = false; try { isDir = yield ioUtil.isDirectory(inputPath); } catch (err) { // if you try to delete a file that doesn't exist, desired result is achieved // other errors are valid if (err.code !== 'ENOENT') throw err; return; } if (isDir) { yield exec(`rm -rf "${inputPath}"`); } else { yield ioUtil.unlink(inputPath); } } }); } exports.rmRF = rmRF; /** * Make a directory. Creates the full path with folders in between * Will throw if it fails * * @param fsPath path to create * @returns Promise */ function mkdirP(fsPath) { return __awaiter(this, void 0, void 0, function* () { yield ioUtil.mkdirP(fsPath); }); } exports.mkdirP = mkdirP; /** * Returns path of a tool had the tool actually been invoked. Resolves via paths. * If you check and the tool does not exist, it will throw. * * @param tool name of the tool * @param check whether to check if tool exists * @returns Promise path to tool */ function which(tool, check) { return __awaiter(this, void 0, void 0, function* () { if (!tool) { throw new Error("parameter 'tool' is required"); } // recursive when check=true if (check) { const result = yield which(tool, false); if (!result) { if (ioUtil.IS_WINDOWS) { throw new Error(`Unable to locate executable file: ${tool}. Please verify either the file path exists or the file can be found within a directory specified by the PATH environment variable. Also verify the file has a valid extension for an executable file.`); } else { throw new Error(`Unable to locate executable file: ${tool}. Please verify either the file path exists or the file can be found within a directory specified by the PATH environment variable. Also check the file mode to verify the file is executable.`); } } } try { // build the list of extensions to try const extensions = []; if (ioUtil.IS_WINDOWS && process.env.PATHEXT) { for (const extension of process.env.PATHEXT.split(path.delimiter)) { if (extension) { extensions.push(extension); } } } // if it's rooted, return it if exists. otherwise return empty. if (ioUtil.isRooted(tool)) { const filePath = yield ioUtil.tryGetExecutablePath(tool, extensions); if (filePath) { return filePath; } return ''; } // if any path separators, return empty if (tool.includes('/') || (ioUtil.IS_WINDOWS && tool.includes('\\'))) { return ''; } // build the list of directories // // Note, technically "where" checks the current directory on Windows. From a task lib perspective, // it feels like we should not do this. Checking the current directory seems like more of a use // case of a shell, and the which() function exposed by the task lib should strive for consistency // across platforms. const directories = []; if (process.env.PATH) { for (const p of process.env.PATH.split(path.delimiter)) { if (p) { directories.push(p); } } } // return the first match for (const directory of directories) { const filePath = yield ioUtil.tryGetExecutablePath(directory + path.sep + tool, extensions); if (filePath) { return filePath; } } return ''; } catch (err) { throw new Error(`which failed with message ${err.message}`); } }); } exports.which = which; // Copies contents of source into dest, making any necessary folders along the way. // Deletes the original copy if deleteOriginal is true function copyDirectoryContents(source, dest, force, deleteOriginal = false) { return __awaiter(this, void 0, void 0, function* () { if (yield ioUtil.isDirectory(source)) { if (yield ioUtil.exists(dest)) { if (!(yield ioUtil.isDirectory(dest))) { throw new Error(`${dest} is not a directory`); } } else { yield mkdirP(dest); } // Copy all child files, and directories recursively const sourceChildren = yield ioUtil.readdir(source); for (const newSource of sourceChildren) { const newDest = path.join(dest, path.basename(newSource)); yield copyDirectoryContents(path.resolve(source, newSource), newDest, force, deleteOriginal); } if (deleteOriginal) { yield ioUtil.rmdir(source); } } else { if (force) { yield ioUtil.copyFile(source, dest); } else { yield ioUtil.copyFile(source, dest, fs.constants.COPYFILE_EXCL); } if (deleteOriginal) { yield ioUtil.unlink(source); } } }); } function move(source, dest, options = {}, moveOptions) { return __awaiter(this, void 0, void 0, function* () { const { force, recursive } = readCopyOptions(options); if (yield ioUtil.isDirectory(source)) { if (!recursive) { throw new Error(`non-recursive cp failed, ${source} is a directory`); } // If directory exists, move source inside it. Otherwise, create it and move contents of source inside. if (yield ioUtil.exists(dest)) { if (!(yield ioUtil.isDirectory(dest))) { throw new Error(`${dest} is not a directory`); } dest = path.join(dest, path.basename(source)); } yield copyDirectoryContents(source, dest, force, moveOptions.deleteOriginal); } else { if ((yield ioUtil.exists(dest)) && (yield ioUtil.isDirectory(dest))) { dest = path.join(dest, path.basename(source)); } if (force) { yield ioUtil.copyFile(source, dest); } else { yield ioUtil.copyFile(source, dest, fs.constants.COPYFILE_EXCL); } if (moveOptions.deleteOriginal) { yield ioUtil.unlink(source); } } }); } function readCopyOptions(options) { const force = options.force == null ? true : options.force; const recursive = Boolean(options.recursive); return { force, recursive }; } //# sourceMappingURL=io.js.map