@buildautomaton/cli 0.1.46 → 0.1.47
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +770 -438
- package/dist/cli.js.map +4 -4
- package/dist/index.js +749 -417
- package/dist/index.js.map +4 -4
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -973,8 +973,8 @@ var require_command = __commonJS({
|
|
|
973
973
|
"../../node_modules/.pnpm/commander@12.1.0/node_modules/commander/lib/command.js"(exports) {
|
|
974
974
|
var EventEmitter2 = __require("node:events").EventEmitter;
|
|
975
975
|
var childProcess2 = __require("node:child_process");
|
|
976
|
-
var
|
|
977
|
-
var
|
|
976
|
+
var path48 = __require("node:path");
|
|
977
|
+
var fs42 = __require("node:fs");
|
|
978
978
|
var process8 = __require("node:process");
|
|
979
979
|
var { Argument: Argument2, humanReadableArgName } = require_argument();
|
|
980
980
|
var { CommanderError: CommanderError2 } = require_error();
|
|
@@ -1906,11 +1906,11 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1906
1906
|
let launchWithNode = false;
|
|
1907
1907
|
const sourceExt = [".js", ".ts", ".tsx", ".mjs", ".cjs"];
|
|
1908
1908
|
function findFile(baseDir, baseName) {
|
|
1909
|
-
const localBin =
|
|
1910
|
-
if (
|
|
1911
|
-
if (sourceExt.includes(
|
|
1909
|
+
const localBin = path48.resolve(baseDir, baseName);
|
|
1910
|
+
if (fs42.existsSync(localBin)) return localBin;
|
|
1911
|
+
if (sourceExt.includes(path48.extname(baseName))) return void 0;
|
|
1912
1912
|
const foundExt = sourceExt.find(
|
|
1913
|
-
(ext) =>
|
|
1913
|
+
(ext) => fs42.existsSync(`${localBin}${ext}`)
|
|
1914
1914
|
);
|
|
1915
1915
|
if (foundExt) return `${localBin}${foundExt}`;
|
|
1916
1916
|
return void 0;
|
|
@@ -1922,21 +1922,21 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1922
1922
|
if (this._scriptPath) {
|
|
1923
1923
|
let resolvedScriptPath;
|
|
1924
1924
|
try {
|
|
1925
|
-
resolvedScriptPath =
|
|
1925
|
+
resolvedScriptPath = fs42.realpathSync(this._scriptPath);
|
|
1926
1926
|
} catch (err) {
|
|
1927
1927
|
resolvedScriptPath = this._scriptPath;
|
|
1928
1928
|
}
|
|
1929
|
-
executableDir =
|
|
1930
|
-
|
|
1929
|
+
executableDir = path48.resolve(
|
|
1930
|
+
path48.dirname(resolvedScriptPath),
|
|
1931
1931
|
executableDir
|
|
1932
1932
|
);
|
|
1933
1933
|
}
|
|
1934
1934
|
if (executableDir) {
|
|
1935
1935
|
let localFile = findFile(executableDir, executableFile);
|
|
1936
1936
|
if (!localFile && !subcommand._executableFile && this._scriptPath) {
|
|
1937
|
-
const legacyName =
|
|
1937
|
+
const legacyName = path48.basename(
|
|
1938
1938
|
this._scriptPath,
|
|
1939
|
-
|
|
1939
|
+
path48.extname(this._scriptPath)
|
|
1940
1940
|
);
|
|
1941
1941
|
if (legacyName !== this._name) {
|
|
1942
1942
|
localFile = findFile(
|
|
@@ -1947,7 +1947,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1947
1947
|
}
|
|
1948
1948
|
executableFile = localFile || executableFile;
|
|
1949
1949
|
}
|
|
1950
|
-
launchWithNode = sourceExt.includes(
|
|
1950
|
+
launchWithNode = sourceExt.includes(path48.extname(executableFile));
|
|
1951
1951
|
let proc;
|
|
1952
1952
|
if (process8.platform !== "win32") {
|
|
1953
1953
|
if (launchWithNode) {
|
|
@@ -2787,7 +2787,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
2787
2787
|
* @return {Command}
|
|
2788
2788
|
*/
|
|
2789
2789
|
nameFromFilename(filename) {
|
|
2790
|
-
this._name =
|
|
2790
|
+
this._name = path48.basename(filename, path48.extname(filename));
|
|
2791
2791
|
return this;
|
|
2792
2792
|
}
|
|
2793
2793
|
/**
|
|
@@ -2801,9 +2801,9 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
2801
2801
|
* @param {string} [path]
|
|
2802
2802
|
* @return {(string|null|Command)}
|
|
2803
2803
|
*/
|
|
2804
|
-
executableDir(
|
|
2805
|
-
if (
|
|
2806
|
-
this._executableDir =
|
|
2804
|
+
executableDir(path49) {
|
|
2805
|
+
if (path49 === void 0) return this._executableDir;
|
|
2806
|
+
this._executableDir = path49;
|
|
2807
2807
|
return this;
|
|
2808
2808
|
}
|
|
2809
2809
|
/**
|
|
@@ -7061,8 +7061,8 @@ var init_parseUtil = __esm({
|
|
|
7061
7061
|
init_errors();
|
|
7062
7062
|
init_en();
|
|
7063
7063
|
makeIssue = (params) => {
|
|
7064
|
-
const { data, path:
|
|
7065
|
-
const fullPath = [...
|
|
7064
|
+
const { data, path: path48, errorMaps, issueData } = params;
|
|
7065
|
+
const fullPath = [...path48, ...issueData.path || []];
|
|
7066
7066
|
const fullIssue = {
|
|
7067
7067
|
...issueData,
|
|
7068
7068
|
path: fullPath
|
|
@@ -7370,11 +7370,11 @@ var init_types = __esm({
|
|
|
7370
7370
|
init_parseUtil();
|
|
7371
7371
|
init_util();
|
|
7372
7372
|
ParseInputLazyPath = class {
|
|
7373
|
-
constructor(parent, value,
|
|
7373
|
+
constructor(parent, value, path48, key) {
|
|
7374
7374
|
this._cachedPath = [];
|
|
7375
7375
|
this.parent = parent;
|
|
7376
7376
|
this.data = value;
|
|
7377
|
-
this._path =
|
|
7377
|
+
this._path = path48;
|
|
7378
7378
|
this._key = key;
|
|
7379
7379
|
}
|
|
7380
7380
|
get path() {
|
|
@@ -11099,15 +11099,15 @@ function assignProp(target, prop, value) {
|
|
|
11099
11099
|
configurable: true
|
|
11100
11100
|
});
|
|
11101
11101
|
}
|
|
11102
|
-
function getElementAtPath(obj,
|
|
11103
|
-
if (!
|
|
11102
|
+
function getElementAtPath(obj, path48) {
|
|
11103
|
+
if (!path48)
|
|
11104
11104
|
return obj;
|
|
11105
|
-
return
|
|
11105
|
+
return path48.reduce((acc, key) => acc?.[key], obj);
|
|
11106
11106
|
}
|
|
11107
11107
|
function promiseAllObject(promisesObj) {
|
|
11108
11108
|
const keys = Object.keys(promisesObj);
|
|
11109
|
-
const
|
|
11110
|
-
return Promise.all(
|
|
11109
|
+
const promises6 = keys.map((key) => promisesObj[key]);
|
|
11110
|
+
return Promise.all(promises6).then((results) => {
|
|
11111
11111
|
const resolvedObj = {};
|
|
11112
11112
|
for (let i = 0; i < keys.length; i++) {
|
|
11113
11113
|
resolvedObj[keys[i]] = results[i];
|
|
@@ -11351,11 +11351,11 @@ function aborted(x, startIndex = 0) {
|
|
|
11351
11351
|
}
|
|
11352
11352
|
return false;
|
|
11353
11353
|
}
|
|
11354
|
-
function prefixIssues(
|
|
11354
|
+
function prefixIssues(path48, issues) {
|
|
11355
11355
|
return issues.map((iss) => {
|
|
11356
11356
|
var _a2;
|
|
11357
11357
|
(_a2 = iss).path ?? (_a2.path = []);
|
|
11358
|
-
iss.path.unshift(
|
|
11358
|
+
iss.path.unshift(path48);
|
|
11359
11359
|
return iss;
|
|
11360
11360
|
});
|
|
11361
11361
|
}
|
|
@@ -11544,7 +11544,7 @@ function treeifyError(error40, _mapper) {
|
|
|
11544
11544
|
return issue2.message;
|
|
11545
11545
|
};
|
|
11546
11546
|
const result = { errors: [] };
|
|
11547
|
-
const processError = (error41,
|
|
11547
|
+
const processError = (error41, path48 = []) => {
|
|
11548
11548
|
var _a2, _b;
|
|
11549
11549
|
for (const issue2 of error41.issues) {
|
|
11550
11550
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
@@ -11554,7 +11554,7 @@ function treeifyError(error40, _mapper) {
|
|
|
11554
11554
|
} else if (issue2.code === "invalid_element") {
|
|
11555
11555
|
processError({ issues: issue2.issues }, issue2.path);
|
|
11556
11556
|
} else {
|
|
11557
|
-
const fullpath = [...
|
|
11557
|
+
const fullpath = [...path48, ...issue2.path];
|
|
11558
11558
|
if (fullpath.length === 0) {
|
|
11559
11559
|
result.errors.push(mapper(issue2));
|
|
11560
11560
|
continue;
|
|
@@ -11584,9 +11584,9 @@ function treeifyError(error40, _mapper) {
|
|
|
11584
11584
|
processError(error40);
|
|
11585
11585
|
return result;
|
|
11586
11586
|
}
|
|
11587
|
-
function toDotPath(
|
|
11587
|
+
function toDotPath(path48) {
|
|
11588
11588
|
const segs = [];
|
|
11589
|
-
for (const seg of
|
|
11589
|
+
for (const seg of path48) {
|
|
11590
11590
|
if (typeof seg === "number")
|
|
11591
11591
|
segs.push(`[${seg}]`);
|
|
11592
11592
|
else if (typeof seg === "symbol")
|
|
@@ -25069,10 +25069,10 @@ var require_src2 = __commonJS({
|
|
|
25069
25069
|
var fs_1 = __require("fs");
|
|
25070
25070
|
var debug_1 = __importDefault(require_src());
|
|
25071
25071
|
var log2 = debug_1.default("@kwsites/file-exists");
|
|
25072
|
-
function check2(
|
|
25073
|
-
log2(`checking %s`,
|
|
25072
|
+
function check2(path48, isFile, isDirectory) {
|
|
25073
|
+
log2(`checking %s`, path48);
|
|
25074
25074
|
try {
|
|
25075
|
-
const stat3 = fs_1.statSync(
|
|
25075
|
+
const stat3 = fs_1.statSync(path48);
|
|
25076
25076
|
if (stat3.isFile() && isFile) {
|
|
25077
25077
|
log2(`[OK] path represents a file`);
|
|
25078
25078
|
return true;
|
|
@@ -25092,8 +25092,8 @@ var require_src2 = __commonJS({
|
|
|
25092
25092
|
throw e;
|
|
25093
25093
|
}
|
|
25094
25094
|
}
|
|
25095
|
-
function exists2(
|
|
25096
|
-
return check2(
|
|
25095
|
+
function exists2(path48, type = exports.READABLE) {
|
|
25096
|
+
return check2(path48, (type & exports.FILE) > 0, (type & exports.FOLDER) > 0);
|
|
25097
25097
|
}
|
|
25098
25098
|
exports.exists = exists2;
|
|
25099
25099
|
exports.FILE = 1;
|
|
@@ -25174,15 +25174,15 @@ var {
|
|
|
25174
25174
|
} = import_index.default;
|
|
25175
25175
|
|
|
25176
25176
|
// src/cli-version.ts
|
|
25177
|
-
var CLI_VERSION = "0.1.
|
|
25177
|
+
var CLI_VERSION = "0.1.47".length > 0 ? "0.1.47" : "0.0.0-dev";
|
|
25178
25178
|
|
|
25179
25179
|
// src/cli/defaults.ts
|
|
25180
25180
|
var DEFAULT_API_URL = process.env.BUILDAUTOMATON_API_URL ?? "https://api.buildautomaton.com";
|
|
25181
25181
|
var DEFAULT_FIREHOSE_URL = "https://buildautomaton-firehose.fly.dev";
|
|
25182
25182
|
|
|
25183
25183
|
// src/cli/run-cli-action.ts
|
|
25184
|
-
import * as
|
|
25185
|
-
import * as
|
|
25184
|
+
import * as fs41 from "node:fs";
|
|
25185
|
+
import * as path47 from "node:path";
|
|
25186
25186
|
|
|
25187
25187
|
// src/cli-log-level.ts
|
|
25188
25188
|
var verbosity = "info";
|
|
@@ -27819,9 +27819,9 @@ function parseChangeSummaryJson(raw, allowedPaths, options) {
|
|
|
27819
27819
|
const rawPath = typeof o.path === "string" ? o.path.trim() : "";
|
|
27820
27820
|
const summary = typeof o.summary === "string" ? o.summary.trim() : "";
|
|
27821
27821
|
if (!rawPath || !summary) continue;
|
|
27822
|
-
const
|
|
27823
|
-
if (!
|
|
27824
|
-
rows.push({ path:
|
|
27822
|
+
const path48 = skip ? normalizeRepoRelativePath(rawPath) || rawPath : resolveChangeSummaryPathAgainstAllowed(rawPath, allowedPaths);
|
|
27823
|
+
if (!path48) continue;
|
|
27824
|
+
rows.push({ path: path48, summary: clampSummaryToAtMostTwoLines(summary) });
|
|
27825
27825
|
}
|
|
27826
27826
|
return rows;
|
|
27827
27827
|
}
|
|
@@ -30981,8 +30981,8 @@ function pathspec(...paths) {
|
|
|
30981
30981
|
cache.set(key, paths);
|
|
30982
30982
|
return key;
|
|
30983
30983
|
}
|
|
30984
|
-
function isPathSpec(
|
|
30985
|
-
return
|
|
30984
|
+
function isPathSpec(path48) {
|
|
30985
|
+
return path48 instanceof String && cache.has(path48);
|
|
30986
30986
|
}
|
|
30987
30987
|
function toPaths(pathSpec) {
|
|
30988
30988
|
return cache.get(pathSpec) || [];
|
|
@@ -31071,8 +31071,8 @@ function toLinesWithContent(input = "", trimmed2 = true, separator = "\n") {
|
|
|
31071
31071
|
function forEachLineWithContent(input, callback) {
|
|
31072
31072
|
return toLinesWithContent(input, true).map((line) => callback(line));
|
|
31073
31073
|
}
|
|
31074
|
-
function folderExists(
|
|
31075
|
-
return (0, import_file_exists.exists)(
|
|
31074
|
+
function folderExists(path48) {
|
|
31075
|
+
return (0, import_file_exists.exists)(path48, import_file_exists.FOLDER);
|
|
31076
31076
|
}
|
|
31077
31077
|
function append(target, item) {
|
|
31078
31078
|
if (Array.isArray(target)) {
|
|
@@ -31476,8 +31476,8 @@ function checkIsRepoRootTask() {
|
|
|
31476
31476
|
commands,
|
|
31477
31477
|
format: "utf-8",
|
|
31478
31478
|
onError,
|
|
31479
|
-
parser(
|
|
31480
|
-
return /^\.(git)?$/.test(
|
|
31479
|
+
parser(path48) {
|
|
31480
|
+
return /^\.(git)?$/.test(path48.trim());
|
|
31481
31481
|
}
|
|
31482
31482
|
};
|
|
31483
31483
|
}
|
|
@@ -31911,11 +31911,11 @@ function parseGrep(grep) {
|
|
|
31911
31911
|
const paths = /* @__PURE__ */ new Set();
|
|
31912
31912
|
const results = {};
|
|
31913
31913
|
forEachLineWithContent(grep, (input) => {
|
|
31914
|
-
const [
|
|
31915
|
-
paths.add(
|
|
31916
|
-
(results[
|
|
31914
|
+
const [path48, line, preview] = input.split(NULL);
|
|
31915
|
+
paths.add(path48);
|
|
31916
|
+
(results[path48] = results[path48] || []).push({
|
|
31917
31917
|
line: asNumber(line),
|
|
31918
|
-
path:
|
|
31918
|
+
path: path48,
|
|
31919
31919
|
preview
|
|
31920
31920
|
});
|
|
31921
31921
|
});
|
|
@@ -32680,14 +32680,14 @@ var init_hash_object = __esm2({
|
|
|
32680
32680
|
init_task();
|
|
32681
32681
|
}
|
|
32682
32682
|
});
|
|
32683
|
-
function parseInit(bare,
|
|
32683
|
+
function parseInit(bare, path48, text) {
|
|
32684
32684
|
const response = String(text).trim();
|
|
32685
32685
|
let result;
|
|
32686
32686
|
if (result = initResponseRegex.exec(response)) {
|
|
32687
|
-
return new InitSummary(bare,
|
|
32687
|
+
return new InitSummary(bare, path48, false, result[1]);
|
|
32688
32688
|
}
|
|
32689
32689
|
if (result = reInitResponseRegex.exec(response)) {
|
|
32690
|
-
return new InitSummary(bare,
|
|
32690
|
+
return new InitSummary(bare, path48, true, result[1]);
|
|
32691
32691
|
}
|
|
32692
32692
|
let gitDir = "";
|
|
32693
32693
|
const tokens = response.split(" ");
|
|
@@ -32698,7 +32698,7 @@ function parseInit(bare, path46, text) {
|
|
|
32698
32698
|
break;
|
|
32699
32699
|
}
|
|
32700
32700
|
}
|
|
32701
|
-
return new InitSummary(bare,
|
|
32701
|
+
return new InitSummary(bare, path48, /^re/i.test(response), gitDir);
|
|
32702
32702
|
}
|
|
32703
32703
|
var InitSummary;
|
|
32704
32704
|
var initResponseRegex;
|
|
@@ -32707,9 +32707,9 @@ var init_InitSummary = __esm2({
|
|
|
32707
32707
|
"src/lib/responses/InitSummary.ts"() {
|
|
32708
32708
|
"use strict";
|
|
32709
32709
|
InitSummary = class {
|
|
32710
|
-
constructor(bare,
|
|
32710
|
+
constructor(bare, path48, existing, gitDir) {
|
|
32711
32711
|
this.bare = bare;
|
|
32712
|
-
this.path =
|
|
32712
|
+
this.path = path48;
|
|
32713
32713
|
this.existing = existing;
|
|
32714
32714
|
this.gitDir = gitDir;
|
|
32715
32715
|
}
|
|
@@ -32721,7 +32721,7 @@ var init_InitSummary = __esm2({
|
|
|
32721
32721
|
function hasBareCommand(command) {
|
|
32722
32722
|
return command.includes(bareCommand);
|
|
32723
32723
|
}
|
|
32724
|
-
function initTask(bare = false,
|
|
32724
|
+
function initTask(bare = false, path48, customArgs) {
|
|
32725
32725
|
const commands = ["init", ...customArgs];
|
|
32726
32726
|
if (bare && !hasBareCommand(commands)) {
|
|
32727
32727
|
commands.splice(1, 0, bareCommand);
|
|
@@ -32730,7 +32730,7 @@ function initTask(bare = false, path46, customArgs) {
|
|
|
32730
32730
|
commands,
|
|
32731
32731
|
format: "utf-8",
|
|
32732
32732
|
parser(text) {
|
|
32733
|
-
return parseInit(commands.includes("--bare"),
|
|
32733
|
+
return parseInit(commands.includes("--bare"), path48, text);
|
|
32734
32734
|
}
|
|
32735
32735
|
};
|
|
32736
32736
|
}
|
|
@@ -33546,12 +33546,12 @@ var init_FileStatusSummary = __esm2({
|
|
|
33546
33546
|
"use strict";
|
|
33547
33547
|
fromPathRegex = /^(.+)\0(.+)$/;
|
|
33548
33548
|
FileStatusSummary = class {
|
|
33549
|
-
constructor(
|
|
33550
|
-
this.path =
|
|
33549
|
+
constructor(path48, index, working_dir) {
|
|
33550
|
+
this.path = path48;
|
|
33551
33551
|
this.index = index;
|
|
33552
33552
|
this.working_dir = working_dir;
|
|
33553
33553
|
if (index === "R" || working_dir === "R") {
|
|
33554
|
-
const detail = fromPathRegex.exec(
|
|
33554
|
+
const detail = fromPathRegex.exec(path48) || [null, path48, path48];
|
|
33555
33555
|
this.from = detail[2] || "";
|
|
33556
33556
|
this.path = detail[1] || "";
|
|
33557
33557
|
}
|
|
@@ -33582,14 +33582,14 @@ function splitLine(result, lineStr) {
|
|
|
33582
33582
|
default:
|
|
33583
33583
|
return;
|
|
33584
33584
|
}
|
|
33585
|
-
function data(index, workingDir,
|
|
33585
|
+
function data(index, workingDir, path48) {
|
|
33586
33586
|
const raw = `${index}${workingDir}`;
|
|
33587
33587
|
const handler = parsers6.get(raw);
|
|
33588
33588
|
if (handler) {
|
|
33589
|
-
handler(result,
|
|
33589
|
+
handler(result, path48);
|
|
33590
33590
|
}
|
|
33591
33591
|
if (raw !== "##" && raw !== "!!") {
|
|
33592
|
-
result.files.push(new FileStatusSummary(
|
|
33592
|
+
result.files.push(new FileStatusSummary(path48, index, workingDir));
|
|
33593
33593
|
}
|
|
33594
33594
|
}
|
|
33595
33595
|
}
|
|
@@ -33898,9 +33898,9 @@ var init_simple_git_api = __esm2({
|
|
|
33898
33898
|
next
|
|
33899
33899
|
);
|
|
33900
33900
|
}
|
|
33901
|
-
hashObject(
|
|
33901
|
+
hashObject(path48, write) {
|
|
33902
33902
|
return this._runTask(
|
|
33903
|
-
hashObjectTask(
|
|
33903
|
+
hashObjectTask(path48, write === true),
|
|
33904
33904
|
trailingFunctionArgument(arguments)
|
|
33905
33905
|
);
|
|
33906
33906
|
}
|
|
@@ -34253,8 +34253,8 @@ var init_branch = __esm2({
|
|
|
34253
34253
|
}
|
|
34254
34254
|
});
|
|
34255
34255
|
function toPath(input) {
|
|
34256
|
-
const
|
|
34257
|
-
return
|
|
34256
|
+
const path48 = input.trim().replace(/^["']|["']$/g, "");
|
|
34257
|
+
return path48 && normalize3(path48);
|
|
34258
34258
|
}
|
|
34259
34259
|
var parseCheckIgnore;
|
|
34260
34260
|
var init_CheckIgnore = __esm2({
|
|
@@ -34568,8 +34568,8 @@ __export2(sub_module_exports, {
|
|
|
34568
34568
|
subModuleTask: () => subModuleTask,
|
|
34569
34569
|
updateSubModuleTask: () => updateSubModuleTask
|
|
34570
34570
|
});
|
|
34571
|
-
function addSubModuleTask(repo,
|
|
34572
|
-
return subModuleTask(["add", repo,
|
|
34571
|
+
function addSubModuleTask(repo, path48) {
|
|
34572
|
+
return subModuleTask(["add", repo, path48]);
|
|
34573
34573
|
}
|
|
34574
34574
|
function initSubModuleTask(customArgs) {
|
|
34575
34575
|
return subModuleTask(["init", ...customArgs]);
|
|
@@ -34902,8 +34902,8 @@ var require_git = __commonJS2({
|
|
|
34902
34902
|
}
|
|
34903
34903
|
return this._runTask(straightThroughStringTask2(command, this._trimmed), next);
|
|
34904
34904
|
};
|
|
34905
|
-
Git2.prototype.submoduleAdd = function(repo,
|
|
34906
|
-
return this._runTask(addSubModuleTask2(repo,
|
|
34905
|
+
Git2.prototype.submoduleAdd = function(repo, path48, then) {
|
|
34906
|
+
return this._runTask(addSubModuleTask2(repo, path48), trailingFunctionArgument2(arguments));
|
|
34907
34907
|
};
|
|
34908
34908
|
Git2.prototype.submoduleUpdate = function(args, then) {
|
|
34909
34909
|
return this._runTask(
|
|
@@ -35866,9 +35866,9 @@ async function collectTurnGitDiffFromPreTurnSnapshot(options) {
|
|
|
35866
35866
|
// src/agents/acp/put-summarize-change-summaries.ts
|
|
35867
35867
|
async function putEncryptedChangeSummaryRows(params) {
|
|
35868
35868
|
const base = params.apiBaseUrl.replace(/\/+$/, "");
|
|
35869
|
-
const entries = params.rows.map(({ path:
|
|
35869
|
+
const entries = params.rows.map(({ path: path48, summary }) => {
|
|
35870
35870
|
const enc = params.e2ee.encryptFields({ summary }, ["summary"]);
|
|
35871
|
-
return { path:
|
|
35871
|
+
return { path: path48, summary: JSON.stringify(enc) };
|
|
35872
35872
|
});
|
|
35873
35873
|
const res = await fetch(
|
|
35874
35874
|
`${base}/internal/sessions/${encodeURIComponent(params.sessionId)}/follow-ups/summarize-changes`,
|
|
@@ -36462,7 +36462,7 @@ async function createAcpManager(options) {
|
|
|
36462
36462
|
// src/git/changes/types.ts
|
|
36463
36463
|
var MAX_PATCH_CHARS = 35e4;
|
|
36464
36464
|
|
|
36465
|
-
// src/git/changes/
|
|
36465
|
+
// src/git/changes/paths/repo-format.ts
|
|
36466
36466
|
function posixJoinDirFile(dir, file2) {
|
|
36467
36467
|
const d = dir === "." || dir === "" ? "" : dir.replace(/\\/g, "/").replace(/\/+$/, "");
|
|
36468
36468
|
const f = file2.replace(/\\/g, "/").replace(/^\/+/, "");
|
|
@@ -36517,7 +36517,7 @@ function formatRemoteDisplayLabel(remoteUrl) {
|
|
|
36517
36517
|
}
|
|
36518
36518
|
|
|
36519
36519
|
// src/git/changes/get-working-tree-change-repo-details.ts
|
|
36520
|
-
import * as
|
|
36520
|
+
import * as path23 from "node:path";
|
|
36521
36521
|
|
|
36522
36522
|
// src/git/commits/resolve-remote-tracking.ts
|
|
36523
36523
|
async function tryConfigGet(g, key) {
|
|
@@ -36687,9 +36687,232 @@ async function listRecentCommits(repoDir, limitInput) {
|
|
|
36687
36687
|
}
|
|
36688
36688
|
}
|
|
36689
36689
|
|
|
36690
|
-
// src/git/changes/
|
|
36691
|
-
function
|
|
36692
|
-
|
|
36690
|
+
// src/git/changes/parse/normalize-git-diff-path.ts
|
|
36691
|
+
function normalizeGitDiffPath(path48) {
|
|
36692
|
+
return path48.replace(/\\/g, "/").replace(/\/ +/g, "/").trim();
|
|
36693
|
+
}
|
|
36694
|
+
|
|
36695
|
+
// src/git/changes/parse/expand-git-rename-numstat-path.ts
|
|
36696
|
+
function expandGitRenameNumstatPath(rawPath) {
|
|
36697
|
+
const open2 = rawPath.indexOf("{");
|
|
36698
|
+
const arrow = rawPath.indexOf("=>");
|
|
36699
|
+
const close = rawPath.lastIndexOf("}");
|
|
36700
|
+
if (open2 === -1 || arrow === -1 || close === -1 || open2 > arrow || arrow > close) {
|
|
36701
|
+
return null;
|
|
36702
|
+
}
|
|
36703
|
+
const prefix = rawPath.slice(0, open2);
|
|
36704
|
+
const suffix = rawPath.slice(close + 1);
|
|
36705
|
+
const oldPart = rawPath.slice(open2 + 1, arrow).trim();
|
|
36706
|
+
const newPart = rawPath.slice(arrow + 2, close).trim();
|
|
36707
|
+
return {
|
|
36708
|
+
oldPath: normalizeGitDiffPath(`${prefix}${oldPart}${suffix}`),
|
|
36709
|
+
newPath: normalizeGitDiffPath(`${prefix}${newPart}${suffix}`)
|
|
36710
|
+
};
|
|
36711
|
+
}
|
|
36712
|
+
function isGitRenameNumstatPath(rawPath) {
|
|
36713
|
+
return expandGitRenameNumstatPath(rawPath) != null;
|
|
36714
|
+
}
|
|
36715
|
+
|
|
36716
|
+
// src/git/changes/rows/build-changed-file-row.ts
|
|
36717
|
+
function buildChangedFileRow(options) {
|
|
36718
|
+
const pathInRepo = normalizeGitDiffPath(options.pathInRepo);
|
|
36719
|
+
const relLauncher = posixJoinDirFile(options.repoRelPath, pathInRepo);
|
|
36720
|
+
const additions = options.numEntry?.additions ?? 0;
|
|
36721
|
+
const deletions = options.numEntry?.deletions ?? 0;
|
|
36722
|
+
let change = options.nameEntry?.change ?? "modified";
|
|
36723
|
+
let movedFromPathRelLauncher;
|
|
36724
|
+
let movedFromPathInRepo;
|
|
36725
|
+
const oldPathInRepo = options.nameEntry?.oldPathInRepo ?? options.numEntry?.oldPathInRepo;
|
|
36726
|
+
if (change === "moved" && oldPathInRepo) {
|
|
36727
|
+
movedFromPathInRepo = normalizeGitDiffPath(oldPathInRepo);
|
|
36728
|
+
movedFromPathRelLauncher = posixJoinDirFile(options.repoRelPath, movedFromPathInRepo);
|
|
36729
|
+
} else if (oldPathInRepo && change === "modified") {
|
|
36730
|
+
change = "moved";
|
|
36731
|
+
movedFromPathInRepo = normalizeGitDiffPath(oldPathInRepo);
|
|
36732
|
+
movedFromPathRelLauncher = posixJoinDirFile(options.repoRelPath, movedFromPathInRepo);
|
|
36733
|
+
}
|
|
36734
|
+
if (options.untracked && !options.nameEntry) {
|
|
36735
|
+
change = "added";
|
|
36736
|
+
} else if (!options.nameEntry && options.numEntry && change !== "moved") {
|
|
36737
|
+
if (additions > 0 && deletions === 0) change = "added";
|
|
36738
|
+
else if (deletions > 0 && additions === 0) change = "removed";
|
|
36739
|
+
else change = "modified";
|
|
36740
|
+
}
|
|
36741
|
+
return {
|
|
36742
|
+
pathRelLauncher: relLauncher,
|
|
36743
|
+
additions,
|
|
36744
|
+
deletions,
|
|
36745
|
+
change,
|
|
36746
|
+
...movedFromPathRelLauncher ? { movedFromPathRelLauncher } : {},
|
|
36747
|
+
...movedFromPathInRepo ? { movedFromPathInRepo } : {}
|
|
36748
|
+
};
|
|
36749
|
+
}
|
|
36750
|
+
|
|
36751
|
+
// src/git/changes/listing/build-changed-file-rows.ts
|
|
36752
|
+
async function buildChangedFileRowsFromPaths(options) {
|
|
36753
|
+
const rows = [];
|
|
36754
|
+
await forEachWithGitYield([...options.paths], async (pathInRepo) => {
|
|
36755
|
+
if (isGitRenameNumstatPath(pathInRepo)) return;
|
|
36756
|
+
if (options.movedSourcePaths.has(pathInRepo)) return;
|
|
36757
|
+
const nameEntry = options.nameByPath.get(pathInRepo);
|
|
36758
|
+
const numEntry = options.numByPath.get(pathInRepo);
|
|
36759
|
+
const row = buildChangedFileRow({
|
|
36760
|
+
pathInRepo,
|
|
36761
|
+
repoRelPath: options.repoRelPath,
|
|
36762
|
+
nameEntry,
|
|
36763
|
+
numEntry,
|
|
36764
|
+
untracked: options.untrackedSet?.has(pathInRepo)
|
|
36765
|
+
});
|
|
36766
|
+
if (options.applyUntrackedStats) {
|
|
36767
|
+
await options.applyUntrackedStats(row, pathInRepo);
|
|
36768
|
+
}
|
|
36769
|
+
rows.push(row);
|
|
36770
|
+
});
|
|
36771
|
+
return rows;
|
|
36772
|
+
}
|
|
36773
|
+
|
|
36774
|
+
// src/git/changes/patch/patch-truncate.ts
|
|
36775
|
+
function truncatePatch(s) {
|
|
36776
|
+
if (s.length <= MAX_PATCH_CHARS) return s;
|
|
36777
|
+
return `${s.slice(0, MAX_PATCH_CHARS)}
|
|
36778
|
+
|
|
36779
|
+
\u2026 (diff truncated)`;
|
|
36780
|
+
}
|
|
36781
|
+
|
|
36782
|
+
// src/git/changes/patch/unified-diff-for-file.ts
|
|
36783
|
+
function patchTextFromGitDiffOutput(raw) {
|
|
36784
|
+
if (raw.trim() === "") return void 0;
|
|
36785
|
+
return normalizePatchContent(raw);
|
|
36786
|
+
}
|
|
36787
|
+
async function unifiedDiffForFile(repoCwd, pathInRepo, change, movedFromPathInRepo) {
|
|
36788
|
+
const g = cliSimpleGit(repoCwd);
|
|
36789
|
+
const renameArgs = ["-M", "--find-renames"];
|
|
36790
|
+
const args = change === "moved" && movedFromPathInRepo ? ["diff", "--no-color", ...renameArgs, "HEAD", "--", movedFromPathInRepo, pathInRepo] : change === "removed" ? ["diff", "--no-color", ...renameArgs, "HEAD", "--", pathInRepo] : ["diff", "--no-color", ...renameArgs, "HEAD", "--", pathInRepo];
|
|
36791
|
+
const raw = await g.raw([...args]).catch(() => "");
|
|
36792
|
+
const patch = patchTextFromGitDiffOutput(String(raw));
|
|
36793
|
+
return patch ? truncatePatch(patch) : void 0;
|
|
36794
|
+
}
|
|
36795
|
+
async function unifiedDiffForFileInRange(repoCwd, range, pathInRepo, change, movedFromPathInRepo) {
|
|
36796
|
+
const g = cliSimpleGit(repoCwd);
|
|
36797
|
+
const renameArgs = ["-M", "--find-renames"];
|
|
36798
|
+
const args = change === "moved" && movedFromPathInRepo ? ["diff", "--no-color", ...renameArgs, "-U20000", range, "--", movedFromPathInRepo, pathInRepo] : ["diff", "--no-color", ...renameArgs, "-U20000", range, "--", pathInRepo];
|
|
36799
|
+
const raw = await g.raw([...args]).catch(() => "");
|
|
36800
|
+
const patch = patchTextFromGitDiffOutput(String(raw));
|
|
36801
|
+
return patch ? truncatePatch(patch) : void 0;
|
|
36802
|
+
}
|
|
36803
|
+
|
|
36804
|
+
// src/git/changes/total-lines/resolve-changed-file-total-lines.ts
|
|
36805
|
+
import * as fs17 from "node:fs";
|
|
36806
|
+
import * as path20 from "node:path";
|
|
36807
|
+
|
|
36808
|
+
// src/git/changes/lines/count-lines.ts
|
|
36809
|
+
import { createReadStream } from "node:fs";
|
|
36810
|
+
import * as readline2 from "node:readline";
|
|
36811
|
+
function countLinesInText(text) {
|
|
36812
|
+
return splitTextIntoDiffLines(text).length;
|
|
36813
|
+
}
|
|
36814
|
+
async function countTextFileLines(filePath) {
|
|
36815
|
+
let bytes = 0;
|
|
36816
|
+
const maxBytes = 512e3;
|
|
36817
|
+
let lines = 0;
|
|
36818
|
+
const stream = createReadStream(filePath, { encoding: "utf8" });
|
|
36819
|
+
const rl = readline2.createInterface({ input: stream, crlfDelay: Infinity });
|
|
36820
|
+
for await (const _line of rl) {
|
|
36821
|
+
lines += 1;
|
|
36822
|
+
bytes += Buffer.byteLength(String(_line), "utf8") + 1;
|
|
36823
|
+
if (bytes > maxBytes) {
|
|
36824
|
+
rl.close();
|
|
36825
|
+
stream.destroy();
|
|
36826
|
+
return lines;
|
|
36827
|
+
}
|
|
36828
|
+
}
|
|
36829
|
+
return lines;
|
|
36830
|
+
}
|
|
36831
|
+
|
|
36832
|
+
// src/git/changes/total-lines/resolve-changed-file-total-lines.ts
|
|
36833
|
+
var MAX_BYTES = 512e3;
|
|
36834
|
+
async function countLinesInGitRef(repoGitCwd, ref, pathInRepo) {
|
|
36835
|
+
const spec = `${ref}:${pathInRepo}`;
|
|
36836
|
+
const g = cliSimpleGit(repoGitCwd);
|
|
36837
|
+
try {
|
|
36838
|
+
await g.raw(["cat-file", "-e", spec]);
|
|
36839
|
+
} catch {
|
|
36840
|
+
return null;
|
|
36841
|
+
}
|
|
36842
|
+
try {
|
|
36843
|
+
const raw = String(await g.raw(["show", spec]));
|
|
36844
|
+
const capped = raw.length > MAX_BYTES ? raw.slice(0, MAX_BYTES) : raw;
|
|
36845
|
+
return countLinesInText(capped);
|
|
36846
|
+
} catch {
|
|
36847
|
+
return null;
|
|
36848
|
+
}
|
|
36849
|
+
}
|
|
36850
|
+
async function resolveWorkingTreeFileTotalLines(options) {
|
|
36851
|
+
if (options.isBinary) return null;
|
|
36852
|
+
const filePath = path20.join(options.repoGitCwd, options.pathInRepo);
|
|
36853
|
+
if (options.change === "removed") {
|
|
36854
|
+
return countLinesInGitRef(options.repoGitCwd, "HEAD", options.pathInRepo);
|
|
36855
|
+
}
|
|
36856
|
+
if (options.change === "moved" || options.change === "modified") {
|
|
36857
|
+
try {
|
|
36858
|
+
const st = await fs17.promises.stat(filePath);
|
|
36859
|
+
if (!st.isFile()) return null;
|
|
36860
|
+
return await countTextFileLines(filePath);
|
|
36861
|
+
} catch {
|
|
36862
|
+
return null;
|
|
36863
|
+
}
|
|
36864
|
+
}
|
|
36865
|
+
return null;
|
|
36866
|
+
}
|
|
36867
|
+
async function resolveCommitFileTotalLines(options) {
|
|
36868
|
+
if (options.isBinary) return null;
|
|
36869
|
+
if (options.change === "removed") {
|
|
36870
|
+
return countLinesInGitRef(options.repoGitCwd, options.parentSha, options.pathInRepo);
|
|
36871
|
+
}
|
|
36872
|
+
if (options.change === "moved" || options.change === "modified") {
|
|
36873
|
+
return countLinesInGitRef(options.repoGitCwd, options.commitSha, options.pathInRepo);
|
|
36874
|
+
}
|
|
36875
|
+
return null;
|
|
36876
|
+
}
|
|
36877
|
+
|
|
36878
|
+
// src/git/changes/listing/path-in-repo-from-launcher.ts
|
|
36879
|
+
function pathInRepoFromLauncher(pathRelLauncher, repoRelPath) {
|
|
36880
|
+
const normRel = repoRelPath === "." || repoRelPath === "" ? "." : repoRelPath;
|
|
36881
|
+
if (normRel === ".") return pathRelLauncher;
|
|
36882
|
+
if (pathRelLauncher.startsWith(`${normRel}/`)) {
|
|
36883
|
+
return pathRelLauncher.slice(normRel.length + 1);
|
|
36884
|
+
}
|
|
36885
|
+
return pathRelLauncher;
|
|
36886
|
+
}
|
|
36887
|
+
function normalizeRepoRelPath(repoRelPath) {
|
|
36888
|
+
return repoRelPath === "." || repoRelPath === "" ? "." : repoRelPath;
|
|
36889
|
+
}
|
|
36890
|
+
|
|
36891
|
+
// src/git/changes/listing/enrich-commit-file-rows.ts
|
|
36892
|
+
async function enrichCommitFileRows(options) {
|
|
36893
|
+
await forEachWithGitYield(options.rows, async (row) => {
|
|
36894
|
+
const pathInRepo = pathInRepoFromLauncher(row.pathRelLauncher, options.repoRelPath);
|
|
36895
|
+
row.patchContent = await unifiedDiffForFileInRange(
|
|
36896
|
+
options.repoGitCwd,
|
|
36897
|
+
options.range,
|
|
36898
|
+
pathInRepo,
|
|
36899
|
+
row.change,
|
|
36900
|
+
row.movedFromPathInRepo
|
|
36901
|
+
);
|
|
36902
|
+
row.totalLines = await resolveCommitFileTotalLines({
|
|
36903
|
+
repoGitCwd: options.repoGitCwd,
|
|
36904
|
+
pathInRepo,
|
|
36905
|
+
change: row.change,
|
|
36906
|
+
commitSha: options.commitSha,
|
|
36907
|
+
parentSha: options.parentSha,
|
|
36908
|
+
isBinary: options.binaryByPath.has(pathInRepo)
|
|
36909
|
+
});
|
|
36910
|
+
});
|
|
36911
|
+
}
|
|
36912
|
+
|
|
36913
|
+
// src/git/changes/parse/parse-name-status-entries.ts
|
|
36914
|
+
function parseNameStatusEntries(lines) {
|
|
36915
|
+
const entries = [];
|
|
36693
36916
|
for (const line of lines) {
|
|
36694
36917
|
if (!line.trim()) continue;
|
|
36695
36918
|
const tabParts = line.split(" ");
|
|
@@ -36697,58 +36920,143 @@ function parseNameStatusLines(lines) {
|
|
|
36697
36920
|
const status = tabParts[0].trim();
|
|
36698
36921
|
const code = status[0];
|
|
36699
36922
|
if (code === "A") {
|
|
36700
|
-
|
|
36923
|
+
entries.push({ pathInRepo: normalizeGitDiffPath(tabParts[tabParts.length - 1]), change: "added" });
|
|
36701
36924
|
} else if (code === "D") {
|
|
36702
|
-
|
|
36925
|
+
entries.push({ pathInRepo: normalizeGitDiffPath(tabParts[tabParts.length - 1]), change: "removed" });
|
|
36703
36926
|
} else if (code === "R" || code === "C") {
|
|
36704
|
-
if (tabParts.length >= 3)
|
|
36927
|
+
if (tabParts.length >= 3) {
|
|
36928
|
+
entries.push({
|
|
36929
|
+
pathInRepo: normalizeGitDiffPath(tabParts[tabParts.length - 1]),
|
|
36930
|
+
oldPathInRepo: normalizeGitDiffPath(tabParts[tabParts.length - 2]),
|
|
36931
|
+
change: "moved"
|
|
36932
|
+
});
|
|
36933
|
+
}
|
|
36705
36934
|
} else if (code === "M" || code === "U" || code === "T") {
|
|
36706
|
-
|
|
36935
|
+
entries.push({ pathInRepo: normalizeGitDiffPath(tabParts[tabParts.length - 1]), change: "modified" });
|
|
36707
36936
|
}
|
|
36708
36937
|
}
|
|
36938
|
+
return entries;
|
|
36939
|
+
}
|
|
36940
|
+
function parseNameStatusLines(lines) {
|
|
36941
|
+
const m = /* @__PURE__ */ new Map();
|
|
36942
|
+
for (const entry of parseNameStatusEntries(lines)) {
|
|
36943
|
+
m.set(entry.pathInRepo, entry.change);
|
|
36944
|
+
}
|
|
36709
36945
|
return m;
|
|
36710
36946
|
}
|
|
36711
|
-
|
|
36947
|
+
|
|
36948
|
+
// src/git/changes/parse/parse-numstat-entries.ts
|
|
36949
|
+
function parseNumstatCounts(parts) {
|
|
36950
|
+
const [a, d] = parts;
|
|
36951
|
+
return {
|
|
36952
|
+
additions: a === "-" ? 0 : parseInt(String(a), 10) || 0,
|
|
36953
|
+
deletions: d === "-" ? 0 : parseInt(String(d), 10) || 0
|
|
36954
|
+
};
|
|
36955
|
+
}
|
|
36956
|
+
function parseNumstatLine(line) {
|
|
36712
36957
|
const parts = line.split(" ");
|
|
36713
36958
|
if (parts.length < 3) return null;
|
|
36714
|
-
const
|
|
36715
|
-
const additions
|
|
36716
|
-
const
|
|
36717
|
-
|
|
36959
|
+
const rawPath = parts[parts.length - 1];
|
|
36960
|
+
const { additions, deletions } = parseNumstatCounts(parts);
|
|
36961
|
+
const expanded = expandGitRenameNumstatPath(rawPath);
|
|
36962
|
+
const pathInRepo = normalizeGitDiffPath(expanded?.newPath ?? rawPath);
|
|
36963
|
+
return {
|
|
36964
|
+
pathInRepo,
|
|
36965
|
+
additions,
|
|
36966
|
+
deletions,
|
|
36967
|
+
...expanded ? { oldPathInRepo: expanded.oldPath } : {}
|
|
36968
|
+
};
|
|
36718
36969
|
}
|
|
36719
|
-
function
|
|
36970
|
+
function parseNumstatEntries(lines) {
|
|
36720
36971
|
const m = /* @__PURE__ */ new Map();
|
|
36721
36972
|
for (const line of lines) {
|
|
36722
36973
|
if (!line.trim()) continue;
|
|
36723
36974
|
const parts = line.split(" ");
|
|
36724
36975
|
if (parts.length < 3) continue;
|
|
36725
|
-
const [
|
|
36726
|
-
const
|
|
36727
|
-
const
|
|
36728
|
-
|
|
36976
|
+
const rawPath = parts[parts.length - 1];
|
|
36977
|
+
const expanded = expandGitRenameNumstatPath(rawPath);
|
|
36978
|
+
const entry = parseNumstatLine(line);
|
|
36979
|
+
if (!entry) continue;
|
|
36980
|
+
const existing = m.get(entry.pathInRepo);
|
|
36981
|
+
if (!existing || expanded) {
|
|
36982
|
+
m.set(entry.pathInRepo, entry);
|
|
36983
|
+
}
|
|
36729
36984
|
}
|
|
36730
36985
|
return m;
|
|
36731
36986
|
}
|
|
36987
|
+
function parseNumstat(lines) {
|
|
36988
|
+
const m = /* @__PURE__ */ new Map();
|
|
36989
|
+
for (const [path48, entry] of parseNumstatEntries(lines)) {
|
|
36990
|
+
m.set(path48, { additions: entry.additions, deletions: entry.deletions });
|
|
36991
|
+
}
|
|
36992
|
+
return m;
|
|
36993
|
+
}
|
|
36994
|
+
|
|
36995
|
+
// src/git/changes/parse/numstat-from-git-no-index.ts
|
|
36732
36996
|
async function numstatFromGitNoIndex(g, pathInRepo) {
|
|
36733
36997
|
const devNull = process.platform === "win32" ? "NUL" : "/dev/null";
|
|
36734
36998
|
try {
|
|
36735
36999
|
const out = await g.raw(["diff", "--numstat", "--no-index", "--", devNull, pathInRepo]);
|
|
36736
37000
|
const first2 = String(out).split("\n").find((l) => l.trim()) ?? "";
|
|
36737
|
-
|
|
37001
|
+
const parsed = parseNumstatLine(first2);
|
|
37002
|
+
if (!parsed) return null;
|
|
37003
|
+
return { additions: parsed.additions, deletions: parsed.deletions };
|
|
36738
37004
|
} catch {
|
|
36739
37005
|
return null;
|
|
36740
37006
|
}
|
|
36741
37007
|
}
|
|
36742
37008
|
|
|
36743
|
-
// src/git/changes/
|
|
36744
|
-
function
|
|
36745
|
-
|
|
36746
|
-
|
|
37009
|
+
// src/git/changes/rows/collect-moved-source-paths.ts
|
|
37010
|
+
function collectMovedSourcePaths(nameEntries, numByPath) {
|
|
37011
|
+
const sources = /* @__PURE__ */ new Set();
|
|
37012
|
+
for (const entry of nameEntries) {
|
|
37013
|
+
if (entry.change === "moved" && entry.oldPathInRepo) sources.add(entry.oldPathInRepo);
|
|
37014
|
+
}
|
|
37015
|
+
for (const entry of numByPath.values()) {
|
|
37016
|
+
if (entry.oldPathInRepo) sources.add(entry.oldPathInRepo);
|
|
37017
|
+
}
|
|
37018
|
+
return sources;
|
|
37019
|
+
}
|
|
36747
37020
|
|
|
36748
|
-
|
|
37021
|
+
// src/git/changes/numstat/is-binary-numstat-line.ts
|
|
37022
|
+
function isBinaryNumstatLine(line) {
|
|
37023
|
+
const parts = line.split(" ");
|
|
37024
|
+
if (parts.length < 3) return false;
|
|
37025
|
+
return parts[0] === "-" || parts[1] === "-";
|
|
36749
37026
|
}
|
|
36750
37027
|
|
|
36751
|
-
// src/git/
|
|
37028
|
+
// src/git/changes/listing/collect-binary-paths-from-numstat.ts
|
|
37029
|
+
function collectBinaryPathsFromNumstat(numstatRaw) {
|
|
37030
|
+
const binaryByPath = /* @__PURE__ */ new Set();
|
|
37031
|
+
for (const line of numstatRaw.split("\n")) {
|
|
37032
|
+
if (!line.trim()) continue;
|
|
37033
|
+
const parts = line.split(" ");
|
|
37034
|
+
if (parts.length < 3) continue;
|
|
37035
|
+
const rawPath = parts[parts.length - 1];
|
|
37036
|
+
const expanded = expandGitRenameNumstatPath(rawPath);
|
|
37037
|
+
if (isBinaryNumstatLine(line)) binaryByPath.add(expanded?.newPath ?? rawPath);
|
|
37038
|
+
}
|
|
37039
|
+
return binaryByPath;
|
|
37040
|
+
}
|
|
37041
|
+
|
|
37042
|
+
// src/git/changes/listing/parse-diff-output.ts
|
|
37043
|
+
function parseDiffOutput(nameStatusRaw, numstatRaw) {
|
|
37044
|
+
const nameEntries = parseNameStatusEntries(nameStatusRaw.split("\n"));
|
|
37045
|
+
const nameByPath = new Map(nameEntries.map((entry) => [entry.pathInRepo, entry]));
|
|
37046
|
+
const numByPath = parseNumstatEntries(numstatRaw.split("\n"));
|
|
37047
|
+
const movedSourcePaths = collectMovedSourcePaths(nameEntries, numByPath);
|
|
37048
|
+
const binaryByPath = collectBinaryPathsFromNumstat(numstatRaw);
|
|
37049
|
+
return { nameEntries, nameByPath, numByPath, movedSourcePaths, binaryByPath };
|
|
37050
|
+
}
|
|
37051
|
+
function collectChangedPaths(options) {
|
|
37052
|
+
const paths = /* @__PURE__ */ new Set();
|
|
37053
|
+
for (const entry of options.nameEntries) paths.add(entry.pathInRepo);
|
|
37054
|
+
for (const pathInRepo of options.numByPath.keys()) paths.add(pathInRepo);
|
|
37055
|
+
for (const pathInRepo of options.untracked ?? []) paths.add(pathInRepo);
|
|
37056
|
+
return paths;
|
|
37057
|
+
}
|
|
37058
|
+
|
|
37059
|
+
// src/git/changes/listing/parent-for-commit-diff.ts
|
|
36752
37060
|
var EMPTY_TREE = "4b825dc642cb6eb9a060e54bf8d69288fbee4904";
|
|
36753
37061
|
async function parentForCommitDiff(g, sha) {
|
|
36754
37062
|
try {
|
|
@@ -36761,76 +37069,112 @@ async function parentForCommitDiff(g, sha) {
|
|
|
36761
37069
|
}
|
|
36762
37070
|
}
|
|
36763
37071
|
}
|
|
37072
|
+
|
|
37073
|
+
// src/git/changes/listing/rename-diff-args.ts
|
|
37074
|
+
var RENAME_DIFF_ARGS = ["-M", "--find-renames"];
|
|
37075
|
+
|
|
37076
|
+
// src/git/changes/rows/pick-preferred-changed-file-row.ts
|
|
37077
|
+
function rowRank(row) {
|
|
37078
|
+
if (row.change === "moved") return 3;
|
|
37079
|
+
if (row.change === "modified") return 2;
|
|
37080
|
+
if (row.change === "added") return 1;
|
|
37081
|
+
return 0;
|
|
37082
|
+
}
|
|
37083
|
+
function pickPreferredChangedFileRow(a, b) {
|
|
37084
|
+
if (rowRank(a) !== rowRank(b)) return rowRank(a) > rowRank(b) ? a : b;
|
|
37085
|
+
const aHasPatch = Boolean(a.patchContent?.trim());
|
|
37086
|
+
const bHasPatch = Boolean(b.patchContent?.trim());
|
|
37087
|
+
if (aHasPatch !== bHasPatch) return aHasPatch ? a : b;
|
|
37088
|
+
const aHasMoveMeta = Boolean(a.movedFromPathInRepo || a.movedFromPathRelLauncher);
|
|
37089
|
+
const bHasMoveMeta = Boolean(b.movedFromPathInRepo || b.movedFromPathRelLauncher);
|
|
37090
|
+
if (aHasMoveMeta !== bHasMoveMeta) return aHasMoveMeta ? a : b;
|
|
37091
|
+
return a;
|
|
37092
|
+
}
|
|
37093
|
+
|
|
37094
|
+
// src/git/changes/rows/dedupe-changed-file-rows.ts
|
|
37095
|
+
function dedupeChangedFileRows(rows) {
|
|
37096
|
+
const byPath = /* @__PURE__ */ new Map();
|
|
37097
|
+
for (const row of rows) {
|
|
37098
|
+
const key = normalizeGitDiffPath(row.pathRelLauncher);
|
|
37099
|
+
const normalizedRow = key === row.pathRelLauncher ? row : { ...row, pathRelLauncher: key };
|
|
37100
|
+
const existing = byPath.get(key);
|
|
37101
|
+
if (!existing) {
|
|
37102
|
+
byPath.set(key, normalizedRow);
|
|
37103
|
+
continue;
|
|
37104
|
+
}
|
|
37105
|
+
const preferRow = pickPreferredChangedFileRow(existing, normalizedRow);
|
|
37106
|
+
byPath.set(key, { ...preferRow, pathRelLauncher: key });
|
|
37107
|
+
}
|
|
37108
|
+
return [...byPath.values()];
|
|
37109
|
+
}
|
|
37110
|
+
|
|
37111
|
+
// src/git/changes/listing/list-changed-files-for-commit.ts
|
|
36764
37112
|
async function listChangedFilesForCommit(repoGitCwd, repoRelPath, commitSha) {
|
|
36765
37113
|
const g = cliSimpleGit(repoGitCwd);
|
|
36766
37114
|
const parent = await parentForCommitDiff(g, commitSha);
|
|
36767
37115
|
const range = `${parent}..${commitSha}`;
|
|
36768
37116
|
const [nameStatusRaw, numstatRaw] = await Promise.all([
|
|
36769
|
-
g.raw(["diff", "--name-status", range]).catch(() => ""),
|
|
36770
|
-
g.raw(["diff", "--numstat", range]).catch(() => "")
|
|
37117
|
+
g.raw(["diff", ...RENAME_DIFF_ARGS, "--name-status", range]).catch(() => ""),
|
|
37118
|
+
g.raw(["diff", ...RENAME_DIFF_ARGS, "--numstat", range]).catch(() => "")
|
|
36771
37119
|
]);
|
|
36772
|
-
const
|
|
36773
|
-
const
|
|
36774
|
-
const paths =
|
|
36775
|
-
|
|
36776
|
-
|
|
36777
|
-
await forEachWithGitYield([...paths], async (pathInRepo) => {
|
|
36778
|
-
const relLauncher = posixJoinDirFile(normRel, pathInRepo.replace(/\\/g, "/"));
|
|
36779
|
-
const nums = numByPath.get(pathInRepo);
|
|
36780
|
-
let additions = nums?.additions ?? 0;
|
|
36781
|
-
let deletions = nums?.deletions ?? 0;
|
|
36782
|
-
let change = kindByPath.get(pathInRepo) ?? "modified";
|
|
36783
|
-
if (!kindByPath.has(pathInRepo) && nums) {
|
|
36784
|
-
if (additions > 0 && deletions === 0) change = "added";
|
|
36785
|
-
else if (deletions > 0 && additions === 0) change = "removed";
|
|
36786
|
-
else change = "modified";
|
|
36787
|
-
}
|
|
36788
|
-
rows.push({ pathRelLauncher: relLauncher, additions, deletions, change });
|
|
36789
|
-
});
|
|
36790
|
-
await forEachWithGitYield(rows, async (row) => {
|
|
36791
|
-
let pathInRepo;
|
|
36792
|
-
if (normRel === ".") {
|
|
36793
|
-
pathInRepo = row.pathRelLauncher;
|
|
36794
|
-
} else if (row.pathRelLauncher.startsWith(`${normRel}/`)) {
|
|
36795
|
-
pathInRepo = row.pathRelLauncher.slice(normRel.length + 1);
|
|
36796
|
-
} else {
|
|
36797
|
-
pathInRepo = row.pathRelLauncher;
|
|
36798
|
-
}
|
|
36799
|
-
const raw = await g.raw(["diff", "-U20000", range, "--", pathInRepo]).catch(() => "");
|
|
36800
|
-
const t = String(raw).trim();
|
|
36801
|
-
row.patchContent = t ? truncatePatch(t) : void 0;
|
|
37120
|
+
const parsed = parseDiffOutput(String(nameStatusRaw), String(numstatRaw));
|
|
37121
|
+
const normRel = normalizeRepoRelPath(repoRelPath);
|
|
37122
|
+
const paths = collectChangedPaths({
|
|
37123
|
+
nameEntries: parsed.nameEntries,
|
|
37124
|
+
numByPath: parsed.numByPath
|
|
36802
37125
|
});
|
|
36803
|
-
rows
|
|
36804
|
-
|
|
36805
|
-
|
|
36806
|
-
|
|
36807
|
-
|
|
37126
|
+
let rows = await buildChangedFileRowsFromPaths({
|
|
37127
|
+
paths,
|
|
37128
|
+
repoRelPath: normRel,
|
|
37129
|
+
nameByPath: parsed.nameByPath,
|
|
37130
|
+
numByPath: parsed.numByPath,
|
|
37131
|
+
movedSourcePaths: parsed.movedSourcePaths
|
|
37132
|
+
});
|
|
37133
|
+
rows = dedupeChangedFileRows(rows);
|
|
37134
|
+
await enrichCommitFileRows({
|
|
37135
|
+
rows,
|
|
37136
|
+
repoGitCwd,
|
|
37137
|
+
repoRelPath: normRel,
|
|
37138
|
+
range,
|
|
37139
|
+
commitSha,
|
|
37140
|
+
parentSha: parent,
|
|
37141
|
+
binaryByPath: parsed.binaryByPath
|
|
37142
|
+
});
|
|
37143
|
+
const finalRows = dedupeChangedFileRows(rows);
|
|
37144
|
+
finalRows.sort((a, b) => a.pathRelLauncher.localeCompare(b.pathRelLauncher));
|
|
37145
|
+
return finalRows;
|
|
37146
|
+
}
|
|
37147
|
+
|
|
37148
|
+
// src/git/changes/listing/apply-untracked-file-stats.ts
|
|
36808
37149
|
import * as fs18 from "node:fs";
|
|
36809
|
-
import * as
|
|
36810
|
-
|
|
36811
|
-
|
|
36812
|
-
|
|
36813
|
-
|
|
36814
|
-
|
|
36815
|
-
|
|
36816
|
-
|
|
36817
|
-
|
|
36818
|
-
|
|
36819
|
-
|
|
36820
|
-
|
|
36821
|
-
lines += 1;
|
|
36822
|
-
bytes += Buffer.byteLength(String(_line), "utf8") + 1;
|
|
36823
|
-
if (bytes > maxBytes) {
|
|
36824
|
-
rl.close();
|
|
36825
|
-
stream.destroy();
|
|
36826
|
-
return lines;
|
|
37150
|
+
import * as path21 from "node:path";
|
|
37151
|
+
function createUntrackedStatsApplier(options) {
|
|
37152
|
+
return async (row, pathInRepo) => {
|
|
37153
|
+
if (!options.untrackedSet.has(pathInRepo)) return;
|
|
37154
|
+
if (options.nameByPath.has(pathInRepo)) return;
|
|
37155
|
+
if (row.change === "moved") return;
|
|
37156
|
+
const repoFilePath = path21.join(options.repoGitCwd, pathInRepo);
|
|
37157
|
+
const fromGit = await numstatFromGitNoIndex(options.g, pathInRepo);
|
|
37158
|
+
if (fromGit) {
|
|
37159
|
+
row.additions = fromGit.additions;
|
|
37160
|
+
row.deletions = fromGit.deletions;
|
|
37161
|
+
return;
|
|
36827
37162
|
}
|
|
36828
|
-
|
|
36829
|
-
|
|
37163
|
+
try {
|
|
37164
|
+
const st = await fs18.promises.stat(repoFilePath);
|
|
37165
|
+
row.additions = st.isFile() ? await countTextFileLines(repoFilePath) : 0;
|
|
37166
|
+
} catch {
|
|
37167
|
+
row.additions = 0;
|
|
37168
|
+
}
|
|
37169
|
+
row.deletions = 0;
|
|
37170
|
+
};
|
|
36830
37171
|
}
|
|
36831
37172
|
|
|
36832
|
-
// src/git/changes/
|
|
36833
|
-
import * as
|
|
37173
|
+
// src/git/changes/listing/enrich-working-tree-file-rows.ts
|
|
37174
|
+
import * as path22 from "node:path";
|
|
37175
|
+
|
|
37176
|
+
// src/git/changes/patch/hydrate-patch.ts
|
|
37177
|
+
import * as fs19 from "node:fs";
|
|
36834
37178
|
var UNIFIED_HUNK_HEADER_RE = /^@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@/;
|
|
36835
37179
|
var MAX_HYDRATE_LINES_PER_GAP = 8e3;
|
|
36836
37180
|
var MAX_HYDRATE_LINES_PER_FILE = 8e4;
|
|
@@ -36845,7 +37189,7 @@ async function readGitBlobLines(repoCwd, pathInRepo) {
|
|
|
36845
37189
|
}
|
|
36846
37190
|
async function readWorktreeFileLines(filePath) {
|
|
36847
37191
|
try {
|
|
36848
|
-
const raw = await
|
|
37192
|
+
const raw = await fs19.promises.readFile(filePath, "utf8");
|
|
36849
37193
|
return raw.split(/\r?\n/);
|
|
36850
37194
|
} catch {
|
|
36851
37195
|
return null;
|
|
@@ -36945,82 +37289,70 @@ async function hydrateUnifiedPatchWithFileContext(patch, filePath, repoGitCwd, p
|
|
|
36945
37289
|
return truncatePatch(out.join("\n"));
|
|
36946
37290
|
}
|
|
36947
37291
|
|
|
36948
|
-
// src/git/changes/
|
|
36949
|
-
function
|
|
36950
|
-
|
|
36951
|
-
|
|
36952
|
-
|
|
36953
|
-
|
|
36954
|
-
|
|
36955
|
-
|
|
36956
|
-
|
|
36957
|
-
|
|
36958
|
-
|
|
37292
|
+
// src/git/changes/listing/enrich-working-tree-file-rows.ts
|
|
37293
|
+
async function enrichWorkingTreeFileRows(options) {
|
|
37294
|
+
await forEachWithGitYield(options.rows, async (row) => {
|
|
37295
|
+
const pathInRepo = pathInRepoFromLauncher(row.pathRelLauncher, options.repoRelPath);
|
|
37296
|
+
const filePath = path22.join(options.repoGitCwd, pathInRepo);
|
|
37297
|
+
const hydrateKind = row.change === "moved" ? "modified" : row.change;
|
|
37298
|
+
let patch = await unifiedDiffForFile(options.repoGitCwd, pathInRepo, row.change, row.movedFromPathInRepo);
|
|
37299
|
+
if (patch) {
|
|
37300
|
+
patch = await hydrateUnifiedPatchWithFileContext(
|
|
37301
|
+
patch,
|
|
37302
|
+
filePath,
|
|
37303
|
+
options.repoGitCwd,
|
|
37304
|
+
pathInRepo,
|
|
37305
|
+
hydrateKind
|
|
37306
|
+
);
|
|
37307
|
+
}
|
|
37308
|
+
row.patchContent = patch;
|
|
37309
|
+
row.totalLines = await resolveWorkingTreeFileTotalLines({
|
|
37310
|
+
repoGitCwd: options.repoGitCwd,
|
|
37311
|
+
pathInRepo,
|
|
37312
|
+
change: row.change,
|
|
37313
|
+
isBinary: options.binaryByPath.has(pathInRepo)
|
|
37314
|
+
});
|
|
37315
|
+
});
|
|
36959
37316
|
}
|
|
36960
37317
|
|
|
36961
|
-
// src/git/changes/list-changed-files-for-repo.ts
|
|
37318
|
+
// src/git/changes/listing/list-changed-files-for-repo.ts
|
|
36962
37319
|
async function listChangedFilesForRepo(repoGitCwd, repoRelPath) {
|
|
36963
37320
|
const g = cliSimpleGit(repoGitCwd);
|
|
36964
37321
|
const [nameStatusRaw, numstatRaw, untrackedRaw] = await Promise.all([
|
|
36965
|
-
g.raw(["diff", "--name-status", "HEAD"]).catch(() => ""),
|
|
36966
|
-
g.raw(["diff", "HEAD", "--numstat"]).catch(() => ""),
|
|
37322
|
+
g.raw(["diff", ...RENAME_DIFF_ARGS, "--name-status", "HEAD"]).catch(() => ""),
|
|
37323
|
+
g.raw(["diff", ...RENAME_DIFF_ARGS, "HEAD", "--numstat"]).catch(() => ""),
|
|
36967
37324
|
g.raw(["ls-files", "--others", "--exclude-standard"]).catch(() => "")
|
|
36968
37325
|
]);
|
|
36969
|
-
const
|
|
36970
|
-
const numByPath = parseNumstat(String(numstatRaw).split("\n"));
|
|
36971
|
-
const paths = /* @__PURE__ */ new Set([...kindByPath.keys(), ...numByPath.keys()]);
|
|
37326
|
+
const parsed = parseDiffOutput(String(nameStatusRaw), String(numstatRaw));
|
|
36972
37327
|
const untracked = String(untrackedRaw).split("\n").map((s) => s.trim()).filter(Boolean);
|
|
36973
|
-
|
|
36974
|
-
const
|
|
36975
|
-
|
|
36976
|
-
|
|
36977
|
-
|
|
36978
|
-
const nums = numByPath.get(pathInRepo);
|
|
36979
|
-
let additions = nums?.additions ?? 0;
|
|
36980
|
-
let deletions = nums?.deletions ?? 0;
|
|
36981
|
-
let change = kindByPath.get(pathInRepo) ?? "modified";
|
|
36982
|
-
if (untracked.includes(pathInRepo) && !kindByPath.has(pathInRepo)) {
|
|
36983
|
-
change = "added";
|
|
36984
|
-
const fromGit = await numstatFromGitNoIndex(g, pathInRepo);
|
|
36985
|
-
if (fromGit) {
|
|
36986
|
-
additions = fromGit.additions;
|
|
36987
|
-
deletions = fromGit.deletions;
|
|
36988
|
-
} else {
|
|
36989
|
-
try {
|
|
36990
|
-
const st = await fs18.promises.stat(repoFilePath);
|
|
36991
|
-
if (st.isFile()) additions = await countTextFileLines(repoFilePath);
|
|
36992
|
-
else additions = 0;
|
|
36993
|
-
} catch {
|
|
36994
|
-
additions = 0;
|
|
36995
|
-
}
|
|
36996
|
-
deletions = 0;
|
|
36997
|
-
}
|
|
36998
|
-
}
|
|
36999
|
-
if (!kindByPath.has(pathInRepo) && nums) {
|
|
37000
|
-
if (additions > 0 && deletions === 0) change = "added";
|
|
37001
|
-
else if (deletions > 0 && additions === 0) change = "removed";
|
|
37002
|
-
else change = "modified";
|
|
37003
|
-
}
|
|
37004
|
-
rows.push({ pathRelLauncher: relLauncher, additions, deletions, change });
|
|
37328
|
+
const untrackedSet = new Set(untracked);
|
|
37329
|
+
const paths = collectChangedPaths({
|
|
37330
|
+
nameEntries: parsed.nameEntries,
|
|
37331
|
+
numByPath: parsed.numByPath,
|
|
37332
|
+
untracked
|
|
37005
37333
|
});
|
|
37006
|
-
|
|
37007
|
-
|
|
37008
|
-
|
|
37009
|
-
|
|
37010
|
-
|
|
37011
|
-
|
|
37012
|
-
|
|
37013
|
-
|
|
37014
|
-
|
|
37015
|
-
|
|
37016
|
-
|
|
37017
|
-
|
|
37018
|
-
|
|
37019
|
-
patch = await hydrateUnifiedPatchWithFileContext(patch, filePath, repoGitCwd, pathInRepo, row.change);
|
|
37020
|
-
}
|
|
37021
|
-
row.patchContent = patch;
|
|
37334
|
+
let rows = await buildChangedFileRowsFromPaths({
|
|
37335
|
+
paths,
|
|
37336
|
+
repoRelPath,
|
|
37337
|
+
nameByPath: parsed.nameByPath,
|
|
37338
|
+
numByPath: parsed.numByPath,
|
|
37339
|
+
movedSourcePaths: parsed.movedSourcePaths,
|
|
37340
|
+
untrackedSet,
|
|
37341
|
+
applyUntrackedStats: createUntrackedStatsApplier({
|
|
37342
|
+
g,
|
|
37343
|
+
repoGitCwd,
|
|
37344
|
+
untrackedSet,
|
|
37345
|
+
nameByPath: parsed.nameByPath
|
|
37346
|
+
})
|
|
37022
37347
|
});
|
|
37023
|
-
|
|
37348
|
+
rows = dedupeChangedFileRows(rows);
|
|
37349
|
+
await enrichWorkingTreeFileRows({
|
|
37350
|
+
rows,
|
|
37351
|
+
repoGitCwd,
|
|
37352
|
+
repoRelPath,
|
|
37353
|
+
binaryByPath: parsed.binaryByPath
|
|
37354
|
+
});
|
|
37355
|
+
return dedupeChangedFileRows(rows);
|
|
37024
37356
|
}
|
|
37025
37357
|
|
|
37026
37358
|
// src/git/changes/get-working-tree-change-repo-details.ts
|
|
@@ -37029,8 +37361,8 @@ function normRepoRel(p) {
|
|
|
37029
37361
|
return x === "" ? "." : x;
|
|
37030
37362
|
}
|
|
37031
37363
|
async function getWorkingTreeChangeRepoDetails(options) {
|
|
37032
|
-
const bridgeRoot =
|
|
37033
|
-
const sessionWtRoot = options.sessionWorktreeRootPath ?
|
|
37364
|
+
const bridgeRoot = path23.resolve(getBridgeRoot());
|
|
37365
|
+
const sessionWtRoot = options.sessionWorktreeRootPath ? path23.resolve(options.sessionWorktreeRootPath) : null;
|
|
37034
37366
|
const legacyNested = options.legacyRepoNestedSessionLayout === true;
|
|
37035
37367
|
const out = [];
|
|
37036
37368
|
const filter = options.repoFilterRelPath != null ? normRepoRel(options.repoFilterRelPath) : null;
|
|
@@ -37045,7 +37377,7 @@ async function getWorkingTreeChangeRepoDetails(options) {
|
|
|
37045
37377
|
for (let i = 0; i < options.commitTargetPaths.length; i++) {
|
|
37046
37378
|
if (i > 0) await yieldToEventLoop2();
|
|
37047
37379
|
const target = options.commitTargetPaths[i];
|
|
37048
|
-
const t =
|
|
37380
|
+
const t = path23.resolve(target);
|
|
37049
37381
|
if (!await isGitRepoDirectory(t)) continue;
|
|
37050
37382
|
const g = cliSimpleGit(t);
|
|
37051
37383
|
let branch = "HEAD";
|
|
@@ -37058,8 +37390,8 @@ async function getWorkingTreeChangeRepoDetails(options) {
|
|
|
37058
37390
|
const remoteDisplay = formatRemoteDisplayLabel(remoteUrl);
|
|
37059
37391
|
let repoRelPath;
|
|
37060
37392
|
if (sessionWtRoot) {
|
|
37061
|
-
const anchor = legacyNested ?
|
|
37062
|
-
const relNorm =
|
|
37393
|
+
const anchor = legacyNested ? path23.dirname(t) : t;
|
|
37394
|
+
const relNorm = path23.relative(sessionWtRoot, anchor);
|
|
37063
37395
|
repoRelPath = relNorm === "" ? "." : relNorm.replace(/\\/g, "/");
|
|
37064
37396
|
} else {
|
|
37065
37397
|
let top = t;
|
|
@@ -37068,8 +37400,8 @@ async function getWorkingTreeChangeRepoDetails(options) {
|
|
|
37068
37400
|
} catch {
|
|
37069
37401
|
top = t;
|
|
37070
37402
|
}
|
|
37071
|
-
const rel =
|
|
37072
|
-
repoRelPath = rel.startsWith("..") ?
|
|
37403
|
+
const rel = path23.relative(bridgeRoot, path23.resolve(top)).replace(/\\/g, "/") || ".";
|
|
37404
|
+
repoRelPath = rel.startsWith("..") ? path23.basename(path23.resolve(top)) : rel;
|
|
37073
37405
|
}
|
|
37074
37406
|
const norm = normRepoRel(repoRelPath === "" ? "." : repoRelPath);
|
|
37075
37407
|
if (filter && norm !== filter) continue;
|
|
@@ -37101,7 +37433,7 @@ async function getWorkingTreeChangeRepoDetails(options) {
|
|
|
37101
37433
|
return out;
|
|
37102
37434
|
}
|
|
37103
37435
|
|
|
37104
|
-
// src/git/changes/
|
|
37436
|
+
// src/git/changes/status/working-tree-changed-path-count.ts
|
|
37105
37437
|
function workingTreeChangedPathCount(nameStatusLines, numstatLines, untrackedLines) {
|
|
37106
37438
|
const kindByPath = parseNameStatusLines(nameStatusLines);
|
|
37107
37439
|
const numByPath = parseNumstat(numstatLines);
|
|
@@ -37197,23 +37529,23 @@ async function commitSessionWorktrees(options) {
|
|
|
37197
37529
|
}
|
|
37198
37530
|
|
|
37199
37531
|
// src/worktrees/remove-session-worktrees.ts
|
|
37200
|
-
import * as
|
|
37532
|
+
import * as fs22 from "node:fs";
|
|
37201
37533
|
|
|
37202
37534
|
// src/git/worktrees/worktree-remove.ts
|
|
37203
|
-
import * as
|
|
37535
|
+
import * as fs21 from "node:fs";
|
|
37204
37536
|
|
|
37205
37537
|
// src/git/worktrees/resolve-main-repo-from-git-file.ts
|
|
37206
|
-
import * as
|
|
37207
|
-
import * as
|
|
37538
|
+
import * as fs20 from "node:fs";
|
|
37539
|
+
import * as path24 from "node:path";
|
|
37208
37540
|
function resolveMainRepoFromWorktreeGitFile(wt) {
|
|
37209
|
-
const gitDirFile =
|
|
37210
|
-
if (!
|
|
37211
|
-
const first2 =
|
|
37541
|
+
const gitDirFile = path24.join(wt, ".git");
|
|
37542
|
+
if (!fs20.existsSync(gitDirFile) || !fs20.statSync(gitDirFile).isFile()) return "";
|
|
37543
|
+
const first2 = fs20.readFileSync(gitDirFile, "utf8").trim();
|
|
37212
37544
|
const m = first2.match(/^gitdir:\s*(.+)$/im);
|
|
37213
37545
|
if (!m) return "";
|
|
37214
|
-
const gitWorktreePath =
|
|
37215
|
-
const gitDir =
|
|
37216
|
-
return
|
|
37546
|
+
const gitWorktreePath = path24.resolve(wt, m[1].trim());
|
|
37547
|
+
const gitDir = path24.dirname(path24.dirname(gitWorktreePath));
|
|
37548
|
+
return path24.dirname(gitDir);
|
|
37217
37549
|
}
|
|
37218
37550
|
|
|
37219
37551
|
// src/git/worktrees/worktree-remove.ts
|
|
@@ -37222,7 +37554,7 @@ async function gitWorktreeRemoveForce(worktreePath) {
|
|
|
37222
37554
|
if (mainRepo) {
|
|
37223
37555
|
await cliSimpleGit(mainRepo).raw(["worktree", "remove", "--force", worktreePath]);
|
|
37224
37556
|
} else {
|
|
37225
|
-
|
|
37557
|
+
fs21.rmSync(worktreePath, { recursive: true, force: true });
|
|
37226
37558
|
}
|
|
37227
37559
|
}
|
|
37228
37560
|
|
|
@@ -37235,7 +37567,7 @@ async function removeSessionWorktrees(paths, log2) {
|
|
|
37235
37567
|
} catch (e) {
|
|
37236
37568
|
log2(`[worktrees] Remove failed for ${wt}: ${e instanceof Error ? e.message : String(e)}`);
|
|
37237
37569
|
try {
|
|
37238
|
-
|
|
37570
|
+
fs22.rmSync(wt, { recursive: true, force: true });
|
|
37239
37571
|
} catch {
|
|
37240
37572
|
}
|
|
37241
37573
|
}
|
|
@@ -37264,12 +37596,12 @@ async function renameSessionWorktreeBranches(paths, newBranch, log2) {
|
|
|
37264
37596
|
}
|
|
37265
37597
|
|
|
37266
37598
|
// src/worktrees/worktree-layout-file.ts
|
|
37267
|
-
import * as
|
|
37268
|
-
import * as
|
|
37599
|
+
import * as fs23 from "node:fs";
|
|
37600
|
+
import * as path25 from "node:path";
|
|
37269
37601
|
import os7 from "node:os";
|
|
37270
37602
|
var LAYOUT_FILENAME = "worktree-launcher-layout.json";
|
|
37271
37603
|
function defaultWorktreeLayoutPath() {
|
|
37272
|
-
return
|
|
37604
|
+
return path25.join(os7.homedir(), ".buildautomaton", LAYOUT_FILENAME);
|
|
37273
37605
|
}
|
|
37274
37606
|
function normalizeLoadedLayout(raw) {
|
|
37275
37607
|
if (raw && typeof raw === "object" && "launcherCwds" in raw) {
|
|
@@ -37281,8 +37613,8 @@ function normalizeLoadedLayout(raw) {
|
|
|
37281
37613
|
function loadWorktreeLayout() {
|
|
37282
37614
|
try {
|
|
37283
37615
|
const p = defaultWorktreeLayoutPath();
|
|
37284
|
-
if (!
|
|
37285
|
-
const raw = JSON.parse(
|
|
37616
|
+
if (!fs23.existsSync(p)) return { launcherCwds: [] };
|
|
37617
|
+
const raw = JSON.parse(fs23.readFileSync(p, "utf8"));
|
|
37286
37618
|
return normalizeLoadedLayout(raw);
|
|
37287
37619
|
} catch {
|
|
37288
37620
|
return { launcherCwds: [] };
|
|
@@ -37290,24 +37622,24 @@ function loadWorktreeLayout() {
|
|
|
37290
37622
|
}
|
|
37291
37623
|
function saveWorktreeLayout(layout) {
|
|
37292
37624
|
try {
|
|
37293
|
-
const dir =
|
|
37294
|
-
|
|
37295
|
-
|
|
37625
|
+
const dir = path25.dirname(defaultWorktreeLayoutPath());
|
|
37626
|
+
fs23.mkdirSync(dir, { recursive: true });
|
|
37627
|
+
fs23.writeFileSync(defaultWorktreeLayoutPath(), JSON.stringify(layout, null, 2), "utf8");
|
|
37296
37628
|
} catch {
|
|
37297
37629
|
}
|
|
37298
37630
|
}
|
|
37299
37631
|
function baseNameSafe(pathString) {
|
|
37300
|
-
return
|
|
37632
|
+
return path25.basename(pathString).replace(/[^a-zA-Z0-9._-]+/g, "-") || "cwd";
|
|
37301
37633
|
}
|
|
37302
37634
|
function getLauncherDirNameIfPresent(layout, bridgeRootPath2) {
|
|
37303
|
-
const norm =
|
|
37304
|
-
const existing = layout.launcherCwds.find((e) =>
|
|
37635
|
+
const norm = path25.resolve(bridgeRootPath2);
|
|
37636
|
+
const existing = layout.launcherCwds.find((e) => path25.resolve(e.absolutePath) === norm);
|
|
37305
37637
|
return existing?.dirName;
|
|
37306
37638
|
}
|
|
37307
37639
|
function allocateDirNameForLauncherCwd(layout, bridgeRootPath2) {
|
|
37308
37640
|
const existing = getLauncherDirNameIfPresent(layout, bridgeRootPath2);
|
|
37309
37641
|
if (existing) return existing;
|
|
37310
|
-
const norm =
|
|
37642
|
+
const norm = path25.resolve(bridgeRootPath2);
|
|
37311
37643
|
const base = baseNameSafe(norm);
|
|
37312
37644
|
const used = new Set(layout.launcherCwds.map((e) => e.dirName));
|
|
37313
37645
|
let name = base;
|
|
@@ -37322,11 +37654,11 @@ function allocateDirNameForLauncherCwd(layout, bridgeRootPath2) {
|
|
|
37322
37654
|
}
|
|
37323
37655
|
|
|
37324
37656
|
// src/worktrees/discover-session-worktree-on-disk.ts
|
|
37325
|
-
import * as
|
|
37326
|
-
import * as
|
|
37657
|
+
import * as fs24 from "node:fs";
|
|
37658
|
+
import * as path26 from "node:path";
|
|
37327
37659
|
function isGitDir(dirPath) {
|
|
37328
37660
|
try {
|
|
37329
|
-
return
|
|
37661
|
+
return fs24.existsSync(path26.join(dirPath, ".git"));
|
|
37330
37662
|
} catch {
|
|
37331
37663
|
return false;
|
|
37332
37664
|
}
|
|
@@ -37335,23 +37667,23 @@ function collectGitRepoRootsUnderDirectory(rootPath) {
|
|
|
37335
37667
|
const out = [];
|
|
37336
37668
|
const walk = (dir) => {
|
|
37337
37669
|
if (isGitDir(dir)) {
|
|
37338
|
-
out.push(
|
|
37670
|
+
out.push(path26.resolve(dir));
|
|
37339
37671
|
return;
|
|
37340
37672
|
}
|
|
37341
37673
|
let entries;
|
|
37342
37674
|
try {
|
|
37343
|
-
entries =
|
|
37675
|
+
entries = fs24.readdirSync(dir, { withFileTypes: true });
|
|
37344
37676
|
} catch {
|
|
37345
37677
|
return;
|
|
37346
37678
|
}
|
|
37347
37679
|
for (const e of entries) {
|
|
37348
37680
|
if (e.name.startsWith(".")) continue;
|
|
37349
|
-
const full =
|
|
37681
|
+
const full = path26.join(dir, e.name);
|
|
37350
37682
|
if (!e.isDirectory()) continue;
|
|
37351
37683
|
walk(full);
|
|
37352
37684
|
}
|
|
37353
37685
|
};
|
|
37354
|
-
walk(
|
|
37686
|
+
walk(path26.resolve(rootPath));
|
|
37355
37687
|
return [...new Set(out)];
|
|
37356
37688
|
}
|
|
37357
37689
|
function collectWorktreeRootsNamed(root, sessionId, maxDepth) {
|
|
@@ -37360,16 +37692,16 @@ function collectWorktreeRootsNamed(root, sessionId, maxDepth) {
|
|
|
37360
37692
|
if (depth > maxDepth) return;
|
|
37361
37693
|
let entries;
|
|
37362
37694
|
try {
|
|
37363
|
-
entries =
|
|
37695
|
+
entries = fs24.readdirSync(dir, { withFileTypes: true });
|
|
37364
37696
|
} catch {
|
|
37365
37697
|
return;
|
|
37366
37698
|
}
|
|
37367
37699
|
for (const e of entries) {
|
|
37368
37700
|
if (e.name.startsWith(".")) continue;
|
|
37369
|
-
const full =
|
|
37701
|
+
const full = path26.join(dir, e.name);
|
|
37370
37702
|
if (!e.isDirectory()) continue;
|
|
37371
37703
|
if (e.name === sessionId) {
|
|
37372
|
-
if (isGitDir(full)) out.push(
|
|
37704
|
+
if (isGitDir(full)) out.push(path26.resolve(full));
|
|
37373
37705
|
} else {
|
|
37374
37706
|
walk(full, depth + 1);
|
|
37375
37707
|
}
|
|
@@ -37381,14 +37713,14 @@ function collectWorktreeRootsNamed(root, sessionId, maxDepth) {
|
|
|
37381
37713
|
function tryBindingFromSessionDirectory(sessionDir) {
|
|
37382
37714
|
let st;
|
|
37383
37715
|
try {
|
|
37384
|
-
st =
|
|
37716
|
+
st = fs24.statSync(sessionDir);
|
|
37385
37717
|
} catch {
|
|
37386
37718
|
return null;
|
|
37387
37719
|
}
|
|
37388
37720
|
if (!st.isDirectory()) return null;
|
|
37389
37721
|
const worktreePaths = collectGitRepoRootsUnderDirectory(sessionDir);
|
|
37390
37722
|
if (worktreePaths.length === 0) return null;
|
|
37391
|
-
const abs =
|
|
37723
|
+
const abs = path26.resolve(sessionDir);
|
|
37392
37724
|
return {
|
|
37393
37725
|
sessionParentPath: abs,
|
|
37394
37726
|
workingTreeRelRoot: abs,
|
|
@@ -37398,20 +37730,20 @@ function tryBindingFromSessionDirectory(sessionDir) {
|
|
|
37398
37730
|
function discoverLegacyBindingAscendingFromCheckout(sessionId, checkoutPath) {
|
|
37399
37731
|
const sid = sessionId.trim();
|
|
37400
37732
|
if (!sid) return null;
|
|
37401
|
-
const hintR =
|
|
37733
|
+
const hintR = path26.resolve(checkoutPath);
|
|
37402
37734
|
let best = null;
|
|
37403
|
-
let cur =
|
|
37735
|
+
let cur = path26.dirname(hintR);
|
|
37404
37736
|
for (let i = 0; i < 40; i++) {
|
|
37405
37737
|
const paths = collectWorktreeRootsNamed(cur, sid, 24);
|
|
37406
|
-
if (paths.some((p) =>
|
|
37407
|
-
const isolated = resolveIsolatedSessionParentPathFromCheckouts(paths) ??
|
|
37738
|
+
if (paths.some((p) => path26.resolve(p) === hintR)) {
|
|
37739
|
+
const isolated = resolveIsolatedSessionParentPathFromCheckouts(paths) ?? path26.resolve(paths[0]);
|
|
37408
37740
|
best = {
|
|
37409
|
-
sessionParentPath:
|
|
37410
|
-
workingTreeRelRoot:
|
|
37411
|
-
repoCheckoutPaths: paths.map((p) =>
|
|
37741
|
+
sessionParentPath: path26.resolve(isolated),
|
|
37742
|
+
workingTreeRelRoot: path26.resolve(cur),
|
|
37743
|
+
repoCheckoutPaths: paths.map((p) => path26.resolve(p))
|
|
37412
37744
|
};
|
|
37413
37745
|
}
|
|
37414
|
-
const next =
|
|
37746
|
+
const next = path26.dirname(cur);
|
|
37415
37747
|
if (next === cur) break;
|
|
37416
37748
|
cur = next;
|
|
37417
37749
|
}
|
|
@@ -37419,33 +37751,33 @@ function discoverLegacyBindingAscendingFromCheckout(sessionId, checkoutPath) {
|
|
|
37419
37751
|
}
|
|
37420
37752
|
function discoverSessionWorktreeOnDisk(options) {
|
|
37421
37753
|
const { sessionId, worktreesRootPath, layout, bridgeRoot } = options;
|
|
37422
|
-
if (!sessionId.trim() || !
|
|
37754
|
+
if (!sessionId.trim() || !fs24.existsSync(worktreesRootPath)) return null;
|
|
37423
37755
|
const preferredKey = getLauncherDirNameIfPresent(layout, bridgeRoot);
|
|
37424
37756
|
const keys = [];
|
|
37425
37757
|
if (preferredKey) keys.push(preferredKey);
|
|
37426
37758
|
try {
|
|
37427
|
-
for (const name of
|
|
37759
|
+
for (const name of fs24.readdirSync(worktreesRootPath)) {
|
|
37428
37760
|
if (name.startsWith(".")) continue;
|
|
37429
|
-
const p =
|
|
37430
|
-
if (!
|
|
37761
|
+
const p = path26.join(worktreesRootPath, name);
|
|
37762
|
+
if (!fs24.statSync(p).isDirectory()) continue;
|
|
37431
37763
|
if (name !== preferredKey) keys.push(name);
|
|
37432
37764
|
}
|
|
37433
37765
|
} catch {
|
|
37434
37766
|
return null;
|
|
37435
37767
|
}
|
|
37436
37768
|
for (const key of keys) {
|
|
37437
|
-
const layoutRoot =
|
|
37438
|
-
if (!
|
|
37439
|
-
const sessionDir =
|
|
37769
|
+
const layoutRoot = path26.join(worktreesRootPath, key);
|
|
37770
|
+
if (!fs24.existsSync(layoutRoot) || !fs24.statSync(layoutRoot).isDirectory()) continue;
|
|
37771
|
+
const sessionDir = path26.join(layoutRoot, sessionId);
|
|
37440
37772
|
const nested = tryBindingFromSessionDirectory(sessionDir);
|
|
37441
37773
|
if (nested) return nested;
|
|
37442
37774
|
const legacyPaths = collectWorktreeRootsNamed(layoutRoot, sessionId, 24);
|
|
37443
37775
|
if (legacyPaths.length > 0) {
|
|
37444
|
-
const isolated = resolveIsolatedSessionParentPathFromCheckouts(legacyPaths) ??
|
|
37776
|
+
const isolated = resolveIsolatedSessionParentPathFromCheckouts(legacyPaths) ?? path26.resolve(legacyPaths[0]);
|
|
37445
37777
|
return {
|
|
37446
|
-
sessionParentPath:
|
|
37447
|
-
workingTreeRelRoot:
|
|
37448
|
-
repoCheckoutPaths: legacyPaths.map((p) =>
|
|
37778
|
+
sessionParentPath: path26.resolve(isolated),
|
|
37779
|
+
workingTreeRelRoot: path26.resolve(layoutRoot),
|
|
37780
|
+
repoCheckoutPaths: legacyPaths.map((p) => path26.resolve(p))
|
|
37449
37781
|
};
|
|
37450
37782
|
}
|
|
37451
37783
|
}
|
|
@@ -37454,12 +37786,12 @@ function discoverSessionWorktreeOnDisk(options) {
|
|
|
37454
37786
|
function discoverSessionWorktreesUnderSessionWorktreeRoot(sessionWorktreeRootPathOrHint, sessionId) {
|
|
37455
37787
|
const sid = sessionId.trim();
|
|
37456
37788
|
if (!sid) return null;
|
|
37457
|
-
const hint =
|
|
37458
|
-
const underHint = tryBindingFromSessionDirectory(
|
|
37789
|
+
const hint = path26.resolve(sessionWorktreeRootPathOrHint);
|
|
37790
|
+
const underHint = tryBindingFromSessionDirectory(path26.join(hint, sid));
|
|
37459
37791
|
if (underHint) return underHint;
|
|
37460
37792
|
const direct = tryBindingFromSessionDirectory(hint);
|
|
37461
37793
|
if (direct) {
|
|
37462
|
-
if (
|
|
37794
|
+
if (path26.basename(hint) === sid && isGitDir(hint)) {
|
|
37463
37795
|
const legacyFromCheckout = discoverLegacyBindingAscendingFromCheckout(sid, hint);
|
|
37464
37796
|
if (legacyFromCheckout && legacyFromCheckout.repoCheckoutPaths.length > direct.repoCheckoutPaths.length) {
|
|
37465
37797
|
return legacyFromCheckout;
|
|
@@ -37467,24 +37799,24 @@ function discoverSessionWorktreesUnderSessionWorktreeRoot(sessionWorktreeRootPat
|
|
|
37467
37799
|
}
|
|
37468
37800
|
return direct;
|
|
37469
37801
|
}
|
|
37470
|
-
if (
|
|
37802
|
+
if (path26.basename(hint) === sid && isGitDir(hint)) {
|
|
37471
37803
|
const legacyFromCheckout = discoverLegacyBindingAscendingFromCheckout(sid, hint);
|
|
37472
37804
|
if (legacyFromCheckout) return legacyFromCheckout;
|
|
37473
37805
|
}
|
|
37474
37806
|
let st;
|
|
37475
37807
|
try {
|
|
37476
|
-
st =
|
|
37808
|
+
st = fs24.statSync(hint);
|
|
37477
37809
|
} catch {
|
|
37478
37810
|
return null;
|
|
37479
37811
|
}
|
|
37480
37812
|
if (!st.isDirectory()) return null;
|
|
37481
37813
|
const legacyPaths = collectWorktreeRootsNamed(hint, sid, 24);
|
|
37482
37814
|
if (legacyPaths.length === 0) return null;
|
|
37483
|
-
const isolated = resolveIsolatedSessionParentPathFromCheckouts(legacyPaths) ??
|
|
37815
|
+
const isolated = resolveIsolatedSessionParentPathFromCheckouts(legacyPaths) ?? path26.resolve(legacyPaths[0]);
|
|
37484
37816
|
return {
|
|
37485
|
-
sessionParentPath:
|
|
37817
|
+
sessionParentPath: path26.resolve(isolated),
|
|
37486
37818
|
workingTreeRelRoot: hint,
|
|
37487
|
-
repoCheckoutPaths: legacyPaths.map((p) =>
|
|
37819
|
+
repoCheckoutPaths: legacyPaths.map((p) => path26.resolve(p))
|
|
37488
37820
|
};
|
|
37489
37821
|
}
|
|
37490
37822
|
|
|
@@ -37541,8 +37873,8 @@ function parseSessionParent(v) {
|
|
|
37541
37873
|
}
|
|
37542
37874
|
|
|
37543
37875
|
// src/worktrees/prepare-new-session-worktrees.ts
|
|
37544
|
-
import * as
|
|
37545
|
-
import * as
|
|
37876
|
+
import * as fs25 from "node:fs";
|
|
37877
|
+
import * as path27 from "node:path";
|
|
37546
37878
|
|
|
37547
37879
|
// src/git/worktrees/worktree-add.ts
|
|
37548
37880
|
async function gitWorktreeAddBranch(mainRepoPath, worktreePath, branch, baseRef = "HEAD") {
|
|
@@ -37552,7 +37884,7 @@ async function gitWorktreeAddBranch(mainRepoPath, worktreePath, branch, baseRef
|
|
|
37552
37884
|
}
|
|
37553
37885
|
|
|
37554
37886
|
// src/worktrees/prepare-new-session-worktrees.ts
|
|
37555
|
-
function
|
|
37887
|
+
function normalizeRepoRelPath2(rel) {
|
|
37556
37888
|
return rel === "" ? "." : rel.replace(/\\/g, "/");
|
|
37557
37889
|
}
|
|
37558
37890
|
function resolveBaseRefForRepo(relNorm, baseBranches) {
|
|
@@ -37564,10 +37896,10 @@ function resolveBaseRefForRepo(relNorm, baseBranches) {
|
|
|
37564
37896
|
}
|
|
37565
37897
|
async function prepareNewSessionWorktrees(options) {
|
|
37566
37898
|
const { worktreesRootPath, bridgeRoot, sessionId, layout, log: log2, worktreeBaseBranches } = options;
|
|
37567
|
-
const bridgeResolved =
|
|
37899
|
+
const bridgeResolved = path27.resolve(bridgeRoot);
|
|
37568
37900
|
const cwdKey = allocateDirNameForLauncherCwd(layout, bridgeResolved);
|
|
37569
|
-
const bridgeKeyDir =
|
|
37570
|
-
const sessionDir =
|
|
37901
|
+
const bridgeKeyDir = path27.join(worktreesRootPath, cwdKey);
|
|
37902
|
+
const sessionDir = path27.join(bridgeKeyDir, sessionId);
|
|
37571
37903
|
const repos = await discoverGitReposUnderRoot(bridgeResolved);
|
|
37572
37904
|
if (repos.length === 0) {
|
|
37573
37905
|
log2("[worktrees] No Git repositories under bridge root; skipping worktree creation.");
|
|
@@ -37575,14 +37907,14 @@ async function prepareNewSessionWorktrees(options) {
|
|
|
37575
37907
|
}
|
|
37576
37908
|
const branch = `session-${sessionId}`;
|
|
37577
37909
|
const worktreePaths = [];
|
|
37578
|
-
|
|
37910
|
+
fs25.mkdirSync(sessionDir, { recursive: true });
|
|
37579
37911
|
for (const repo of repos) {
|
|
37580
|
-
let rel =
|
|
37581
|
-
if (rel.startsWith("..") ||
|
|
37582
|
-
const relNorm =
|
|
37583
|
-
const wtPath = relNorm === "." ? sessionDir :
|
|
37912
|
+
let rel = path27.relative(bridgeResolved, repo.absolutePath);
|
|
37913
|
+
if (rel.startsWith("..") || path27.isAbsolute(rel)) continue;
|
|
37914
|
+
const relNorm = normalizeRepoRelPath2(rel === "" ? "." : rel);
|
|
37915
|
+
const wtPath = relNorm === "." ? sessionDir : path27.join(sessionDir, relNorm);
|
|
37584
37916
|
if (relNorm !== ".") {
|
|
37585
|
-
|
|
37917
|
+
fs25.mkdirSync(path27.dirname(wtPath), { recursive: true });
|
|
37586
37918
|
}
|
|
37587
37919
|
const baseRef = resolveBaseRefForRepo(relNorm, worktreeBaseBranches);
|
|
37588
37920
|
try {
|
|
@@ -37635,9 +37967,9 @@ function resolveExistingSessionParentPath(sessionId, cache2, discover) {
|
|
|
37635
37967
|
}
|
|
37636
37968
|
|
|
37637
37969
|
// src/worktrees/manager/resolve-explicit-session-parent-path.ts
|
|
37638
|
-
import * as
|
|
37970
|
+
import * as path28 from "node:path";
|
|
37639
37971
|
function resolveExplicitSessionParentPath(params) {
|
|
37640
|
-
const resolved =
|
|
37972
|
+
const resolved = path28.resolve(params.parentPathRaw);
|
|
37641
37973
|
if (parseSessionParent(params.sessionParent) !== "worktrees_root") {
|
|
37642
37974
|
return resolved;
|
|
37643
37975
|
}
|
|
@@ -37653,7 +37985,7 @@ function resolveExplicitSessionParentPath(params) {
|
|
|
37653
37985
|
for (let i = 0; i < 16; i++) {
|
|
37654
37986
|
const tryRoot = discoverSessionWorktreesUnderSessionWorktreeRoot(cur, params.sessionId);
|
|
37655
37987
|
if (tryRoot) return rememberAndReturn(tryRoot);
|
|
37656
|
-
const next =
|
|
37988
|
+
const next = path28.dirname(cur);
|
|
37657
37989
|
if (next === cur) break;
|
|
37658
37990
|
cur = next;
|
|
37659
37991
|
}
|
|
@@ -37705,16 +38037,16 @@ async function resolveSessionParentPathForPrompt(params) {
|
|
|
37705
38037
|
}
|
|
37706
38038
|
|
|
37707
38039
|
// src/worktrees/manager/session-worktree-cache.ts
|
|
37708
|
-
import * as
|
|
38040
|
+
import * as path29 from "node:path";
|
|
37709
38041
|
var SessionWorktreeCache = class {
|
|
37710
38042
|
sessionRepoCheckoutPaths = /* @__PURE__ */ new Map();
|
|
37711
38043
|
sessionParentPathBySession = /* @__PURE__ */ new Map();
|
|
37712
38044
|
sessionWorkingTreeRelRootBySession = /* @__PURE__ */ new Map();
|
|
37713
38045
|
remember(sessionId, binding) {
|
|
37714
|
-
const paths = binding.repoCheckoutPaths.map((p) =>
|
|
38046
|
+
const paths = binding.repoCheckoutPaths.map((p) => path29.resolve(p));
|
|
37715
38047
|
this.sessionRepoCheckoutPaths.set(sessionId, paths);
|
|
37716
|
-
this.sessionParentPathBySession.set(sessionId,
|
|
37717
|
-
this.sessionWorkingTreeRelRootBySession.set(sessionId,
|
|
38048
|
+
this.sessionParentPathBySession.set(sessionId, path29.resolve(binding.sessionParentPath));
|
|
38049
|
+
this.sessionWorkingTreeRelRootBySession.set(sessionId, path29.resolve(binding.workingTreeRelRoot));
|
|
37718
38050
|
}
|
|
37719
38051
|
clearSession(sessionId) {
|
|
37720
38052
|
const paths = this.sessionRepoCheckoutPaths.get(sessionId);
|
|
@@ -37744,7 +38076,7 @@ var SessionWorktreeCache = class {
|
|
|
37744
38076
|
const parent = this.sessionParentPathBySession.get(sessionId);
|
|
37745
38077
|
const relRoot = this.sessionWorkingTreeRelRootBySession.get(sessionId);
|
|
37746
38078
|
if (!parent || !relRoot) return false;
|
|
37747
|
-
return
|
|
38079
|
+
return path29.resolve(parent) !== path29.resolve(relRoot);
|
|
37748
38080
|
}
|
|
37749
38081
|
};
|
|
37750
38082
|
|
|
@@ -37848,29 +38180,29 @@ var SessionWorktreeManager = class {
|
|
|
37848
38180
|
};
|
|
37849
38181
|
|
|
37850
38182
|
// src/worktrees/manager/default-worktrees-root-path.ts
|
|
37851
|
-
import * as
|
|
38183
|
+
import * as path30 from "node:path";
|
|
37852
38184
|
import os8 from "node:os";
|
|
37853
38185
|
function defaultWorktreesRootPath() {
|
|
37854
|
-
return
|
|
38186
|
+
return path30.join(os8.homedir(), ".buildautomaton", "worktrees");
|
|
37855
38187
|
}
|
|
37856
38188
|
|
|
37857
38189
|
// src/files/watch-file-index.ts
|
|
37858
38190
|
import { watch } from "node:fs";
|
|
37859
|
-
import
|
|
38191
|
+
import path35 from "node:path";
|
|
37860
38192
|
|
|
37861
38193
|
// src/files/index/paths.ts
|
|
37862
|
-
import
|
|
38194
|
+
import path31 from "node:path";
|
|
37863
38195
|
import crypto2 from "node:crypto";
|
|
37864
38196
|
function getCwdHashForFileIndex(resolvedCwd) {
|
|
37865
|
-
return crypto2.createHash("sha256").update(
|
|
38197
|
+
return crypto2.createHash("sha256").update(path31.resolve(resolvedCwd)).digest("hex").slice(0, INDEX_HASH_LEN);
|
|
37866
38198
|
}
|
|
37867
38199
|
|
|
37868
38200
|
// src/files/index/build-file-index.ts
|
|
37869
|
-
import
|
|
38201
|
+
import path33 from "node:path";
|
|
37870
38202
|
|
|
37871
38203
|
// src/files/index/walk-workspace-tree.ts
|
|
37872
|
-
import
|
|
37873
|
-
import
|
|
38204
|
+
import fs26 from "node:fs";
|
|
38205
|
+
import path32 from "node:path";
|
|
37874
38206
|
var DEPENDENCY_INSTALL_DIR_NAMES = /* @__PURE__ */ new Set([
|
|
37875
38207
|
"node_modules",
|
|
37876
38208
|
"bower_components",
|
|
@@ -37887,7 +38219,7 @@ function shouldSkipWorkspaceWalkEntry(name) {
|
|
|
37887
38219
|
async function walkWorkspaceTreeAsync(dir, baseDir, onFile, state) {
|
|
37888
38220
|
let names;
|
|
37889
38221
|
try {
|
|
37890
|
-
names = await
|
|
38222
|
+
names = await fs26.promises.readdir(dir);
|
|
37891
38223
|
} catch {
|
|
37892
38224
|
return;
|
|
37893
38225
|
}
|
|
@@ -37899,14 +38231,14 @@ async function walkWorkspaceTreeAsync(dir, baseDir, onFile, state) {
|
|
|
37899
38231
|
if (isCliImmediateShutdownRequested()) throw new CliSqliteInterrupted();
|
|
37900
38232
|
}
|
|
37901
38233
|
state.n++;
|
|
37902
|
-
const full =
|
|
38234
|
+
const full = path32.join(dir, name);
|
|
37903
38235
|
let stat3;
|
|
37904
38236
|
try {
|
|
37905
|
-
stat3 = await
|
|
38237
|
+
stat3 = await fs26.promises.stat(full);
|
|
37906
38238
|
} catch {
|
|
37907
38239
|
continue;
|
|
37908
38240
|
}
|
|
37909
|
-
const relative6 =
|
|
38241
|
+
const relative6 = path32.relative(baseDir, full).replace(/\\/g, "/");
|
|
37910
38242
|
if (stat3.isDirectory()) {
|
|
37911
38243
|
await walkWorkspaceTreeAsync(full, baseDir, onFile, state);
|
|
37912
38244
|
} else if (stat3.isFile()) {
|
|
@@ -37919,7 +38251,7 @@ function createWalkYieldState() {
|
|
|
37919
38251
|
}
|
|
37920
38252
|
|
|
37921
38253
|
// src/files/index/file-index-sqlite-lock.ts
|
|
37922
|
-
import
|
|
38254
|
+
import fs27 from "node:fs";
|
|
37923
38255
|
function isSqliteCorruptError(e) {
|
|
37924
38256
|
const msg = e instanceof Error ? e.message : String(e);
|
|
37925
38257
|
return msg.includes("malformed") || msg.includes("database disk image is malformed") || msg.includes("corrupt");
|
|
@@ -37933,7 +38265,7 @@ function withFileIndexSqliteLock(fn) {
|
|
|
37933
38265
|
if (!isSqliteCorruptError(e)) throw e;
|
|
37934
38266
|
closeAllCliSqliteConnections();
|
|
37935
38267
|
try {
|
|
37936
|
-
|
|
38268
|
+
fs27.unlinkSync(getCliSqlitePath());
|
|
37937
38269
|
} catch {
|
|
37938
38270
|
}
|
|
37939
38271
|
chain = Promise.resolve();
|
|
@@ -38008,7 +38340,7 @@ async function collectWorkspacePathsAsync(resolved) {
|
|
|
38008
38340
|
}
|
|
38009
38341
|
async function buildFileIndexAsync(cwd) {
|
|
38010
38342
|
return withFileIndexSqliteLock(async () => {
|
|
38011
|
-
const resolved =
|
|
38343
|
+
const resolved = path33.resolve(cwd);
|
|
38012
38344
|
await yieldToEventLoop();
|
|
38013
38345
|
assertNotShutdown();
|
|
38014
38346
|
const paths = await collectWorkspacePathsAsync(resolved);
|
|
@@ -38020,7 +38352,7 @@ async function buildFileIndexAsync(cwd) {
|
|
|
38020
38352
|
}
|
|
38021
38353
|
|
|
38022
38354
|
// src/files/index/ensure-file-index.ts
|
|
38023
|
-
import
|
|
38355
|
+
import path34 from "node:path";
|
|
38024
38356
|
|
|
38025
38357
|
// src/files/index/search-file-index.ts
|
|
38026
38358
|
function escapeLikePattern(fragment) {
|
|
@@ -38072,7 +38404,7 @@ async function searchBridgeFilePathsAsync(resolvedCwd, query, limit = 100) {
|
|
|
38072
38404
|
|
|
38073
38405
|
// src/files/index/ensure-file-index.ts
|
|
38074
38406
|
async function ensureFileIndexAsync(cwd) {
|
|
38075
|
-
const resolved =
|
|
38407
|
+
const resolved = path34.resolve(cwd);
|
|
38076
38408
|
if (await bridgeFileIndexIsPopulated(resolved)) {
|
|
38077
38409
|
return { fromCache: true, pathCount: await bridgeFileIndexPathCount(resolved) };
|
|
38078
38410
|
}
|
|
@@ -38116,7 +38448,7 @@ function createFsWatcher(resolved, schedule) {
|
|
|
38116
38448
|
}
|
|
38117
38449
|
}
|
|
38118
38450
|
function startFileIndexWatcher(cwd = getBridgeRoot()) {
|
|
38119
|
-
const resolved =
|
|
38451
|
+
const resolved = path35.resolve(cwd);
|
|
38120
38452
|
void buildFileIndexAsync(resolved).catch((e) => {
|
|
38121
38453
|
if (e instanceof CliSqliteInterrupted) return;
|
|
38122
38454
|
console.error("[file-index] Initial index build failed:", e);
|
|
@@ -38146,7 +38478,7 @@ function startFileIndexWatcher(cwd = getBridgeRoot()) {
|
|
|
38146
38478
|
}
|
|
38147
38479
|
|
|
38148
38480
|
// src/connection/create-bridge-connection.ts
|
|
38149
|
-
import * as
|
|
38481
|
+
import * as path46 from "node:path";
|
|
38150
38482
|
|
|
38151
38483
|
// src/dev-servers/manager/dev-server-manager.ts
|
|
38152
38484
|
import { rm as rm2 } from "node:fs/promises";
|
|
@@ -38190,7 +38522,7 @@ function forceKillChild(proc, log2, shortId, graceMs) {
|
|
|
38190
38522
|
}
|
|
38191
38523
|
|
|
38192
38524
|
// src/dev-servers/process/wire-dev-server-child-process.ts
|
|
38193
|
-
import
|
|
38525
|
+
import fs28 from "node:fs";
|
|
38194
38526
|
|
|
38195
38527
|
// src/dev-servers/manager/forward-pipe.ts
|
|
38196
38528
|
function forwardChildPipe(childReadable, terminal, onData) {
|
|
@@ -38226,7 +38558,7 @@ function wireDevServerChildProcess(d) {
|
|
|
38226
38558
|
d.setPollInterval(void 0);
|
|
38227
38559
|
return;
|
|
38228
38560
|
}
|
|
38229
|
-
|
|
38561
|
+
fs28.readFile(d.mergedLogPath, (err, buf) => {
|
|
38230
38562
|
if (err || (d.getSpawnGeneration() ?? 0) !== d.scheduledGen) return;
|
|
38231
38563
|
if (buf.length <= d.mergedReadPos.value) return;
|
|
38232
38564
|
const chunk = Buffer.from(buf.subarray(d.mergedReadPos.value));
|
|
@@ -38264,7 +38596,7 @@ ${errTail}` : ""}`);
|
|
|
38264
38596
|
d.sendStatus(code === 0 || code == null ? "stopped" : "error", detail, tails);
|
|
38265
38597
|
};
|
|
38266
38598
|
if (mergedPath) {
|
|
38267
|
-
|
|
38599
|
+
fs28.readFile(mergedPath, (err, buf) => {
|
|
38268
38600
|
if (!err && buf.length > d.mergedReadPos.value) {
|
|
38269
38601
|
const chunk = Buffer.from(buf.subarray(d.mergedReadPos.value));
|
|
38270
38602
|
if (chunk.length > 0) {
|
|
@@ -38366,13 +38698,13 @@ function parseDevServerDefs(servers) {
|
|
|
38366
38698
|
}
|
|
38367
38699
|
|
|
38368
38700
|
// src/dev-servers/manager/shell-spawn/utils.ts
|
|
38369
|
-
import
|
|
38701
|
+
import fs29 from "node:fs";
|
|
38370
38702
|
function isSpawnEbadf(e) {
|
|
38371
38703
|
return typeof e === "object" && e !== null && "code" in e && e.code === "EBADF";
|
|
38372
38704
|
}
|
|
38373
38705
|
function rmDirQuiet(dir) {
|
|
38374
38706
|
try {
|
|
38375
|
-
|
|
38707
|
+
fs29.rmSync(dir, { recursive: true, force: true });
|
|
38376
38708
|
} catch {
|
|
38377
38709
|
}
|
|
38378
38710
|
}
|
|
@@ -38380,7 +38712,7 @@ var cachedDevNullReadFd;
|
|
|
38380
38712
|
function devNullReadFd() {
|
|
38381
38713
|
if (cachedDevNullReadFd === void 0) {
|
|
38382
38714
|
const devPath = process.platform === "win32" ? "nul" : "/dev/null";
|
|
38383
|
-
cachedDevNullReadFd =
|
|
38715
|
+
cachedDevNullReadFd = fs29.openSync(devPath, "r");
|
|
38384
38716
|
}
|
|
38385
38717
|
return cachedDevNullReadFd;
|
|
38386
38718
|
}
|
|
@@ -38454,15 +38786,15 @@ function trySpawnShellTruePiped(command, env, cwd, devNullFd, signal) {
|
|
|
38454
38786
|
|
|
38455
38787
|
// src/dev-servers/manager/shell-spawn/try-spawn-merged-log-file.ts
|
|
38456
38788
|
import { spawn as spawn7 } from "node:child_process";
|
|
38457
|
-
import
|
|
38789
|
+
import fs30 from "node:fs";
|
|
38458
38790
|
import { tmpdir } from "node:os";
|
|
38459
|
-
import
|
|
38791
|
+
import path36 from "node:path";
|
|
38460
38792
|
function trySpawnMergedLogFile(command, env, cwd, signal) {
|
|
38461
|
-
const tmpRoot =
|
|
38462
|
-
const logPath =
|
|
38793
|
+
const tmpRoot = fs30.mkdtempSync(path36.join(tmpdir(), "ba-devsrv-log-"));
|
|
38794
|
+
const logPath = path36.join(tmpRoot, "combined.log");
|
|
38463
38795
|
let logFd;
|
|
38464
38796
|
try {
|
|
38465
|
-
logFd =
|
|
38797
|
+
logFd = fs30.openSync(logPath, "a");
|
|
38466
38798
|
} catch {
|
|
38467
38799
|
rmDirQuiet(tmpRoot);
|
|
38468
38800
|
return null;
|
|
@@ -38481,7 +38813,7 @@ function trySpawnMergedLogFile(command, env, cwd, signal) {
|
|
|
38481
38813
|
} else {
|
|
38482
38814
|
proc = spawn7("/bin/sh", ["-c", command], { env, cwd, stdio, ...signal ? { signal } : {} });
|
|
38483
38815
|
}
|
|
38484
|
-
|
|
38816
|
+
fs30.closeSync(logFd);
|
|
38485
38817
|
return {
|
|
38486
38818
|
proc,
|
|
38487
38819
|
pipedStdoutStderr: true,
|
|
@@ -38490,7 +38822,7 @@ function trySpawnMergedLogFile(command, env, cwd, signal) {
|
|
|
38490
38822
|
};
|
|
38491
38823
|
} catch (e) {
|
|
38492
38824
|
try {
|
|
38493
|
-
|
|
38825
|
+
fs30.closeSync(logFd);
|
|
38494
38826
|
} catch {
|
|
38495
38827
|
}
|
|
38496
38828
|
rmDirQuiet(tmpRoot);
|
|
@@ -38501,22 +38833,22 @@ function trySpawnMergedLogFile(command, env, cwd, signal) {
|
|
|
38501
38833
|
|
|
38502
38834
|
// src/dev-servers/manager/shell-spawn/try-spawn-shell-script-log-redirect.ts
|
|
38503
38835
|
import { spawn as spawn8 } from "node:child_process";
|
|
38504
|
-
import
|
|
38836
|
+
import fs31 from "node:fs";
|
|
38505
38837
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
38506
|
-
import
|
|
38838
|
+
import path37 from "node:path";
|
|
38507
38839
|
function shSingleQuote(s) {
|
|
38508
38840
|
return `'${s.replace(/'/g, `'\\''`)}'`;
|
|
38509
38841
|
}
|
|
38510
38842
|
function trySpawnShellScriptLogRedirectUnix(command, env, cwd, signal) {
|
|
38511
|
-
const tmpRoot =
|
|
38512
|
-
const logPath =
|
|
38513
|
-
const innerPath =
|
|
38514
|
-
const runnerPath =
|
|
38843
|
+
const tmpRoot = fs31.mkdtempSync(path37.join(tmpdir2(), "ba-devsrv-sh-"));
|
|
38844
|
+
const logPath = path37.join(tmpRoot, "combined.log");
|
|
38845
|
+
const innerPath = path37.join(tmpRoot, "_cmd.sh");
|
|
38846
|
+
const runnerPath = path37.join(tmpRoot, "_run.sh");
|
|
38515
38847
|
try {
|
|
38516
|
-
|
|
38848
|
+
fs31.writeFileSync(innerPath, `#!/bin/sh
|
|
38517
38849
|
${command}
|
|
38518
38850
|
`);
|
|
38519
|
-
|
|
38851
|
+
fs31.writeFileSync(
|
|
38520
38852
|
runnerPath,
|
|
38521
38853
|
`#!/bin/sh
|
|
38522
38854
|
cd ${shSingleQuote(cwd)}
|
|
@@ -38542,13 +38874,13 @@ cd ${shSingleQuote(cwd)}
|
|
|
38542
38874
|
}
|
|
38543
38875
|
}
|
|
38544
38876
|
function trySpawnShellScriptLogRedirectWin(command, env, cwd, signal) {
|
|
38545
|
-
const tmpRoot =
|
|
38546
|
-
const logPath =
|
|
38547
|
-
const runnerPath =
|
|
38877
|
+
const tmpRoot = fs31.mkdtempSync(path37.join(tmpdir2(), "ba-devsrv-sh-"));
|
|
38878
|
+
const logPath = path37.join(tmpRoot, "combined.log");
|
|
38879
|
+
const runnerPath = path37.join(tmpRoot, "_run.bat");
|
|
38548
38880
|
const q = (p) => `"${p.replace(/"/g, '""')}"`;
|
|
38549
38881
|
const com = process.env.ComSpec || "cmd.exe";
|
|
38550
38882
|
try {
|
|
38551
|
-
|
|
38883
|
+
fs31.writeFileSync(
|
|
38552
38884
|
runnerPath,
|
|
38553
38885
|
`@ECHO OFF\r
|
|
38554
38886
|
CD /D ${q(cwd)}\r
|
|
@@ -39485,30 +39817,30 @@ function createOnBridgeIdentified(opts) {
|
|
|
39485
39817
|
}
|
|
39486
39818
|
|
|
39487
39819
|
// src/skills/discover-local-agent-skills.ts
|
|
39488
|
-
import
|
|
39489
|
-
import
|
|
39820
|
+
import fs32 from "node:fs";
|
|
39821
|
+
import path38 from "node:path";
|
|
39490
39822
|
var SKILL_DISCOVERY_ROOTS = [".agents/skills", ".claude/skills", ".cursor/skills", "skills"];
|
|
39491
39823
|
function discoverLocalSkills(cwd) {
|
|
39492
39824
|
const out = [];
|
|
39493
39825
|
const seenKeys = /* @__PURE__ */ new Set();
|
|
39494
39826
|
for (const rel of SKILL_DISCOVERY_ROOTS) {
|
|
39495
|
-
const base =
|
|
39496
|
-
if (!
|
|
39827
|
+
const base = path38.join(cwd, rel);
|
|
39828
|
+
if (!fs32.existsSync(base) || !fs32.statSync(base).isDirectory()) continue;
|
|
39497
39829
|
let entries = [];
|
|
39498
39830
|
try {
|
|
39499
|
-
entries =
|
|
39831
|
+
entries = fs32.readdirSync(base);
|
|
39500
39832
|
} catch {
|
|
39501
39833
|
continue;
|
|
39502
39834
|
}
|
|
39503
39835
|
for (const name of entries) {
|
|
39504
|
-
const dir =
|
|
39836
|
+
const dir = path38.join(base, name);
|
|
39505
39837
|
try {
|
|
39506
|
-
if (!
|
|
39838
|
+
if (!fs32.statSync(dir).isDirectory()) continue;
|
|
39507
39839
|
} catch {
|
|
39508
39840
|
continue;
|
|
39509
39841
|
}
|
|
39510
|
-
const skillMd =
|
|
39511
|
-
if (!
|
|
39842
|
+
const skillMd = path38.join(dir, "SKILL.md");
|
|
39843
|
+
if (!fs32.existsSync(skillMd)) continue;
|
|
39512
39844
|
const key = `${rel}/${name}`;
|
|
39513
39845
|
if (seenKeys.has(key)) continue;
|
|
39514
39846
|
seenKeys.add(key);
|
|
@@ -39520,23 +39852,23 @@ function discoverLocalSkills(cwd) {
|
|
|
39520
39852
|
function discoverSkillLayoutRoots(cwd) {
|
|
39521
39853
|
const roots = [];
|
|
39522
39854
|
for (const rel of SKILL_DISCOVERY_ROOTS) {
|
|
39523
|
-
const base =
|
|
39524
|
-
if (!
|
|
39855
|
+
const base = path38.join(cwd, rel);
|
|
39856
|
+
if (!fs32.existsSync(base) || !fs32.statSync(base).isDirectory()) continue;
|
|
39525
39857
|
let entries = [];
|
|
39526
39858
|
try {
|
|
39527
|
-
entries =
|
|
39859
|
+
entries = fs32.readdirSync(base);
|
|
39528
39860
|
} catch {
|
|
39529
39861
|
continue;
|
|
39530
39862
|
}
|
|
39531
39863
|
const skills2 = [];
|
|
39532
39864
|
for (const name of entries) {
|
|
39533
|
-
const dir =
|
|
39865
|
+
const dir = path38.join(base, name);
|
|
39534
39866
|
try {
|
|
39535
|
-
if (!
|
|
39867
|
+
if (!fs32.statSync(dir).isDirectory()) continue;
|
|
39536
39868
|
} catch {
|
|
39537
39869
|
continue;
|
|
39538
39870
|
}
|
|
39539
|
-
if (!
|
|
39871
|
+
if (!fs32.existsSync(path38.join(dir, "SKILL.md"))) continue;
|
|
39540
39872
|
const relPath = `${rel}/${name}`.replace(/\\/g, "/");
|
|
39541
39873
|
skills2.push({ name, relPath });
|
|
39542
39874
|
}
|
|
@@ -39892,7 +40224,7 @@ function syncRunningTurnQueueKeys(turns, queueKey) {
|
|
|
39892
40224
|
}
|
|
39893
40225
|
|
|
39894
40226
|
// src/prompt-turn-queue/runner/run-local-revert-before-queued-prompt.ts
|
|
39895
|
-
import
|
|
40227
|
+
import fs33 from "node:fs";
|
|
39896
40228
|
async function runLocalRevertBeforeQueuedPrompt(next, deps) {
|
|
39897
40229
|
if (next.serverState !== "requeued_with_revert") return true;
|
|
39898
40230
|
const sid = next.sessionId;
|
|
@@ -39901,7 +40233,7 @@ async function runLocalRevertBeforeQueuedPrompt(next, deps) {
|
|
|
39901
40233
|
const agentBase = deps.sessionWorktreeManager.getSessionWorktreeRootForSession(sid) ?? getBridgeRoot();
|
|
39902
40234
|
const file2 = snapshotFilePath(agentBase, tid);
|
|
39903
40235
|
try {
|
|
39904
|
-
await
|
|
40236
|
+
await fs33.promises.access(file2, fs33.constants.F_OK);
|
|
39905
40237
|
} catch {
|
|
39906
40238
|
deps.log(
|
|
39907
40239
|
`[Queue] requeued_with_revert: no pre-turn snapshot for ${tid.slice(0, 8)}\u2026; continuing without revert.`
|
|
@@ -40189,9 +40521,9 @@ function parseChangeSummarySnapshots(raw) {
|
|
|
40189
40521
|
for (const item of raw) {
|
|
40190
40522
|
if (!item || typeof item !== "object") continue;
|
|
40191
40523
|
const o = item;
|
|
40192
|
-
const
|
|
40193
|
-
if (!
|
|
40194
|
-
const row = { path:
|
|
40524
|
+
const path48 = typeof o.path === "string" && o.path.trim() !== "" ? o.path.trim() : "";
|
|
40525
|
+
if (!path48) continue;
|
|
40526
|
+
const row = { path: path48 };
|
|
40195
40527
|
if (typeof o.patchContent === "string") row.patchContent = o.patchContent;
|
|
40196
40528
|
if (typeof o.oldText === "string") row.oldText = o.oldText;
|
|
40197
40529
|
if (typeof o.newText === "string") row.newText = o.newText;
|
|
@@ -40401,8 +40733,8 @@ function randomSecret() {
|
|
|
40401
40733
|
}
|
|
40402
40734
|
return Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
|
|
40403
40735
|
}
|
|
40404
|
-
async function requestPreviewApi(port, secret, method,
|
|
40405
|
-
const url2 = `http://127.0.0.1:${port}${
|
|
40736
|
+
async function requestPreviewApi(port, secret, method, path48, body) {
|
|
40737
|
+
const url2 = `http://127.0.0.1:${port}${path48}`;
|
|
40406
40738
|
const headers = {
|
|
40407
40739
|
[PREVIEW_SECRET_HEADER]: secret,
|
|
40408
40740
|
"Content-Type": "application/json"
|
|
@@ -40414,7 +40746,7 @@ async function requestPreviewApi(port, secret, method, path46, body) {
|
|
|
40414
40746
|
});
|
|
40415
40747
|
const data = await res.json().catch(() => ({}));
|
|
40416
40748
|
if (!res.ok) {
|
|
40417
|
-
throw new Error(data?.error ?? `Preview API ${method} ${
|
|
40749
|
+
throw new Error(data?.error ?? `Preview API ${method} ${path48}: ${res.status}`);
|
|
40418
40750
|
}
|
|
40419
40751
|
return data;
|
|
40420
40752
|
}
|
|
@@ -40579,14 +40911,14 @@ var handleSkillCallMessage = (msg, { getWs, log: log2 }) => {
|
|
|
40579
40911
|
};
|
|
40580
40912
|
|
|
40581
40913
|
// src/files/list-dir/index.ts
|
|
40582
|
-
import
|
|
40914
|
+
import fs35 from "node:fs";
|
|
40583
40915
|
|
|
40584
40916
|
// src/files/ensure-under-cwd.ts
|
|
40585
|
-
import
|
|
40917
|
+
import path39 from "node:path";
|
|
40586
40918
|
function ensureUnderCwd(relativePath, cwd = getBridgeRoot()) {
|
|
40587
|
-
const normalized =
|
|
40588
|
-
const resolved =
|
|
40589
|
-
if (!resolved.startsWith(cwd +
|
|
40919
|
+
const normalized = path39.normalize(relativePath).replace(/^(\.\/)+/, "");
|
|
40920
|
+
const resolved = path39.resolve(cwd, normalized);
|
|
40921
|
+
if (!resolved.startsWith(cwd + path39.sep) && resolved !== cwd) {
|
|
40590
40922
|
return null;
|
|
40591
40923
|
}
|
|
40592
40924
|
return resolved;
|
|
@@ -40596,15 +40928,15 @@ function ensureUnderCwd(relativePath, cwd = getBridgeRoot()) {
|
|
|
40596
40928
|
var LIST_DIR_YIELD_EVERY = 256;
|
|
40597
40929
|
|
|
40598
40930
|
// src/files/list-dir/map-dir-entry.ts
|
|
40599
|
-
import
|
|
40600
|
-
import
|
|
40931
|
+
import path40 from "node:path";
|
|
40932
|
+
import fs34 from "node:fs";
|
|
40601
40933
|
async function mapDirEntry(d, relativePath, resolved) {
|
|
40602
|
-
const entryPath =
|
|
40603
|
-
const fullPath =
|
|
40934
|
+
const entryPath = path40.join(relativePath || ".", d.name).replace(/\\/g, "/");
|
|
40935
|
+
const fullPath = path40.join(resolved, d.name);
|
|
40604
40936
|
let isDir = d.isDirectory();
|
|
40605
40937
|
if (d.isSymbolicLink()) {
|
|
40606
40938
|
try {
|
|
40607
|
-
const targetStat = await
|
|
40939
|
+
const targetStat = await fs34.promises.stat(fullPath);
|
|
40608
40940
|
isDir = targetStat.isDirectory();
|
|
40609
40941
|
} catch {
|
|
40610
40942
|
isDir = false;
|
|
@@ -40634,7 +40966,7 @@ async function listDirAsync(relativePath, sessionParentPath = getBridgeRoot()) {
|
|
|
40634
40966
|
return { error: "Path is outside working directory" };
|
|
40635
40967
|
}
|
|
40636
40968
|
try {
|
|
40637
|
-
const names = await
|
|
40969
|
+
const names = await fs35.promises.readdir(resolved, { withFileTypes: true });
|
|
40638
40970
|
const entries = [];
|
|
40639
40971
|
for (let i = 0; i < names.length; i++) {
|
|
40640
40972
|
if (i > 0 && i % LIST_DIR_YIELD_EVERY === 0) {
|
|
@@ -40654,18 +40986,18 @@ var LINE_CHUNK_SIZE = 64 * 1024;
|
|
|
40654
40986
|
var READ_RANGE_YIELD_EVERY_BYTES = 256 * 1024;
|
|
40655
40987
|
|
|
40656
40988
|
// src/files/read-file/resolve-file-path.ts
|
|
40657
|
-
import
|
|
40989
|
+
import fs36 from "node:fs";
|
|
40658
40990
|
async function resolveFilePathAsync(relativePath, sessionParentPath = getBridgeRoot()) {
|
|
40659
40991
|
const resolved = ensureUnderCwd(relativePath, sessionParentPath);
|
|
40660
40992
|
if (!resolved) return { error: "Path is outside working directory" };
|
|
40661
40993
|
let real;
|
|
40662
40994
|
try {
|
|
40663
|
-
real = await
|
|
40995
|
+
real = await fs36.promises.realpath(resolved);
|
|
40664
40996
|
} catch {
|
|
40665
40997
|
real = resolved;
|
|
40666
40998
|
}
|
|
40667
40999
|
try {
|
|
40668
|
-
const stat3 = await
|
|
41000
|
+
const stat3 = await fs36.promises.stat(real);
|
|
40669
41001
|
if (!stat3.isFile()) return { error: "Not a file" };
|
|
40670
41002
|
return real;
|
|
40671
41003
|
} catch (err) {
|
|
@@ -40674,11 +41006,11 @@ async function resolveFilePathAsync(relativePath, sessionParentPath = getBridgeR
|
|
|
40674
41006
|
}
|
|
40675
41007
|
|
|
40676
41008
|
// src/files/read-file/read-file-range-async.ts
|
|
40677
|
-
import
|
|
41009
|
+
import fs37 from "node:fs";
|
|
40678
41010
|
import { StringDecoder } from "node:string_decoder";
|
|
40679
41011
|
async function readFileRangeAsync(filePath, startLine, endLine, lineOffsetIn, lineChunkSize = LINE_CHUNK_SIZE) {
|
|
40680
|
-
const fileSize = (await
|
|
40681
|
-
const fd = await
|
|
41012
|
+
const fileSize = (await fs37.promises.stat(filePath)).size;
|
|
41013
|
+
const fd = await fs37.promises.open(filePath, "r");
|
|
40682
41014
|
const bufSize = 64 * 1024;
|
|
40683
41015
|
const buf = Buffer.alloc(bufSize);
|
|
40684
41016
|
const decoder = new StringDecoder("utf8");
|
|
@@ -40840,11 +41172,11 @@ async function readFileRangeAsync(filePath, startLine, endLine, lineOffsetIn, li
|
|
|
40840
41172
|
}
|
|
40841
41173
|
|
|
40842
41174
|
// src/files/read-file/read-file-buffer-full-async.ts
|
|
40843
|
-
import
|
|
41175
|
+
import fs38 from "node:fs";
|
|
40844
41176
|
var READ_CHUNK_BYTES = 256 * 1024;
|
|
40845
41177
|
async function readFileBufferFullAsync(filePath) {
|
|
40846
|
-
const stat3 = await
|
|
40847
|
-
const fd = await
|
|
41178
|
+
const stat3 = await fs38.promises.stat(filePath);
|
|
41179
|
+
const fd = await fs38.promises.open(filePath, "r");
|
|
40848
41180
|
const chunks = [];
|
|
40849
41181
|
let position = 0;
|
|
40850
41182
|
let bytesSinceYield = 0;
|
|
@@ -40951,13 +41283,13 @@ function resolveFileBrowserSessionParent(sessionWorktreeManager, sessionId) {
|
|
|
40951
41283
|
}
|
|
40952
41284
|
|
|
40953
41285
|
// src/files/handle-file-browser-search.ts
|
|
40954
|
-
import
|
|
41286
|
+
import path41 from "node:path";
|
|
40955
41287
|
var SEARCH_LIMIT = 100;
|
|
40956
41288
|
function handleFileBrowserSearch(msg, socket, e2ee, sessionWorktreeManager) {
|
|
40957
41289
|
void (async () => {
|
|
40958
41290
|
await yieldToEventLoop();
|
|
40959
41291
|
const q = typeof msg.q === "string" ? msg.q : "";
|
|
40960
|
-
const sessionParentPath =
|
|
41292
|
+
const sessionParentPath = path41.resolve(
|
|
40961
41293
|
sessionWorktreeManager != null ? resolveFileBrowserSessionParent(sessionWorktreeManager, msg.sessionId) : getBridgeRoot()
|
|
40962
41294
|
);
|
|
40963
41295
|
if (!await bridgeFileIndexIsPopulated(sessionParentPath)) {
|
|
@@ -41076,8 +41408,8 @@ function handleSkillLayoutRequest(msg, deps) {
|
|
|
41076
41408
|
}
|
|
41077
41409
|
|
|
41078
41410
|
// src/skills/install-remote-skills.ts
|
|
41079
|
-
import
|
|
41080
|
-
import
|
|
41411
|
+
import fs39 from "node:fs";
|
|
41412
|
+
import path42 from "node:path";
|
|
41081
41413
|
function installRemoteSkills(cwd, targetDir, items) {
|
|
41082
41414
|
const installed2 = [];
|
|
41083
41415
|
if (!Array.isArray(items)) {
|
|
@@ -41088,15 +41420,15 @@ function installRemoteSkills(cwd, targetDir, items) {
|
|
|
41088
41420
|
if (typeof item.sourceId !== "string" || typeof item.skillName !== "string" || typeof item.versionHash !== "string" || !Array.isArray(item.files)) {
|
|
41089
41421
|
continue;
|
|
41090
41422
|
}
|
|
41091
|
-
const skillDir =
|
|
41423
|
+
const skillDir = path42.join(cwd, targetDir, item.skillName);
|
|
41092
41424
|
for (const f of item.files) {
|
|
41093
41425
|
if (typeof f.path !== "string" || !f.text && !f.base64) continue;
|
|
41094
|
-
const dest =
|
|
41095
|
-
|
|
41426
|
+
const dest = path42.join(skillDir, f.path);
|
|
41427
|
+
fs39.mkdirSync(path42.dirname(dest), { recursive: true });
|
|
41096
41428
|
if (f.text !== void 0) {
|
|
41097
|
-
|
|
41429
|
+
fs39.writeFileSync(dest, f.text, "utf8");
|
|
41098
41430
|
} else if (f.base64) {
|
|
41099
|
-
|
|
41431
|
+
fs39.writeFileSync(dest, Buffer.from(f.base64, "base64"));
|
|
41100
41432
|
}
|
|
41101
41433
|
}
|
|
41102
41434
|
installed2.push({
|
|
@@ -41254,7 +41586,7 @@ var handleSessionDiscardedMessage = (msg, deps) => {
|
|
|
41254
41586
|
};
|
|
41255
41587
|
|
|
41256
41588
|
// src/routing/handlers/revert-turn-snapshot.ts
|
|
41257
|
-
import * as
|
|
41589
|
+
import * as fs40 from "node:fs";
|
|
41258
41590
|
var handleRevertTurnSnapshotMessage = (msg, deps) => {
|
|
41259
41591
|
const id = typeof msg.id === "string" ? msg.id : "";
|
|
41260
41592
|
const sessionId = typeof msg.sessionId === "string" ? msg.sessionId : "";
|
|
@@ -41267,7 +41599,7 @@ var handleRevertTurnSnapshotMessage = (msg, deps) => {
|
|
|
41267
41599
|
const agentBase = sessionWorktreeManager.getSessionWorktreeRootForSession(sessionId) ?? getBridgeRoot();
|
|
41268
41600
|
const file2 = snapshotFilePath(agentBase, turnId);
|
|
41269
41601
|
try {
|
|
41270
|
-
await
|
|
41602
|
+
await fs40.promises.access(file2, fs40.constants.F_OK);
|
|
41271
41603
|
} catch {
|
|
41272
41604
|
sendWsMessage(s, {
|
|
41273
41605
|
type: "revert_turn_snapshot_result",
|
|
@@ -41309,7 +41641,7 @@ var handleDevServersConfig = (msg, deps) => {
|
|
|
41309
41641
|
};
|
|
41310
41642
|
|
|
41311
41643
|
// src/git/bridge-git-context.ts
|
|
41312
|
-
import * as
|
|
41644
|
+
import * as path43 from "node:path";
|
|
41313
41645
|
|
|
41314
41646
|
// src/git/branches/get-current-branch.ts
|
|
41315
41647
|
async function getCurrentBranch(repoPath) {
|
|
@@ -41359,12 +41691,12 @@ async function listRepoBranchRefs(repoPath) {
|
|
|
41359
41691
|
// src/git/bridge-git-context.ts
|
|
41360
41692
|
function folderNameForRelPath(relPath, bridgeRoot) {
|
|
41361
41693
|
if (relPath === "." || relPath === "") {
|
|
41362
|
-
return
|
|
41694
|
+
return path43.basename(path43.resolve(bridgeRoot)) || "repo";
|
|
41363
41695
|
}
|
|
41364
|
-
return
|
|
41696
|
+
return path43.basename(relPath) || relPath;
|
|
41365
41697
|
}
|
|
41366
41698
|
async function discoverGitReposForBridgeContext(bridgeRoot) {
|
|
41367
|
-
const root =
|
|
41699
|
+
const root = path43.resolve(bridgeRoot);
|
|
41368
41700
|
if (await isGitRepoDirectory(root)) {
|
|
41369
41701
|
const remoteUrl = await getRemoteOriginUrl(root);
|
|
41370
41702
|
return [{ absolutePath: root, remoteUrl }];
|
|
@@ -41372,17 +41704,17 @@ async function discoverGitReposForBridgeContext(bridgeRoot) {
|
|
|
41372
41704
|
const [deep, shallow] = await Promise.all([discoverGitReposUnderRoot(root), discoverGitRepos(root)]);
|
|
41373
41705
|
const byPath = /* @__PURE__ */ new Map();
|
|
41374
41706
|
for (const repo of [...deep, ...shallow]) {
|
|
41375
|
-
byPath.set(
|
|
41707
|
+
byPath.set(path43.resolve(repo.absolutePath), repo);
|
|
41376
41708
|
}
|
|
41377
41709
|
return [...byPath.values()];
|
|
41378
41710
|
}
|
|
41379
41711
|
async function getBridgeGitContext(bridgeRoot = getBridgeRoot()) {
|
|
41380
|
-
const bridgeResolved =
|
|
41712
|
+
const bridgeResolved = path43.resolve(bridgeRoot);
|
|
41381
41713
|
const repos = await discoverGitReposForBridgeContext(bridgeResolved);
|
|
41382
41714
|
const rows = [];
|
|
41383
41715
|
for (const repo of repos) {
|
|
41384
|
-
let rel =
|
|
41385
|
-
if (rel.startsWith("..") ||
|
|
41716
|
+
let rel = path43.relative(bridgeResolved, repo.absolutePath);
|
|
41717
|
+
if (rel.startsWith("..") || path43.isAbsolute(rel)) continue;
|
|
41386
41718
|
const relPath = rel === "" ? "." : rel.replace(/\\/g, "/");
|
|
41387
41719
|
const currentBranch = await getCurrentBranch(repo.absolutePath);
|
|
41388
41720
|
const remoteUrl = repo.remoteUrl.trim() || null;
|
|
@@ -41397,11 +41729,11 @@ async function getBridgeGitContext(bridgeRoot = getBridgeRoot()) {
|
|
|
41397
41729
|
return rows;
|
|
41398
41730
|
}
|
|
41399
41731
|
async function listRepoBranchesForBridge(repoRelPath, bridgeRoot = getBridgeRoot()) {
|
|
41400
|
-
const bridgeResolved =
|
|
41732
|
+
const bridgeResolved = path43.resolve(bridgeRoot);
|
|
41401
41733
|
const rel = repoRelPath.trim() === "." ? "" : repoRelPath.trim().replace(/\\/g, "/");
|
|
41402
|
-
const repoPath = rel === "" ? bridgeResolved :
|
|
41403
|
-
const resolved =
|
|
41404
|
-
if (!resolved.startsWith(bridgeResolved +
|
|
41734
|
+
const repoPath = rel === "" ? bridgeResolved : path43.join(bridgeResolved, rel);
|
|
41735
|
+
const resolved = path43.resolve(repoPath);
|
|
41736
|
+
if (!resolved.startsWith(bridgeResolved + path43.sep) && resolved !== bridgeResolved) {
|
|
41405
41737
|
return [];
|
|
41406
41738
|
}
|
|
41407
41739
|
return listRepoBranchRefs(resolved);
|
|
@@ -41906,10 +42238,10 @@ function listCliAgentCapabilityCacheForWorkspace(db, workspaceId) {
|
|
|
41906
42238
|
}
|
|
41907
42239
|
|
|
41908
42240
|
// src/agents/capabilities/warmup-agent-capabilities-on-connect.ts
|
|
41909
|
-
import * as
|
|
42241
|
+
import * as path45 from "node:path";
|
|
41910
42242
|
|
|
41911
42243
|
// src/agents/capabilities/probe-one-agent-type-for-capabilities.ts
|
|
41912
|
-
import * as
|
|
42244
|
+
import * as path44 from "node:path";
|
|
41913
42245
|
async function probeOneAgentTypeForCapabilities(params) {
|
|
41914
42246
|
const { agentType, cwd, workspaceId, log: log2, reportAgentCapabilities, bridgeReport = true, shouldContinue } = params;
|
|
41915
42247
|
const canContinue = () => shouldContinue?.() !== false;
|
|
@@ -41947,7 +42279,7 @@ async function probeOneAgentTypeForCapabilities(params) {
|
|
|
41947
42279
|
if (!canContinue()) return false;
|
|
41948
42280
|
handle = await resolved.createClient({
|
|
41949
42281
|
command: resolved.command,
|
|
41950
|
-
cwd:
|
|
42282
|
+
cwd: path44.resolve(cwd),
|
|
41951
42283
|
backendAgentType: agentType,
|
|
41952
42284
|
sessionMode: "agent",
|
|
41953
42285
|
persistedAcpSessionId: null,
|
|
@@ -42025,7 +42357,7 @@ async function warmupAgentCapabilitiesOnConnect(params) {
|
|
|
42025
42357
|
const { workspaceId, log: log2, getWs } = params;
|
|
42026
42358
|
const isCurrent = beginAgentCapabilityWarmupRun();
|
|
42027
42359
|
if (!isCurrent()) return;
|
|
42028
|
-
const cwd =
|
|
42360
|
+
const cwd = path45.resolve(getBridgeRoot());
|
|
42029
42361
|
async function sendBatchFromCache() {
|
|
42030
42362
|
if (!isCurrent()) return;
|
|
42031
42363
|
const socket = getWs();
|
|
@@ -42430,8 +42762,8 @@ async function createBridgeConnection(options) {
|
|
|
42430
42762
|
getCloudAccessToken: () => tokens.accessToken
|
|
42431
42763
|
};
|
|
42432
42764
|
const identifyReportedPaths = {
|
|
42433
|
-
bridgeRootPath:
|
|
42434
|
-
worktreesRootPath:
|
|
42765
|
+
bridgeRootPath: path46.resolve(getBridgeRoot()),
|
|
42766
|
+
worktreesRootPath: path46.resolve(worktreesRootPath)
|
|
42435
42767
|
};
|
|
42436
42768
|
const { connect } = createMainBridgeWebSocketLifecycle({
|
|
42437
42769
|
state,
|
|
@@ -42686,9 +43018,9 @@ async function runCliAction(program2, opts) {
|
|
|
42686
43018
|
const firehoseServerUrl = opts.firehoseUrl ?? opts.proxyUrl ?? process.env.BUILDAUTOMATON_FIREHOSE_URL ?? process.env.BUILDAUTOMATON_PROXY_URL ?? DEFAULT_FIREHOSE_URL;
|
|
42687
43019
|
const bridgeRootOpt = (opts.bridgeRoot && typeof opts.bridgeRoot === "string" && opts.bridgeRoot.trim() ? opts.bridgeRoot.trim() : null) ?? (opts.cwd && typeof opts.cwd === "string" && opts.cwd.trim() ? opts.cwd.trim() : null);
|
|
42688
43020
|
if (bridgeRootOpt) {
|
|
42689
|
-
const resolvedBridgeRoot =
|
|
43021
|
+
const resolvedBridgeRoot = path47.resolve(process.cwd(), bridgeRootOpt);
|
|
42690
43022
|
try {
|
|
42691
|
-
const st =
|
|
43023
|
+
const st = fs41.statSync(resolvedBridgeRoot);
|
|
42692
43024
|
if (!st.isDirectory()) {
|
|
42693
43025
|
console.error(`Bridge root is not a directory: ${resolvedBridgeRoot}`);
|
|
42694
43026
|
process.exit(1);
|
|
@@ -42708,7 +43040,7 @@ async function runCliAction(program2, opts) {
|
|
|
42708
43040
|
);
|
|
42709
43041
|
let worktreesRootPath;
|
|
42710
43042
|
if (opts.worktreesRoot && opts.worktreesRoot.trim()) {
|
|
42711
|
-
worktreesRootPath =
|
|
43043
|
+
worktreesRootPath = path47.resolve(opts.worktreesRoot.trim());
|
|
42712
43044
|
}
|
|
42713
43045
|
const e2eCertificates = opts.e2eeCertificatesDir?.trim() ? await loadOrCreateE2eCertificates(opts.e2eeCertificatesDir.trim()) : void 0;
|
|
42714
43046
|
if (e2eCertificates) {
|