UNPKG

@atomist/automation-client

Version:

Atomist API for software low-level client

272 lines • 10.2 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } 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) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); const fg = require("fast-glob"); const fs = require("fs-extra"); const fpath = require("path"); const stream = require("stream"); const RepoId_1 = require("../../operations/common/RepoId"); const logger_1 = require("../../util/logger"); const InMemoryProject_1 = require("../mem/InMemoryProject"); const AbstractProject_1 = require("../support/AbstractProject"); const projectUtils_1 = require("../util/projectUtils"); const LocalProject_1 = require("./LocalProject"); const NodeFsLocalFile_1 = require("./NodeFsLocalFile"); class NodeFsLocalProject extends AbstractProject_1.AbstractProject { /** * Note: this does not validate existence of the target * directory, so using it except in tests should be avoided * @param {RepoRef} ident identification of the repo * @param {string} baseDir * @param cleanup function that will release locks, delete temp directories etc */ constructor(ident, baseDir, cleanup = () => Promise.resolve(), shouldCache = false) { super(typeof ident === "string" ? new RepoId_1.SimpleRepoId(undefined, ident) : ident, shouldCache); this.cleanup = cleanup; // TODO not sure why app-root-path can return something weird and this coercion is necessary this.baseDir = "" + baseDir; } /** * Create a project from an existing directory. The directory must exist * @param {RepoRef} id * @param {string} baseDir * @param cleanup * @return {Promise<LocalProject>} */ static fromExistingDirectory(id, baseDir, cleanup = () => Promise.resolve()) { return fs.stat(baseDir).then(stat => { if (!stat.isDirectory()) { throw new Error(`No such directory: [${baseDir}] when trying to create LocalProject`); } else { return new NodeFsLocalProject(id, baseDir, cleanup); } }); } /** * Copy the contents of the other project to this project * @param {Project} other * @param {string} baseDir * @param cleanup * @returns {LocalProject} */ static copy(other, baseDir, cleanup = () => Promise.resolve()) { return fs.ensureDir(baseDir) .then(() => { if (LocalProject_1.isLocalProject(other)) { return fs.copy(other.baseDir, baseDir) .then(() => new NodeFsLocalProject(other.id, baseDir, cleanup)); } else { // We don't know what kind of project the other one is, // so we are going to need to copy the files one at a time const p = new NodeFsLocalProject(other.id, baseDir, cleanup); return projectUtils_1.copyFiles(other, p) .then(() => { // Add empty directories if necessary let prom = Promise.resolve(p); if (InMemoryProject_1.isInMemoryProject(other)) { other.addedDirectoryPaths.forEach(path => { prom = prom.then(() => p.addDirectory(path)); }); } return prom; }); } }); } release() { return this.cleanup(); } addFileSync(path, content) { this.invalidateCache(); const realName = this.toRealPath(path); fs.outputFileSync(realName, content); } addFile(path, content) { return __awaiter(this, void 0, void 0, function* () { this.invalidateCache(); const realName = this.toRealPath(path); yield fs.outputFile(realName, content); return this; }); } addDirectory(path) { return __awaiter(this, void 0, void 0, function* () { this.invalidateCache(); const realName = this.toRealPath(path); yield fs.ensureDir(realName); return this; }); } deleteDirectory(path) { return __awaiter(this, void 0, void 0, function* () { try { yield fs.remove(this.toRealPath(path)); this.invalidateCache(); } catch (e) { logger_1.logger.debug("Unable to delete directory '%s': %s", path, e.message); } return this; }); } deleteDirectorySync(path) { const localPath = this.toRealPath(path); try { fs.removeSync(localPath); this.invalidateCache(); } catch (e) { logger_1.logger.debug("Unable to delete directory '%s': %s", path, e.message); } } deleteFileSync(path) { try { fs.unlinkSync(this.toRealPath(path)); this.invalidateCache(); } catch (e) { logger_1.logger.debug("Unable to delete file '%s': %s", path, e.message); } } deleteFile(path) { return __awaiter(this, void 0, void 0, function* () { try { yield fs.unlink(this.toRealPath(path)); this.invalidateCache(); } catch (e) { logger_1.logger.debug("Unable to delete file '%s': %s", path, e.message); } return this; }); } makeExecutable(path) { return __awaiter(this, void 0, void 0, function* () { const stat = yield fs.stat(this.toRealPath(path)); // tslint:disable-next-line:no-bitwise const newMode = stat.mode | fs.constants.S_IXUSR | fs.constants.S_IXGRP | fs.constants.S_IXOTH; yield fs.chmod(this.toRealPath(path), newMode); return this; }); } makeExecutableSync(path) { const stat = fs.statSync(this.toRealPath(path)); // tslint:disable-next-line:no-bitwise const newMode = stat.mode | fs.constants.S_IXUSR | fs.constants.S_IXGRP | fs.constants.S_IXOTH; fs.chmodSync(this.toRealPath(path), newMode); } directoryExistsSync(path) { try { const stat = fs.statSync(this.toRealPath(path)); return stat.isDirectory(); } catch (e) { return false; } } hasDirectory(path) { return __awaiter(this, void 0, void 0, function* () { try { const stat = yield fs.stat(this.toRealPath(path)); return stat.isDirectory(); } catch (e) { return false; } }); } fileExistsSync(path) { try { const stat = fs.statSync(this.toRealPath(path)); return stat.isFile(); } catch (e) { return false; } } findFile(path) { return __awaiter(this, void 0, void 0, function* () { let stat; try { stat = yield fs.stat(this.toRealPath(path)); } catch (e) { throw fileNotFound(path); } if (!stat.isFile()) { throw new Error(`Path ${path} is not a regular file`); } return new NodeFsLocalFile_1.NodeFsLocalFile(this.baseDir, path); }); } getFile(path) { return __awaiter(this, void 0, void 0, function* () { try { const stat = yield fs.stat(this.toRealPath(path)); return stat.isFile() ? new NodeFsLocalFile_1.NodeFsLocalFile(this.baseDir, path) : undefined; } catch (e) { return undefined; } }); } findFileSync(path) { try { const stat = fs.statSync(this.toRealPath(path)); return stat.isFile() ? new NodeFsLocalFile_1.NodeFsLocalFile(this.baseDir, path) : undefined; } catch (e) { return undefined; } } getFilesInternal(globPatterns) { return __awaiter(this, void 0, void 0, function* () { const optsToUse = { onlyFiles: true, dot: true, cwd: this.baseDir, }; const paths = yield fg(globPatterns, optsToUse); const files = paths.map(path => new NodeFsLocalFile_1.NodeFsLocalFile(this.baseDir, path)); return files; }); } streamFilesRaw(globPatterns, opts) { // Fight arrow function "this" issue const baseDir = this.baseDir; const toFileTransform = new stream.Transform({ objectMode: true }); toFileTransform._transform = function (chunk, encoding, done) { const f = new NodeFsLocalFile_1.NodeFsLocalFile(baseDir, chunk); this.push(f); done(); }; const optsToUse = Object.assign(Object.assign({ // We can override these defaults... onlyFiles: true }, opts), { // ...but we force this one cwd: this.baseDir }); return fg.stream(globPatterns, optsToUse) .pipe(toFileTransform); } toRealPath(path) { return fpath.join(this.baseDir, path); } } exports.NodeFsLocalProject = NodeFsLocalProject; // construct a useful exception function fileNotFound(path) { const error = new Error(`File not found at ${path}`); error.code = "ENOENT"; return error; } //# sourceMappingURL=NodeFsLocalProject.js.map