1 | ;
|
2 | var task_utils_1 = require("./task.utils");
|
3 | var fs_1 = require("fs");
|
4 | var path_1 = require("path");
|
5 | var fs_2 = require("fs");
|
6 | var path_2 = require("path");
|
7 | var fs_3 = require("fs");
|
8 | var Rx = require("rx");
|
9 | var path_3 = require("path");
|
10 | var fs_4 = require("fs");
|
11 | var crypto_1 = require("crypto");
|
12 | var fs_5 = require("fs");
|
13 | var hd = require("hash-dir");
|
14 | var hashDirAsObservable = Rx.Observable.fromNodeCallback(hd);
|
15 | var hashFileAsObservable = Rx.Observable.fromNodeCallback(hashFile);
|
16 | var lstatAsObservable = Rx.Observable.fromNodeCallback(fs_5.lstat);
|
17 | var _ = require("../lodash.custom");
|
18 | // todo windows support for .bat files etc
|
19 | var supportedTaskFileExtensions = [".js", ".sh"];
|
20 | /**
|
21 | * Try to auto-load configuration files
|
22 | * from the users CWD
|
23 | */
|
24 | function retrieveDefaultInputFiles(config) {
|
25 | var defaultConfigFiles = ["crossbow.yaml", "crossbow.js", "crossbow.yml", "crossbow.json"];
|
26 | return readInputFiles(defaultConfigFiles, config.cwd);
|
27 | }
|
28 | exports.retrieveDefaultInputFiles = retrieveDefaultInputFiles;
|
29 | /**
|
30 | * Try to load cbfiles (like gulp) from the users
|
31 | * working directory
|
32 | * @param config
|
33 | * @returns {InputFiles}
|
34 | */
|
35 | function retrieveCBFiles(config) {
|
36 | var defaultCBFiles = ["cbfile.js", "crossbowfile.js"];
|
37 | var maybes = (function () {
|
38 | if (config.cbfile) {
|
39 | return [config.cbfile];
|
40 | }
|
41 | return defaultCBFiles;
|
42 | })();
|
43 | return readInputFiles(maybes, config.cwd);
|
44 | }
|
45 | exports.retrieveCBFiles = retrieveCBFiles;
|
46 | /**
|
47 | * Try to retrieve input files from disk.
|
48 | * This is different from regular file reading as
|
49 | * we deliver errors with context
|
50 | */
|
51 | function readInputFiles(paths, cwd) {
|
52 | /**
|
53 | * Get files that exist on disk
|
54 | * @type {ExternalFile[]}
|
55 | */
|
56 | var inputFiles = readFilesFromDisk(paths, cwd);
|
57 | /**
|
58 | * Add parsed input keys to them
|
59 | * @type {}
|
60 | */
|
61 | var inputs = inputFiles.map(function (inputFile) {
|
62 | /**
|
63 | * If the file does not exist, change the error to be an InputFileNotFound error
|
64 | * as this will allow more descriptive logging when needed
|
65 | */
|
66 | if (inputFile.errors.length) {
|
67 | return _.assign({}, inputFile, {
|
68 | // here there may be any types of file error,
|
69 | // but we only care that was an error, and normalise it
|
70 | // here for logging. We can added nice per-error messages later.
|
71 | errors: [{ type: task_utils_1.InputErrorTypes.InputFileNotFound }],
|
72 | input: undefined
|
73 | });
|
74 | }
|
75 | /**
|
76 | * If the input file was yaml, load it & translate to JS
|
77 | */
|
78 | if (inputFile.parsed.ext.match(/ya?ml$/i)) {
|
79 | var yml = require("js-yaml");
|
80 | try {
|
81 | return _.assign(inputFile, {
|
82 | input: yml.safeLoad(fs_1.readFileSync(inputFile.resolved, "utf8"))
|
83 | });
|
84 | }
|
85 | catch (e) {
|
86 | return _.assign(inputFile, {
|
87 | input: undefined,
|
88 | errors: [{ type: task_utils_1.InputErrorTypes.InvalidYaml, error: e }]
|
89 | });
|
90 | }
|
91 | }
|
92 | /**
|
93 | * Finally assume a JS/JSON file and 'require' it as normal
|
94 | */
|
95 | try {
|
96 | return _.assign({}, inputFile, {
|
97 | input: require(inputFile.resolved)
|
98 | });
|
99 | }
|
100 | catch (e) {
|
101 | return _.assign(inputFile, {
|
102 | input: undefined,
|
103 | errors: [{ type: task_utils_1.InputErrorTypes.InvalidInput, error: e }]
|
104 | });
|
105 | }
|
106 | });
|
107 | return {
|
108 | all: inputs,
|
109 | valid: inputs.filter(function (x) { return x.errors.length === 0; }),
|
110 | invalid: inputs.filter(function (x) { return x.errors.length > 0; })
|
111 | };
|
112 | }
|
113 | exports.readInputFiles = readInputFiles;
|
114 | function readFilesFromDiskWithContent(paths, cwd) {
|
115 | var files = readFilesFromDisk(paths, cwd);
|
116 | return files
|
117 | .map(function (x) {
|
118 | if (x.errors.length)
|
119 | return x;
|
120 | x.content = fs_1.readFileSync(x.resolved, "utf8");
|
121 | return x;
|
122 | });
|
123 | }
|
124 | exports.readFilesFromDiskWithContent = readFilesFromDiskWithContent;
|
125 | function readFileContent(file) {
|
126 | return fs_1.readFileSync(file.resolved, "utf8");
|
127 | }
|
128 | exports.readFileContent = readFileContent;
|
129 | function writeFileToDisk(file, content) {
|
130 | var mkdirp = require("mkdirp").sync;
|
131 | mkdirp(path_3.dirname(file.resolved));
|
132 | fs_1.writeFileSync(file.resolved, content);
|
133 | }
|
134 | exports.writeFileToDisk = writeFileToDisk;
|
135 | function getStubFileWithContent(path, cwd) {
|
136 | var file = getStubFile(path, cwd);
|
137 | file.content = "";
|
138 | return file;
|
139 | }
|
140 | exports.getStubFileWithContent = getStubFileWithContent;
|
141 | function readOrCreateJsonFile(path, cwd) {
|
142 | var existing = readFilesFromDiskWithContent([path], cwd)[0];
|
143 | if (existing.errors.length) {
|
144 | if (existing.errors[0].type === task_utils_1.InputErrorTypes.FileNotFound) {
|
145 | var stub = getStubFileWithContent(path, cwd);
|
146 | stub.content = "{}";
|
147 | stub.data = JSON.parse(stub.content);
|
148 | return stub;
|
149 | }
|
150 | }
|
151 | else {
|
152 | try {
|
153 | existing.data = JSON.parse(existing.content);
|
154 | }
|
155 | catch (e) {
|
156 | existing.data = {};
|
157 | }
|
158 | }
|
159 | return existing;
|
160 | }
|
161 | exports.readOrCreateJsonFile = readOrCreateJsonFile;
|
162 | function getStubFile(path, cwd) {
|
163 | var resolved = path_1.resolve(cwd, path);
|
164 | return {
|
165 | errors: [],
|
166 | rawInput: path,
|
167 | resolved: resolved,
|
168 | parsed: path_1.parse(resolved),
|
169 | relative: path_1.relative(cwd, resolved)
|
170 | };
|
171 | }
|
172 | exports.getStubFile = getStubFile;
|
173 | /**
|
174 | * Take an array of paths and return file info + errors if they don't exist
|
175 | * @param paths
|
176 | * @param cwd
|
177 | * @returns {ExternalFile[]}
|
178 | */
|
179 | function readFilesFromDisk(paths, cwd) {
|
180 | return paths
|
181 | .map(String)
|
182 | .map(function (x) { return getStubFile(x, cwd); })
|
183 | .map(function (incoming) {
|
184 | var resolved = incoming.resolved;
|
185 | /**
|
186 | * If the path does not exist, it's a FileNotFound error
|
187 | */
|
188 | if (!fs_1.existsSync(resolved)) {
|
189 | return _.assign(incoming, {
|
190 | errors: [{ type: task_utils_1.InputErrorTypes.FileNotFound }]
|
191 | });
|
192 | }
|
193 | /**
|
194 | * Not check it's a file & NOT a dir
|
195 | * @type {Stats}
|
196 | */
|
197 | var stat = fs_2.statSync(resolved);
|
198 | if (!stat.isFile()) {
|
199 | return _.assign(incoming, {
|
200 | errors: [{ type: task_utils_1.InputErrorTypes.NotAFile }],
|
201 | });
|
202 | }
|
203 | /**
|
204 | * At this point the file DOES exist
|
205 | */
|
206 | return incoming;
|
207 | });
|
208 | }
|
209 | exports.readFilesFromDisk = readFilesFromDisk;
|
210 | /**
|
211 | * Attempt to use the LOCALLY installed crossbow version
|
212 | * first, this will ensure anything registered with .task etc
|
213 | * can be picked up by global installs too.
|
214 | * @param config
|
215 | * @returns {InputFiles}
|
216 | */
|
217 | function getRequirePaths(config) {
|
218 | var local = path_2.join("node_modules", "crossbow", "dist", "public", "create.js");
|
219 | var global = path_2.join(__dirname, "public", "create.js");
|
220 | return readInputFiles([local, global], config.cwd);
|
221 | }
|
222 | exports.getRequirePaths = getRequirePaths;
|
223 | function getExternalFiles(dirpaths, cwd) {
|
224 | return dirpaths
|
225 | .map(function (dirpath) {
|
226 | return path_1.resolve(cwd, dirpath);
|
227 | })
|
228 | .filter(fs_1.existsSync)
|
229 | .reduce(function (acc, dirPath) {
|
230 | return acc.concat(fs_3.readdirSync(dirPath).map(function (filepath) {
|
231 | var resolved = path_2.join(dirPath, filepath);
|
232 | var parsed = path_1.parse(resolved);
|
233 | var output = {
|
234 | rawInput: filepath,
|
235 | resolved: resolved,
|
236 | relative: path_1.relative(cwd, resolved),
|
237 | parsed: parsed,
|
238 | errors: []
|
239 | };
|
240 | return output;
|
241 | }));
|
242 | }, []);
|
243 | }
|
244 | exports.getExternalFiles = getExternalFiles;
|
245 | function getPossibleTasksFromDirectories(dirpaths, cwd) {
|
246 | return getExternalFiles(dirpaths, cwd)
|
247 | .filter(function (x) { return supportedTaskFileExtensions.indexOf(x.parsed.ext) > -1; })
|
248 | .map(function (x) {
|
249 | return x.relative;
|
250 | });
|
251 | }
|
252 | exports.getPossibleTasksFromDirectories = getPossibleTasksFromDirectories;
|
253 | (function (HashDirErrorTypes) {
|
254 | HashDirErrorTypes[HashDirErrorTypes["HashNotADirectory"] = "HashNotADirectory"] = "HashNotADirectory";
|
255 | HashDirErrorTypes[HashDirErrorTypes["HashPathNotFound"] = "HashPathNotFound"] = "HashPathNotFound";
|
256 | })(exports.HashDirErrorTypes || (exports.HashDirErrorTypes = {}));
|
257 | var HashDirErrorTypes = exports.HashDirErrorTypes;
|
258 | function hashItems(dirs, cwd, existingHashes) {
|
259 | return Rx.Observable
|
260 | .from(dirs)
|
261 | .map(function (x) {
|
262 | return {
|
263 | userInput: x,
|
264 | pathObj: getStubFile(x, cwd)
|
265 | };
|
266 | })
|
267 | .distinct(function (x) { return x.pathObj.resolved; })
|
268 | .flatMap(hashFileOrDir)
|
269 | .toArray()
|
270 | .map(function (x) {
|
271 | return markHashes(x, existingHashes);
|
272 | });
|
273 | }
|
274 | exports.hashItems = hashItems;
|
275 | function hashFile(filepath, fn) {
|
276 | var hash = crypto_1.createHash("sha256");
|
277 | fs_4.createReadStream(filepath)
|
278 | .on("data", function (chunk) {
|
279 | hash.update(chunk);
|
280 | })
|
281 | .on("end", function () {
|
282 | fn(null, hash.digest("hex"));
|
283 | })
|
284 | .on("error", fn);
|
285 | }
|
286 | function hashFileOrDir(input) {
|
287 | return lstatAsObservable(input.pathObj.resolved).flatMap(function (stats) {
|
288 | if (stats.isDirectory()) {
|
289 | return hashDirAsObservable(input.pathObj.resolved).map(function (tree) {
|
290 | return {
|
291 | userInput: input.userInput,
|
292 | resolved: input.pathObj.resolved,
|
293 | hash: tree.hash
|
294 | };
|
295 | });
|
296 | }
|
297 | if (stats.isFile()) {
|
298 | return hashFileAsObservable(input.pathObj.resolved).map(function (hash) {
|
299 | return {
|
300 | userInput: input.userInput,
|
301 | resolved: input.pathObj.resolved,
|
302 | hash: hash
|
303 | };
|
304 | });
|
305 | }
|
306 | return Rx.Observable.empty();
|
307 | });
|
308 | }
|
309 | function markHashes(newHashes, existingHashes) {
|
310 | var newHashPaths = newHashes.map(function (x) { return x.resolved; });
|
311 | var markedHashes = newHashes.map(function (newHash) {
|
312 | var match = existingHashes.filter(function (x) { return x.resolved === newHash.resolved; });
|
313 | newHash.changed = (function () {
|
314 | if (match.length) {
|
315 | return match[0].hash !== newHash.hash;
|
316 | }
|
317 | return true; // return true by default so that new entries always run
|
318 | })();
|
319 | return newHash;
|
320 | });
|
321 | var otherHashes = existingHashes.filter(function (hash) {
|
322 | return newHashPaths.indexOf(hash.resolved) === -1;
|
323 | });
|
324 | var output = otherHashes.concat(newHashes).filter(Boolean);
|
325 | return {
|
326 | output: output,
|
327 | markedHashes: markedHashes
|
328 | };
|
329 | }
|
330 | var binDirectoryExists = function (path) {
|
331 | return fs_1.existsSync(path)
|
332 | ? exports.Right(path)
|
333 | : exports.Left({ type: task_utils_1.InputErrorTypes.BinDirectoryNotFound });
|
334 | };
|
335 | var isDirectory = function (path) {
|
336 | return fs_2.statSync(path).isDirectory()
|
337 | ? exports.Right(path)
|
338 | : exports.Left({ type: task_utils_1.InputErrorTypes.BinPathNotADirectory });
|
339 | };
|
340 | var joinPath = function (path, cwd) { return exports.Right(path_2.join(cwd, path)); };
|
341 | exports.getBinLookup = function (path, cwd) {
|
342 | return joinPath(String(path), cwd)
|
343 | .chain(function (resolved) { return exports.Right(resolved)
|
344 | .chain(function (resolved) { return binDirectoryExists(resolved); })
|
345 | .chain(function (resolved) { return isDirectory(resolved); })
|
346 | .fold(function (error) {
|
347 | return {
|
348 | errors: [error],
|
349 | resolved: resolved,
|
350 | input: path
|
351 | };
|
352 | }, function (resolved) {
|
353 | return {
|
354 | errors: [],
|
355 | resolved: resolved,
|
356 | input: path
|
357 | };
|
358 | }); });
|
359 | };
|
360 | exports.getBinLookups = function (paths, cwd) {
|
361 | return exports.Right([].concat(paths).map(function (path) { return exports.getBinLookup(path, cwd); }))
|
362 | .chain(function (xs) {
|
363 | return {
|
364 | all: xs,
|
365 | valid: xs.filter(function (x) { return x.errors.length === 0; }),
|
366 | invalid: xs.filter(function (x) { return x.errors.length > 0; })
|
367 | };
|
368 | });
|
369 | };
|
370 | exports.Right = function (x) { return ({
|
371 | chain: function (f) { return f(x); },
|
372 | map: function (f) { return exports.Right(f(x)); },
|
373 | fold: function (f, g) { return g(x); },
|
374 | inspect: function () { return ("Right(" + x + ")"); }
|
375 | }); };
|
376 | exports.Left = function (x) { return ({
|
377 | chain: function (f) { return exports.Left(x); },
|
378 | map: function (f) { return exports.Left(x); },
|
379 | fold: function (f, g) { return f(x); },
|
380 | inspect: function () { return ("Left(" + x + ")"); }
|
381 | }); };
|
382 | exports.tryCatch = function (f) {
|
383 | try {
|
384 | return exports.Right(f());
|
385 | }
|
386 | catch (e) {
|
387 | return exports.Left(e);
|
388 | }
|
389 | };
|
390 | //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmlsZS51dGlscy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9maWxlLnV0aWxzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFDQSwyQkFBc0QsY0FBYyxDQUFDLENBQUE7QUFDckUsbUJBQXNELElBQUksQ0FBQyxDQUFBO0FBQzNELHFCQUF1QyxNQUFNLENBQUMsQ0FBQTtBQUc5QyxtQkFBdUIsSUFBSSxDQUFDLENBQUE7QUFDNUIscUJBQW1CLE1BQU0sQ0FBQyxDQUFBO0FBQzFCLG1CQUEwQixJQUFJLENBQUMsQ0FBQTtBQUMvQixJQUFPLEVBQUUsV0FBVyxJQUFJLENBQUMsQ0FBQztBQUMxQixxQkFBc0IsTUFBTSxDQUFDLENBQUE7QUFDN0IsbUJBQStCLElBQUksQ0FBQyxDQUFBO0FBQ3BDLHVCQUF5QixRQUFRLENBQUMsQ0FBQTtBQUNsQyxtQkFBMkIsSUFBSSxDQUFDLENBQUE7QUFFaEMsSUFBTSxFQUFFLEdBQUcsT0FBTyxDQUFDLFVBQVUsQ0FBQyxDQUFDO0FBQy9CLElBQU0sbUJBQW1CLEdBQUcsRUFBRSxDQUFDLFVBQVUsQ0FBQyxnQkFBZ0IsQ0FBQyxFQUFFLENBQUMsQ0FBQztBQUMvRCxJQUFNLG9CQUFvQixHQUFHLEVBQUUsQ0FBQyxVQUFVLENBQUMsZ0JBQWdCLENBQUMsUUFBUSxDQUFDLENBQUM7QUFDdEUsSUFBTSxpQkFBaUIsR0FBRyxFQUFFLENBQUMsVUFBVSxDQUFDLGdCQUFnQixDQUFDLFVBQUssQ0FBQyxDQUFDO0FBRWhFLElBQU0sQ0FBQyxHQUFHLE9BQU8sQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO0FBRXRDLDBDQUEwQztBQUMxQyxJQUFNLDJCQUEyQixHQUFHLENBQUMsS0FBSyxFQUFFLEtBQUssQ0FBQyxDQUFDO0FBdUJuRDs7O0dBR0c7QUFDSCxtQ0FBMEMsTUFBNkI7SUFDbkUsSUFBTSxrQkFBa0IsR0FBRyxDQUFDLGVBQWUsRUFBRSxhQUFhLEVBQUUsY0FBYyxFQUFFLGVBQWUsQ0FBQyxDQUFD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 |
\ | No newline at end of file |