gitorial-cli 1.1.0 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +114 -59
- package/package.json +6 -4
- package/src/commands/build-gitorial.js +152 -0
- package/src/commands/build-mdbook.js +321 -0
- package/src/index.js +29 -35
- package/src/lib/fs.js +112 -0
- package/src/lib/git.js +45 -0
- package/src/lib/logger.js +22 -0
- package/src/lib/mdbook-templates.js +18 -0
- package/src/lib/monaco-assets.js +1091 -0
- package/src/constants.js +0 -5
- package/src/mdbook.js +0 -482
- package/src/repack.js +0 -85
- package/src/unpack.js +0 -88
- package/src/utils.js +0 -79
package/src/constants.js
DELETED
package/src/mdbook.js
DELETED
|
@@ -1,482 +0,0 @@
|
|
|
1
|
-
const simpleGit = require("simple-git");
|
|
2
|
-
const fs = require("fs");
|
|
3
|
-
const os = require('os');
|
|
4
|
-
const path = require("path");
|
|
5
|
-
const { copyAllContentsAndReplace, copyFilesAndDirectories, doesBranchExist } = require("./utils");
|
|
6
|
-
|
|
7
|
-
async function mdbook(repoPath, inputBranch, outputBranch, subFolder) {
|
|
8
|
-
try {
|
|
9
|
-
// Create a new temporary folder
|
|
10
|
-
const sourceDir = fs.mkdtempSync(path.join(os.tmpdir(), 'gitorial-source-'));
|
|
11
|
-
const mdbookDir = fs.mkdtempSync(path.join(os.tmpdir(), 'gitorial-mdbook-'));
|
|
12
|
-
|
|
13
|
-
// Clone the repo into the source folder.
|
|
14
|
-
const tempGit = simpleGit(sourceDir);
|
|
15
|
-
|
|
16
|
-
// Resolve the full path to the local repository
|
|
17
|
-
const resolvedRepoPath = path.resolve(repoPath);
|
|
18
|
-
await tempGit.clone(resolvedRepoPath, '.', ['--branch', inputBranch]);
|
|
19
|
-
|
|
20
|
-
await processGitorial(sourceDir, mdbookDir);
|
|
21
|
-
|
|
22
|
-
let sourceGit = simpleGit(repoPath);
|
|
23
|
-
// Check if the branch exists in the list of local branches
|
|
24
|
-
const branchExists = await doesBranchExist(sourceGit, outputBranch)
|
|
25
|
-
|
|
26
|
-
if (!branchExists) {
|
|
27
|
-
// Create a fresh branch if it does not exist.
|
|
28
|
-
await sourceGit.raw(['switch', '--orphan', outputBranch]);
|
|
29
|
-
} else {
|
|
30
|
-
// Checkout the current branch if it does.
|
|
31
|
-
await sourceGit.checkout(outputBranch);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
let outputFolder = repoPath;
|
|
35
|
-
if (subFolder) {
|
|
36
|
-
outputFolder = path.join(outputFolder, subFolder);
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
copyAllContentsAndReplace(mdbookDir, outputFolder);
|
|
40
|
-
|
|
41
|
-
// Stage all files
|
|
42
|
-
await sourceGit.add('*');
|
|
43
|
-
|
|
44
|
-
// Create commit with commit message
|
|
45
|
-
await sourceGit.commit(`mdBook generated from ${inputBranch}`);
|
|
46
|
-
|
|
47
|
-
// Clean up source folder
|
|
48
|
-
fs.rmSync(sourceDir, { recursive: true });
|
|
49
|
-
fs.rmSync(mdbookDir, { recursive: true });
|
|
50
|
-
console.log("Temporary files removed.");
|
|
51
|
-
|
|
52
|
-
console.log("mdBook completed.");
|
|
53
|
-
} catch (error) {
|
|
54
|
-
console.error('Error:', error.message || error);
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
async function processGitorial(sourceDir, mdbookDir) {
|
|
59
|
-
const sourceGit = simpleGit(sourceDir);
|
|
60
|
-
|
|
61
|
-
// Retrieve commit log
|
|
62
|
-
const logs = await sourceGit.log();
|
|
63
|
-
|
|
64
|
-
let stepCounter = 0;
|
|
65
|
-
let templateFound = false;
|
|
66
|
-
let solutionFound = false;
|
|
67
|
-
let templateFiles = [];
|
|
68
|
-
let solutionFiles = [];
|
|
69
|
-
let sourceFiles = [];
|
|
70
|
-
let stepNames = [];
|
|
71
|
-
|
|
72
|
-
// Create a folder for each commit
|
|
73
|
-
// Reverse to make the oldest commit first
|
|
74
|
-
for ([index, log] of logs.all.reverse().entries()) {
|
|
75
|
-
const commitHash = log.hash;
|
|
76
|
-
const commitMessage = log.message;
|
|
77
|
-
|
|
78
|
-
// These are the possible gitorial commit types
|
|
79
|
-
const isReadme = commitMessage.toLowerCase().startsWith("readme: ");
|
|
80
|
-
const isTemplate = commitMessage.toLowerCase().startsWith("template: ");
|
|
81
|
-
const isSolution = commitMessage.toLowerCase().startsWith("solution: ");
|
|
82
|
-
const isSection = commitMessage.toLowerCase().startsWith("section: ");
|
|
83
|
-
const isAction = commitMessage.toLowerCase().startsWith("action: ");
|
|
84
|
-
const isStartingTemplate = commitMessage.toLowerCase().startsWith("starting-template");
|
|
85
|
-
|
|
86
|
-
// A step may not increment with a new commit, for example a `template` and `solution` happen in one step.
|
|
87
|
-
let stepFolder = path.join(mdbookDir, stepCounter.toString());
|
|
88
|
-
if (!fs.existsSync(stepFolder)) {
|
|
89
|
-
fs.mkdirSync(stepFolder);
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
let sourceFolder = path.join(stepFolder, "source");
|
|
93
|
-
let templateFolder = path.join(stepFolder, "template");
|
|
94
|
-
let solutionFolder = path.join(stepFolder, "solution");
|
|
95
|
-
|
|
96
|
-
// Default assumption is output is not a template or solution
|
|
97
|
-
let outputFolder = sourceFolder;
|
|
98
|
-
|
|
99
|
-
// We skip the starting template commit since it is only used for starting the project.
|
|
100
|
-
if (isStartingTemplate) {
|
|
101
|
-
continue;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
if (isTemplate) {
|
|
105
|
-
// Check there isn't a template already in queue
|
|
106
|
-
if (templateFound) {
|
|
107
|
-
console.error("A second template was found before a solution.");
|
|
108
|
-
process.exit(1);
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
templateFound = true;
|
|
112
|
-
|
|
113
|
-
// make step folder
|
|
114
|
-
outputFolder = templateFolder;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
if (isSolution) {
|
|
118
|
-
// Check that there is a template in queue
|
|
119
|
-
if (!templateFound) {
|
|
120
|
-
console.error("No template was found for this solution.");
|
|
121
|
-
process.exit(1);
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
// Check that a solution is not already found.
|
|
125
|
-
if (solutionFound) {
|
|
126
|
-
console.error("A second solution was found before a template.");
|
|
127
|
-
process.exit(1);
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
solutionFound = true;
|
|
131
|
-
outputFolder = solutionFolder;
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
fs.mkdirSync(outputFolder);
|
|
135
|
-
|
|
136
|
-
// Checkout the commit
|
|
137
|
-
console.log(`Checking out commit: ${commitHash}`);
|
|
138
|
-
await sourceGit.checkout(commitHash)
|
|
139
|
-
|
|
140
|
-
// Copy the contents to the commit folder
|
|
141
|
-
copyFilesAndDirectories(sourceDir, outputFolder);
|
|
142
|
-
console.log(`Contents of commit ${index} copied to ${outputFolder}`);
|
|
143
|
-
|
|
144
|
-
let previousCommit = "HEAD~1";
|
|
145
|
-
// This is the commit hash for an empty git project.
|
|
146
|
-
let emptyTree = "4b825dc642cb6eb9a060e54bf8d69288fbee4904";
|
|
147
|
-
|
|
148
|
-
if (index == 0) {
|
|
149
|
-
previousCommit = emptyTree;
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
// Get the list of modified or created files in the commit
|
|
153
|
-
const diffOutput = await sourceGit.diff(['--name-status', `${previousCommit}`, `HEAD`])
|
|
154
|
-
// Get the raw diff between the previous commit and HEAD, excluding README.md
|
|
155
|
-
const diffRaw = await sourceGit.diff([`${previousCommit}`, `HEAD`, ':(exclude)README.md']);
|
|
156
|
-
|
|
157
|
-
// Create a raw output
|
|
158
|
-
let diff_name = "changes.diff";
|
|
159
|
-
if (isSolution) {
|
|
160
|
-
diff_name = "solution.diff";
|
|
161
|
-
} else if (isTemplate) {
|
|
162
|
-
diff_name = "template.diff";
|
|
163
|
-
}
|
|
164
|
-
const diffFilePath = path.join(outputFolder, diff_name);
|
|
165
|
-
fs.writeFileSync(diffFilePath, diffRaw);
|
|
166
|
-
|
|
167
|
-
let fileStatus = diffOutput.split("\n").map((line) => {
|
|
168
|
-
const [status, file] = line.split("\t");
|
|
169
|
-
return { status, file };
|
|
170
|
-
});
|
|
171
|
-
|
|
172
|
-
if (isTemplate) {
|
|
173
|
-
templateFiles = fileStatus;
|
|
174
|
-
} else if (isSolution) {
|
|
175
|
-
solutionFiles = fileStatus;
|
|
176
|
-
} else {
|
|
177
|
-
sourceFiles = fileStatus;
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
// Reset sanity check and increment step
|
|
181
|
-
// Handle when both template and solution is found,
|
|
182
|
-
// or when there is a step that is neither a template or solution
|
|
183
|
-
if (
|
|
184
|
-
(templateFound && solutionFound) ||
|
|
185
|
-
(!templateFound && !solutionFound)
|
|
186
|
-
) {
|
|
187
|
-
if (isReadme) {
|
|
188
|
-
markdownContent = sectionMarkdown;
|
|
189
|
-
} else if (isSection) {
|
|
190
|
-
markdownContent = sectionMarkdown;
|
|
191
|
-
stepNames.push({
|
|
192
|
-
name: getStepName(sourceFolder),
|
|
193
|
-
is_section: true,
|
|
194
|
-
});
|
|
195
|
-
} else if (templateFound) {
|
|
196
|
-
markdownContent = templateMarkdown;
|
|
197
|
-
let templateFileText = generateFileMarkdown("template", templateFiles);
|
|
198
|
-
let solutionFileText = generateFileMarkdown("solution", solutionFiles);
|
|
199
|
-
markdownContent = markdownContent.replace(
|
|
200
|
-
"<!-- insert_template_files -->",
|
|
201
|
-
templateFileText
|
|
202
|
-
);
|
|
203
|
-
markdownContent = markdownContent.replace(
|
|
204
|
-
"<!-- insert_solution_files -->",
|
|
205
|
-
solutionFileText
|
|
206
|
-
);
|
|
207
|
-
|
|
208
|
-
let diffText = generateDiffMarkdown("template");
|
|
209
|
-
markdownContent = markdownContent.replace(
|
|
210
|
-
"<!-- insert_diff_files -->",
|
|
211
|
-
diffText
|
|
212
|
-
);
|
|
213
|
-
|
|
214
|
-
stepNames.push({
|
|
215
|
-
name: getStepName(templateFolder),
|
|
216
|
-
is_section: false,
|
|
217
|
-
});
|
|
218
|
-
} else if (isAction) {
|
|
219
|
-
markdownContent = sourceMarkdown;
|
|
220
|
-
let sourceFileText = generateFileMarkdown("source", sourceFiles);
|
|
221
|
-
markdownContent = markdownContent.replace(
|
|
222
|
-
"<!-- insert_source_files -->",
|
|
223
|
-
sourceFileText
|
|
224
|
-
);
|
|
225
|
-
|
|
226
|
-
let diffText = generateDiffMarkdown("source");
|
|
227
|
-
markdownContent = markdownContent.replace(
|
|
228
|
-
"<!-- insert_diff_files -->",
|
|
229
|
-
diffText
|
|
230
|
-
);
|
|
231
|
-
|
|
232
|
-
stepNames.push({
|
|
233
|
-
name: getStepName(sourceFolder),
|
|
234
|
-
is_section: false,
|
|
235
|
-
});
|
|
236
|
-
} else {
|
|
237
|
-
console.error(`Unknown Gitorial Commit Type: ${commitMessage}`)
|
|
238
|
-
}
|
|
239
|
-
// Create a Markdown file in the commit folder
|
|
240
|
-
const markdownFilePath = path.join(stepFolder, "README.md");
|
|
241
|
-
fs.writeFileSync(markdownFilePath, markdownContent);
|
|
242
|
-
stepCounter += 1;
|
|
243
|
-
templateFound = false;
|
|
244
|
-
solutionFound = false;
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
generateSidebar(mdbookDir, stepNames);
|
|
249
|
-
|
|
250
|
-
console.log("Finished Parsing.");
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
// Generate the markdown text for files.
|
|
254
|
-
function generateFileMarkdown(type, files) {
|
|
255
|
-
// type is expected to be one of "source", "solution", or "template"
|
|
256
|
-
if (type != "solution" && type != "source" && type != "template") {
|
|
257
|
-
process.exit(1);
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
let output = "";
|
|
261
|
-
|
|
262
|
-
let parsedFiles = [];
|
|
263
|
-
for (file of files) {
|
|
264
|
-
if (!file.file) {
|
|
265
|
-
continue;
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
// Skip all hidden folders, like `.gitorial`.
|
|
269
|
-
if (file.file.startsWith(".")) {
|
|
270
|
-
continue;
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
let filepath = `./${type}/${file.file}`;
|
|
274
|
-
let filename = path.parse(filepath).base;
|
|
275
|
-
|
|
276
|
-
// Skip README
|
|
277
|
-
if (filename == "README.md") {
|
|
278
|
-
continue;
|
|
279
|
-
}
|
|
280
|
-
// Skip hidden files
|
|
281
|
-
if (filename.startsWith(".")) {
|
|
282
|
-
continue;
|
|
283
|
-
}
|
|
284
|
-
// Skip Cargo.lock
|
|
285
|
-
if (filename == "Cargo.lock") {
|
|
286
|
-
continue;
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
let classStyle = `file-${type}`;
|
|
290
|
-
if (file.status == "M") {
|
|
291
|
-
classStyle += " file-modified";
|
|
292
|
-
} else if (file.status == "A") {
|
|
293
|
-
classStyle += " file-added";
|
|
294
|
-
} else if (file.status == "D") {
|
|
295
|
-
classStyle += " file-deleted";
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
let codeStyle = "text";
|
|
299
|
-
let extname = path.extname(filepath);
|
|
300
|
-
switch (extname) {
|
|
301
|
-
case ".rs":
|
|
302
|
-
codeStyle = "rust";
|
|
303
|
-
break;
|
|
304
|
-
case ".toml":
|
|
305
|
-
codeStyle = "toml";
|
|
306
|
-
break;
|
|
307
|
-
case ".js":
|
|
308
|
-
codeStyle = "js";
|
|
309
|
-
break;
|
|
310
|
-
case ".json":
|
|
311
|
-
codeStyle = "json";
|
|
312
|
-
break;
|
|
313
|
-
case ".ts":
|
|
314
|
-
codeStyle = "ts";
|
|
315
|
-
break;
|
|
316
|
-
default:
|
|
317
|
-
codeStyle = "text";
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
parsedFiles.push({ filename: file.file, classStyle, codeStyle, filepath })
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
if (parsedFiles.length > 0) {
|
|
324
|
-
output += `<div class="tab">\n`;
|
|
325
|
-
|
|
326
|
-
for ([i, file] of parsedFiles.entries()) {
|
|
327
|
-
output += `<button class="subtab tablinks ${file.classStyle}${i == 0 ? " active" : ""}" onclick="switchSubTab(event, '${file.filename}')" data-id="${file.filename}">${file.filename}</button>\n`;
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
output += `</div>\n`
|
|
331
|
-
|
|
332
|
-
for ([i, file] of parsedFiles.entries()) {
|
|
333
|
-
output += `<div id="${type}/${file.filename}" class="subtab tabcontent${i == 0 ? " active" : ""}" data-id="${file.filename}">\n\n`;
|
|
334
|
-
output += `\`\`\`${file.codeStyle}\n{{#include ${file.filepath}}}\n\`\`\`\n\n`;
|
|
335
|
-
output += `</div>\n\n`;
|
|
336
|
-
}
|
|
337
|
-
} else {
|
|
338
|
-
output = "No files edited in this step.";
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
return output;
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
function generateDiffMarkdown(type) {
|
|
345
|
-
let output = "";
|
|
346
|
-
|
|
347
|
-
if (type == "template" || type == "solution") {
|
|
348
|
-
output += solutionDiffMarkdown;
|
|
349
|
-
} else {
|
|
350
|
-
output += changesDiffMarkdown;
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
return output;
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
let solutionDiffMarkdown = `
|
|
357
|
-
<div class="tab">
|
|
358
|
-
<button class="difftab tablinks active" onclick="switchDiff(event, 'template.diff')" data-id="template.diff">template.diff</button>
|
|
359
|
-
<button class="difftab tablinks" onclick="switchDiff(event, 'solution.diff')" data-id="solution.diff">solution.diff</button>
|
|
360
|
-
</div>
|
|
361
|
-
<div id="template.diff" class="difftab tabcontent active" data-id="template.diff">
|
|
362
|
-
|
|
363
|
-
\`\`\`diff\n{{#include ./template/template.diff}}\n\`\`\`
|
|
364
|
-
|
|
365
|
-
</div>
|
|
366
|
-
<div id="solution.diff" class="difftab tabcontent" data-id="solution.diff">
|
|
367
|
-
|
|
368
|
-
\`\`\`diff\n{{#include ./solution/solution.diff}}\n\`\`\`
|
|
369
|
-
|
|
370
|
-
</div>`;
|
|
371
|
-
|
|
372
|
-
let changesDiffMarkdown = `
|
|
373
|
-
<div class="tab">
|
|
374
|
-
<button class="difftab tablinks active" onclick="switchDiff(event, 'changes.diff')" data-id="changes.diff">changes.diff</button>
|
|
375
|
-
</div>
|
|
376
|
-
<div id="changes.diff" class="difftab tabcontent active" data-id="changes.diff">
|
|
377
|
-
|
|
378
|
-
\`\`\`diff\n{{#include ./source/changes.diff}}\n\`\`\`
|
|
379
|
-
|
|
380
|
-
</div>`;
|
|
381
|
-
|
|
382
|
-
let templateMarkdown = `
|
|
383
|
-
<div class="content-row">
|
|
384
|
-
<div class="content-col">
|
|
385
|
-
|
|
386
|
-
{{#include ./template/README.md}}
|
|
387
|
-
|
|
388
|
-
</div>
|
|
389
|
-
|
|
390
|
-
<div class="content-col">
|
|
391
|
-
|
|
392
|
-
<div class="tab">
|
|
393
|
-
<button class="maintab tablinks active" onclick="switchMainTab(event, 'Template')">Template</button>
|
|
394
|
-
<button class="maintab tablinks" onclick="switchMainTab(event, 'Solution')">Solution</button>
|
|
395
|
-
<button class="maintab tablinks" onclick="switchMainTab(event, 'Diff')">Diff</button>
|
|
396
|
-
</div>
|
|
397
|
-
|
|
398
|
-
<div id="Template" class="maintab tabcontent active">
|
|
399
|
-
|
|
400
|
-
<!-- insert_template_files -->
|
|
401
|
-
|
|
402
|
-
</div>
|
|
403
|
-
|
|
404
|
-
<div id="Solution" class="maintab tabcontent">
|
|
405
|
-
|
|
406
|
-
<!-- insert_solution_files -->
|
|
407
|
-
|
|
408
|
-
</div>
|
|
409
|
-
|
|
410
|
-
<div id="Diff" class="maintab tabcontent">
|
|
411
|
-
|
|
412
|
-
<!-- insert_diff_files -->
|
|
413
|
-
|
|
414
|
-
</div>
|
|
415
|
-
|
|
416
|
-
</div>
|
|
417
|
-
</div>
|
|
418
|
-
`;
|
|
419
|
-
|
|
420
|
-
let sourceMarkdown = `
|
|
421
|
-
<div class="content-row">
|
|
422
|
-
<div class="content-col">
|
|
423
|
-
|
|
424
|
-
{{#include ./source/README.md}}
|
|
425
|
-
|
|
426
|
-
</div>
|
|
427
|
-
<div class="content-col">
|
|
428
|
-
|
|
429
|
-
<div class="tab">
|
|
430
|
-
<button class="maintab tablinks active" onclick="switchMainTab(event, 'Source')">Source</button>
|
|
431
|
-
<button class="maintab tablinks" onclick="switchMainTab(event, 'Diff')">Diff</button>
|
|
432
|
-
</div>
|
|
433
|
-
|
|
434
|
-
<div id="Source" class="maintab tabcontent active">
|
|
435
|
-
|
|
436
|
-
<!-- insert_source_files -->
|
|
437
|
-
|
|
438
|
-
</div>
|
|
439
|
-
|
|
440
|
-
<div id="Diff" class="maintab tabcontent">
|
|
441
|
-
|
|
442
|
-
<!-- insert_diff_files -->
|
|
443
|
-
|
|
444
|
-
</div>
|
|
445
|
-
|
|
446
|
-
</div>
|
|
447
|
-
</div>
|
|
448
|
-
`;
|
|
449
|
-
|
|
450
|
-
let sectionMarkdown = `
|
|
451
|
-
<div class="content-section">
|
|
452
|
-
|
|
453
|
-
{{#include ./source/README.md}}
|
|
454
|
-
|
|
455
|
-
</div>
|
|
456
|
-
`;
|
|
457
|
-
|
|
458
|
-
function getStepName(folder) {
|
|
459
|
-
const filePath = path.join(folder, "README.md");
|
|
460
|
-
const markdownContent = fs.readFileSync(filePath, "utf8");
|
|
461
|
-
const titleMatch = markdownContent.match(/^#\s+(.*)/m);
|
|
462
|
-
if (titleMatch) {
|
|
463
|
-
return titleMatch[1];
|
|
464
|
-
} else {
|
|
465
|
-
console.error(`Error getting markdown title.`);
|
|
466
|
-
process.exit(1);
|
|
467
|
-
}
|
|
468
|
-
}
|
|
469
|
-
|
|
470
|
-
function generateSidebar(mdbookDir, steps) {
|
|
471
|
-
const sidebarFilePath = path.join(mdbookDir, "SUMMARY.md");
|
|
472
|
-
let output = "";
|
|
473
|
-
steps.forEach(({ name, is_section }, index) => {
|
|
474
|
-
if (!is_section) {
|
|
475
|
-
output += ` `;
|
|
476
|
-
}
|
|
477
|
-
output += `- [${index}. ${name}](${index}/README.md)\n`;
|
|
478
|
-
});
|
|
479
|
-
fs.writeFileSync(sidebarFilePath, output);
|
|
480
|
-
}
|
|
481
|
-
|
|
482
|
-
module.exports = mdbook;
|
package/src/repack.js
DELETED
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
const simpleGit = require('simple-git');
|
|
2
|
-
const fs = require('fs');
|
|
3
|
-
const os = require('os');
|
|
4
|
-
const path = require('path');
|
|
5
|
-
const { GITORIAL_METADATA } = require('./constants');
|
|
6
|
-
const { copyAllContentsAndReplace } = require('./utils')
|
|
7
|
-
|
|
8
|
-
async function repack(repoPath, inputBranch, outputBranch, subFolder, force) {
|
|
9
|
-
try {
|
|
10
|
-
const git = simpleGit(repoPath);
|
|
11
|
-
|
|
12
|
-
if (force) {
|
|
13
|
-
let saveBranch = `${outputBranch}-__gitorial-old`;
|
|
14
|
-
// Delete the existing `__gitorial-old` branch if it exists
|
|
15
|
-
try {
|
|
16
|
-
await git.raw(['branch', '-D', saveBranch]);
|
|
17
|
-
} catch (error) {
|
|
18
|
-
// Ignore the error if the branch does not exist
|
|
19
|
-
}
|
|
20
|
-
// Move the output branch to the save branch
|
|
21
|
-
try {
|
|
22
|
-
await git.branch(['-m', outputBranch, saveBranch]);
|
|
23
|
-
} catch (error) {
|
|
24
|
-
// Ignore the error if the branch does not exist
|
|
25
|
-
}
|
|
26
|
-
await git.raw(['switch', '--orphan', outputBranch]);
|
|
27
|
-
} else {
|
|
28
|
-
await git.raw(['switch', '--orphan', outputBranch]);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'gitorial-repack-'));
|
|
32
|
-
await git.clone(repoPath, tempDir, ['--branch', inputBranch]);
|
|
33
|
-
|
|
34
|
-
let unpackedDir = tempDir;
|
|
35
|
-
if (subFolder) {
|
|
36
|
-
unpackedDir = path.join(unpackedDir, subFolder)
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
// Get list of steps
|
|
40
|
-
const steps = fs.readdirSync(unpackedDir)
|
|
41
|
-
.filter(item => fs.statSync(path.join(unpackedDir, item)).isDirectory())
|
|
42
|
-
.filter(item => item != '.git') // skip the git directory
|
|
43
|
-
.sort((a, b) => parseInt(a) - parseInt(b)); // Sort folders numerically
|
|
44
|
-
|
|
45
|
-
for (const step of steps) {
|
|
46
|
-
const stepFolderPath = path.join(unpackedDir, step);
|
|
47
|
-
|
|
48
|
-
// Read commit message from GITORIAL_METADATA
|
|
49
|
-
const commitInfoPath = path.join(stepFolderPath, GITORIAL_METADATA);
|
|
50
|
-
const commitInfo = JSON.parse(fs.readFileSync(commitInfoPath, 'utf-8'));
|
|
51
|
-
const commitMessage = commitInfo.commitMessage;
|
|
52
|
-
|
|
53
|
-
// Copy files from numbered folder to repo path
|
|
54
|
-
copyAllContentsAndReplace(stepFolderPath, repoPath);
|
|
55
|
-
|
|
56
|
-
// Stage all files
|
|
57
|
-
await git.add('*');
|
|
58
|
-
|
|
59
|
-
// Remove GITORIAL_METADATA
|
|
60
|
-
await git.reset(GITORIAL_METADATA);
|
|
61
|
-
await git.rm(GITORIAL_METADATA);
|
|
62
|
-
|
|
63
|
-
// Create commit with commit message
|
|
64
|
-
await git.commit(commitMessage);
|
|
65
|
-
console.log(`Commit created for step ${step} with message: ${commitMessage}`);
|
|
66
|
-
|
|
67
|
-
// We want to tag the `starting-template` so it can be easily referenced.
|
|
68
|
-
if (commitMessage == 'starting-template') {
|
|
69
|
-
await git.raw(['tag', 'starting-template', '--force']);
|
|
70
|
-
console.log(`Added ${commitMessage} tag.`);
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
// Clean up temp folder
|
|
75
|
-
fs.rmSync(tempDir, { recursive: true });
|
|
76
|
-
console.log("Temporary files removed.");
|
|
77
|
-
|
|
78
|
-
console.log('Commits created successfully.')
|
|
79
|
-
|
|
80
|
-
} catch (error) {
|
|
81
|
-
console.error('Error:', error.message || error);
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
module.exports = repack;
|
package/src/unpack.js
DELETED
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
const simpleGit = require('simple-git');
|
|
2
|
-
const fs = require('fs');
|
|
3
|
-
const os = require('os');
|
|
4
|
-
const path = require('path');
|
|
5
|
-
const { GITORIAL_METADATA } = require('./constants');
|
|
6
|
-
const { copyAllContentsAndReplace, doesBranchExist, copyFilesAndDirectories } = require('./utils')
|
|
7
|
-
|
|
8
|
-
async function unpack(repoPath, inputBranch, outputBranch, outputSubFolder) {
|
|
9
|
-
try {
|
|
10
|
-
// Create a new temporary folder
|
|
11
|
-
const sourceDir = fs.mkdtempSync(path.join(os.tmpdir(), 'gitorial-source-'));
|
|
12
|
-
const unpackedDir = fs.mkdtempSync(path.join(os.tmpdir(), 'gitorial-unpacked-'));
|
|
13
|
-
|
|
14
|
-
// Clone the repo into the source folder.
|
|
15
|
-
const tempGit = simpleGit(sourceDir);
|
|
16
|
-
|
|
17
|
-
// Resolve the full path to the local repository
|
|
18
|
-
const resolvedRepoPath = path.resolve(repoPath);
|
|
19
|
-
await tempGit.clone(resolvedRepoPath, '.', ['--branch', inputBranch]);
|
|
20
|
-
|
|
21
|
-
// Retrieve commit log
|
|
22
|
-
const logs = await tempGit.log();
|
|
23
|
-
|
|
24
|
-
// Create a folder for each commit
|
|
25
|
-
// Reverse to make the oldest commit first
|
|
26
|
-
for ([index, log] of logs.all.reverse().entries()) {
|
|
27
|
-
const commitHash = log.hash;
|
|
28
|
-
const commitMessage = log.message;
|
|
29
|
-
|
|
30
|
-
let stepFolder = path.join(unpackedDir, index.toString());
|
|
31
|
-
|
|
32
|
-
// Checkout the commit
|
|
33
|
-
console.log(`Checking out commit: ${commitHash}`);
|
|
34
|
-
await tempGit.checkout(commitHash);
|
|
35
|
-
|
|
36
|
-
// Copy the contents to the commit folder
|
|
37
|
-
copyFilesAndDirectories(sourceDir, stepFolder);
|
|
38
|
-
console.log(`Contents copied from ${sourceDir} to ${stepFolder}`);
|
|
39
|
-
|
|
40
|
-
// Create a JSON file in the commit folder
|
|
41
|
-
const jsonFilePath = path.join(stepFolder, GITORIAL_METADATA);
|
|
42
|
-
const commitInfoObject = {
|
|
43
|
-
"_Note": "This file will not be included in your final gitorial.",
|
|
44
|
-
commitMessage,
|
|
45
|
-
};
|
|
46
|
-
|
|
47
|
-
fs.writeFileSync(jsonFilePath, JSON.stringify(commitInfoObject, null, 2));
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
let sourceGit = simpleGit(repoPath);
|
|
51
|
-
|
|
52
|
-
// Check if the branch exists in the list of local branches
|
|
53
|
-
const branchExists = await doesBranchExist(sourceGit, outputBranch)
|
|
54
|
-
|
|
55
|
-
if (!branchExists) {
|
|
56
|
-
// Create a fresh branch if it does not exist.
|
|
57
|
-
await sourceGit.raw(['switch', '--orphan', outputBranch]);
|
|
58
|
-
} else {
|
|
59
|
-
// Checkout the current branch if it does.
|
|
60
|
-
await sourceGit.checkout(outputBranch)
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
let outputFolder = repoPath;
|
|
64
|
-
if (outputSubFolder) {
|
|
65
|
-
outputFolder = path.join(repoPath, outputSubFolder)
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
copyAllContentsAndReplace(unpackedDir, outputFolder);
|
|
69
|
-
|
|
70
|
-
// Stage all files
|
|
71
|
-
await sourceGit.add('*');
|
|
72
|
-
|
|
73
|
-
// Create commit with commit message
|
|
74
|
-
await sourceGit.commit(`Unpacked from ${inputBranch}`);
|
|
75
|
-
|
|
76
|
-
// Clean up source folder
|
|
77
|
-
fs.rmSync(sourceDir, { recursive: true });
|
|
78
|
-
fs.rmSync(unpackedDir, { recursive: true });
|
|
79
|
-
console.log("Temporary files removed.");
|
|
80
|
-
|
|
81
|
-
console.log("Process completed.");
|
|
82
|
-
} catch (error) {
|
|
83
|
-
console.error('Error:', error.message || error);
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
module.exports = unpack;
|