@fern-api/generator-cli 0.6.2 → 0.6.4
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/api.js +7407 -22334
- package/dist/cli.js +1091 -1217
- package/package.json +9 -33
- package/lib/api.js +0 -9
package/dist/cli.js
CHANGED
|
@@ -4867,18 +4867,18 @@ var require_build3 = __commonJS({
|
|
|
4867
4867
|
var require_sync = __commonJS({
|
|
4868
4868
|
"../../node_modules/.pnpm/escalade@3.2.0/node_modules/escalade/sync/index.js"(exports2, module2) {
|
|
4869
4869
|
"use strict";
|
|
4870
|
-
var { dirname:
|
|
4870
|
+
var { dirname: dirname4, resolve: resolve8 } = require("path");
|
|
4871
4871
|
var { readdirSync: readdirSync2, statSync: statSync4 } = require("fs");
|
|
4872
4872
|
module2.exports = function(start, callback) {
|
|
4873
4873
|
let dir = resolve8(".", start);
|
|
4874
4874
|
let tmp3, stats = statSync4(dir);
|
|
4875
4875
|
if (!stats.isDirectory()) {
|
|
4876
|
-
dir =
|
|
4876
|
+
dir = dirname4(dir);
|
|
4877
4877
|
}
|
|
4878
4878
|
while (true) {
|
|
4879
4879
|
tmp3 = callback(dir, readdirSync2(dir));
|
|
4880
4880
|
if (tmp3) return resolve8(dir, tmp3);
|
|
4881
|
-
dir =
|
|
4881
|
+
dir = dirname4(tmp3 = dir);
|
|
4882
4882
|
if (tmp3 === dir) break;
|
|
4883
4883
|
}
|
|
4884
4884
|
};
|
|
@@ -4914,9 +4914,9 @@ var require_require_directory = __commonJS({
|
|
|
4914
4914
|
"../../node_modules/.pnpm/require-directory@2.1.1/node_modules/require-directory/index.js"(exports2, module2) {
|
|
4915
4915
|
"use strict";
|
|
4916
4916
|
var fs3 = require("fs");
|
|
4917
|
-
var
|
|
4917
|
+
var join9 = require("path").join;
|
|
4918
4918
|
var resolve8 = require("path").resolve;
|
|
4919
|
-
var
|
|
4919
|
+
var dirname4 = require("path").dirname;
|
|
4920
4920
|
var defaultOptions2 = {
|
|
4921
4921
|
extensions: ["js", "json", "coffee"],
|
|
4922
4922
|
recurse: true,
|
|
@@ -4949,9 +4949,9 @@ var require_require_directory = __commonJS({
|
|
|
4949
4949
|
options[prop] = defaultOptions2[prop];
|
|
4950
4950
|
}
|
|
4951
4951
|
}
|
|
4952
|
-
path5 = !path5 ?
|
|
4952
|
+
path5 = !path5 ? dirname4(m.filename) : resolve8(dirname4(m.filename), path5);
|
|
4953
4953
|
fs3.readdirSync(path5).forEach(function(filename) {
|
|
4954
|
-
var joined =
|
|
4954
|
+
var joined = join9(path5, filename), files, key, obj;
|
|
4955
4955
|
if (fs3.statSync(joined).isDirectory() && options.recurse) {
|
|
4956
4956
|
files = requireDirectory(m, joined, options);
|
|
4957
4957
|
if (Object.keys(files).length) {
|
|
@@ -6604,7 +6604,7 @@ var require_ms = __commonJS({
|
|
|
6604
6604
|
options = options || {};
|
|
6605
6605
|
var type = typeof val;
|
|
6606
6606
|
if (type === "string" && val.length > 0) {
|
|
6607
|
-
return
|
|
6607
|
+
return parse3(val);
|
|
6608
6608
|
} else if (type === "number" && isFinite(val)) {
|
|
6609
6609
|
return options.long ? fmtLong(val) : fmtShort(val);
|
|
6610
6610
|
}
|
|
@@ -6612,7 +6612,7 @@ var require_ms = __commonJS({
|
|
|
6612
6612
|
"val is not a non-empty string or a valid number. val=" + JSON.stringify(val)
|
|
6613
6613
|
);
|
|
6614
6614
|
};
|
|
6615
|
-
function
|
|
6615
|
+
function parse3(str) {
|
|
6616
6616
|
str = String(str);
|
|
6617
6617
|
if (str.length > 100) {
|
|
6618
6618
|
return;
|
|
@@ -7387,11 +7387,11 @@ var require_src2 = __commonJS({
|
|
|
7387
7387
|
var require_dist = __commonJS({
|
|
7388
7388
|
"../../node_modules/.pnpm/@kwsites+file-exists@1.1.1/node_modules/@kwsites/file-exists/dist/index.js"(exports2) {
|
|
7389
7389
|
"use strict";
|
|
7390
|
-
function
|
|
7390
|
+
function __export4(m) {
|
|
7391
7391
|
for (var p in m) if (!exports2.hasOwnProperty(p)) exports2[p] = m[p];
|
|
7392
7392
|
}
|
|
7393
7393
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
7394
|
-
|
|
7394
|
+
__export4(require_src2());
|
|
7395
7395
|
}
|
|
7396
7396
|
});
|
|
7397
7397
|
|
|
@@ -7654,7 +7654,7 @@ function parseStringResponse(result, parsers12, texts, trim = true) {
|
|
|
7654
7654
|
}
|
|
7655
7655
|
return lines[i + offset];
|
|
7656
7656
|
};
|
|
7657
|
-
parsers12.some(({ parse:
|
|
7657
|
+
parsers12.some(({ parse: parse3 }) => parse3(line, result));
|
|
7658
7658
|
}
|
|
7659
7659
|
});
|
|
7660
7660
|
return result;
|
|
@@ -11898,7 +11898,7 @@ var require_fast_content_type_parse = __commonJS({
|
|
|
11898
11898
|
var defaultContentType = { type: "", parameters: new NullObject() };
|
|
11899
11899
|
Object.freeze(defaultContentType.parameters);
|
|
11900
11900
|
Object.freeze(defaultContentType);
|
|
11901
|
-
function
|
|
11901
|
+
function parse3(header) {
|
|
11902
11902
|
if (typeof header !== "string") {
|
|
11903
11903
|
throw new TypeError("argument header is required and must be a string");
|
|
11904
11904
|
}
|
|
@@ -11974,148 +11974,13 @@ var require_fast_content_type_parse = __commonJS({
|
|
|
11974
11974
|
}
|
|
11975
11975
|
return result;
|
|
11976
11976
|
}
|
|
11977
|
-
module2.exports.default = { parse:
|
|
11978
|
-
module2.exports.parse =
|
|
11977
|
+
module2.exports.default = { parse: parse3, safeParse: safeParse2 };
|
|
11978
|
+
module2.exports.parse = parse3;
|
|
11979
11979
|
module2.exports.safeParse = safeParse2;
|
|
11980
11980
|
module2.exports.defaultContentType = defaultContentType;
|
|
11981
11981
|
}
|
|
11982
11982
|
});
|
|
11983
11983
|
|
|
11984
|
-
// ../../node_modules/.pnpm/@fern-api+replay@0.6.0/node_modules/@fern-api/replay/dist/git/GitClient.js
|
|
11985
|
-
var GitClient_exports = {};
|
|
11986
|
-
__export(GitClient_exports, {
|
|
11987
|
-
GitClient: () => GitClient
|
|
11988
|
-
});
|
|
11989
|
-
var GitClient;
|
|
11990
|
-
var init_GitClient = __esm({
|
|
11991
|
-
"../../node_modules/.pnpm/@fern-api+replay@0.6.0/node_modules/@fern-api/replay/dist/git/GitClient.js"() {
|
|
11992
|
-
"use strict";
|
|
11993
|
-
init_esm4();
|
|
11994
|
-
GitClient = class {
|
|
11995
|
-
git;
|
|
11996
|
-
repoPath;
|
|
11997
|
-
constructor(repoPath) {
|
|
11998
|
-
this.repoPath = repoPath;
|
|
11999
|
-
this.git = simpleGit(repoPath);
|
|
12000
|
-
}
|
|
12001
|
-
async exec(args) {
|
|
12002
|
-
return this.git.raw(args);
|
|
12003
|
-
}
|
|
12004
|
-
async execWithInput(args, input) {
|
|
12005
|
-
const { spawn: spawn2 } = await import("child_process");
|
|
12006
|
-
return new Promise((resolve8, reject) => {
|
|
12007
|
-
const proc = spawn2("git", args, { cwd: this.repoPath });
|
|
12008
|
-
let stdout = "";
|
|
12009
|
-
let stderr = "";
|
|
12010
|
-
proc.stdout.on("data", (data) => {
|
|
12011
|
-
stdout += data.toString();
|
|
12012
|
-
});
|
|
12013
|
-
proc.stderr.on("data", (data) => {
|
|
12014
|
-
stderr += data.toString();
|
|
12015
|
-
});
|
|
12016
|
-
proc.on("close", (code) => {
|
|
12017
|
-
if (code === 0) {
|
|
12018
|
-
resolve8(stdout);
|
|
12019
|
-
} else {
|
|
12020
|
-
reject(new Error(`git ${args.join(" ")} failed (code ${code}): ${stderr}`));
|
|
12021
|
-
}
|
|
12022
|
-
});
|
|
12023
|
-
proc.stdin.write(input);
|
|
12024
|
-
proc.stdin.end();
|
|
12025
|
-
});
|
|
12026
|
-
}
|
|
12027
|
-
async formatPatch(commitSha) {
|
|
12028
|
-
return this.exec(["format-patch", "-1", commitSha, "--stdout"]);
|
|
12029
|
-
}
|
|
12030
|
-
async applyPatch(patchContent) {
|
|
12031
|
-
await this.execWithInput(["am", "--3way"], patchContent);
|
|
12032
|
-
}
|
|
12033
|
-
async getTreeHash(commitSha) {
|
|
12034
|
-
return (await this.exec(["rev-parse", `${commitSha}^{tree}`])).trim();
|
|
12035
|
-
}
|
|
12036
|
-
async showFile(treeish, filePath) {
|
|
12037
|
-
try {
|
|
12038
|
-
return await this.exec(["show", `${treeish}:${filePath}`]);
|
|
12039
|
-
} catch {
|
|
12040
|
-
return null;
|
|
12041
|
-
}
|
|
12042
|
-
}
|
|
12043
|
-
async getCommitInfo(commitSha) {
|
|
12044
|
-
const format3 = "%H%x00%an%x00%ae%x00%s";
|
|
12045
|
-
const output = await this.exec(["log", "-1", `--format=${format3}`, commitSha]);
|
|
12046
|
-
const [sha, authorName, authorEmail, message] = output.trim().split("\0");
|
|
12047
|
-
return { sha, authorName, authorEmail, message };
|
|
12048
|
-
}
|
|
12049
|
-
async getCommitParents(commitSha) {
|
|
12050
|
-
const output = await this.exec(["rev-parse", `${commitSha}^@`]);
|
|
12051
|
-
return output.trim().split("\n").filter(Boolean);
|
|
12052
|
-
}
|
|
12053
|
-
async detectRenames(fromTree, toTree) {
|
|
12054
|
-
try {
|
|
12055
|
-
const output = await this.exec(["diff", "--find-renames", "--name-status", fromTree, toTree]);
|
|
12056
|
-
const renames = [];
|
|
12057
|
-
for (const line of output.trim().split("\n")) {
|
|
12058
|
-
if (!line)
|
|
12059
|
-
continue;
|
|
12060
|
-
if (line.startsWith("R")) {
|
|
12061
|
-
const parts = line.split(" ");
|
|
12062
|
-
if (parts.length >= 3) {
|
|
12063
|
-
renames.push({ from: parts[1], to: parts[2] });
|
|
12064
|
-
}
|
|
12065
|
-
}
|
|
12066
|
-
}
|
|
12067
|
-
return renames;
|
|
12068
|
-
} catch {
|
|
12069
|
-
return [];
|
|
12070
|
-
}
|
|
12071
|
-
}
|
|
12072
|
-
async isAncestor(commit, descendant) {
|
|
12073
|
-
try {
|
|
12074
|
-
const mergeBase = (await this.exec(["merge-base", commit, descendant])).trim();
|
|
12075
|
-
return mergeBase === commit;
|
|
12076
|
-
} catch {
|
|
12077
|
-
return false;
|
|
12078
|
-
}
|
|
12079
|
-
}
|
|
12080
|
-
async commitExists(sha) {
|
|
12081
|
-
try {
|
|
12082
|
-
const type = await this.exec(["cat-file", "-t", sha]);
|
|
12083
|
-
return type.trim() === "commit";
|
|
12084
|
-
} catch {
|
|
12085
|
-
return false;
|
|
12086
|
-
}
|
|
12087
|
-
}
|
|
12088
|
-
getRepoPath() {
|
|
12089
|
-
return this.repoPath;
|
|
12090
|
-
}
|
|
12091
|
-
};
|
|
12092
|
-
}
|
|
12093
|
-
});
|
|
12094
|
-
|
|
12095
|
-
// ../../node_modules/.pnpm/@fern-api+replay@0.6.0/node_modules/@fern-api/replay/dist/git/CommitDetection.js
|
|
12096
|
-
function isGenerationCommit(commit) {
|
|
12097
|
-
const isFernSupport = FERN_SUPPORT_NAMES.includes(commit.authorName);
|
|
12098
|
-
const isBotAuthor = !isFernSupport && (commit.authorLogin === FERN_BOT_LOGIN2 || commit.authorEmail === FERN_BOT_EMAIL2 || commit.authorName === FERN_BOT_NAME2);
|
|
12099
|
-
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.
|
|
12100
|
-
// The default PR title is "SDK Generation" (from GithubStep's commitMessage default).
|
|
12101
|
-
// GitHub appends "(#N)" for the PR number, e.g. "SDK Generation (#70)".
|
|
12102
|
-
commit.message.startsWith("SDK Generation");
|
|
12103
|
-
return isBotAuthor || hasGenerationMarker;
|
|
12104
|
-
}
|
|
12105
|
-
function isReplayCommit(commit) {
|
|
12106
|
-
return commit.message.startsWith("[fern-replay]");
|
|
12107
|
-
}
|
|
12108
|
-
var FERN_BOT_NAME2, FERN_BOT_EMAIL2, FERN_BOT_LOGIN2, FERN_SUPPORT_NAMES;
|
|
12109
|
-
var init_CommitDetection = __esm({
|
|
12110
|
-
"../../node_modules/.pnpm/@fern-api+replay@0.6.0/node_modules/@fern-api/replay/dist/git/CommitDetection.js"() {
|
|
12111
|
-
"use strict";
|
|
12112
|
-
FERN_BOT_NAME2 = "fern-api";
|
|
12113
|
-
FERN_BOT_EMAIL2 = "115122769+fern-api[bot]@users.noreply.github.com";
|
|
12114
|
-
FERN_BOT_LOGIN2 = "fern-api[bot]";
|
|
12115
|
-
FERN_SUPPORT_NAMES = ["fern-support", "Fern Support"];
|
|
12116
|
-
}
|
|
12117
|
-
});
|
|
12118
|
-
|
|
12119
11984
|
// ../../node_modules/.pnpm/yaml@2.3.3/node_modules/yaml/dist/nodes/identity.js
|
|
12120
11985
|
var require_identity = __commonJS({
|
|
12121
11986
|
"../../node_modules/.pnpm/yaml@2.3.3/node_modules/yaml/dist/nodes/identity.js"(exports2) {
|
|
@@ -19145,7 +19010,7 @@ var require_public_api = __commonJS({
|
|
|
19145
19010
|
}
|
|
19146
19011
|
return doc;
|
|
19147
19012
|
}
|
|
19148
|
-
function
|
|
19013
|
+
function parse3(src, reviver, options) {
|
|
19149
19014
|
let _reviver = void 0;
|
|
19150
19015
|
if (typeof reviver === "function") {
|
|
19151
19016
|
_reviver = reviver;
|
|
@@ -19184,7 +19049,7 @@ var require_public_api = __commonJS({
|
|
|
19184
19049
|
}
|
|
19185
19050
|
return new Document.Document(value, _replacer, options).toString(options);
|
|
19186
19051
|
}
|
|
19187
|
-
exports2.parse =
|
|
19052
|
+
exports2.parse = parse3;
|
|
19188
19053
|
exports2.parseAllDocuments = parseAllDocuments;
|
|
19189
19054
|
exports2.parseDocument = parseDocument;
|
|
19190
19055
|
exports2.stringify = stringify3;
|
|
@@ -19243,485 +19108,259 @@ var require_dist3 = __commonJS({
|
|
|
19243
19108
|
}
|
|
19244
19109
|
});
|
|
19245
19110
|
|
|
19246
|
-
// ../../node_modules/.pnpm
|
|
19247
|
-
|
|
19248
|
-
|
|
19249
|
-
|
|
19250
|
-
|
|
19251
|
-
|
|
19252
|
-
|
|
19253
|
-
|
|
19254
|
-
|
|
19255
|
-
|
|
19256
|
-
|
|
19257
|
-
|
|
19258
|
-
|
|
19259
|
-
|
|
19260
|
-
|
|
19261
|
-
|
|
19262
|
-
|
|
19263
|
-
|
|
19264
|
-
|
|
19265
|
-
|
|
19266
|
-
|
|
19267
|
-
|
|
19268
|
-
|
|
19269
|
-
|
|
19270
|
-
read() {
|
|
19271
|
-
if (this.lock) {
|
|
19272
|
-
return this.lock;
|
|
19273
|
-
}
|
|
19274
|
-
if (!this.exists()) {
|
|
19275
|
-
throw new Error(`Lockfile not found: ${this.lockfilePath}`);
|
|
19111
|
+
// ../../node_modules/.pnpm/node-diff3@3.2.0/node_modules/node-diff3/dist/diff3.mjs
|
|
19112
|
+
function LCS(buffer1, buffer2) {
|
|
19113
|
+
let equivalenceClasses = {};
|
|
19114
|
+
for (let j = 0; j < buffer2.length; j++) {
|
|
19115
|
+
const item = buffer2[j];
|
|
19116
|
+
if (equivalenceClasses[item]) {
|
|
19117
|
+
equivalenceClasses[item].push(j);
|
|
19118
|
+
} else {
|
|
19119
|
+
equivalenceClasses[item] = [j];
|
|
19120
|
+
}
|
|
19121
|
+
}
|
|
19122
|
+
const NULLRESULT = { buffer1index: -1, buffer2index: -1, chain: null };
|
|
19123
|
+
let candidates = [NULLRESULT];
|
|
19124
|
+
for (let i = 0; i < buffer1.length; i++) {
|
|
19125
|
+
const item = buffer1[i];
|
|
19126
|
+
const buffer2indices = equivalenceClasses[item] || [];
|
|
19127
|
+
let r = 0;
|
|
19128
|
+
let c = candidates[0];
|
|
19129
|
+
for (let jx = 0; jx < buffer2indices.length; jx++) {
|
|
19130
|
+
const j = buffer2indices[jx];
|
|
19131
|
+
let s;
|
|
19132
|
+
for (s = r; s < candidates.length; s++) {
|
|
19133
|
+
if (candidates[s].buffer2index < j && (s === candidates.length - 1 || candidates[s + 1].buffer2index > j)) {
|
|
19134
|
+
break;
|
|
19276
19135
|
}
|
|
19277
|
-
const content = (0, import_node_fs.readFileSync)(this.lockfilePath, "utf-8");
|
|
19278
|
-
this.lock = (0, import_yaml.parse)(content);
|
|
19279
|
-
return this.lock;
|
|
19280
|
-
}
|
|
19281
|
-
initialize(firstGeneration) {
|
|
19282
|
-
this.initializeInMemory(firstGeneration);
|
|
19283
|
-
this.save();
|
|
19284
|
-
}
|
|
19285
|
-
/**
|
|
19286
|
-
* Set up in-memory lock state without writing to disk.
|
|
19287
|
-
* Useful for bootstrap dry-run where we need state for detection
|
|
19288
|
-
* but don't want to persist anything.
|
|
19289
|
-
*/
|
|
19290
|
-
initializeInMemory(firstGeneration) {
|
|
19291
|
-
this.lock = {
|
|
19292
|
-
version: "1.0",
|
|
19293
|
-
generations: [firstGeneration],
|
|
19294
|
-
current_generation: firstGeneration.commit_sha,
|
|
19295
|
-
patches: []
|
|
19296
|
-
};
|
|
19297
19136
|
}
|
|
19298
|
-
|
|
19299
|
-
|
|
19300
|
-
|
|
19137
|
+
if (s < candidates.length) {
|
|
19138
|
+
const newCandidate = { buffer1index: i, buffer2index: j, chain: candidates[s] };
|
|
19139
|
+
if (r === candidates.length) {
|
|
19140
|
+
candidates.push(c);
|
|
19141
|
+
} else {
|
|
19142
|
+
candidates[r] = c;
|
|
19301
19143
|
}
|
|
19302
|
-
|
|
19303
|
-
|
|
19304
|
-
|
|
19144
|
+
r = s + 1;
|
|
19145
|
+
c = newCandidate;
|
|
19146
|
+
if (r === candidates.length) {
|
|
19147
|
+
break;
|
|
19305
19148
|
}
|
|
19306
|
-
const yaml = (0, import_yaml.stringify)(this.lock, {
|
|
19307
|
-
lineWidth: 0,
|
|
19308
|
-
blockQuote: "literal"
|
|
19309
|
-
});
|
|
19310
|
-
const content = LOCKFILE_HEADER + yaml;
|
|
19311
|
-
const tmpPath = this.lockfilePath + ".tmp";
|
|
19312
|
-
(0, import_node_fs.writeFileSync)(tmpPath, content, "utf-8");
|
|
19313
|
-
(0, import_node_fs.renameSync)(tmpPath, this.lockfilePath);
|
|
19314
19149
|
}
|
|
19315
|
-
|
|
19316
|
-
|
|
19317
|
-
|
|
19318
|
-
|
|
19150
|
+
}
|
|
19151
|
+
candidates[r] = c;
|
|
19152
|
+
}
|
|
19153
|
+
return candidates[candidates.length - 1];
|
|
19154
|
+
}
|
|
19155
|
+
function diffIndices(buffer1, buffer2) {
|
|
19156
|
+
const lcs = LCS(buffer1, buffer2);
|
|
19157
|
+
let result = [];
|
|
19158
|
+
let tail1 = buffer1.length;
|
|
19159
|
+
let tail2 = buffer2.length;
|
|
19160
|
+
for (let candidate = lcs; candidate !== null; candidate = candidate.chain) {
|
|
19161
|
+
const mismatchLength1 = tail1 - candidate.buffer1index - 1;
|
|
19162
|
+
const mismatchLength2 = tail2 - candidate.buffer2index - 1;
|
|
19163
|
+
tail1 = candidate.buffer1index;
|
|
19164
|
+
tail2 = candidate.buffer2index;
|
|
19165
|
+
if (mismatchLength1 || mismatchLength2) {
|
|
19166
|
+
result.push({
|
|
19167
|
+
buffer1: [tail1 + 1, mismatchLength1],
|
|
19168
|
+
buffer1Content: buffer1.slice(tail1 + 1, tail1 + 1 + mismatchLength1),
|
|
19169
|
+
buffer2: [tail2 + 1, mismatchLength2],
|
|
19170
|
+
buffer2Content: buffer2.slice(tail2 + 1, tail2 + 1 + mismatchLength2)
|
|
19171
|
+
});
|
|
19172
|
+
}
|
|
19173
|
+
}
|
|
19174
|
+
result.reverse();
|
|
19175
|
+
return result;
|
|
19176
|
+
}
|
|
19177
|
+
function diff3MergeRegions(a, o, b) {
|
|
19178
|
+
let hunks = [];
|
|
19179
|
+
function addHunk(h, ab) {
|
|
19180
|
+
hunks.push({
|
|
19181
|
+
ab,
|
|
19182
|
+
oStart: h.buffer1[0],
|
|
19183
|
+
oLength: h.buffer1[1],
|
|
19184
|
+
abStart: h.buffer2[0],
|
|
19185
|
+
abLength: h.buffer2[1]
|
|
19186
|
+
});
|
|
19187
|
+
}
|
|
19188
|
+
diffIndices(o, a).forEach((item) => addHunk(item, "a"));
|
|
19189
|
+
diffIndices(o, b).forEach((item) => addHunk(item, "b"));
|
|
19190
|
+
hunks.sort((x, y) => x.oStart - y.oStart);
|
|
19191
|
+
let results = [];
|
|
19192
|
+
let currOffset = 0;
|
|
19193
|
+
function advanceTo(endOffset) {
|
|
19194
|
+
if (endOffset > currOffset) {
|
|
19195
|
+
results.push({
|
|
19196
|
+
stable: true,
|
|
19197
|
+
buffer: "o",
|
|
19198
|
+
bufferStart: currOffset,
|
|
19199
|
+
bufferLength: endOffset - currOffset,
|
|
19200
|
+
bufferContent: o.slice(currOffset, endOffset)
|
|
19201
|
+
});
|
|
19202
|
+
currOffset = endOffset;
|
|
19203
|
+
}
|
|
19204
|
+
}
|
|
19205
|
+
while (hunks.length) {
|
|
19206
|
+
let hunk = hunks.shift();
|
|
19207
|
+
let regionStart = hunk.oStart;
|
|
19208
|
+
let regionEnd = hunk.oStart + hunk.oLength;
|
|
19209
|
+
let regionHunks = [hunk];
|
|
19210
|
+
advanceTo(regionStart);
|
|
19211
|
+
while (hunks.length) {
|
|
19212
|
+
const nextHunk = hunks[0];
|
|
19213
|
+
const nextHunkStart = nextHunk.oStart;
|
|
19214
|
+
if (nextHunkStart > regionEnd)
|
|
19215
|
+
break;
|
|
19216
|
+
regionEnd = Math.max(regionEnd, nextHunkStart + nextHunk.oLength);
|
|
19217
|
+
regionHunks.push(hunks.shift());
|
|
19218
|
+
}
|
|
19219
|
+
if (regionHunks.length === 1) {
|
|
19220
|
+
if (hunk.abLength > 0) {
|
|
19221
|
+
const buffer = hunk.ab === "a" ? a : b;
|
|
19222
|
+
results.push({
|
|
19223
|
+
stable: true,
|
|
19224
|
+
buffer: hunk.ab,
|
|
19225
|
+
bufferStart: hunk.abStart,
|
|
19226
|
+
bufferLength: hunk.abLength,
|
|
19227
|
+
bufferContent: buffer.slice(hunk.abStart, hunk.abStart + hunk.abLength)
|
|
19228
|
+
});
|
|
19319
19229
|
}
|
|
19320
|
-
|
|
19321
|
-
|
|
19322
|
-
|
|
19230
|
+
} else {
|
|
19231
|
+
let bounds = {
|
|
19232
|
+
a: [a.length, -1, o.length, -1],
|
|
19233
|
+
b: [b.length, -1, o.length, -1]
|
|
19234
|
+
};
|
|
19235
|
+
while (regionHunks.length) {
|
|
19236
|
+
hunk = regionHunks.shift();
|
|
19237
|
+
const oStart = hunk.oStart;
|
|
19238
|
+
const oEnd = oStart + hunk.oLength;
|
|
19239
|
+
const abStart = hunk.abStart;
|
|
19240
|
+
const abEnd = abStart + hunk.abLength;
|
|
19241
|
+
let b2 = bounds[hunk.ab];
|
|
19242
|
+
b2[0] = Math.min(abStart, b2[0]);
|
|
19243
|
+
b2[1] = Math.max(abEnd, b2[1]);
|
|
19244
|
+
b2[2] = Math.min(oStart, b2[2]);
|
|
19245
|
+
b2[3] = Math.max(oEnd, b2[3]);
|
|
19323
19246
|
}
|
|
19324
|
-
|
|
19325
|
-
|
|
19326
|
-
|
|
19327
|
-
|
|
19328
|
-
|
|
19329
|
-
|
|
19330
|
-
|
|
19331
|
-
|
|
19332
|
-
|
|
19333
|
-
|
|
19334
|
-
|
|
19335
|
-
|
|
19336
|
-
|
|
19337
|
-
|
|
19338
|
-
|
|
19339
|
-
}
|
|
19340
|
-
|
|
19341
|
-
|
|
19342
|
-
|
|
19343
|
-
}
|
|
19344
|
-
setReplaySkippedAt(timestamp) {
|
|
19345
|
-
this.ensureLoaded();
|
|
19346
|
-
this.lock.replay_skipped_at = timestamp;
|
|
19347
|
-
}
|
|
19348
|
-
clearReplaySkippedAt() {
|
|
19349
|
-
this.ensureLoaded();
|
|
19350
|
-
delete this.lock.replay_skipped_at;
|
|
19351
|
-
}
|
|
19352
|
-
isReplaySkipped() {
|
|
19353
|
-
this.ensureLoaded();
|
|
19354
|
-
return this.lock.replay_skipped_at != null;
|
|
19355
|
-
}
|
|
19356
|
-
getGeneration(commitSha) {
|
|
19357
|
-
this.ensureLoaded();
|
|
19358
|
-
return this.lock.generations.find((g) => g.commit_sha === commitSha);
|
|
19359
|
-
}
|
|
19360
|
-
getCustomizationsConfig() {
|
|
19361
|
-
if (!(0, import_node_fs.existsSync)(this.customizationsPath)) {
|
|
19362
|
-
return {};
|
|
19363
|
-
}
|
|
19364
|
-
const content = (0, import_node_fs.readFileSync)(this.customizationsPath, "utf-8");
|
|
19365
|
-
return (0, import_yaml.parse)(content) ?? {};
|
|
19366
|
-
}
|
|
19367
|
-
ensureLoaded() {
|
|
19368
|
-
if (!this.lock) {
|
|
19369
|
-
throw new Error("No lockfile loaded. Call read() or initialize() first.");
|
|
19370
|
-
}
|
|
19371
|
-
}
|
|
19372
|
-
};
|
|
19247
|
+
const aStart = bounds.a[0] + (regionStart - bounds.a[2]);
|
|
19248
|
+
const aEnd = bounds.a[1] + (regionEnd - bounds.a[3]);
|
|
19249
|
+
const bStart = bounds.b[0] + (regionStart - bounds.b[2]);
|
|
19250
|
+
const bEnd = bounds.b[1] + (regionEnd - bounds.b[3]);
|
|
19251
|
+
let result = {
|
|
19252
|
+
stable: false,
|
|
19253
|
+
aStart,
|
|
19254
|
+
aLength: aEnd - aStart,
|
|
19255
|
+
aContent: a.slice(aStart, aEnd),
|
|
19256
|
+
oStart: regionStart,
|
|
19257
|
+
oLength: regionEnd - regionStart,
|
|
19258
|
+
oContent: o.slice(regionStart, regionEnd),
|
|
19259
|
+
bStart,
|
|
19260
|
+
bLength: bEnd - bStart,
|
|
19261
|
+
bContent: b.slice(bStart, bEnd)
|
|
19262
|
+
};
|
|
19263
|
+
results.push(result);
|
|
19264
|
+
}
|
|
19265
|
+
currOffset = regionEnd;
|
|
19373
19266
|
}
|
|
19374
|
-
|
|
19375
|
-
|
|
19376
|
-
|
|
19377
|
-
|
|
19378
|
-
|
|
19379
|
-
|
|
19380
|
-
|
|
19381
|
-
|
|
19382
|
-
|
|
19383
|
-
|
|
19384
|
-
|
|
19385
|
-
|
|
19386
|
-
|
|
19387
|
-
|
|
19388
|
-
|
|
19389
|
-
|
|
19390
|
-
|
|
19391
|
-
|
|
19392
|
-
|
|
19393
|
-
|
|
19394
|
-
|
|
19395
|
-
|
|
19396
|
-
|
|
19397
|
-
|
|
19398
|
-
|
|
19399
|
-
|
|
19400
|
-
|
|
19401
|
-
|
|
19402
|
-
|
|
19403
|
-
|
|
19404
|
-
|
|
19405
|
-
|
|
19406
|
-
|
|
19407
|
-
|
|
19408
|
-
|
|
19409
|
-
|
|
19410
|
-
|
|
19411
|
-
|
|
19412
|
-
|
|
19413
|
-
|
|
19414
|
-
|
|
19415
|
-
|
|
19416
|
-
|
|
19417
|
-
|
|
19418
|
-
|
|
19419
|
-
|
|
19420
|
-
|
|
19421
|
-
|
|
19422
|
-
|
|
19423
|
-
continue;
|
|
19424
|
-
}
|
|
19425
|
-
const parents = await this.git.getCommitParents(commit.sha);
|
|
19426
|
-
if (parents.length > 1) {
|
|
19427
|
-
continue;
|
|
19428
|
-
}
|
|
19429
|
-
if (lock.patches.find((p) => p.original_commit === commit.sha)) {
|
|
19430
|
-
continue;
|
|
19431
|
-
}
|
|
19432
|
-
const patchContent = await this.git.formatPatch(commit.sha);
|
|
19433
|
-
const contentHash = this.computeContentHash(patchContent);
|
|
19434
|
-
if (lock.patches.find((p) => p.content_hash === contentHash)) {
|
|
19435
|
-
continue;
|
|
19436
|
-
}
|
|
19437
|
-
const filesOutput = await this.git.exec(["diff-tree", "--no-commit-id", "--name-only", "-r", commit.sha]);
|
|
19438
|
-
const files = filesOutput.trim().split("\n").filter(Boolean).filter((f) => !INFRASTRUCTURE_FILES.has(f));
|
|
19439
|
-
if (files.length === 0) {
|
|
19440
|
-
continue;
|
|
19441
|
-
}
|
|
19442
|
-
newPatches.push({
|
|
19443
|
-
id: `patch-${commit.sha.slice(0, 8)}`,
|
|
19444
|
-
content_hash: contentHash,
|
|
19445
|
-
original_commit: commit.sha,
|
|
19446
|
-
original_message: commit.message,
|
|
19447
|
-
original_author: `${commit.authorName} <${commit.authorEmail}>`,
|
|
19448
|
-
base_generation: lastGen.commit_sha,
|
|
19449
|
-
files,
|
|
19450
|
-
patch_content: patchContent
|
|
19451
|
-
});
|
|
19452
|
-
}
|
|
19453
|
-
return newPatches.reverse();
|
|
19454
|
-
}
|
|
19455
|
-
/**
|
|
19456
|
-
* Compute content hash for deduplication.
|
|
19457
|
-
* Removes commit SHA line and index lines before hashing,
|
|
19458
|
-
* so rebased commits with same content produce the same hash.
|
|
19459
|
-
*/
|
|
19460
|
-
computeContentHash(patchContent) {
|
|
19461
|
-
const normalized = patchContent.split("\n").filter((line) => !line.startsWith("From ") && !line.startsWith("index ") && !line.startsWith("Date: ")).join("\n");
|
|
19462
|
-
return `sha256:${(0, import_node_crypto.createHash)("sha256").update(normalized).digest("hex")}`;
|
|
19463
|
-
}
|
|
19464
|
-
/** Detect patches via tree diff for non-linear history. Returns a composite patch. */
|
|
19465
|
-
async detectPatchesViaTreeDiff(lastGen) {
|
|
19466
|
-
const filesOutput = await this.git.exec(["diff", "--name-only", lastGen.commit_sha, "HEAD"]);
|
|
19467
|
-
const files = filesOutput.trim().split("\n").filter(Boolean).filter((f) => !INFRASTRUCTURE_FILES.has(f)).filter((f) => !f.startsWith(".fern/"));
|
|
19468
|
-
if (files.length === 0)
|
|
19469
|
-
return [];
|
|
19470
|
-
const diff = await this.git.exec(["diff", lastGen.commit_sha, "HEAD", "--", ...files]);
|
|
19471
|
-
if (!diff.trim())
|
|
19472
|
-
return [];
|
|
19473
|
-
const contentHash = this.computeContentHash(diff);
|
|
19474
|
-
const lock = this.lockManager.read();
|
|
19475
|
-
if (lock.patches.some((p) => p.content_hash === contentHash)) {
|
|
19476
|
-
return [];
|
|
19477
|
-
}
|
|
19478
|
-
const headSha = (await this.git.exec(["rev-parse", "HEAD"])).trim();
|
|
19479
|
-
return [
|
|
19480
|
-
{
|
|
19481
|
-
id: `patch-composite-${headSha.slice(0, 8)}`,
|
|
19482
|
-
content_hash: contentHash,
|
|
19483
|
-
original_commit: headSha,
|
|
19484
|
-
original_message: "Customer customizations (composite)",
|
|
19485
|
-
original_author: "composite",
|
|
19486
|
-
base_generation: lastGen.commit_sha,
|
|
19487
|
-
files,
|
|
19488
|
-
patch_content: diff
|
|
19267
|
+
advanceTo(o.length);
|
|
19268
|
+
return results;
|
|
19269
|
+
}
|
|
19270
|
+
function diff3Merge(a, o, b, options) {
|
|
19271
|
+
let defaults3 = {
|
|
19272
|
+
excludeFalseConflicts: true,
|
|
19273
|
+
stringSeparator: /\s+/
|
|
19274
|
+
};
|
|
19275
|
+
options = Object.assign(defaults3, options);
|
|
19276
|
+
if (typeof a === "string")
|
|
19277
|
+
a = a.split(options.stringSeparator);
|
|
19278
|
+
if (typeof o === "string")
|
|
19279
|
+
o = o.split(options.stringSeparator);
|
|
19280
|
+
if (typeof b === "string")
|
|
19281
|
+
b = b.split(options.stringSeparator);
|
|
19282
|
+
let results = [];
|
|
19283
|
+
const regions = diff3MergeRegions(a, o, b);
|
|
19284
|
+
let okBuffer = [];
|
|
19285
|
+
function flushOk() {
|
|
19286
|
+
if (okBuffer.length) {
|
|
19287
|
+
results.push({ ok: okBuffer });
|
|
19288
|
+
}
|
|
19289
|
+
okBuffer = [];
|
|
19290
|
+
}
|
|
19291
|
+
function isFalseConflict(a2, b2) {
|
|
19292
|
+
if (a2.length !== b2.length)
|
|
19293
|
+
return false;
|
|
19294
|
+
for (let i = 0; i < a2.length; i++) {
|
|
19295
|
+
if (a2[i] !== b2[i])
|
|
19296
|
+
return false;
|
|
19297
|
+
}
|
|
19298
|
+
return true;
|
|
19299
|
+
}
|
|
19300
|
+
regions.forEach((region) => {
|
|
19301
|
+
if (region.stable) {
|
|
19302
|
+
okBuffer.push(...region.bufferContent);
|
|
19303
|
+
} else {
|
|
19304
|
+
if (options.excludeFalseConflicts && isFalseConflict(region.aContent, region.bContent)) {
|
|
19305
|
+
okBuffer.push(...region.aContent);
|
|
19306
|
+
} else {
|
|
19307
|
+
flushOk();
|
|
19308
|
+
results.push({
|
|
19309
|
+
conflict: {
|
|
19310
|
+
a: region.aContent,
|
|
19311
|
+
aIndex: region.aStart,
|
|
19312
|
+
o: region.oContent,
|
|
19313
|
+
oIndex: region.oStart,
|
|
19314
|
+
b: region.bContent,
|
|
19315
|
+
bIndex: region.bStart
|
|
19489
19316
|
}
|
|
19490
|
-
];
|
|
19491
|
-
}
|
|
19492
|
-
parseGitLog(log) {
|
|
19493
|
-
return log.trim().split("\n").map((line) => {
|
|
19494
|
-
const [sha, authorName, authorEmail, message] = line.split("\0");
|
|
19495
|
-
return { sha, authorName, authorEmail, message };
|
|
19496
19317
|
});
|
|
19497
19318
|
}
|
|
19498
|
-
|
|
19499
|
-
|
|
19500
|
-
|
|
19501
|
-
|
|
19319
|
+
}
|
|
19320
|
+
});
|
|
19321
|
+
flushOk();
|
|
19322
|
+
return results;
|
|
19323
|
+
}
|
|
19324
|
+
var init_diff3 = __esm({
|
|
19325
|
+
"../../node_modules/.pnpm/node-diff3@3.2.0/node_modules/node-diff3/dist/diff3.mjs"() {
|
|
19326
|
+
"use strict";
|
|
19502
19327
|
}
|
|
19503
19328
|
});
|
|
19504
19329
|
|
|
19505
|
-
// ../../node_modules/.pnpm
|
|
19506
|
-
|
|
19507
|
-
|
|
19508
|
-
|
|
19509
|
-
|
|
19510
|
-
|
|
19511
|
-
|
|
19512
|
-
|
|
19513
|
-
|
|
19514
|
-
|
|
19515
|
-
|
|
19516
|
-
|
|
19517
|
-
|
|
19518
|
-
|
|
19519
|
-
|
|
19520
|
-
|
|
19521
|
-
|
|
19522
|
-
|
|
19523
|
-
|
|
19524
|
-
|
|
19525
|
-
|
|
19526
|
-
|
|
19527
|
-
|
|
19528
|
-
|
|
19529
|
-
|
|
19530
|
-
|
|
19531
|
-
|
|
19532
|
-
|
|
19533
|
-
|
|
19534
|
-
|
|
19535
|
-
} else {
|
|
19536
|
-
candidates[r] = c;
|
|
19537
|
-
}
|
|
19538
|
-
r = s + 1;
|
|
19539
|
-
c = newCandidate;
|
|
19540
|
-
if (r === candidates.length) {
|
|
19541
|
-
break;
|
|
19542
|
-
}
|
|
19543
|
-
}
|
|
19544
|
-
}
|
|
19545
|
-
candidates[r] = c;
|
|
19546
|
-
}
|
|
19547
|
-
return candidates[candidates.length - 1];
|
|
19548
|
-
}
|
|
19549
|
-
function diffIndices(buffer1, buffer2) {
|
|
19550
|
-
const lcs = LCS(buffer1, buffer2);
|
|
19551
|
-
let result = [];
|
|
19552
|
-
let tail1 = buffer1.length;
|
|
19553
|
-
let tail2 = buffer2.length;
|
|
19554
|
-
for (let candidate = lcs; candidate !== null; candidate = candidate.chain) {
|
|
19555
|
-
const mismatchLength1 = tail1 - candidate.buffer1index - 1;
|
|
19556
|
-
const mismatchLength2 = tail2 - candidate.buffer2index - 1;
|
|
19557
|
-
tail1 = candidate.buffer1index;
|
|
19558
|
-
tail2 = candidate.buffer2index;
|
|
19559
|
-
if (mismatchLength1 || mismatchLength2) {
|
|
19560
|
-
result.push({
|
|
19561
|
-
buffer1: [tail1 + 1, mismatchLength1],
|
|
19562
|
-
buffer1Content: buffer1.slice(tail1 + 1, tail1 + 1 + mismatchLength1),
|
|
19563
|
-
buffer2: [tail2 + 1, mismatchLength2],
|
|
19564
|
-
buffer2Content: buffer2.slice(tail2 + 1, tail2 + 1 + mismatchLength2)
|
|
19565
|
-
});
|
|
19566
|
-
}
|
|
19567
|
-
}
|
|
19568
|
-
result.reverse();
|
|
19569
|
-
return result;
|
|
19570
|
-
}
|
|
19571
|
-
function diff3MergeRegions(a, o, b) {
|
|
19572
|
-
let hunks = [];
|
|
19573
|
-
function addHunk(h, ab) {
|
|
19574
|
-
hunks.push({
|
|
19575
|
-
ab,
|
|
19576
|
-
oStart: h.buffer1[0],
|
|
19577
|
-
oLength: h.buffer1[1],
|
|
19578
|
-
abStart: h.buffer2[0],
|
|
19579
|
-
abLength: h.buffer2[1]
|
|
19580
|
-
});
|
|
19581
|
-
}
|
|
19582
|
-
diffIndices(o, a).forEach((item) => addHunk(item, "a"));
|
|
19583
|
-
diffIndices(o, b).forEach((item) => addHunk(item, "b"));
|
|
19584
|
-
hunks.sort((x, y) => x.oStart - y.oStart);
|
|
19585
|
-
let results = [];
|
|
19586
|
-
let currOffset = 0;
|
|
19587
|
-
function advanceTo(endOffset) {
|
|
19588
|
-
if (endOffset > currOffset) {
|
|
19589
|
-
results.push({
|
|
19590
|
-
stable: true,
|
|
19591
|
-
buffer: "o",
|
|
19592
|
-
bufferStart: currOffset,
|
|
19593
|
-
bufferLength: endOffset - currOffset,
|
|
19594
|
-
bufferContent: o.slice(currOffset, endOffset)
|
|
19595
|
-
});
|
|
19596
|
-
currOffset = endOffset;
|
|
19597
|
-
}
|
|
19598
|
-
}
|
|
19599
|
-
while (hunks.length) {
|
|
19600
|
-
let hunk = hunks.shift();
|
|
19601
|
-
let regionStart = hunk.oStart;
|
|
19602
|
-
let regionEnd = hunk.oStart + hunk.oLength;
|
|
19603
|
-
let regionHunks = [hunk];
|
|
19604
|
-
advanceTo(regionStart);
|
|
19605
|
-
while (hunks.length) {
|
|
19606
|
-
const nextHunk = hunks[0];
|
|
19607
|
-
const nextHunkStart = nextHunk.oStart;
|
|
19608
|
-
if (nextHunkStart > regionEnd)
|
|
19609
|
-
break;
|
|
19610
|
-
regionEnd = Math.max(regionEnd, nextHunkStart + nextHunk.oLength);
|
|
19611
|
-
regionHunks.push(hunks.shift());
|
|
19612
|
-
}
|
|
19613
|
-
if (regionHunks.length === 1) {
|
|
19614
|
-
if (hunk.abLength > 0) {
|
|
19615
|
-
const buffer = hunk.ab === "a" ? a : b;
|
|
19616
|
-
results.push({
|
|
19617
|
-
stable: true,
|
|
19618
|
-
buffer: hunk.ab,
|
|
19619
|
-
bufferStart: hunk.abStart,
|
|
19620
|
-
bufferLength: hunk.abLength,
|
|
19621
|
-
bufferContent: buffer.slice(hunk.abStart, hunk.abStart + hunk.abLength)
|
|
19622
|
-
});
|
|
19623
|
-
}
|
|
19624
|
-
} else {
|
|
19625
|
-
let bounds = {
|
|
19626
|
-
a: [a.length, -1, o.length, -1],
|
|
19627
|
-
b: [b.length, -1, o.length, -1]
|
|
19628
|
-
};
|
|
19629
|
-
while (regionHunks.length) {
|
|
19630
|
-
hunk = regionHunks.shift();
|
|
19631
|
-
const oStart = hunk.oStart;
|
|
19632
|
-
const oEnd = oStart + hunk.oLength;
|
|
19633
|
-
const abStart = hunk.abStart;
|
|
19634
|
-
const abEnd = abStart + hunk.abLength;
|
|
19635
|
-
let b2 = bounds[hunk.ab];
|
|
19636
|
-
b2[0] = Math.min(abStart, b2[0]);
|
|
19637
|
-
b2[1] = Math.max(abEnd, b2[1]);
|
|
19638
|
-
b2[2] = Math.min(oStart, b2[2]);
|
|
19639
|
-
b2[3] = Math.max(oEnd, b2[3]);
|
|
19640
|
-
}
|
|
19641
|
-
const aStart = bounds.a[0] + (regionStart - bounds.a[2]);
|
|
19642
|
-
const aEnd = bounds.a[1] + (regionEnd - bounds.a[3]);
|
|
19643
|
-
const bStart = bounds.b[0] + (regionStart - bounds.b[2]);
|
|
19644
|
-
const bEnd = bounds.b[1] + (regionEnd - bounds.b[3]);
|
|
19645
|
-
let result = {
|
|
19646
|
-
stable: false,
|
|
19647
|
-
aStart,
|
|
19648
|
-
aLength: aEnd - aStart,
|
|
19649
|
-
aContent: a.slice(aStart, aEnd),
|
|
19650
|
-
oStart: regionStart,
|
|
19651
|
-
oLength: regionEnd - regionStart,
|
|
19652
|
-
oContent: o.slice(regionStart, regionEnd),
|
|
19653
|
-
bStart,
|
|
19654
|
-
bLength: bEnd - bStart,
|
|
19655
|
-
bContent: b.slice(bStart, bEnd)
|
|
19656
|
-
};
|
|
19657
|
-
results.push(result);
|
|
19658
|
-
}
|
|
19659
|
-
currOffset = regionEnd;
|
|
19660
|
-
}
|
|
19661
|
-
advanceTo(o.length);
|
|
19662
|
-
return results;
|
|
19330
|
+
// ../../node_modules/.pnpm/@fern-api+replay@0.6.1/node_modules/@fern-api/replay/dist/index.js
|
|
19331
|
+
var dist_exports = {};
|
|
19332
|
+
__export(dist_exports, {
|
|
19333
|
+
FERN_BOT_EMAIL: () => FERN_BOT_EMAIL2,
|
|
19334
|
+
FERN_BOT_LOGIN: () => FERN_BOT_LOGIN2,
|
|
19335
|
+
FERN_BOT_NAME: () => FERN_BOT_NAME2,
|
|
19336
|
+
FernignoreMigrator: () => FernignoreMigrator,
|
|
19337
|
+
GitClient: () => GitClient,
|
|
19338
|
+
LockfileManager: () => LockfileManager,
|
|
19339
|
+
ReplayApplicator: () => ReplayApplicator,
|
|
19340
|
+
ReplayCommitter: () => ReplayCommitter,
|
|
19341
|
+
ReplayDetector: () => ReplayDetector,
|
|
19342
|
+
ReplayService: () => ReplayService,
|
|
19343
|
+
bootstrap: () => bootstrap,
|
|
19344
|
+
forget: () => forget,
|
|
19345
|
+
isGenerationCommit: () => isGenerationCommit,
|
|
19346
|
+
isReplayCommit: () => isReplayCommit,
|
|
19347
|
+
reset: () => reset,
|
|
19348
|
+
resolve: () => resolve7,
|
|
19349
|
+
status: () => status,
|
|
19350
|
+
threeWayMerge: () => threeWayMerge
|
|
19351
|
+
});
|
|
19352
|
+
function isGenerationCommit(commit) {
|
|
19353
|
+
const isFernSupport = FERN_SUPPORT_NAMES.includes(commit.authorName);
|
|
19354
|
+
const isBotAuthor = !isFernSupport && (commit.authorLogin === FERN_BOT_LOGIN2 || commit.authorEmail === FERN_BOT_EMAIL2 || commit.authorName === FERN_BOT_NAME2);
|
|
19355
|
+
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.
|
|
19356
|
+
// The default PR title is "SDK Generation" (from GithubStep's commitMessage default).
|
|
19357
|
+
// GitHub appends "(#N)" for the PR number, e.g. "SDK Generation (#70)".
|
|
19358
|
+
commit.message.startsWith("SDK Generation");
|
|
19359
|
+
return isBotAuthor || hasGenerationMarker;
|
|
19663
19360
|
}
|
|
19664
|
-
function
|
|
19665
|
-
|
|
19666
|
-
excludeFalseConflicts: true,
|
|
19667
|
-
stringSeparator: /\s+/
|
|
19668
|
-
};
|
|
19669
|
-
options = Object.assign(defaults3, options);
|
|
19670
|
-
if (typeof a === "string")
|
|
19671
|
-
a = a.split(options.stringSeparator);
|
|
19672
|
-
if (typeof o === "string")
|
|
19673
|
-
o = o.split(options.stringSeparator);
|
|
19674
|
-
if (typeof b === "string")
|
|
19675
|
-
b = b.split(options.stringSeparator);
|
|
19676
|
-
let results = [];
|
|
19677
|
-
const regions = diff3MergeRegions(a, o, b);
|
|
19678
|
-
let okBuffer = [];
|
|
19679
|
-
function flushOk() {
|
|
19680
|
-
if (okBuffer.length) {
|
|
19681
|
-
results.push({ ok: okBuffer });
|
|
19682
|
-
}
|
|
19683
|
-
okBuffer = [];
|
|
19684
|
-
}
|
|
19685
|
-
function isFalseConflict(a2, b2) {
|
|
19686
|
-
if (a2.length !== b2.length)
|
|
19687
|
-
return false;
|
|
19688
|
-
for (let i = 0; i < a2.length; i++) {
|
|
19689
|
-
if (a2[i] !== b2[i])
|
|
19690
|
-
return false;
|
|
19691
|
-
}
|
|
19692
|
-
return true;
|
|
19693
|
-
}
|
|
19694
|
-
regions.forEach((region) => {
|
|
19695
|
-
if (region.stable) {
|
|
19696
|
-
okBuffer.push(...region.bufferContent);
|
|
19697
|
-
} else {
|
|
19698
|
-
if (options.excludeFalseConflicts && isFalseConflict(region.aContent, region.bContent)) {
|
|
19699
|
-
okBuffer.push(...region.aContent);
|
|
19700
|
-
} else {
|
|
19701
|
-
flushOk();
|
|
19702
|
-
results.push({
|
|
19703
|
-
conflict: {
|
|
19704
|
-
a: region.aContent,
|
|
19705
|
-
aIndex: region.aStart,
|
|
19706
|
-
o: region.oContent,
|
|
19707
|
-
oIndex: region.oStart,
|
|
19708
|
-
b: region.bContent,
|
|
19709
|
-
bIndex: region.bStart
|
|
19710
|
-
}
|
|
19711
|
-
});
|
|
19712
|
-
}
|
|
19713
|
-
}
|
|
19714
|
-
});
|
|
19715
|
-
flushOk();
|
|
19716
|
-
return results;
|
|
19361
|
+
function isReplayCommit(commit) {
|
|
19362
|
+
return commit.message.startsWith("[fern-replay]");
|
|
19717
19363
|
}
|
|
19718
|
-
var init_diff3 = __esm({
|
|
19719
|
-
"../../node_modules/.pnpm/node-diff3@3.2.0/node_modules/node-diff3/dist/diff3.mjs"() {
|
|
19720
|
-
"use strict";
|
|
19721
|
-
}
|
|
19722
|
-
});
|
|
19723
|
-
|
|
19724
|
-
// ../../node_modules/.pnpm/@fern-api+replay@0.6.0/node_modules/@fern-api/replay/dist/ThreeWayMerge.js
|
|
19725
19364
|
function threeWayMerge(base, ours, theirs) {
|
|
19726
19365
|
const baseLines = base.split("\n");
|
|
19727
19366
|
const oursLines = ours.split("\n");
|
|
@@ -19757,54 +19396,702 @@ function threeWayMerge(base, ours, theirs) {
|
|
|
19757
19396
|
conflicts: conflicts2
|
|
19758
19397
|
};
|
|
19759
19398
|
}
|
|
19760
|
-
var init_ThreeWayMerge = __esm({
|
|
19761
|
-
"../../node_modules/.pnpm/@fern-api+replay@0.6.0/node_modules/@fern-api/replay/dist/ThreeWayMerge.js"() {
|
|
19762
|
-
"use strict";
|
|
19763
|
-
init_diff3();
|
|
19764
|
-
}
|
|
19765
|
-
});
|
|
19766
|
-
|
|
19767
|
-
// ../../node_modules/.pnpm/@fern-api+replay@0.6.0/node_modules/@fern-api/replay/dist/ReplayApplicator.js
|
|
19768
19399
|
function isBinaryFile(filePath) {
|
|
19769
|
-
const ext2 = (0,
|
|
19400
|
+
const ext2 = (0, import_path9.extname)(filePath).toLowerCase();
|
|
19770
19401
|
return BINARY_EXTENSIONS.has(ext2);
|
|
19771
19402
|
}
|
|
19772
19403
|
function isDiffLineForFile(diffLine, filePath) {
|
|
19773
19404
|
const match2 = diffLine.match(/^diff --git a\/.+ b\/(.+)$/);
|
|
19774
19405
|
return match2 !== null && match2[1] === filePath;
|
|
19775
19406
|
}
|
|
19776
|
-
|
|
19777
|
-
|
|
19778
|
-
|
|
19779
|
-
|
|
19780
|
-
|
|
19781
|
-
|
|
19782
|
-
|
|
19783
|
-
|
|
19784
|
-
|
|
19785
|
-
|
|
19786
|
-
|
|
19787
|
-
|
|
19788
|
-
|
|
19789
|
-
".
|
|
19790
|
-
|
|
19791
|
-
"
|
|
19792
|
-
|
|
19793
|
-
|
|
19794
|
-
|
|
19795
|
-
|
|
19796
|
-
|
|
19797
|
-
|
|
19798
|
-
|
|
19799
|
-
|
|
19800
|
-
|
|
19801
|
-
|
|
19802
|
-
|
|
19803
|
-
|
|
19804
|
-
|
|
19805
|
-
|
|
19806
|
-
|
|
19807
|
-
"
|
|
19407
|
+
async function bootstrap(outputDir, options) {
|
|
19408
|
+
const git = new GitClient(outputDir);
|
|
19409
|
+
const lockManager = new LockfileManager(outputDir);
|
|
19410
|
+
const maxCommits = options?.maxCommitsToScan ?? 500;
|
|
19411
|
+
const warnings = [];
|
|
19412
|
+
if (lockManager.exists() && !options?.force) {
|
|
19413
|
+
return {
|
|
19414
|
+
generationCommit: null,
|
|
19415
|
+
patchesDetected: 0,
|
|
19416
|
+
patchesCreated: 0,
|
|
19417
|
+
patches: [],
|
|
19418
|
+
fernignorePatterns: [],
|
|
19419
|
+
fernignoreUpdated: false,
|
|
19420
|
+
warnings: ["Replay lockfile already exists. Use --force to overwrite."],
|
|
19421
|
+
staleGenerationsSkipped: 0,
|
|
19422
|
+
scannedSinceGeneration: ""
|
|
19423
|
+
};
|
|
19424
|
+
}
|
|
19425
|
+
const genCommits = await findAllGenerationCommits(git, maxCommits);
|
|
19426
|
+
if (genCommits.length === 0) {
|
|
19427
|
+
return {
|
|
19428
|
+
generationCommit: null,
|
|
19429
|
+
patchesDetected: 0,
|
|
19430
|
+
patchesCreated: 0,
|
|
19431
|
+
patches: [],
|
|
19432
|
+
fernignorePatterns: [],
|
|
19433
|
+
fernignoreUpdated: false,
|
|
19434
|
+
warnings: [
|
|
19435
|
+
"No generation commits found in the last " + maxCommits + " commits. Run 'fern generate' first to establish a baseline."
|
|
19436
|
+
],
|
|
19437
|
+
staleGenerationsSkipped: 0,
|
|
19438
|
+
scannedSinceGeneration: ""
|
|
19439
|
+
};
|
|
19440
|
+
}
|
|
19441
|
+
const latestGen = genCommits[0];
|
|
19442
|
+
const anchorSha = options?.importHistory ? latestGen.sha : (await git.exec(["rev-parse", "HEAD"])).trim();
|
|
19443
|
+
const treeHash = await git.getTreeHash(anchorSha);
|
|
19444
|
+
const genRecord = {
|
|
19445
|
+
commit_sha: anchorSha,
|
|
19446
|
+
tree_hash: treeHash,
|
|
19447
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
19448
|
+
cli_version: "unknown",
|
|
19449
|
+
generator_versions: {}
|
|
19450
|
+
};
|
|
19451
|
+
lockManager.initializeInMemory(genRecord);
|
|
19452
|
+
const patches = options?.importHistory ? await findAllUserPatches(git, genCommits) : [];
|
|
19453
|
+
const migrator = new FernignoreMigrator(git, lockManager, outputDir);
|
|
19454
|
+
const fernignorePatterns = migrator.readFernignorePatterns();
|
|
19455
|
+
let fernignoreAnalysis;
|
|
19456
|
+
if (options?.importHistory && migrator.fernignoreExists() && fernignorePatterns.length > 0) {
|
|
19457
|
+
fernignoreAnalysis = await migrator.analyzeMigration();
|
|
19458
|
+
if (fernignoreAnalysis.syntheticPatches.length > 0) {
|
|
19459
|
+
patches.push(...fernignoreAnalysis.syntheticPatches);
|
|
19460
|
+
}
|
|
19461
|
+
if (fernignoreAnalysis.fernignoreOnly.length > 0) {
|
|
19462
|
+
for (const file of fernignoreAnalysis.fernignoreOnly) {
|
|
19463
|
+
warnings.push(
|
|
19464
|
+
`${file}: in .fernignore but no recent commits found since last generation. File may be stale, matches generated output, or does not exist. No customization to track.`
|
|
19465
|
+
);
|
|
19466
|
+
}
|
|
19467
|
+
}
|
|
19468
|
+
}
|
|
19469
|
+
if (options?.dryRun) {
|
|
19470
|
+
return {
|
|
19471
|
+
generationCommit: latestGen,
|
|
19472
|
+
patchesDetected: patches.length,
|
|
19473
|
+
patchesCreated: 0,
|
|
19474
|
+
patches,
|
|
19475
|
+
fernignorePatterns,
|
|
19476
|
+
fernignoreAnalysis,
|
|
19477
|
+
fernignoreUpdated: false,
|
|
19478
|
+
warnings,
|
|
19479
|
+
staleGenerationsSkipped: genCommits.length - 1,
|
|
19480
|
+
scannedSinceGeneration: latestGen.sha
|
|
19481
|
+
};
|
|
19482
|
+
}
|
|
19483
|
+
for (const patch of patches) {
|
|
19484
|
+
lockManager.addPatch(patch);
|
|
19485
|
+
}
|
|
19486
|
+
lockManager.save();
|
|
19487
|
+
const fernignoreUpdated = ensureFernignoreEntries(outputDir);
|
|
19488
|
+
if (migrator.fernignoreExists() && fernignorePatterns.length > 0) {
|
|
19489
|
+
const action = options?.fernignoreAction ?? "skip";
|
|
19490
|
+
if (action === "migrate") {
|
|
19491
|
+
const patternsToExclude = fernignoreAnalysis?.fernignoreOnly ?? [];
|
|
19492
|
+
if (patternsToExclude.length > 0) {
|
|
19493
|
+
migrator.movePatternsToReplayYml(patternsToExclude);
|
|
19494
|
+
}
|
|
19495
|
+
}
|
|
19496
|
+
}
|
|
19497
|
+
return {
|
|
19498
|
+
generationCommit: latestGen,
|
|
19499
|
+
patchesDetected: patches.length,
|
|
19500
|
+
patchesCreated: patches.length,
|
|
19501
|
+
patches,
|
|
19502
|
+
fernignorePatterns,
|
|
19503
|
+
fernignoreAnalysis,
|
|
19504
|
+
fernignoreUpdated,
|
|
19505
|
+
warnings,
|
|
19506
|
+
staleGenerationsSkipped: genCommits.length - 1,
|
|
19507
|
+
scannedSinceGeneration: latestGen.sha
|
|
19508
|
+
};
|
|
19509
|
+
}
|
|
19510
|
+
async function findAllGenerationCommits(git, maxCommits) {
|
|
19511
|
+
const log = await git.exec(["log", "--format=%H%x00%an%x00%ae%x00%s", `-${maxCommits}`]);
|
|
19512
|
+
if (!log.trim()) {
|
|
19513
|
+
return [];
|
|
19514
|
+
}
|
|
19515
|
+
const genCommits = [];
|
|
19516
|
+
for (const line of log.trim().split("\n")) {
|
|
19517
|
+
if (!line) continue;
|
|
19518
|
+
const [sha, authorName, authorEmail, message] = line.split("\0");
|
|
19519
|
+
const commit = { sha, authorName, authorEmail, message };
|
|
19520
|
+
if (isGenerationCommit(commit) && !isReplayCommit(commit)) {
|
|
19521
|
+
genCommits.push(commit);
|
|
19522
|
+
}
|
|
19523
|
+
}
|
|
19524
|
+
return genCommits;
|
|
19525
|
+
}
|
|
19526
|
+
async function findAllUserPatches(git, genCommits) {
|
|
19527
|
+
const patches = [];
|
|
19528
|
+
const seenHashes = /* @__PURE__ */ new Set();
|
|
19529
|
+
const latestGen = genCommits[0];
|
|
19530
|
+
const recentPatches = await extractUserPatches(git, latestGen.sha, "HEAD", latestGen.sha, seenHashes);
|
|
19531
|
+
patches.push(...recentPatches);
|
|
19532
|
+
return patches;
|
|
19533
|
+
}
|
|
19534
|
+
async function extractUserPatches(git, fromSha, toRef, baseGeneration, seenHashes) {
|
|
19535
|
+
const log = await git.exec(["log", "--format=%H%x00%an%x00%ae%x00%s", `${fromSha}..${toRef}`]);
|
|
19536
|
+
if (!log.trim()) {
|
|
19537
|
+
return [];
|
|
19538
|
+
}
|
|
19539
|
+
const commits = parseGitLog(log);
|
|
19540
|
+
const patches = [];
|
|
19541
|
+
for (const commit of commits.reverse()) {
|
|
19542
|
+
if (isGenerationCommit(commit)) continue;
|
|
19543
|
+
const parents = await git.getCommitParents(commit.sha);
|
|
19544
|
+
if (parents.length > 1) continue;
|
|
19545
|
+
const patchContent = await git.formatPatch(commit.sha);
|
|
19546
|
+
const contentHash = computeContentHash(patchContent);
|
|
19547
|
+
if (seenHashes.has(contentHash)) continue;
|
|
19548
|
+
seenHashes.add(contentHash);
|
|
19549
|
+
const filesOutput = await git.exec(["diff-tree", "--no-commit-id", "--name-only", "-r", commit.sha]);
|
|
19550
|
+
patches.push({
|
|
19551
|
+
id: `patch-${commit.sha.slice(0, 8)}`,
|
|
19552
|
+
content_hash: contentHash,
|
|
19553
|
+
original_commit: commit.sha,
|
|
19554
|
+
original_message: commit.message,
|
|
19555
|
+
original_author: `${commit.authorName} <${commit.authorEmail}>`,
|
|
19556
|
+
base_generation: baseGeneration,
|
|
19557
|
+
files: filesOutput.trim().split("\n").filter(Boolean),
|
|
19558
|
+
patch_content: patchContent
|
|
19559
|
+
});
|
|
19560
|
+
}
|
|
19561
|
+
return patches;
|
|
19562
|
+
}
|
|
19563
|
+
function parseGitLog(log) {
|
|
19564
|
+
return log.trim().split("\n").filter(Boolean).map((line) => {
|
|
19565
|
+
const [sha, authorName, authorEmail, message] = line.split("\0");
|
|
19566
|
+
return { sha, authorName, authorEmail, message };
|
|
19567
|
+
});
|
|
19568
|
+
}
|
|
19569
|
+
function ensureFernignoreEntries(outputDir) {
|
|
19570
|
+
const fernignorePath = (0, import_path12.join)(outputDir, ".fernignore");
|
|
19571
|
+
let content = "";
|
|
19572
|
+
if ((0, import_fs9.existsSync)(fernignorePath)) {
|
|
19573
|
+
content = (0, import_fs9.readFileSync)(fernignorePath, "utf-8");
|
|
19574
|
+
}
|
|
19575
|
+
const lines = content.split("\n");
|
|
19576
|
+
const toAdd = [];
|
|
19577
|
+
for (const entry of REPLAY_FERNIGNORE_ENTRIES) {
|
|
19578
|
+
if (!lines.some((line) => line.trim() === entry)) {
|
|
19579
|
+
toAdd.push(entry);
|
|
19580
|
+
}
|
|
19581
|
+
}
|
|
19582
|
+
if (toAdd.length === 0) {
|
|
19583
|
+
return false;
|
|
19584
|
+
}
|
|
19585
|
+
if (content && !content.endsWith("\n")) {
|
|
19586
|
+
content += "\n";
|
|
19587
|
+
}
|
|
19588
|
+
content += toAdd.join("\n") + "\n";
|
|
19589
|
+
(0, import_fs9.writeFileSync)(fernignorePath, content, "utf-8");
|
|
19590
|
+
return true;
|
|
19591
|
+
}
|
|
19592
|
+
function computeContentHash(patchContent) {
|
|
19593
|
+
const normalized = patchContent.split("\n").filter((line) => !line.startsWith("From ") && !line.startsWith("index ") && !line.startsWith("Date: ")).join("\n");
|
|
19594
|
+
return `sha256:${(0, import_crypto3.createHash)("sha256").update(normalized).digest("hex")}`;
|
|
19595
|
+
}
|
|
19596
|
+
function forget(outputDir, filePattern, options) {
|
|
19597
|
+
const lockManager = new LockfileManager(outputDir);
|
|
19598
|
+
if (!lockManager.exists()) {
|
|
19599
|
+
return { removed: [], notFound: true };
|
|
19600
|
+
}
|
|
19601
|
+
const lock = lockManager.read();
|
|
19602
|
+
const matchingPatches = lock.patches.filter(
|
|
19603
|
+
(patch) => patch.files.some((file) => file === filePattern || minimatch(file, filePattern))
|
|
19604
|
+
);
|
|
19605
|
+
if (matchingPatches.length === 0) {
|
|
19606
|
+
return { removed: [], notFound: true };
|
|
19607
|
+
}
|
|
19608
|
+
const removed = matchingPatches.map((p) => ({
|
|
19609
|
+
id: p.id,
|
|
19610
|
+
message: p.original_message,
|
|
19611
|
+
files: p.files
|
|
19612
|
+
}));
|
|
19613
|
+
if (!options?.dryRun) {
|
|
19614
|
+
for (const patch of matchingPatches) {
|
|
19615
|
+
lockManager.removePatch(patch.id);
|
|
19616
|
+
}
|
|
19617
|
+
lockManager.save();
|
|
19618
|
+
}
|
|
19619
|
+
return { removed, notFound: false };
|
|
19620
|
+
}
|
|
19621
|
+
function reset(outputDir, options) {
|
|
19622
|
+
const lockManager = new LockfileManager(outputDir);
|
|
19623
|
+
if (!lockManager.exists()) {
|
|
19624
|
+
return {
|
|
19625
|
+
success: true,
|
|
19626
|
+
patchesRemoved: 0,
|
|
19627
|
+
lockfileDeleted: false,
|
|
19628
|
+
nothingToReset: true
|
|
19629
|
+
};
|
|
19630
|
+
}
|
|
19631
|
+
const lock = lockManager.read();
|
|
19632
|
+
const patchCount = lock.patches.length;
|
|
19633
|
+
if (!options?.dryRun) {
|
|
19634
|
+
(0, import_fs10.unlinkSync)(lockManager.lockfilePath);
|
|
19635
|
+
}
|
|
19636
|
+
return {
|
|
19637
|
+
success: true,
|
|
19638
|
+
patchesRemoved: patchCount,
|
|
19639
|
+
lockfileDeleted: true,
|
|
19640
|
+
nothingToReset: false
|
|
19641
|
+
};
|
|
19642
|
+
}
|
|
19643
|
+
async function resolve7(outputDir, options) {
|
|
19644
|
+
const lockManager = new LockfileManager(outputDir);
|
|
19645
|
+
if (!lockManager.exists()) {
|
|
19646
|
+
return { success: false, reason: "no-lockfile" };
|
|
19647
|
+
}
|
|
19648
|
+
const lock = lockManager.read();
|
|
19649
|
+
if (lock.patches.length === 0) {
|
|
19650
|
+
return { success: false, reason: "no-patches" };
|
|
19651
|
+
}
|
|
19652
|
+
const git = new GitClient(outputDir);
|
|
19653
|
+
if (options?.checkMarkers !== false) {
|
|
19654
|
+
const markerFiles = await git.exec(["grep", "-l", "<<<<<<<", "--", "."]).catch(() => "");
|
|
19655
|
+
if (markerFiles.trim()) {
|
|
19656
|
+
const files = markerFiles.trim().split("\n").filter(Boolean);
|
|
19657
|
+
return { success: false, reason: "unresolved-conflicts", unresolvedFiles: files };
|
|
19658
|
+
}
|
|
19659
|
+
}
|
|
19660
|
+
const committer = new ReplayCommitter(git, outputDir);
|
|
19661
|
+
await committer.stageAll();
|
|
19662
|
+
const commitSha = await committer.commitReplay(lock.patches.length, lock.patches);
|
|
19663
|
+
return { success: true, commitSha };
|
|
19664
|
+
}
|
|
19665
|
+
function status(outputDir) {
|
|
19666
|
+
const lockManager = new LockfileManager(outputDir);
|
|
19667
|
+
if (!lockManager.exists()) {
|
|
19668
|
+
return { initialized: false, patches: [], lastGeneration: void 0 };
|
|
19669
|
+
}
|
|
19670
|
+
const lock = lockManager.read();
|
|
19671
|
+
const patches = lock.patches.map((patch) => ({
|
|
19672
|
+
sha: patch.original_commit.slice(0, 7),
|
|
19673
|
+
author: patch.original_author.split("<")[0]?.trim() ?? "unknown",
|
|
19674
|
+
message: patch.original_message,
|
|
19675
|
+
files: patch.files
|
|
19676
|
+
}));
|
|
19677
|
+
let lastGeneration;
|
|
19678
|
+
const lastGen = lock.generations.find((g) => g.commit_sha === lock.current_generation);
|
|
19679
|
+
if (lastGen) {
|
|
19680
|
+
lastGeneration = {
|
|
19681
|
+
sha: lastGen.commit_sha,
|
|
19682
|
+
timestamp: lastGen.timestamp
|
|
19683
|
+
};
|
|
19684
|
+
}
|
|
19685
|
+
return { initialized: true, patches, lastGeneration };
|
|
19686
|
+
}
|
|
19687
|
+
var import_fs6, import_path8, import_yaml, import_crypto, import_promises4, import_os, import_path9, import_fs7, import_path10, import_crypto2, import_fs8, import_path11, import_yaml2, import_crypto3, import_fs9, import_path12, import_fs10, __defProp3, __getOwnPropNames3, __esm3, __export3, GitClient_exports, GitClient, init_GitClient, FERN_BOT_NAME2, FERN_BOT_EMAIL2, FERN_BOT_LOGIN2, FERN_SUPPORT_NAMES, LOCKFILE_HEADER, LockfileManager, INFRASTRUCTURE_FILES, ReplayDetector, BINARY_EXTENSIONS, ReplayApplicator, ReplayCommitter, ReplayService, FernignoreMigrator, REPLAY_FERNIGNORE_ENTRIES;
|
|
19688
|
+
var init_dist = __esm({
|
|
19689
|
+
"../../node_modules/.pnpm/@fern-api+replay@0.6.1/node_modules/@fern-api/replay/dist/index.js"() {
|
|
19690
|
+
"use strict";
|
|
19691
|
+
init_esm4();
|
|
19692
|
+
import_fs6 = require("fs");
|
|
19693
|
+
import_path8 = require("path");
|
|
19694
|
+
import_yaml = __toESM(require_dist3(), 1);
|
|
19695
|
+
import_crypto = require("crypto");
|
|
19696
|
+
init_diff3();
|
|
19697
|
+
import_promises4 = require("fs/promises");
|
|
19698
|
+
import_os = require("os");
|
|
19699
|
+
import_path9 = require("path");
|
|
19700
|
+
init_esm3();
|
|
19701
|
+
import_fs7 = require("fs");
|
|
19702
|
+
import_path10 = require("path");
|
|
19703
|
+
init_esm3();
|
|
19704
|
+
import_crypto2 = require("crypto");
|
|
19705
|
+
import_fs8 = require("fs");
|
|
19706
|
+
import_path11 = require("path");
|
|
19707
|
+
init_esm3();
|
|
19708
|
+
import_yaml2 = __toESM(require_dist3(), 1);
|
|
19709
|
+
import_crypto3 = require("crypto");
|
|
19710
|
+
import_fs9 = require("fs");
|
|
19711
|
+
import_path12 = require("path");
|
|
19712
|
+
init_esm3();
|
|
19713
|
+
import_fs10 = require("fs");
|
|
19714
|
+
__defProp3 = Object.defineProperty;
|
|
19715
|
+
__getOwnPropNames3 = Object.getOwnPropertyNames;
|
|
19716
|
+
__esm3 = (fn, res) => function __init() {
|
|
19717
|
+
return fn && (res = (0, fn[__getOwnPropNames3(fn)[0]])(fn = 0)), res;
|
|
19718
|
+
};
|
|
19719
|
+
__export3 = (target, all) => {
|
|
19720
|
+
for (var name in all)
|
|
19721
|
+
__defProp3(target, name, { get: all[name], enumerable: true });
|
|
19722
|
+
};
|
|
19723
|
+
GitClient_exports = {};
|
|
19724
|
+
__export3(GitClient_exports, {
|
|
19725
|
+
GitClient: () => GitClient
|
|
19726
|
+
});
|
|
19727
|
+
init_GitClient = __esm3({
|
|
19728
|
+
"src/git/GitClient.ts"() {
|
|
19729
|
+
"use strict";
|
|
19730
|
+
GitClient = class {
|
|
19731
|
+
git;
|
|
19732
|
+
repoPath;
|
|
19733
|
+
constructor(repoPath) {
|
|
19734
|
+
this.repoPath = repoPath;
|
|
19735
|
+
this.git = simpleGit(repoPath);
|
|
19736
|
+
}
|
|
19737
|
+
async exec(args) {
|
|
19738
|
+
return this.git.raw(args);
|
|
19739
|
+
}
|
|
19740
|
+
async execWithInput(args, input) {
|
|
19741
|
+
const { spawn: spawn2 } = await import("child_process");
|
|
19742
|
+
return new Promise((resolve22, reject) => {
|
|
19743
|
+
const proc = spawn2("git", args, { cwd: this.repoPath });
|
|
19744
|
+
let stdout = "";
|
|
19745
|
+
let stderr = "";
|
|
19746
|
+
proc.stdout.on("data", (data) => {
|
|
19747
|
+
stdout += data.toString();
|
|
19748
|
+
});
|
|
19749
|
+
proc.stderr.on("data", (data) => {
|
|
19750
|
+
stderr += data.toString();
|
|
19751
|
+
});
|
|
19752
|
+
proc.on("close", (code) => {
|
|
19753
|
+
if (code === 0) {
|
|
19754
|
+
resolve22(stdout);
|
|
19755
|
+
} else {
|
|
19756
|
+
reject(new Error(`git ${args.join(" ")} failed (code ${code}): ${stderr}`));
|
|
19757
|
+
}
|
|
19758
|
+
});
|
|
19759
|
+
proc.stdin.write(input);
|
|
19760
|
+
proc.stdin.end();
|
|
19761
|
+
});
|
|
19762
|
+
}
|
|
19763
|
+
async formatPatch(commitSha) {
|
|
19764
|
+
return this.exec(["format-patch", "-1", commitSha, "--stdout"]);
|
|
19765
|
+
}
|
|
19766
|
+
async applyPatch(patchContent) {
|
|
19767
|
+
await this.execWithInput(["am", "--3way"], patchContent);
|
|
19768
|
+
}
|
|
19769
|
+
async getTreeHash(commitSha) {
|
|
19770
|
+
return (await this.exec(["rev-parse", `${commitSha}^{tree}`])).trim();
|
|
19771
|
+
}
|
|
19772
|
+
async showFile(treeish, filePath) {
|
|
19773
|
+
try {
|
|
19774
|
+
return await this.exec(["show", `${treeish}:${filePath}`]);
|
|
19775
|
+
} catch {
|
|
19776
|
+
return null;
|
|
19777
|
+
}
|
|
19778
|
+
}
|
|
19779
|
+
async getCommitInfo(commitSha) {
|
|
19780
|
+
const format3 = "%H%x00%an%x00%ae%x00%s";
|
|
19781
|
+
const output = await this.exec(["log", "-1", `--format=${format3}`, commitSha]);
|
|
19782
|
+
const [sha, authorName, authorEmail, message] = output.trim().split("\0");
|
|
19783
|
+
return { sha, authorName, authorEmail, message };
|
|
19784
|
+
}
|
|
19785
|
+
async getCommitParents(commitSha) {
|
|
19786
|
+
const output = await this.exec(["rev-parse", `${commitSha}^@`]);
|
|
19787
|
+
return output.trim().split("\n").filter(Boolean);
|
|
19788
|
+
}
|
|
19789
|
+
async detectRenames(fromTree, toTree) {
|
|
19790
|
+
try {
|
|
19791
|
+
const output = await this.exec(["diff", "--find-renames", "--name-status", fromTree, toTree]);
|
|
19792
|
+
const renames = [];
|
|
19793
|
+
for (const line of output.trim().split("\n")) {
|
|
19794
|
+
if (!line) continue;
|
|
19795
|
+
if (line.startsWith("R")) {
|
|
19796
|
+
const parts = line.split(" ");
|
|
19797
|
+
if (parts.length >= 3) {
|
|
19798
|
+
renames.push({ from: parts[1], to: parts[2] });
|
|
19799
|
+
}
|
|
19800
|
+
}
|
|
19801
|
+
}
|
|
19802
|
+
return renames;
|
|
19803
|
+
} catch {
|
|
19804
|
+
return [];
|
|
19805
|
+
}
|
|
19806
|
+
}
|
|
19807
|
+
async isAncestor(commit, descendant) {
|
|
19808
|
+
try {
|
|
19809
|
+
const mergeBase = (await this.exec(["merge-base", commit, descendant])).trim();
|
|
19810
|
+
return mergeBase === commit;
|
|
19811
|
+
} catch {
|
|
19812
|
+
return false;
|
|
19813
|
+
}
|
|
19814
|
+
}
|
|
19815
|
+
async commitExists(sha) {
|
|
19816
|
+
try {
|
|
19817
|
+
const type = await this.exec(["cat-file", "-t", sha]);
|
|
19818
|
+
return type.trim() === "commit";
|
|
19819
|
+
} catch {
|
|
19820
|
+
return false;
|
|
19821
|
+
}
|
|
19822
|
+
}
|
|
19823
|
+
getRepoPath() {
|
|
19824
|
+
return this.repoPath;
|
|
19825
|
+
}
|
|
19826
|
+
};
|
|
19827
|
+
}
|
|
19828
|
+
});
|
|
19829
|
+
init_GitClient();
|
|
19830
|
+
FERN_BOT_NAME2 = "fern-api";
|
|
19831
|
+
FERN_BOT_EMAIL2 = "115122769+fern-api[bot]@users.noreply.github.com";
|
|
19832
|
+
FERN_BOT_LOGIN2 = "fern-api[bot]";
|
|
19833
|
+
FERN_SUPPORT_NAMES = ["fern-support", "Fern Support"];
|
|
19834
|
+
LOCKFILE_HEADER = "# DO NOT EDIT MANUALLY - Managed by Fern Replay\n";
|
|
19835
|
+
LockfileManager = class {
|
|
19836
|
+
outputDir;
|
|
19837
|
+
lock = null;
|
|
19838
|
+
constructor(outputDir) {
|
|
19839
|
+
this.outputDir = outputDir;
|
|
19840
|
+
}
|
|
19841
|
+
get lockfilePath() {
|
|
19842
|
+
return (0, import_path8.join)(this.outputDir, ".fern", "replay.lock");
|
|
19843
|
+
}
|
|
19844
|
+
get customizationsPath() {
|
|
19845
|
+
return (0, import_path8.join)(this.outputDir, ".fern", "replay.yml");
|
|
19846
|
+
}
|
|
19847
|
+
exists() {
|
|
19848
|
+
return (0, import_fs6.existsSync)(this.lockfilePath);
|
|
19849
|
+
}
|
|
19850
|
+
read() {
|
|
19851
|
+
if (this.lock) {
|
|
19852
|
+
return this.lock;
|
|
19853
|
+
}
|
|
19854
|
+
if (!this.exists()) {
|
|
19855
|
+
throw new Error(`Lockfile not found: ${this.lockfilePath}`);
|
|
19856
|
+
}
|
|
19857
|
+
const content = (0, import_fs6.readFileSync)(this.lockfilePath, "utf-8");
|
|
19858
|
+
this.lock = (0, import_yaml.parse)(content);
|
|
19859
|
+
return this.lock;
|
|
19860
|
+
}
|
|
19861
|
+
initialize(firstGeneration) {
|
|
19862
|
+
this.initializeInMemory(firstGeneration);
|
|
19863
|
+
this.save();
|
|
19864
|
+
}
|
|
19865
|
+
/**
|
|
19866
|
+
* Set up in-memory lock state without writing to disk.
|
|
19867
|
+
* Useful for bootstrap dry-run where we need state for detection
|
|
19868
|
+
* but don't want to persist anything.
|
|
19869
|
+
*/
|
|
19870
|
+
initializeInMemory(firstGeneration) {
|
|
19871
|
+
this.lock = {
|
|
19872
|
+
version: "1.0",
|
|
19873
|
+
generations: [firstGeneration],
|
|
19874
|
+
current_generation: firstGeneration.commit_sha,
|
|
19875
|
+
patches: []
|
|
19876
|
+
};
|
|
19877
|
+
}
|
|
19878
|
+
save() {
|
|
19879
|
+
if (!this.lock) {
|
|
19880
|
+
throw new Error("No lockfile data to save. Call read() or initialize() first.");
|
|
19881
|
+
}
|
|
19882
|
+
const dir = (0, import_path8.dirname)(this.lockfilePath);
|
|
19883
|
+
if (!(0, import_fs6.existsSync)(dir)) {
|
|
19884
|
+
(0, import_fs6.mkdirSync)(dir, { recursive: true });
|
|
19885
|
+
}
|
|
19886
|
+
const yaml = (0, import_yaml.stringify)(this.lock, {
|
|
19887
|
+
lineWidth: 0,
|
|
19888
|
+
blockQuote: "literal"
|
|
19889
|
+
});
|
|
19890
|
+
const content = LOCKFILE_HEADER + yaml;
|
|
19891
|
+
const tmpPath = this.lockfilePath + ".tmp";
|
|
19892
|
+
(0, import_fs6.writeFileSync)(tmpPath, content, "utf-8");
|
|
19893
|
+
(0, import_fs6.renameSync)(tmpPath, this.lockfilePath);
|
|
19894
|
+
}
|
|
19895
|
+
addGeneration(record2) {
|
|
19896
|
+
this.ensureLoaded();
|
|
19897
|
+
this.lock.generations.push(record2);
|
|
19898
|
+
this.lock.current_generation = record2.commit_sha;
|
|
19899
|
+
}
|
|
19900
|
+
addPatch(patch) {
|
|
19901
|
+
this.ensureLoaded();
|
|
19902
|
+
this.lock.patches.push(patch);
|
|
19903
|
+
}
|
|
19904
|
+
updatePatch(patchId, updates) {
|
|
19905
|
+
this.ensureLoaded();
|
|
19906
|
+
const patch = this.lock.patches.find((p) => p.id === patchId);
|
|
19907
|
+
if (!patch) {
|
|
19908
|
+
throw new Error(`Patch not found: ${patchId}`);
|
|
19909
|
+
}
|
|
19910
|
+
Object.assign(patch, updates);
|
|
19911
|
+
}
|
|
19912
|
+
removePatch(patchId) {
|
|
19913
|
+
this.ensureLoaded();
|
|
19914
|
+
this.lock.patches = this.lock.patches.filter((p) => p.id !== patchId);
|
|
19915
|
+
}
|
|
19916
|
+
clearPatches() {
|
|
19917
|
+
this.ensureLoaded();
|
|
19918
|
+
this.lock.patches = [];
|
|
19919
|
+
}
|
|
19920
|
+
getPatches() {
|
|
19921
|
+
this.ensureLoaded();
|
|
19922
|
+
return this.lock.patches;
|
|
19923
|
+
}
|
|
19924
|
+
setReplaySkippedAt(timestamp) {
|
|
19925
|
+
this.ensureLoaded();
|
|
19926
|
+
this.lock.replay_skipped_at = timestamp;
|
|
19927
|
+
}
|
|
19928
|
+
clearReplaySkippedAt() {
|
|
19929
|
+
this.ensureLoaded();
|
|
19930
|
+
delete this.lock.replay_skipped_at;
|
|
19931
|
+
}
|
|
19932
|
+
isReplaySkipped() {
|
|
19933
|
+
this.ensureLoaded();
|
|
19934
|
+
return this.lock.replay_skipped_at != null;
|
|
19935
|
+
}
|
|
19936
|
+
getGeneration(commitSha) {
|
|
19937
|
+
this.ensureLoaded();
|
|
19938
|
+
return this.lock.generations.find((g) => g.commit_sha === commitSha);
|
|
19939
|
+
}
|
|
19940
|
+
getCustomizationsConfig() {
|
|
19941
|
+
if (!(0, import_fs6.existsSync)(this.customizationsPath)) {
|
|
19942
|
+
return {};
|
|
19943
|
+
}
|
|
19944
|
+
const content = (0, import_fs6.readFileSync)(this.customizationsPath, "utf-8");
|
|
19945
|
+
return (0, import_yaml.parse)(content) ?? {};
|
|
19946
|
+
}
|
|
19947
|
+
ensureLoaded() {
|
|
19948
|
+
if (!this.lock) {
|
|
19949
|
+
throw new Error("No lockfile loaded. Call read() or initialize() first.");
|
|
19950
|
+
}
|
|
19951
|
+
}
|
|
19952
|
+
};
|
|
19953
|
+
INFRASTRUCTURE_FILES = /* @__PURE__ */ new Set([".fernignore"]);
|
|
19954
|
+
ReplayDetector = class {
|
|
19955
|
+
git;
|
|
19956
|
+
lockManager;
|
|
19957
|
+
sdkOutputDir;
|
|
19958
|
+
warnings = [];
|
|
19959
|
+
constructor(git, lockManager, sdkOutputDir) {
|
|
19960
|
+
this.git = git;
|
|
19961
|
+
this.lockManager = lockManager;
|
|
19962
|
+
this.sdkOutputDir = sdkOutputDir;
|
|
19963
|
+
}
|
|
19964
|
+
async detectNewPatches() {
|
|
19965
|
+
const lock = this.lockManager.read();
|
|
19966
|
+
const lastGen = this.getLastGeneration(lock);
|
|
19967
|
+
if (!lastGen) {
|
|
19968
|
+
return [];
|
|
19969
|
+
}
|
|
19970
|
+
const exists2 = await this.git.commitExists(lastGen.commit_sha);
|
|
19971
|
+
if (!exists2) {
|
|
19972
|
+
this.warnings.push(
|
|
19973
|
+
`Generation commit ${lastGen.commit_sha.slice(0, 7)} not found in git history. Skipping new patch detection. Existing lockfile patches will still be applied.`
|
|
19974
|
+
);
|
|
19975
|
+
return [];
|
|
19976
|
+
}
|
|
19977
|
+
const isAncestor = await this.git.isAncestor(lastGen.commit_sha, "HEAD");
|
|
19978
|
+
if (!isAncestor) {
|
|
19979
|
+
return this.detectPatchesViaTreeDiff(lastGen);
|
|
19980
|
+
}
|
|
19981
|
+
const log = await this.git.exec([
|
|
19982
|
+
"log",
|
|
19983
|
+
"--format=%H%x00%an%x00%ae%x00%s",
|
|
19984
|
+
`${lastGen.commit_sha}..HEAD`,
|
|
19985
|
+
"--",
|
|
19986
|
+
this.sdkOutputDir
|
|
19987
|
+
]);
|
|
19988
|
+
if (!log.trim()) {
|
|
19989
|
+
return [];
|
|
19990
|
+
}
|
|
19991
|
+
const commits = this.parseGitLog(log);
|
|
19992
|
+
const newPatches = [];
|
|
19993
|
+
for (const commit of commits) {
|
|
19994
|
+
if (isGenerationCommit(commit)) {
|
|
19995
|
+
continue;
|
|
19996
|
+
}
|
|
19997
|
+
const parents = await this.git.getCommitParents(commit.sha);
|
|
19998
|
+
if (parents.length > 1) {
|
|
19999
|
+
continue;
|
|
20000
|
+
}
|
|
20001
|
+
if (lock.patches.find((p) => p.original_commit === commit.sha)) {
|
|
20002
|
+
continue;
|
|
20003
|
+
}
|
|
20004
|
+
const patchContent = await this.git.formatPatch(commit.sha);
|
|
20005
|
+
const contentHash = this.computeContentHash(patchContent);
|
|
20006
|
+
if (lock.patches.find((p) => p.content_hash === contentHash)) {
|
|
20007
|
+
continue;
|
|
20008
|
+
}
|
|
20009
|
+
const filesOutput = await this.git.exec(["diff-tree", "--no-commit-id", "--name-only", "-r", commit.sha]);
|
|
20010
|
+
const files = filesOutput.trim().split("\n").filter(Boolean).filter((f) => !INFRASTRUCTURE_FILES.has(f));
|
|
20011
|
+
if (files.length === 0) {
|
|
20012
|
+
continue;
|
|
20013
|
+
}
|
|
20014
|
+
newPatches.push({
|
|
20015
|
+
id: `patch-${commit.sha.slice(0, 8)}`,
|
|
20016
|
+
content_hash: contentHash,
|
|
20017
|
+
original_commit: commit.sha,
|
|
20018
|
+
original_message: commit.message,
|
|
20019
|
+
original_author: `${commit.authorName} <${commit.authorEmail}>`,
|
|
20020
|
+
base_generation: lastGen.commit_sha,
|
|
20021
|
+
files,
|
|
20022
|
+
patch_content: patchContent
|
|
20023
|
+
});
|
|
20024
|
+
}
|
|
20025
|
+
return newPatches.reverse();
|
|
20026
|
+
}
|
|
20027
|
+
/**
|
|
20028
|
+
* Compute content hash for deduplication.
|
|
20029
|
+
* Removes commit SHA line and index lines before hashing,
|
|
20030
|
+
* so rebased commits with same content produce the same hash.
|
|
20031
|
+
*/
|
|
20032
|
+
computeContentHash(patchContent) {
|
|
20033
|
+
const normalized = patchContent.split("\n").filter((line) => !line.startsWith("From ") && !line.startsWith("index ") && !line.startsWith("Date: ")).join("\n");
|
|
20034
|
+
return `sha256:${(0, import_crypto.createHash)("sha256").update(normalized).digest("hex")}`;
|
|
20035
|
+
}
|
|
20036
|
+
/** Detect patches via tree diff for non-linear history. Returns a composite patch. */
|
|
20037
|
+
async detectPatchesViaTreeDiff(lastGen) {
|
|
20038
|
+
const filesOutput = await this.git.exec(["diff", "--name-only", lastGen.commit_sha, "HEAD"]);
|
|
20039
|
+
const files = filesOutput.trim().split("\n").filter(Boolean).filter((f) => !INFRASTRUCTURE_FILES.has(f)).filter((f) => !f.startsWith(".fern/"));
|
|
20040
|
+
if (files.length === 0) return [];
|
|
20041
|
+
const diff = await this.git.exec(["diff", lastGen.commit_sha, "HEAD", "--", ...files]);
|
|
20042
|
+
if (!diff.trim()) return [];
|
|
20043
|
+
const contentHash = this.computeContentHash(diff);
|
|
20044
|
+
const lock = this.lockManager.read();
|
|
20045
|
+
if (lock.patches.some((p) => p.content_hash === contentHash)) {
|
|
20046
|
+
return [];
|
|
20047
|
+
}
|
|
20048
|
+
const headSha = (await this.git.exec(["rev-parse", "HEAD"])).trim();
|
|
20049
|
+
return [
|
|
20050
|
+
{
|
|
20051
|
+
id: `patch-composite-${headSha.slice(0, 8)}`,
|
|
20052
|
+
content_hash: contentHash,
|
|
20053
|
+
original_commit: headSha,
|
|
20054
|
+
original_message: "Customer customizations (composite)",
|
|
20055
|
+
original_author: "composite",
|
|
20056
|
+
base_generation: lastGen.commit_sha,
|
|
20057
|
+
files,
|
|
20058
|
+
patch_content: diff
|
|
20059
|
+
}
|
|
20060
|
+
];
|
|
20061
|
+
}
|
|
20062
|
+
parseGitLog(log) {
|
|
20063
|
+
return log.trim().split("\n").map((line) => {
|
|
20064
|
+
const [sha, authorName, authorEmail, message] = line.split("\0");
|
|
20065
|
+
return { sha, authorName, authorEmail, message };
|
|
20066
|
+
});
|
|
20067
|
+
}
|
|
20068
|
+
getLastGeneration(lock) {
|
|
20069
|
+
return lock.generations.find((g) => g.commit_sha === lock.current_generation);
|
|
20070
|
+
}
|
|
20071
|
+
};
|
|
20072
|
+
BINARY_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
20073
|
+
".png",
|
|
20074
|
+
".jpg",
|
|
20075
|
+
".jpeg",
|
|
20076
|
+
".gif",
|
|
20077
|
+
".bmp",
|
|
20078
|
+
".ico",
|
|
20079
|
+
".webp",
|
|
20080
|
+
".svg",
|
|
20081
|
+
".pdf",
|
|
20082
|
+
".doc",
|
|
20083
|
+
".docx",
|
|
20084
|
+
".xls",
|
|
20085
|
+
".xlsx",
|
|
20086
|
+
".ppt",
|
|
20087
|
+
".pptx",
|
|
20088
|
+
".zip",
|
|
20089
|
+
".gz",
|
|
20090
|
+
".tar",
|
|
20091
|
+
".bz2",
|
|
20092
|
+
".7z",
|
|
20093
|
+
".rar",
|
|
20094
|
+
".jar",
|
|
19808
20095
|
".war",
|
|
19809
20096
|
".ear",
|
|
19810
20097
|
".class",
|
|
@@ -19869,9 +20156,8 @@ var init_ReplayApplicator = __esm({
|
|
|
19869
20156
|
}
|
|
19870
20157
|
/** Populate accumulator after git apply succeeds. */
|
|
19871
20158
|
async populateAccumulatorForPatch(patch, baseGen, currentTreeHash) {
|
|
19872
|
-
if (!baseGen)
|
|
19873
|
-
|
|
19874
|
-
const tempDir = await (0, import_promises4.mkdtemp)((0, import_node_path3.join)((0, import_node_os.tmpdir)(), "replay-acc-"));
|
|
20159
|
+
if (!baseGen) return;
|
|
20160
|
+
const tempDir = await (0, import_promises4.mkdtemp)((0, import_path9.join)((0, import_os.tmpdir)(), "replay-acc-"));
|
|
19875
20161
|
const { GitClient: GitClient2 } = await Promise.resolve().then(() => (init_GitClient(), GitClient_exports));
|
|
19876
20162
|
const tempGit = new GitClient2(tempDir);
|
|
19877
20163
|
await tempGit.exec(["init"]);
|
|
@@ -19879,8 +20165,7 @@ var init_ReplayApplicator = __esm({
|
|
|
19879
20165
|
await tempGit.exec(["config", "user.name", "Fern Replay"]);
|
|
19880
20166
|
try {
|
|
19881
20167
|
for (const filePath of patch.files) {
|
|
19882
|
-
if (isBinaryFile(filePath))
|
|
19883
|
-
continue;
|
|
20168
|
+
if (isBinaryFile(filePath)) continue;
|
|
19884
20169
|
const resolvedPath = await this.resolveFilePath(filePath, baseGen.tree_hash, currentTreeHash);
|
|
19885
20170
|
const base = await this.git.showFile(baseGen.tree_hash, filePath);
|
|
19886
20171
|
const theirs = await this.applyPatchToContent(base, patch.patch_content, filePath, tempGit, tempDir);
|
|
@@ -19901,12 +20186,13 @@ var init_ReplayApplicator = __esm({
|
|
|
19901
20186
|
const lock = this.lockManager.read();
|
|
19902
20187
|
const currentGen = lock.generations.find((g) => g.commit_sha === lock.current_generation);
|
|
19903
20188
|
const currentTreeHash = currentGen?.tree_hash ?? baseGen?.tree_hash ?? "";
|
|
19904
|
-
const needsAccumulation = await Promise.all(
|
|
19905
|
-
|
|
19906
|
-
return false;
|
|
19907
|
-
|
|
19908
|
-
|
|
19909
|
-
|
|
20189
|
+
const needsAccumulation = await Promise.all(
|
|
20190
|
+
patch.files.map(async (f) => {
|
|
20191
|
+
if (!baseGen) return false;
|
|
20192
|
+
const resolved = await this.resolveFilePath(f, baseGen.tree_hash, currentTreeHash);
|
|
20193
|
+
return this.fileTheirsAccumulator.has(resolved);
|
|
20194
|
+
})
|
|
20195
|
+
).then((results) => results.some(Boolean));
|
|
19910
20196
|
if (!needsAccumulation) {
|
|
19911
20197
|
const snapshots = /* @__PURE__ */ new Map();
|
|
19912
20198
|
const resolvedFiles = {};
|
|
@@ -19915,7 +20201,7 @@ var init_ReplayApplicator = __esm({
|
|
|
19915
20201
|
if (resolvedPath !== filePath) {
|
|
19916
20202
|
resolvedFiles[filePath] = resolvedPath;
|
|
19917
20203
|
}
|
|
19918
|
-
const fullPath = (0,
|
|
20204
|
+
const fullPath = (0, import_path9.join)(this.outputDir, resolvedPath);
|
|
19919
20205
|
snapshots.set(resolvedPath, await (0, import_promises4.readFile)(fullPath, "utf-8").catch(() => null));
|
|
19920
20206
|
}
|
|
19921
20207
|
try {
|
|
@@ -19930,7 +20216,7 @@ var init_ReplayApplicator = __esm({
|
|
|
19930
20216
|
} catch {
|
|
19931
20217
|
for (const [resolvedPath, content] of snapshots) {
|
|
19932
20218
|
if (content != null) {
|
|
19933
|
-
await (0, import_promises4.writeFile)((0,
|
|
20219
|
+
await (0, import_promises4.writeFile)((0, import_path9.join)(this.outputDir, resolvedPath), content);
|
|
19934
20220
|
}
|
|
19935
20221
|
}
|
|
19936
20222
|
}
|
|
@@ -19940,7 +20226,7 @@ var init_ReplayApplicator = __esm({
|
|
|
19940
20226
|
async applyWithThreeWayMerge(patch) {
|
|
19941
20227
|
const fileResults = [];
|
|
19942
20228
|
const resolvedFiles = {};
|
|
19943
|
-
const tempDir = await (0, import_promises4.mkdtemp)((0,
|
|
20229
|
+
const tempDir = await (0, import_promises4.mkdtemp)((0, import_path9.join)((0, import_os.tmpdir)(), "replay-"));
|
|
19944
20230
|
const { GitClient: GitClient2 } = await Promise.resolve().then(() => (init_GitClient(), GitClient_exports));
|
|
19945
20231
|
const tempGit = new GitClient2(tempDir);
|
|
19946
20232
|
await tempGit.exec(["init"]);
|
|
@@ -20003,13 +20289,26 @@ var init_ReplayApplicator = __esm({
|
|
|
20003
20289
|
renameSourcePath = renameSource;
|
|
20004
20290
|
}
|
|
20005
20291
|
}
|
|
20006
|
-
const oursPath = (0,
|
|
20292
|
+
const oursPath = (0, import_path9.join)(this.outputDir, resolvedPath);
|
|
20007
20293
|
const ours = await (0, import_promises4.readFile)(oursPath, "utf-8").catch(() => null);
|
|
20008
|
-
let theirs = await this.applyPatchToContent(
|
|
20294
|
+
let theirs = await this.applyPatchToContent(
|
|
20295
|
+
base,
|
|
20296
|
+
patch.patch_content,
|
|
20297
|
+
filePath,
|
|
20298
|
+
tempGit,
|
|
20299
|
+
tempDir,
|
|
20300
|
+
renameSourcePath
|
|
20301
|
+
);
|
|
20009
20302
|
let useAccumulatorAsMergeBase = false;
|
|
20010
20303
|
const accumulatorEntry = this.fileTheirsAccumulator.get(resolvedPath);
|
|
20011
20304
|
if (!theirs && base && accumulatorEntry) {
|
|
20012
|
-
theirs = await this.applyPatchToContent(
|
|
20305
|
+
theirs = await this.applyPatchToContent(
|
|
20306
|
+
accumulatorEntry.content,
|
|
20307
|
+
patch.patch_content,
|
|
20308
|
+
filePath,
|
|
20309
|
+
tempGit,
|
|
20310
|
+
tempDir
|
|
20311
|
+
);
|
|
20013
20312
|
if (theirs) {
|
|
20014
20313
|
useAccumulatorAsMergeBase = true;
|
|
20015
20314
|
}
|
|
@@ -20033,14 +20332,14 @@ var init_ReplayApplicator = __esm({
|
|
|
20033
20332
|
}
|
|
20034
20333
|
}
|
|
20035
20334
|
if (!base && !ours && effective_theirs) {
|
|
20036
|
-
const outDir2 = (0,
|
|
20335
|
+
const outDir2 = (0, import_path9.dirname)(oursPath);
|
|
20037
20336
|
await (0, import_promises4.mkdir)(outDir2, { recursive: true });
|
|
20038
20337
|
await (0, import_promises4.writeFile)(oursPath, effective_theirs);
|
|
20039
20338
|
return { file: resolvedPath, status: "merged", reason: "new-file" };
|
|
20040
20339
|
}
|
|
20041
20340
|
if (!base && ours && effective_theirs) {
|
|
20042
20341
|
const merged2 = threeWayMerge("", ours, effective_theirs);
|
|
20043
|
-
const outDir2 = (0,
|
|
20342
|
+
const outDir2 = (0, import_path9.dirname)(oursPath);
|
|
20044
20343
|
await (0, import_promises4.mkdir)(outDir2, { recursive: true });
|
|
20045
20344
|
await (0, import_promises4.writeFile)(oursPath, merged2.content);
|
|
20046
20345
|
if (merged2.hasConflicts) {
|
|
@@ -20070,7 +20369,7 @@ var init_ReplayApplicator = __esm({
|
|
|
20070
20369
|
}
|
|
20071
20370
|
const mergeBase = useAccumulatorAsMergeBase && accumulatorEntry ? accumulatorEntry.content : base;
|
|
20072
20371
|
const merged = threeWayMerge(mergeBase, ours, effective_theirs);
|
|
20073
|
-
const outDir = (0,
|
|
20372
|
+
const outDir = (0, import_path9.dirname)(oursPath);
|
|
20074
20373
|
await (0, import_promises4.mkdir)(outDir, { recursive: true });
|
|
20075
20374
|
await (0, import_promises4.writeFile)(oursPath, merged.content);
|
|
20076
20375
|
if (effective_theirs && base) {
|
|
@@ -20099,8 +20398,7 @@ var init_ReplayApplicator = __esm({
|
|
|
20099
20398
|
}
|
|
20100
20399
|
isExcluded(patch) {
|
|
20101
20400
|
const config = this.lockManager.getCustomizationsConfig();
|
|
20102
|
-
if (!config.exclude)
|
|
20103
|
-
return false;
|
|
20401
|
+
if (!config.exclude) return false;
|
|
20104
20402
|
return patch.files.some((file) => config.exclude.some((pattern) => minimatch(file, pattern)));
|
|
20105
20403
|
}
|
|
20106
20404
|
async resolveFilePath(filePath, baseTreeHash, currentTreeHash) {
|
|
@@ -20136,12 +20434,11 @@ var init_ReplayApplicator = __esm({
|
|
|
20136
20434
|
return this.extractNewFileFromPatch(patchContent, filePath);
|
|
20137
20435
|
}
|
|
20138
20436
|
const fileDiff = this.extractFileDiff(patchContent, filePath);
|
|
20139
|
-
if (!fileDiff)
|
|
20140
|
-
return null;
|
|
20437
|
+
if (!fileDiff) return null;
|
|
20141
20438
|
try {
|
|
20142
20439
|
if (sourceFilePath) {
|
|
20143
|
-
const tempSourcePath = (0,
|
|
20144
|
-
await (0, import_promises4.mkdir)((0,
|
|
20440
|
+
const tempSourcePath = (0, import_path9.join)(tempDir, sourceFilePath);
|
|
20441
|
+
await (0, import_promises4.mkdir)((0, import_path9.dirname)(tempSourcePath), { recursive: true });
|
|
20145
20442
|
await (0, import_promises4.writeFile)(tempSourcePath, base);
|
|
20146
20443
|
await tempGit.exec(["add", sourceFilePath]);
|
|
20147
20444
|
await tempGit.exec([
|
|
@@ -20151,11 +20448,11 @@ var init_ReplayApplicator = __esm({
|
|
|
20151
20448
|
"--allow-empty"
|
|
20152
20449
|
]);
|
|
20153
20450
|
await tempGit.execWithInput(["apply", "--allow-empty"], fileDiff);
|
|
20154
|
-
const tempTargetPath = (0,
|
|
20451
|
+
const tempTargetPath = (0, import_path9.join)(tempDir, filePath);
|
|
20155
20452
|
return await (0, import_promises4.readFile)(tempTargetPath, "utf-8");
|
|
20156
20453
|
}
|
|
20157
|
-
const tempFilePath = (0,
|
|
20158
|
-
await (0, import_promises4.mkdir)((0,
|
|
20454
|
+
const tempFilePath = (0, import_path9.join)(tempDir, filePath);
|
|
20455
|
+
await (0, import_promises4.mkdir)((0, import_path9.dirname)(tempFilePath), { recursive: true });
|
|
20159
20456
|
await (0, import_promises4.writeFile)(tempFilePath, base);
|
|
20160
20457
|
await tempGit.exec(["add", filePath]);
|
|
20161
20458
|
await tempGit.exec(["commit", "-m", `base for ${filePath}`, "--allow-empty"]);
|
|
@@ -20191,15 +20488,12 @@ var init_ReplayApplicator = __esm({
|
|
|
20191
20488
|
let inTargetFile = false;
|
|
20192
20489
|
for (const line of lines) {
|
|
20193
20490
|
if (line.startsWith("diff --git")) {
|
|
20194
|
-
if (inTargetFile)
|
|
20195
|
-
break;
|
|
20491
|
+
if (inTargetFile) break;
|
|
20196
20492
|
inTargetFile = isDiffLineForFile(line, targetFilePath);
|
|
20197
20493
|
continue;
|
|
20198
20494
|
}
|
|
20199
|
-
if (!inTargetFile)
|
|
20200
|
-
|
|
20201
|
-
if (line.startsWith("@@"))
|
|
20202
|
-
break;
|
|
20495
|
+
if (!inTargetFile) continue;
|
|
20496
|
+
if (line.startsWith("@@")) break;
|
|
20203
20497
|
if (line.startsWith("rename from ")) {
|
|
20204
20498
|
return line.slice("rename from ".length);
|
|
20205
20499
|
}
|
|
@@ -20214,20 +20508,17 @@ var init_ReplayApplicator = __esm({
|
|
|
20214
20508
|
let noTrailingNewline = false;
|
|
20215
20509
|
for (const line of lines) {
|
|
20216
20510
|
if (line.startsWith("diff --git")) {
|
|
20217
|
-
if (inTargetFile)
|
|
20218
|
-
break;
|
|
20511
|
+
if (inTargetFile) break;
|
|
20219
20512
|
inTargetFile = isDiffLineForFile(line, filePath);
|
|
20220
20513
|
inHunk = false;
|
|
20221
20514
|
continue;
|
|
20222
20515
|
}
|
|
20223
|
-
if (!inTargetFile)
|
|
20224
|
-
continue;
|
|
20516
|
+
if (!inTargetFile) continue;
|
|
20225
20517
|
if (line.startsWith("@@")) {
|
|
20226
20518
|
inHunk = true;
|
|
20227
20519
|
continue;
|
|
20228
20520
|
}
|
|
20229
|
-
if (!inHunk)
|
|
20230
|
-
continue;
|
|
20521
|
+
if (!inHunk) continue;
|
|
20231
20522
|
if (line === "\") {
|
|
20232
20523
|
noTrailingNewline = true;
|
|
20233
20524
|
continue;
|
|
@@ -20236,19 +20527,10 @@ var init_ReplayApplicator = __esm({
|
|
|
20236
20527
|
addedLines.push(line.slice(1));
|
|
20237
20528
|
}
|
|
20238
20529
|
}
|
|
20239
|
-
if (addedLines.length === 0)
|
|
20240
|
-
return null;
|
|
20530
|
+
if (addedLines.length === 0) return null;
|
|
20241
20531
|
return addedLines.join("\n") + (noTrailingNewline ? "" : "\n");
|
|
20242
20532
|
}
|
|
20243
20533
|
};
|
|
20244
|
-
}
|
|
20245
|
-
});
|
|
20246
|
-
|
|
20247
|
-
// ../../node_modules/.pnpm/@fern-api+replay@0.6.0/node_modules/@fern-api/replay/dist/ReplayCommitter.js
|
|
20248
|
-
var ReplayCommitter;
|
|
20249
|
-
var init_ReplayCommitter = __esm({
|
|
20250
|
-
"../../node_modules/.pnpm/@fern-api+replay@0.6.0/node_modules/@fern-api/replay/dist/ReplayCommitter.js"() {
|
|
20251
|
-
"use strict";
|
|
20252
20534
|
ReplayCommitter = class {
|
|
20253
20535
|
git;
|
|
20254
20536
|
outputDir;
|
|
@@ -20317,22 +20599,7 @@ CLI Version: ${options.cliVersion}`;
|
|
|
20317
20599
|
return this.git.getTreeHash(commitSha);
|
|
20318
20600
|
}
|
|
20319
20601
|
};
|
|
20320
|
-
}
|
|
20321
|
-
});
|
|
20322
|
-
|
|
20323
|
-
// ../../node_modules/.pnpm/@fern-api+replay@0.6.0/node_modules/@fern-api/replay/dist/ReplayService.js
|
|
20324
|
-
var import_node_fs2, import_node_path4, ReplayService;
|
|
20325
|
-
var init_ReplayService = __esm({
|
|
20326
|
-
"../../node_modules/.pnpm/@fern-api+replay@0.6.0/node_modules/@fern-api/replay/dist/ReplayService.js"() {
|
|
20327
|
-
"use strict";
|
|
20328
|
-
import_node_fs2 = require("fs");
|
|
20329
|
-
import_node_path4 = require("path");
|
|
20330
|
-
init_esm3();
|
|
20331
20602
|
init_GitClient();
|
|
20332
|
-
init_LockfileManager();
|
|
20333
|
-
init_ReplayApplicator();
|
|
20334
|
-
init_ReplayCommitter();
|
|
20335
|
-
init_ReplayDetector();
|
|
20336
20603
|
ReplayService = class {
|
|
20337
20604
|
git;
|
|
20338
20605
|
detector;
|
|
@@ -20578,7 +20845,15 @@ var init_ReplayService = __esm({
|
|
|
20578
20845
|
await this.committer.commitReplay(appliedCount, allPatches);
|
|
20579
20846
|
}
|
|
20580
20847
|
}
|
|
20581
|
-
return this.buildReport(
|
|
20848
|
+
return this.buildReport(
|
|
20849
|
+
"normal-regeneration",
|
|
20850
|
+
allPatches,
|
|
20851
|
+
results,
|
|
20852
|
+
options,
|
|
20853
|
+
warnings,
|
|
20854
|
+
rebaseCounts,
|
|
20855
|
+
preRebaseCounts
|
|
20856
|
+
);
|
|
20582
20857
|
}
|
|
20583
20858
|
/**
|
|
20584
20859
|
* Rebase cleanly applied patches so they are relative to the current generation.
|
|
@@ -20608,23 +20883,23 @@ var init_ReplayService = __esm({
|
|
|
20608
20883
|
await this.trimAbsorbedFiles(result, currentGenSha);
|
|
20609
20884
|
continue;
|
|
20610
20885
|
}
|
|
20611
|
-
if (result.status !== "applied")
|
|
20612
|
-
continue;
|
|
20886
|
+
if (result.status !== "applied") continue;
|
|
20613
20887
|
const patch = result.patch;
|
|
20614
|
-
if (patch.base_generation === currentGenSha)
|
|
20615
|
-
continue;
|
|
20888
|
+
if (patch.base_generation === currentGenSha) continue;
|
|
20616
20889
|
try {
|
|
20617
20890
|
const fernignorePatterns = this.readFernignorePatterns();
|
|
20618
|
-
const isUserOwned = await Promise.all(
|
|
20619
|
-
|
|
20620
|
-
|
|
20621
|
-
|
|
20622
|
-
|
|
20623
|
-
|
|
20624
|
-
|
|
20625
|
-
|
|
20626
|
-
|
|
20627
|
-
|
|
20891
|
+
const isUserOwned = await Promise.all(
|
|
20892
|
+
patch.files.map(async (file) => {
|
|
20893
|
+
if (file === ".fernignore") {
|
|
20894
|
+
return true;
|
|
20895
|
+
}
|
|
20896
|
+
if (fernignorePatterns.some((p) => file === p || minimatch(file, p))) {
|
|
20897
|
+
return true;
|
|
20898
|
+
}
|
|
20899
|
+
const content = await this.git.showFile(currentGenSha, file);
|
|
20900
|
+
return content === null;
|
|
20901
|
+
})
|
|
20902
|
+
);
|
|
20628
20903
|
const hasUserOwnedFiles = isUserOwned.some(Boolean);
|
|
20629
20904
|
if (hasUserOwnedFiles) {
|
|
20630
20905
|
this.lockManager.updatePatch(patch.id, {
|
|
@@ -20670,23 +20945,18 @@ var init_ReplayService = __esm({
|
|
|
20670
20945
|
*/
|
|
20671
20946
|
async trimAbsorbedFiles(result, currentGenSha) {
|
|
20672
20947
|
const cleanFiles = result.fileResults.filter((f) => f.status === "merged").map((f) => f.file);
|
|
20673
|
-
if (cleanFiles.length === 0)
|
|
20674
|
-
return;
|
|
20948
|
+
if (cleanFiles.length === 0) return;
|
|
20675
20949
|
const patch = result.patch;
|
|
20676
20950
|
const fernignorePatterns = this.readFernignorePatterns();
|
|
20677
20951
|
const generatorCleanFiles = [];
|
|
20678
20952
|
for (const file of cleanFiles) {
|
|
20679
|
-
if (file === ".fernignore")
|
|
20680
|
-
|
|
20681
|
-
if (fernignorePatterns.some((p) => file === p || minimatch(file, p)))
|
|
20682
|
-
continue;
|
|
20953
|
+
if (file === ".fernignore") continue;
|
|
20954
|
+
if (fernignorePatterns.some((p) => file === p || minimatch(file, p))) continue;
|
|
20683
20955
|
const content = await this.git.showFile(currentGenSha, file);
|
|
20684
|
-
if (content === null)
|
|
20685
|
-
continue;
|
|
20956
|
+
if (content === null) continue;
|
|
20686
20957
|
generatorCleanFiles.push(file);
|
|
20687
20958
|
}
|
|
20688
|
-
if (generatorCleanFiles.length === 0)
|
|
20689
|
-
return;
|
|
20959
|
+
if (generatorCleanFiles.length === 0) return;
|
|
20690
20960
|
const absorbedFiles = /* @__PURE__ */ new Set();
|
|
20691
20961
|
for (const file of generatorCleanFiles) {
|
|
20692
20962
|
try {
|
|
@@ -20697,11 +20967,9 @@ var init_ReplayService = __esm({
|
|
|
20697
20967
|
} catch {
|
|
20698
20968
|
}
|
|
20699
20969
|
}
|
|
20700
|
-
if (absorbedFiles.size === 0)
|
|
20701
|
-
return;
|
|
20970
|
+
if (absorbedFiles.size === 0) return;
|
|
20702
20971
|
const remainingFiles = patch.files.filter((f) => !absorbedFiles.has(f));
|
|
20703
|
-
if (remainingFiles.length === patch.files.length)
|
|
20704
|
-
return;
|
|
20972
|
+
if (remainingFiles.length === patch.files.length) return;
|
|
20705
20973
|
try {
|
|
20706
20974
|
this.lockManager.updatePatch(patch.id, { files: remainingFiles });
|
|
20707
20975
|
} catch {
|
|
@@ -20726,8 +20994,7 @@ var init_ReplayService = __esm({
|
|
|
20726
20994
|
if (patch.base_generation === currentGen) {
|
|
20727
20995
|
try {
|
|
20728
20996
|
const diff = await this.git.exec(["diff", currentGen, "HEAD", "--", ...patch.files]).catch(() => null);
|
|
20729
|
-
if (diff === null)
|
|
20730
|
-
continue;
|
|
20997
|
+
if (diff === null) continue;
|
|
20731
20998
|
if (!diff.trim()) {
|
|
20732
20999
|
this.lockManager.removePatch(patch.id);
|
|
20733
21000
|
contentRefreshed++;
|
|
@@ -20754,11 +21021,9 @@ var init_ReplayService = __esm({
|
|
|
20754
21021
|
}
|
|
20755
21022
|
try {
|
|
20756
21023
|
const markerFiles = await this.git.exec(["grep", "-l", "<<<<<<<", "HEAD", "--", ...patch.files]).catch(() => "");
|
|
20757
|
-
if (markerFiles.trim())
|
|
20758
|
-
continue;
|
|
21024
|
+
if (markerFiles.trim()) continue;
|
|
20759
21025
|
const diff = await this.git.exec(["diff", currentGen, "HEAD", "--", ...patch.files]).catch(() => null);
|
|
20760
|
-
if (diff === null)
|
|
20761
|
-
continue;
|
|
21026
|
+
if (diff === null) continue;
|
|
20762
21027
|
if (!diff.trim()) {
|
|
20763
21028
|
this.lockManager.removePatch(patch.id);
|
|
20764
21029
|
conflictAbsorbed++;
|
|
@@ -20777,10 +21042,9 @@ var init_ReplayService = __esm({
|
|
|
20777
21042
|
return { conflictResolved, conflictAbsorbed, contentRefreshed };
|
|
20778
21043
|
}
|
|
20779
21044
|
readFernignorePatterns() {
|
|
20780
|
-
const fernignorePath = (0,
|
|
20781
|
-
if (!(0,
|
|
20782
|
-
|
|
20783
|
-
return (0, import_node_fs2.readFileSync)(fernignorePath, "utf-8").split("\n").map((line) => line.trim()).filter((line) => line && !line.startsWith("#"));
|
|
21045
|
+
const fernignorePath = (0, import_path10.join)(this.outputDir, ".fernignore");
|
|
21046
|
+
if (!(0, import_fs7.existsSync)(fernignorePath)) return [];
|
|
21047
|
+
return (0, import_fs7.readFileSync)(fernignorePath, "utf-8").split("\n").map((line) => line.trim()).filter((line) => line && !line.startsWith("#"));
|
|
20784
21048
|
}
|
|
20785
21049
|
buildReport(flow, patches, results, options, warnings, rebaseCounts, preRebaseCounts) {
|
|
20786
21050
|
const conflictResults = results.filter((r) => r.status === "conflict");
|
|
@@ -20816,20 +21080,6 @@ var init_ReplayService = __esm({
|
|
|
20816
21080
|
};
|
|
20817
21081
|
}
|
|
20818
21082
|
};
|
|
20819
|
-
}
|
|
20820
|
-
});
|
|
20821
|
-
|
|
20822
|
-
// ../../node_modules/.pnpm/@fern-api+replay@0.6.0/node_modules/@fern-api/replay/dist/FernignoreMigrator.js
|
|
20823
|
-
var import_node_crypto2, import_node_fs3, import_node_path5, import_yaml2, FernignoreMigrator;
|
|
20824
|
-
var init_FernignoreMigrator = __esm({
|
|
20825
|
-
"../../node_modules/.pnpm/@fern-api+replay@0.6.0/node_modules/@fern-api/replay/dist/FernignoreMigrator.js"() {
|
|
20826
|
-
"use strict";
|
|
20827
|
-
import_node_crypto2 = require("crypto");
|
|
20828
|
-
import_node_fs3 = require("fs");
|
|
20829
|
-
import_node_path5 = require("path");
|
|
20830
|
-
init_esm3();
|
|
20831
|
-
import_yaml2 = __toESM(require_dist3(), 1);
|
|
20832
|
-
init_ReplayDetector();
|
|
20833
21083
|
FernignoreMigrator = class {
|
|
20834
21084
|
git;
|
|
20835
21085
|
lockManager;
|
|
@@ -20840,14 +21090,14 @@ var init_FernignoreMigrator = __esm({
|
|
|
20840
21090
|
this.outputDir = outputDir;
|
|
20841
21091
|
}
|
|
20842
21092
|
fernignoreExists() {
|
|
20843
|
-
return (0,
|
|
21093
|
+
return (0, import_fs8.existsSync)((0, import_path11.join)(this.outputDir, ".fernignore"));
|
|
20844
21094
|
}
|
|
20845
21095
|
readFernignorePatterns() {
|
|
20846
|
-
const fernignorePath = (0,
|
|
20847
|
-
if (!(0,
|
|
21096
|
+
const fernignorePath = (0, import_path11.join)(this.outputDir, ".fernignore");
|
|
21097
|
+
if (!(0, import_fs8.existsSync)(fernignorePath)) {
|
|
20848
21098
|
return [];
|
|
20849
21099
|
}
|
|
20850
|
-
const content = (0,
|
|
21100
|
+
const content = (0, import_fs8.readFileSync)(fernignorePath, "utf-8");
|
|
20851
21101
|
return content.split("\n").map((line) => line.trim()).filter((line) => line && !line.startsWith("#"));
|
|
20852
21102
|
}
|
|
20853
21103
|
/** Analyze .fernignore patterns vs git history. Creates synthetic patches for files differing from pristine generation. */
|
|
@@ -20894,9 +21144,9 @@ var init_FernignoreMigrator = __esm({
|
|
|
20894
21144
|
}
|
|
20895
21145
|
if (patchFiles.length > 0) {
|
|
20896
21146
|
const patchContent = diffParts.join("\n");
|
|
20897
|
-
const contentHash = `sha256:${(0,
|
|
21147
|
+
const contentHash = `sha256:${(0, import_crypto2.createHash)("sha256").update(patchContent).digest("hex")}`;
|
|
20898
21148
|
syntheticPatches.push({
|
|
20899
|
-
id: `patch-fernignore-${(0,
|
|
21149
|
+
id: `patch-fernignore-${(0, import_crypto2.createHash)("sha256").update(pattern).digest("hex").slice(0, 8)}`,
|
|
20900
21150
|
content_hash: contentHash,
|
|
20901
21151
|
original_commit: currentGen.commit_sha,
|
|
20902
21152
|
original_message: `[fernignore-migration] Customizations for ${pattern}`,
|
|
@@ -20928,22 +21178,24 @@ var init_FernignoreMigrator = __esm({
|
|
|
20928
21178
|
const allFiles = (await this.git.exec(["ls-files"])).trim().split("\n").filter(Boolean);
|
|
20929
21179
|
const results = [];
|
|
20930
21180
|
for (const pattern of patterns) {
|
|
20931
|
-
const matching = allFiles.filter(
|
|
21181
|
+
const matching = allFiles.filter(
|
|
21182
|
+
(f) => minimatch(f, pattern) || f === pattern || f.startsWith(pattern + "/")
|
|
21183
|
+
);
|
|
20932
21184
|
results.push({ pattern, files: matching.length > 0 ? matching : [pattern] });
|
|
20933
21185
|
}
|
|
20934
21186
|
return results;
|
|
20935
21187
|
}
|
|
20936
21188
|
readFileContent(filePath) {
|
|
20937
|
-
const fullPath = (0,
|
|
20938
|
-
if (!(0,
|
|
21189
|
+
const fullPath = (0, import_path11.join)(this.outputDir, filePath);
|
|
21190
|
+
if (!(0, import_fs8.existsSync)(fullPath)) {
|
|
20939
21191
|
return null;
|
|
20940
21192
|
}
|
|
20941
21193
|
try {
|
|
20942
|
-
const stat = (0,
|
|
21194
|
+
const stat = (0, import_fs8.statSync)(fullPath);
|
|
20943
21195
|
if (stat.isDirectory()) {
|
|
20944
21196
|
return null;
|
|
20945
21197
|
}
|
|
20946
|
-
return (0,
|
|
21198
|
+
return (0, import_fs8.readFileSync)(fullPath, "utf-8");
|
|
20947
21199
|
} catch {
|
|
20948
21200
|
return null;
|
|
20949
21201
|
}
|
|
@@ -20981,421 +21233,43 @@ var init_FernignoreMigrator = __esm({
|
|
|
20981
21233
|
const warnings = [];
|
|
20982
21234
|
let patchesCreated = 0;
|
|
20983
21235
|
for (const patch of patches) {
|
|
20984
|
-
this.lockManager.addPatch(patch);
|
|
20985
|
-
patchesCreated++;
|
|
20986
|
-
}
|
|
20987
|
-
if (patchesCreated > 0) {
|
|
20988
|
-
this.lockManager.save();
|
|
20989
|
-
}
|
|
20990
|
-
for (const file of analysis.fernignoreOnly) {
|
|
20991
|
-
warnings.push(
|
|
20992
|
-
|
|
20993
|
-
|
|
20994
|
-
|
|
20995
|
-
|
|
20996
|
-
|
|
20997
|
-
|
|
20998
|
-
|
|
20999
|
-
|
|
21000
|
-
|
|
21001
|
-
|
|
21002
|
-
|
|
21003
|
-
|
|
21004
|
-
|
|
21005
|
-
|
|
21006
|
-
|
|
21007
|
-
|
|
21008
|
-
config.exclude
|
|
21009
|
-
const
|
|
21010
|
-
|
|
21011
|
-
|
|
21012
|
-
|
|
21013
|
-
|
|
21014
|
-
|
|
21015
|
-
|
|
21016
|
-
}
|
|
21017
|
-
});
|
|
21018
|
-
|
|
21019
|
-
// ../../node_modules/.pnpm/@fern-api+replay@0.6.0/node_modules/@fern-api/replay/dist/commands/bootstrap.js
|
|
21020
|
-
async function bootstrap(outputDir, options) {
|
|
21021
|
-
const git = new GitClient(outputDir);
|
|
21022
|
-
const lockManager = new LockfileManager(outputDir);
|
|
21023
|
-
const maxCommits = options?.maxCommitsToScan ?? 500;
|
|
21024
|
-
const warnings = [];
|
|
21025
|
-
if (lockManager.exists() && !options?.force) {
|
|
21026
|
-
return {
|
|
21027
|
-
generationCommit: null,
|
|
21028
|
-
patchesDetected: 0,
|
|
21029
|
-
patchesCreated: 0,
|
|
21030
|
-
patches: [],
|
|
21031
|
-
fernignorePatterns: [],
|
|
21032
|
-
fernignoreUpdated: false,
|
|
21033
|
-
warnings: ["Replay lockfile already exists. Use --force to overwrite."],
|
|
21034
|
-
staleGenerationsSkipped: 0,
|
|
21035
|
-
scannedSinceGeneration: ""
|
|
21036
|
-
};
|
|
21037
|
-
}
|
|
21038
|
-
const genCommits = await findAllGenerationCommits(git, maxCommits);
|
|
21039
|
-
if (genCommits.length === 0) {
|
|
21040
|
-
return {
|
|
21041
|
-
generationCommit: null,
|
|
21042
|
-
patchesDetected: 0,
|
|
21043
|
-
patchesCreated: 0,
|
|
21044
|
-
patches: [],
|
|
21045
|
-
fernignorePatterns: [],
|
|
21046
|
-
fernignoreUpdated: false,
|
|
21047
|
-
warnings: [
|
|
21048
|
-
"No generation commits found in the last " + maxCommits + " commits. Run 'fern generate' first to establish a baseline."
|
|
21049
|
-
],
|
|
21050
|
-
staleGenerationsSkipped: 0,
|
|
21051
|
-
scannedSinceGeneration: ""
|
|
21052
|
-
};
|
|
21053
|
-
}
|
|
21054
|
-
const latestGen = genCommits[0];
|
|
21055
|
-
const anchorSha = options?.importHistory ? latestGen.sha : (await git.exec(["rev-parse", "HEAD"])).trim();
|
|
21056
|
-
const treeHash = await git.getTreeHash(anchorSha);
|
|
21057
|
-
const genRecord = {
|
|
21058
|
-
commit_sha: anchorSha,
|
|
21059
|
-
tree_hash: treeHash,
|
|
21060
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
21061
|
-
cli_version: "unknown",
|
|
21062
|
-
generator_versions: {}
|
|
21063
|
-
};
|
|
21064
|
-
lockManager.initializeInMemory(genRecord);
|
|
21065
|
-
const patches = options?.importHistory ? await findAllUserPatches(git, genCommits) : [];
|
|
21066
|
-
const migrator = new FernignoreMigrator(git, lockManager, outputDir);
|
|
21067
|
-
const fernignorePatterns = migrator.readFernignorePatterns();
|
|
21068
|
-
let fernignoreAnalysis;
|
|
21069
|
-
if (options?.importHistory && migrator.fernignoreExists() && fernignorePatterns.length > 0) {
|
|
21070
|
-
fernignoreAnalysis = await migrator.analyzeMigration();
|
|
21071
|
-
if (fernignoreAnalysis.syntheticPatches.length > 0) {
|
|
21072
|
-
patches.push(...fernignoreAnalysis.syntheticPatches);
|
|
21073
|
-
}
|
|
21074
|
-
if (fernignoreAnalysis.fernignoreOnly.length > 0) {
|
|
21075
|
-
for (const file of fernignoreAnalysis.fernignoreOnly) {
|
|
21076
|
-
warnings.push(`${file}: in .fernignore but no recent commits found since last generation. File may be stale, matches generated output, or does not exist. No customization to track.`);
|
|
21077
|
-
}
|
|
21078
|
-
}
|
|
21079
|
-
}
|
|
21080
|
-
if (options?.dryRun) {
|
|
21081
|
-
return {
|
|
21082
|
-
generationCommit: latestGen,
|
|
21083
|
-
patchesDetected: patches.length,
|
|
21084
|
-
patchesCreated: 0,
|
|
21085
|
-
patches,
|
|
21086
|
-
fernignorePatterns,
|
|
21087
|
-
fernignoreAnalysis,
|
|
21088
|
-
fernignoreUpdated: false,
|
|
21089
|
-
warnings,
|
|
21090
|
-
staleGenerationsSkipped: genCommits.length - 1,
|
|
21091
|
-
scannedSinceGeneration: latestGen.sha
|
|
21092
|
-
};
|
|
21093
|
-
}
|
|
21094
|
-
for (const patch of patches) {
|
|
21095
|
-
lockManager.addPatch(patch);
|
|
21096
|
-
}
|
|
21097
|
-
lockManager.save();
|
|
21098
|
-
const fernignoreUpdated = ensureFernignoreEntries(outputDir);
|
|
21099
|
-
if (migrator.fernignoreExists() && fernignorePatterns.length > 0) {
|
|
21100
|
-
const action = options?.fernignoreAction ?? "skip";
|
|
21101
|
-
if (action === "migrate") {
|
|
21102
|
-
const patternsToExclude = fernignoreAnalysis?.fernignoreOnly ?? [];
|
|
21103
|
-
if (patternsToExclude.length > 0) {
|
|
21104
|
-
migrator.movePatternsToReplayYml(patternsToExclude);
|
|
21236
|
+
this.lockManager.addPatch(patch);
|
|
21237
|
+
patchesCreated++;
|
|
21238
|
+
}
|
|
21239
|
+
if (patchesCreated > 0) {
|
|
21240
|
+
this.lockManager.save();
|
|
21241
|
+
}
|
|
21242
|
+
for (const file of analysis.fernignoreOnly) {
|
|
21243
|
+
warnings.push(
|
|
21244
|
+
`${file}: in .fernignore but no commit history found. Commit this file or keep in .fernignore as fallback.`
|
|
21245
|
+
);
|
|
21246
|
+
}
|
|
21247
|
+
return {
|
|
21248
|
+
patchesCreated,
|
|
21249
|
+
filesSkipped: analysis.fernignoreOnly,
|
|
21250
|
+
warnings
|
|
21251
|
+
};
|
|
21252
|
+
}
|
|
21253
|
+
movePatternsToReplayYml(patterns) {
|
|
21254
|
+
const replayYmlPath = (0, import_path11.join)(this.outputDir, ".fern", "replay.yml");
|
|
21255
|
+
let config = {};
|
|
21256
|
+
if ((0, import_fs8.existsSync)(replayYmlPath)) {
|
|
21257
|
+
const content = (0, import_fs8.readFileSync)(replayYmlPath, "utf-8");
|
|
21258
|
+
config = (0, import_yaml2.parse)(content) ?? {};
|
|
21259
|
+
}
|
|
21260
|
+
const existing = config.exclude ?? [];
|
|
21261
|
+
const merged = [.../* @__PURE__ */ new Set([...existing, ...patterns])];
|
|
21262
|
+
config.exclude = merged;
|
|
21263
|
+
const dir = (0, import_path11.dirname)(replayYmlPath);
|
|
21264
|
+
if (!(0, import_fs8.existsSync)(dir)) {
|
|
21265
|
+
(0, import_fs8.mkdirSync)(dir, { recursive: true });
|
|
21266
|
+
}
|
|
21267
|
+
(0, import_fs8.writeFileSync)(replayYmlPath, (0, import_yaml2.stringify)(config, { lineWidth: 0 }), "utf-8");
|
|
21105
21268
|
}
|
|
21106
|
-
}
|
|
21107
|
-
}
|
|
21108
|
-
return {
|
|
21109
|
-
generationCommit: latestGen,
|
|
21110
|
-
patchesDetected: patches.length,
|
|
21111
|
-
patchesCreated: patches.length,
|
|
21112
|
-
patches,
|
|
21113
|
-
fernignorePatterns,
|
|
21114
|
-
fernignoreAnalysis,
|
|
21115
|
-
fernignoreUpdated,
|
|
21116
|
-
warnings,
|
|
21117
|
-
staleGenerationsSkipped: genCommits.length - 1,
|
|
21118
|
-
scannedSinceGeneration: latestGen.sha
|
|
21119
|
-
};
|
|
21120
|
-
}
|
|
21121
|
-
async function findAllGenerationCommits(git, maxCommits) {
|
|
21122
|
-
const log = await git.exec(["log", "--format=%H%x00%an%x00%ae%x00%s", `-${maxCommits}`]);
|
|
21123
|
-
if (!log.trim()) {
|
|
21124
|
-
return [];
|
|
21125
|
-
}
|
|
21126
|
-
const genCommits = [];
|
|
21127
|
-
for (const line of log.trim().split("\n")) {
|
|
21128
|
-
if (!line)
|
|
21129
|
-
continue;
|
|
21130
|
-
const [sha, authorName, authorEmail, message] = line.split("\0");
|
|
21131
|
-
const commit = { sha, authorName, authorEmail, message };
|
|
21132
|
-
if (isGenerationCommit(commit) && !isReplayCommit(commit)) {
|
|
21133
|
-
genCommits.push(commit);
|
|
21134
|
-
}
|
|
21135
|
-
}
|
|
21136
|
-
return genCommits;
|
|
21137
|
-
}
|
|
21138
|
-
async function findAllUserPatches(git, genCommits) {
|
|
21139
|
-
const patches = [];
|
|
21140
|
-
const seenHashes = /* @__PURE__ */ new Set();
|
|
21141
|
-
const latestGen = genCommits[0];
|
|
21142
|
-
const recentPatches = await extractUserPatches(git, latestGen.sha, "HEAD", latestGen.sha, seenHashes);
|
|
21143
|
-
patches.push(...recentPatches);
|
|
21144
|
-
return patches;
|
|
21145
|
-
}
|
|
21146
|
-
async function extractUserPatches(git, fromSha, toRef, baseGeneration, seenHashes) {
|
|
21147
|
-
const log = await git.exec(["log", "--format=%H%x00%an%x00%ae%x00%s", `${fromSha}..${toRef}`]);
|
|
21148
|
-
if (!log.trim()) {
|
|
21149
|
-
return [];
|
|
21150
|
-
}
|
|
21151
|
-
const commits = parseGitLog(log);
|
|
21152
|
-
const patches = [];
|
|
21153
|
-
for (const commit of commits.reverse()) {
|
|
21154
|
-
if (isGenerationCommit(commit))
|
|
21155
|
-
continue;
|
|
21156
|
-
const parents = await git.getCommitParents(commit.sha);
|
|
21157
|
-
if (parents.length > 1)
|
|
21158
|
-
continue;
|
|
21159
|
-
const patchContent = await git.formatPatch(commit.sha);
|
|
21160
|
-
const contentHash = computeContentHash(patchContent);
|
|
21161
|
-
if (seenHashes.has(contentHash))
|
|
21162
|
-
continue;
|
|
21163
|
-
seenHashes.add(contentHash);
|
|
21164
|
-
const filesOutput = await git.exec(["diff-tree", "--no-commit-id", "--name-only", "-r", commit.sha]);
|
|
21165
|
-
patches.push({
|
|
21166
|
-
id: `patch-${commit.sha.slice(0, 8)}`,
|
|
21167
|
-
content_hash: contentHash,
|
|
21168
|
-
original_commit: commit.sha,
|
|
21169
|
-
original_message: commit.message,
|
|
21170
|
-
original_author: `${commit.authorName} <${commit.authorEmail}>`,
|
|
21171
|
-
base_generation: baseGeneration,
|
|
21172
|
-
files: filesOutput.trim().split("\n").filter(Boolean),
|
|
21173
|
-
patch_content: patchContent
|
|
21174
|
-
});
|
|
21175
|
-
}
|
|
21176
|
-
return patches;
|
|
21177
|
-
}
|
|
21178
|
-
function parseGitLog(log) {
|
|
21179
|
-
return log.trim().split("\n").filter(Boolean).map((line) => {
|
|
21180
|
-
const [sha, authorName, authorEmail, message] = line.split("\0");
|
|
21181
|
-
return { sha, authorName, authorEmail, message };
|
|
21182
|
-
});
|
|
21183
|
-
}
|
|
21184
|
-
function ensureFernignoreEntries(outputDir) {
|
|
21185
|
-
const fernignorePath = (0, import_node_path6.join)(outputDir, ".fernignore");
|
|
21186
|
-
let content = "";
|
|
21187
|
-
if ((0, import_node_fs4.existsSync)(fernignorePath)) {
|
|
21188
|
-
content = (0, import_node_fs4.readFileSync)(fernignorePath, "utf-8");
|
|
21189
|
-
}
|
|
21190
|
-
const lines = content.split("\n");
|
|
21191
|
-
const toAdd = [];
|
|
21192
|
-
for (const entry of REPLAY_FERNIGNORE_ENTRIES) {
|
|
21193
|
-
if (!lines.some((line) => line.trim() === entry)) {
|
|
21194
|
-
toAdd.push(entry);
|
|
21195
|
-
}
|
|
21196
|
-
}
|
|
21197
|
-
if (toAdd.length === 0) {
|
|
21198
|
-
return false;
|
|
21199
|
-
}
|
|
21200
|
-
if (content && !content.endsWith("\n")) {
|
|
21201
|
-
content += "\n";
|
|
21202
|
-
}
|
|
21203
|
-
content += toAdd.join("\n") + "\n";
|
|
21204
|
-
(0, import_node_fs4.writeFileSync)(fernignorePath, content, "utf-8");
|
|
21205
|
-
return true;
|
|
21206
|
-
}
|
|
21207
|
-
function computeContentHash(patchContent) {
|
|
21208
|
-
const normalized = patchContent.split("\n").filter((line) => !line.startsWith("From ") && !line.startsWith("index ") && !line.startsWith("Date: ")).join("\n");
|
|
21209
|
-
return `sha256:${(0, import_node_crypto3.createHash)("sha256").update(normalized).digest("hex")}`;
|
|
21210
|
-
}
|
|
21211
|
-
var import_node_crypto3, import_node_fs4, import_node_path6, REPLAY_FERNIGNORE_ENTRIES;
|
|
21212
|
-
var init_bootstrap = __esm({
|
|
21213
|
-
"../../node_modules/.pnpm/@fern-api+replay@0.6.0/node_modules/@fern-api/replay/dist/commands/bootstrap.js"() {
|
|
21214
|
-
"use strict";
|
|
21215
|
-
import_node_crypto3 = require("crypto");
|
|
21216
|
-
import_node_fs4 = require("fs");
|
|
21217
|
-
import_node_path6 = require("path");
|
|
21218
|
-
init_FernignoreMigrator();
|
|
21219
|
-
init_CommitDetection();
|
|
21220
|
-
init_GitClient();
|
|
21221
|
-
init_LockfileManager();
|
|
21222
|
-
REPLAY_FERNIGNORE_ENTRIES = [".fern/replay.lock", ".fern/replay.yml"];
|
|
21223
|
-
}
|
|
21224
|
-
});
|
|
21225
|
-
|
|
21226
|
-
// ../../node_modules/.pnpm/@fern-api+replay@0.6.0/node_modules/@fern-api/replay/dist/commands/forget.js
|
|
21227
|
-
function forget(outputDir, filePattern, options) {
|
|
21228
|
-
const lockManager = new LockfileManager(outputDir);
|
|
21229
|
-
if (!lockManager.exists()) {
|
|
21230
|
-
return { removed: [], notFound: true };
|
|
21231
|
-
}
|
|
21232
|
-
const lock = lockManager.read();
|
|
21233
|
-
const matchingPatches = lock.patches.filter((patch) => patch.files.some((file) => file === filePattern || minimatch(file, filePattern)));
|
|
21234
|
-
if (matchingPatches.length === 0) {
|
|
21235
|
-
return { removed: [], notFound: true };
|
|
21236
|
-
}
|
|
21237
|
-
const removed = matchingPatches.map((p) => ({
|
|
21238
|
-
id: p.id,
|
|
21239
|
-
message: p.original_message,
|
|
21240
|
-
files: p.files
|
|
21241
|
-
}));
|
|
21242
|
-
if (!options?.dryRun) {
|
|
21243
|
-
for (const patch of matchingPatches) {
|
|
21244
|
-
lockManager.removePatch(patch.id);
|
|
21245
|
-
}
|
|
21246
|
-
lockManager.save();
|
|
21247
|
-
}
|
|
21248
|
-
return { removed, notFound: false };
|
|
21249
|
-
}
|
|
21250
|
-
var init_forget = __esm({
|
|
21251
|
-
"../../node_modules/.pnpm/@fern-api+replay@0.6.0/node_modules/@fern-api/replay/dist/commands/forget.js"() {
|
|
21252
|
-
"use strict";
|
|
21253
|
-
init_esm3();
|
|
21254
|
-
init_LockfileManager();
|
|
21255
|
-
}
|
|
21256
|
-
});
|
|
21257
|
-
|
|
21258
|
-
// ../../node_modules/.pnpm/@fern-api+replay@0.6.0/node_modules/@fern-api/replay/dist/commands/reset.js
|
|
21259
|
-
function reset(outputDir, options) {
|
|
21260
|
-
const lockManager = new LockfileManager(outputDir);
|
|
21261
|
-
if (!lockManager.exists()) {
|
|
21262
|
-
return {
|
|
21263
|
-
success: true,
|
|
21264
|
-
patchesRemoved: 0,
|
|
21265
|
-
lockfileDeleted: false,
|
|
21266
|
-
nothingToReset: true
|
|
21267
21269
|
};
|
|
21268
|
-
}
|
|
21269
|
-
const lock = lockManager.read();
|
|
21270
|
-
const patchCount = lock.patches.length;
|
|
21271
|
-
if (!options?.dryRun) {
|
|
21272
|
-
(0, import_node_fs5.unlinkSync)(lockManager.lockfilePath);
|
|
21273
|
-
}
|
|
21274
|
-
return {
|
|
21275
|
-
success: true,
|
|
21276
|
-
patchesRemoved: patchCount,
|
|
21277
|
-
lockfileDeleted: true,
|
|
21278
|
-
nothingToReset: false
|
|
21279
|
-
};
|
|
21280
|
-
}
|
|
21281
|
-
var import_node_fs5;
|
|
21282
|
-
var init_reset2 = __esm({
|
|
21283
|
-
"../../node_modules/.pnpm/@fern-api+replay@0.6.0/node_modules/@fern-api/replay/dist/commands/reset.js"() {
|
|
21284
|
-
"use strict";
|
|
21285
|
-
import_node_fs5 = require("fs");
|
|
21286
|
-
init_LockfileManager();
|
|
21287
|
-
}
|
|
21288
|
-
});
|
|
21289
|
-
|
|
21290
|
-
// ../../node_modules/.pnpm/@fern-api+replay@0.6.0/node_modules/@fern-api/replay/dist/commands/resolve.js
|
|
21291
|
-
async function resolve7(outputDir, options) {
|
|
21292
|
-
const lockManager = new LockfileManager(outputDir);
|
|
21293
|
-
if (!lockManager.exists()) {
|
|
21294
|
-
return { success: false, reason: "no-lockfile" };
|
|
21295
|
-
}
|
|
21296
|
-
const lock = lockManager.read();
|
|
21297
|
-
if (lock.patches.length === 0) {
|
|
21298
|
-
return { success: false, reason: "no-patches" };
|
|
21299
|
-
}
|
|
21300
|
-
const git = new GitClient(outputDir);
|
|
21301
|
-
if (options?.checkMarkers !== false) {
|
|
21302
|
-
const markerFiles = await git.exec(["grep", "-l", "<<<<<<<", "--", "."]).catch(() => "");
|
|
21303
|
-
if (markerFiles.trim()) {
|
|
21304
|
-
const files = markerFiles.trim().split("\n").filter(Boolean);
|
|
21305
|
-
return { success: false, reason: "unresolved-conflicts", unresolvedFiles: files };
|
|
21306
|
-
}
|
|
21307
|
-
}
|
|
21308
|
-
const committer = new ReplayCommitter(git, outputDir);
|
|
21309
|
-
await committer.stageAll();
|
|
21310
|
-
const commitSha = await committer.commitReplay(lock.patches.length, lock.patches);
|
|
21311
|
-
return { success: true, commitSha };
|
|
21312
|
-
}
|
|
21313
|
-
var init_resolve = __esm({
|
|
21314
|
-
"../../node_modules/.pnpm/@fern-api+replay@0.6.0/node_modules/@fern-api/replay/dist/commands/resolve.js"() {
|
|
21315
|
-
"use strict";
|
|
21316
21270
|
init_GitClient();
|
|
21317
|
-
|
|
21318
|
-
init_ReplayCommitter();
|
|
21319
|
-
}
|
|
21320
|
-
});
|
|
21321
|
-
|
|
21322
|
-
// ../../node_modules/.pnpm/@fern-api+replay@0.6.0/node_modules/@fern-api/replay/dist/commands/status.js
|
|
21323
|
-
function status(outputDir) {
|
|
21324
|
-
const lockManager = new LockfileManager(outputDir);
|
|
21325
|
-
if (!lockManager.exists()) {
|
|
21326
|
-
return { initialized: false, patches: [], lastGeneration: void 0 };
|
|
21327
|
-
}
|
|
21328
|
-
const lock = lockManager.read();
|
|
21329
|
-
const patches = lock.patches.map((patch) => ({
|
|
21330
|
-
sha: patch.original_commit.slice(0, 7),
|
|
21331
|
-
author: patch.original_author.split("<")[0]?.trim() ?? "unknown",
|
|
21332
|
-
message: patch.original_message,
|
|
21333
|
-
files: patch.files
|
|
21334
|
-
}));
|
|
21335
|
-
let lastGeneration;
|
|
21336
|
-
const lastGen = lock.generations.find((g) => g.commit_sha === lock.current_generation);
|
|
21337
|
-
if (lastGen) {
|
|
21338
|
-
lastGeneration = {
|
|
21339
|
-
sha: lastGen.commit_sha,
|
|
21340
|
-
timestamp: lastGen.timestamp
|
|
21341
|
-
};
|
|
21342
|
-
}
|
|
21343
|
-
return { initialized: true, patches, lastGeneration };
|
|
21344
|
-
}
|
|
21345
|
-
var init_status2 = __esm({
|
|
21346
|
-
"../../node_modules/.pnpm/@fern-api+replay@0.6.0/node_modules/@fern-api/replay/dist/commands/status.js"() {
|
|
21347
|
-
"use strict";
|
|
21348
|
-
init_LockfileManager();
|
|
21349
|
-
}
|
|
21350
|
-
});
|
|
21351
|
-
|
|
21352
|
-
// ../../node_modules/.pnpm/@fern-api+replay@0.6.0/node_modules/@fern-api/replay/dist/commands/index.js
|
|
21353
|
-
var init_commands = __esm({
|
|
21354
|
-
"../../node_modules/.pnpm/@fern-api+replay@0.6.0/node_modules/@fern-api/replay/dist/commands/index.js"() {
|
|
21355
|
-
"use strict";
|
|
21356
|
-
init_bootstrap();
|
|
21357
|
-
init_forget();
|
|
21358
|
-
init_reset2();
|
|
21359
|
-
init_resolve();
|
|
21360
|
-
init_status2();
|
|
21361
|
-
}
|
|
21362
|
-
});
|
|
21363
|
-
|
|
21364
|
-
// ../../node_modules/.pnpm/@fern-api+replay@0.6.0/node_modules/@fern-api/replay/dist/index.js
|
|
21365
|
-
var dist_exports = {};
|
|
21366
|
-
__export(dist_exports, {
|
|
21367
|
-
FERN_BOT_EMAIL: () => FERN_BOT_EMAIL2,
|
|
21368
|
-
FERN_BOT_LOGIN: () => FERN_BOT_LOGIN2,
|
|
21369
|
-
FERN_BOT_NAME: () => FERN_BOT_NAME2,
|
|
21370
|
-
FernignoreMigrator: () => FernignoreMigrator,
|
|
21371
|
-
GitClient: () => GitClient,
|
|
21372
|
-
LockfileManager: () => LockfileManager,
|
|
21373
|
-
ReplayApplicator: () => ReplayApplicator,
|
|
21374
|
-
ReplayCommitter: () => ReplayCommitter,
|
|
21375
|
-
ReplayDetector: () => ReplayDetector,
|
|
21376
|
-
ReplayService: () => ReplayService,
|
|
21377
|
-
bootstrap: () => bootstrap,
|
|
21378
|
-
forget: () => forget,
|
|
21379
|
-
isGenerationCommit: () => isGenerationCommit,
|
|
21380
|
-
isReplayCommit: () => isReplayCommit,
|
|
21381
|
-
reset: () => reset,
|
|
21382
|
-
resolve: () => resolve7,
|
|
21383
|
-
status: () => status,
|
|
21384
|
-
threeWayMerge: () => threeWayMerge
|
|
21385
|
-
});
|
|
21386
|
-
var init_dist = __esm({
|
|
21387
|
-
"../../node_modules/.pnpm/@fern-api+replay@0.6.0/node_modules/@fern-api/replay/dist/index.js"() {
|
|
21388
|
-
"use strict";
|
|
21271
|
+
REPLAY_FERNIGNORE_ENTRIES = [".fern/replay.lock", ".fern/replay.yml"];
|
|
21389
21272
|
init_GitClient();
|
|
21390
|
-
init_CommitDetection();
|
|
21391
|
-
init_LockfileManager();
|
|
21392
|
-
init_ReplayDetector();
|
|
21393
|
-
init_ThreeWayMerge();
|
|
21394
|
-
init_ReplayApplicator();
|
|
21395
|
-
init_ReplayCommitter();
|
|
21396
|
-
init_ReplayService();
|
|
21397
|
-
init_FernignoreMigrator();
|
|
21398
|
-
init_commands();
|
|
21399
21273
|
}
|
|
21400
21274
|
});
|
|
21401
21275
|
|
|
@@ -21433,9 +21307,9 @@ function resolve(...paths) {
|
|
|
21433
21307
|
}
|
|
21434
21308
|
|
|
21435
21309
|
// src/cli.ts
|
|
21436
|
-
var
|
|
21310
|
+
var import_fs14 = __toESM(require("fs"));
|
|
21437
21311
|
var import_promises9 = require("fs/promises");
|
|
21438
|
-
var
|
|
21312
|
+
var import_path16 = __toESM(require("path"));
|
|
21439
21313
|
|
|
21440
21314
|
// ../../node_modules/.pnpm/yargs@17.7.2/node_modules/yargs/build/lib/yerror.js
|
|
21441
21315
|
var YError = class _YError extends Error {
|
|
@@ -31705,16 +31579,16 @@ function sleep(ms) {
|
|
|
31705
31579
|
// src/replay/replay-run.ts
|
|
31706
31580
|
init_dist();
|
|
31707
31581
|
var import_child_process3 = require("child_process");
|
|
31708
|
-
var
|
|
31709
|
-
var
|
|
31582
|
+
var import_fs12 = require("fs");
|
|
31583
|
+
var import_path14 = require("path");
|
|
31710
31584
|
|
|
31711
31585
|
// src/replay/fernignore.ts
|
|
31712
|
-
var
|
|
31586
|
+
var import_fs11 = require("fs");
|
|
31713
31587
|
var import_promises5 = require("fs/promises");
|
|
31714
|
-
var
|
|
31588
|
+
var import_path13 = require("path");
|
|
31715
31589
|
var REPLAY_FERNIGNORE_ENTRIES2 = [".fern/replay.lock", ".fern/replay.yml"];
|
|
31716
31590
|
async function ensureReplayFernignoreEntries(outputDir) {
|
|
31717
|
-
const fernignorePath = (0,
|
|
31591
|
+
const fernignorePath = (0, import_path13.join)(outputDir, ".fernignore");
|
|
31718
31592
|
let content = "";
|
|
31719
31593
|
try {
|
|
31720
31594
|
content = await (0, import_promises5.readFile)(fernignorePath, "utf-8");
|
|
@@ -31730,16 +31604,16 @@ async function ensureReplayFernignoreEntries(outputDir) {
|
|
|
31730
31604
|
return false;
|
|
31731
31605
|
}
|
|
31732
31606
|
function ensureReplayFernignoreEntriesSync(outputDir) {
|
|
31733
|
-
const fernignorePath = (0,
|
|
31607
|
+
const fernignorePath = (0, import_path13.join)(outputDir, ".fernignore");
|
|
31734
31608
|
let content = "";
|
|
31735
|
-
if ((0,
|
|
31736
|
-
content = (0,
|
|
31609
|
+
if ((0, import_fs11.existsSync)(fernignorePath)) {
|
|
31610
|
+
content = (0, import_fs11.readFileSync)(fernignorePath, "utf-8");
|
|
31737
31611
|
}
|
|
31738
31612
|
const lines = content.split("\n");
|
|
31739
31613
|
const toAdd = REPLAY_FERNIGNORE_ENTRIES2.filter((entry) => !lines.some((line) => line.trim() === entry));
|
|
31740
31614
|
if (toAdd.length > 0) {
|
|
31741
31615
|
const suffix = content.length > 0 && !content.endsWith("\n") ? "\n" : "";
|
|
31742
|
-
(0,
|
|
31616
|
+
(0, import_fs11.writeFileSync)(fernignorePath, content + suffix + toAdd.join("\n") + "\n", "utf-8");
|
|
31743
31617
|
}
|
|
31744
31618
|
}
|
|
31745
31619
|
|
|
@@ -31754,8 +31628,8 @@ async function replayRun(params) {
|
|
|
31754
31628
|
skipApplication,
|
|
31755
31629
|
logger
|
|
31756
31630
|
} = params;
|
|
31757
|
-
const lockfilePath = (0,
|
|
31758
|
-
if (!(0,
|
|
31631
|
+
const lockfilePath = (0, import_path14.join)(outputDir, ".fern", "replay.lock");
|
|
31632
|
+
if (!(0, import_fs12.existsSync)(lockfilePath)) {
|
|
31759
31633
|
return {
|
|
31760
31634
|
report: null,
|
|
31761
31635
|
fernignoreUpdated: false,
|
|
@@ -32017,8 +31891,8 @@ var PostGenerationPipeline = class {
|
|
|
32017
31891
|
|
|
32018
31892
|
// src/replay/replay-init.ts
|
|
32019
31893
|
init_dist();
|
|
32020
|
-
var
|
|
32021
|
-
var
|
|
31894
|
+
var import_fs13 = require("fs");
|
|
31895
|
+
var import_path15 = require("path");
|
|
32022
31896
|
var import_tmp_promise2 = __toESM(require_tmp_promise());
|
|
32023
31897
|
async function replayInit(params) {
|
|
32024
31898
|
const { githubRepo, token, dryRun } = params;
|
|
@@ -32049,7 +31923,7 @@ async function replayInit(params) {
|
|
|
32049
31923
|
Tracked ${bootstrapResult.patchesCreated} customization patch(es).
|
|
32050
31924
|
Base generation: ${bootstrapResult.generationCommit.sha.slice(0, 7)}`;
|
|
32051
31925
|
const filesToAdd = [".fern/replay.lock", ".fern/replay.yml", ".fernignore"].filter(
|
|
32052
|
-
(f) => (0,
|
|
31926
|
+
(f) => (0, import_fs13.existsSync)((0, import_path15.join)(repoPath, f))
|
|
32053
31927
|
);
|
|
32054
31928
|
const branchName = `fern-replay/init-${Date.now()}`;
|
|
32055
31929
|
await repository.checkoutOrCreateLocal(branchName);
|
|
@@ -32385,8 +32259,8 @@ void yargs_default(hideBin(process.argv)).scriptName(process.env.CLI_NAME ?? "ge
|
|
|
32385
32259
|
const result = await pipeline.run();
|
|
32386
32260
|
if (argv["result-file"] != null) {
|
|
32387
32261
|
const resultPath = resolve(wd, argv["result-file"]);
|
|
32388
|
-
await (0, import_promises9.mkdir)(
|
|
32389
|
-
await
|
|
32262
|
+
await (0, import_promises9.mkdir)(import_path16.default.dirname(resultPath), { recursive: true });
|
|
32263
|
+
await import_fs14.default.promises.writeFile(resultPath, JSON.stringify(result, null, 2));
|
|
32390
32264
|
}
|
|
32391
32265
|
process.stderr.write(`Pipeline ${result.success ? "succeeded" : "failed"}
|
|
32392
32266
|
`);
|
|
@@ -32592,9 +32466,9 @@ async function createWriteStream(outputPath) {
|
|
|
32592
32466
|
}
|
|
32593
32467
|
async function createWriteStreamFromFile(filepath) {
|
|
32594
32468
|
if (!await doesPathExist(filepath)) {
|
|
32595
|
-
await (0, import_promises9.mkdir)(
|
|
32469
|
+
await (0, import_promises9.mkdir)(import_path16.default.dirname(filepath), { recursive: true });
|
|
32596
32470
|
}
|
|
32597
|
-
return
|
|
32471
|
+
return import_fs14.default.createWriteStream(filepath);
|
|
32598
32472
|
}
|
|
32599
32473
|
/*! Bundled license information:
|
|
32600
32474
|
|