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