@vibedeckx/linux-x64 0.3.38 → 0.3.39
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/bin.js +198 -129
- package/package.json +1 -1
package/dist/bin.js
CHANGED
|
@@ -66967,7 +66967,7 @@ var require_sonic_boom = __commonJS({
|
|
|
66967
66967
|
if (!(this instanceof SonicBoom)) {
|
|
66968
66968
|
return new SonicBoom(opts);
|
|
66969
66969
|
}
|
|
66970
|
-
let { fd, dest, minLength, maxLength, maxWrite, periodicFlush, sync, append = true, mkdir:
|
|
66970
|
+
let { fd, dest, minLength, maxLength, maxWrite, periodicFlush, sync, append = true, mkdir: mkdir6, retryEAGAIN, fsync, contentMode, mode } = opts || {};
|
|
66971
66971
|
fd = fd || dest;
|
|
66972
66972
|
this._len = 0;
|
|
66973
66973
|
this.fd = -1;
|
|
@@ -66992,7 +66992,7 @@ var require_sonic_boom = __commonJS({
|
|
|
66992
66992
|
this.append = append || false;
|
|
66993
66993
|
this.mode = mode;
|
|
66994
66994
|
this.retryEAGAIN = retryEAGAIN || (() => true);
|
|
66995
|
-
this.mkdir =
|
|
66995
|
+
this.mkdir = mkdir6 || false;
|
|
66996
66996
|
let fsWriteSync;
|
|
66997
66997
|
let fsWrite;
|
|
66998
66998
|
if (contentMode === kContentModeBuffer) {
|
|
@@ -100215,7 +100215,7 @@ var require_commonjs6 = __commonJS({
|
|
|
100215
100215
|
var node_url_1 = __require("node:url");
|
|
100216
100216
|
var fs_1 = __require("fs");
|
|
100217
100217
|
var actualFS = __importStar(__require("node:fs"));
|
|
100218
|
-
var
|
|
100218
|
+
var realpathSync2 = fs_1.realpathSync.native;
|
|
100219
100219
|
var promises_1 = __require("node:fs/promises");
|
|
100220
100220
|
var minipass_1 = require_commonjs5();
|
|
100221
100221
|
var defaultFS = {
|
|
@@ -100223,7 +100223,7 @@ var require_commonjs6 = __commonJS({
|
|
|
100223
100223
|
readdir: fs_1.readdir,
|
|
100224
100224
|
readdirSync: fs_1.readdirSync,
|
|
100225
100225
|
readlinkSync: fs_1.readlinkSync,
|
|
100226
|
-
realpathSync,
|
|
100226
|
+
realpathSync: realpathSync2,
|
|
100227
100227
|
promises: {
|
|
100228
100228
|
lstat: promises_1.lstat,
|
|
100229
100229
|
readdir: promises_1.readdir,
|
|
@@ -115594,7 +115594,7 @@ var require_token_io = __commonJS({
|
|
|
115594
115594
|
});
|
|
115595
115595
|
module.exports = __toCommonJS2(token_io_exports);
|
|
115596
115596
|
var import_path16 = __toESM3(__require("path"));
|
|
115597
|
-
var
|
|
115597
|
+
var import_fs11 = __toESM3(__require("fs"));
|
|
115598
115598
|
var import_os4 = __toESM3(__require("os"));
|
|
115599
115599
|
var import_token_error = require_token_error();
|
|
115600
115600
|
function findRootDir() {
|
|
@@ -115602,7 +115602,7 @@ var require_token_io = __commonJS({
|
|
|
115602
115602
|
let dir = process.cwd();
|
|
115603
115603
|
while (dir !== import_path16.default.dirname(dir)) {
|
|
115604
115604
|
const pkgPath = import_path16.default.join(dir, ".vercel");
|
|
115605
|
-
if (
|
|
115605
|
+
if (import_fs11.default.existsSync(pkgPath)) {
|
|
115606
115606
|
return dir;
|
|
115607
115607
|
}
|
|
115608
115608
|
dir = import_path16.default.dirname(dir);
|
|
@@ -128873,7 +128873,7 @@ var require_snapshot_utils = __commonJS({
|
|
|
128873
128873
|
var require_snapshot_recorder = __commonJS({
|
|
128874
128874
|
"../../node_modules/.pnpm/undici@7.22.0/node_modules/undici/lib/mock/snapshot-recorder.js"(exports, module) {
|
|
128875
128875
|
"use strict";
|
|
128876
|
-
var { writeFile: writeFile2, readFile: readFile2, mkdir:
|
|
128876
|
+
var { writeFile: writeFile2, readFile: readFile2, mkdir: mkdir6 } = __require("node:fs/promises");
|
|
128877
128877
|
var { dirname, resolve: resolve3 } = __require("node:path");
|
|
128878
128878
|
var { setTimeout: setTimeout3, clearTimeout: clearTimeout2 } = __require("node:timers");
|
|
128879
128879
|
var { InvalidArgumentError: InvalidArgumentError4, UndiciError } = require_errors7();
|
|
@@ -129105,7 +129105,7 @@ var require_snapshot_recorder = __commonJS({
|
|
|
129105
129105
|
throw new InvalidArgumentError4("Snapshot path is required");
|
|
129106
129106
|
}
|
|
129107
129107
|
const resolvedPath = resolve3(path26);
|
|
129108
|
-
await
|
|
129108
|
+
await mkdir6(dirname(resolvedPath), { recursive: true });
|
|
129109
129109
|
const data = Array.from(this.#snapshots.entries()).map(([hash2, snapshot]) => ({
|
|
129110
129110
|
hash: hash2,
|
|
129111
129111
|
snapshot
|
|
@@ -208665,6 +208665,7 @@ function parseRows(rows, sessionIdForLog) {
|
|
|
208665
208665
|
import path7 from "path";
|
|
208666
208666
|
import { createHash } from "crypto";
|
|
208667
208667
|
import { execSync, execFileSync as execFileSync2 } from "child_process";
|
|
208668
|
+
import { mkdirSync as mkdirSync2, realpathSync } from "fs";
|
|
208668
208669
|
var WORKTREE_BASE_DIR = "/var/tmp/vibedeckx/worktrees";
|
|
208669
208670
|
var WORKTREE_LIST_TTL_MS = 1e4;
|
|
208670
208671
|
var worktreeListCache = /* @__PURE__ */ new Map();
|
|
@@ -208677,35 +208678,41 @@ function isSubpath(basePath33, targetPath) {
|
|
|
208677
208678
|
const relative = path7.relative(basePath33, targetPath);
|
|
208678
208679
|
return relative === "" || !relative.startsWith("..") && !path7.isAbsolute(relative);
|
|
208679
208680
|
}
|
|
208681
|
+
function canonicalPath(target) {
|
|
208682
|
+
try {
|
|
208683
|
+
return realpathSync(target);
|
|
208684
|
+
} catch {
|
|
208685
|
+
return path7.resolve(target);
|
|
208686
|
+
}
|
|
208687
|
+
}
|
|
208680
208688
|
function isTrustedWorktreePath(projectPath, worktreePath) {
|
|
208681
|
-
const normalizedWorktreePath =
|
|
208682
|
-
if (normalizedWorktreePath ===
|
|
208683
|
-
const managedBase =
|
|
208689
|
+
const normalizedWorktreePath = canonicalPath(worktreePath);
|
|
208690
|
+
if (normalizedWorktreePath === canonicalPath(projectPath)) return true;
|
|
208691
|
+
const managedBase = canonicalPath(getWorktreeBaseForProject(projectPath));
|
|
208684
208692
|
return isSubpath(managedBase, normalizedWorktreePath);
|
|
208685
208693
|
}
|
|
208686
|
-
function
|
|
208694
|
+
function readWorktreeRecords(projectPath) {
|
|
208687
208695
|
const output = execSync("git worktree list --porcelain", {
|
|
208688
208696
|
cwd: projectPath,
|
|
208689
208697
|
encoding: "utf-8",
|
|
208690
208698
|
stdio: ["pipe", "pipe", "pipe"]
|
|
208691
208699
|
});
|
|
208692
|
-
const
|
|
208693
|
-
const
|
|
208694
|
-
for (const block of blocks) {
|
|
208695
|
-
const lines = block.split("\n");
|
|
208700
|
+
const records = [];
|
|
208701
|
+
for (const block of output.trim().split("\n\n")) {
|
|
208696
208702
|
let worktreePath = "";
|
|
208697
208703
|
let branch = null;
|
|
208698
|
-
let
|
|
208699
|
-
for (const line of
|
|
208704
|
+
let prunable = false;
|
|
208705
|
+
for (const line of block.split("\n")) {
|
|
208700
208706
|
if (line.startsWith("worktree ")) worktreePath = line.slice(9);
|
|
208701
208707
|
else if (line.startsWith("branch refs/heads/")) branch = line.slice(18);
|
|
208702
|
-
else if (line === "prunable" || line.startsWith("prunable "))
|
|
208703
|
-
}
|
|
208704
|
-
if (worktreePath && !isPrunable && isTrustedWorktreePath(projectPath, worktreePath)) {
|
|
208705
|
-
entries.push({ path: worktreePath, branch });
|
|
208708
|
+
else if (line === "prunable" || line.startsWith("prunable ")) prunable = true;
|
|
208706
208709
|
}
|
|
208710
|
+
if (worktreePath) records.push({ path: worktreePath, branch, prunable });
|
|
208707
208711
|
}
|
|
208708
|
-
return
|
|
208712
|
+
return records;
|
|
208713
|
+
}
|
|
208714
|
+
function readWorktreeListFromGit(projectPath) {
|
|
208715
|
+
return readWorktreeRecords(projectPath).filter((record2) => !record2.prunable && isTrustedWorktreePath(projectPath, record2.path)).map(({ path: worktreePath, branch }) => ({ path: worktreePath, branch }));
|
|
208709
208716
|
}
|
|
208710
208717
|
function parseGitWorktreeList(projectPath) {
|
|
208711
208718
|
const now3 = Date.now();
|
|
@@ -208739,6 +208746,76 @@ function pruneWorktrees(projectPath) {
|
|
|
208739
208746
|
function invalidateWorktreeListCache(projectPath) {
|
|
208740
208747
|
worktreeListCache.delete(projectPath);
|
|
208741
208748
|
}
|
|
208749
|
+
function branchExists(projectPath, branch) {
|
|
208750
|
+
try {
|
|
208751
|
+
execFileSync2("git", ["rev-parse", "--verify", `refs/heads/${branch}`], {
|
|
208752
|
+
cwd: projectPath,
|
|
208753
|
+
encoding: "utf-8",
|
|
208754
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
208755
|
+
});
|
|
208756
|
+
return true;
|
|
208757
|
+
} catch {
|
|
208758
|
+
return false;
|
|
208759
|
+
}
|
|
208760
|
+
}
|
|
208761
|
+
function planWorktreeAdd(projectPath, branch, startPoint) {
|
|
208762
|
+
const exists2 = branchExists(projectPath, branch);
|
|
208763
|
+
if (exists2) {
|
|
208764
|
+
pruneWorktrees(projectPath);
|
|
208765
|
+
const existing = parseGitWorktreeList(projectPath).find((e) => e.branch === branch);
|
|
208766
|
+
if (existing) {
|
|
208767
|
+
if (canonicalPath(existing.path) === canonicalPath(projectPath)) {
|
|
208768
|
+
throw Object.assign(
|
|
208769
|
+
new Error(`Branch '${branch}' is checked out in the main workspace`),
|
|
208770
|
+
{ statusCode: 409 }
|
|
208771
|
+
);
|
|
208772
|
+
}
|
|
208773
|
+
return { worktreePath: existing.path, adopted: true, addArgs: null };
|
|
208774
|
+
}
|
|
208775
|
+
}
|
|
208776
|
+
const worktreePath = resolveWorktreePath(projectPath, branch);
|
|
208777
|
+
return {
|
|
208778
|
+
worktreePath,
|
|
208779
|
+
adopted: exists2,
|
|
208780
|
+
addArgs: exists2 ? ["worktree", "add", worktreePath, branch] : ["worktree", "add", "-b", branch, worktreePath, startPoint]
|
|
208781
|
+
};
|
|
208782
|
+
}
|
|
208783
|
+
function liveWorktreeRecord(projectPath, worktreePath) {
|
|
208784
|
+
const target = canonicalPath(worktreePath);
|
|
208785
|
+
const match2 = readWorktreeRecords(projectPath).find((record2) => !record2.prunable && canonicalPath(record2.path) === target);
|
|
208786
|
+
return match2 ? { path: match2.path, branch: match2.branch } : null;
|
|
208787
|
+
}
|
|
208788
|
+
function worktreeRecordExists(projectPath, worktreePath) {
|
|
208789
|
+
try {
|
|
208790
|
+
return liveWorktreeRecord(projectPath, worktreePath) !== null;
|
|
208791
|
+
} catch {
|
|
208792
|
+
return null;
|
|
208793
|
+
}
|
|
208794
|
+
}
|
|
208795
|
+
function deleteBranchAfterRemoval(projectPath, branch) {
|
|
208796
|
+
if (!branchExists(projectPath, branch)) return null;
|
|
208797
|
+
try {
|
|
208798
|
+
execFileSync2("git", ["branch", "-d", branch], {
|
|
208799
|
+
cwd: projectPath,
|
|
208800
|
+
encoding: "utf-8",
|
|
208801
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
208802
|
+
});
|
|
208803
|
+
return null;
|
|
208804
|
+
} catch (error48) {
|
|
208805
|
+
const stderr = String(error48?.stderr ?? "");
|
|
208806
|
+
return { branch, unmerged: /not fully merged/i.test(stderr) };
|
|
208807
|
+
}
|
|
208808
|
+
}
|
|
208809
|
+
function applyWorktreeAdd(projectPath, plan) {
|
|
208810
|
+
if (!plan.addArgs) return;
|
|
208811
|
+
mkdirSync2(getWorktreeBaseForProject(projectPath), { recursive: true });
|
|
208812
|
+
execFileSync2("git", plan.addArgs, {
|
|
208813
|
+
cwd: projectPath,
|
|
208814
|
+
encoding: "utf-8",
|
|
208815
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
208816
|
+
});
|
|
208817
|
+
invalidateWorktreeListCache(projectPath);
|
|
208818
|
+
}
|
|
208742
208819
|
function resolveWorktreePath(projectPath, branch) {
|
|
208743
208820
|
if (!branch) return projectPath;
|
|
208744
208821
|
try {
|
|
@@ -247391,7 +247468,6 @@ var process_routes_default = (0, import_fastify_plugin8.default)(routes7, { name
|
|
|
247391
247468
|
|
|
247392
247469
|
// src/routes/worktree-routes.ts
|
|
247393
247470
|
var import_fastify_plugin9 = __toESM(require_plugin2(), 1);
|
|
247394
|
-
import { mkdir as mkdir4 } from "fs/promises";
|
|
247395
247471
|
|
|
247396
247472
|
// src/utils/path-project.ts
|
|
247397
247473
|
async function ensurePathProjectId(fastify2, projectPath) {
|
|
@@ -247413,7 +247489,8 @@ async function getAllRemoteConfigs(fastify2, project) {
|
|
|
247413
247489
|
const remotes = await fastify2.storage.projectRemotes.getByProject(project.id);
|
|
247414
247490
|
return remotes.map((r) => ({
|
|
247415
247491
|
serverId: r.remote_server_id,
|
|
247416
|
-
remotePath: r.remote_path
|
|
247492
|
+
remotePath: r.remote_path,
|
|
247493
|
+
serverName: r.server_name
|
|
247417
247494
|
}));
|
|
247418
247495
|
}
|
|
247419
247496
|
async function getRemoteConfig(fastify2, project) {
|
|
@@ -247436,6 +247513,30 @@ async function ensurePathProject(fastify2, projectPath) {
|
|
|
247436
247513
|
if (!project) throw new Error(`Path project '${projectId}' was not persisted`);
|
|
247437
247514
|
return project;
|
|
247438
247515
|
}
|
|
247516
|
+
function removeWorktreeIfPresent(execFileSync8, projectPath, worktreePath) {
|
|
247517
|
+
try {
|
|
247518
|
+
execFileSync8("git", ["worktree", "remove", worktreePath], {
|
|
247519
|
+
cwd: projectPath,
|
|
247520
|
+
encoding: "utf-8",
|
|
247521
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
247522
|
+
});
|
|
247523
|
+
} catch (error48) {
|
|
247524
|
+
if (worktreeRecordExists(projectPath, worktreePath) !== false) throw error48;
|
|
247525
|
+
pruneWorktrees(projectPath);
|
|
247526
|
+
}
|
|
247527
|
+
}
|
|
247528
|
+
async function assertPathIsFree(fastify2, opts) {
|
|
247529
|
+
const registered = await fastify2.storage.workspaceRegistry.listByProject(opts.projectId, opts.targetId);
|
|
247530
|
+
const target = canonicalPath(opts.worktreePath);
|
|
247531
|
+
const owner = registered.find((row) => row.workspace.branch !== opts.branch && canonicalPath(row.checkout.worktree_path) === target);
|
|
247532
|
+
if (!owner) return;
|
|
247533
|
+
throw Object.assign(
|
|
247534
|
+
new Error(
|
|
247535
|
+
`That worktree already belongs to workspace '${owner.workspace.branch || "main"}'`
|
|
247536
|
+
),
|
|
247537
|
+
{ statusCode: 409 }
|
|
247538
|
+
);
|
|
247539
|
+
}
|
|
247439
247540
|
async function syncRemoteWorktreeList(fastify2, projectId, remote, data) {
|
|
247440
247541
|
const worktrees = data?.worktrees;
|
|
247441
247542
|
if (!Array.isArray(worktrees)) return;
|
|
@@ -247535,37 +247636,27 @@ var routes8 = async (fastify2) => {
|
|
|
247535
247636
|
console.log(`[worktree] ${requestId} Creating: branch=${trimmedBranch}, base=${startPoint}, path=${projectPath}`);
|
|
247536
247637
|
let pendingCheckoutId = null;
|
|
247537
247638
|
try {
|
|
247538
|
-
const
|
|
247539
|
-
try {
|
|
247540
|
-
execFileSync8("git", ["rev-parse", "--verify", `refs/heads/${trimmedBranch}`], {
|
|
247541
|
-
cwd: projectPath,
|
|
247542
|
-
encoding: "utf-8",
|
|
247543
|
-
stdio: ["pipe", "pipe", "pipe"]
|
|
247544
|
-
});
|
|
247545
|
-
return reply.code(409).send({ error: `Branch '${trimmedBranch}' already exists` });
|
|
247546
|
-
} catch {
|
|
247547
|
-
}
|
|
247548
|
-
const worktreeAbsolutePath = resolveWorktreePath(projectPath, trimmedBranch);
|
|
247639
|
+
const plan = planWorktreeAdd(projectPath, trimmedBranch, startPoint);
|
|
247549
247640
|
const project = await ensurePathProject(fastify2, projectPath);
|
|
247641
|
+
await assertPathIsFree(fastify2, {
|
|
247642
|
+
projectId: project.id,
|
|
247643
|
+
branch: trimmedBranch,
|
|
247644
|
+
targetId: "local",
|
|
247645
|
+
worktreePath: plan.worktreePath
|
|
247646
|
+
});
|
|
247550
247647
|
const pending = await fastify2.storage.workspaceRegistry.beginCheckout({
|
|
247551
247648
|
projectId: project.id,
|
|
247552
247649
|
branch: trimmedBranch,
|
|
247553
247650
|
targetId: "local",
|
|
247554
|
-
worktreePath:
|
|
247651
|
+
worktreePath: plan.worktreePath,
|
|
247555
247652
|
expectedBranch: trimmedBranch
|
|
247556
247653
|
});
|
|
247557
247654
|
pendingCheckoutId = pending.checkout.id;
|
|
247558
|
-
|
|
247559
|
-
execFileSync8("git", ["worktree", "add", "-b", trimmedBranch, worktreeAbsolutePath, startPoint], {
|
|
247560
|
-
cwd: projectPath,
|
|
247561
|
-
encoding: "utf-8",
|
|
247562
|
-
stdio: ["pipe", "pipe", "pipe"]
|
|
247563
|
-
});
|
|
247564
|
-
invalidateWorktreeListCache(projectPath);
|
|
247655
|
+
applyWorktreeAdd(projectPath, plan);
|
|
247565
247656
|
await fastify2.storage.workspaceRegistry.setCheckoutStatus(pending.checkout.id, "ready");
|
|
247566
|
-
console.log(`[worktree] ${requestId} Created: branch=${trimmedBranch}`);
|
|
247657
|
+
console.log(`[worktree] ${requestId} ${plan.adopted ? "Adopted" : "Created"}: branch=${trimmedBranch}`);
|
|
247567
247658
|
return reply.code(201).send({
|
|
247568
|
-
worktree: { branch: trimmedBranch, worktreePath:
|
|
247659
|
+
worktree: { branch: trimmedBranch, worktreePath: plan.worktreePath, adopted: plan.adopted }
|
|
247569
247660
|
});
|
|
247570
247661
|
} catch (error48) {
|
|
247571
247662
|
const errorMessage = error48 instanceof Error ? error48.message : "Unknown error";
|
|
@@ -247574,6 +247665,8 @@ var routes8 = async (fastify2) => {
|
|
|
247574
247665
|
}
|
|
247575
247666
|
const stderr = error48?.stderr || "";
|
|
247576
247667
|
console.error(`[worktree] ${requestId} Failed: ${errorMessage}${stderr ? `, stderr: ${stderr}` : ""}`);
|
|
247668
|
+
const statusCode = error48?.statusCode;
|
|
247669
|
+
if (statusCode) return reply.code(statusCode).send({ error: errorMessage });
|
|
247577
247670
|
return reply.code(500).send({ error: `Failed to create worktree: ${errorMessage}` });
|
|
247578
247671
|
}
|
|
247579
247672
|
});
|
|
@@ -247615,34 +247708,19 @@ var routes8 = async (fastify2) => {
|
|
|
247615
247708
|
branch,
|
|
247616
247709
|
worktreePath: worktreeAbsPath
|
|
247617
247710
|
});
|
|
247618
|
-
let branchToDelete =
|
|
247711
|
+
let branchToDelete = branch;
|
|
247619
247712
|
try {
|
|
247620
|
-
|
|
247621
|
-
const match2 = entries.find((e) => e.path === worktreeAbsPath);
|
|
247622
|
-
if (match2) branchToDelete = match2.branch;
|
|
247713
|
+
branchToDelete = liveWorktreeRecord(projectPath, worktreeAbsPath)?.branch ?? branch;
|
|
247623
247714
|
} catch {
|
|
247624
247715
|
}
|
|
247625
|
-
execFileSync8
|
|
247626
|
-
cwd: projectPath,
|
|
247627
|
-
encoding: "utf-8",
|
|
247628
|
-
stdio: ["pipe", "pipe", "pipe"]
|
|
247629
|
-
});
|
|
247716
|
+
removeWorktreeIfPresent(execFileSync8, projectPath, worktreeAbsPath);
|
|
247630
247717
|
worktreeRemoved = true;
|
|
247631
247718
|
invalidateWorktreeListCache(projectPath);
|
|
247632
|
-
|
|
247633
|
-
try {
|
|
247634
|
-
execFileSync8("git", ["branch", "-d", branchToDelete], {
|
|
247635
|
-
cwd: projectPath,
|
|
247636
|
-
encoding: "utf-8",
|
|
247637
|
-
stdio: ["pipe", "pipe", "pipe"]
|
|
247638
|
-
});
|
|
247639
|
-
} catch {
|
|
247640
|
-
}
|
|
247641
|
-
}
|
|
247719
|
+
const branchRetained = branchToDelete ? deleteBranchAfterRemoval(projectPath, branchToDelete) : null;
|
|
247642
247720
|
if (registered) {
|
|
247643
247721
|
await fastify2.storage.workspaceRegistry.markCheckoutDeleted(registered.checkout.id);
|
|
247644
247722
|
}
|
|
247645
|
-
return reply.code(200).send({ success: true });
|
|
247723
|
+
return reply.code(200).send({ success: true, branchRetained });
|
|
247646
247724
|
} catch (error48) {
|
|
247647
247725
|
const errorMessage = error48 instanceof Error ? error48.message : "Unknown error";
|
|
247648
247726
|
const busy = error48 instanceof WorktreeBusyError;
|
|
@@ -247757,7 +247835,11 @@ var routes8 = async (fastify2) => {
|
|
|
247757
247835
|
} else {
|
|
247758
247836
|
const targetRemote = await fastify2.storage.projectRemotes.getByProjectAndServer(project.id, requestedTarget);
|
|
247759
247837
|
if (!targetRemote) return reply.code(400).send({ error: "Unknown remote target" });
|
|
247760
|
-
remoteConfig = {
|
|
247838
|
+
remoteConfig = {
|
|
247839
|
+
serverId: targetRemote.remote_server_id,
|
|
247840
|
+
remotePath: targetRemote.remote_path,
|
|
247841
|
+
serverName: targetRemote.server_name
|
|
247842
|
+
};
|
|
247761
247843
|
}
|
|
247762
247844
|
if (remoteConfig) {
|
|
247763
247845
|
const result = await proxyToRemoteAuto(
|
|
@@ -247807,7 +247889,11 @@ var routes8 = async (fastify2) => {
|
|
|
247807
247889
|
} else {
|
|
247808
247890
|
const targetRemote = await fastify2.storage.projectRemotes.getByProjectAndServer(project.id, requestedTarget);
|
|
247809
247891
|
if (!targetRemote) return reply.code(400).send({ error: "Unknown remote target" });
|
|
247810
|
-
remoteConfig = {
|
|
247892
|
+
remoteConfig = {
|
|
247893
|
+
serverId: targetRemote.remote_server_id,
|
|
247894
|
+
remotePath: targetRemote.remote_path,
|
|
247895
|
+
serverName: targetRemote.server_name
|
|
247896
|
+
};
|
|
247811
247897
|
}
|
|
247812
247898
|
if (remoteConfig) {
|
|
247813
247899
|
const result = await proxyToRemoteAuto(
|
|
@@ -247951,17 +248037,19 @@ var routes8 = async (fastify2) => {
|
|
|
247951
248037
|
await Promise.allSettled(
|
|
247952
248038
|
remoteConfigs.map(async (rc) => {
|
|
247953
248039
|
const key2 = rc.serverId;
|
|
248040
|
+
const label = rc.serverName;
|
|
247954
248041
|
try {
|
|
247955
248042
|
const result = await deleteOnRemote(rc);
|
|
247956
248043
|
if (result.ok) {
|
|
247957
|
-
|
|
248044
|
+
const data = result.data;
|
|
248045
|
+
results2[key2] = { success: true, label, branchRetained: data?.branchRetained };
|
|
247958
248046
|
} else {
|
|
247959
248047
|
const data = result.data;
|
|
247960
|
-
results2[key2] = { success: false, error: data.error || "Remote deletion failed" };
|
|
248048
|
+
results2[key2] = { success: false, label, error: data.error || "Remote deletion failed" };
|
|
247961
248049
|
}
|
|
247962
248050
|
} catch (error48) {
|
|
247963
248051
|
const errorMessage = error48 instanceof Error ? error48.message : "Unknown error";
|
|
247964
|
-
results2[key2] = { success: false, error: errorMessage };
|
|
248052
|
+
results2[key2] = { success: false, label, error: errorMessage };
|
|
247965
248053
|
}
|
|
247966
248054
|
})
|
|
247967
248055
|
);
|
|
@@ -248000,33 +248088,19 @@ var routes8 = async (fastify2) => {
|
|
|
248000
248088
|
branch,
|
|
248001
248089
|
worktreePath: worktreeAbsPath
|
|
248002
248090
|
});
|
|
248003
|
-
let branchToDelete =
|
|
248091
|
+
let branchToDelete = branch;
|
|
248004
248092
|
try {
|
|
248005
|
-
|
|
248006
|
-
const match2 = entries.find((e) => e.path === worktreeAbsPath);
|
|
248007
|
-
if (match2) branchToDelete = match2.branch;
|
|
248093
|
+
branchToDelete = liveWorktreeRecord(project.path, worktreeAbsPath)?.branch ?? branch;
|
|
248008
248094
|
} catch {
|
|
248009
248095
|
}
|
|
248010
|
-
execFileSync8
|
|
248011
|
-
cwd: project.path,
|
|
248012
|
-
encoding: "utf-8",
|
|
248013
|
-
stdio: ["pipe", "pipe", "pipe"]
|
|
248014
|
-
});
|
|
248096
|
+
removeWorktreeIfPresent(execFileSync8, project.path, worktreeAbsPath);
|
|
248015
248097
|
worktreeRemoved = true;
|
|
248016
248098
|
invalidateWorktreeListCache(project.path);
|
|
248017
|
-
|
|
248018
|
-
try {
|
|
248019
|
-
execFileSync8("git", ["branch", "-d", branchToDelete], {
|
|
248020
|
-
cwd: project.path,
|
|
248021
|
-
encoding: "utf-8",
|
|
248022
|
-
stdio: ["pipe", "pipe", "pipe"]
|
|
248023
|
-
});
|
|
248024
|
-
} catch {
|
|
248025
|
-
}
|
|
248026
|
-
}
|
|
248099
|
+
const branchRetained = branchToDelete ? deleteBranchAfterRemoval(project.path, branchToDelete) : null;
|
|
248027
248100
|
if (registered) {
|
|
248028
248101
|
await fastify2.storage.workspaceRegistry.markCheckoutDeleted(registered.checkout.id);
|
|
248029
248102
|
}
|
|
248103
|
+
return branchRetained;
|
|
248030
248104
|
} catch (error48) {
|
|
248031
248105
|
if (registered && !worktreeRemoved) {
|
|
248032
248106
|
const message = error48 instanceof Error ? error48.message : "Local deletion failed";
|
|
@@ -248038,8 +248112,8 @@ var routes8 = async (fastify2) => {
|
|
|
248038
248112
|
};
|
|
248039
248113
|
if (!hasRemote) {
|
|
248040
248114
|
try {
|
|
248041
|
-
await deleteLocal();
|
|
248042
|
-
return reply.code(200).send({ success: true });
|
|
248115
|
+
const branchRetained = await deleteLocal();
|
|
248116
|
+
return reply.code(200).send({ success: true, branchRetained });
|
|
248043
248117
|
} catch (error48) {
|
|
248044
248118
|
const errorMessage = error48 instanceof Error ? error48.message : "Unknown error";
|
|
248045
248119
|
if (errorMessage.includes("uncommitted changes") || error48 instanceof WorktreeBusyError) {
|
|
@@ -248050,8 +248124,7 @@ var routes8 = async (fastify2) => {
|
|
|
248050
248124
|
}
|
|
248051
248125
|
const results = {};
|
|
248052
248126
|
try {
|
|
248053
|
-
await deleteLocal();
|
|
248054
|
-
results.local = { success: true };
|
|
248127
|
+
results.local = { success: true, label: "local", branchRetained: await deleteLocal() };
|
|
248055
248128
|
} catch (error48) {
|
|
248056
248129
|
const errorMessage = error48 instanceof Error ? error48.message : "Unknown error";
|
|
248057
248130
|
return reply.code(500).send({ error: `Failed to delete local worktree: ${errorMessage}` });
|
|
@@ -248059,17 +248132,19 @@ var routes8 = async (fastify2) => {
|
|
|
248059
248132
|
await Promise.allSettled(
|
|
248060
248133
|
remoteConfigs.map(async (rc) => {
|
|
248061
248134
|
const key2 = remoteConfigs.length === 1 ? "remote" : rc.serverId;
|
|
248135
|
+
const label = rc.serverName;
|
|
248062
248136
|
try {
|
|
248063
248137
|
const remoteResult = await deleteOnRemote(rc);
|
|
248064
248138
|
if (remoteResult.ok) {
|
|
248065
|
-
|
|
248139
|
+
const remoteData = remoteResult.data;
|
|
248140
|
+
results[key2] = { success: true, label, branchRetained: remoteData?.branchRetained };
|
|
248066
248141
|
} else {
|
|
248067
248142
|
const remoteData = remoteResult.data;
|
|
248068
|
-
results[key2] = { success: false, error: remoteData.error || "Remote deletion failed" };
|
|
248143
|
+
results[key2] = { success: false, label, error: remoteData.error || "Remote deletion failed" };
|
|
248069
248144
|
}
|
|
248070
248145
|
} catch (error48) {
|
|
248071
248146
|
const errorMessage = error48 instanceof Error ? error48.message : "Unknown error";
|
|
248072
|
-
results[key2] = { success: false, error: errorMessage };
|
|
248147
|
+
results[key2] = { success: false, label, error: errorMessage };
|
|
248073
248148
|
}
|
|
248074
248149
|
})
|
|
248075
248150
|
);
|
|
@@ -248183,20 +248258,21 @@ var routes8 = async (fastify2) => {
|
|
|
248183
248258
|
const settled = await Promise.allSettled(
|
|
248184
248259
|
remoteConfigs.map(async (rc) => {
|
|
248185
248260
|
const key2 = rc.serverId;
|
|
248261
|
+
const label = rc.serverName;
|
|
248186
248262
|
console.log(`[worktree] Creating remote worktree: project=${req.params.id}, branch=${trimmedBranch}, serverId=${rc.serverId}`);
|
|
248187
248263
|
try {
|
|
248188
248264
|
const result = await createOnRemote(rc);
|
|
248189
248265
|
if (result.ok) {
|
|
248190
248266
|
const data = result.data;
|
|
248191
|
-
results2[key2] = { success: true, worktree: data.worktree };
|
|
248267
|
+
results2[key2] = { success: true, label, worktree: data.worktree, adopted: data.worktree?.adopted };
|
|
248192
248268
|
} else {
|
|
248193
248269
|
const data = result.data;
|
|
248194
248270
|
console.error(`[worktree] Remote failed: serverId=${rc.serverId}, requestId=${result.requestId}, error=${JSON.stringify(result.data)}`);
|
|
248195
|
-
results2[key2] = { success: false, error: data.error || "Remote creation failed", errorCode: result.errorCode, requestId: result.requestId };
|
|
248271
|
+
results2[key2] = { success: false, label, error: data.error || "Remote creation failed", errorCode: result.errorCode, requestId: result.requestId };
|
|
248196
248272
|
}
|
|
248197
248273
|
} catch (error48) {
|
|
248198
248274
|
const errorMessage = error48 instanceof Error ? error48.message : "Unknown error";
|
|
248199
|
-
results2[key2] = { success: false, error: errorMessage };
|
|
248275
|
+
results2[key2] = { success: false, label, error: errorMessage };
|
|
248200
248276
|
}
|
|
248201
248277
|
})
|
|
248202
248278
|
);
|
|
@@ -248211,35 +248287,24 @@ var routes8 = async (fastify2) => {
|
|
|
248211
248287
|
return reply.code(201).send({ worktree: { branch: trimmedBranch }, results: results2 });
|
|
248212
248288
|
}
|
|
248213
248289
|
const createLocal = async () => {
|
|
248214
|
-
const
|
|
248215
|
-
|
|
248216
|
-
|
|
248217
|
-
|
|
248218
|
-
|
|
248219
|
-
|
|
248220
|
-
|
|
248221
|
-
throw new Error(`Branch '${trimmedBranch}' already exists`);
|
|
248222
|
-
} catch (err) {
|
|
248223
|
-
if (err instanceof Error && err.message.includes("already exists")) throw err;
|
|
248224
|
-
}
|
|
248225
|
-
const worktreeAbsolutePath = resolveWorktreePath(project.path, trimmedBranch);
|
|
248290
|
+
const plan = planWorktreeAdd(project.path, trimmedBranch, localStartPoint);
|
|
248291
|
+
await assertPathIsFree(fastify2, {
|
|
248292
|
+
projectId: project.id,
|
|
248293
|
+
branch: trimmedBranch,
|
|
248294
|
+
targetId: "local",
|
|
248295
|
+
worktreePath: plan.worktreePath
|
|
248296
|
+
});
|
|
248226
248297
|
const pending = await fastify2.storage.workspaceRegistry.beginCheckout({
|
|
248227
248298
|
projectId: project.id,
|
|
248228
248299
|
branch: trimmedBranch,
|
|
248229
248300
|
targetId: "local",
|
|
248230
|
-
worktreePath:
|
|
248301
|
+
worktreePath: plan.worktreePath,
|
|
248231
248302
|
expectedBranch: trimmedBranch
|
|
248232
248303
|
});
|
|
248233
248304
|
try {
|
|
248234
|
-
|
|
248235
|
-
execFileSync8("git", ["worktree", "add", "-b", trimmedBranch, worktreeAbsolutePath, localStartPoint], {
|
|
248236
|
-
cwd: project.path,
|
|
248237
|
-
encoding: "utf-8",
|
|
248238
|
-
stdio: ["pipe", "pipe", "pipe"]
|
|
248239
|
-
});
|
|
248240
|
-
invalidateWorktreeListCache(project.path);
|
|
248305
|
+
applyWorktreeAdd(project.path, plan);
|
|
248241
248306
|
await fastify2.storage.workspaceRegistry.setCheckoutStatus(pending.checkout.id, "ready");
|
|
248242
|
-
return { branch: trimmedBranch };
|
|
248307
|
+
return { branch: trimmedBranch, adopted: plan.adopted };
|
|
248243
248308
|
} catch (error48) {
|
|
248244
248309
|
const message = error48 instanceof Error ? error48.message : "Local creation failed";
|
|
248245
248310
|
await fastify2.storage.workspaceRegistry.setCheckoutStatus(pending.checkout.id, "error", message).catch((registryError) => console.error("[worktree] Failed to record local checkout error:", registryError));
|
|
@@ -248252,6 +248317,8 @@ var routes8 = async (fastify2) => {
|
|
|
248252
248317
|
return reply.code(201).send({ worktree });
|
|
248253
248318
|
} catch (error48) {
|
|
248254
248319
|
const errorMessage = error48 instanceof Error ? error48.message : "Unknown error";
|
|
248320
|
+
const statusCode = error48?.statusCode;
|
|
248321
|
+
if (statusCode) return reply.code(statusCode).send({ error: errorMessage });
|
|
248255
248322
|
if (errorMessage.includes("already exists")) {
|
|
248256
248323
|
return reply.code(409).send({ error: errorMessage });
|
|
248257
248324
|
}
|
|
@@ -248262,7 +248329,7 @@ var routes8 = async (fastify2) => {
|
|
|
248262
248329
|
let localWorktree;
|
|
248263
248330
|
try {
|
|
248264
248331
|
localWorktree = await createLocal();
|
|
248265
|
-
results.local = { success: true, worktree: localWorktree };
|
|
248332
|
+
results.local = { success: true, label: "local", worktree: localWorktree, adopted: localWorktree.adopted };
|
|
248266
248333
|
} catch (error48) {
|
|
248267
248334
|
const errorMessage = error48 instanceof Error ? error48.message : "Unknown error";
|
|
248268
248335
|
return reply.code(500).send({ error: `Failed to create local worktree: ${errorMessage}` });
|
|
@@ -248270,17 +248337,19 @@ var routes8 = async (fastify2) => {
|
|
|
248270
248337
|
await Promise.allSettled(
|
|
248271
248338
|
remoteConfigs.map(async (rc) => {
|
|
248272
248339
|
const key2 = remoteConfigs.length === 1 ? "remote" : rc.serverId;
|
|
248340
|
+
const label = rc.serverName;
|
|
248273
248341
|
console.log(`[worktree] Creating remote worktree: project=${req.params.id}, branch=${trimmedBranch}, serverId=${rc.serverId}`);
|
|
248274
248342
|
try {
|
|
248275
248343
|
const remoteResult = await createOnRemote(rc);
|
|
248276
248344
|
if (remoteResult.ok) {
|
|
248277
248345
|
const remoteData = remoteResult.data;
|
|
248278
|
-
results[key2] = { success: true, worktree: remoteData.worktree };
|
|
248346
|
+
results[key2] = { success: true, label, worktree: remoteData.worktree, adopted: remoteData.worktree?.adopted };
|
|
248279
248347
|
} else {
|
|
248280
248348
|
const remoteData = remoteResult.data;
|
|
248281
248349
|
console.error(`[worktree] Remote failed: serverId=${rc.serverId}, requestId=${remoteResult.requestId}, errorCode=${remoteResult.errorCode}, status=${remoteResult.status}, duration=${remoteResult.durationMs}ms, error=${JSON.stringify(remoteResult.data)}`);
|
|
248282
248350
|
results[key2] = {
|
|
248283
248351
|
success: false,
|
|
248352
|
+
label,
|
|
248284
248353
|
error: remoteData.error || "Remote creation failed",
|
|
248285
248354
|
errorCode: remoteResult.errorCode,
|
|
248286
248355
|
requestId: remoteResult.requestId
|
|
@@ -248288,7 +248357,7 @@ var routes8 = async (fastify2) => {
|
|
|
248288
248357
|
}
|
|
248289
248358
|
} catch (error48) {
|
|
248290
248359
|
const errorMessage = error48 instanceof Error ? error48.message : "Unknown error";
|
|
248291
|
-
results[key2] = { success: false, error: errorMessage };
|
|
248360
|
+
results[key2] = { success: false, label, error: errorMessage };
|
|
248292
248361
|
}
|
|
248293
248362
|
})
|
|
248294
248363
|
);
|
|
@@ -249600,7 +249669,7 @@ var file_routes_default = (0, import_fastify_plugin11.default)(routes10, { name:
|
|
|
249600
249669
|
var import_fastify_plugin12 = __toESM(require_plugin2(), 1);
|
|
249601
249670
|
|
|
249602
249671
|
// src/utils/paste-file.ts
|
|
249603
|
-
import { chmod, mkdir as
|
|
249672
|
+
import { chmod, mkdir as mkdir4, open as open2 } from "node:fs/promises";
|
|
249604
249673
|
import { constants as fsConstants2 } from "node:fs";
|
|
249605
249674
|
import path15 from "node:path";
|
|
249606
249675
|
import { randomUUID as randomUUID15 } from "node:crypto";
|
|
@@ -249646,7 +249715,7 @@ var DIR_MODE = 448;
|
|
|
249646
249715
|
var FILE_MODE = 384;
|
|
249647
249716
|
var FILE_FLAGS = fsConstants2.O_WRONLY | fsConstants2.O_CREAT | fsConstants2.O_EXCL | fsConstants2.O_NOFOLLOW;
|
|
249648
249717
|
async function writePasteToTempFile(content) {
|
|
249649
|
-
await
|
|
249718
|
+
await mkdir4(PASTE_DIR, { recursive: true, mode: DIR_MODE });
|
|
249650
249719
|
await chmod(PASTE_DIR, DIR_MODE);
|
|
249651
249720
|
const filePath = path15.join(PASTE_DIR, `${randomUUID15()}.txt`);
|
|
249652
249721
|
const handle = await open2(filePath, FILE_FLAGS, FILE_MODE);
|
|
@@ -249660,7 +249729,7 @@ async function writePasteToTempFile(content) {
|
|
|
249660
249729
|
}
|
|
249661
249730
|
|
|
249662
249731
|
// src/utils/attachment-file.ts
|
|
249663
|
-
import { chmod as chmod2, mkdir as
|
|
249732
|
+
import { chmod as chmod2, mkdir as mkdir5, open as open3 } from "node:fs/promises";
|
|
249664
249733
|
import { constants as fsConstants3 } from "node:fs";
|
|
249665
249734
|
import path16 from "node:path";
|
|
249666
249735
|
import { randomUUID as randomUUID16 } from "node:crypto";
|
|
@@ -249683,10 +249752,10 @@ function sanitizeAttachmentName(raw) {
|
|
|
249683
249752
|
}
|
|
249684
249753
|
async function writeAttachmentToTempFile(rawName, data) {
|
|
249685
249754
|
const name25 = sanitizeAttachmentName(rawName);
|
|
249686
|
-
await
|
|
249755
|
+
await mkdir5(ATTACHMENT_DIR, { recursive: true, mode: DIR_MODE2 });
|
|
249687
249756
|
await chmod2(ATTACHMENT_DIR, DIR_MODE2);
|
|
249688
249757
|
const dir = path16.join(ATTACHMENT_DIR, randomUUID16());
|
|
249689
|
-
await
|
|
249758
|
+
await mkdir5(dir, { mode: DIR_MODE2 });
|
|
249690
249759
|
const filePath = path16.join(dir, name25);
|
|
249691
249760
|
const handle = await open3(filePath, FILE_FLAGS2, FILE_MODE2);
|
|
249692
249761
|
try {
|