1 | "use strict";
|
2 | var __importDefault = (this && this.__importDefault) || function (mod) {
|
3 | return (mod && mod.__esModule) ? mod : { "default": mod };
|
4 | };
|
5 | Object.defineProperty(exports, "__esModule", { value: true });
|
6 | const broccoli_plugin_1 = __importDefault(require("broccoli-plugin"));
|
7 | const path_1 = require("path");
|
8 | const walk_sync_1 = __importDefault(require("walk-sync"));
|
9 | const fs_extra_1 = require("fs-extra");
|
10 | const fs_tree_diff_1 = __importDefault(require("fs-tree-diff"));
|
11 | const symlink_or_copy_1 = __importDefault(require("symlink-or-copy"));
|
12 | const uniqBy_1 = __importDefault(require("lodash/uniqBy"));
|
13 | const source_map_url_1 = require("./source-map-url");
|
14 | class Append extends broccoli_plugin_1.default {
|
15 | constructor(upstreamTree, appendedTree, options) {
|
16 | super([upstreamTree, appendedTree], {
|
17 | annotation: 'ember-auto-import-analyzer',
|
18 | persistentOutput: true
|
19 | });
|
20 | this.previousUpstreamTree = new fs_tree_diff_1.default();
|
21 | this.previousAppendedTree = new fs_tree_diff_1.default();
|
22 |
|
23 |
|
24 | let reverseMappings = new Map();
|
25 | for (let [key, map] of options.mappings.entries()) {
|
26 | for (let value of map.values()) {
|
27 | reverseMappings.set(value, key);
|
28 | }
|
29 | }
|
30 | this.mappings = options.mappings;
|
31 | this.reverseMappings = reverseMappings;
|
32 | this.passthrough = options.passthrough;
|
33 | }
|
34 | get upstreamDir() {
|
35 | return this.inputPaths[0];
|
36 | }
|
37 | get appendedDir() {
|
38 | return this.inputPaths[1];
|
39 | }
|
40 |
|
41 |
|
42 | diffAppendedTree() {
|
43 | let changed = new Set();
|
44 | let { patchset, passthroughEntries } = this.appendedPatchset();
|
45 | for (let [, relativePath] of patchset) {
|
46 | let match = findByPrefix(relativePath, this.mappings);
|
47 | if (match) {
|
48 | let ext = path_1.extname(relativePath).slice(1);
|
49 | if (match.mapsTo.has(ext)) {
|
50 | changed.add(match.mapsTo.get(ext));
|
51 | }
|
52 | }
|
53 | }
|
54 | return { needsUpdate: changed, passthroughEntries };
|
55 | }
|
56 | build() {
|
57 |
|
58 |
|
59 | let { needsUpdate, passthroughEntries } = this.diffAppendedTree();
|
60 |
|
61 | for (let [operation, relativePath, entry] of this.upstreamPatchset(passthroughEntries)) {
|
62 | let outputPath = path_1.join(this.outputPath, relativePath);
|
63 | switch (operation) {
|
64 | case 'unlink':
|
65 | fs_extra_1.unlinkSync(outputPath);
|
66 | break;
|
67 | case 'rmdir':
|
68 | fs_extra_1.rmdirSync(outputPath);
|
69 | break;
|
70 | case 'mkdir':
|
71 | fs_extra_1.mkdirSync(outputPath);
|
72 | break;
|
73 | case 'change':
|
74 | fs_extra_1.removeSync(outputPath);
|
75 |
|
76 | case 'create':
|
77 | if (this.reverseMappings.has(relativePath)) {
|
78 |
|
79 |
|
80 | this.handleAppend(relativePath);
|
81 |
|
82 | needsUpdate.delete(relativePath);
|
83 | }
|
84 | else {
|
85 | if (isPassthrough(entry)) {
|
86 | symlink_or_copy_1.default.sync(path_1.join(this.appendedDir, entry.originalRelativePath), outputPath);
|
87 | }
|
88 | else {
|
89 | symlink_or_copy_1.default.sync(path_1.join(this.upstreamDir, relativePath), outputPath);
|
90 | }
|
91 | }
|
92 | }
|
93 | }
|
94 |
|
95 |
|
96 |
|
97 | for (let relativePath of needsUpdate.values()) {
|
98 | this.handleAppend(relativePath);
|
99 | }
|
100 | }
|
101 | upstreamPatchset(passthroughEntries) {
|
102 | let input = walk_sync_1.default.entries(this.upstreamDir).concat(passthroughEntries);
|
103 |
|
104 | input.sort(compareByRelativePath);
|
105 | input = uniqBy_1.default(input, e => e.relativePath);
|
106 | let previous = this.previousUpstreamTree;
|
107 | let next = (this.previousUpstreamTree = fs_tree_diff_1.default.fromEntries(input));
|
108 | return previous.calculatePatch(next);
|
109 | }
|
110 | appendedPatchset() {
|
111 | let input = walk_sync_1.default.entries(this.appendedDir);
|
112 | let passthroughEntries = input
|
113 | .map(e => {
|
114 | let match = findByPrefix(e.relativePath, this.passthrough);
|
115 | if (match) {
|
116 | let o = Object.create(e);
|
117 | o.relativePath = e.relativePath.replace(new RegExp('^' + match.prefix), match.mapsTo);
|
118 | o.isPassthrough = true;
|
119 | o.originalRelativePath = e.relativePath;
|
120 | return o;
|
121 | }
|
122 | }).filter(e => e && e.relativePath !== './');
|
123 | let previous = this.previousAppendedTree;
|
124 | let next = (this.previousAppendedTree = fs_tree_diff_1.default.fromEntries(input));
|
125 | return { patchset: previous.calculatePatch(next), passthroughEntries };
|
126 | }
|
127 | handleAppend(relativePath) {
|
128 | let upstreamPath = path_1.join(this.upstreamDir, relativePath);
|
129 | let outputPath = path_1.join(this.outputPath, relativePath);
|
130 | let ext = path_1.extname(relativePath);
|
131 | if (!fs_extra_1.existsSync(upstreamPath)) {
|
132 | fs_extra_1.removeSync(outputPath);
|
133 | return;
|
134 | }
|
135 | let sourceDir = path_1.join(this.appendedDir, this.reverseMappings.get(relativePath));
|
136 | if (!fs_extra_1.existsSync(sourceDir)) {
|
137 | symlink_or_copy_1.default.sync(upstreamPath, outputPath);
|
138 | return;
|
139 | }
|
140 | let appendedContent = fs_extra_1.readdirSync(sourceDir).map(name => {
|
141 | if (name.endsWith(ext)) {
|
142 | return fs_extra_1.readFileSync(path_1.join(sourceDir, name), 'utf8');
|
143 | }
|
144 | }).filter(Boolean).join(";\n");
|
145 | let upstreamContent = fs_extra_1.readFileSync(upstreamPath, 'utf8');
|
146 | if (appendedContent.length > 0) {
|
147 | upstreamContent = source_map_url_1.insertBefore(upstreamContent, ";\n" + appendedContent);
|
148 | }
|
149 | fs_extra_1.writeFileSync(outputPath, upstreamContent, 'utf8');
|
150 | }
|
151 | }
|
152 | exports.default = Append;
|
153 | function compareByRelativePath(entryA, entryB) {
|
154 | let pathA = entryA.relativePath;
|
155 | let pathB = entryB.relativePath;
|
156 | if (pathA < pathB) {
|
157 | return -1;
|
158 | }
|
159 | else if (pathA > pathB) {
|
160 | return 1;
|
161 | }
|
162 | return 0;
|
163 | }
|
164 | function isPassthrough(entry) {
|
165 | return entry.isPassthrough;
|
166 | }
|
167 | function findByPrefix(path, map) {
|
168 | let parts = path.split('/');
|
169 | for (let i = 1; i < parts.length; i++) {
|
170 | let candidate = parts.slice(0, i).join('/');
|
171 | if (map.has(candidate)) {
|
172 | return {
|
173 | prefix: candidate,
|
174 | mapsTo: map.get(candidate)
|
175 | };
|
176 | }
|
177 | }
|
178 | }
|
179 |
|
\ | No newline at end of file |