1 | "use strict";
|
2 | var __assign = (this && this.__assign) || function () {
|
3 | __assign = Object.assign || function(t) {
|
4 | for (var s, i = 1, n = arguments.length; i < n; i++) {
|
5 | s = arguments[i];
|
6 | for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
7 | t[p] = s[p];
|
8 | }
|
9 | return t;
|
10 | };
|
11 | return __assign.apply(this, arguments);
|
12 | };
|
13 | Object.defineProperty(exports, "__esModule", { value: true });
|
14 | var Fs = require("fs-extra");
|
15 | var Path = require("path");
|
16 | var ReadlineSync = require("readline-sync");
|
17 | var semver = require("semver");
|
18 | var Tmp = require("tmp");
|
19 | var git_1 = require("./git");
|
20 | var paths_1 = require("./paths");
|
21 | var release_1 = require("./release");
|
22 | var submodule_1 = require("./submodule");
|
23 | var utils_1 = require("./utils");
|
24 | var defaultDumpFileName = 'tutorial.json';
|
25 | var headEnd = '[//]: # (head-end)\n';
|
26 | var footStart = '[//]: # (foot-start)\n';
|
27 |
|
28 |
|
29 | function dumpProject(out, options) {
|
30 | if (out === void 0) { out = utils_1.Utils.cwd(); }
|
31 | if (options === void 0) { options = {}; }
|
32 | if (out instanceof Object && !(out instanceof String)) {
|
33 | options = out;
|
34 | out = utils_1.Utils.cwd();
|
35 | }
|
36 | options = __assign({ filter: options.filter, reject: options.reject }, options);
|
37 |
|
38 | out = Path.resolve(utils_1.Utils.cwd(), out);
|
39 |
|
40 | if (utils_1.Utils.exists(out, 'dir')) {
|
41 | out = Path.join(out, defaultDumpFileName);
|
42 | }
|
43 | if (utils_1.Utils.exists(out, 'file')) {
|
44 | options.override = options.override || ReadlineSync.keyInYN([
|
45 | 'Output path already exists.',
|
46 | 'Would you like to override it and continue?',
|
47 | ].join('\n'));
|
48 | if (!options.override) {
|
49 | return;
|
50 | }
|
51 | }
|
52 | console.log();
|
53 | console.log("Dumping into " + out + "...");
|
54 | console.log();
|
55 |
|
56 |
|
57 |
|
58 | submodule_1.Submodule.list().forEach(function (submodule) {
|
59 | submodule_1.Submodule.update(submodule);
|
60 | });
|
61 |
|
62 | Fs.ensureFileSync(out);
|
63 |
|
64 | var tags = git_1.Git([
|
65 | 'log', '--tags', '--simplify-by-decoration', '--pretty=format:%ci %d'
|
66 | ]).split('\n')
|
67 | .filter(Boolean)
|
68 | .map(function (line) {
|
69 | return line.match(/^([^(]+) \(.*tag: ([^@]+@\d+\.\d+\.\d+).*\)$/) ||
|
70 | line.match(/^([^(]+) \(.*tag: ([^@]+@next).*\)$/);
|
71 | })
|
72 | .filter(Boolean)
|
73 | .map(function (_a) {
|
74 | var str = _a[0], date = _a[1], name = _a[2];
|
75 | return ({
|
76 | date: date,
|
77 | name: name,
|
78 | });
|
79 | })
|
80 | .sort(function (a, b) {
|
81 | return new Date(a.date) > new Date(b.date) ? -1 : 1;
|
82 | });
|
83 | var branchNames = tags
|
84 | .map(function (tag) {
|
85 | return tag.name.split('@')[0];
|
86 | })
|
87 | .reduce(function (prev, branchName) {
|
88 | if (!prev.includes(branchName)) {
|
89 | prev.push(branchName);
|
90 | }
|
91 | return prev;
|
92 | }, []);
|
93 | if (options.filter) {
|
94 | branchNames = branchNames.filter(function (branchName) {
|
95 | return options.filter.includes(branchName);
|
96 | });
|
97 | }
|
98 | if (options.reject) {
|
99 | branchNames = branchNames.filter(function (branchName) {
|
100 | return !options.reject.includes(branchName);
|
101 | });
|
102 | }
|
103 | var pack = Fs.readJsonSync(paths_1.Paths.npm.package);
|
104 |
|
105 |
|
106 | var repoUrl = (typeof pack.repository === 'string' ? pack.repository :
|
107 | typeof pack.repository === 'object' ? pack.repository.url :
|
108 | '').replace(/\.git$/, '');
|
109 | var dump = branchNames.map(function (branchName) {
|
110 | var historyBranchName = branchName + "-history";
|
111 |
|
112 | try {
|
113 | git_1.Git(['rev-parse', historyBranchName]);
|
114 |
|
115 | }
|
116 | catch (e) {
|
117 | git_1.Git.print(['branch', '--track', historyBranchName, "remotes/origin/" + historyBranchName]);
|
118 | }
|
119 |
|
120 | var releaseTags = tags
|
121 | .filter(function (tag) {
|
122 | return tag.name.match(branchName);
|
123 | })
|
124 | .map(function (tag) { return ({
|
125 | date: tag.date,
|
126 | version: tag.name.split('@').pop(),
|
127 | }); });
|
128 | var releases = releaseTags.map(function (releaseTag, releaseIndex) {
|
129 | var prevReleaseTag = releaseTags[releaseIndex + 1] || {};
|
130 | var tagName = branchName + "@" + releaseTag.version;
|
131 | var tagRevision = git_1.Git(['rev-parse', tagName]);
|
132 | var historyRevision = git_1.Git([
|
133 | 'log', historyBranchName, "--grep=^" + tagName + ":", '--format=%H',
|
134 | ]).split('\n')
|
135 | .filter(Boolean)
|
136 | .pop();
|
137 |
|
138 | var changesDiff = release_1.Release.diff(prevReleaseTag.version, releaseTag.version, null, {
|
139 | branch: branchName,
|
140 | pipe: true
|
141 | });
|
142 | var manuals = Fs
|
143 | .readdirSync(paths_1.Paths.manuals.views)
|
144 |
|
145 |
|
146 |
|
147 | .filter(function (fileName) { return /\.md$/.test(fileName); })
|
148 | .sort(utils_1.Utils.naturalSort)
|
149 | .map(function (manualName, stepIndex) {
|
150 | var format = '%H %s';
|
151 | var stepLog;
|
152 | var manualPath;
|
153 |
|
154 | if (stepIndex) {
|
155 | manualPath = Path.resolve(paths_1.Paths.manuals.views, manualName);
|
156 | stepLog = git_1.Git([
|
157 | 'log', tagRevision, "--grep=^Step " + stepIndex + ":", "--format=" + format,
|
158 | ]);
|
159 | }
|
160 | else {
|
161 | manualPath = paths_1.Paths.readme;
|
162 | stepLog = git_1.Git([
|
163 | 'log', git_1.Git.rootHash(tagRevision), "--format=" + format,
|
164 | ]);
|
165 | }
|
166 | manualPath = Path.relative(utils_1.Utils.cwd(), manualPath);
|
167 | stepLog = stepLog.split(' ');
|
168 | var stepRevision = stepLog.shift();
|
169 | var manualTitle = stepLog.join(' ');
|
170 | var stepPack = JSON.parse(git_1.Git(['show', stepRevision + ":package.json"]));
|
171 | var keywords = stepPack.keywords || [];
|
172 |
|
173 |
|
174 | var manualView = git_1.Git(['show', stepRevision + ":" + manualPath]);
|
175 | if (manualView.includes(headEnd)) {
|
176 | manualView = manualView
|
177 | .split(headEnd)
|
178 | .slice(1)
|
179 | .join(headEnd);
|
180 | }
|
181 | if (manualView.includes(footStart)) {
|
182 | manualView = manualView
|
183 | .split(footStart)
|
184 | .slice(0, -1)
|
185 | .join(footStart);
|
186 | }
|
187 | manualView = manualView.trim();
|
188 | return {
|
189 | manualTitle: manualTitle,
|
190 | stepRevision: stepRevision,
|
191 | manualView: manualView,
|
192 | keywords: keywords
|
193 | };
|
194 | });
|
195 | return {
|
196 | releaseVersion: releaseTag.version,
|
197 | releaseDate: releaseTag.date,
|
198 | tagName: tagName,
|
199 | tagRevision: tagRevision,
|
200 | historyRevision: historyRevision,
|
201 | changesDiff: changesDiff,
|
202 | manuals: manuals,
|
203 | };
|
204 | });
|
205 | return {
|
206 | repoUrl: repoUrl,
|
207 | branchName: branchName,
|
208 | historyBranchName: historyBranchName,
|
209 | releases: releases,
|
210 | };
|
211 | });
|
212 | Fs.writeJsonSync(out, dump, { spaces: 2 });
|
213 | console.log();
|
214 | console.log('Dump finished.');
|
215 | console.log();
|
216 | }
|
217 |
|
218 |
|
219 | function diffReleases(dump, srcTag, dstTag) {
|
220 | var _a = srcTag.split('@'), srcBranchName = _a[0], srcReleaseVersion = _a[1];
|
221 | var _b = dstTag.split('@'), dstBranchName = _b[0], dstReleaseVersion = _b[1];
|
222 | if (!srcReleaseVersion && !dstReleaseVersion) {
|
223 | srcReleaseVersion = srcBranchName;
|
224 | dstReleaseVersion = dstBranchName;
|
225 | srcBranchName = null;
|
226 | dstBranchName = null;
|
227 | }
|
228 | if (semverEq(srcReleaseVersion, dstReleaseVersion)) {
|
229 | return '';
|
230 | }
|
231 |
|
232 | var reversed = semverGt(srcReleaseVersion, dstReleaseVersion);
|
233 | if (reversed) {
|
234 | var temp = void 0;
|
235 | temp = srcReleaseVersion;
|
236 | srcReleaseVersion = dstReleaseVersion;
|
237 | dstReleaseVersion = temp;
|
238 | temp = srcBranchName;
|
239 | srcBranchName = dstBranchName;
|
240 | dstBranchName = temp;
|
241 | }
|
242 |
|
243 | if (typeof dump === 'string' || dump instanceof String) {
|
244 |
|
245 |
|
246 | dump = Path.resolve(process.cwd(), dump);
|
247 |
|
248 | dump = Fs.readJSONSync(dump);
|
249 | }
|
250 | var srcDir = buildRelease(dump, srcReleaseVersion, srcBranchName);
|
251 | var dstDir = buildRelease(dump, dstReleaseVersion, dstBranchName);
|
252 | Fs.removeSync(srcDir.name + "/.git");
|
253 | Fs.copySync(dstDir.name + "/.git", srcDir.name + "/.git");
|
254 | var diff = utils_1.Utils.scopeEnv(function () {
|
255 | git_1.Git(['add', '.']);
|
256 | try {
|
257 | git_1.Git(['commit', '-m', dstReleaseVersion]);
|
258 |
|
259 |
|
260 | }
|
261 | catch (e) {
|
262 | return '';
|
263 | }
|
264 | return reversed
|
265 | ? git_1.Git(['diff', 'HEAD^', 'HEAD'])
|
266 | : git_1.Git(['diff', 'HEAD', 'HEAD^']);
|
267 | }, {
|
268 | TORTILLA_CWD: srcDir.name
|
269 | });
|
270 | srcDir.removeCallback();
|
271 | dstDir.removeCallback();
|
272 | return postTransformDiff(diff);
|
273 | }
|
274 | function buildRelease(dump, releaseVersion, branchName) {
|
275 |
|
276 | var chunk = branchName ? dump.find(function (c) { return c.branchName === branchName; }) : dump;
|
277 | var releaseIndex = chunk.releases.findIndex(function (r) { return r.releaseVersion === releaseVersion; });
|
278 |
|
279 | var releases = chunk.releases.slice(releaseIndex - chunk.releases.length).reverse();
|
280 | var diffs = releases.map(function (r) { return r.changesDiff; }).filter(Boolean).map(preTransformDiff);
|
281 | var dir = Tmp.dirSync({ unsafeCleanup: true });
|
282 | utils_1.Utils.scopeEnv(function () {
|
283 | git_1.Git(['init']);
|
284 | diffs.forEach(function (diff) {
|
285 | try {
|
286 | git_1.Git(['apply'], {
|
287 | input: diff
|
288 | });
|
289 | }
|
290 | catch (e) {
|
291 | e.message += " (version " + releaseVersion + ")";
|
292 | throw e;
|
293 | }
|
294 | });
|
295 | git_1.Git(['add', '.']);
|
296 | git_1.Git(['commit', '-m', releaseVersion]);
|
297 | }, {
|
298 | TORTILLA_CWD: dir.name
|
299 | });
|
300 | return dir;
|
301 | }
|
302 |
|
303 |
|
304 | function preTransformDiff(diff) {
|
305 | return diff
|
306 | .replace(/Binary files \/dev\/null and b\/([^ ]+) differ/g, [
|
307 | '--- /dev/null',
|
308 | '+++ b/$1',
|
309 | '@@ -0,0 +1 @@',
|
310 | '+__tortilla_bin__',
|
311 | ].join('\n'))
|
312 | .replace(/Binary files a\/([^ ]+) and \/dev\/null differ/g, [
|
313 | '--- a/$1',
|
314 | '+++ /dev/null',
|
315 | '@@ -1 +0,0 @@',
|
316 | '-__tortilla_bin__',
|
317 | ].join('\n'))
|
318 | .replace(/Binary files a\/([^ ]+) and b\/([^ ]+) differ/g, [
|
319 | '--- a/$1',
|
320 | '+++ b/$2',
|
321 | '@@ -1 +1 @@',
|
322 | '-__tortilla_bin__',
|
323 | '+__tortilla_bin__',
|
324 | ].join('\n'));
|
325 | }
|
326 |
|
327 | function postTransformDiff(diff) {
|
328 | return diff
|
329 | .replace(/--- \/dev\/null\n\+\+\+ b\/(.+)\n@@ -0,0 \+1 @@\n\+__tortilla_bin__/g, 'Binary files /dev/null and b/$1 differ')
|
330 | .replace(/--- a\/(.+)\n\+\+\+ \/dev\/null\n@@ -1 \+0,0 @@\n-__tortilla_bin__/g, 'Binary files a/$1 and /dev/null differ')
|
331 | .replace(/--- a\/(.+)\n\+\+\+ b\/(.+)\n@@ -1 \+1 @@\n-__tortilla_bin__\n\+__tortilla_bin__/g, 'Binary files a/$1 and b/$2 differ');
|
332 | }
|
333 |
|
334 | function semverEq(src, dst) {
|
335 | if (src === 'next' && dst === 'next') {
|
336 | return true;
|
337 | }
|
338 | if (src === 'next') {
|
339 | return false;
|
340 | }
|
341 | if (dst === 'next') {
|
342 | return false;
|
343 | }
|
344 | return semver.eq(src, dst);
|
345 | }
|
346 |
|
347 | function semverGt(src, dst) {
|
348 | if (src === 'next' && dst === 'next') {
|
349 | return false;
|
350 | }
|
351 | if (src === 'next') {
|
352 | return true;
|
353 | }
|
354 | if (dst === 'next') {
|
355 | return false;
|
356 | }
|
357 | return semver.gt(src, dst);
|
358 | }
|
359 | exports.Dump = {
|
360 | create: dumpProject,
|
361 | diffReleases: diffReleases
|
362 | };
|
363 |
|
\ | No newline at end of file |