1 | ;
|
2 | var task_resolve_1 = require("./task.resolve");
|
3 | var _ = require("../lodash.custom");
|
4 | var Rx = require("rx");
|
5 | var Observable = Rx.Observable;
|
6 | var adaptors = require("./adaptors");
|
7 | var Immutable = require("immutable");
|
8 | var task_sequence_factories_1 = require("./task.sequence.factories");
|
9 | var task_runner_1 = require("./task.runner");
|
10 | var task_utils_1 = require("./task.utils");
|
11 | function createFlattenedSequence(tasks, trigger) {
|
12 | return flatten(tasks, []);
|
13 | function flatten(items, initial, options, viaName) {
|
14 | return items.reduce(function (all, task) {
|
15 | /**
|
16 | * If the current task has child tasks, we build a tree of
|
17 | * nested observables for it (a task with children cannot itself
|
18 | * be a task that should be run)
|
19 | */
|
20 | if (task.type === task_resolve_1.TaskTypes.TaskGroup || task.type === task_resolve_1.TaskTypes.ParentGroup) {
|
21 | /**
|
22 | * If we're looking at a group of tasks that was run
|
23 | * with sub-tasks, we need to resolve differently to
|
24 | * allow things such as parallel running to work as expected
|
25 | */
|
26 | if (task.subTasks.length && task.tasks.length) {
|
27 | /**
|
28 | * Build the list of tasks/groups
|
29 | * @type {Array}
|
30 | */
|
31 | var output = resolveGroupOfTasks(task, trigger.input);
|
32 | /**
|
33 | * Wrap as parallel group if this task has a runMode of 'parallel'
|
34 | */
|
35 | if (task.runMode === task_resolve_1.TaskRunModes.parallel) {
|
36 | return all.concat(task_sequence_factories_1.createSequenceParallelGroup({
|
37 | taskName: task.taskName,
|
38 | items: output,
|
39 | skipped: task.skipped
|
40 | }));
|
41 | }
|
42 | /**
|
43 | * Wrap as a series group if this task has a runMode of 'series'
|
44 | */
|
45 | if (task.runMode === task_resolve_1.TaskRunModes.series) {
|
46 | return all.concat(task_sequence_factories_1.createSequenceSeriesGroup({
|
47 | taskName: task.taskName,
|
48 | items: output,
|
49 | skipped: task.skipped
|
50 | }));
|
51 | }
|
52 | }
|
53 | /**
|
54 | * If the current task was marked as `parallel`, all immediate children
|
55 | * of (this task) will be run in `parallel`
|
56 | */
|
57 | if (task.runMode === task_resolve_1.TaskRunModes.parallel) {
|
58 | return all.concat(resolveGroup(task, task_sequence_factories_1.createSequenceParallelGroup));
|
59 | }
|
60 | /**
|
61 | * If the current task was marked as `series`, all immediate child tasks
|
62 | * will be queued and run in series - each waiting until the previous
|
63 | * one has completed
|
64 | */
|
65 | if (task.runMode === task_resolve_1.TaskRunModes.series) {
|
66 | return all.concat(resolveGroup(task, task_sequence_factories_1.createSequenceSeriesGroup));
|
67 | }
|
68 | }
|
69 | /**
|
70 | * At this point, we must be dealing with a task that should be run,
|
71 | * so we first check if it's an adaptor @ task first
|
72 | */
|
73 | if (task.type === task_resolve_1.TaskTypes.Adaptor) {
|
74 | return all.concat(getSequenceItemWithOptions(task, trigger, adaptors[task.adaptor].create(task, trigger), {}));
|
75 | }
|
76 | /**
|
77 | * Finally, if the does not have children tasks & is not an
|
78 | * adaptor task it must have at least 1 associated module
|
79 | * (or an inline function) so we can begin working with it
|
80 | * by first resolving the top-level options object for it.
|
81 | */
|
82 | var localOptions = _.assign({}, loadTopLevelOptions(task, trigger), options);
|
83 | /**
|
84 | * Decide where the callable function is coming from
|
85 | * (inline function, external task etc)
|
86 | * @type {CBFunction}
|
87 | */
|
88 | var callable = (function () {
|
89 | if (task.type === task_resolve_1.TaskTypes.InlineFunction) {
|
90 | return task.inlineFunctions[0];
|
91 | }
|
92 | return require(task.externalTasks[0].resolved);
|
93 | })();
|
94 | /**
|
95 | * Take the callable and create items with it + options
|
96 | */
|
97 | return all.concat(resolveFromFunction(task, callable, trigger, localOptions, viaName));
|
98 | }, initial);
|
99 | }
|
100 | /**
|
101 | * Resolve a group of tasks
|
102 | * @param task
|
103 | * @param groupCreatorFn
|
104 | * @param continueFn
|
105 | * @returns {any}
|
106 | */
|
107 | function resolveGroup(task, groupCreatorFn) {
|
108 | /**
|
109 | * If the group contains no subtasks
|
110 | */
|
111 | if (!task.subTasks.length) {
|
112 | /**
|
113 | * If a group has _default options,
|
114 | * but here no 'subTasks' were given, use the
|
115 | * default options always
|
116 | */
|
117 | var parentOptions = (function () {
|
118 | if (task.options._default !== undefined) {
|
119 | return _.merge({}, task.options._default, task.query, task.flags);
|
120 | }
|
121 | return task.options;
|
122 | })();
|
123 | /**
|
124 | * Here the group had no direct 'sub tasks', so just return the item
|
125 | */
|
126 | return [groupCreatorFn({
|
127 | taskName: task.taskName,
|
128 | items: flatten(task.tasks, [], parentOptions),
|
129 | skipped: task.skipped
|
130 | })];
|
131 | }
|
132 | /**
|
133 | * Use either subtasks directly, or if '*' was given, use
|
134 | * each key in the object to create a task
|
135 | */
|
136 | var lookupKeys = getLookupKeys(task.subTasks, task.options);
|
137 | /**
|
138 | * Now for each sub-task create a separate task item
|
139 | */
|
140 | return lookupKeys.map(function (subTaskName) {
|
141 | /**
|
142 | * When things like options, flags or query strings
|
143 | * were present on this task-group - pass them into the upcoming task instead
|
144 | * Order of presedence
|
145 | * flags -> query -> options -> shared
|
146 | */
|
147 | var taskOptions = _.merge({}, task.options._default, _.get(task.options, subTaskName, {}), task.query, task.flags);
|
148 | return groupCreatorFn({
|
149 | taskName: task.taskName,
|
150 | items: flatten(task.tasks, [], taskOptions, task.taskName + ":" + subTaskName),
|
151 | skipped: task.skipped,
|
152 | subTaskName: subTaskName
|
153 | });
|
154 | });
|
155 | }
|
156 | function resolveGroupOfTasks(task, input) {
|
157 | if (task.type === task_resolve_1.TaskTypes.ParentGroup) {
|
158 | var opts = _.merge({}, task.options._default, task.query, task.flags);
|
159 | return flatten(task.tasks, [], opts, task.taskName);
|
160 | }
|
161 | var lookupKeys = getLookupKeys(task.subTasks, task.options);
|
162 | return lookupKeys.reduce(function (acc, subTaskName) {
|
163 | var opts = _.merge({}, task.options._default, _.get(task.options, subTaskName, {}), _.get(input.options, [task.baseTaskName, subTaskName], {}), task.query, task.flags);
|
164 | return acc.concat(flatten(task.tasks, [], opts, task.taskName + ":" + subTaskName));
|
165 | }, []);
|
166 | }
|
167 | }
|
168 | exports.createFlattenedSequence = createFlattenedSequence;
|
169 | function resolveFromFunction(task, callable, trigger, localOptions, viaName) {
|
170 | /**
|
171 | * If the current item has no sub-tasks, we can return early
|
172 | * with a simple task creation using the global options
|
173 | *
|
174 | * eg:
|
175 | * $ crossbow run sass
|
176 | *
|
177 | * options:
|
178 | * sass:
|
179 | * input: "core.scss"
|
180 | * output: "core.css"
|
181 | *
|
182 | * -> `sass` task will be run with the options
|
183 | * {input: "core.scss", output: "core.css"}
|
184 | */
|
185 | if (!task.subTasks.length) {
|
186 | return getSequenceItemWithOptions(task, trigger, callable, localOptions, viaName);
|
187 | }
|
188 | /**
|
189 | * Get lookup keys for this task
|
190 | */
|
191 | var lookupKeys = getLookupKeys(task.subTasks, localOptions);
|
192 | /**
|
193 | * Now generate 1 task per lookup key.
|
194 | */
|
195 | var group = lookupKeys.reduce(function (acc, optionKey) {
|
196 | /**
|
197 | * `optionKey` here will be a string that represented the subTask
|
198 | * name, so we use that to try and find a child key
|
199 | * in the options that matched it.
|
200 | * */
|
201 | var currentOptionObject = _.merge({}, localOptions._default, _.get(localOptions, optionKey));
|
202 | var sequenceItems = getSequenceItemWithOptions(task, trigger, callable, currentOptionObject, optionKey)
|
203 | .map(function (seqItem) {
|
204 | seqItem.subTaskName = optionKey;
|
205 | return seqItem;
|
206 | });
|
207 | return acc.concat(sequenceItems);
|
208 | }, []);
|
209 | /**
|
210 | * Don't create a 'group' if we're only talking about 1 item
|
211 | */
|
212 | if (group.length === 1) {
|
213 | return group;
|
214 | }
|
215 | if (task.runMode === task_resolve_1.TaskRunModes.parallel) {
|
216 | return [task_sequence_factories_1.createSequenceParallelGroup({
|
217 | taskName: task.taskName,
|
218 | items: group,
|
219 | skipped: task.skipped
|
220 | })];
|
221 | }
|
222 | /**
|
223 | * If the current task was marked as `series`, all immediate child tasks
|
224 | * will be queued and run in series - each waiting until the previous
|
225 | * one has completed
|
226 | */
|
227 | if (task.runMode === task_resolve_1.TaskRunModes.series) {
|
228 | return [task_sequence_factories_1.createSequenceSeriesGroup({
|
229 | taskName: task.taskName,
|
230 | items: group,
|
231 | skipped: task.skipped
|
232 | })];
|
233 | }
|
234 | }
|
235 | function getSequenceItemWithOptions(task, trigger, imported, options, viaName) {
|
236 | /**
|
237 | * Merge incoming options with query + flags
|
238 | * eg:
|
239 | * $ sass?input=css/core.css --production
|
240 | * -> sass
|
241 | * input: css/core.css
|
242 | * production: true
|
243 | */
|
244 | var mergedOptionsWithQuery = _.merge({}, options, task.options, task.query, task.flags);
|
245 | /**
|
246 | * If the module did not export a function, but has a 'tasks'
|
247 | * property that is an array, use each function from it
|
248 | * eg:
|
249 | * module.exports.tasks = [sass, cssmin, version-rev]
|
250 | */
|
251 | if (imported.tasks && Array.isArray(imported.tasks)) {
|
252 | return imported.tasks.map(function (importedFn, i) {
|
253 | return task_sequence_factories_1.createSequenceTaskItem({
|
254 | fnName: getFunctionName(imported, i + 1),
|
255 | factory: importedFn,
|
256 | task: task,
|
257 | options: mergedOptionsWithQuery,
|
258 | viaName: viaName
|
259 | });
|
260 | });
|
261 | }
|
262 | /**
|
263 | * If the module exported a function, use that as the factory
|
264 | * and return a single task for it.
|
265 | * eg:
|
266 | * module.exports = function runSass() {}
|
267 | */
|
268 | if (typeof imported === "function") {
|
269 | return [task_sequence_factories_1.createSequenceTaskItem({
|
270 | fnName: getFunctionName(imported, 0),
|
271 | factory: imported,
|
272 | task: task,
|
273 | options: mergedOptionsWithQuery,
|
274 | viaName: viaName
|
275 | })];
|
276 | }
|
277 | }
|
278 | /**
|
279 | * For reporting purposes, try to 'name' a function
|
280 | */
|
281 | function getFunctionName(fn, count) {
|
282 | if (count === void 0) { count = 0; }
|
283 | if (fn.name === undefined) {
|
284 | return "Anonymous Function " + count;
|
285 | }
|
286 | return fn.name;
|
287 | }
|
288 | /**
|
289 | * ******************
|
290 | * Where the **--~~Magic~~--** happens!!!
|
291 | * ******************
|
292 | *
|
293 | * Creating a task runner in crossbow is really about
|
294 | * wrapping the process of running the tasks in a way
|
295 | * that allows comprehensive logging/reporting
|
296 | *
|
297 | * Series & Parallel have different semantics and are
|
298 | * therefor handled separately.
|
299 | *
|
300 | * Note that everything here is completely lazy and
|
301 | * nothing will be executed until a user calls subscribe
|
302 | */
|
303 | function createRunner(items, trigger) {
|
304 | return {
|
305 | sequence: items,
|
306 | series: function (ctx) {
|
307 | if (!ctx)
|
308 | ctx = Immutable.Map({});
|
309 | var flattened = createObservableTree(items, [], false, ctx);
|
310 | var run = Observable
|
311 | .from(flattened)
|
312 | .concatAll()
|
313 | .catch(function (x) { return Rx.Observable.empty(); });
|
314 | return run;
|
315 | },
|
316 | parallel: function (ctx) {
|
317 | if (!ctx)
|
318 | ctx = Immutable.Map({});
|
319 | var flattened = createObservableTree(items, [], true, ctx);
|
320 | var run = Observable.from(flattened).mergeAll();
|
321 | return run;
|
322 | }
|
323 | };
|
324 | /**
|
325 | * Any task in 'Parallel' run mode that throws an
|
326 | * error should not adversely affect sibling tasks
|
327 | */
|
328 | function shouldCatch(trigger) {
|
329 | return trigger.config.runMode === task_resolve_1.TaskRunModes.parallel;
|
330 | }
|
331 | /**
|
332 | * Create a nested tree of Observables that can contain tasks
|
333 | * alongside parallel/series groups. To understand how this works
|
334 | * you can think of the following to be an accurate representation of
|
335 | * what this function produces:
|
336 | *
|
337 | * const out = [
|
338 | Observable.concat(
|
339 | task1(),
|
340 | task2()
|
341 | ),
|
342 | Observable.concat(
|
343 | task3(),
|
344 | task4(),
|
345 | Observable.concat(
|
346 | task5(),
|
347 | task6(),
|
348 | task7()
|
349 | )
|
350 | )
|
351 | ];
|
352 | *
|
353 | */
|
354 | function createObservableTree(items, initial, addCatch, ctx) {
|
355 | if (addCatch === void 0) { addCatch = false; }
|
356 | return items.reduce(function (all, item) {
|
357 | var output;
|
358 | /**
|
359 | * If the current task was marked as `parallel`, all immediate children
|
360 | * of (this task) will be run in `parallel`
|
361 | */
|
362 | if (item.type === task_sequence_factories_1.SequenceItemTypes.ParallelGroup) {
|
363 | output = Observable.merge(createObservableTree(item.items, [], shouldCatch(trigger), ctx));
|
364 | }
|
365 | /**
|
366 | * If the current task was marked as `series`, all immediate child tasks
|
367 | * will be queued and run in series - each waiting until the previous
|
368 | * one has completed
|
369 | */
|
370 | if (item.type === task_sequence_factories_1.SequenceItemTypes.SeriesGroup) {
|
371 | output = Observable.concat(createObservableTree(item.items, [], false, ctx));
|
372 | }
|
373 | /**
|
374 | * Finally is item is a task, create an observable for it.
|
375 | */
|
376 | if (item.type === task_sequence_factories_1.SequenceItemTypes.Task && item.factory) {
|
377 | output = task_runner_1.createObservableFromSequenceItem(item, trigger, ctx);
|
378 | }
|
379 | /**
|
380 | * Should we add a catch clause to this item to enable
|
381 | * siblings to continue when a task errors
|
382 | */
|
383 | if (addCatch || !trigger.config.fail) {
|
384 | return all.concat(output.catch(function (x) { return Rx.Observable.empty(); }));
|
385 | }
|
386 | return all.concat(output);
|
387 | }, initial);
|
388 | }
|
389 | }
|
390 | exports.createRunner = createRunner;
|
391 | /**
|
392 | * From user input, try to locate a options object
|
393 | */
|
394 | function loadTopLevelOptions(task, trigger) {
|
395 | // todo - more robust way of matching options -> tasks
|
396 | var fullMatch = _.get(trigger.input.options, [task.taskName]);
|
397 | if (fullMatch !== undefined) {
|
398 | /**
|
399 | * If this item was given as top-level + options
|
400 | * just return the options here
|
401 | */
|
402 | if (fullMatch.options && fullMatch.tasks) {
|
403 | return fullMatch.options;
|
404 | }
|
405 | /**
|
406 | * If this task has a _default key, don't pass
|
407 | * all the options in, just pass the stuff under default
|
408 | */
|
409 | if (task.subTasks.length === 0 && fullMatch._default !== undefined) {
|
410 | return fullMatch._default;
|
411 | }
|
412 | return fullMatch;
|
413 | }
|
414 | if (task_utils_1.isInternal(task.rawInput)) {
|
415 | var lookup = task.taskName.replace(/(.+?)_internal_fn_\d{0,10}/, "");
|
416 | var fromInternal = _.get(trigger.input.options, [lookup]);
|
417 | if (fromInternal !== undefined) {
|
418 | return fromInternal;
|
419 | }
|
420 | }
|
421 | return {};
|
422 | }
|
423 | /**
|
424 | * After a bunch of tasks have run, we need to link up task-ended reports
|
425 | * with their original position in the sequence. This will allow us to
|
426 | * reconstruct the task render-tree but also show any tasks that errored
|
427 | * or did not complete
|
428 | * @param sequence
|
429 | * @param reports
|
430 | * @returns {*}
|
431 | */
|
432 | function decorateSequenceWithReports(sequence, reports) {
|
433 | return addMany(sequence, []);
|
434 | function addMany(sequence, initial) {
|
435 | return sequence.reduce(function (all, item) {
|
436 | var c = _.assign({}, item);
|
437 | if (item.type === task_sequence_factories_1.SequenceItemTypes.Task) {
|
438 | c.stats = getMergedStats(item, reports);
|
439 | return all.concat(c);
|
440 | }
|
441 | else {
|
442 | c.items = addMany(item.items, []);
|
443 | return all.concat(c);
|
444 | }
|
445 | }, initial);
|
446 | }
|
447 | }
|
448 | exports.decorateSequenceWithReports = decorateSequenceWithReports;
|
449 | /**
|
450 | * Look at every item in the sequence tree and count how many
|
451 | * error have occured
|
452 | */
|
453 | function countSequenceErrors(items) {
|
454 | return items.reduce(function (acc, item) {
|
455 | if (item.type === task_sequence_factories_1.SequenceItemTypes.Task) {
|
456 | var errors = _.get(item, "stats.errors", []);
|
457 | if (errors.length) {
|
458 | return acc + errors.length;
|
459 | }
|
460 | return acc;
|
461 | }
|
462 | return acc + countSequenceErrors(item.items);
|
463 | }, 0);
|
464 | }
|
465 | exports.countSequenceErrors = countSequenceErrors;
|
466 | function collectSkippedTasks(items, initial) {
|
467 | return items.reduce(function (acc, item) {
|
468 | if (item.type === task_sequence_factories_1.SequenceItemTypes.Task) {
|
469 | if (item.stats.skipped) {
|
470 | return acc.concat(item);
|
471 | }
|
472 | return acc;
|
473 | }
|
474 | return acc.concat(collectSkippedTasks(item.items, []));
|
475 | }, initial);
|
476 | }
|
477 | exports.collectSkippedTasks = collectSkippedTasks;
|
478 | function collectRunnableTasks(items, initial) {
|
479 | return items.reduce(function (acc, item) {
|
480 | if (item.type === task_sequence_factories_1.SequenceItemTypes.Task) {
|
481 | return acc.concat(item);
|
482 | }
|
483 | return acc.concat(collectRunnableTasks(item.items, []));
|
484 | }, initial);
|
485 | }
|
486 | exports.collectRunnableTasks = collectRunnableTasks;
|
487 | /**
|
488 | * Look at the reports array to find stats linked to a
|
489 | * given task
|
490 | */
|
491 | function getMergedStats(item, reports) {
|
492 | var match = reports.filter(function (report) {
|
493 | return report.item.seqUID === item.seqUID;
|
494 | });
|
495 | var start = match.filter(function (x) { return x.type === task_runner_1.TaskReportType.start; })[0];
|
496 | var error = match.filter(function (x) { return x.type === task_runner_1.TaskReportType.error; })[0];
|
497 | var end = match.filter(function (x) { return x.type === task_runner_1.TaskReportType.end; })[0];
|
498 | if (start && end) {
|
499 | return _.assign({}, start.stats, end.stats);
|
500 | }
|
501 | if (start && error) {
|
502 | var duration = error.stats.endTime - start.stats.startTime;
|
503 | return _.assign({}, start.stats, error.stats, { duration: duration });
|
504 | }
|
505 | if (start) {
|
506 | return _.assign({}, start.stats);
|
507 | }
|
508 | return { item: item, errors: [] };
|
509 | }
|
510 | /**
|
511 | * When we know a task has `subTasks` we need to check if
|
512 | * if the first entry in the subTasks array is a `*` - then
|
513 | * the user wants to run all tasks under this options
|
514 | * object. So we need to get the keys and use each one as a lookup
|
515 | * on the local options. (minus any excluded tasks)
|
516 | *
|
517 | * eg:
|
518 | * $ crossbow run sass:*
|
519 | *
|
520 | * options:
|
521 | * sass:
|
522 | * site: {input: "core.scss"}
|
523 | * debug: {input: "debug.scss"}
|
524 | *
|
525 | * lookupKeys = ['site', 'debug']
|
526 | */
|
527 | var blacklistedSubTaskNames = ["_default"];
|
528 | function getLookupKeys(subTasks, topLevelObject) {
|
529 | if (subTasks[0] === "*") {
|
530 | return Object.keys(topLevelObject)
|
531 | .filter(function (x) { return blacklistedSubTaskNames.indexOf(x) === -1; });
|
532 | }
|
533 | return subTasks;
|
534 | }
|
535 | //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGFzay5zZXF1ZW5jZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy90YXNrLnNlcXVlbmNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQSw2QkFBc0MsZ0JBQWdCLENBQUMsQ0FBQTtBQUN2RCxJQUFNLENBQUMsR0FBRyxPQUFPLENBQUMsa0JBQWtCLENBQUMsQ0FBQztBQUN0QyxJQUFNLEVBQUUsR0FBRyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUM7QUFDekIsSUFBTSxVQUFVLEdBQUcsRUFBRSxDQUFDLFVBQVUsQ0FBQztBQUVqQyxJQUFZLFFBQVEsV0FBTSxZQUFZLENBQUMsQ0FBQTtBQUN2QyxJQUFPLFNBQVMsV0FBVyxXQUFXLENBQUMsQ0FBQztBQUl4Qyx3Q0FPTywyQkFBMkIsQ0FBQyxDQUFBO0FBRW5DLDRCQUErRCxlQUFlLENBQUMsQ0FBQTtBQUUvRSwyQkFBeUIsY0FBYyxDQUFDLENBQUE7QUFFeEMsaUNBQXdDLEtBQWEsRUFBRSxPQUF1QjtJQUUxRSxNQUFNLENBQUMsT0FBTyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsQ0FBQztJQUUxQixpQkFBaUIsS0FBYSxFQUFFLE9BQXVCLEVBQUUsT0FBUSxFQUFFLE9BQVE7UUFFdkUsTUFBTSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsVUFBQyxHQUFHLEVBQUUsSUFBVTtZQUVoQzs7OztlQUlHO1lBQ0gsRUFBRSxDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksS0FBSyx3QkFBUyxDQUFDLFNBQVMsSUFBSSxJQUFJLENBQUMsSUFBSSxLQUFLLHdCQUFTLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQztnQkFFM0U7Ozs7bUJBSUc7Z0JBQ0gsRUFBRSxDQUFDLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxNQUFNLElBQUksSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDO29CQUU1Qzs7O3VCQUdHO29CQUNILElBQU0sTUFBTSxHQUFHLG1CQUFtQixD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 |
\ | No newline at end of file |