@fern-api/replay 0.7.0 → 0.8.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/dist/cli.cjs +173 -61
- package/dist/cli.cjs.map +1 -1
- package/dist/index.cjs +174 -60
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +19 -8
- package/dist/index.d.ts +19 -8
- package/dist/index.js +172 -61
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.cjs
CHANGED
|
@@ -5335,6 +5335,9 @@ var init_GitClient = __esm({
|
|
|
5335
5335
|
return false;
|
|
5336
5336
|
}
|
|
5337
5337
|
}
|
|
5338
|
+
async getCommitBody(commitSha) {
|
|
5339
|
+
return this.exec(["log", "-1", "--format=%B", commitSha]);
|
|
5340
|
+
}
|
|
5338
5341
|
getRepoPath() {
|
|
5339
5342
|
return this.repoPath;
|
|
5340
5343
|
}
|
|
@@ -13009,6 +13012,17 @@ function isGenerationCommit(commit) {
|
|
|
13009
13012
|
function isReplayCommit(commit) {
|
|
13010
13013
|
return commit.message.startsWith("[fern-replay]");
|
|
13011
13014
|
}
|
|
13015
|
+
function isRevertCommit(message) {
|
|
13016
|
+
return /^Revert ".+"$/.test(message);
|
|
13017
|
+
}
|
|
13018
|
+
function parseRevertedSha(fullBody) {
|
|
13019
|
+
const match2 = fullBody.match(/This reverts commit ([0-9a-f]{40})\./);
|
|
13020
|
+
return match2?.[1];
|
|
13021
|
+
}
|
|
13022
|
+
function parseRevertedMessage(subject) {
|
|
13023
|
+
const match2 = subject.match(/^Revert "(.+)"$/);
|
|
13024
|
+
return match2?.[1];
|
|
13025
|
+
}
|
|
13012
13026
|
|
|
13013
13027
|
// src/ReplayDetector.ts
|
|
13014
13028
|
var INFRASTRUCTURE_FILES = /* @__PURE__ */ new Set([".fernignore"]);
|
|
@@ -13026,14 +13040,14 @@ var ReplayDetector = class {
|
|
|
13026
13040
|
const lock = this.lockManager.read();
|
|
13027
13041
|
const lastGen = this.getLastGeneration(lock);
|
|
13028
13042
|
if (!lastGen) {
|
|
13029
|
-
return [];
|
|
13043
|
+
return { patches: [], revertedPatchIds: [] };
|
|
13030
13044
|
}
|
|
13031
13045
|
const exists2 = await this.git.commitExists(lastGen.commit_sha);
|
|
13032
13046
|
if (!exists2) {
|
|
13033
13047
|
this.warnings.push(
|
|
13034
13048
|
`Generation commit ${lastGen.commit_sha.slice(0, 7)} not found in git history. Skipping new patch detection. Existing lockfile patches will still be applied.`
|
|
13035
13049
|
);
|
|
13036
|
-
return [];
|
|
13050
|
+
return { patches: [], revertedPatchIds: [] };
|
|
13037
13051
|
}
|
|
13038
13052
|
const isAncestor = await this.git.isAncestor(lastGen.commit_sha, "HEAD");
|
|
13039
13053
|
if (!isAncestor) {
|
|
@@ -13047,7 +13061,7 @@ var ReplayDetector = class {
|
|
|
13047
13061
|
this.sdkOutputDir
|
|
13048
13062
|
]);
|
|
13049
13063
|
if (!log.trim()) {
|
|
13050
|
-
return [];
|
|
13064
|
+
return { patches: [], revertedPatchIds: [] };
|
|
13051
13065
|
}
|
|
13052
13066
|
const commits = this.parseGitLog(log);
|
|
13053
13067
|
const newPatches = [];
|
|
@@ -13083,7 +13097,63 @@ var ReplayDetector = class {
|
|
|
13083
13097
|
patch_content: patchContent
|
|
13084
13098
|
});
|
|
13085
13099
|
}
|
|
13086
|
-
|
|
13100
|
+
newPatches.reverse();
|
|
13101
|
+
const revertedPatchIdSet = /* @__PURE__ */ new Set();
|
|
13102
|
+
const revertIndicesToRemove = /* @__PURE__ */ new Set();
|
|
13103
|
+
for (let i = 0; i < newPatches.length; i++) {
|
|
13104
|
+
const patch = newPatches[i];
|
|
13105
|
+
if (!isRevertCommit(patch.original_message)) continue;
|
|
13106
|
+
let body = "";
|
|
13107
|
+
try {
|
|
13108
|
+
body = await this.git.getCommitBody(patch.original_commit);
|
|
13109
|
+
} catch {
|
|
13110
|
+
}
|
|
13111
|
+
const revertedSha = parseRevertedSha(body);
|
|
13112
|
+
const revertedMessage = parseRevertedMessage(patch.original_message);
|
|
13113
|
+
let matchedExisting = false;
|
|
13114
|
+
if (revertedSha) {
|
|
13115
|
+
const existing = lock.patches.find((p) => p.original_commit === revertedSha);
|
|
13116
|
+
if (existing) {
|
|
13117
|
+
revertedPatchIdSet.add(existing.id);
|
|
13118
|
+
revertIndicesToRemove.add(i);
|
|
13119
|
+
matchedExisting = true;
|
|
13120
|
+
}
|
|
13121
|
+
}
|
|
13122
|
+
if (!matchedExisting && revertedMessage) {
|
|
13123
|
+
const existing = lock.patches.find((p) => p.original_message === revertedMessage);
|
|
13124
|
+
if (existing) {
|
|
13125
|
+
revertedPatchIdSet.add(existing.id);
|
|
13126
|
+
revertIndicesToRemove.add(i);
|
|
13127
|
+
matchedExisting = true;
|
|
13128
|
+
}
|
|
13129
|
+
}
|
|
13130
|
+
if (matchedExisting) continue;
|
|
13131
|
+
let matchedNew = false;
|
|
13132
|
+
if (revertedSha) {
|
|
13133
|
+
const idx = newPatches.findIndex(
|
|
13134
|
+
(p, j) => j !== i && !revertIndicesToRemove.has(j) && p.original_commit === revertedSha
|
|
13135
|
+
);
|
|
13136
|
+
if (idx !== -1) {
|
|
13137
|
+
revertIndicesToRemove.add(i);
|
|
13138
|
+
revertIndicesToRemove.add(idx);
|
|
13139
|
+
matchedNew = true;
|
|
13140
|
+
}
|
|
13141
|
+
}
|
|
13142
|
+
if (!matchedNew && revertedMessage) {
|
|
13143
|
+
const idx = newPatches.findIndex(
|
|
13144
|
+
(p, j) => j !== i && !revertIndicesToRemove.has(j) && p.original_message === revertedMessage
|
|
13145
|
+
);
|
|
13146
|
+
if (idx !== -1) {
|
|
13147
|
+
revertIndicesToRemove.add(i);
|
|
13148
|
+
revertIndicesToRemove.add(idx);
|
|
13149
|
+
}
|
|
13150
|
+
}
|
|
13151
|
+
if (!matchedExisting && !matchedNew) {
|
|
13152
|
+
revertIndicesToRemove.add(i);
|
|
13153
|
+
}
|
|
13154
|
+
}
|
|
13155
|
+
const filteredPatches = newPatches.filter((_, i) => !revertIndicesToRemove.has(i));
|
|
13156
|
+
return { patches: filteredPatches, revertedPatchIds: [...revertedPatchIdSet] };
|
|
13087
13157
|
}
|
|
13088
13158
|
/**
|
|
13089
13159
|
* Compute content hash for deduplication.
|
|
@@ -13094,31 +13164,34 @@ var ReplayDetector = class {
|
|
|
13094
13164
|
const normalized = patchContent.split("\n").filter((line) => !line.startsWith("From ") && !line.startsWith("index ") && !line.startsWith("Date: ")).join("\n");
|
|
13095
13165
|
return `sha256:${(0, import_node_crypto.createHash)("sha256").update(normalized).digest("hex")}`;
|
|
13096
13166
|
}
|
|
13097
|
-
/**
|
|
13167
|
+
/**
|
|
13168
|
+
* Detect patches via tree diff for non-linear history. Returns a composite patch.
|
|
13169
|
+
* Revert reconciliation is skipped here because tree-diff produces a single composite
|
|
13170
|
+
* patch from the aggregate diff — individual revert commits are not distinguishable.
|
|
13171
|
+
*/
|
|
13098
13172
|
async detectPatchesViaTreeDiff(lastGen) {
|
|
13099
13173
|
const filesOutput = await this.git.exec(["diff", "--name-only", lastGen.commit_sha, "HEAD"]);
|
|
13100
13174
|
const files = filesOutput.trim().split("\n").filter(Boolean).filter((f) => !INFRASTRUCTURE_FILES.has(f)).filter((f) => !f.startsWith(".fern/"));
|
|
13101
|
-
if (files.length === 0) return [];
|
|
13175
|
+
if (files.length === 0) return { patches: [], revertedPatchIds: [] };
|
|
13102
13176
|
const diff = await this.git.exec(["diff", lastGen.commit_sha, "HEAD", "--", ...files]);
|
|
13103
|
-
if (!diff.trim()) return [];
|
|
13177
|
+
if (!diff.trim()) return { patches: [], revertedPatchIds: [] };
|
|
13104
13178
|
const contentHash = this.computeContentHash(diff);
|
|
13105
13179
|
const lock = this.lockManager.read();
|
|
13106
13180
|
if (lock.patches.some((p) => p.content_hash === contentHash)) {
|
|
13107
|
-
return [];
|
|
13181
|
+
return { patches: [], revertedPatchIds: [] };
|
|
13108
13182
|
}
|
|
13109
13183
|
const headSha = (await this.git.exec(["rev-parse", "HEAD"])).trim();
|
|
13110
|
-
|
|
13111
|
-
{
|
|
13112
|
-
|
|
13113
|
-
|
|
13114
|
-
|
|
13115
|
-
|
|
13116
|
-
|
|
13117
|
-
|
|
13118
|
-
|
|
13119
|
-
|
|
13120
|
-
|
|
13121
|
-
];
|
|
13184
|
+
const compositePatch = {
|
|
13185
|
+
id: `patch-composite-${headSha.slice(0, 8)}`,
|
|
13186
|
+
content_hash: contentHash,
|
|
13187
|
+
original_commit: headSha,
|
|
13188
|
+
original_message: "Customer customizations (composite)",
|
|
13189
|
+
original_author: "composite",
|
|
13190
|
+
base_generation: lastGen.commit_sha,
|
|
13191
|
+
files,
|
|
13192
|
+
patch_content: diff
|
|
13193
|
+
};
|
|
13194
|
+
return { patches: [compositePatch], revertedPatchIds: [] };
|
|
13122
13195
|
}
|
|
13123
13196
|
parseGitLog(log) {
|
|
13124
13197
|
return log.trim().split("\n").map((line) => {
|
|
@@ -15266,6 +15339,34 @@ CLI Version: ${options.cliVersion}`;
|
|
|
15266
15339
|
}
|
|
15267
15340
|
};
|
|
15268
15341
|
|
|
15342
|
+
// src/conflict-utils.ts
|
|
15343
|
+
function stripConflictMarkers(content) {
|
|
15344
|
+
const lines = content.split("\n");
|
|
15345
|
+
const result = [];
|
|
15346
|
+
let inConflict = false;
|
|
15347
|
+
let inOurs = false;
|
|
15348
|
+
for (const line of lines) {
|
|
15349
|
+
if (line.startsWith("<<<<<<< ")) {
|
|
15350
|
+
inConflict = true;
|
|
15351
|
+
inOurs = true;
|
|
15352
|
+
continue;
|
|
15353
|
+
}
|
|
15354
|
+
if (inConflict && line === "=======") {
|
|
15355
|
+
inOurs = false;
|
|
15356
|
+
continue;
|
|
15357
|
+
}
|
|
15358
|
+
if (inConflict && line.startsWith(">>>>>>> ")) {
|
|
15359
|
+
inConflict = false;
|
|
15360
|
+
inOurs = false;
|
|
15361
|
+
continue;
|
|
15362
|
+
}
|
|
15363
|
+
if (!inConflict || inOurs) {
|
|
15364
|
+
result.push(line);
|
|
15365
|
+
}
|
|
15366
|
+
}
|
|
15367
|
+
return result.join("\n");
|
|
15368
|
+
}
|
|
15369
|
+
|
|
15269
15370
|
// src/ReplayService.ts
|
|
15270
15371
|
var ReplayService = class {
|
|
15271
15372
|
git;
|
|
@@ -15334,7 +15435,7 @@ var ReplayService = class {
|
|
|
15334
15435
|
}
|
|
15335
15436
|
this.lockManager.save();
|
|
15336
15437
|
try {
|
|
15337
|
-
const redetectedPatches = await this.detector.detectNewPatches();
|
|
15438
|
+
const { patches: redetectedPatches } = await this.detector.detectNewPatches();
|
|
15338
15439
|
if (redetectedPatches.length > 0) {
|
|
15339
15440
|
const redetectedFiles = new Set(redetectedPatches.flatMap((p) => p.files));
|
|
15340
15441
|
const currentPatches = this.lockManager.getPatches();
|
|
@@ -15425,7 +15526,7 @@ var ReplayService = class {
|
|
|
15425
15526
|
};
|
|
15426
15527
|
}
|
|
15427
15528
|
async handleNoPatchesRegeneration(options) {
|
|
15428
|
-
const newPatches = await this.detector.detectNewPatches();
|
|
15529
|
+
const { patches: newPatches, revertedPatchIds } = await this.detector.detectNewPatches();
|
|
15429
15530
|
const warnings = [...this.detector.warnings];
|
|
15430
15531
|
if (options?.dryRun) {
|
|
15431
15532
|
return {
|
|
@@ -15434,11 +15535,18 @@ var ReplayService = class {
|
|
|
15434
15535
|
patchesApplied: 0,
|
|
15435
15536
|
patchesWithConflicts: 0,
|
|
15436
15537
|
patchesSkipped: 0,
|
|
15538
|
+
patchesReverted: revertedPatchIds.length,
|
|
15437
15539
|
conflicts: [],
|
|
15438
15540
|
wouldApply: newPatches,
|
|
15439
15541
|
warnings: warnings.length > 0 ? warnings : void 0
|
|
15440
15542
|
};
|
|
15441
15543
|
}
|
|
15544
|
+
for (const id of revertedPatchIds) {
|
|
15545
|
+
try {
|
|
15546
|
+
this.lockManager.removePatch(id);
|
|
15547
|
+
} catch {
|
|
15548
|
+
}
|
|
15549
|
+
}
|
|
15442
15550
|
const commitOpts = options ? {
|
|
15443
15551
|
cliVersion: options.cliVersion ?? "unknown",
|
|
15444
15552
|
generatorVersions: options.generatorVersions ?? {},
|
|
@@ -15472,12 +15580,12 @@ var ReplayService = class {
|
|
|
15472
15580
|
await this.committer.stageAll();
|
|
15473
15581
|
}
|
|
15474
15582
|
}
|
|
15475
|
-
return this.buildReport("no-patches", newPatches, results, options, warnings, rebaseCounts);
|
|
15583
|
+
return this.buildReport("no-patches", newPatches, results, options, warnings, rebaseCounts, void 0, revertedPatchIds.length);
|
|
15476
15584
|
}
|
|
15477
15585
|
async handleNormalRegeneration(options) {
|
|
15478
15586
|
if (options?.dryRun) {
|
|
15479
15587
|
const existingPatches2 = this.lockManager.getPatches();
|
|
15480
|
-
const newPatches2 = await this.detector.detectNewPatches();
|
|
15588
|
+
const { patches: newPatches2, revertedPatchIds: dryRunReverted } = await this.detector.detectNewPatches();
|
|
15481
15589
|
const warnings2 = [...this.detector.warnings];
|
|
15482
15590
|
const allPatches2 = [...existingPatches2, ...newPatches2];
|
|
15483
15591
|
return {
|
|
@@ -15486,13 +15594,19 @@ var ReplayService = class {
|
|
|
15486
15594
|
patchesApplied: 0,
|
|
15487
15595
|
patchesWithConflicts: 0,
|
|
15488
15596
|
patchesSkipped: 0,
|
|
15597
|
+
patchesReverted: dryRunReverted.length,
|
|
15489
15598
|
conflicts: [],
|
|
15490
15599
|
wouldApply: allPatches2,
|
|
15491
15600
|
warnings: warnings2.length > 0 ? warnings2 : void 0
|
|
15492
15601
|
};
|
|
15493
15602
|
}
|
|
15494
15603
|
let existingPatches = this.lockManager.getPatches();
|
|
15604
|
+
const preRebasePatchIds = new Set(existingPatches.map((p) => p.id));
|
|
15495
15605
|
const preRebaseCounts = await this.preGenerationRebase(existingPatches);
|
|
15606
|
+
const postRebasePatchIds = new Set(this.lockManager.getPatches().map((p) => p.id));
|
|
15607
|
+
const removedByPreRebase = existingPatches.filter(
|
|
15608
|
+
(p) => preRebasePatchIds.has(p.id) && !postRebasePatchIds.has(p.id)
|
|
15609
|
+
);
|
|
15496
15610
|
existingPatches = this.lockManager.getPatches();
|
|
15497
15611
|
const seenHashes = /* @__PURE__ */ new Set();
|
|
15498
15612
|
for (const p of existingPatches) {
|
|
@@ -15503,8 +15617,28 @@ var ReplayService = class {
|
|
|
15503
15617
|
}
|
|
15504
15618
|
}
|
|
15505
15619
|
existingPatches = this.lockManager.getPatches();
|
|
15506
|
-
|
|
15620
|
+
let { patches: newPatches, revertedPatchIds } = await this.detector.detectNewPatches();
|
|
15507
15621
|
const warnings = [...this.detector.warnings];
|
|
15622
|
+
if (removedByPreRebase.length > 0) {
|
|
15623
|
+
const removedOriginalCommits = new Set(removedByPreRebase.map((p) => p.original_commit));
|
|
15624
|
+
const removedOriginalMessages = new Set(removedByPreRebase.map((p) => p.original_message));
|
|
15625
|
+
newPatches = newPatches.filter((p) => {
|
|
15626
|
+
if (removedOriginalCommits.has(p.original_commit)) return false;
|
|
15627
|
+
if (isRevertCommit(p.original_message)) {
|
|
15628
|
+
const revertedMsg = parseRevertedMessage(p.original_message);
|
|
15629
|
+
if (revertedMsg && removedOriginalMessages.has(revertedMsg)) return false;
|
|
15630
|
+
}
|
|
15631
|
+
return true;
|
|
15632
|
+
});
|
|
15633
|
+
}
|
|
15634
|
+
for (const id of revertedPatchIds) {
|
|
15635
|
+
try {
|
|
15636
|
+
this.lockManager.removePatch(id);
|
|
15637
|
+
} catch {
|
|
15638
|
+
}
|
|
15639
|
+
}
|
|
15640
|
+
const revertedSet = new Set(revertedPatchIds);
|
|
15641
|
+
existingPatches = existingPatches.filter((p) => !revertedSet.has(p.id));
|
|
15508
15642
|
const allPatches = [...existingPatches, ...newPatches];
|
|
15509
15643
|
const commitOpts = options ? {
|
|
15510
15644
|
cliVersion: options.cliVersion ?? "unknown",
|
|
@@ -15549,7 +15683,8 @@ var ReplayService = class {
|
|
|
15549
15683
|
options,
|
|
15550
15684
|
warnings,
|
|
15551
15685
|
rebaseCounts,
|
|
15552
|
-
preRebaseCounts
|
|
15686
|
+
preRebaseCounts,
|
|
15687
|
+
revertedPatchIds.length
|
|
15553
15688
|
);
|
|
15554
15689
|
}
|
|
15555
15690
|
/**
|
|
@@ -15742,36 +15877,6 @@ var ReplayService = class {
|
|
|
15742
15877
|
}
|
|
15743
15878
|
return { conflictResolved, conflictAbsorbed, contentRefreshed };
|
|
15744
15879
|
}
|
|
15745
|
-
/**
|
|
15746
|
-
* Strip conflict markers from file content, keeping the OURS (Generated) side.
|
|
15747
|
-
* Preserves clean patches' non-conflicting changes on shared files.
|
|
15748
|
-
*/
|
|
15749
|
-
stripConflictMarkers(content) {
|
|
15750
|
-
const lines = content.split("\n");
|
|
15751
|
-
const result = [];
|
|
15752
|
-
let inConflict = false;
|
|
15753
|
-
let inOurs = false;
|
|
15754
|
-
for (const line of lines) {
|
|
15755
|
-
if (line.startsWith("<<<<<<< ")) {
|
|
15756
|
-
inConflict = true;
|
|
15757
|
-
inOurs = true;
|
|
15758
|
-
continue;
|
|
15759
|
-
}
|
|
15760
|
-
if (inConflict && line === "=======") {
|
|
15761
|
-
inOurs = false;
|
|
15762
|
-
continue;
|
|
15763
|
-
}
|
|
15764
|
-
if (inConflict && line.startsWith(">>>>>>> ")) {
|
|
15765
|
-
inConflict = false;
|
|
15766
|
-
inOurs = false;
|
|
15767
|
-
continue;
|
|
15768
|
-
}
|
|
15769
|
-
if (!inConflict || inOurs) {
|
|
15770
|
-
result.push(line);
|
|
15771
|
-
}
|
|
15772
|
-
}
|
|
15773
|
-
return result.join("\n");
|
|
15774
|
-
}
|
|
15775
15880
|
/**
|
|
15776
15881
|
* After applyPatches(), strip conflict markers from conflicting files
|
|
15777
15882
|
* so only clean content is committed. Keeps the Generated (OURS) side.
|
|
@@ -15784,7 +15889,7 @@ var ReplayService = class {
|
|
|
15784
15889
|
const filePath = (0, import_node_path4.join)(this.outputDir, fileResult.file);
|
|
15785
15890
|
try {
|
|
15786
15891
|
const content = (0, import_node_fs2.readFileSync)(filePath, "utf-8");
|
|
15787
|
-
const stripped =
|
|
15892
|
+
const stripped = stripConflictMarkers(content);
|
|
15788
15893
|
(0, import_node_fs2.writeFileSync)(filePath, stripped);
|
|
15789
15894
|
} catch {
|
|
15790
15895
|
}
|
|
@@ -15796,7 +15901,7 @@ var ReplayService = class {
|
|
|
15796
15901
|
if (!(0, import_node_fs2.existsSync)(fernignorePath)) return [];
|
|
15797
15902
|
return (0, import_node_fs2.readFileSync)(fernignorePath, "utf-8").split("\n").map((line) => line.trim()).filter((line) => line && !line.startsWith("#"));
|
|
15798
15903
|
}
|
|
15799
|
-
buildReport(flow, patches, results, options, warnings, rebaseCounts, preRebaseCounts) {
|
|
15904
|
+
buildReport(flow, patches, results, options, warnings, rebaseCounts, preRebaseCounts, patchesReverted) {
|
|
15800
15905
|
const conflictResults = results.filter((r) => r.status === "conflict");
|
|
15801
15906
|
const conflictDetails = conflictResults.map((r) => {
|
|
15802
15907
|
const conflictFiles = r.fileResults?.filter((f) => f.status === "conflict") ?? [];
|
|
@@ -15821,6 +15926,7 @@ var ReplayService = class {
|
|
|
15821
15926
|
patchesRepointed: rebaseCounts && rebaseCounts.repointed > 0 ? rebaseCounts.repointed : void 0,
|
|
15822
15927
|
patchesContentRebased: rebaseCounts && rebaseCounts.contentRebased > 0 ? rebaseCounts.contentRebased : void 0,
|
|
15823
15928
|
patchesKeptAsUserOwned: rebaseCounts && rebaseCounts.keptAsUserOwned > 0 ? rebaseCounts.keptAsUserOwned : void 0,
|
|
15929
|
+
patchesReverted: patchesReverted && patchesReverted > 0 ? patchesReverted : void 0,
|
|
15824
15930
|
patchesConflictResolved: preRebaseCounts && preRebaseCounts.conflictResolved + preRebaseCounts.conflictAbsorbed > 0 ? preRebaseCounts.conflictResolved + preRebaseCounts.conflictAbsorbed : void 0,
|
|
15825
15931
|
patchesRefreshed: preRebaseCounts && preRebaseCounts.contentRefreshed > 0 ? preRebaseCounts.contentRefreshed : void 0,
|
|
15826
15932
|
conflicts: conflictResults.flatMap((r) => r.fileResults?.filter((f) => f.status === "conflict") ?? []),
|
|
@@ -15866,7 +15972,7 @@ var FernignoreMigrator = class {
|
|
|
15866
15972
|
async analyzeMigration() {
|
|
15867
15973
|
const patterns = this.readFernignorePatterns();
|
|
15868
15974
|
const detector = new ReplayDetector(this.git, this.lockManager, this.outputDir);
|
|
15869
|
-
const patches = await detector.detectNewPatches();
|
|
15975
|
+
const { patches } = await detector.detectNewPatches();
|
|
15870
15976
|
const trackedByBoth = [];
|
|
15871
15977
|
const fernignoreOnly = [];
|
|
15872
15978
|
const commitsOnly = [];
|
|
@@ -15991,7 +16097,7 @@ var FernignoreMigrator = class {
|
|
|
15991
16097
|
async migrate() {
|
|
15992
16098
|
const analysis = await this.analyzeMigration();
|
|
15993
16099
|
const detector = new ReplayDetector(this.git, this.lockManager, this.outputDir);
|
|
15994
|
-
const patches = await detector.detectNewPatches();
|
|
16100
|
+
const { patches } = await detector.detectNewPatches();
|
|
15995
16101
|
const warnings = [];
|
|
15996
16102
|
let patchesCreated = 0;
|
|
15997
16103
|
for (const patch of patches) {
|
|
@@ -16544,11 +16650,14 @@ async function runDetect(dir) {
|
|
|
16544
16650
|
lockManager.read();
|
|
16545
16651
|
const git = new GitClient(dir);
|
|
16546
16652
|
const detector = new ReplayDetector(git, lockManager, dir);
|
|
16547
|
-
const patches = await detector.detectNewPatches();
|
|
16653
|
+
const { patches, revertedPatchIds } = await detector.detectNewPatches();
|
|
16548
16654
|
if (detector.warnings.length > 0) {
|
|
16549
16655
|
for (const w of detector.warnings) console.log(`Warning: ${w}`);
|
|
16550
16656
|
console.log();
|
|
16551
16657
|
}
|
|
16658
|
+
if (revertedPatchIds.length > 0) {
|
|
16659
|
+
console.log(`Reverted patches: ${revertedPatchIds.length}`);
|
|
16660
|
+
}
|
|
16552
16661
|
console.log(`Detected ${patches.length} new patch(es) since last generation:
|
|
16553
16662
|
`);
|
|
16554
16663
|
if (patches.length === 0) {
|
|
@@ -16590,6 +16699,9 @@ function printReport(report) {
|
|
|
16590
16699
|
if (report.patchesKeptAsUserOwned) {
|
|
16591
16700
|
console.log(`Patches kept (user-owned files): ${report.patchesKeptAsUserOwned}`);
|
|
16592
16701
|
}
|
|
16702
|
+
if (report.patchesReverted) {
|
|
16703
|
+
console.log(`Patches reverted by user: ${report.patchesReverted}`);
|
|
16704
|
+
}
|
|
16593
16705
|
if (report.patchesPartiallyApplied) {
|
|
16594
16706
|
console.log(`Patches partially applied: ${report.patchesPartiallyApplied}`);
|
|
16595
16707
|
}
|