UNPKG

12.7 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3var fs_extra_1 = require("fs-extra");
4var path_1 = require("path");
5var logger_1 = require("./logger/logger");
6var config_1 = require("./util/config");
7var Constants = require("./util/constants");
8var events_1 = require("./util/events");
9var glob_util_1 = require("./util/glob-util");
10var helpers_1 = require("./util/helpers");
11var watch_1 = require("./watch");
12var copyFilePathCache = new Map();
13var FILTER_OUT_DIRS_FOR_CLEAN = ['{{WWW}}', '{{BUILD}}'];
14function copy(context, configFile) {
15 configFile = config_1.getUserConfigFile(context, exports.taskInfo, configFile);
16 var logger = new logger_1.Logger('copy');
17 return copyWorker(context, configFile)
18 .then(function () {
19 logger.finish();
20 })
21 .catch(function (err) {
22 throw logger.fail(err);
23 });
24}
25exports.copy = copy;
26function copyWorker(context, configFile) {
27 var copyConfig = config_1.fillConfigDefaults(configFile, exports.taskInfo.defaultConfigFile);
28 var keys = Object.keys(copyConfig);
29 var directoriesToCreate = new Set();
30 var toCopyList = [];
31 return Promise.resolve().then(function () {
32 // for each entry, make sure each glob in the list of globs has had string replacement performed on it
33 cleanConfigContent(keys, copyConfig, context);
34 return getFilesPathsForConfig(keys, copyConfig);
35 }).then(function (resultMap) {
36 // sweet, we have the absolute path of the files in the glob, and the ability to get the relative path
37 // basically, we've got a stew goin'
38 return populateFileAndDirectoryInfo(resultMap, copyConfig, toCopyList, directoriesToCreate);
39 }).then(function () {
40 if (helpers_1.getBooleanPropertyValue(Constants.ENV_CLEAN_BEFORE_COPY)) {
41 cleanDirectories(context, directoriesToCreate);
42 }
43 }).then(function () {
44 // create the directories synchronously to avoid any disk locking issues
45 var directoryPathList = Array.from(directoriesToCreate);
46 for (var _i = 0, directoryPathList_1 = directoryPathList; _i < directoryPathList_1.length; _i++) {
47 var directoryPath = directoryPathList_1[_i];
48 fs_extra_1.mkdirpSync(directoryPath);
49 }
50 }).then(function () {
51 // sweet, the directories are created, so now let's stream the files
52 var promises = [];
53 var _loop_1 = function (file) {
54 cacheCopyData(file);
55 var promise = helpers_1.copyFileAsync(file.absoluteSourcePath, file.absoluteDestPath);
56 promise.then(function () {
57 logger_1.Logger.debug("Successfully copied " + file.absoluteSourcePath + " to " + file.absoluteDestPath);
58 }).catch(function (err) {
59 logger_1.Logger.warn("Failed to copy " + file.absoluteSourcePath + " to " + file.absoluteDestPath);
60 });
61 promises.push(promise);
62 };
63 for (var _i = 0, toCopyList_1 = toCopyList; _i < toCopyList_1.length; _i++) {
64 var file = toCopyList_1[_i];
65 _loop_1(file);
66 }
67 return Promise.all(promises);
68 });
69}
70exports.copyWorker = copyWorker;
71function copyUpdate(changedFiles, context) {
72 var logger = new logger_1.Logger('copy update');
73 var configFile = config_1.getUserConfigFile(context, exports.taskInfo, null);
74 var copyConfig = config_1.fillConfigDefaults(configFile, exports.taskInfo.defaultConfigFile);
75 var keys = Object.keys(copyConfig);
76 var directoriesToCreate = new Set();
77 var toCopyList = [];
78 return Promise.resolve().then(function () {
79 changedFiles.forEach(function (changedFile) { return logger_1.Logger.debug("copyUpdate, event: " + changedFile.event + ", path: " + changedFile.filePath); });
80 // for each entry, make sure each glob in the list of globs has had string replacement performed on it
81 cleanConfigContent(keys, copyConfig, context);
82 return getFilesPathsForConfig(keys, copyConfig);
83 }).then(function (resultMap) {
84 // sweet, we have the absolute path of the files in the glob, and the ability to get the relative path
85 // basically, we've got a stew goin'
86 return populateFileAndDirectoryInfo(resultMap, copyConfig, toCopyList, directoriesToCreate);
87 }).then(function () {
88 // first, process any deleted directories
89 var promises = [];
90 var directoryDeletions = changedFiles.filter(function (changedFile) { return changedFile.event === 'unlinkDir'; });
91 directoryDeletions.forEach(function (changedFile) { return promises.push(processRemoveDir(changedFile)); });
92 return Promise.all(promises);
93 }).then(function () {
94 // process any deleted files
95 var promises = [];
96 var fileDeletions = changedFiles.filter(function (changedFile) { return changedFile.event === 'unlink'; });
97 fileDeletions.forEach(function (changedFile) { return promises.push(processRemoveFile(changedFile)); });
98 return Promise.all(promises);
99 }).then(function () {
100 var promises = [];
101 var additions = changedFiles.filter(function (changedFile) { return changedFile.event === 'change' || changedFile.event === 'add' || changedFile.event === 'addDir'; });
102 additions.forEach(function (changedFile) {
103 var matchingItems = toCopyList.filter(function (toCopyEntry) { return toCopyEntry.absoluteSourcePath === changedFile.filePath; });
104 matchingItems.forEach(function (matchingItem) {
105 // create the directories first (if needed)
106 fs_extra_1.mkdirpSync(path_1.dirname(matchingItem.absoluteDestPath));
107 // cache the data and copy the files
108 cacheCopyData(matchingItem);
109 promises.push(helpers_1.copyFileAsync(matchingItem.absoluteSourcePath, matchingItem.absoluteDestPath));
110 events_1.emit(events_1.EventType.FileChange, additions);
111 });
112 });
113 return Promise.all(promises);
114 }).then(function () {
115 logger.finish('green', true);
116 logger_1.Logger.newLine();
117 }).catch(function (err) {
118 throw logger.fail(err);
119 });
120}
121exports.copyUpdate = copyUpdate;
122function cleanDirectories(context, directoriesToCreate) {
123 var filterOut = config_1.replacePathVars(context, FILTER_OUT_DIRS_FOR_CLEAN);
124 var directoryPathList = Array.from(directoriesToCreate);
125 // filter out any directories that we don't want to allow a clean on
126 var cleanableDirectories = directoryPathList.filter(function (directoryPath) {
127 for (var _i = 0, filterOut_1 = filterOut; _i < filterOut_1.length; _i++) {
128 var uncleanableDir = filterOut_1[_i];
129 if (uncleanableDir === directoryPath) {
130 return false;
131 }
132 }
133 return true;
134 });
135 return deleteDirectories(cleanableDirectories);
136}
137function deleteDirectories(directoryPaths) {
138 var promises = [];
139 for (var _i = 0, directoryPaths_1 = directoryPaths; _i < directoryPaths_1.length; _i++) {
140 var directoryPath = directoryPaths_1[_i];
141 promises.push(helpers_1.rimRafAsync(directoryPath));
142 }
143 return Promise.all(promises);
144}
145function processRemoveFile(changedFile) {
146 // delete any destination files that match the source file
147 var list = copyFilePathCache.get(changedFile.filePath) || [];
148 copyFilePathCache.delete(changedFile.filePath);
149 var promises = [];
150 var deletedFilePaths = [];
151 list.forEach(function (copiedFile) {
152 var promise = helpers_1.unlinkAsync(copiedFile.absoluteDestPath);
153 promises.push(promise);
154 promise.catch(function (err) {
155 if (err && err.message && err.message.indexOf('ENOENT') >= 0) {
156 logger_1.Logger.warn("Failed to delete " + copiedFile.absoluteDestPath + " because it doesn't exist");
157 return;
158 }
159 throw err;
160 });
161 deletedFilePaths.push(copiedFile.absoluteDestPath);
162 });
163 events_1.emit(events_1.EventType.FileDelete, deletedFilePaths);
164 return Promise.all(promises).catch(function (err) {
165 });
166}
167function processRemoveDir(changedFile) {
168 // remove any files from the cache where the dirname equals the provided path
169 var keysToRemove = [];
170 var directoriesToRemove = new Set();
171 copyFilePathCache.forEach(function (copiedFiles, filePath) {
172 if (path_1.dirname(filePath) === changedFile.filePath) {
173 keysToRemove.push(filePath);
174 copiedFiles.forEach(function (copiedFile) { return directoriesToRemove.add(path_1.dirname(copiedFile.absoluteDestPath)); });
175 }
176 });
177 keysToRemove.forEach(function (keyToRemove) { return copyFilePathCache.delete(keyToRemove); });
178 // the entries are removed from the cache, now just rim raf the directoryPath
179 var promises = [];
180 directoriesToRemove.forEach(function (directoryToRemove) {
181 promises.push(helpers_1.rimRafAsync(directoryToRemove));
182 });
183 events_1.emit(events_1.EventType.DirectoryDelete, Array.from(directoriesToRemove));
184 return Promise.all(promises);
185}
186function cacheCopyData(copyObject) {
187 var list = copyFilePathCache.get(copyObject.absoluteSourcePath);
188 if (!list) {
189 list = [];
190 }
191 list.push(copyObject);
192 copyFilePathCache.set(copyObject.absoluteSourcePath, list);
193}
194function getFilesPathsForConfig(copyConfigKeys, copyConfig) {
195 // execute the glob functions to determine what files match each glob
196 var srcToResultsMap = new Map();
197 var promises = [];
198 copyConfigKeys.forEach(function (key) {
199 var copyOptions = copyConfig[key];
200 if (copyOptions && copyOptions.src) {
201 var promise = glob_util_1.globAll(copyOptions.src);
202 promises.push(promise);
203 promise.then(function (globResultList) {
204 srcToResultsMap.set(key, globResultList);
205 });
206 }
207 });
208 return Promise.all(promises).then(function () {
209 return srcToResultsMap;
210 });
211}
212function populateFileAndDirectoryInfo(resultMap, copyConfig, toCopyList, directoriesToCreate) {
213 resultMap.forEach(function (globResults, dictionaryKey) {
214 globResults.forEach(function (globResult) {
215 // get the relative path from the of each file from the glob
216 var relativePath = path_1.relative(globResult.base, globResult.absolutePath);
217 // append the relative path to the dest
218 var destFileName = path_1.resolve(path_1.join(copyConfig[dictionaryKey].dest, relativePath));
219 // store the file information
220 toCopyList.push({
221 absoluteSourcePath: globResult.absolutePath,
222 absoluteDestPath: destFileName
223 });
224 var directoryToCreate = path_1.dirname(destFileName);
225 directoriesToCreate.add(directoryToCreate);
226 });
227 });
228}
229function cleanConfigContent(dictionaryKeys, copyConfig, context) {
230 dictionaryKeys.forEach(function (key) {
231 var copyOption = copyConfig[key];
232 if (copyOption && copyOption.src && copyOption.src.length) {
233 var cleanedUpSrc = config_1.replacePathVars(context, copyOption.src);
234 copyOption.src = cleanedUpSrc;
235 var cleanedUpDest = config_1.replacePathVars(context, copyOption.dest);
236 copyOption.dest = cleanedUpDest;
237 }
238 });
239}
240function copyConfigToWatchConfig(context) {
241 if (!context) {
242 context = config_1.generateContext(context);
243 }
244 var configFile = config_1.getUserConfigFile(context, exports.taskInfo, '');
245 var copyConfig = config_1.fillConfigDefaults(configFile, exports.taskInfo.defaultConfigFile);
246 var results = [];
247 for (var _i = 0, _a = Object.keys(copyConfig); _i < _a.length; _i++) {
248 var key = _a[_i];
249 if (copyConfig[key] && copyConfig[key].src) {
250 var list = glob_util_1.generateGlobTasks(copyConfig[key].src, {});
251 results = results.concat(list);
252 }
253 }
254 var paths = [];
255 var ignored = [];
256 for (var _b = 0, results_1 = results; _b < results_1.length; _b++) {
257 var result = results_1[_b];
258 paths.push(result.pattern);
259 if (result.opts && result.opts.ignore) {
260 ignored = ignored.concat(result.opts.ignore);
261 }
262 }
263 return {
264 paths: paths,
265 options: {
266 ignored: ignored
267 },
268 callback: watch_1.copyUpdate
269 };
270}
271exports.copyConfigToWatchConfig = copyConfigToWatchConfig;
272exports.taskInfo = {
273 fullArg: '--copy',
274 shortArg: '-y',
275 envVar: 'IONIC_COPY',
276 packageConfig: 'ionic_copy',
277 defaultConfigFile: 'copy.config'
278};