@fern-api/generator-cli 0.9.20 → 0.9.21
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/dist/cli.js +726 -122
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -7078,7 +7078,7 @@ var require_require_directory = __commonJS({
|
|
|
7078
7078
|
"../../node_modules/.pnpm/require-directory@2.1.1/node_modules/require-directory/index.js"(exports2, module2) {
|
|
7079
7079
|
"use strict";
|
|
7080
7080
|
var fs3 = require("fs");
|
|
7081
|
-
var
|
|
7081
|
+
var join14 = require("path").join;
|
|
7082
7082
|
var resolve8 = require("path").resolve;
|
|
7083
7083
|
var dirname4 = require("path").dirname;
|
|
7084
7084
|
var defaultOptions2 = {
|
|
@@ -7115,7 +7115,7 @@ var require_require_directory = __commonJS({
|
|
|
7115
7115
|
}
|
|
7116
7116
|
path5 = !path5 ? dirname4(m.filename) : resolve8(dirname4(m.filename), path5);
|
|
7117
7117
|
fs3.readdirSync(path5).forEach(function(filename) {
|
|
7118
|
-
var joined =
|
|
7118
|
+
var joined = join14(path5, filename), files, key, obj;
|
|
7119
7119
|
if (fs3.statSync(joined).isDirectory() && options.recurse) {
|
|
7120
7120
|
files = requireDirectory(m, joined, options);
|
|
7121
7121
|
if (Object.keys(files).length) {
|
|
@@ -18885,7 +18885,7 @@ var require_resolve_block_scalar = __commonJS({
|
|
|
18885
18885
|
if (!header)
|
|
18886
18886
|
return { value: "", type: null, comment: "", range: [start, start, start] };
|
|
18887
18887
|
const type = header.mode === ">" ? Scalar.Scalar.BLOCK_FOLDED : Scalar.Scalar.BLOCK_LITERAL;
|
|
18888
|
-
const lines = scalar.source ?
|
|
18888
|
+
const lines = scalar.source ? splitLines2(scalar.source) : [];
|
|
18889
18889
|
let chompStart = lines.length;
|
|
18890
18890
|
for (let i = lines.length - 1; i >= 0; --i) {
|
|
18891
18891
|
const content = lines[i][1];
|
|
@@ -19043,7 +19043,7 @@ var require_resolve_block_scalar = __commonJS({
|
|
|
19043
19043
|
}
|
|
19044
19044
|
return { mode, indent, chomp, comment, length };
|
|
19045
19045
|
}
|
|
19046
|
-
function
|
|
19046
|
+
function splitLines2(source) {
|
|
19047
19047
|
const split = source.split(/\n( *)/);
|
|
19048
19048
|
const first2 = split[0];
|
|
19049
19049
|
const m = first2.match(/^( *)/);
|
|
@@ -22028,7 +22028,7 @@ var init_diff3 = __esm({
|
|
|
22028
22028
|
}
|
|
22029
22029
|
});
|
|
22030
22030
|
|
|
22031
|
-
// ../../node_modules/.pnpm/@fern-api+replay@0.
|
|
22031
|
+
// ../../node_modules/.pnpm/@fern-api+replay@0.14.0/node_modules/@fern-api/replay/dist/index.js
|
|
22032
22032
|
var dist_exports = {};
|
|
22033
22033
|
__export(dist_exports, {
|
|
22034
22034
|
CREDENTIAL_PATTERNS: () => CREDENTIAL_PATTERNS,
|
|
@@ -22401,11 +22401,43 @@ function threeWayMerge(base, ours, theirs) {
|
|
|
22401
22401
|
}
|
|
22402
22402
|
}
|
|
22403
22403
|
}
|
|
22404
|
-
|
|
22404
|
+
const result = {
|
|
22405
22405
|
content: outputLines.join("\n"),
|
|
22406
22406
|
hasConflicts: conflicts2.length > 0,
|
|
22407
22407
|
conflicts: conflicts2
|
|
22408
22408
|
};
|
|
22409
|
+
if (conflicts2.length === 0) {
|
|
22410
|
+
const dropped = computeDroppedContextLines(baseLines, theirsLines, outputLines);
|
|
22411
|
+
if (dropped.length > 0) {
|
|
22412
|
+
result.droppedContextLines = dropped;
|
|
22413
|
+
}
|
|
22414
|
+
}
|
|
22415
|
+
return result;
|
|
22416
|
+
}
|
|
22417
|
+
function computeDroppedContextLines(baseLines, theirsLines, mergedLines) {
|
|
22418
|
+
const baseCounts = countLines(baseLines);
|
|
22419
|
+
const theirsCounts = countLines(theirsLines);
|
|
22420
|
+
const mergedCounts = countLines(mergedLines);
|
|
22421
|
+
const dropped = [];
|
|
22422
|
+
const seen = /* @__PURE__ */ new Set();
|
|
22423
|
+
for (const line of baseLines) {
|
|
22424
|
+
if (seen.has(line)) continue;
|
|
22425
|
+
const inBase = baseCounts.get(line) ?? 0;
|
|
22426
|
+
const inTheirs = theirsCounts.get(line) ?? 0;
|
|
22427
|
+
const inMerged = mergedCounts.get(line) ?? 0;
|
|
22428
|
+
if (inBase > 0 && inTheirs > 0 && inMerged < Math.min(inBase, inTheirs)) {
|
|
22429
|
+
dropped.push(line);
|
|
22430
|
+
seen.add(line);
|
|
22431
|
+
}
|
|
22432
|
+
}
|
|
22433
|
+
return dropped;
|
|
22434
|
+
}
|
|
22435
|
+
function countLines(lines) {
|
|
22436
|
+
const counts = /* @__PURE__ */ new Map();
|
|
22437
|
+
for (const line of lines) {
|
|
22438
|
+
counts.set(line, (counts.get(line) ?? 0) + 1);
|
|
22439
|
+
}
|
|
22440
|
+
return counts;
|
|
22409
22441
|
}
|
|
22410
22442
|
function tryResolveConflict(oursLines, baseLines, theirsLines) {
|
|
22411
22443
|
if (baseLines.length === 0) {
|
|
@@ -22535,10 +22567,346 @@ function isBinaryFile(filePath) {
|
|
|
22535
22567
|
const ext2 = (0, import_path8.extname)(filePath).toLowerCase();
|
|
22536
22568
|
return BINARY_EXTENSIONS.has(ext2);
|
|
22537
22569
|
}
|
|
22570
|
+
function computeDroppedContextLinesForFile(base, theirs, finalContent) {
|
|
22571
|
+
const baseLines = base.split("\n");
|
|
22572
|
+
const theirsLines = theirs.split("\n");
|
|
22573
|
+
const finalLines = finalContent.split("\n");
|
|
22574
|
+
const baseCounts = /* @__PURE__ */ new Map();
|
|
22575
|
+
const theirsCounts = /* @__PURE__ */ new Map();
|
|
22576
|
+
const finalCounts = /* @__PURE__ */ new Map();
|
|
22577
|
+
for (const l of baseLines) baseCounts.set(l, (baseCounts.get(l) ?? 0) + 1);
|
|
22578
|
+
for (const l of theirsLines) theirsCounts.set(l, (theirsCounts.get(l) ?? 0) + 1);
|
|
22579
|
+
for (const l of finalLines) finalCounts.set(l, (finalCounts.get(l) ?? 0) + 1);
|
|
22580
|
+
const dropped = [];
|
|
22581
|
+
const seen = /* @__PURE__ */ new Set();
|
|
22582
|
+
for (const line of baseLines) {
|
|
22583
|
+
if (seen.has(line)) continue;
|
|
22584
|
+
const inBase = baseCounts.get(line) ?? 0;
|
|
22585
|
+
const inTheirs = theirsCounts.get(line) ?? 0;
|
|
22586
|
+
const inFinal = finalCounts.get(line) ?? 0;
|
|
22587
|
+
if (inBase > 0 && inTheirs > 0 && inFinal < Math.min(inBase, inTheirs)) {
|
|
22588
|
+
dropped.push(line);
|
|
22589
|
+
seen.add(line);
|
|
22590
|
+
}
|
|
22591
|
+
}
|
|
22592
|
+
return dropped;
|
|
22593
|
+
}
|
|
22538
22594
|
function isDiffLineForFile(diffLine, filePath) {
|
|
22539
22595
|
const match2 = diffLine.match(/^diff --git a\/.+ b\/(.+)$/);
|
|
22540
22596
|
return match2 !== null && match2[1] === filePath;
|
|
22541
22597
|
}
|
|
22598
|
+
function normalizeHunkBody(hunk) {
|
|
22599
|
+
let contextC = 0;
|
|
22600
|
+
let removeC = 0;
|
|
22601
|
+
let addC = 0;
|
|
22602
|
+
const trimmed2 = [];
|
|
22603
|
+
for (const line of hunk.lines) {
|
|
22604
|
+
const oldUsed = contextC + removeC;
|
|
22605
|
+
const newUsed = contextC + addC;
|
|
22606
|
+
if (oldUsed >= hunk.oldCount && newUsed >= hunk.newCount) break;
|
|
22607
|
+
trimmed2.push(line);
|
|
22608
|
+
if (line.type === "context") contextC++;
|
|
22609
|
+
else if (line.type === "remove") removeC++;
|
|
22610
|
+
else if (line.type === "add") addC++;
|
|
22611
|
+
}
|
|
22612
|
+
return { ...hunk, lines: trimmed2 };
|
|
22613
|
+
}
|
|
22614
|
+
function extractFileDiffForFile(patchContent, filePath) {
|
|
22615
|
+
const lines = patchContent.split("\n");
|
|
22616
|
+
const out = [];
|
|
22617
|
+
let inTarget = false;
|
|
22618
|
+
for (const line of lines) {
|
|
22619
|
+
if (line.startsWith("diff --git")) {
|
|
22620
|
+
if (inTarget) break;
|
|
22621
|
+
if (isDiffLineForFile2(line, filePath)) {
|
|
22622
|
+
inTarget = true;
|
|
22623
|
+
out.push(line);
|
|
22624
|
+
}
|
|
22625
|
+
continue;
|
|
22626
|
+
}
|
|
22627
|
+
if (inTarget) out.push(line);
|
|
22628
|
+
}
|
|
22629
|
+
return out.length > 0 ? out.join("\n") + "\n" : null;
|
|
22630
|
+
}
|
|
22631
|
+
function isDiffLineForFile2(line, filePath) {
|
|
22632
|
+
const match2 = line.match(/^diff --git a\/(.+) b\/(.+)$/);
|
|
22633
|
+
return match2 !== null && (match2[2] === filePath || match2[1] === filePath);
|
|
22634
|
+
}
|
|
22635
|
+
async function computePerPatchDiff(patch, getCurrentGenContent, getWorkingTreeContent) {
|
|
22636
|
+
const fragments = [];
|
|
22637
|
+
const unlocatableFiles = [];
|
|
22638
|
+
for (const file of patch.files) {
|
|
22639
|
+
const fileDiff = extractFileDiffForFile(patch.patch_content, file);
|
|
22640
|
+
if (fileDiff == null) {
|
|
22641
|
+
unlocatableFiles.push(file);
|
|
22642
|
+
continue;
|
|
22643
|
+
}
|
|
22644
|
+
const hunksRaw = parseHunks(fileDiff).map(normalizeHunkBody);
|
|
22645
|
+
const hunks = hunksRaw.filter((h) => {
|
|
22646
|
+
if (h.lines.length === 0) return false;
|
|
22647
|
+
let ctx = 0, rm3 = 0, add = 0;
|
|
22648
|
+
for (const ln of h.lines) {
|
|
22649
|
+
if (ln.type === "context") ctx++;
|
|
22650
|
+
else if (ln.type === "remove") rm3++;
|
|
22651
|
+
else if (ln.type === "add") add++;
|
|
22652
|
+
}
|
|
22653
|
+
return ctx + rm3 === h.oldCount && ctx + add === h.newCount;
|
|
22654
|
+
});
|
|
22655
|
+
if (hunks.length === 0) {
|
|
22656
|
+
if (hunksRaw.length > 0) unlocatableFiles.push(file);
|
|
22657
|
+
continue;
|
|
22658
|
+
}
|
|
22659
|
+
const currentGen = await getCurrentGenContent(file);
|
|
22660
|
+
const workingTree = await getWorkingTreeContent(file);
|
|
22661
|
+
const isPureNewFile = hunks.every((h) => h.oldCount === 0);
|
|
22662
|
+
const isPureDelete = hunks.every((h) => h.newCount === 0);
|
|
22663
|
+
if (currentGen == null) {
|
|
22664
|
+
if (!isPureNewFile) {
|
|
22665
|
+
unlocatableFiles.push(file);
|
|
22666
|
+
continue;
|
|
22667
|
+
}
|
|
22668
|
+
if (workingTree == null) continue;
|
|
22669
|
+
fragments.push(synthesizeNewFileDiff(file, workingTree));
|
|
22670
|
+
continue;
|
|
22671
|
+
}
|
|
22672
|
+
if (isPureNewFile) {
|
|
22673
|
+
if (workingTree == null) {
|
|
22674
|
+
fragments.push(synthesizeDeleteFileDiff(file, currentGen));
|
|
22675
|
+
continue;
|
|
22676
|
+
}
|
|
22677
|
+
if (workingTree === currentGen) {
|
|
22678
|
+
continue;
|
|
22679
|
+
}
|
|
22680
|
+
const fullDiff = await unifiedDiff(currentGen, workingTree, file);
|
|
22681
|
+
if (fullDiff && fullDiff.trim()) fragments.push(fullDiff);
|
|
22682
|
+
continue;
|
|
22683
|
+
}
|
|
22684
|
+
if (workingTree == null) {
|
|
22685
|
+
if (!isPureDelete) {
|
|
22686
|
+
unlocatableFiles.push(file);
|
|
22687
|
+
continue;
|
|
22688
|
+
}
|
|
22689
|
+
fragments.push(synthesizeDeleteFileDiff(file, currentGen));
|
|
22690
|
+
continue;
|
|
22691
|
+
}
|
|
22692
|
+
const currentGenLines = splitLines(currentGen);
|
|
22693
|
+
const workingTreeLines = splitLines(workingTree);
|
|
22694
|
+
const locInCurrentGenRaw = locateHunksInOurs(hunks, currentGenLines);
|
|
22695
|
+
const locInWorkingTreeRaw = locateHunksInOurs(hunks, workingTreeLines);
|
|
22696
|
+
if (locInCurrentGenRaw == null || locInWorkingTreeRaw == null) {
|
|
22697
|
+
unlocatableFiles.push(file);
|
|
22698
|
+
continue;
|
|
22699
|
+
}
|
|
22700
|
+
const locInCurrentGen = locInCurrentGenRaw.map(
|
|
22701
|
+
(l) => resolveSpan(l, currentGenLines, "old")
|
|
22702
|
+
);
|
|
22703
|
+
const locInWorkingTree = locInWorkingTreeRaw.map(
|
|
22704
|
+
(l) => resolveSpan(l, workingTreeLines, "new")
|
|
22705
|
+
);
|
|
22706
|
+
const overlay = overlayRegions(
|
|
22707
|
+
currentGenLines,
|
|
22708
|
+
locInCurrentGen,
|
|
22709
|
+
workingTreeLines,
|
|
22710
|
+
locInWorkingTree
|
|
22711
|
+
);
|
|
22712
|
+
if (overlay === null) {
|
|
22713
|
+
unlocatableFiles.push(file);
|
|
22714
|
+
continue;
|
|
22715
|
+
}
|
|
22716
|
+
if (overlay === currentGen) {
|
|
22717
|
+
continue;
|
|
22718
|
+
}
|
|
22719
|
+
const fileUnifiedDiff = await unifiedDiff(currentGen, overlay, file);
|
|
22720
|
+
if (fileUnifiedDiff && fileUnifiedDiff.trim()) {
|
|
22721
|
+
fragments.push(fileUnifiedDiff);
|
|
22722
|
+
}
|
|
22723
|
+
}
|
|
22724
|
+
return {
|
|
22725
|
+
diff: fragments.join(""),
|
|
22726
|
+
unlocatableFiles
|
|
22727
|
+
};
|
|
22728
|
+
}
|
|
22729
|
+
async function computePerPatchDiffWithFallback(patch, getCurrentGenContent, getWorkingTreeContent, runCumulativeDiff) {
|
|
22730
|
+
const ppDiff = await computePerPatchDiff(
|
|
22731
|
+
patch,
|
|
22732
|
+
getCurrentGenContent,
|
|
22733
|
+
getWorkingTreeContent
|
|
22734
|
+
);
|
|
22735
|
+
if (ppDiff.unlocatableFiles.length === 0) {
|
|
22736
|
+
return { diff: ppDiff.diff, hadFallback: false, fallbackFiles: [] };
|
|
22737
|
+
}
|
|
22738
|
+
const cumulative = await runCumulativeDiff(ppDiff.unlocatableFiles);
|
|
22739
|
+
if (cumulative === null) {
|
|
22740
|
+
return null;
|
|
22741
|
+
}
|
|
22742
|
+
const merged = ppDiff.diff + (cumulative.trim() ? cumulative : "");
|
|
22743
|
+
return { diff: merged, hadFallback: true, fallbackFiles: ppDiff.unlocatableFiles };
|
|
22744
|
+
}
|
|
22745
|
+
function splitLines(content) {
|
|
22746
|
+
return content.split("\n");
|
|
22747
|
+
}
|
|
22748
|
+
function resolveSpan(loc, oursLines, prefer) {
|
|
22749
|
+
const { hunk, oursOffset } = loc;
|
|
22750
|
+
const oldSide = [];
|
|
22751
|
+
const newSide = [];
|
|
22752
|
+
for (const line of hunk.lines) {
|
|
22753
|
+
if (line.type === "context") {
|
|
22754
|
+
oldSide.push(line.content);
|
|
22755
|
+
newSide.push(line.content);
|
|
22756
|
+
} else if (line.type === "remove") {
|
|
22757
|
+
oldSide.push(line.content);
|
|
22758
|
+
} else if (line.type === "add") {
|
|
22759
|
+
newSide.push(line.content);
|
|
22760
|
+
}
|
|
22761
|
+
}
|
|
22762
|
+
const oldFits = sequenceMatches(oldSide, oursLines, oursOffset);
|
|
22763
|
+
const newFits = sequenceMatches(newSide, oursLines, oursOffset);
|
|
22764
|
+
if (prefer === "old") {
|
|
22765
|
+
if (oldFits) return { ...loc, oursSpan: hunk.oldCount };
|
|
22766
|
+
if (newFits) return { ...loc, oursSpan: hunk.newCount };
|
|
22767
|
+
} else {
|
|
22768
|
+
if (newFits) return { ...loc, oursSpan: hunk.newCount };
|
|
22769
|
+
if (oldFits) return { ...loc, oursSpan: hunk.oldCount };
|
|
22770
|
+
}
|
|
22771
|
+
return loc;
|
|
22772
|
+
}
|
|
22773
|
+
function sequenceMatches(needle, haystack, offset) {
|
|
22774
|
+
if (offset + needle.length > haystack.length) return false;
|
|
22775
|
+
for (let i = 0; i < needle.length; i++) {
|
|
22776
|
+
if (haystack[offset + i] !== needle[i]) return false;
|
|
22777
|
+
}
|
|
22778
|
+
return true;
|
|
22779
|
+
}
|
|
22780
|
+
function overlayRegions(currentGenLines, locInCurrentGen, workingTreeLines, locInWorkingTree) {
|
|
22781
|
+
if (locInCurrentGen.length !== locInWorkingTree.length) {
|
|
22782
|
+
return null;
|
|
22783
|
+
}
|
|
22784
|
+
const out = [];
|
|
22785
|
+
let cursor = 0;
|
|
22786
|
+
for (let i = 0; i < locInCurrentGen.length; i++) {
|
|
22787
|
+
const cg = locInCurrentGen[i];
|
|
22788
|
+
const wt = locInWorkingTree[i];
|
|
22789
|
+
if (cg.oursOffset > cursor) {
|
|
22790
|
+
out.push(...currentGenLines.slice(cursor, cg.oursOffset));
|
|
22791
|
+
}
|
|
22792
|
+
out.push(...workingTreeLines.slice(wt.oursOffset, wt.oursOffset + wt.oursSpan));
|
|
22793
|
+
cursor = cg.oursOffset + cg.oursSpan;
|
|
22794
|
+
}
|
|
22795
|
+
if (cursor < currentGenLines.length) {
|
|
22796
|
+
out.push(...currentGenLines.slice(cursor));
|
|
22797
|
+
}
|
|
22798
|
+
return out.join("\n");
|
|
22799
|
+
}
|
|
22800
|
+
async function unifiedDiff(beforeContent, afterContent, filePath) {
|
|
22801
|
+
if (beforeContent === afterContent) return "";
|
|
22802
|
+
const tmp3 = await (0, import_promises4.mkdtemp)((0, import_path10.join)((0, import_os2.tmpdir)(), "fern-replay-pp-"));
|
|
22803
|
+
try {
|
|
22804
|
+
const beforePath = (0, import_path10.join)(tmp3, "before");
|
|
22805
|
+
const afterPath = (0, import_path10.join)(tmp3, "after");
|
|
22806
|
+
await (0, import_promises4.writeFile)(beforePath, beforeContent, "utf-8");
|
|
22807
|
+
await (0, import_promises4.writeFile)(afterPath, afterContent, "utf-8");
|
|
22808
|
+
const raw = await runGitDiffNoIndex(beforePath, afterPath);
|
|
22809
|
+
if (!raw.trim()) return "";
|
|
22810
|
+
return rewriteDiffHeaders(raw, filePath);
|
|
22811
|
+
} finally {
|
|
22812
|
+
await (0, import_promises4.rm)(tmp3, { recursive: true, force: true });
|
|
22813
|
+
}
|
|
22814
|
+
}
|
|
22815
|
+
function runGitDiffNoIndex(beforePath, afterPath) {
|
|
22816
|
+
return new Promise((resolve22, reject) => {
|
|
22817
|
+
const proc = (0, import_child_process3.spawn)("git", ["diff", "--no-index", "--", beforePath, afterPath]);
|
|
22818
|
+
let stdout = "";
|
|
22819
|
+
let stderr = "";
|
|
22820
|
+
proc.stdout.on("data", (d) => stdout += d.toString());
|
|
22821
|
+
proc.stderr.on("data", (d) => stderr += d.toString());
|
|
22822
|
+
proc.on("close", (code) => {
|
|
22823
|
+
if (code === 0 || code === 1) resolve22(stdout);
|
|
22824
|
+
else reject(new Error(`git diff --no-index failed (code ${code}): ${stderr}`));
|
|
22825
|
+
});
|
|
22826
|
+
});
|
|
22827
|
+
}
|
|
22828
|
+
function rewriteDiffHeaders(raw, filePath) {
|
|
22829
|
+
const lines = raw.split("\n");
|
|
22830
|
+
const out = [];
|
|
22831
|
+
let seenFirstHeader = false;
|
|
22832
|
+
for (const line of lines) {
|
|
22833
|
+
if (line.startsWith("diff --git ")) {
|
|
22834
|
+
out.push(`diff --git a/${filePath} b/${filePath}`);
|
|
22835
|
+
seenFirstHeader = true;
|
|
22836
|
+
continue;
|
|
22837
|
+
}
|
|
22838
|
+
if (!seenFirstHeader) {
|
|
22839
|
+
continue;
|
|
22840
|
+
}
|
|
22841
|
+
if (line.startsWith("--- ")) {
|
|
22842
|
+
out.push(`--- a/${filePath}`);
|
|
22843
|
+
continue;
|
|
22844
|
+
}
|
|
22845
|
+
if (line.startsWith("+++ ")) {
|
|
22846
|
+
out.push(`+++ b/${filePath}`);
|
|
22847
|
+
continue;
|
|
22848
|
+
}
|
|
22849
|
+
out.push(line);
|
|
22850
|
+
}
|
|
22851
|
+
return out.join("\n");
|
|
22852
|
+
}
|
|
22853
|
+
function synthesizeNewFileDiff(file, content) {
|
|
22854
|
+
const lines = content.split("\n");
|
|
22855
|
+
const hasTrailingNewline = content.endsWith("\n");
|
|
22856
|
+
const bodyLines = hasTrailingNewline ? lines.slice(0, -1) : lines;
|
|
22857
|
+
const header = [
|
|
22858
|
+
`diff --git a/${file} b/${file}`,
|
|
22859
|
+
"new file mode 100644",
|
|
22860
|
+
"--- /dev/null",
|
|
22861
|
+
`+++ b/${file}`,
|
|
22862
|
+
`@@ -0,0 +1,${bodyLines.length} @@`
|
|
22863
|
+
].join("\n");
|
|
22864
|
+
const body = bodyLines.map((l) => `+${l}`).join("\n");
|
|
22865
|
+
const trailer = hasTrailingNewline ? "" : "\n\";
|
|
22866
|
+
return header + "\n" + body + trailer + "\n";
|
|
22867
|
+
}
|
|
22868
|
+
function synthesizeDeleteFileDiff(file, content) {
|
|
22869
|
+
const lines = content.split("\n");
|
|
22870
|
+
const hasTrailingNewline = content.endsWith("\n");
|
|
22871
|
+
const bodyLines = hasTrailingNewline ? lines.slice(0, -1) : lines;
|
|
22872
|
+
const header = [
|
|
22873
|
+
`diff --git a/${file} b/${file}`,
|
|
22874
|
+
"deleted file mode 100644",
|
|
22875
|
+
`--- a/${file}`,
|
|
22876
|
+
"+++ /dev/null",
|
|
22877
|
+
`@@ -1,${bodyLines.length} +0,0 @@`
|
|
22878
|
+
].join("\n");
|
|
22879
|
+
const body = bodyLines.map((l) => `-${l}`).join("\n");
|
|
22880
|
+
const trailer = hasTrailingNewline ? "" : "\n\";
|
|
22881
|
+
return header + "\n" + body + trailer + "\n";
|
|
22882
|
+
}
|
|
22883
|
+
function computeCommitBuckets(results, absorbedPatchIds, patchesPassedToCommit) {
|
|
22884
|
+
const resultByPatchId = /* @__PURE__ */ new Map();
|
|
22885
|
+
for (const r2 of results) resultByPatchId.set(r2.patch.id, r2);
|
|
22886
|
+
const applied = [];
|
|
22887
|
+
const unresolved = [];
|
|
22888
|
+
const absorbed = [];
|
|
22889
|
+
for (const patch of patchesPassedToCommit) {
|
|
22890
|
+
if (absorbedPatchIds.has(patch.id)) {
|
|
22891
|
+
absorbed.push(patch);
|
|
22892
|
+
continue;
|
|
22893
|
+
}
|
|
22894
|
+
const r2 = resultByPatchId.get(patch.id);
|
|
22895
|
+
if (!r2) {
|
|
22896
|
+
applied.push(patch);
|
|
22897
|
+
continue;
|
|
22898
|
+
}
|
|
22899
|
+
if (r2.status === "conflict" || patch.status === "unresolved") {
|
|
22900
|
+
unresolved.push(patch);
|
|
22901
|
+
continue;
|
|
22902
|
+
}
|
|
22903
|
+
if (r2.status === "applied") {
|
|
22904
|
+
applied.push(patch);
|
|
22905
|
+
continue;
|
|
22906
|
+
}
|
|
22907
|
+
}
|
|
22908
|
+
return { applied, unresolved, absorbed };
|
|
22909
|
+
}
|
|
22542
22910
|
async function bootstrap(outputDir, options) {
|
|
22543
22911
|
const git = new GitClient(outputDir);
|
|
22544
22912
|
const lockManager = new LockfileManager(outputDir);
|
|
@@ -22703,7 +23071,7 @@ function parseGitLog(log) {
|
|
|
22703
23071
|
});
|
|
22704
23072
|
}
|
|
22705
23073
|
function ensureFernignoreEntries(outputDir) {
|
|
22706
|
-
const fernignorePath = (0,
|
|
23074
|
+
const fernignorePath = (0, import_path12.join)(outputDir, ".fernignore");
|
|
22707
23075
|
let content = "";
|
|
22708
23076
|
if ((0, import_fs9.existsSync)(fernignorePath)) {
|
|
22709
23077
|
content = (0, import_fs9.readFileSync)(fernignorePath, "utf-8");
|
|
@@ -22726,7 +23094,7 @@ function ensureFernignoreEntries(outputDir) {
|
|
|
22726
23094
|
return true;
|
|
22727
23095
|
}
|
|
22728
23096
|
function ensureGitattributesEntries(outputDir) {
|
|
22729
|
-
const gitattributesPath = (0,
|
|
23097
|
+
const gitattributesPath = (0, import_path12.join)(outputDir, ".gitattributes");
|
|
22730
23098
|
let content = "";
|
|
22731
23099
|
if ((0, import_fs9.existsSync)(gitattributesPath)) {
|
|
22732
23100
|
content = (0, import_fs9.readFileSync)(gitattributesPath, "utf-8");
|
|
@@ -22921,7 +23289,7 @@ async function resolve7(outputDir, options) {
|
|
|
22921
23289
|
const resolvingPatches = lockManager.getResolvingPatches();
|
|
22922
23290
|
if (unresolvedPatches.length > 0) {
|
|
22923
23291
|
const applicator = new ReplayApplicator(git, lockManager, outputDir);
|
|
22924
|
-
await applicator.applyPatches(unresolvedPatches);
|
|
23292
|
+
await applicator.applyPatches(unresolvedPatches, { applyMode: "resolve" });
|
|
22925
23293
|
const markerFiles = await findConflictMarkerFiles(git);
|
|
22926
23294
|
if (markerFiles.length > 0) {
|
|
22927
23295
|
for (const patch of unresolvedPatches) {
|
|
@@ -22947,20 +23315,38 @@ async function resolve7(outputDir, options) {
|
|
|
22947
23315
|
if (patchesToCommit.length > 0) {
|
|
22948
23316
|
const currentGen = lock.current_generation;
|
|
22949
23317
|
const detector = new ReplayDetector(git, lockManager, outputDir);
|
|
23318
|
+
const warnings = [];
|
|
22950
23319
|
let patchesResolved = 0;
|
|
22951
23320
|
for (const patch of patchesToCommit) {
|
|
22952
|
-
const
|
|
22953
|
-
|
|
23321
|
+
const result = await computePerPatchDiffWithFallback(
|
|
23322
|
+
patch,
|
|
23323
|
+
(f2) => git.showFile(currentGen, f2),
|
|
23324
|
+
(f2) => (0, import_promises5.readFile)((0, import_path13.join)(outputDir, f2), "utf-8").catch(() => null),
|
|
23325
|
+
(files) => git.exec(["diff", currentGen, "--", ...files]).catch(() => null)
|
|
23326
|
+
);
|
|
23327
|
+
if (result === null) {
|
|
23328
|
+
warnings.push(
|
|
23329
|
+
`Patch ${patch.id}: cumulative-diff fallback failed for unlocatable files; preserving patch unchanged`
|
|
23330
|
+
);
|
|
23331
|
+
continue;
|
|
23332
|
+
}
|
|
23333
|
+
const diff = result.diff;
|
|
23334
|
+
if (!diff.trim()) {
|
|
22954
23335
|
lockManager.removePatch(patch.id);
|
|
22955
23336
|
continue;
|
|
22956
23337
|
}
|
|
23338
|
+
if (result.hadFallback) {
|
|
23339
|
+
warnings.push(
|
|
23340
|
+
`Patch ${patch.id}: ${result.fallbackFiles.join(", ")} could not be anchored; cumulative-diff fallback applied for those files`
|
|
23341
|
+
);
|
|
23342
|
+
}
|
|
22957
23343
|
const newContentHash = detector.computeContentHash(diff);
|
|
22958
|
-
const changedFiles = await getChangedFiles(git, currentGen, patch.files);
|
|
23344
|
+
const changedFiles = result.hadFallback ? await getChangedFiles(git, currentGen, patch.files) : extractFilesFromDiff(diff);
|
|
22959
23345
|
lockManager.markPatchResolved(patch.id, {
|
|
22960
23346
|
patch_content: diff,
|
|
22961
23347
|
content_hash: newContentHash,
|
|
22962
23348
|
base_generation: currentGen,
|
|
22963
|
-
files: changedFiles
|
|
23349
|
+
files: changedFiles.length > 0 ? changedFiles : patch.files
|
|
22964
23350
|
});
|
|
22965
23351
|
patchesResolved++;
|
|
22966
23352
|
}
|
|
@@ -22976,7 +23362,8 @@ async function resolve7(outputDir, options) {
|
|
|
22976
23362
|
success: true,
|
|
22977
23363
|
commitSha: commitSha2,
|
|
22978
23364
|
phase: "committed",
|
|
22979
|
-
patchesResolved
|
|
23365
|
+
patchesResolved,
|
|
23366
|
+
warnings: warnings.length > 0 ? warnings : void 0
|
|
22980
23367
|
};
|
|
22981
23368
|
}
|
|
22982
23369
|
const committer = new ReplayCommitter(git, outputDir);
|
|
@@ -22994,6 +23381,24 @@ async function getChangedFiles(git, currentGen, files) {
|
|
|
22994
23381
|
const changed = filesOutput.trim().split("\n").filter(Boolean).filter((f2) => !f2.startsWith(".fern/"));
|
|
22995
23382
|
return changed.length > 0 ? changed : files;
|
|
22996
23383
|
}
|
|
23384
|
+
function extractFilesFromDiff(unifiedDiff2) {
|
|
23385
|
+
const out = /* @__PURE__ */ new Set();
|
|
23386
|
+
const renameSources = /* @__PURE__ */ new Set();
|
|
23387
|
+
let currentTarget = null;
|
|
23388
|
+
for (const line of unifiedDiff2.split("\n")) {
|
|
23389
|
+
const headerMatch = line.match(/^diff --git a\/(.+?) b\/(.+)$/);
|
|
23390
|
+
if (headerMatch) {
|
|
23391
|
+
currentTarget = headerMatch[2];
|
|
23392
|
+
if (!currentTarget.startsWith(".fern/")) out.add(currentTarget);
|
|
23393
|
+
continue;
|
|
23394
|
+
}
|
|
23395
|
+
if (currentTarget && line.startsWith("rename from ")) {
|
|
23396
|
+
renameSources.add(line.slice("rename from ".length));
|
|
23397
|
+
}
|
|
23398
|
+
}
|
|
23399
|
+
for (const src of renameSources) out.delete(src);
|
|
23400
|
+
return Array.from(out);
|
|
23401
|
+
}
|
|
22997
23402
|
function status(outputDir) {
|
|
22998
23403
|
const lockManager = new LockfileManager(outputDir);
|
|
22999
23404
|
if (!lockManager.exists()) {
|
|
@@ -23041,9 +23446,9 @@ function status(outputDir) {
|
|
|
23041
23446
|
excludePatterns
|
|
23042
23447
|
};
|
|
23043
23448
|
}
|
|
23044
|
-
var import_fs6, import_path7, import_yaml, import_crypto, import_promises3, import_os, import_path8, import_fs7, import_path9, import_crypto2, import_fs8,
|
|
23449
|
+
var import_fs6, import_path7, import_yaml, import_crypto, import_promises3, import_os, import_path8, import_fs7, import_path9, import_promises4, import_os2, import_path10, import_child_process3, import_crypto2, import_fs8, import_path11, import_yaml2, import_crypto3, import_fs9, import_path12, import_fs10, import_promises5, import_path13, __defProp3, __getOwnPropNames3, __esm3, __export3, GitClient_exports, GitClient, init_GitClient, HybridReconstruction_exports, init_HybridReconstruction, CREDENTIAL_PATTERNS, SENSITIVE_FILE_PATTERNS, FERN_BOT_NAME, FERN_BOT_EMAIL, FERN_BOT_LOGIN, FERN_SUPPORT_NAMES, LOCKFILE_HEADER, LockfileNotFoundError, LockfileManager, INFRASTRUCTURE_FILES, ReplayDetector, CONFLICT_OPENER, CONFLICT_SEPARATOR, CONFLICT_CLOSER, BINARY_EXTENSIONS, ReplayApplicator, ReplayCommitter, ReplayService, FernignoreMigrator, REPLAY_FERNIGNORE_ENTRIES, GITATTRIBUTES_ENTRIES, EMPTY_RESULT;
|
|
23045
23450
|
var init_dist3 = __esm({
|
|
23046
|
-
"../../node_modules/.pnpm/@fern-api+replay@0.
|
|
23451
|
+
"../../node_modules/.pnpm/@fern-api+replay@0.14.0/node_modules/@fern-api/replay/dist/index.js"() {
|
|
23047
23452
|
"use strict";
|
|
23048
23453
|
init_esm4();
|
|
23049
23454
|
import_fs6 = require("fs");
|
|
@@ -23058,16 +23463,22 @@ var init_dist3 = __esm({
|
|
|
23058
23463
|
import_fs7 = require("fs");
|
|
23059
23464
|
import_path9 = require("path");
|
|
23060
23465
|
init_esm3();
|
|
23466
|
+
import_promises4 = require("fs/promises");
|
|
23467
|
+
import_os2 = require("os");
|
|
23468
|
+
import_path10 = require("path");
|
|
23469
|
+
import_child_process3 = require("child_process");
|
|
23061
23470
|
import_crypto2 = require("crypto");
|
|
23062
23471
|
import_fs8 = require("fs");
|
|
23063
|
-
|
|
23472
|
+
import_path11 = require("path");
|
|
23064
23473
|
init_esm3();
|
|
23065
23474
|
import_yaml2 = __toESM(require_dist3(), 1);
|
|
23066
23475
|
import_crypto3 = require("crypto");
|
|
23067
23476
|
import_fs9 = require("fs");
|
|
23068
|
-
|
|
23477
|
+
import_path12 = require("path");
|
|
23069
23478
|
init_esm3();
|
|
23070
23479
|
import_fs10 = require("fs");
|
|
23480
|
+
import_promises5 = require("fs/promises");
|
|
23481
|
+
import_path13 = require("path");
|
|
23071
23482
|
__defProp3 = Object.defineProperty;
|
|
23072
23483
|
__getOwnPropNames3 = Object.getOwnPropertyNames;
|
|
23073
23484
|
__esm3 = (fn, res) => function __init() {
|
|
@@ -23095,9 +23506,9 @@ var init_dist3 = __esm({
|
|
|
23095
23506
|
return this.git.raw(args);
|
|
23096
23507
|
}
|
|
23097
23508
|
async execWithInput(args, input) {
|
|
23098
|
-
const { spawn:
|
|
23509
|
+
const { spawn: spawn22 } = await import("child_process");
|
|
23099
23510
|
return new Promise((resolve22, reject) => {
|
|
23100
|
-
const proc =
|
|
23511
|
+
const proc = spawn22("git", args, { cwd: this.repoPath });
|
|
23101
23512
|
let stdout = "";
|
|
23102
23513
|
let stderr = "";
|
|
23103
23514
|
proc.stdout.on("data", (data) => {
|
|
@@ -24021,6 +24432,19 @@ var init_dist3 = __esm({
|
|
|
24021
24432
|
renameCache = /* @__PURE__ */ new Map();
|
|
24022
24433
|
treeExistsCache = /* @__PURE__ */ new Map();
|
|
24023
24434
|
fileTheirsAccumulator = /* @__PURE__ */ new Map();
|
|
24435
|
+
/**
|
|
24436
|
+
* Apply mode for the current `applyPatches` invocation. Set at the start
|
|
24437
|
+
* of `applyPatches`, read by `mergeFile` to decide:
|
|
24438
|
+
* - whether to skip the intra-loop marker strip (kept in `applyPatches`)
|
|
24439
|
+
* - whether to populate the accumulator after a conflicted merge
|
|
24440
|
+
* (resolve mode populates so subsequent patches on the same file
|
|
24441
|
+
* can use patch A's THEIRS as a structurally-correct merge base
|
|
24442
|
+
* when their diff was authored against post-A structure)
|
|
24443
|
+
* - whether to retry THEIRS reconstruction against the accumulator
|
|
24444
|
+
* when the BASE-relative reconstruction produced markers from a
|
|
24445
|
+
* cross-patch context mismatch
|
|
24446
|
+
*/
|
|
24447
|
+
currentApplyMode = "replay";
|
|
24024
24448
|
constructor(git, lockManager, outputDir) {
|
|
24025
24449
|
this.git = git;
|
|
24026
24450
|
this.lockManager = lockManager;
|
|
@@ -24068,8 +24492,23 @@ var init_dist3 = __esm({
|
|
|
24068
24492
|
/**
|
|
24069
24493
|
* Apply all patches, returning results for each.
|
|
24070
24494
|
* Skips patches that match exclude patterns in replay.yml
|
|
24495
|
+
*
|
|
24496
|
+
* `applyMode` controls the post-conflict marker strategy:
|
|
24497
|
+
* - `"replay"` (default): strip conflict markers from disk between
|
|
24498
|
+
* iterations whenever a later patch touches the same file. Lets the
|
|
24499
|
+
* follow-up patch's `git apply --3way` see clean OURS content,
|
|
24500
|
+
* which is what the silent-loss fix (PR #73) relies on. The replay
|
|
24501
|
+
* pipeline calls `revertConflictingFiles` after the loop to clean
|
|
24502
|
+
* any markers that survive.
|
|
24503
|
+
* - `"resolve"`: keep markers on disk. The resolve command needs the
|
|
24504
|
+
* customer to see them. Slow-path 3-way merge naturally preserves
|
|
24505
|
+
* A's markers and B's clean writes when their regions don't overlap;
|
|
24506
|
+
* when they do overlap, the customer gets nested markers and
|
|
24507
|
+
* resolves manually. Either way they aren't silently dropped.
|
|
24071
24508
|
*/
|
|
24072
|
-
async applyPatches(patches) {
|
|
24509
|
+
async applyPatches(patches, opts) {
|
|
24510
|
+
const applyMode = opts?.applyMode ?? "replay";
|
|
24511
|
+
this.currentApplyMode = applyMode;
|
|
24073
24512
|
this.resetAccumulator();
|
|
24074
24513
|
const results = [];
|
|
24075
24514
|
for (let i = 0; i < patches.length; i++) {
|
|
@@ -24084,7 +24523,7 @@ var init_dist3 = __esm({
|
|
|
24084
24523
|
}
|
|
24085
24524
|
const result = await this.applyPatchWithFallback(patch);
|
|
24086
24525
|
results.push(result);
|
|
24087
|
-
if (result.status === "conflict" && result.fileResults) {
|
|
24526
|
+
if (applyMode !== "resolve" && result.status === "conflict" && result.fileResults) {
|
|
24088
24527
|
const laterFiles = /* @__PURE__ */ new Set();
|
|
24089
24528
|
for (let j2 = i + 1; j2 < patches.length; j2++) {
|
|
24090
24529
|
for (const f2 of patches[j2].files) {
|
|
@@ -24114,9 +24553,17 @@ var init_dist3 = __esm({
|
|
|
24114
24553
|
}
|
|
24115
24554
|
return results;
|
|
24116
24555
|
}
|
|
24117
|
-
/**
|
|
24556
|
+
/**
|
|
24557
|
+
* Populate accumulator after git apply succeeds, AND collect per-file
|
|
24558
|
+
* results including any "dropped context lines" — lines that were
|
|
24559
|
+
* present in BASE and THEIRS (unchanged context) but absent from the
|
|
24560
|
+
* final on-disk state because OURS deleted them. This is the fast-path
|
|
24561
|
+
* counterpart to ThreeWayMerge.computeDroppedContextLines used by the
|
|
24562
|
+
* 3-way slow path; both must surface the same warning.
|
|
24563
|
+
*/
|
|
24118
24564
|
async populateAccumulatorForPatch(patch, baseGen, currentTreeHash) {
|
|
24119
|
-
|
|
24565
|
+
const fileResults = [];
|
|
24566
|
+
if (!baseGen) return fileResults;
|
|
24120
24567
|
const tempDir = await (0, import_promises3.mkdtemp)((0, import_path8.join)((0, import_os.tmpdir)(), "replay-acc-"));
|
|
24121
24568
|
const { GitClient: GitClient2 } = await Promise.resolve().then(() => (init_GitClient(), GitClient_exports));
|
|
24122
24569
|
const tempGit = new GitClient2(tempDir);
|
|
@@ -24129,18 +24576,30 @@ var init_dist3 = __esm({
|
|
|
24129
24576
|
const resolvedPath = await this.resolveFilePath(filePath, baseGen.tree_hash, currentTreeHash);
|
|
24130
24577
|
const base = await this.git.showFile(baseGen.tree_hash, filePath);
|
|
24131
24578
|
const theirs = await this.applyPatchToContent(base, patch.patch_content, filePath, tempGit, tempDir);
|
|
24132
|
-
const
|
|
24579
|
+
const finalOnDisk = await (0, import_promises3.readFile)((0, import_path8.join)(this.outputDir, resolvedPath), "utf-8").catch(() => null);
|
|
24580
|
+
const effectiveTheirs = theirs ?? finalOnDisk;
|
|
24133
24581
|
if (effectiveTheirs != null) {
|
|
24134
24582
|
this.fileTheirsAccumulator.set(resolvedPath, {
|
|
24135
24583
|
content: effectiveTheirs,
|
|
24136
24584
|
baseGeneration: patch.base_generation
|
|
24137
24585
|
});
|
|
24138
24586
|
}
|
|
24587
|
+
if (base != null && effectiveTheirs != null && finalOnDisk != null) {
|
|
24588
|
+
const dropped = computeDroppedContextLinesForFile(base, effectiveTheirs, finalOnDisk);
|
|
24589
|
+
if (dropped.length > 0) {
|
|
24590
|
+
fileResults.push({
|
|
24591
|
+
file: resolvedPath,
|
|
24592
|
+
status: "merged",
|
|
24593
|
+
droppedContextLines: dropped
|
|
24594
|
+
});
|
|
24595
|
+
}
|
|
24596
|
+
}
|
|
24139
24597
|
}
|
|
24140
24598
|
} finally {
|
|
24141
24599
|
await (0, import_promises3.rm)(tempDir, { recursive: true }).catch(() => {
|
|
24142
24600
|
});
|
|
24143
24601
|
}
|
|
24602
|
+
return fileResults;
|
|
24144
24603
|
}
|
|
24145
24604
|
async applyPatchWithFallback(patch) {
|
|
24146
24605
|
const baseGen = await this.resolveBaseGeneration(patch.base_generation);
|
|
@@ -24171,11 +24630,12 @@ var init_dist3 = __esm({
|
|
|
24171
24630
|
}
|
|
24172
24631
|
try {
|
|
24173
24632
|
await this.git.execWithInput(["apply", "--3way"], patch.patch_content);
|
|
24174
|
-
await this.populateAccumulatorForPatch(patch, baseGen, currentTreeHash);
|
|
24633
|
+
const fastPathFileResults = await this.populateAccumulatorForPatch(patch, baseGen, currentTreeHash);
|
|
24175
24634
|
return {
|
|
24176
24635
|
patch,
|
|
24177
24636
|
status: "applied",
|
|
24178
24637
|
method: "git-am",
|
|
24638
|
+
...fastPathFileResults.length > 0 && { fileResults: fastPathFileResults },
|
|
24179
24639
|
...Object.keys(resolvedFiles).length > 0 && { resolvedFiles }
|
|
24180
24640
|
};
|
|
24181
24641
|
} catch {
|
|
@@ -24287,19 +24747,23 @@ var init_dist3 = __esm({
|
|
|
24287
24747
|
renameSourcePath
|
|
24288
24748
|
);
|
|
24289
24749
|
}
|
|
24750
|
+
const accumulatorEntry = this.fileTheirsAccumulator.get(resolvedPath);
|
|
24290
24751
|
if (theirs) {
|
|
24291
24752
|
const theirsHasMarkers = theirs.includes("<<<<<<< Generated") || theirs.includes(">>>>>>> Your customization");
|
|
24292
24753
|
const baseHasMarkers = base != null && (base.includes("<<<<<<< Generated") || base.includes(">>>>>>> Your customization"));
|
|
24293
24754
|
if (theirsHasMarkers && !baseHasMarkers) {
|
|
24294
|
-
|
|
24295
|
-
|
|
24296
|
-
|
|
24297
|
-
|
|
24298
|
-
|
|
24755
|
+
if (accumulatorEntry) {
|
|
24756
|
+
theirs = null;
|
|
24757
|
+
} else {
|
|
24758
|
+
return {
|
|
24759
|
+
file: resolvedPath,
|
|
24760
|
+
status: "skipped",
|
|
24761
|
+
reason: "stale-conflict-markers"
|
|
24762
|
+
};
|
|
24763
|
+
}
|
|
24299
24764
|
}
|
|
24300
24765
|
}
|
|
24301
24766
|
let useAccumulatorAsMergeBase = false;
|
|
24302
|
-
const accumulatorEntry = this.fileTheirsAccumulator.get(resolvedPath);
|
|
24303
24767
|
if (accumulatorEntry && (theirs == null || base == null)) {
|
|
24304
24768
|
theirs = await this.applyPatchToContent(
|
|
24305
24769
|
accumulatorEntry.content,
|
|
@@ -24406,7 +24870,8 @@ var init_dist3 = __esm({
|
|
|
24406
24870
|
const outDir = (0, import_path8.dirname)(oursPath);
|
|
24407
24871
|
await (0, import_promises3.mkdir)(outDir, { recursive: true });
|
|
24408
24872
|
await (0, import_promises3.writeFile)(oursPath, merged.content);
|
|
24409
|
-
|
|
24873
|
+
const populateAccumulator = effective_theirs != null && (!merged.hasConflicts || this.currentApplyMode === "resolve");
|
|
24874
|
+
if (populateAccumulator) {
|
|
24410
24875
|
this.fileTheirsAccumulator.set(resolvedPath, {
|
|
24411
24876
|
content: effective_theirs,
|
|
24412
24877
|
baseGeneration: patch.base_generation
|
|
@@ -24421,7 +24886,11 @@ var init_dist3 = __esm({
|
|
|
24421
24886
|
conflictMetadata: metadata
|
|
24422
24887
|
};
|
|
24423
24888
|
}
|
|
24424
|
-
return {
|
|
24889
|
+
return {
|
|
24890
|
+
file: resolvedPath,
|
|
24891
|
+
status: "merged",
|
|
24892
|
+
...merged.droppedContextLines && merged.droppedContextLines.length > 0 ? { droppedContextLines: merged.droppedContextLines } : {}
|
|
24893
|
+
};
|
|
24425
24894
|
} catch (error) {
|
|
24426
24895
|
return {
|
|
24427
24896
|
file: filePath,
|
|
@@ -24632,13 +25101,46 @@ CLI Version: ${options.cliVersion}`;
|
|
|
24632
25101
|
await this.git.exec(["commit", "-m", fullMessage]);
|
|
24633
25102
|
return (await this.git.exec(["rev-parse", "HEAD"])).trim();
|
|
24634
25103
|
}
|
|
24635
|
-
async commitReplay(_patchCount, patches, message) {
|
|
25104
|
+
async commitReplay(_patchCount, patches, message, options) {
|
|
24636
25105
|
await this.stageAll();
|
|
24637
25106
|
if (!await this.hasStagedChanges()) {
|
|
24638
25107
|
return (await this.git.exec(["rev-parse", "HEAD"])).trim();
|
|
24639
25108
|
}
|
|
24640
25109
|
let fullMessage = message ?? `[fern-replay] Applied customizations`;
|
|
24641
|
-
|
|
25110
|
+
const buckets = options?.buckets;
|
|
25111
|
+
if (buckets) {
|
|
25112
|
+
if (buckets.applied.length > 0) {
|
|
25113
|
+
fullMessage += `
|
|
25114
|
+
|
|
25115
|
+
Patches applied (${buckets.applied.length}):`;
|
|
25116
|
+
for (const p of buckets.applied) {
|
|
25117
|
+
fullMessage += `
|
|
25118
|
+
- ${p.id}: ${p.original_message}`;
|
|
25119
|
+
}
|
|
25120
|
+
}
|
|
25121
|
+
if (buckets.unresolved.length > 0) {
|
|
25122
|
+
fullMessage += `
|
|
25123
|
+
|
|
25124
|
+
Patches with unresolved conflicts (${buckets.unresolved.length}):`;
|
|
25125
|
+
for (const p of buckets.unresolved) {
|
|
25126
|
+
fullMessage += `
|
|
25127
|
+
- ${p.id}: ${p.original_message}`;
|
|
25128
|
+
}
|
|
25129
|
+
fullMessage += `
|
|
25130
|
+
Run \`fern-replay resolve\` to apply these customizations.`;
|
|
25131
|
+
}
|
|
25132
|
+
if (buckets.absorbed.length > 0) {
|
|
25133
|
+
fullMessage += `
|
|
25134
|
+
|
|
25135
|
+
Patches absorbed by generator (${buckets.absorbed.length}):`;
|
|
25136
|
+
for (const p of buckets.absorbed) {
|
|
25137
|
+
fullMessage += `
|
|
25138
|
+
- ${p.id}: ${p.original_message}`;
|
|
25139
|
+
}
|
|
25140
|
+
fullMessage += `
|
|
25141
|
+
The generator now produces these customizations natively.`;
|
|
25142
|
+
}
|
|
25143
|
+
} else if (patches && patches.length > 0) {
|
|
24642
25144
|
fullMessage += "\n\nPatches replayed:";
|
|
24643
25145
|
for (const patch of patches) {
|
|
24644
25146
|
fullMessage += `
|
|
@@ -24672,6 +25174,7 @@ CLI Version: ${options.cliVersion}`;
|
|
|
24672
25174
|
}
|
|
24673
25175
|
};
|
|
24674
25176
|
init_GitClient();
|
|
25177
|
+
init_HybridReconstruction();
|
|
24675
25178
|
ReplayService = class {
|
|
24676
25179
|
git;
|
|
24677
25180
|
detector;
|
|
@@ -25065,6 +25568,7 @@ CLI Version: ${options.cliVersion}`;
|
|
|
25065
25568
|
if (newPatches.length > 0) {
|
|
25066
25569
|
results = await this.applicator.applyPatches(newPatches);
|
|
25067
25570
|
this._lastApplyResults = results;
|
|
25571
|
+
this.recordDroppedContextLineWarnings(results);
|
|
25068
25572
|
this.revertConflictingFiles(results);
|
|
25069
25573
|
for (const result of results) {
|
|
25070
25574
|
if (result.status === "conflict") {
|
|
@@ -25083,7 +25587,8 @@ CLI Version: ${options.cliVersion}`;
|
|
|
25083
25587
|
if (newPatches.length > 0) {
|
|
25084
25588
|
if (!options?.stageOnly) {
|
|
25085
25589
|
const appliedCount = results.filter((r2) => r2.status === "applied").length;
|
|
25086
|
-
|
|
25590
|
+
const buckets = computeCommitBuckets(results, rebaseCounts.absorbedPatchIds, newPatches);
|
|
25591
|
+
await this.committer.commitReplay(appliedCount, newPatches, void 0, { buckets });
|
|
25087
25592
|
} else {
|
|
25088
25593
|
await this.committer.stageAll();
|
|
25089
25594
|
}
|
|
@@ -25146,12 +25651,21 @@ CLI Version: ${options.cliVersion}`;
|
|
|
25146
25651
|
(p) => preRebasePatchIds.has(p.id) && !postRebasePatchIds.has(p.id)
|
|
25147
25652
|
);
|
|
25148
25653
|
existingPatches = this.lockManager.getPatches();
|
|
25149
|
-
const seenHashes = /* @__PURE__ */ new
|
|
25654
|
+
const seenHashes = /* @__PURE__ */ new Map();
|
|
25150
25655
|
for (const p of existingPatches) {
|
|
25151
|
-
|
|
25152
|
-
|
|
25656
|
+
const priorOrigin = seenHashes.get(p.content_hash);
|
|
25657
|
+
if (priorOrigin !== void 0) {
|
|
25658
|
+
const provenanceMissing = !priorOrigin || !p.original_commit;
|
|
25659
|
+
const sameOrigin = priorOrigin === p.original_commit;
|
|
25660
|
+
if (sameOrigin && !provenanceMissing) {
|
|
25661
|
+
this.lockManager.removePatch(p.id);
|
|
25662
|
+
} else {
|
|
25663
|
+
this.warnings.push(
|
|
25664
|
+
`Preserving patch ${p.id} (commit ${(p.original_commit || "<missing>").slice(0, 7)}): shares content_hash with a prior patch ${provenanceMissing ? "(provenance missing on at least one side)" : "from a different source commit"}. Both retained to avoid silent customization loss (FER-9983).`
|
|
25665
|
+
);
|
|
25666
|
+
}
|
|
25153
25667
|
} else {
|
|
25154
|
-
seenHashes.
|
|
25668
|
+
seenHashes.set(p.content_hash, p.original_commit);
|
|
25155
25669
|
}
|
|
25156
25670
|
}
|
|
25157
25671
|
existingPatches = this.lockManager.getPatches();
|
|
@@ -25212,6 +25726,7 @@ CLI Version: ${options.cliVersion}`;
|
|
|
25212
25726
|
const genSha = prep._prepared.genSha;
|
|
25213
25727
|
const results = await this.applicator.applyPatches(allPatches);
|
|
25214
25728
|
this._lastApplyResults = results;
|
|
25729
|
+
this.recordDroppedContextLineWarnings(results);
|
|
25215
25730
|
this.revertConflictingFiles(results);
|
|
25216
25731
|
for (const result of results) {
|
|
25217
25732
|
if (result.status === "conflict") {
|
|
@@ -25239,7 +25754,8 @@ CLI Version: ${options.cliVersion}`;
|
|
|
25239
25754
|
await this.committer.stageAll();
|
|
25240
25755
|
} else {
|
|
25241
25756
|
const appliedCount = results.filter((r2) => r2.status === "applied").length;
|
|
25242
|
-
|
|
25757
|
+
const buckets = computeCommitBuckets(results, rebaseCounts.absorbedPatchIds, allPatches);
|
|
25758
|
+
await this.committer.commitReplay(appliedCount, allPatches, void 0, { buckets });
|
|
25243
25759
|
}
|
|
25244
25760
|
const warnings = [...detectorWarnings, ...this.warnings];
|
|
25245
25761
|
return this.buildReport(
|
|
@@ -25263,7 +25779,7 @@ CLI Version: ${options.cliVersion}`;
|
|
|
25263
25779
|
let repointed = 0;
|
|
25264
25780
|
let contentRebased = 0;
|
|
25265
25781
|
let keptAsUserOwned = 0;
|
|
25266
|
-
const seenContentHashes = /* @__PURE__ */ new
|
|
25782
|
+
const seenContentHashes = /* @__PURE__ */ new Map();
|
|
25267
25783
|
const absorbedPatchIds = /* @__PURE__ */ new Set();
|
|
25268
25784
|
const fernignorePatterns = this.readFernignorePatterns();
|
|
25269
25785
|
for (const result of results) {
|
|
@@ -25277,6 +25793,23 @@ CLI Version: ${options.cliVersion}`;
|
|
|
25277
25793
|
}
|
|
25278
25794
|
}
|
|
25279
25795
|
}
|
|
25796
|
+
const conflictedFilePaths = /* @__PURE__ */ new Set();
|
|
25797
|
+
for (const r2 of results) {
|
|
25798
|
+
if (r2.status !== "conflict") continue;
|
|
25799
|
+
if (r2.fileResults) {
|
|
25800
|
+
for (const fr of r2.fileResults) {
|
|
25801
|
+
if (fr.status !== "conflict") continue;
|
|
25802
|
+
conflictedFilePaths.add(fr.file);
|
|
25803
|
+
if (r2.resolvedFiles) {
|
|
25804
|
+
for (const [orig, resolved] of Object.entries(r2.resolvedFiles)) {
|
|
25805
|
+
if (resolved === fr.file) conflictedFilePaths.add(orig);
|
|
25806
|
+
}
|
|
25807
|
+
}
|
|
25808
|
+
}
|
|
25809
|
+
} else {
|
|
25810
|
+
for (const f2 of r2.patch.files) conflictedFilePaths.add(f2);
|
|
25811
|
+
}
|
|
25812
|
+
}
|
|
25280
25813
|
for (const result of results) {
|
|
25281
25814
|
if (result.status === "conflict" && result.fileResults) {
|
|
25282
25815
|
await this.trimAbsorbedFiles(result, currentGenSha);
|
|
@@ -25344,6 +25877,18 @@ CLI Version: ${options.cliVersion}`;
|
|
|
25344
25877
|
keptAsUserOwned++;
|
|
25345
25878
|
continue;
|
|
25346
25879
|
}
|
|
25880
|
+
const overlapsConflicted = patch.files.some((f2) => conflictedFilePaths.has(f2));
|
|
25881
|
+
if (overlapsConflicted) {
|
|
25882
|
+
patch.status = "unresolved";
|
|
25883
|
+
try {
|
|
25884
|
+
this.lockManager.updatePatch(patch.id, { status: "unresolved" });
|
|
25885
|
+
} catch {
|
|
25886
|
+
}
|
|
25887
|
+
this.warnings.push(
|
|
25888
|
+
`Patch ${patch.id} (${patch.original_message}) was preserved as unresolved because an earlier patch conflicted on the same file(s) (${patch.files.join(", ")}). Run \`fern replay resolve\` to apply this customization manually.`
|
|
25889
|
+
);
|
|
25890
|
+
continue;
|
|
25891
|
+
}
|
|
25347
25892
|
this.lockManager.removePatch(patch.id);
|
|
25348
25893
|
absorbedPatchIds.add(patch.id);
|
|
25349
25894
|
absorbed++;
|
|
@@ -25359,13 +25904,22 @@ CLI Version: ${options.cliVersion}`;
|
|
|
25359
25904
|
continue;
|
|
25360
25905
|
}
|
|
25361
25906
|
const newContentHash = this.detector.computeContentHash(diff);
|
|
25362
|
-
|
|
25363
|
-
|
|
25364
|
-
|
|
25365
|
-
|
|
25366
|
-
|
|
25907
|
+
const priorOrigin = seenContentHashes.get(newContentHash);
|
|
25908
|
+
if (priorOrigin !== void 0) {
|
|
25909
|
+
const provenanceMissing = !priorOrigin || !patch.original_commit;
|
|
25910
|
+
const sameOrigin = priorOrigin === patch.original_commit;
|
|
25911
|
+
if (sameOrigin && !provenanceMissing) {
|
|
25912
|
+
this.lockManager.removePatch(patch.id);
|
|
25913
|
+
absorbedPatchIds.add(patch.id);
|
|
25914
|
+
absorbed++;
|
|
25915
|
+
continue;
|
|
25916
|
+
}
|
|
25917
|
+
this.warnings.push(
|
|
25918
|
+
`Preserving patch ${patch.id} (commit ${(patch.original_commit || "<missing>").slice(0, 7)}): shares content_hash with a prior patch ${provenanceMissing ? "(provenance missing on at least one side)" : "from a different source commit"}. Both retained to avoid silent customization loss (FER-9983).`
|
|
25919
|
+
);
|
|
25920
|
+
} else {
|
|
25921
|
+
seenContentHashes.set(newContentHash, patch.original_commit);
|
|
25367
25922
|
}
|
|
25368
|
-
seenContentHashes.add(newContentHash);
|
|
25369
25923
|
patch.base_generation = currentGenSha;
|
|
25370
25924
|
patch.patch_content = diff;
|
|
25371
25925
|
patch.content_hash = newContentHash;
|
|
@@ -25541,8 +26095,14 @@ CLI Version: ${options.cliVersion}`;
|
|
|
25541
26095
|
}
|
|
25542
26096
|
if (patch.base_generation === currentGen) {
|
|
25543
26097
|
try {
|
|
25544
|
-
const
|
|
25545
|
-
|
|
26098
|
+
const ppResult = await computePerPatchDiffWithFallback(
|
|
26099
|
+
patch,
|
|
26100
|
+
(f2) => this.git.showFile(currentGen, f2),
|
|
26101
|
+
(f2) => this.git.showFile("HEAD", f2),
|
|
26102
|
+
(files) => this.git.exec(["diff", currentGen, "HEAD", "--", ...files]).catch(() => null)
|
|
26103
|
+
);
|
|
26104
|
+
if (ppResult === null) continue;
|
|
26105
|
+
const diff = ppResult.diff;
|
|
25546
26106
|
if (!diff.trim()) {
|
|
25547
26107
|
if (await allPatchFilesUserOwned(patch)) continue;
|
|
25548
26108
|
this.lockManager.removePatch(patch.id);
|
|
@@ -25584,8 +26144,14 @@ CLI Version: ${options.cliVersion}`;
|
|
|
25584
26144
|
try {
|
|
25585
26145
|
const markerFiles = await this.git.exec(["grep", "-l", "<<<<<<< Generated", "HEAD", "--", ...patch.files]).catch(() => "");
|
|
25586
26146
|
if (markerFiles.trim()) continue;
|
|
25587
|
-
const
|
|
25588
|
-
|
|
26147
|
+
const ppResult = await computePerPatchDiffWithFallback(
|
|
26148
|
+
patch,
|
|
26149
|
+
(f2) => this.git.showFile(currentGen, f2),
|
|
26150
|
+
(f2) => this.git.showFile("HEAD", f2),
|
|
26151
|
+
(files) => this.git.exec(["diff", currentGen, "HEAD", "--", ...files]).catch(() => null)
|
|
26152
|
+
);
|
|
26153
|
+
if (ppResult === null) continue;
|
|
26154
|
+
const diff = ppResult.diff;
|
|
25589
26155
|
if (!diff.trim()) {
|
|
25590
26156
|
if (await allPatchFilesUserOwned(patch)) {
|
|
25591
26157
|
try {
|
|
@@ -25610,6 +26176,32 @@ CLI Version: ${options.cliVersion}`;
|
|
|
25610
26176
|
}
|
|
25611
26177
|
return { conflictResolved, conflictAbsorbed, contentRefreshed };
|
|
25612
26178
|
}
|
|
26179
|
+
/**
|
|
26180
|
+
* After applyPatches(), surface a warning for each (patch × file) where
|
|
26181
|
+
* diff3 silently dropped lines that were unchanged context in the
|
|
26182
|
+
* customer's THEIRS. The deletion stays on disk (correct diff3 outcome),
|
|
26183
|
+
* but the customer must learn so they can re-add the lines if they
|
|
26184
|
+
* relied on them. This is the "surface or preserve, never silently drop"
|
|
26185
|
+
* contract for legitimate-deletion cases.
|
|
26186
|
+
*/
|
|
26187
|
+
recordDroppedContextLineWarnings(results) {
|
|
26188
|
+
const PREVIEW_COUNT = 5;
|
|
26189
|
+
for (const result of results) {
|
|
26190
|
+
if (!result.fileResults) continue;
|
|
26191
|
+
for (const fr of result.fileResults) {
|
|
26192
|
+
const dropped = fr.droppedContextLines;
|
|
26193
|
+
if (!dropped || dropped.length === 0) continue;
|
|
26194
|
+
const preview = dropped.slice(0, PREVIEW_COUNT).map((line) => ` ${line}`).join("\n");
|
|
26195
|
+
const more = dropped.length > PREVIEW_COUNT ? `
|
|
26196
|
+
... and ${dropped.length - PREVIEW_COUNT} more` : "";
|
|
26197
|
+
this.warnings.push(
|
|
26198
|
+
`${fr.file}: ${dropped.length} line(s) that appeared as unchanged context in your customization were deleted by the new generator output. The merge followed the deletion. First lines deleted:
|
|
26199
|
+
${preview}${more}
|
|
26200
|
+
If you want to keep these lines, restore them in a follow-up commit and re-run replay; otherwise this warning can be safely ignored.`
|
|
26201
|
+
);
|
|
26202
|
+
}
|
|
26203
|
+
}
|
|
26204
|
+
}
|
|
25613
26205
|
/**
|
|
25614
26206
|
* After applyPatches(), strip conflict markers from conflicting files
|
|
25615
26207
|
* so only clean content is committed. Keeps the Generated (OURS) side.
|
|
@@ -25667,6 +26259,9 @@ CLI Version: ${options.cliVersion}`;
|
|
|
25667
26259
|
};
|
|
25668
26260
|
}).filter((d) => d.files.length > 0);
|
|
25669
26261
|
const partialCount = conflictDetails.filter((d) => d.cleanFiles && d.cleanFiles.length > 0).length;
|
|
26262
|
+
const unresolvedResults = results.filter(
|
|
26263
|
+
(r2) => r2.status === "conflict" || r2.patch.status === "unresolved"
|
|
26264
|
+
);
|
|
25670
26265
|
return {
|
|
25671
26266
|
flow,
|
|
25672
26267
|
patchesDetected: patches.length,
|
|
@@ -25683,7 +26278,7 @@ CLI Version: ${options.cliVersion}`;
|
|
|
25683
26278
|
patchesRefreshed: preRebaseCounts && preRebaseCounts.contentRefreshed > 0 ? preRebaseCounts.contentRefreshed : void 0,
|
|
25684
26279
|
conflicts: conflictResults.flatMap((r2) => r2.fileResults?.filter((f2) => f2.status === "conflict") ?? []),
|
|
25685
26280
|
conflictDetails: conflictDetails.length > 0 ? conflictDetails : void 0,
|
|
25686
|
-
unresolvedPatches:
|
|
26281
|
+
unresolvedPatches: unresolvedResults.length > 0 ? unresolvedResults.map((r2) => ({
|
|
25687
26282
|
patchId: r2.patch.id,
|
|
25688
26283
|
patchMessage: r2.patch.original_message,
|
|
25689
26284
|
files: r2.patch.files,
|
|
@@ -25704,10 +26299,10 @@ CLI Version: ${options.cliVersion}`;
|
|
|
25704
26299
|
this.outputDir = outputDir;
|
|
25705
26300
|
}
|
|
25706
26301
|
fernignoreExists() {
|
|
25707
|
-
return (0, import_fs8.existsSync)((0,
|
|
26302
|
+
return (0, import_fs8.existsSync)((0, import_path11.join)(this.outputDir, ".fernignore"));
|
|
25708
26303
|
}
|
|
25709
26304
|
readFernignorePatterns() {
|
|
25710
|
-
const fernignorePath = (0,
|
|
26305
|
+
const fernignorePath = (0, import_path11.join)(this.outputDir, ".fernignore");
|
|
25711
26306
|
if (!(0, import_fs8.existsSync)(fernignorePath)) {
|
|
25712
26307
|
return [];
|
|
25713
26308
|
}
|
|
@@ -25767,7 +26362,16 @@ CLI Version: ${options.cliVersion}`;
|
|
|
25767
26362
|
original_author: "Fern Replay <replay@buildwithfern.com>",
|
|
25768
26363
|
base_generation: currentGen.commit_sha,
|
|
25769
26364
|
files: patchFiles,
|
|
25770
|
-
patch_content: patchContent
|
|
26365
|
+
patch_content: patchContent,
|
|
26366
|
+
// Synthetic patches captured from .fernignore-protected files
|
|
26367
|
+
// are user-owned by definition — the customer's content
|
|
26368
|
+
// diverges from the generator's pristine output, and the
|
|
26369
|
+
// generator never produced this divergent content. Without
|
|
26370
|
+
// this flag, removing the file from .fernignore later (so
|
|
26371
|
+
// it leaves the protection check in `isFileUserOwned`) would
|
|
26372
|
+
// expose the patch to absorption on the next regen,
|
|
26373
|
+
// silently losing the customization.
|
|
26374
|
+
user_owned: true
|
|
25771
26375
|
});
|
|
25772
26376
|
trackedByBoth.push({
|
|
25773
26377
|
file: pattern,
|
|
@@ -25800,7 +26404,7 @@ CLI Version: ${options.cliVersion}`;
|
|
|
25800
26404
|
return results;
|
|
25801
26405
|
}
|
|
25802
26406
|
readFileContent(filePath) {
|
|
25803
|
-
const fullPath = (0,
|
|
26407
|
+
const fullPath = (0, import_path11.join)(this.outputDir, filePath);
|
|
25804
26408
|
if (!(0, import_fs8.existsSync)(fullPath)) {
|
|
25805
26409
|
return null;
|
|
25806
26410
|
}
|
|
@@ -25865,7 +26469,7 @@ CLI Version: ${options.cliVersion}`;
|
|
|
25865
26469
|
};
|
|
25866
26470
|
}
|
|
25867
26471
|
movePatternsToReplayYml(patterns) {
|
|
25868
|
-
const replayYmlPath = (0,
|
|
26472
|
+
const replayYmlPath = (0, import_path11.join)(this.outputDir, ".fern", "replay.yml");
|
|
25869
26473
|
let config = {};
|
|
25870
26474
|
if ((0, import_fs8.existsSync)(replayYmlPath)) {
|
|
25871
26475
|
const content = (0, import_fs8.readFileSync)(replayYmlPath, "utf-8");
|
|
@@ -25874,7 +26478,7 @@ CLI Version: ${options.cliVersion}`;
|
|
|
25874
26478
|
const existing = config.exclude ?? [];
|
|
25875
26479
|
const merged = [.../* @__PURE__ */ new Set([...existing, ...patterns])];
|
|
25876
26480
|
config.exclude = merged;
|
|
25877
|
-
const dir = (0,
|
|
26481
|
+
const dir = (0, import_path11.dirname)(replayYmlPath);
|
|
25878
26482
|
if (!(0, import_fs8.existsSync)(dir)) {
|
|
25879
26483
|
(0, import_fs8.mkdirSync)(dir, { recursive: true });
|
|
25880
26484
|
}
|
|
@@ -26378,7 +26982,7 @@ var require_cross_spawn = __commonJS({
|
|
|
26378
26982
|
var cp2 = require("child_process");
|
|
26379
26983
|
var parse3 = require_parse2();
|
|
26380
26984
|
var enoent = require_enoent();
|
|
26381
|
-
function
|
|
26985
|
+
function spawn3(command, args, options) {
|
|
26382
26986
|
const parsed = parse3(command, args, options);
|
|
26383
26987
|
const spawned = cp2.spawn(parsed.command, parsed.args, parsed.options);
|
|
26384
26988
|
enoent.hookChildProcess(spawned, parsed);
|
|
@@ -26390,8 +26994,8 @@ var require_cross_spawn = __commonJS({
|
|
|
26390
26994
|
result.error = result.error || enoent.verifyENOENTSync(result.status, parsed);
|
|
26391
26995
|
return result;
|
|
26392
26996
|
}
|
|
26393
|
-
module2.exports =
|
|
26394
|
-
module2.exports.spawn =
|
|
26997
|
+
module2.exports = spawn3;
|
|
26998
|
+
module2.exports.spawn = spawn3;
|
|
26395
26999
|
module2.exports.sync = spawnSync;
|
|
26396
27000
|
module2.exports._parse = parse3;
|
|
26397
27001
|
module2.exports._enoent = enoent;
|
|
@@ -28430,8 +29034,8 @@ function resolve(...paths) {
|
|
|
28430
29034
|
|
|
28431
29035
|
// src/cli.ts
|
|
28432
29036
|
var import_fs15 = __toESM(require("fs"));
|
|
28433
|
-
var
|
|
28434
|
-
var
|
|
29037
|
+
var import_promises13 = require("fs/promises");
|
|
29038
|
+
var import_path20 = __toESM(require("path"));
|
|
28435
29039
|
|
|
28436
29040
|
// ../../node_modules/.pnpm/yargs@17.7.2/node_modules/yargs/build/lib/yerror.js
|
|
28437
29041
|
var YError = class _YError extends Error {
|
|
@@ -38132,42 +38736,42 @@ function replayForget(params) {
|
|
|
38132
38736
|
// src/replay/replay-init.ts
|
|
38133
38737
|
init_dist3();
|
|
38134
38738
|
var import_fs11 = require("fs");
|
|
38135
|
-
var
|
|
38739
|
+
var import_path15 = require("path");
|
|
38136
38740
|
var import_tmp_promise2 = __toESM(require_tmp_promise());
|
|
38137
38741
|
|
|
38138
38742
|
// src/replay/fernignore.ts
|
|
38139
|
-
var
|
|
38140
|
-
var
|
|
38743
|
+
var import_promises6 = require("fs/promises");
|
|
38744
|
+
var import_path14 = require("path");
|
|
38141
38745
|
var REPLAY_FERNIGNORE_ENTRIES2 = [".fern/replay.lock", ".fern/replay.yml", ".gitattributes"];
|
|
38142
38746
|
var GITATTRIBUTES_ENTRIES2 = [".fern/replay.lock linguist-generated=true"];
|
|
38143
38747
|
async function ensureReplayFernignoreEntries(outputDir) {
|
|
38144
|
-
const fernignorePath = (0,
|
|
38748
|
+
const fernignorePath = (0, import_path14.join)(outputDir, ".fernignore");
|
|
38145
38749
|
let content = "";
|
|
38146
38750
|
try {
|
|
38147
|
-
content = await (0,
|
|
38751
|
+
content = await (0, import_promises6.readFile)(fernignorePath, "utf-8");
|
|
38148
38752
|
} catch {
|
|
38149
38753
|
}
|
|
38150
38754
|
const lines = content.split("\n");
|
|
38151
38755
|
const toAdd = REPLAY_FERNIGNORE_ENTRIES2.filter((entry) => !lines.some((line) => line.trim() === entry));
|
|
38152
38756
|
if (toAdd.length > 0) {
|
|
38153
38757
|
const suffix = content.length > 0 && !content.endsWith("\n") ? "\n" : "";
|
|
38154
|
-
await (0,
|
|
38758
|
+
await (0, import_promises6.writeFile)(fernignorePath, content + suffix + toAdd.join("\n") + "\n", "utf-8");
|
|
38155
38759
|
return true;
|
|
38156
38760
|
}
|
|
38157
38761
|
return false;
|
|
38158
38762
|
}
|
|
38159
38763
|
async function ensureGitattributesEntries2(outputDir) {
|
|
38160
|
-
const gitattributesPath = (0,
|
|
38764
|
+
const gitattributesPath = (0, import_path14.join)(outputDir, ".gitattributes");
|
|
38161
38765
|
let content = "";
|
|
38162
38766
|
try {
|
|
38163
|
-
content = await (0,
|
|
38767
|
+
content = await (0, import_promises6.readFile)(gitattributesPath, "utf-8");
|
|
38164
38768
|
} catch {
|
|
38165
38769
|
}
|
|
38166
38770
|
const lines = content.split("\n");
|
|
38167
38771
|
const toAdd = GITATTRIBUTES_ENTRIES2.filter((entry) => !lines.some((line) => line.trim() === entry));
|
|
38168
38772
|
if (toAdd.length > 0) {
|
|
38169
38773
|
const suffix = content.length > 0 && !content.endsWith("\n") ? "\n" : "";
|
|
38170
|
-
await (0,
|
|
38774
|
+
await (0, import_promises6.writeFile)(gitattributesPath, content + suffix + toAdd.join("\n") + "\n", "utf-8");
|
|
38171
38775
|
}
|
|
38172
38776
|
}
|
|
38173
38777
|
|
|
@@ -38194,7 +38798,7 @@ async function replayInit(params) {
|
|
|
38194
38798
|
if (dryRun) {
|
|
38195
38799
|
return { bootstrap: bootstrapResult, fernignoreEntries: [], gitattributesEntries: [] };
|
|
38196
38800
|
}
|
|
38197
|
-
const lockfilePath = (0,
|
|
38801
|
+
const lockfilePath = (0, import_path15.join)(repoPath, ".fern", "replay.lock");
|
|
38198
38802
|
const lockfileContent = (0, import_fs11.existsSync)(lockfilePath) ? (0, import_fs11.readFileSync)(lockfilePath, "utf-8") : void 0;
|
|
38199
38803
|
return {
|
|
38200
38804
|
bootstrap: bootstrapResult,
|
|
@@ -38315,9 +38919,9 @@ init_dist3();
|
|
|
38315
38919
|
|
|
38316
38920
|
// src/replay/replay-run.ts
|
|
38317
38921
|
init_dist3();
|
|
38318
|
-
var
|
|
38922
|
+
var import_child_process4 = require("child_process");
|
|
38319
38923
|
var import_fs12 = require("fs");
|
|
38320
|
-
var
|
|
38924
|
+
var import_path16 = require("path");
|
|
38321
38925
|
async function replayPrepare(params) {
|
|
38322
38926
|
const {
|
|
38323
38927
|
outputDir,
|
|
@@ -38328,7 +38932,7 @@ async function replayPrepare(params) {
|
|
|
38328
38932
|
skipApplication,
|
|
38329
38933
|
logger
|
|
38330
38934
|
} = params;
|
|
38331
|
-
const lockfilePath = (0,
|
|
38935
|
+
const lockfilePath = (0, import_path16.join)(outputDir, ".fern", "replay.lock");
|
|
38332
38936
|
if (!(0, import_fs12.existsSync)(lockfilePath)) {
|
|
38333
38937
|
return null;
|
|
38334
38938
|
}
|
|
@@ -38460,7 +39064,7 @@ async function replayRun(params) {
|
|
|
38460
39064
|
}
|
|
38461
39065
|
function isTagMergedIntoHead(cwd2, tagSha) {
|
|
38462
39066
|
try {
|
|
38463
|
-
(0,
|
|
39067
|
+
(0, import_child_process4.execFileSync)("git", ["merge-base", "--is-ancestor", tagSha, "HEAD"], {
|
|
38464
39068
|
cwd: cwd2,
|
|
38465
39069
|
stdio: "pipe"
|
|
38466
39070
|
});
|
|
@@ -38472,7 +39076,7 @@ function isTagMergedIntoHead(cwd2, tagSha) {
|
|
|
38472
39076
|
return false;
|
|
38473
39077
|
}
|
|
38474
39078
|
try {
|
|
38475
|
-
const trees = (0,
|
|
39079
|
+
const trees = (0, import_child_process4.execFileSync)("git", ["log", "HEAD", "--format=%T", "--max-count=500"], {
|
|
38476
39080
|
cwd: cwd2,
|
|
38477
39081
|
encoding: "utf-8",
|
|
38478
39082
|
stdio: "pipe"
|
|
@@ -38484,7 +39088,7 @@ function isTagMergedIntoHead(cwd2, tagSha) {
|
|
|
38484
39088
|
}
|
|
38485
39089
|
function gitRevParse(cwd2, rev) {
|
|
38486
39090
|
try {
|
|
38487
|
-
return (0,
|
|
39091
|
+
return (0, import_child_process4.execFileSync)("git", ["rev-parse", "--verify", rev], {
|
|
38488
39092
|
cwd: cwd2,
|
|
38489
39093
|
encoding: "utf-8",
|
|
38490
39094
|
stdio: "pipe"
|
|
@@ -38495,7 +39099,7 @@ function gitRevParse(cwd2, rev) {
|
|
|
38495
39099
|
}
|
|
38496
39100
|
function gitDiffNameOnly(cwd2, from, to) {
|
|
38497
39101
|
try {
|
|
38498
|
-
const output = (0,
|
|
39102
|
+
const output = (0, import_child_process4.execFileSync)("git", ["diff", "--name-only", from, to], {
|
|
38499
39103
|
cwd: cwd2,
|
|
38500
39104
|
encoding: "utf-8",
|
|
38501
39105
|
stdio: "pipe"
|
|
@@ -38513,29 +39117,29 @@ function replayStatus(params) {
|
|
|
38513
39117
|
}
|
|
38514
39118
|
|
|
38515
39119
|
// src/configuration/loadGitHubConfig.ts
|
|
38516
|
-
var
|
|
39120
|
+
var import_promises7 = require("fs/promises");
|
|
38517
39121
|
async function loadGitHubConfig({
|
|
38518
39122
|
absolutePathToConfig
|
|
38519
39123
|
}) {
|
|
38520
|
-
const rawContents = await (0,
|
|
39124
|
+
const rawContents = await (0, import_promises7.readFile)(absolutePathToConfig, "utf8");
|
|
38521
39125
|
return JSON.parse(rawContents);
|
|
38522
39126
|
}
|
|
38523
39127
|
|
|
38524
39128
|
// src/configuration/loadReadmeConfig.ts
|
|
38525
|
-
var
|
|
39129
|
+
var import_promises8 = require("fs/promises");
|
|
38526
39130
|
async function loadReadmeConfig({
|
|
38527
39131
|
absolutePathToConfig
|
|
38528
39132
|
}) {
|
|
38529
|
-
const rawContents = await (0,
|
|
39133
|
+
const rawContents = await (0, import_promises8.readFile)(absolutePathToConfig, "utf8");
|
|
38530
39134
|
return JSON.parse(rawContents);
|
|
38531
39135
|
}
|
|
38532
39136
|
|
|
38533
39137
|
// src/configuration/loadReferenceConfig.ts
|
|
38534
|
-
var
|
|
39138
|
+
var import_promises9 = require("fs/promises");
|
|
38535
39139
|
async function loadReferenceConfig({
|
|
38536
39140
|
absolutePathToConfig
|
|
38537
39141
|
}) {
|
|
38538
|
-
const rawContents = await (0,
|
|
39142
|
+
const rawContents = await (0, import_promises9.readFile)(absolutePathToConfig, "utf8");
|
|
38539
39143
|
return JSON.parse(rawContents);
|
|
38540
39144
|
}
|
|
38541
39145
|
|
|
@@ -38552,7 +39156,7 @@ var consolePipelineLogger = {
|
|
|
38552
39156
|
};
|
|
38553
39157
|
|
|
38554
39158
|
// src/pipeline/PostGenerationPipeline.ts
|
|
38555
|
-
var
|
|
39159
|
+
var import_child_process6 = require("child_process");
|
|
38556
39160
|
|
|
38557
39161
|
// src/pipeline/github/constants.ts
|
|
38558
39162
|
var FERN_BOT_NAME2 = "fern-api";
|
|
@@ -38560,10 +39164,10 @@ var FERN_BOT_EMAIL2 = "115122769+fern-api[bot]@users.noreply.github.com";
|
|
|
38560
39164
|
var FERN_BOT_LOGIN2 = "fern-api[bot]";
|
|
38561
39165
|
|
|
38562
39166
|
// src/pipeline/steps/AutoVersionStep.ts
|
|
38563
|
-
var
|
|
39167
|
+
var import_child_process5 = require("child_process");
|
|
38564
39168
|
var import_fs14 = require("fs");
|
|
38565
|
-
var
|
|
38566
|
-
var
|
|
39169
|
+
var import_promises11 = require("fs/promises");
|
|
39170
|
+
var import_path18 = require("path");
|
|
38567
39171
|
|
|
38568
39172
|
// ../commons/logging-execa/lib/loggingExeca.js
|
|
38569
39173
|
var import_execa = __toESM(require_execa(), 1);
|
|
@@ -38622,8 +39226,8 @@ async function loggingExeca(logger, executable, args = [], { doNotPipeOutput = f
|
|
|
38622
39226
|
|
|
38623
39227
|
// src/autoversion/AutoVersioningService.ts
|
|
38624
39228
|
var import_fs13 = require("fs");
|
|
38625
|
-
var
|
|
38626
|
-
var
|
|
39229
|
+
var import_promises10 = require("fs/promises");
|
|
39230
|
+
var import_path17 = require("path");
|
|
38627
39231
|
var import_semver = __toESM(require_semver2());
|
|
38628
39232
|
var AutoVersioningException = class extends Error {
|
|
38629
39233
|
/**
|
|
@@ -39310,7 +39914,7 @@ var AutoVersioningService = class _AutoVersioningService {
|
|
|
39310
39914
|
);
|
|
39311
39915
|
return;
|
|
39312
39916
|
}
|
|
39313
|
-
const goModPath = (0,
|
|
39917
|
+
const goModPath = (0, import_path17.join)(workingDirectory, "go.mod");
|
|
39314
39918
|
if (!(0, import_fs13.existsSync)(goModPath)) {
|
|
39315
39919
|
this.logger.debug(`No go.mod found in ${workingDirectory}, skipping Go module path update`);
|
|
39316
39920
|
return;
|
|
@@ -39344,7 +39948,7 @@ var AutoVersioningService = class _AutoVersioningService {
|
|
|
39344
39948
|
* Reads the module path from a go.mod file.
|
|
39345
39949
|
*/
|
|
39346
39950
|
async readGoModulePath(goModPath) {
|
|
39347
|
-
const content = await (0,
|
|
39951
|
+
const content = await (0, import_promises10.readFile)(goModPath, "utf-8");
|
|
39348
39952
|
for (const line of content.split("\n")) {
|
|
39349
39953
|
const trimmed2 = line.trim();
|
|
39350
39954
|
if (trimmed2.startsWith("module ")) {
|
|
@@ -39357,7 +39961,7 @@ var AutoVersioningService = class _AutoVersioningService {
|
|
|
39357
39961
|
* Adds a version suffix to the module line in go.mod.
|
|
39358
39962
|
*/
|
|
39359
39963
|
async addSuffixToGoMod(goModPath, modulePath, suffix) {
|
|
39360
|
-
const content = await (0,
|
|
39964
|
+
const content = await (0, import_promises10.readFile)(goModPath, "utf-8");
|
|
39361
39965
|
const lines = content.split("\n");
|
|
39362
39966
|
let changed = false;
|
|
39363
39967
|
for (let i = 0; i < lines.length; i++) {
|
|
@@ -39369,7 +39973,7 @@ var AutoVersioningService = class _AutoVersioningService {
|
|
|
39369
39973
|
}
|
|
39370
39974
|
}
|
|
39371
39975
|
if (changed) {
|
|
39372
|
-
await (0,
|
|
39976
|
+
await (0, import_promises10.writeFile)(goModPath, lines.join("\n"), "utf-8");
|
|
39373
39977
|
this.logger.debug(`Updated go.mod: added ${suffix} to module path`);
|
|
39374
39978
|
}
|
|
39375
39979
|
}
|
|
@@ -39378,10 +39982,10 @@ var AutoVersioningService = class _AutoVersioningService {
|
|
|
39378
39982
|
*/
|
|
39379
39983
|
async walkDirectory(dir, filter2) {
|
|
39380
39984
|
const results = [];
|
|
39381
|
-
const entries2 = await (0,
|
|
39985
|
+
const entries2 = await (0, import_promises10.readdir)(dir);
|
|
39382
39986
|
for (const entry of entries2) {
|
|
39383
|
-
const fullPath = (0,
|
|
39384
|
-
const entryStat = await (0,
|
|
39987
|
+
const fullPath = (0, import_path17.join)(dir, entry);
|
|
39988
|
+
const entryStat = await (0, import_promises10.stat)(fullPath);
|
|
39385
39989
|
if (entryStat.isDirectory()) {
|
|
39386
39990
|
if (entry === ".git" || entry === "vendor") {
|
|
39387
39991
|
continue;
|
|
@@ -39398,7 +40002,7 @@ var AutoVersioningService = class _AutoVersioningService {
|
|
|
39398
40002
|
* Adds a version suffix to import paths in all .go files in the repository.
|
|
39399
40003
|
*/
|
|
39400
40004
|
async addSuffixToGoFiles(repoRoot, modulePath, suffix) {
|
|
39401
|
-
const goFiles = await this.walkDirectory(repoRoot, (filePath) => (0,
|
|
40005
|
+
const goFiles = await this.walkDirectory(repoRoot, (filePath) => (0, import_path17.extname)(filePath) === ".go");
|
|
39402
40006
|
for (const filePath of goFiles) {
|
|
39403
40007
|
await this.addSuffixToGoFile(filePath, modulePath, suffix);
|
|
39404
40008
|
}
|
|
@@ -39408,7 +40012,7 @@ var AutoVersioningService = class _AutoVersioningService {
|
|
|
39408
40012
|
* Replaces occurrences of the module path with modulePath + suffix in import statements.
|
|
39409
40013
|
*/
|
|
39410
40014
|
async addSuffixToGoFile(filePath, modulePath, suffix) {
|
|
39411
|
-
const content = await (0,
|
|
40015
|
+
const content = await (0, import_promises10.readFile)(filePath, "utf-8");
|
|
39412
40016
|
const lines = content.split("\n");
|
|
39413
40017
|
let changed = false;
|
|
39414
40018
|
let inImportBlock = false;
|
|
@@ -39437,7 +40041,7 @@ var AutoVersioningService = class _AutoVersioningService {
|
|
|
39437
40041
|
}
|
|
39438
40042
|
}
|
|
39439
40043
|
if (changed) {
|
|
39440
|
-
await (0,
|
|
40044
|
+
await (0, import_promises10.writeFile)(filePath, lines.join("\n"), "utf-8");
|
|
39441
40045
|
this.logger.debug(`Updated Go imports in ${filePath}`);
|
|
39442
40046
|
}
|
|
39443
40047
|
}
|
|
@@ -39800,7 +40404,7 @@ var AutoVersionStep = class extends BaseStep {
|
|
|
39800
40404
|
}
|
|
39801
40405
|
async readVersionFromMetadata() {
|
|
39802
40406
|
try {
|
|
39803
|
-
const output = (0,
|
|
40407
|
+
const output = (0, import_child_process5.execFileSync)("git", ["show", "HEAD~1:.fern/metadata.json"], {
|
|
39804
40408
|
cwd: this.outputDir,
|
|
39805
40409
|
encoding: "utf-8",
|
|
39806
40410
|
stdio: "pipe"
|
|
@@ -39816,7 +40420,7 @@ var AutoVersionStep = class extends BaseStep {
|
|
|
39816
40420
|
return mappedMagicVersion.startsWith("v") ? `v${stripped}` : stripped;
|
|
39817
40421
|
}
|
|
39818
40422
|
gitDiff(from, to) {
|
|
39819
|
-
return (0,
|
|
40423
|
+
return (0, import_child_process5.execFileSync)("git", ["diff", from, to, "--", ".", ":(exclude).fern/metadata.json"], {
|
|
39820
40424
|
cwd: this.outputDir,
|
|
39821
40425
|
encoding: "utf-8",
|
|
39822
40426
|
stdio: "pipe",
|
|
@@ -39829,12 +40433,12 @@ var AutoVersionStep = class extends BaseStep {
|
|
|
39829
40433
|
const fullMessage = body.length > 0 ? `${COMMIT_MARKER} ${subject}
|
|
39830
40434
|
|
|
39831
40435
|
${body}` : `${COMMIT_MARKER} ${subject}`;
|
|
39832
|
-
(0,
|
|
39833
|
-
(0,
|
|
40436
|
+
(0, import_child_process5.execFileSync)("git", ["add", "-A"], { cwd: this.outputDir, stdio: "pipe" });
|
|
40437
|
+
(0, import_child_process5.execFileSync)("git", ["commit", "--allow-empty", "-m", fullMessage], {
|
|
39834
40438
|
cwd: this.outputDir,
|
|
39835
40439
|
stdio: "pipe"
|
|
39836
40440
|
});
|
|
39837
|
-
return (0,
|
|
40441
|
+
return (0, import_child_process5.execFileSync)("git", ["rev-parse", "HEAD"], {
|
|
39838
40442
|
cwd: this.outputDir,
|
|
39839
40443
|
encoding: "utf-8",
|
|
39840
40444
|
stdio: "pipe"
|
|
@@ -39842,7 +40446,7 @@ ${body}` : `${COMMIT_MARKER} ${subject}`;
|
|
|
39842
40446
|
}
|
|
39843
40447
|
async prependChangelogEntry(params) {
|
|
39844
40448
|
const { version: version2, entry } = params;
|
|
39845
|
-
const changelogPath = (0,
|
|
40449
|
+
const changelogPath = (0, import_path18.join)(this.outputDir, "changelog.md");
|
|
39846
40450
|
const now = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
39847
40451
|
const header = `## [${version2}] - ${now}
|
|
39848
40452
|
`;
|
|
@@ -39851,7 +40455,7 @@ ${body}` : `${COMMIT_MARKER} ${subject}`;
|
|
|
39851
40455
|
`;
|
|
39852
40456
|
let existing = "";
|
|
39853
40457
|
if ((0, import_fs14.existsSync)(changelogPath)) {
|
|
39854
|
-
existing = await (0,
|
|
40458
|
+
existing = await (0, import_promises11.readFile)(changelogPath, "utf-8");
|
|
39855
40459
|
}
|
|
39856
40460
|
let output;
|
|
39857
40461
|
if (existing.trim().length === 0) {
|
|
@@ -39868,7 +40472,7 @@ ${newBlock}${remainder}`;
|
|
|
39868
40472
|
} else {
|
|
39869
40473
|
output = `${newBlock}${existing}`;
|
|
39870
40474
|
}
|
|
39871
|
-
await (0,
|
|
40475
|
+
await (0, import_promises11.writeFile)(changelogPath, output, "utf-8");
|
|
39872
40476
|
}
|
|
39873
40477
|
brandMessage(message) {
|
|
39874
40478
|
if (this.config.isWhitelabel) {
|
|
@@ -40050,8 +40654,8 @@ var GenerationCommitStep = class extends BaseStep {
|
|
|
40050
40654
|
};
|
|
40051
40655
|
|
|
40052
40656
|
// src/pipeline/steps/GithubStep.ts
|
|
40053
|
-
var
|
|
40054
|
-
var
|
|
40657
|
+
var import_promises12 = require("fs/promises");
|
|
40658
|
+
var import_path19 = require("path");
|
|
40055
40659
|
|
|
40056
40660
|
// src/pipeline/github/createReplayBranch.ts
|
|
40057
40661
|
async function createReplayBranch(repository, branchName, commitMessage, replayConflictInfo, logger) {
|
|
@@ -40668,13 +41272,13 @@ var GithubStep = class extends BaseStep {
|
|
|
40668
41272
|
}
|
|
40669
41273
|
async ensureFernignore() {
|
|
40670
41274
|
this.logger.debug("Checking for .fernignore file...");
|
|
40671
|
-
const fernignorePath = (0,
|
|
41275
|
+
const fernignorePath = (0, import_path19.join)(this.outputDir, ".fernignore");
|
|
40672
41276
|
try {
|
|
40673
|
-
await (0,
|
|
41277
|
+
await (0, import_promises12.access)(fernignorePath);
|
|
40674
41278
|
this.logger.debug(".fernignore already exists");
|
|
40675
41279
|
} catch {
|
|
40676
41280
|
this.logger.debug("Creating .fernignore file...");
|
|
40677
|
-
await (0,
|
|
41281
|
+
await (0, import_promises12.writeFile)(fernignorePath, "# Specify files that shouldn't be modified by Fern\n", "utf-8");
|
|
40678
41282
|
}
|
|
40679
41283
|
}
|
|
40680
41284
|
deriveSkipCommit(replayResult) {
|
|
@@ -40896,8 +41500,8 @@ var PostGenerationPipeline = class {
|
|
|
40896
41500
|
async run() {
|
|
40897
41501
|
if (this.config.github?.enabled) {
|
|
40898
41502
|
try {
|
|
40899
|
-
(0,
|
|
40900
|
-
(0,
|
|
41503
|
+
(0, import_child_process6.execFileSync)("git", ["config", "user.name", FERN_BOT_NAME2], { cwd: this.config.outputDir });
|
|
41504
|
+
(0, import_child_process6.execFileSync)("git", ["config", "user.email", FERN_BOT_EMAIL2], { cwd: this.config.outputDir });
|
|
40901
41505
|
} catch {
|
|
40902
41506
|
}
|
|
40903
41507
|
}
|
|
@@ -40967,7 +41571,7 @@ void yargs_default(hideBin(process.argv)).scriptName(process.env.CLI_NAME ?? "ge
|
|
|
40967
41571
|
const readmeConfig = await loadReadmeConfig({
|
|
40968
41572
|
absolutePathToConfig: resolve(wd, argv.config)
|
|
40969
41573
|
});
|
|
40970
|
-
const originalReadmeContent = argv.originalReadme != null ? await (0,
|
|
41574
|
+
const originalReadmeContent = argv.originalReadme != null ? await (0, import_promises13.readFile)(argv.originalReadme, "utf8") : void 0;
|
|
40971
41575
|
await generateReadmeToStream({
|
|
40972
41576
|
originalReadmeContent,
|
|
40973
41577
|
readmeConfig,
|
|
@@ -41095,7 +41699,7 @@ void yargs_default(hideBin(process.argv)).scriptName(process.env.CLI_NAME ?? "ge
|
|
|
41095
41699
|
try {
|
|
41096
41700
|
const wd = cwd();
|
|
41097
41701
|
const configValue = argv.config;
|
|
41098
|
-
const configContent = configValue === STDIN_MARKER ? await readStdin() : configValue.trimStart().startsWith("{") ? configValue : await (0,
|
|
41702
|
+
const configContent = configValue === STDIN_MARKER ? await readStdin() : configValue.trimStart().startsWith("{") ? configValue : await (0, import_promises13.readFile)(resolve(wd, configValue), "utf-8");
|
|
41099
41703
|
let config;
|
|
41100
41704
|
try {
|
|
41101
41705
|
config = JSON.parse(configContent);
|
|
@@ -41391,7 +41995,7 @@ async function createWriteStream(outputPath) {
|
|
|
41391
41995
|
}
|
|
41392
41996
|
async function createWriteStreamFromFile(filepath) {
|
|
41393
41997
|
if (!await doesPathExist(filepath)) {
|
|
41394
|
-
await (0,
|
|
41998
|
+
await (0, import_promises13.mkdir)(import_path20.default.dirname(filepath), { recursive: true });
|
|
41395
41999
|
}
|
|
41396
42000
|
return import_fs15.default.createWriteStream(filepath);
|
|
41397
42001
|
}
|