UNPKG

8.32 kBJavaScriptView Raw
1"use strict";
2var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3 return new (P || (P = Promise))(function (resolve, reject) {
4 function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5 function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6 function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
7 step((generator = generator.apply(thisArg, _arguments || [])).next());
8 });
9};
10Object.defineProperty(exports, "__esModule", { value: true });
11const fs = require("fs-extra");
12const gs = require("glob-stream");
13const fpath = require("path");
14const stream = require("stream");
15const file_1 = require("../../internal/util/file");
16const logger_1 = require("../../internal/util/logger");
17const RepoId_1 = require("../../operations/common/RepoId");
18const InMemoryProject_1 = require("../mem/InMemoryProject");
19const AbstractProject_1 = require("../support/AbstractProject");
20const projectUtils_1 = require("../support/projectUtils");
21const LocalProject_1 = require("./LocalProject");
22const NodeFsLocalFile_1 = require("./NodeFsLocalFile");
23class NodeFsLocalProject extends AbstractProject_1.AbstractProject {
24 /**
25 * Note: this does not validate existence of the target
26 * directory, so using it except in tests should be avoided
27 * @param {RepoRef} ident identification of the repo
28 * @param {string} baseDir
29 * @param cleanup function that will release locks, delete temp directories etc
30 */
31 constructor(ident, baseDir, cleanup = () => Promise.resolve()) {
32 super(typeof ident === "string" ? new RepoId_1.SimpleRepoId(undefined, ident) : ident);
33 this.cleanup = cleanup;
34 // TODO not sure why app-root-path can return something weird and this coercion is necessary
35 this.baseDir = "" + baseDir;
36 }
37 /**
38 * Create a project from an existing directory. The directory must exist
39 * @param {RepoRef} id
40 * @param {string} baseDir
41 * @param cleanup
42 * @return {Promise<LocalProject>}
43 */
44 static fromExistingDirectory(id, baseDir, cleanup = () => Promise.resolve()) {
45 return fs.stat(baseDir).then(stat => {
46 if (!stat.isDirectory()) {
47 throw new Error(`No such directory: [${baseDir}] when trying to create LocalProject`);
48 }
49 else {
50 return new NodeFsLocalProject(id, baseDir, cleanup);
51 }
52 });
53 }
54 /**
55 * Copy the contents of the other project to this project
56 * @param {Project} other
57 * @param {string} baseDir
58 * @param newName new name of the project. Defaults to name of old project
59 * @param cleanup
60 * @returns {LocalProject}
61 */
62 static copy(other, baseDir, cleanup = () => Promise.resolve()) {
63 return fs.ensureDir(baseDir)
64 .then(() => {
65 if (LocalProject_1.isLocalProject(other)) {
66 return fs.copy(other.baseDir, baseDir)
67 .then(() => new NodeFsLocalProject(other.id, baseDir, cleanup));
68 }
69 else {
70 // We don't know what kind of project the other one is,
71 // so we are going to need to copy the files one at a time
72 const p = new NodeFsLocalProject(other.id, baseDir, cleanup);
73 return projectUtils_1.copyFiles(other, p)
74 .then(() => {
75 // Add empty directories if necessary
76 let prom = Promise.resolve(p);
77 if (InMemoryProject_1.isInMemoryProject(other)) {
78 other.addedDirectoryPaths.forEach(path => {
79 prom = prom.then(() => p.addDirectory(path));
80 });
81 }
82 return prom;
83 });
84 }
85 });
86 }
87 release() {
88 return this.cleanup();
89 }
90 addFileSync(path, content) {
91 const realName = this.baseDir + "/" + path;
92 const dir = fpath.dirname(realName);
93 if (!fs.existsSync(dir)) {
94 fs.mkdirsSync(dir);
95 }
96 fs.writeFileSync(realName, content);
97 }
98 addFile(path, content) {
99 const realName = this.baseDir + "/" + path;
100 const dir = fpath.dirname(realName);
101 return fs.pathExists(dir).then(exists => exists ? Promise.resolve() : fs.mkdirs(dir))
102 .then(() => fs.writeFile(realName, content))
103 .then(() => this);
104 }
105 addDirectory(path) {
106 const realName = this.baseDir + "/" + path;
107 return fs.mkdirp(realName)
108 .then(() => this);
109 }
110 deleteDirectory(path) {
111 return fs.remove(this.toRealPath(path))
112 .then(_ => this)
113 .catch(err => {
114 logger_1.logger.warn("Unable to delete directory '%s': %s", path, err);
115 return this;
116 });
117 }
118 deleteDirectorySync(path) {
119 const localPath = this.toRealPath(path);
120 try {
121 file_1.deleteFolderRecursive(localPath);
122 fs.unlinkSync(localPath);
123 }
124 catch (e) {
125 logger_1.logger.warn("Ignoring directory deletion error: " + e);
126 }
127 }
128 deleteFileSync(path) {
129 try {
130 fs.unlinkSync(this.toRealPath(path));
131 }
132 catch (e) {
133 logger_1.logger.warn("Ignoring file deletion error: " + e);
134 }
135 }
136 deleteFile(path) {
137 return fs.unlink(this.toRealPath(path)).then(_ => this);
138 }
139 makeExecutable(path) {
140 return fs.stat(this.toRealPath(path))
141 .then(stats => {
142 logger_1.logger.debug("Starting mode: " + stats.mode);
143 // tslint:disable-next-line:no-bitwise
144 const newMode = stats.mode | fs.constants.S_IXUSR;
145 logger_1.logger.debug("Setting mode to: " + newMode);
146 return fs.chmod(this.toRealPath(path), newMode);
147 })
148 .then(() => this);
149 }
150 makeExecutableSync(path) {
151 throw new Error("makeExecutableSync not implemented.");
152 }
153 directoryExistsSync(path) {
154 throw new Error("directoryExistsSync not implemented.");
155 }
156 fileExistsSync(path) {
157 return fs.existsSync(this.baseDir + "/" + path);
158 }
159 findFile(path) {
160 return fs.pathExists(this.baseDir + "/" + path)
161 .then(exists => exists ?
162 Promise.resolve(new NodeFsLocalFile_1.NodeFsLocalFile(this.baseDir, path)) :
163 Promise.reject(fileNotFound(path)));
164 }
165 getFile(path) {
166 return __awaiter(this, void 0, void 0, function* () {
167 const exists = yield fs.pathExists(this.baseDir + "/" + path);
168 return exists ? new NodeFsLocalFile_1.NodeFsLocalFile(this.baseDir, path) :
169 undefined;
170 });
171 }
172 findFileSync(path) {
173 if (!this.fileExistsSync(path)) {
174 return undefined;
175 }
176 return new NodeFsLocalFile_1.NodeFsLocalFile(this.baseDir, path);
177 }
178 streamFilesRaw(globPatterns, opts) {
179 // Fight arrow function "this" issue
180 const baseDir = this.baseDir;
181 const toFileTransform = new stream.Transform({ objectMode: true });
182 toFileTransform._transform = function (chunk, encoding, done) {
183 const f = new NodeFsLocalFile_1.NodeFsLocalFile(baseDir, pathWithinArchive(baseDir, chunk.path));
184 this.push(f);
185 done();
186 };
187 const optsToUse = Object.assign({
188 // We can override these defaults...
189 nodir: true, allowEmpty: true }, opts, {
190 // ...but we force this one
191 cwd: this.baseDir });
192 return gs(globPatterns, optsToUse)
193 .pipe(toFileTransform);
194 }
195 toRealPath(path) {
196 return this.baseDir + "/" + path;
197 }
198}
199exports.NodeFsLocalProject = NodeFsLocalProject;
200function pathWithinArchive(baseDir, rawPath) {
201 return rawPath.substr(baseDir.length);
202}
203// construct a useful exception
204function fileNotFound(path) {
205 const error = new Error(`File not found at ${path}`);
206 error.code = "ENOENT";
207 return error;
208}
209//# sourceMappingURL=NodeFsLocalProject.js.map
\No newline at end of file