@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.js
CHANGED
|
@@ -439,7 +439,7 @@ var FERN_SUPPORT_NAMES = ["fern-support", "Fern Support"];
|
|
|
439
439
|
function isGenerationCommit(commit) {
|
|
440
440
|
const isFernSupport = FERN_SUPPORT_NAMES.includes(commit.authorName);
|
|
441
441
|
const isBotAuthor = !isFernSupport && (commit.authorLogin === FERN_BOT_LOGIN || commit.authorEmail === FERN_BOT_EMAIL || commit.authorName === FERN_BOT_NAME);
|
|
442
|
-
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.
|
|
442
|
+
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.
|
|
443
443
|
// The default PR title is "SDK Generation" (from GithubStep's commitMessage default).
|
|
444
444
|
// GitHub appends "(#N)" for the PR number, e.g. "SDK Generation (#70)".
|
|
445
445
|
commit.message.startsWith("SDK Generation");
|
|
@@ -708,17 +708,57 @@ var ReplayDetector = class {
|
|
|
708
708
|
}
|
|
709
709
|
const isAncestor = await this.git.isAncestor(lastGen.commit_sha, "HEAD");
|
|
710
710
|
if (!isAncestor) {
|
|
711
|
+
return this.detectPatchesViaMergeBase(lastGen, lock);
|
|
712
|
+
}
|
|
713
|
+
return this.detectPatchesInRange(lastGen.commit_sha, lastGen, lock);
|
|
714
|
+
}
|
|
715
|
+
/**
|
|
716
|
+
* FER-10201 — Non-linear-history detection via `merge-base(prevGen, HEAD)`.
|
|
717
|
+
*
|
|
718
|
+
* After a squash-merge of a Fern-bot PR, `lastGen.commit_sha` (the previous
|
|
719
|
+
* `[fern-generated]`) is orphaned but still in git's object database. The
|
|
720
|
+
* merge-base is the commit on main from which the bot's branch was created —
|
|
721
|
+
* a reachable ancestor of HEAD. Walking that range and classifying each
|
|
722
|
+
* commit via `isGenerationCommit` mirrors the linear path and eliminates
|
|
723
|
+
* the bug class where pipeline-driven changes (autoversion, replay,
|
|
724
|
+
* generation) get bundled as customer customizations.
|
|
725
|
+
*
|
|
726
|
+
* Falls through to the legacy composite path when no common ancestor exists
|
|
727
|
+
* (truly disjoint history — orphan branches with no shared root).
|
|
728
|
+
*/
|
|
729
|
+
async detectPatchesViaMergeBase(lastGen, lock) {
|
|
730
|
+
let mergeBase = "";
|
|
731
|
+
try {
|
|
732
|
+
mergeBase = (await this.git.exec(["merge-base", lastGen.commit_sha, "HEAD"])).trim();
|
|
733
|
+
} catch {
|
|
734
|
+
}
|
|
735
|
+
if (!mergeBase) {
|
|
736
|
+
this.warnings.push(
|
|
737
|
+
`No common ancestor between previous generation ${lastGen.commit_sha.slice(0, 7)} and HEAD. Falling back to composite tree-diff detection.`
|
|
738
|
+
);
|
|
711
739
|
return this.detectPatchesViaTreeDiff(
|
|
712
740
|
lastGen,
|
|
713
741
|
/* commitKnownMissing */
|
|
714
742
|
false
|
|
715
743
|
);
|
|
716
744
|
}
|
|
745
|
+
return this.detectPatchesInRange(mergeBase, lastGen, lock);
|
|
746
|
+
}
|
|
747
|
+
/**
|
|
748
|
+
* FER-10201 — Walk `${rangeStart}..HEAD`, classify each commit, emit one
|
|
749
|
+
* `StoredPatch` per customer commit. Body shared by the linear path
|
|
750
|
+
* (rangeStart = lastGen.commit_sha) and the merge-base path.
|
|
751
|
+
*
|
|
752
|
+
* Patch `base_generation` is always `lastGen.commit_sha` — the
|
|
753
|
+
* lockfile-tracked reference the applicator uses to fetch base file
|
|
754
|
+
* content, regardless of where the walk actually started.
|
|
755
|
+
*/
|
|
756
|
+
async detectPatchesInRange(rangeStart, lastGen, lock) {
|
|
717
757
|
const log = await this.git.exec([
|
|
718
758
|
"log",
|
|
719
759
|
"--first-parent",
|
|
720
760
|
"--format=%H%x00%an%x00%ae%x00%s",
|
|
721
|
-
`${
|
|
761
|
+
`${rangeStart}..HEAD`,
|
|
722
762
|
"--",
|
|
723
763
|
this.sdkOutputDir
|
|
724
764
|
]);
|
|
@@ -2126,21 +2166,66 @@ var ReplayService = class {
|
|
|
2126
2166
|
this.applicator = new ReplayApplicator(git, this.lockManager, outputDir);
|
|
2127
2167
|
this.committer = new ReplayCommitter(git, outputDir);
|
|
2128
2168
|
}
|
|
2129
|
-
|
|
2169
|
+
/**
|
|
2170
|
+
* Phase 1 of the two-phase replay flow. Runs preGenerationRebase (when applicable),
|
|
2171
|
+
* detects new patches, and creates the `[fern-generated]` commit. Leaves HEAD at
|
|
2172
|
+
* the generation commit (or unchanged for dry-run).
|
|
2173
|
+
*
|
|
2174
|
+
* Does NOT apply patches — the returned handle must be passed to
|
|
2175
|
+
* `applyPreparedReplay()` to complete the run. No disk writes to the lockfile
|
|
2176
|
+
* happen here; lockfile persistence is deferred to phase 2.
|
|
2177
|
+
*
|
|
2178
|
+
* Callers may land additional commits on HEAD between `prepareReplay` and
|
|
2179
|
+
* `applyPreparedReplay` (e.g., `[fern-autoversion]`).
|
|
2180
|
+
*/
|
|
2181
|
+
async prepareReplay(options) {
|
|
2130
2182
|
this.warnings = [];
|
|
2183
|
+
this.detector.warnings.length = 0;
|
|
2131
2184
|
if (options?.skipApplication) {
|
|
2132
|
-
return this.
|
|
2185
|
+
return this._prepareSkipApplication(options);
|
|
2133
2186
|
}
|
|
2134
2187
|
const flow = this.determineFlow();
|
|
2135
2188
|
switch (flow) {
|
|
2136
2189
|
case "first-generation":
|
|
2137
|
-
return this.
|
|
2190
|
+
return this._prepareFirstGeneration(options);
|
|
2191
|
+
case "no-patches":
|
|
2192
|
+
return this._prepareNoPatchesRegeneration(options);
|
|
2193
|
+
case "normal-regeneration":
|
|
2194
|
+
return this._prepareNormalRegeneration(options);
|
|
2195
|
+
}
|
|
2196
|
+
}
|
|
2197
|
+
/**
|
|
2198
|
+
* Phase 2 of the two-phase replay flow. Applies patches, rebases them against
|
|
2199
|
+
* the generation, saves the lockfile, and commits `[fern-replay]` (or stages
|
|
2200
|
+
* under `stageOnly`). Operates on HEAD at call time — mid-phase commits are
|
|
2201
|
+
* respected.
|
|
2202
|
+
*
|
|
2203
|
+
* For terminal handles (dry-run, first-gen has no patch work, skip-app does
|
|
2204
|
+
* its own post-commit logic), this returns the precomputed report.
|
|
2205
|
+
*/
|
|
2206
|
+
async applyPreparedReplay(prep, options) {
|
|
2207
|
+
if (prep._prepared.terminal) {
|
|
2208
|
+
return prep._prepared.preparedReport;
|
|
2209
|
+
}
|
|
2210
|
+
switch (prep._prepared.flow) {
|
|
2211
|
+
case "first-generation":
|
|
2212
|
+
return this._applyFirstGeneration(prep);
|
|
2213
|
+
case "skip-application":
|
|
2214
|
+
return this._applySkipApplication(prep, options);
|
|
2138
2215
|
case "no-patches":
|
|
2139
|
-
return this.
|
|
2216
|
+
return this._applyNoPatchesRegeneration(prep, options);
|
|
2140
2217
|
case "normal-regeneration":
|
|
2141
|
-
return this.
|
|
2218
|
+
return this._applyNormalRegeneration(prep, options);
|
|
2142
2219
|
}
|
|
2143
2220
|
}
|
|
2221
|
+
/**
|
|
2222
|
+
* Backwards-compatible atomic entry point. Composes `prepareReplay` + `applyPreparedReplay`.
|
|
2223
|
+
* Behavior is byte-identical to the pre-split implementation for all existing callers.
|
|
2224
|
+
*/
|
|
2225
|
+
async runReplay(options) {
|
|
2226
|
+
const prep = await this.prepareReplay(options);
|
|
2227
|
+
return this.applyPreparedReplay(prep, options);
|
|
2228
|
+
}
|
|
2144
2229
|
/**
|
|
2145
2230
|
* Sync the lockfile after a divergent PR was squash-merged.
|
|
2146
2231
|
* Call this BEFORE runReplay() when the CLI detects a merged divergent PR.
|
|
@@ -2214,15 +2299,35 @@ var ReplayService = class {
|
|
|
2214
2299
|
throw error;
|
|
2215
2300
|
}
|
|
2216
2301
|
}
|
|
2217
|
-
|
|
2302
|
+
firstGenerationReport() {
|
|
2303
|
+
return {
|
|
2304
|
+
flow: "first-generation",
|
|
2305
|
+
patchesDetected: 0,
|
|
2306
|
+
patchesApplied: 0,
|
|
2307
|
+
patchesWithConflicts: 0,
|
|
2308
|
+
patchesSkipped: 0,
|
|
2309
|
+
conflicts: []
|
|
2310
|
+
};
|
|
2311
|
+
}
|
|
2312
|
+
async _prepareFirstGeneration(options) {
|
|
2218
2313
|
if (options?.dryRun) {
|
|
2314
|
+
const headSha = await this.git.exec(["rev-parse", "HEAD"]).then((s) => s.trim()).catch(() => "");
|
|
2219
2315
|
return {
|
|
2220
2316
|
flow: "first-generation",
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2317
|
+
previousGenerationSha: null,
|
|
2318
|
+
currentGenerationSha: headSha,
|
|
2319
|
+
baseBranchHead: options.baseBranchHead ?? null,
|
|
2320
|
+
_prepared: {
|
|
2321
|
+
flow: "first-generation",
|
|
2322
|
+
terminal: true,
|
|
2323
|
+
preparedReport: this.firstGenerationReport(),
|
|
2324
|
+
patchesToApply: [],
|
|
2325
|
+
newPatchIds: /* @__PURE__ */ new Set(),
|
|
2326
|
+
detectorWarnings: [],
|
|
2327
|
+
revertedCount: 0,
|
|
2328
|
+
genSha: headSha,
|
|
2329
|
+
optionsSnapshot: options
|
|
2330
|
+
}
|
|
2226
2331
|
};
|
|
2227
2332
|
}
|
|
2228
2333
|
const commitOpts = options ? {
|
|
@@ -2232,22 +2337,36 @@ var ReplayService = class {
|
|
|
2232
2337
|
} : void 0;
|
|
2233
2338
|
await this.committer.commitGeneration("Initial SDK generation", commitOpts);
|
|
2234
2339
|
const genRecord = await this.committer.createGenerationRecord(commitOpts);
|
|
2235
|
-
this.lockManager.
|
|
2340
|
+
this.lockManager.initializeInMemory(genRecord);
|
|
2236
2341
|
return {
|
|
2237
2342
|
flow: "first-generation",
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
|
|
2241
|
-
|
|
2242
|
-
|
|
2343
|
+
previousGenerationSha: null,
|
|
2344
|
+
currentGenerationSha: genRecord.commit_sha,
|
|
2345
|
+
baseBranchHead: options?.baseBranchHead ?? null,
|
|
2346
|
+
_prepared: {
|
|
2347
|
+
flow: "first-generation",
|
|
2348
|
+
terminal: false,
|
|
2349
|
+
patchesToApply: [],
|
|
2350
|
+
newPatchIds: /* @__PURE__ */ new Set(),
|
|
2351
|
+
detectorWarnings: [],
|
|
2352
|
+
revertedCount: 0,
|
|
2353
|
+
genSha: genRecord.commit_sha,
|
|
2354
|
+
optionsSnapshot: options
|
|
2355
|
+
}
|
|
2243
2356
|
};
|
|
2244
2357
|
}
|
|
2358
|
+
async _applyFirstGeneration(_prep) {
|
|
2359
|
+
this.lockManager.save();
|
|
2360
|
+
return this.firstGenerationReport();
|
|
2361
|
+
}
|
|
2245
2362
|
/**
|
|
2246
|
-
* Skip-application mode: commit the generation and update the
|
|
2247
|
-
* but don't detect or apply patches. Sets a marker
|
|
2248
|
-
* run skips revert detection in preGenerationRebase().
|
|
2363
|
+
* Skip-application mode phase 1: commit the generation and update the
|
|
2364
|
+
* in-memory lockfile, but don't detect or apply patches. Sets a marker
|
|
2365
|
+
* so the next normal run skips revert detection in preGenerationRebase().
|
|
2366
|
+
*
|
|
2367
|
+
* Disk save is deferred to `_applySkipApplication`.
|
|
2249
2368
|
*/
|
|
2250
|
-
async
|
|
2369
|
+
async _prepareSkipApplication(options) {
|
|
2251
2370
|
const commitOpts = options ? {
|
|
2252
2371
|
cliVersion: options.cliVersion ?? "unknown",
|
|
2253
2372
|
generatorVersions: options.generatorVersions ?? {},
|
|
@@ -2256,8 +2375,10 @@ var ReplayService = class {
|
|
|
2256
2375
|
await this.committer.commitGeneration("Update SDK (replay skipped)", commitOpts);
|
|
2257
2376
|
await this.cleanupStaleConflictMarkers();
|
|
2258
2377
|
const genRecord = await this.committer.createGenerationRecord(commitOpts);
|
|
2378
|
+
let previousGenerationSha = null;
|
|
2259
2379
|
try {
|
|
2260
|
-
this.lockManager.read();
|
|
2380
|
+
const lock = this.lockManager.read();
|
|
2381
|
+
previousGenerationSha = lock.current_generation ?? null;
|
|
2261
2382
|
this.lockManager.addGeneration(genRecord);
|
|
2262
2383
|
} catch (error) {
|
|
2263
2384
|
if (error instanceof LockfileNotFoundError) {
|
|
@@ -2267,6 +2388,24 @@ var ReplayService = class {
|
|
|
2267
2388
|
}
|
|
2268
2389
|
}
|
|
2269
2390
|
this.lockManager.setReplaySkippedAt((/* @__PURE__ */ new Date()).toISOString());
|
|
2391
|
+
return {
|
|
2392
|
+
flow: "skip-application",
|
|
2393
|
+
previousGenerationSha,
|
|
2394
|
+
currentGenerationSha: genRecord.commit_sha,
|
|
2395
|
+
baseBranchHead: options?.baseBranchHead ?? null,
|
|
2396
|
+
_prepared: {
|
|
2397
|
+
flow: "skip-application",
|
|
2398
|
+
terminal: false,
|
|
2399
|
+
patchesToApply: [],
|
|
2400
|
+
newPatchIds: /* @__PURE__ */ new Set(),
|
|
2401
|
+
detectorWarnings: [],
|
|
2402
|
+
revertedCount: 0,
|
|
2403
|
+
genSha: genRecord.commit_sha,
|
|
2404
|
+
optionsSnapshot: options
|
|
2405
|
+
}
|
|
2406
|
+
};
|
|
2407
|
+
}
|
|
2408
|
+
async _applySkipApplication(_prep, options) {
|
|
2270
2409
|
this.lockManager.save();
|
|
2271
2410
|
const credentialWarnings = [...this.lockManager.warnings];
|
|
2272
2411
|
if (!options?.stageOnly) {
|
|
@@ -2284,12 +2423,14 @@ var ReplayService = class {
|
|
|
2284
2423
|
warnings: credentialWarnings.length > 0 ? credentialWarnings : void 0
|
|
2285
2424
|
};
|
|
2286
2425
|
}
|
|
2287
|
-
async
|
|
2426
|
+
async _prepareNoPatchesRegeneration(options) {
|
|
2427
|
+
const preLock = this.lockManager.read();
|
|
2428
|
+
const previousGenerationSha = preLock.current_generation ?? null;
|
|
2288
2429
|
let { patches: newPatches, revertedPatchIds } = await this.detector.detectNewPatches();
|
|
2289
2430
|
const detectorWarnings = [...this.detector.warnings];
|
|
2290
2431
|
if (options?.dryRun) {
|
|
2291
2432
|
const dryRunWarnings = [...detectorWarnings, ...this.warnings];
|
|
2292
|
-
|
|
2433
|
+
const preparedReport = {
|
|
2293
2434
|
flow: "no-patches",
|
|
2294
2435
|
patchesDetected: newPatches.length,
|
|
2295
2436
|
patchesApplied: 0,
|
|
@@ -2300,9 +2441,26 @@ var ReplayService = class {
|
|
|
2300
2441
|
wouldApply: newPatches,
|
|
2301
2442
|
warnings: dryRunWarnings.length > 0 ? dryRunWarnings : void 0
|
|
2302
2443
|
};
|
|
2444
|
+
const headSha = await this.git.exec(["rev-parse", "HEAD"]).then((s) => s.trim()).catch(() => "");
|
|
2445
|
+
return {
|
|
2446
|
+
flow: "no-patches",
|
|
2447
|
+
previousGenerationSha,
|
|
2448
|
+
currentGenerationSha: headSha,
|
|
2449
|
+
baseBranchHead: options.baseBranchHead ?? null,
|
|
2450
|
+
_prepared: {
|
|
2451
|
+
flow: "no-patches",
|
|
2452
|
+
terminal: true,
|
|
2453
|
+
preparedReport,
|
|
2454
|
+
patchesToApply: [],
|
|
2455
|
+
newPatchIds: /* @__PURE__ */ new Set(),
|
|
2456
|
+
detectorWarnings,
|
|
2457
|
+
revertedCount: revertedPatchIds.length,
|
|
2458
|
+
genSha: headSha,
|
|
2459
|
+
optionsSnapshot: options
|
|
2460
|
+
}
|
|
2461
|
+
};
|
|
2303
2462
|
}
|
|
2304
2463
|
{
|
|
2305
|
-
const preLock = this.lockManager.read();
|
|
2306
2464
|
const preCurrentGen = preLock.current_generation;
|
|
2307
2465
|
const uniqueFiles = [...new Set(newPatches.flatMap((p) => p.files))];
|
|
2308
2466
|
const absorbedFiles = /* @__PURE__ */ new Set();
|
|
@@ -2333,6 +2491,27 @@ var ReplayService = class {
|
|
|
2333
2491
|
await this.cleanupStaleConflictMarkers();
|
|
2334
2492
|
const genRecord = await this.committer.createGenerationRecord(commitOpts);
|
|
2335
2493
|
this.lockManager.addGeneration(genRecord);
|
|
2494
|
+
return {
|
|
2495
|
+
flow: "no-patches",
|
|
2496
|
+
previousGenerationSha,
|
|
2497
|
+
currentGenerationSha: genRecord.commit_sha,
|
|
2498
|
+
baseBranchHead: options?.baseBranchHead ?? null,
|
|
2499
|
+
_prepared: {
|
|
2500
|
+
flow: "no-patches",
|
|
2501
|
+
terminal: false,
|
|
2502
|
+
patchesToApply: newPatches,
|
|
2503
|
+
newPatchIds: new Set(newPatches.map((p) => p.id)),
|
|
2504
|
+
detectorWarnings,
|
|
2505
|
+
revertedCount: revertedPatchIds.length,
|
|
2506
|
+
genSha: genRecord.commit_sha,
|
|
2507
|
+
optionsSnapshot: options
|
|
2508
|
+
}
|
|
2509
|
+
};
|
|
2510
|
+
}
|
|
2511
|
+
async _applyNoPatchesRegeneration(prep, options) {
|
|
2512
|
+
const newPatches = prep._prepared.patchesToApply;
|
|
2513
|
+
const detectorWarnings = prep._prepared.detectorWarnings;
|
|
2514
|
+
const genSha = prep._prepared.genSha;
|
|
2336
2515
|
let results = [];
|
|
2337
2516
|
if (newPatches.length > 0) {
|
|
2338
2517
|
results = await this.applicator.applyPatches(newPatches);
|
|
@@ -2344,7 +2523,7 @@ var ReplayService = class {
|
|
|
2344
2523
|
}
|
|
2345
2524
|
}
|
|
2346
2525
|
}
|
|
2347
|
-
const rebaseCounts = await this.rebasePatches(results,
|
|
2526
|
+
const rebaseCounts = await this.rebasePatches(results, genSha);
|
|
2348
2527
|
for (const patch of newPatches) {
|
|
2349
2528
|
if (!rebaseCounts.absorbedPatchIds.has(patch.id)) {
|
|
2350
2529
|
this.lockManager.addPatch(patch);
|
|
@@ -2361,15 +2540,26 @@ var ReplayService = class {
|
|
|
2361
2540
|
}
|
|
2362
2541
|
}
|
|
2363
2542
|
const warnings = [...detectorWarnings, ...this.warnings];
|
|
2364
|
-
return this.buildReport(
|
|
2543
|
+
return this.buildReport(
|
|
2544
|
+
"no-patches",
|
|
2545
|
+
newPatches,
|
|
2546
|
+
results,
|
|
2547
|
+
prep._prepared.optionsSnapshot,
|
|
2548
|
+
warnings,
|
|
2549
|
+
rebaseCounts,
|
|
2550
|
+
void 0,
|
|
2551
|
+
prep._prepared.revertedCount
|
|
2552
|
+
);
|
|
2365
2553
|
}
|
|
2366
|
-
async
|
|
2554
|
+
async _prepareNormalRegeneration(options) {
|
|
2555
|
+
const preLock = this.lockManager.read();
|
|
2556
|
+
const previousGenerationSha = preLock.current_generation ?? null;
|
|
2367
2557
|
if (options?.dryRun) {
|
|
2368
2558
|
const existingPatches2 = this.lockManager.getPatches();
|
|
2369
2559
|
const { patches: newPatches2, revertedPatchIds: dryRunReverted } = await this.detector.detectNewPatches();
|
|
2370
|
-
const
|
|
2560
|
+
const warnings = [...this.detector.warnings, ...this.warnings];
|
|
2371
2561
|
const allPatches2 = [...existingPatches2, ...newPatches2];
|
|
2372
|
-
|
|
2562
|
+
const preparedReport = {
|
|
2373
2563
|
flow: "normal-regeneration",
|
|
2374
2564
|
patchesDetected: allPatches2.length,
|
|
2375
2565
|
patchesApplied: 0,
|
|
@@ -2378,7 +2568,25 @@ var ReplayService = class {
|
|
|
2378
2568
|
patchesReverted: dryRunReverted.length,
|
|
2379
2569
|
conflicts: [],
|
|
2380
2570
|
wouldApply: allPatches2,
|
|
2381
|
-
warnings:
|
|
2571
|
+
warnings: warnings.length > 0 ? warnings : void 0
|
|
2572
|
+
};
|
|
2573
|
+
const headSha = await this.git.exec(["rev-parse", "HEAD"]).then((s) => s.trim()).catch(() => "");
|
|
2574
|
+
return {
|
|
2575
|
+
flow: "normal-regeneration",
|
|
2576
|
+
previousGenerationSha,
|
|
2577
|
+
currentGenerationSha: headSha,
|
|
2578
|
+
baseBranchHead: options.baseBranchHead ?? null,
|
|
2579
|
+
_prepared: {
|
|
2580
|
+
flow: "normal-regeneration",
|
|
2581
|
+
terminal: true,
|
|
2582
|
+
preparedReport,
|
|
2583
|
+
patchesToApply: [],
|
|
2584
|
+
newPatchIds: /* @__PURE__ */ new Set(),
|
|
2585
|
+
detectorWarnings: [...this.detector.warnings],
|
|
2586
|
+
revertedCount: dryRunReverted.length,
|
|
2587
|
+
genSha: headSha,
|
|
2588
|
+
optionsSnapshot: options
|
|
2589
|
+
}
|
|
2382
2590
|
};
|
|
2383
2591
|
}
|
|
2384
2592
|
let existingPatches = this.lockManager.getPatches();
|
|
@@ -2430,6 +2638,29 @@ var ReplayService = class {
|
|
|
2430
2638
|
await this.cleanupStaleConflictMarkers();
|
|
2431
2639
|
const genRecord = await this.committer.createGenerationRecord(commitOpts);
|
|
2432
2640
|
this.lockManager.addGeneration(genRecord);
|
|
2641
|
+
return {
|
|
2642
|
+
flow: "normal-regeneration",
|
|
2643
|
+
previousGenerationSha,
|
|
2644
|
+
currentGenerationSha: genRecord.commit_sha,
|
|
2645
|
+
baseBranchHead: options?.baseBranchHead ?? null,
|
|
2646
|
+
_prepared: {
|
|
2647
|
+
flow: "normal-regeneration",
|
|
2648
|
+
terminal: false,
|
|
2649
|
+
patchesToApply: allPatches,
|
|
2650
|
+
newPatchIds: new Set(newPatches.map((p) => p.id)),
|
|
2651
|
+
preRebaseCounts,
|
|
2652
|
+
detectorWarnings,
|
|
2653
|
+
revertedCount: revertedPatchIds.length,
|
|
2654
|
+
genSha: genRecord.commit_sha,
|
|
2655
|
+
optionsSnapshot: options
|
|
2656
|
+
}
|
|
2657
|
+
};
|
|
2658
|
+
}
|
|
2659
|
+
async _applyNormalRegeneration(prep, options) {
|
|
2660
|
+
const allPatches = prep._prepared.patchesToApply;
|
|
2661
|
+
const newPatchIds = prep._prepared.newPatchIds;
|
|
2662
|
+
const detectorWarnings = prep._prepared.detectorWarnings;
|
|
2663
|
+
const genSha = prep._prepared.genSha;
|
|
2433
2664
|
const results = await this.applicator.applyPatches(allPatches);
|
|
2434
2665
|
this._lastApplyResults = results;
|
|
2435
2666
|
this.revertConflictingFiles(results);
|
|
@@ -2438,7 +2669,8 @@ var ReplayService = class {
|
|
|
2438
2669
|
result.patch.status = "unresolved";
|
|
2439
2670
|
}
|
|
2440
2671
|
}
|
|
2441
|
-
const rebaseCounts = await this.rebasePatches(results,
|
|
2672
|
+
const rebaseCounts = await this.rebasePatches(results, genSha);
|
|
2673
|
+
const newPatches = allPatches.filter((p) => newPatchIds.has(p.id));
|
|
2442
2674
|
for (const patch of newPatches) {
|
|
2443
2675
|
if (!rebaseCounts.absorbedPatchIds.has(patch.id)) {
|
|
2444
2676
|
this.lockManager.addPatch(patch);
|
|
@@ -2465,11 +2697,11 @@ var ReplayService = class {
|
|
|
2465
2697
|
"normal-regeneration",
|
|
2466
2698
|
allPatches,
|
|
2467
2699
|
results,
|
|
2468
|
-
|
|
2700
|
+
prep._prepared.optionsSnapshot,
|
|
2469
2701
|
warnings,
|
|
2470
2702
|
rebaseCounts,
|
|
2471
|
-
preRebaseCounts,
|
|
2472
|
-
|
|
2703
|
+
prep._prepared.preRebaseCounts,
|
|
2704
|
+
prep._prepared.revertedCount
|
|
2473
2705
|
);
|
|
2474
2706
|
}
|
|
2475
2707
|
/**
|