@fern-api/replay 0.11.0 → 0.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.cjs +269 -37
- package/dist/cli.cjs.map +1 -1
- package/dist/index.cjs +269 -37
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +133 -8
- package/dist/index.d.ts +133 -8
- package/dist/index.js +269 -37
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -493,7 +493,7 @@ var FERN_SUPPORT_NAMES = ["fern-support", "Fern Support"];
|
|
|
493
493
|
function isGenerationCommit(commit) {
|
|
494
494
|
const isFernSupport = FERN_SUPPORT_NAMES.includes(commit.authorName);
|
|
495
495
|
const isBotAuthor = !isFernSupport && (commit.authorLogin === FERN_BOT_LOGIN || commit.authorEmail === FERN_BOT_EMAIL || commit.authorName === FERN_BOT_NAME);
|
|
496
|
-
const hasGenerationMarker = commit.message.startsWith("[fern-generated]") || commit.message.startsWith("[fern-replay]") || commit.message.includes("Generated by Fern") || commit.message.includes("\u{1F916} Generated with Fern") || // Squash merge of a Fern-generated PR uses the PR title as commit message.
|
|
496
|
+
const hasGenerationMarker = commit.message.startsWith("[fern-generated]") || commit.message.startsWith("[fern-replay]") || commit.message.startsWith("[fern-autoversion]") || commit.message.includes("Generated by Fern") || commit.message.includes("\u{1F916} Generated with Fern") || // Squash merge of a Fern-generated PR uses the PR title as commit message.
|
|
497
497
|
// The default PR title is "SDK Generation" (from GithubStep's commitMessage default).
|
|
498
498
|
// GitHub appends "(#N)" for the PR number, e.g. "SDK Generation (#70)".
|
|
499
499
|
commit.message.startsWith("SDK Generation");
|
|
@@ -762,17 +762,57 @@ var ReplayDetector = class {
|
|
|
762
762
|
}
|
|
763
763
|
const isAncestor = await this.git.isAncestor(lastGen.commit_sha, "HEAD");
|
|
764
764
|
if (!isAncestor) {
|
|
765
|
+
return this.detectPatchesViaMergeBase(lastGen, lock);
|
|
766
|
+
}
|
|
767
|
+
return this.detectPatchesInRange(lastGen.commit_sha, lastGen, lock);
|
|
768
|
+
}
|
|
769
|
+
/**
|
|
770
|
+
* FER-10201 — Non-linear-history detection via `merge-base(prevGen, HEAD)`.
|
|
771
|
+
*
|
|
772
|
+
* After a squash-merge of a Fern-bot PR, `lastGen.commit_sha` (the previous
|
|
773
|
+
* `[fern-generated]`) is orphaned but still in git's object database. The
|
|
774
|
+
* merge-base is the commit on main from which the bot's branch was created —
|
|
775
|
+
* a reachable ancestor of HEAD. Walking that range and classifying each
|
|
776
|
+
* commit via `isGenerationCommit` mirrors the linear path and eliminates
|
|
777
|
+
* the bug class where pipeline-driven changes (autoversion, replay,
|
|
778
|
+
* generation) get bundled as customer customizations.
|
|
779
|
+
*
|
|
780
|
+
* Falls through to the legacy composite path when no common ancestor exists
|
|
781
|
+
* (truly disjoint history — orphan branches with no shared root).
|
|
782
|
+
*/
|
|
783
|
+
async detectPatchesViaMergeBase(lastGen, lock) {
|
|
784
|
+
let mergeBase = "";
|
|
785
|
+
try {
|
|
786
|
+
mergeBase = (await this.git.exec(["merge-base", lastGen.commit_sha, "HEAD"])).trim();
|
|
787
|
+
} catch {
|
|
788
|
+
}
|
|
789
|
+
if (!mergeBase) {
|
|
790
|
+
this.warnings.push(
|
|
791
|
+
`No common ancestor between previous generation ${lastGen.commit_sha.slice(0, 7)} and HEAD. Falling back to composite tree-diff detection.`
|
|
792
|
+
);
|
|
765
793
|
return this.detectPatchesViaTreeDiff(
|
|
766
794
|
lastGen,
|
|
767
795
|
/* commitKnownMissing */
|
|
768
796
|
false
|
|
769
797
|
);
|
|
770
798
|
}
|
|
799
|
+
return this.detectPatchesInRange(mergeBase, lastGen, lock);
|
|
800
|
+
}
|
|
801
|
+
/**
|
|
802
|
+
* FER-10201 — Walk `${rangeStart}..HEAD`, classify each commit, emit one
|
|
803
|
+
* `StoredPatch` per customer commit. Body shared by the linear path
|
|
804
|
+
* (rangeStart = lastGen.commit_sha) and the merge-base path.
|
|
805
|
+
*
|
|
806
|
+
* Patch `base_generation` is always `lastGen.commit_sha` — the
|
|
807
|
+
* lockfile-tracked reference the applicator uses to fetch base file
|
|
808
|
+
* content, regardless of where the walk actually started.
|
|
809
|
+
*/
|
|
810
|
+
async detectPatchesInRange(rangeStart, lastGen, lock) {
|
|
771
811
|
const log = await this.git.exec([
|
|
772
812
|
"log",
|
|
773
813
|
"--first-parent",
|
|
774
814
|
"--format=%H%x00%an%x00%ae%x00%s",
|
|
775
|
-
`${
|
|
815
|
+
`${rangeStart}..HEAD`,
|
|
776
816
|
"--",
|
|
777
817
|
this.sdkOutputDir
|
|
778
818
|
]);
|
|
@@ -2180,21 +2220,66 @@ var ReplayService = class {
|
|
|
2180
2220
|
this.applicator = new ReplayApplicator(git, this.lockManager, outputDir);
|
|
2181
2221
|
this.committer = new ReplayCommitter(git, outputDir);
|
|
2182
2222
|
}
|
|
2183
|
-
|
|
2223
|
+
/**
|
|
2224
|
+
* Phase 1 of the two-phase replay flow. Runs preGenerationRebase (when applicable),
|
|
2225
|
+
* detects new patches, and creates the `[fern-generated]` commit. Leaves HEAD at
|
|
2226
|
+
* the generation commit (or unchanged for dry-run).
|
|
2227
|
+
*
|
|
2228
|
+
* Does NOT apply patches — the returned handle must be passed to
|
|
2229
|
+
* `applyPreparedReplay()` to complete the run. No disk writes to the lockfile
|
|
2230
|
+
* happen here; lockfile persistence is deferred to phase 2.
|
|
2231
|
+
*
|
|
2232
|
+
* Callers may land additional commits on HEAD between `prepareReplay` and
|
|
2233
|
+
* `applyPreparedReplay` (e.g., `[fern-autoversion]`).
|
|
2234
|
+
*/
|
|
2235
|
+
async prepareReplay(options) {
|
|
2184
2236
|
this.warnings = [];
|
|
2237
|
+
this.detector.warnings.length = 0;
|
|
2185
2238
|
if (options?.skipApplication) {
|
|
2186
|
-
return this.
|
|
2239
|
+
return this._prepareSkipApplication(options);
|
|
2187
2240
|
}
|
|
2188
2241
|
const flow = this.determineFlow();
|
|
2189
2242
|
switch (flow) {
|
|
2190
2243
|
case "first-generation":
|
|
2191
|
-
return this.
|
|
2244
|
+
return this._prepareFirstGeneration(options);
|
|
2245
|
+
case "no-patches":
|
|
2246
|
+
return this._prepareNoPatchesRegeneration(options);
|
|
2247
|
+
case "normal-regeneration":
|
|
2248
|
+
return this._prepareNormalRegeneration(options);
|
|
2249
|
+
}
|
|
2250
|
+
}
|
|
2251
|
+
/**
|
|
2252
|
+
* Phase 2 of the two-phase replay flow. Applies patches, rebases them against
|
|
2253
|
+
* the generation, saves the lockfile, and commits `[fern-replay]` (or stages
|
|
2254
|
+
* under `stageOnly`). Operates on HEAD at call time — mid-phase commits are
|
|
2255
|
+
* respected.
|
|
2256
|
+
*
|
|
2257
|
+
* For terminal handles (dry-run, first-gen has no patch work, skip-app does
|
|
2258
|
+
* its own post-commit logic), this returns the precomputed report.
|
|
2259
|
+
*/
|
|
2260
|
+
async applyPreparedReplay(prep, options) {
|
|
2261
|
+
if (prep._prepared.terminal) {
|
|
2262
|
+
return prep._prepared.preparedReport;
|
|
2263
|
+
}
|
|
2264
|
+
switch (prep._prepared.flow) {
|
|
2265
|
+
case "first-generation":
|
|
2266
|
+
return this._applyFirstGeneration(prep);
|
|
2267
|
+
case "skip-application":
|
|
2268
|
+
return this._applySkipApplication(prep, options);
|
|
2192
2269
|
case "no-patches":
|
|
2193
|
-
return this.
|
|
2270
|
+
return this._applyNoPatchesRegeneration(prep, options);
|
|
2194
2271
|
case "normal-regeneration":
|
|
2195
|
-
return this.
|
|
2272
|
+
return this._applyNormalRegeneration(prep, options);
|
|
2196
2273
|
}
|
|
2197
2274
|
}
|
|
2275
|
+
/**
|
|
2276
|
+
* Backwards-compatible atomic entry point. Composes `prepareReplay` + `applyPreparedReplay`.
|
|
2277
|
+
* Behavior is byte-identical to the pre-split implementation for all existing callers.
|
|
2278
|
+
*/
|
|
2279
|
+
async runReplay(options) {
|
|
2280
|
+
const prep = await this.prepareReplay(options);
|
|
2281
|
+
return this.applyPreparedReplay(prep, options);
|
|
2282
|
+
}
|
|
2198
2283
|
/**
|
|
2199
2284
|
* Sync the lockfile after a divergent PR was squash-merged.
|
|
2200
2285
|
* Call this BEFORE runReplay() when the CLI detects a merged divergent PR.
|
|
@@ -2268,15 +2353,35 @@ var ReplayService = class {
|
|
|
2268
2353
|
throw error;
|
|
2269
2354
|
}
|
|
2270
2355
|
}
|
|
2271
|
-
|
|
2356
|
+
firstGenerationReport() {
|
|
2357
|
+
return {
|
|
2358
|
+
flow: "first-generation",
|
|
2359
|
+
patchesDetected: 0,
|
|
2360
|
+
patchesApplied: 0,
|
|
2361
|
+
patchesWithConflicts: 0,
|
|
2362
|
+
patchesSkipped: 0,
|
|
2363
|
+
conflicts: []
|
|
2364
|
+
};
|
|
2365
|
+
}
|
|
2366
|
+
async _prepareFirstGeneration(options) {
|
|
2272
2367
|
if (options?.dryRun) {
|
|
2368
|
+
const headSha = await this.git.exec(["rev-parse", "HEAD"]).then((s) => s.trim()).catch(() => "");
|
|
2273
2369
|
return {
|
|
2274
2370
|
flow: "first-generation",
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2371
|
+
previousGenerationSha: null,
|
|
2372
|
+
currentGenerationSha: headSha,
|
|
2373
|
+
baseBranchHead: options.baseBranchHead ?? null,
|
|
2374
|
+
_prepared: {
|
|
2375
|
+
flow: "first-generation",
|
|
2376
|
+
terminal: true,
|
|
2377
|
+
preparedReport: this.firstGenerationReport(),
|
|
2378
|
+
patchesToApply: [],
|
|
2379
|
+
newPatchIds: /* @__PURE__ */ new Set(),
|
|
2380
|
+
detectorWarnings: [],
|
|
2381
|
+
revertedCount: 0,
|
|
2382
|
+
genSha: headSha,
|
|
2383
|
+
optionsSnapshot: options
|
|
2384
|
+
}
|
|
2280
2385
|
};
|
|
2281
2386
|
}
|
|
2282
2387
|
const commitOpts = options ? {
|
|
@@ -2286,22 +2391,36 @@ var ReplayService = class {
|
|
|
2286
2391
|
} : void 0;
|
|
2287
2392
|
await this.committer.commitGeneration("Initial SDK generation", commitOpts);
|
|
2288
2393
|
const genRecord = await this.committer.createGenerationRecord(commitOpts);
|
|
2289
|
-
this.lockManager.
|
|
2394
|
+
this.lockManager.initializeInMemory(genRecord);
|
|
2290
2395
|
return {
|
|
2291
2396
|
flow: "first-generation",
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2397
|
+
previousGenerationSha: null,
|
|
2398
|
+
currentGenerationSha: genRecord.commit_sha,
|
|
2399
|
+
baseBranchHead: options?.baseBranchHead ?? null,
|
|
2400
|
+
_prepared: {
|
|
2401
|
+
flow: "first-generation",
|
|
2402
|
+
terminal: false,
|
|
2403
|
+
patchesToApply: [],
|
|
2404
|
+
newPatchIds: /* @__PURE__ */ new Set(),
|
|
2405
|
+
detectorWarnings: [],
|
|
2406
|
+
revertedCount: 0,
|
|
2407
|
+
genSha: genRecord.commit_sha,
|
|
2408
|
+
optionsSnapshot: options
|
|
2409
|
+
}
|
|
2297
2410
|
};
|
|
2298
2411
|
}
|
|
2412
|
+
async _applyFirstGeneration(_prep) {
|
|
2413
|
+
this.lockManager.save();
|
|
2414
|
+
return this.firstGenerationReport();
|
|
2415
|
+
}
|
|
2299
2416
|
/**
|
|
2300
|
-
* Skip-application mode: commit the generation and update the
|
|
2301
|
-
* but don't detect or apply patches. Sets a marker
|
|
2302
|
-
* run skips revert detection in preGenerationRebase().
|
|
2417
|
+
* Skip-application mode phase 1: commit the generation and update the
|
|
2418
|
+
* in-memory lockfile, but don't detect or apply patches. Sets a marker
|
|
2419
|
+
* so the next normal run skips revert detection in preGenerationRebase().
|
|
2420
|
+
*
|
|
2421
|
+
* Disk save is deferred to `_applySkipApplication`.
|
|
2303
2422
|
*/
|
|
2304
|
-
async
|
|
2423
|
+
async _prepareSkipApplication(options) {
|
|
2305
2424
|
const commitOpts = options ? {
|
|
2306
2425
|
cliVersion: options.cliVersion ?? "unknown",
|
|
2307
2426
|
generatorVersions: options.generatorVersions ?? {},
|
|
@@ -2310,8 +2429,10 @@ var ReplayService = class {
|
|
|
2310
2429
|
await this.committer.commitGeneration("Update SDK (replay skipped)", commitOpts);
|
|
2311
2430
|
await this.cleanupStaleConflictMarkers();
|
|
2312
2431
|
const genRecord = await this.committer.createGenerationRecord(commitOpts);
|
|
2432
|
+
let previousGenerationSha = null;
|
|
2313
2433
|
try {
|
|
2314
|
-
this.lockManager.read();
|
|
2434
|
+
const lock = this.lockManager.read();
|
|
2435
|
+
previousGenerationSha = lock.current_generation ?? null;
|
|
2315
2436
|
this.lockManager.addGeneration(genRecord);
|
|
2316
2437
|
} catch (error) {
|
|
2317
2438
|
if (error instanceof LockfileNotFoundError) {
|
|
@@ -2321,6 +2442,24 @@ var ReplayService = class {
|
|
|
2321
2442
|
}
|
|
2322
2443
|
}
|
|
2323
2444
|
this.lockManager.setReplaySkippedAt((/* @__PURE__ */ new Date()).toISOString());
|
|
2445
|
+
return {
|
|
2446
|
+
flow: "skip-application",
|
|
2447
|
+
previousGenerationSha,
|
|
2448
|
+
currentGenerationSha: genRecord.commit_sha,
|
|
2449
|
+
baseBranchHead: options?.baseBranchHead ?? null,
|
|
2450
|
+
_prepared: {
|
|
2451
|
+
flow: "skip-application",
|
|
2452
|
+
terminal: false,
|
|
2453
|
+
patchesToApply: [],
|
|
2454
|
+
newPatchIds: /* @__PURE__ */ new Set(),
|
|
2455
|
+
detectorWarnings: [],
|
|
2456
|
+
revertedCount: 0,
|
|
2457
|
+
genSha: genRecord.commit_sha,
|
|
2458
|
+
optionsSnapshot: options
|
|
2459
|
+
}
|
|
2460
|
+
};
|
|
2461
|
+
}
|
|
2462
|
+
async _applySkipApplication(_prep, options) {
|
|
2324
2463
|
this.lockManager.save();
|
|
2325
2464
|
const credentialWarnings = [...this.lockManager.warnings];
|
|
2326
2465
|
if (!options?.stageOnly) {
|
|
@@ -2338,12 +2477,14 @@ var ReplayService = class {
|
|
|
2338
2477
|
warnings: credentialWarnings.length > 0 ? credentialWarnings : void 0
|
|
2339
2478
|
};
|
|
2340
2479
|
}
|
|
2341
|
-
async
|
|
2480
|
+
async _prepareNoPatchesRegeneration(options) {
|
|
2481
|
+
const preLock = this.lockManager.read();
|
|
2482
|
+
const previousGenerationSha = preLock.current_generation ?? null;
|
|
2342
2483
|
let { patches: newPatches, revertedPatchIds } = await this.detector.detectNewPatches();
|
|
2343
2484
|
const detectorWarnings = [...this.detector.warnings];
|
|
2344
2485
|
if (options?.dryRun) {
|
|
2345
2486
|
const dryRunWarnings = [...detectorWarnings, ...this.warnings];
|
|
2346
|
-
|
|
2487
|
+
const preparedReport = {
|
|
2347
2488
|
flow: "no-patches",
|
|
2348
2489
|
patchesDetected: newPatches.length,
|
|
2349
2490
|
patchesApplied: 0,
|
|
@@ -2354,9 +2495,26 @@ var ReplayService = class {
|
|
|
2354
2495
|
wouldApply: newPatches,
|
|
2355
2496
|
warnings: dryRunWarnings.length > 0 ? dryRunWarnings : void 0
|
|
2356
2497
|
};
|
|
2498
|
+
const headSha = await this.git.exec(["rev-parse", "HEAD"]).then((s) => s.trim()).catch(() => "");
|
|
2499
|
+
return {
|
|
2500
|
+
flow: "no-patches",
|
|
2501
|
+
previousGenerationSha,
|
|
2502
|
+
currentGenerationSha: headSha,
|
|
2503
|
+
baseBranchHead: options.baseBranchHead ?? null,
|
|
2504
|
+
_prepared: {
|
|
2505
|
+
flow: "no-patches",
|
|
2506
|
+
terminal: true,
|
|
2507
|
+
preparedReport,
|
|
2508
|
+
patchesToApply: [],
|
|
2509
|
+
newPatchIds: /* @__PURE__ */ new Set(),
|
|
2510
|
+
detectorWarnings,
|
|
2511
|
+
revertedCount: revertedPatchIds.length,
|
|
2512
|
+
genSha: headSha,
|
|
2513
|
+
optionsSnapshot: options
|
|
2514
|
+
}
|
|
2515
|
+
};
|
|
2357
2516
|
}
|
|
2358
2517
|
{
|
|
2359
|
-
const preLock = this.lockManager.read();
|
|
2360
2518
|
const preCurrentGen = preLock.current_generation;
|
|
2361
2519
|
const uniqueFiles = [...new Set(newPatches.flatMap((p) => p.files))];
|
|
2362
2520
|
const absorbedFiles = /* @__PURE__ */ new Set();
|
|
@@ -2387,6 +2545,27 @@ var ReplayService = class {
|
|
|
2387
2545
|
await this.cleanupStaleConflictMarkers();
|
|
2388
2546
|
const genRecord = await this.committer.createGenerationRecord(commitOpts);
|
|
2389
2547
|
this.lockManager.addGeneration(genRecord);
|
|
2548
|
+
return {
|
|
2549
|
+
flow: "no-patches",
|
|
2550
|
+
previousGenerationSha,
|
|
2551
|
+
currentGenerationSha: genRecord.commit_sha,
|
|
2552
|
+
baseBranchHead: options?.baseBranchHead ?? null,
|
|
2553
|
+
_prepared: {
|
|
2554
|
+
flow: "no-patches",
|
|
2555
|
+
terminal: false,
|
|
2556
|
+
patchesToApply: newPatches,
|
|
2557
|
+
newPatchIds: new Set(newPatches.map((p) => p.id)),
|
|
2558
|
+
detectorWarnings,
|
|
2559
|
+
revertedCount: revertedPatchIds.length,
|
|
2560
|
+
genSha: genRecord.commit_sha,
|
|
2561
|
+
optionsSnapshot: options
|
|
2562
|
+
}
|
|
2563
|
+
};
|
|
2564
|
+
}
|
|
2565
|
+
async _applyNoPatchesRegeneration(prep, options) {
|
|
2566
|
+
const newPatches = prep._prepared.patchesToApply;
|
|
2567
|
+
const detectorWarnings = prep._prepared.detectorWarnings;
|
|
2568
|
+
const genSha = prep._prepared.genSha;
|
|
2390
2569
|
let results = [];
|
|
2391
2570
|
if (newPatches.length > 0) {
|
|
2392
2571
|
results = await this.applicator.applyPatches(newPatches);
|
|
@@ -2398,7 +2577,7 @@ var ReplayService = class {
|
|
|
2398
2577
|
}
|
|
2399
2578
|
}
|
|
2400
2579
|
}
|
|
2401
|
-
const rebaseCounts = await this.rebasePatches(results,
|
|
2580
|
+
const rebaseCounts = await this.rebasePatches(results, genSha);
|
|
2402
2581
|
for (const patch of newPatches) {
|
|
2403
2582
|
if (!rebaseCounts.absorbedPatchIds.has(patch.id)) {
|
|
2404
2583
|
this.lockManager.addPatch(patch);
|
|
@@ -2415,15 +2594,26 @@ var ReplayService = class {
|
|
|
2415
2594
|
}
|
|
2416
2595
|
}
|
|
2417
2596
|
const warnings = [...detectorWarnings, ...this.warnings];
|
|
2418
|
-
return this.buildReport(
|
|
2597
|
+
return this.buildReport(
|
|
2598
|
+
"no-patches",
|
|
2599
|
+
newPatches,
|
|
2600
|
+
results,
|
|
2601
|
+
prep._prepared.optionsSnapshot,
|
|
2602
|
+
warnings,
|
|
2603
|
+
rebaseCounts,
|
|
2604
|
+
void 0,
|
|
2605
|
+
prep._prepared.revertedCount
|
|
2606
|
+
);
|
|
2419
2607
|
}
|
|
2420
|
-
async
|
|
2608
|
+
async _prepareNormalRegeneration(options) {
|
|
2609
|
+
const preLock = this.lockManager.read();
|
|
2610
|
+
const previousGenerationSha = preLock.current_generation ?? null;
|
|
2421
2611
|
if (options?.dryRun) {
|
|
2422
2612
|
const existingPatches2 = this.lockManager.getPatches();
|
|
2423
2613
|
const { patches: newPatches2, revertedPatchIds: dryRunReverted } = await this.detector.detectNewPatches();
|
|
2424
|
-
const
|
|
2614
|
+
const warnings = [...this.detector.warnings, ...this.warnings];
|
|
2425
2615
|
const allPatches2 = [...existingPatches2, ...newPatches2];
|
|
2426
|
-
|
|
2616
|
+
const preparedReport = {
|
|
2427
2617
|
flow: "normal-regeneration",
|
|
2428
2618
|
patchesDetected: allPatches2.length,
|
|
2429
2619
|
patchesApplied: 0,
|
|
@@ -2432,7 +2622,25 @@ var ReplayService = class {
|
|
|
2432
2622
|
patchesReverted: dryRunReverted.length,
|
|
2433
2623
|
conflicts: [],
|
|
2434
2624
|
wouldApply: allPatches2,
|
|
2435
|
-
warnings:
|
|
2625
|
+
warnings: warnings.length > 0 ? warnings : void 0
|
|
2626
|
+
};
|
|
2627
|
+
const headSha = await this.git.exec(["rev-parse", "HEAD"]).then((s) => s.trim()).catch(() => "");
|
|
2628
|
+
return {
|
|
2629
|
+
flow: "normal-regeneration",
|
|
2630
|
+
previousGenerationSha,
|
|
2631
|
+
currentGenerationSha: headSha,
|
|
2632
|
+
baseBranchHead: options.baseBranchHead ?? null,
|
|
2633
|
+
_prepared: {
|
|
2634
|
+
flow: "normal-regeneration",
|
|
2635
|
+
terminal: true,
|
|
2636
|
+
preparedReport,
|
|
2637
|
+
patchesToApply: [],
|
|
2638
|
+
newPatchIds: /* @__PURE__ */ new Set(),
|
|
2639
|
+
detectorWarnings: [...this.detector.warnings],
|
|
2640
|
+
revertedCount: dryRunReverted.length,
|
|
2641
|
+
genSha: headSha,
|
|
2642
|
+
optionsSnapshot: options
|
|
2643
|
+
}
|
|
2436
2644
|
};
|
|
2437
2645
|
}
|
|
2438
2646
|
let existingPatches = this.lockManager.getPatches();
|
|
@@ -2484,6 +2692,29 @@ var ReplayService = class {
|
|
|
2484
2692
|
await this.cleanupStaleConflictMarkers();
|
|
2485
2693
|
const genRecord = await this.committer.createGenerationRecord(commitOpts);
|
|
2486
2694
|
this.lockManager.addGeneration(genRecord);
|
|
2695
|
+
return {
|
|
2696
|
+
flow: "normal-regeneration",
|
|
2697
|
+
previousGenerationSha,
|
|
2698
|
+
currentGenerationSha: genRecord.commit_sha,
|
|
2699
|
+
baseBranchHead: options?.baseBranchHead ?? null,
|
|
2700
|
+
_prepared: {
|
|
2701
|
+
flow: "normal-regeneration",
|
|
2702
|
+
terminal: false,
|
|
2703
|
+
patchesToApply: allPatches,
|
|
2704
|
+
newPatchIds: new Set(newPatches.map((p) => p.id)),
|
|
2705
|
+
preRebaseCounts,
|
|
2706
|
+
detectorWarnings,
|
|
2707
|
+
revertedCount: revertedPatchIds.length,
|
|
2708
|
+
genSha: genRecord.commit_sha,
|
|
2709
|
+
optionsSnapshot: options
|
|
2710
|
+
}
|
|
2711
|
+
};
|
|
2712
|
+
}
|
|
2713
|
+
async _applyNormalRegeneration(prep, options) {
|
|
2714
|
+
const allPatches = prep._prepared.patchesToApply;
|
|
2715
|
+
const newPatchIds = prep._prepared.newPatchIds;
|
|
2716
|
+
const detectorWarnings = prep._prepared.detectorWarnings;
|
|
2717
|
+
const genSha = prep._prepared.genSha;
|
|
2487
2718
|
const results = await this.applicator.applyPatches(allPatches);
|
|
2488
2719
|
this._lastApplyResults = results;
|
|
2489
2720
|
this.revertConflictingFiles(results);
|
|
@@ -2492,7 +2723,8 @@ var ReplayService = class {
|
|
|
2492
2723
|
result.patch.status = "unresolved";
|
|
2493
2724
|
}
|
|
2494
2725
|
}
|
|
2495
|
-
const rebaseCounts = await this.rebasePatches(results,
|
|
2726
|
+
const rebaseCounts = await this.rebasePatches(results, genSha);
|
|
2727
|
+
const newPatches = allPatches.filter((p) => newPatchIds.has(p.id));
|
|
2496
2728
|
for (const patch of newPatches) {
|
|
2497
2729
|
if (!rebaseCounts.absorbedPatchIds.has(patch.id)) {
|
|
2498
2730
|
this.lockManager.addPatch(patch);
|
|
@@ -2519,11 +2751,11 @@ var ReplayService = class {
|
|
|
2519
2751
|
"normal-regeneration",
|
|
2520
2752
|
allPatches,
|
|
2521
2753
|
results,
|
|
2522
|
-
|
|
2754
|
+
prep._prepared.optionsSnapshot,
|
|
2523
2755
|
warnings,
|
|
2524
2756
|
rebaseCounts,
|
|
2525
|
-
preRebaseCounts,
|
|
2526
|
-
|
|
2757
|
+
prep._prepared.preRebaseCounts,
|
|
2758
|
+
prep._prepared.revertedCount
|
|
2527
2759
|
);
|
|
2528
2760
|
}
|
|
2529
2761
|
/**
|