reslop 0.1.9 → 0.2.1
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/CHANGELOG.md +25 -1
- package/README.md +3 -1
- package/bin/reslop.js +2 -2
- package/lib/ansi.js +148 -5
- package/lib/api.js +4 -2
- package/lib/capabilities.js +13 -14
- package/lib/cli.js +38 -49
- package/lib/clipboard.js +1 -1
- package/lib/{deps/changes.js → deps-diff.js} +309 -19
- package/lib/deps.js +498 -29
- package/lib/detect.js +1 -7
- package/lib/diff/align.js +7 -10
- package/lib/diff/diff.js +53 -0
- package/lib/diff/display.js +5 -4
- package/lib/diff/inline.js +26 -21
- package/lib/diff/items.js +6 -4
- package/lib/diff/patch.js +1 -3
- package/lib/diff/unit.js +392 -0
- package/lib/files.js +5 -8
- package/lib/{git/branches.js → git-branches.js} +191 -11
- package/lib/{git/dependencies.js → git-deps.js} +111 -38
- package/lib/git-reword-todo.js +20 -0
- package/lib/git.js +606 -68
- package/lib/github.js +28 -197
- package/lib/gitlab.js +24 -195
- package/lib/highlight/bash.js +1 -3
- package/lib/highlight/css.js +1 -3
- package/lib/highlight/js.js +11 -14
- package/lib/highlight.js +6 -9
- package/lib/keys.js +14 -8
- package/lib/manifest.js +330 -0
- package/lib/remote.js +374 -0
- package/lib/render/branches.js +18 -100
- package/lib/render/chrome.js +71 -14
- package/lib/render/commits.js +69 -60
- package/lib/render/diff.js +20 -20
- package/lib/render/files.js +6 -34
- package/lib/render/frame.js +36 -13
- package/lib/render/notes.js +26 -8
- package/lib/render/primitives.js +99 -11
- package/lib/{render.js → render/render.js} +8 -8
- package/lib/render/unit.js +41 -0
- package/lib/review-merge.js +270 -0
- package/lib/review.js +782 -14
- package/lib/select.js +5 -10
- package/lib/session/accessors.js +9 -1
- package/lib/session/actions.js +61 -18
- package/lib/session/branches.js +116 -128
- package/lib/session/change-actions.js +202 -123
- package/lib/session/commit.js +201 -115
- package/lib/session/compose.js +181 -15
- package/lib/session/dispatch.js +110 -60
- package/lib/session/files-pane.js +156 -148
- package/lib/session/items.js +22 -30
- package/lib/session/lifecycle.js +151 -54
- package/lib/session/load.js +19 -33
- package/lib/session/navigation.js +12 -1
- package/lib/session/ops.js +28 -41
- package/lib/session/pointer.js +57 -57
- package/lib/session/review.js +23 -37
- package/lib/session/terminal.js +6 -12
- package/lib/session/todos.js +37 -13
- package/lib/session/unit.js +208 -0
- package/lib/session/update.js +33 -46
- package/lib/session/view.js +78 -9
- package/lib/session/watch.js +128 -24
- package/lib/session.js +22 -246
- package/lib/source.js +3 -3
- package/lib/update.js +40 -75
- package/lib/{git/proc.js → utilities.js} +75 -11
- package/lib/wrap.js +1 -3
- package/package.json +2 -2
- package/lib/deps/items.js +0 -134
- package/lib/deps/manifest.js +0 -152
- package/lib/deps/merge.js +0 -120
- package/lib/deps/proposals.js +0 -164
- package/lib/deps/reports.js +0 -180
- package/lib/deps/rows.js +0 -176
- package/lib/deps/scan.js +0 -138
- package/lib/deps/usage.js +0 -68
- package/lib/deps/versions.js +0 -119
- package/lib/diff.js +0 -33
- package/lib/git/changes.js +0 -164
- package/lib/git/read.js +0 -253
- package/lib/git/run.js +0 -100
- package/lib/npm/commands.js +0 -100
- package/lib/remote/changes.js +0 -37
- package/lib/remote/headers.js +0 -36
- package/lib/remote/http.js +0 -122
- package/lib/remote/notes.js +0 -94
- package/lib/review/format.js +0 -434
- package/lib/review/storage.js +0 -150
- package/lib/review/store.js +0 -178
- package/lib/review/templates.js +0 -49
- package/lib/session/origins.js +0 -7
- package/lib/sys.js +0 -84
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const {
|
|
3
|
+
const { jsonParse } = require('metautil');
|
|
4
|
+
const { itemPath } = require('./files.js');
|
|
4
5
|
const {
|
|
5
6
|
countSides,
|
|
6
7
|
formatHunkHeader,
|
|
7
8
|
formatPatch,
|
|
8
|
-
} = require('
|
|
9
|
-
|
|
9
|
+
} = require('./diff/patch.js');
|
|
10
|
+
const { isCtxType } = require('./diff/diff.js');
|
|
10
11
|
const manifest = require('./manifest.js');
|
|
11
12
|
const { MANIFEST, LOCKFILE, SECTION_KEYS, depFileMeta, relOf } = manifest;
|
|
12
|
-
const {
|
|
13
|
+
const { listFilePath, readSections, emptySectionMaps } = manifest;
|
|
13
14
|
const { lockRootSections, lockEntries, lockPackageCount } = manifest;
|
|
14
15
|
|
|
15
16
|
const SECTION_ORDER = [...SECTION_KEYS, 'resolved', 'field'];
|
|
@@ -51,9 +52,6 @@ const fieldText = (value) => {
|
|
|
51
52
|
return JSON.stringify(value);
|
|
52
53
|
};
|
|
53
54
|
|
|
54
|
-
const sameJson = (left, right) =>
|
|
55
|
-
JSON.stringify(left) === JSON.stringify(right);
|
|
56
|
-
|
|
57
55
|
const diffOtherFields = (oldPkg, newPkg) => {
|
|
58
56
|
if (!oldPkg && !newPkg) return [];
|
|
59
57
|
const oldObj = oldPkg ?? {};
|
|
@@ -66,7 +64,7 @@ const diffOtherFields = (oldPkg, newPkg) => {
|
|
|
66
64
|
if (SECTION_KEYS.includes(name)) continue;
|
|
67
65
|
const prev = oldObj[name];
|
|
68
66
|
const next = newObj[name];
|
|
69
|
-
if (
|
|
67
|
+
if (JSON.stringify(prev) === JSON.stringify(next)) continue;
|
|
70
68
|
let action = 'changed';
|
|
71
69
|
if (!Object.hasOwn(oldObj, name)) action = 'added';
|
|
72
70
|
else if (!Object.hasOwn(newObj, name)) action = 'removed';
|
|
@@ -98,9 +96,6 @@ const lineInBlock = (item, line) => {
|
|
|
98
96
|
return line.blockId === blockId;
|
|
99
97
|
};
|
|
100
98
|
|
|
101
|
-
const isSectionFence = (text) =>
|
|
102
|
-
SECTION_OPEN.test(text) || SECTION_END.test(text);
|
|
103
|
-
|
|
104
99
|
const hunkOnlyFoldedDeps = (item, names) => {
|
|
105
100
|
if (!item.hunk || !names.size) return false;
|
|
106
101
|
let folded = 0;
|
|
@@ -112,7 +107,7 @@ const hunkOnlyFoldedDeps = (item, names) => {
|
|
|
112
107
|
folded += 1;
|
|
113
108
|
continue;
|
|
114
109
|
}
|
|
115
|
-
if (
|
|
110
|
+
if (SECTION_OPEN.test(line.text) || SECTION_END.test(line.text)) continue;
|
|
116
111
|
return false;
|
|
117
112
|
}
|
|
118
113
|
return folded > 0;
|
|
@@ -228,12 +223,14 @@ const directNames = (oldMaps, newMaps) => {
|
|
|
228
223
|
|
|
229
224
|
const mergeResolved = (changes, oldResolved, newResolved, oldMaps, newMaps) => {
|
|
230
225
|
const seen = new Set();
|
|
231
|
-
const
|
|
232
|
-
|
|
226
|
+
const { length } = changes;
|
|
227
|
+
const merged = new Array(length);
|
|
228
|
+
for (let i = 0; i < length; i++) {
|
|
229
|
+
const change = changes[i];
|
|
233
230
|
seen.add(change.name);
|
|
234
231
|
const resolvedFrom = oldResolved.get(change.name) ?? '';
|
|
235
232
|
const resolvedTo = newResolved.get(change.name) ?? '';
|
|
236
|
-
merged
|
|
233
|
+
merged[i] = { ...change, resolvedFrom, resolvedTo };
|
|
237
234
|
}
|
|
238
235
|
const names = [...directNames(oldMaps, newMaps)];
|
|
239
236
|
names.sort();
|
|
@@ -286,10 +283,10 @@ const readGroupSnapshot = (group, readSides) => {
|
|
|
286
283
|
const lockRel = relOf(dir, LOCKFILE);
|
|
287
284
|
const manifestSides = readSides(origin, manifestRel);
|
|
288
285
|
const lockSides = readSides(origin, lockRel);
|
|
289
|
-
const oldPkg =
|
|
290
|
-
const newPkg =
|
|
291
|
-
const oldLock =
|
|
292
|
-
const newLock =
|
|
286
|
+
const oldPkg = jsonParse(manifestSides.oldText ?? '');
|
|
287
|
+
const newPkg = jsonParse(manifestSides.newText ?? '');
|
|
288
|
+
const oldLock = jsonParse(lockSides.oldText ?? '');
|
|
289
|
+
const newLock = jsonParse(lockSides.newText ?? '');
|
|
293
290
|
const parsedManifest = !!(oldPkg || newPkg);
|
|
294
291
|
return {
|
|
295
292
|
origin,
|
|
@@ -410,7 +407,296 @@ const takeManifestItems = (summary) => {
|
|
|
410
407
|
return taken;
|
|
411
408
|
};
|
|
412
409
|
|
|
410
|
+
const DEP_CAPTION = 'Dependencies in package.json & package-lock.json';
|
|
411
|
+
|
|
412
|
+
const changeMarks = (change) => {
|
|
413
|
+
const marks = [];
|
|
414
|
+
if (change.unused) marks.push('unused');
|
|
415
|
+
if (change.outdated && !change.propose) marks.push('outdated');
|
|
416
|
+
if (change.audit) marks.push(change.audit.severity);
|
|
417
|
+
return marks;
|
|
418
|
+
};
|
|
419
|
+
|
|
420
|
+
const changeSources = (change) => {
|
|
421
|
+
const sources = [];
|
|
422
|
+
if (change.unused) {
|
|
423
|
+
sources.push('npm uninstall');
|
|
424
|
+
return sources;
|
|
425
|
+
}
|
|
426
|
+
if (change.propose && change.outdated) sources.push('npm outdated');
|
|
427
|
+
if (change.audit) sources.push('npm audit');
|
|
428
|
+
return sources;
|
|
429
|
+
};
|
|
430
|
+
|
|
431
|
+
const sectionTitle = (section, action, marks, sources) => {
|
|
432
|
+
const title = action === 'changed' ? 'version changed' : action;
|
|
433
|
+
const kind = section.replace(/ies$/, 'y');
|
|
434
|
+
let label = `${kind} ${title}`;
|
|
435
|
+
if (section === 'field') label = `package.json ${title}`;
|
|
436
|
+
if (section === 'resolved' && action === 'vulnerable') {
|
|
437
|
+
label = 'lockfile vulnerable';
|
|
438
|
+
} else if (section === 'resolved') {
|
|
439
|
+
label = `lockfile resolved ${title}`;
|
|
440
|
+
}
|
|
441
|
+
if (marks.includes('unused')) {
|
|
442
|
+
label = `${kind} unused`;
|
|
443
|
+
const extra = [];
|
|
444
|
+
for (const mark of marks) {
|
|
445
|
+
if (mark !== 'unused') extra.push(mark);
|
|
446
|
+
}
|
|
447
|
+
if (extra.length) label = `${label}, ${extra.join(', ')}`;
|
|
448
|
+
} else if (marks.length) {
|
|
449
|
+
label = `${label}, ${marks.join(', ')}`;
|
|
450
|
+
}
|
|
451
|
+
if (!sources.length) return label;
|
|
452
|
+
return `${sources.join(', ')}: ${label}`;
|
|
453
|
+
};
|
|
454
|
+
|
|
455
|
+
const entryText = (change, side) => {
|
|
456
|
+
const version = side === 'old' ? change.from : change.to;
|
|
457
|
+
return `"${change.name}": "${version}"`;
|
|
458
|
+
};
|
|
459
|
+
|
|
460
|
+
const ctxLine = (text) => {
|
|
461
|
+
const type = 'ctx';
|
|
462
|
+
return { type, text };
|
|
463
|
+
};
|
|
464
|
+
|
|
465
|
+
const warnLine = (text) => {
|
|
466
|
+
const type = 'warn';
|
|
467
|
+
return { type, text };
|
|
468
|
+
};
|
|
469
|
+
|
|
470
|
+
const noteLine = (text) => {
|
|
471
|
+
const type = 'note';
|
|
472
|
+
return { type, text };
|
|
473
|
+
};
|
|
474
|
+
|
|
475
|
+
const noteSepLine = () => {
|
|
476
|
+
const type = 'noteSep';
|
|
477
|
+
const text = '';
|
|
478
|
+
return { type, text };
|
|
479
|
+
};
|
|
480
|
+
|
|
481
|
+
const changeLine = (type, change, side) => {
|
|
482
|
+
const text = entryText(change, side);
|
|
483
|
+
return { type, text };
|
|
484
|
+
};
|
|
485
|
+
|
|
486
|
+
const pushChangeLines = (rows, change) => {
|
|
487
|
+
if (change.unused) {
|
|
488
|
+
const side = change.action === 'added' ? 'new' : 'old';
|
|
489
|
+
rows.push(changeLine('del', change, side));
|
|
490
|
+
return;
|
|
491
|
+
}
|
|
492
|
+
if (change.action === 'added') {
|
|
493
|
+
rows.push(changeLine('add', change, 'new'));
|
|
494
|
+
return;
|
|
495
|
+
}
|
|
496
|
+
if (change.action === 'removed') {
|
|
497
|
+
rows.push(changeLine('del', change, 'old'));
|
|
498
|
+
return;
|
|
499
|
+
}
|
|
500
|
+
if (change.from === change.to) {
|
|
501
|
+
rows.push(changeLine('ctx', change, 'old'));
|
|
502
|
+
return;
|
|
503
|
+
}
|
|
504
|
+
rows.push(changeLine('del', change, 'old'));
|
|
505
|
+
rows.push(changeLine('add', change, 'new'));
|
|
506
|
+
};
|
|
507
|
+
|
|
508
|
+
const lockCountText = (oldCount, newCount) => {
|
|
509
|
+
if (oldCount === newCount) return '';
|
|
510
|
+
return `lockfile packages ${oldCount} → ${newCount}`;
|
|
511
|
+
};
|
|
512
|
+
|
|
513
|
+
const auditNoteTexts = (audit) => {
|
|
514
|
+
if (!audit) return [];
|
|
515
|
+
const notes = [];
|
|
516
|
+
if (Array.isArray(audit.titles)) {
|
|
517
|
+
for (const note of audit.titles) {
|
|
518
|
+
if (note && !notes.includes(note)) notes.push(note);
|
|
519
|
+
}
|
|
520
|
+
} else if (audit.title) {
|
|
521
|
+
notes.push(audit.title);
|
|
522
|
+
}
|
|
523
|
+
const severity = audit.severity;
|
|
524
|
+
if (!notes.length) return [`npm audit ${severity}`];
|
|
525
|
+
const { length } = notes;
|
|
526
|
+
const texts = new Array(length);
|
|
527
|
+
for (let i = 0; i < length; i++) {
|
|
528
|
+
texts[i] = `npm audit ${severity} ${notes[i]}`;
|
|
529
|
+
}
|
|
530
|
+
return texts;
|
|
531
|
+
};
|
|
532
|
+
|
|
533
|
+
const pushAuditNotes = (rows, audit) => {
|
|
534
|
+
const texts = auditNoteTexts(audit);
|
|
535
|
+
if (!texts.length) return;
|
|
536
|
+
rows.push(ctxLine(''));
|
|
537
|
+
let first = true;
|
|
538
|
+
for (const text of texts) {
|
|
539
|
+
if (!first) rows.push(noteSepLine());
|
|
540
|
+
first = false;
|
|
541
|
+
rows.push(noteLine(text));
|
|
542
|
+
}
|
|
543
|
+
};
|
|
544
|
+
|
|
545
|
+
const buildRows = (change, oldCount, newCount) => {
|
|
546
|
+
const rows = [ctxLine(DEP_CAPTION), ctxLine('')];
|
|
547
|
+
if (change) {
|
|
548
|
+
const marks = changeMarks(change);
|
|
549
|
+
const sources = changeSources(change);
|
|
550
|
+
const title = sectionTitle(change.section, change.action, marks, sources);
|
|
551
|
+
const audited = sources.includes('npm audit');
|
|
552
|
+
rows.push(audited ? warnLine(title) : ctxLine(title));
|
|
553
|
+
rows.push(ctxLine(''));
|
|
554
|
+
pushChangeLines(rows, change);
|
|
555
|
+
pushAuditNotes(rows, change.audit);
|
|
556
|
+
}
|
|
557
|
+
const countLine = lockCountText(oldCount, newCount);
|
|
558
|
+
if (countLine) {
|
|
559
|
+
if (rows.at(-1).text !== '') rows.push(ctxLine(''));
|
|
560
|
+
rows.push(ctxLine(countLine));
|
|
561
|
+
}
|
|
562
|
+
return rows;
|
|
563
|
+
};
|
|
564
|
+
|
|
565
|
+
const toHunkLine = (row, blockId) => {
|
|
566
|
+
const type = row.type;
|
|
567
|
+
const text = row.text;
|
|
568
|
+
const noNl = false;
|
|
569
|
+
const id = isCtxType(type) ? null : blockId;
|
|
570
|
+
return { type, text, noNl, blockId: id };
|
|
571
|
+
};
|
|
572
|
+
|
|
573
|
+
const makeHunk = (rows, blockId) => {
|
|
574
|
+
const lines = rows.map((row) => toHunkLine(row, blockId));
|
|
575
|
+
const counts = countSides(lines);
|
|
576
|
+
const oldCount = counts.oldCount;
|
|
577
|
+
const newCount = counts.newCount;
|
|
578
|
+
const header = `@@ -1,${oldCount} +1,${newCount} @@`;
|
|
579
|
+
return { oldStart: 1, oldCount, newStart: 1, newCount, header, lines };
|
|
580
|
+
};
|
|
581
|
+
|
|
582
|
+
const uniquePaths = (items) => {
|
|
583
|
+
const files = [];
|
|
584
|
+
const seen = new Set();
|
|
585
|
+
for (const item of items) {
|
|
586
|
+
const rel = itemPath(item);
|
|
587
|
+
if (!rel || seen.has(rel)) continue;
|
|
588
|
+
seen.add(rel);
|
|
589
|
+
files.push(rel);
|
|
590
|
+
}
|
|
591
|
+
return files;
|
|
592
|
+
};
|
|
593
|
+
|
|
594
|
+
const filesForChange = (change, files) => {
|
|
595
|
+
const manifest = [];
|
|
596
|
+
const lockfile = [];
|
|
597
|
+
for (const rel of files) {
|
|
598
|
+
const meta = depFileMeta(rel);
|
|
599
|
+
if (!meta) continue;
|
|
600
|
+
if (meta.kind === 'manifest') manifest.push(rel);
|
|
601
|
+
else lockfile.push(rel);
|
|
602
|
+
}
|
|
603
|
+
if (change.section === 'field') {
|
|
604
|
+
if (manifest.length) return manifest;
|
|
605
|
+
return files;
|
|
606
|
+
}
|
|
607
|
+
if (change.section === 'resolved') {
|
|
608
|
+
if (lockfile.length) return lockfile;
|
|
609
|
+
return files;
|
|
610
|
+
}
|
|
611
|
+
if (change.propose) {
|
|
612
|
+
if (manifest.length) return manifest;
|
|
613
|
+
return files;
|
|
614
|
+
}
|
|
615
|
+
const both = [...manifest, ...lockfile];
|
|
616
|
+
if (both.length) return both;
|
|
617
|
+
return files;
|
|
618
|
+
};
|
|
619
|
+
|
|
620
|
+
const pickPrimary = (items) => {
|
|
621
|
+
for (const item of items) {
|
|
622
|
+
const rel = itemPath(item);
|
|
623
|
+
const meta = depFileMeta(rel);
|
|
624
|
+
if (meta && meta.kind === 'manifest') return item;
|
|
625
|
+
}
|
|
626
|
+
return items[0];
|
|
627
|
+
};
|
|
628
|
+
|
|
629
|
+
const makeDepItem = (origin, fileItems, hidden, change, extra, blockId) => {
|
|
630
|
+
const allFiles = uniquePaths(fileItems);
|
|
631
|
+
const files = change ? filesForChange(change, allFiles) : allFiles;
|
|
632
|
+
const primary = pickPrimary(fileItems);
|
|
633
|
+
const oldPath = listFilePath(itemPath(primary));
|
|
634
|
+
const newPath = oldPath;
|
|
635
|
+
const isNew = fileItems.some((item) => item.file && item.file.isNew);
|
|
636
|
+
const isDeleted = fileItems.every((item) => item.file && item.file.isDeleted);
|
|
637
|
+
let oldCount = 0;
|
|
638
|
+
let newCount = 0;
|
|
639
|
+
if (!change) {
|
|
640
|
+
oldCount = extra.oldCount ?? 0;
|
|
641
|
+
newCount = extra.newCount ?? 0;
|
|
642
|
+
}
|
|
643
|
+
const rows = buildRows(change, oldCount, newCount);
|
|
644
|
+
const hunk = makeHunk(rows, blockId);
|
|
645
|
+
const isBinary = false;
|
|
646
|
+
const preamble = [];
|
|
647
|
+
const hunks = [hunk];
|
|
648
|
+
const file = {
|
|
649
|
+
oldPath,
|
|
650
|
+
newPath,
|
|
651
|
+
isNew,
|
|
652
|
+
isDeleted,
|
|
653
|
+
isBinary,
|
|
654
|
+
preamble,
|
|
655
|
+
hunks,
|
|
656
|
+
};
|
|
657
|
+
const patchAdd = '';
|
|
658
|
+
const patchRevert = '';
|
|
659
|
+
const items = hidden;
|
|
660
|
+
const dep = { files, items, change };
|
|
661
|
+
const reload = !!(change && change.propose);
|
|
662
|
+
return { origin, file, hunk, blockId, patchAdd, patchRevert, dep, reload };
|
|
663
|
+
};
|
|
664
|
+
|
|
665
|
+
const makeDepItems = (origin, fileItems, hidden, summary) => {
|
|
666
|
+
const ordered = orderedChanges(summary.changes);
|
|
667
|
+
if (!ordered.length) {
|
|
668
|
+
const oldCount = summary.oldCount ?? 0;
|
|
669
|
+
const newCount = summary.newCount ?? 0;
|
|
670
|
+
if (oldCount === newCount) return [];
|
|
671
|
+
return [makeDepItem(origin, fileItems, hidden, null, summary, 0)];
|
|
672
|
+
}
|
|
673
|
+
const { length } = ordered;
|
|
674
|
+
const items = new Array(length);
|
|
675
|
+
for (let i = 0; i < length; i++) {
|
|
676
|
+
items[i] = makeDepItem(origin, fileItems, hidden, ordered[i], summary, i);
|
|
677
|
+
}
|
|
678
|
+
return items;
|
|
679
|
+
};
|
|
680
|
+
|
|
681
|
+
const stubFileItem = (rel, origin) => {
|
|
682
|
+
const file = {
|
|
683
|
+
oldPath: rel,
|
|
684
|
+
newPath: rel,
|
|
685
|
+
isNew: false,
|
|
686
|
+
isDeleted: false,
|
|
687
|
+
isBinary: false,
|
|
688
|
+
preamble: [],
|
|
689
|
+
hunks: [],
|
|
690
|
+
};
|
|
691
|
+
const hunk = null;
|
|
692
|
+
const blockId = 0;
|
|
693
|
+
const patchAdd = '';
|
|
694
|
+
const patchRevert = '';
|
|
695
|
+
return { origin, file, hunk, blockId, patchAdd, patchRevert };
|
|
696
|
+
};
|
|
697
|
+
|
|
413
698
|
module.exports = {
|
|
699
|
+
DEP_CAPTION,
|
|
414
700
|
diffSections,
|
|
415
701
|
mergeResolved,
|
|
416
702
|
orderedChanges,
|
|
@@ -419,4 +705,8 @@ module.exports = {
|
|
|
419
705
|
takeManifestItems,
|
|
420
706
|
foldedDepNames,
|
|
421
707
|
stripFoldedDepItem,
|
|
708
|
+
buildRows,
|
|
709
|
+
makeHunk,
|
|
710
|
+
makeDepItems,
|
|
711
|
+
stubFileItem,
|
|
422
712
|
};
|