@ganglion/xacpx 0.17.0-beta.8 → 0.17.0-beta.9
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 +42 -6
- package/dist/control/workspace-git.d.ts +10 -3
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -35409,7 +35409,7 @@ import { execFile as execFile2 } from "node:child_process";
|
|
|
35409
35409
|
import { createHash as createHash4 } from "node:crypto";
|
|
35410
35410
|
import { lstat, mkdir as mkdir10, realpath as realpath2 } from "node:fs/promises";
|
|
35411
35411
|
import { homedir as homedir13 } from "node:os";
|
|
35412
|
-
import { basename as basename4, isAbsolute as isAbsolute4, join as join23, resolve as resolve4, sep as sep2 } from "node:path";
|
|
35412
|
+
import { basename as basename4, isAbsolute as isAbsolute4, join as join23, resolve as resolve4, sep as sep2, win32 as win322 } from "node:path";
|
|
35413
35413
|
import { promisify as promisify2 } from "node:util";
|
|
35414
35414
|
function expandHome3(path14) {
|
|
35415
35415
|
if (path14 === "~")
|
|
@@ -35418,14 +35418,48 @@ function expandHome3(path14) {
|
|
|
35418
35418
|
return resolve4(homedir13(), path14.slice(2));
|
|
35419
35419
|
return path14;
|
|
35420
35420
|
}
|
|
35421
|
+
function worktreePathsEqual(left, right, platform = process.platform) {
|
|
35422
|
+
if (platform === "win32") {
|
|
35423
|
+
return normalizeWindowsWorktreePath(left) === normalizeWindowsWorktreePath(right);
|
|
35424
|
+
}
|
|
35425
|
+
return left === right;
|
|
35426
|
+
}
|
|
35427
|
+
function worktreePathIsWithin(parent, child, platform = process.platform) {
|
|
35428
|
+
const normalizedParent = platform === "win32" ? normalizeWindowsWorktreePath(parent) : parent;
|
|
35429
|
+
const normalizedChild = platform === "win32" ? normalizeWindowsWorktreePath(child) : child;
|
|
35430
|
+
if (normalizedParent === normalizedChild)
|
|
35431
|
+
return false;
|
|
35432
|
+
const separator = platform === "win32" ? win322.sep : sep2;
|
|
35433
|
+
const parentPrefix = normalizedParent.endsWith(separator) ? normalizedParent : normalizedParent + separator;
|
|
35434
|
+
return normalizedChild.startsWith(parentPrefix);
|
|
35435
|
+
}
|
|
35436
|
+
function normalizeWindowsWorktreePath(path14) {
|
|
35437
|
+
let normalized = win322.normalize(path14);
|
|
35438
|
+
const folded = normalized.toLowerCase();
|
|
35439
|
+
if (folded.startsWith("\\\\?\\unc\\")) {
|
|
35440
|
+
normalized = `\\\\${normalized.slice(8)}`;
|
|
35441
|
+
} else if (folded.startsWith("\\\\?\\")) {
|
|
35442
|
+
normalized = normalized.slice(4);
|
|
35443
|
+
}
|
|
35444
|
+
normalized = win322.normalize(normalized);
|
|
35445
|
+
const root = win322.parse(normalized).root;
|
|
35446
|
+
while (normalized.length > root.length && normalized.endsWith(win322.sep)) {
|
|
35447
|
+
normalized = normalized.slice(0, -1);
|
|
35448
|
+
}
|
|
35449
|
+
return normalized.toLowerCase();
|
|
35450
|
+
}
|
|
35421
35451
|
|
|
35422
35452
|
class WorkspaceGit {
|
|
35423
35453
|
listWorkspaces;
|
|
35424
35454
|
managedWorktreesRoot;
|
|
35455
|
+
platform;
|
|
35456
|
+
runGitOverride;
|
|
35425
35457
|
writeTails = new Map;
|
|
35426
35458
|
constructor(listWorkspaces, options = {}) {
|
|
35427
35459
|
this.listWorkspaces = listWorkspaces;
|
|
35428
35460
|
this.managedWorktreesRoot = options.managedWorktreesRoot ?? join23(homedir13(), ".xacpx", "worktrees");
|
|
35461
|
+
this.platform = options.platform ?? process.platform;
|
|
35462
|
+
this.runGitOverride = options.runGit;
|
|
35429
35463
|
}
|
|
35430
35464
|
async rootFor(workspace3) {
|
|
35431
35465
|
const ref = this.listWorkspaces().find((item) => item.name === workspace3);
|
|
@@ -35441,6 +35475,8 @@ class WorkspaceGit {
|
|
|
35441
35475
|
return (await this.runRaw(root, args)).trim();
|
|
35442
35476
|
}
|
|
35443
35477
|
async runRaw(root, args) {
|
|
35478
|
+
if (this.runGitOverride)
|
|
35479
|
+
return await this.runGitOverride(root, args);
|
|
35444
35480
|
const result = await execFileAsync2("git", ["-C", root, ...args], {
|
|
35445
35481
|
timeout: GIT_TIMEOUT_MS2,
|
|
35446
35482
|
killSignal: "SIGKILL",
|
|
@@ -35624,7 +35660,7 @@ class WorkspaceGit {
|
|
|
35624
35660
|
await mkdir10(repoDir);
|
|
35625
35661
|
}
|
|
35626
35662
|
const realRepoDir = await realpath2(repoDir);
|
|
35627
|
-
if (!
|
|
35663
|
+
if (!worktreePathIsWithin(managedRoot, realRepoDir, this.platform))
|
|
35628
35664
|
throw new Error("worktree-path-unsafe");
|
|
35629
35665
|
const target = join23(realRepoDir, branchKey);
|
|
35630
35666
|
try {
|
|
@@ -35640,7 +35676,7 @@ class WorkspaceGit {
|
|
|
35640
35676
|
await this.run(root, ["worktree", "add", target, branch]);
|
|
35641
35677
|
}
|
|
35642
35678
|
const createdPath = await realpath2(target);
|
|
35643
|
-
if (!
|
|
35679
|
+
if (!worktreePathIsWithin(managedRoot, createdPath, this.platform))
|
|
35644
35680
|
throw new Error("worktree-path-unsafe");
|
|
35645
35681
|
return { path: createdPath, branch, linked: true };
|
|
35646
35682
|
});
|
|
@@ -35650,10 +35686,10 @@ class WorkspaceGit {
|
|
|
35650
35686
|
const root = await this.rootFor(workspace3);
|
|
35651
35687
|
const managedRoot = await realpath2(this.managedWorktreesRoot);
|
|
35652
35688
|
const target = await realpath2(path14);
|
|
35653
|
-
if (!
|
|
35689
|
+
if (!worktreePathIsWithin(managedRoot, target, this.platform))
|
|
35654
35690
|
throw new Error("worktree-outside-managed-root");
|
|
35655
35691
|
const worktrees = await this.readWorktrees(root);
|
|
35656
|
-
const worktree = worktrees.find((item) => item.path
|
|
35692
|
+
const worktree = worktrees.find((item) => worktreePathsEqual(item.path, target, this.platform));
|
|
35657
35693
|
if (!worktree)
|
|
35658
35694
|
throw new Error("worktree-not-found");
|
|
35659
35695
|
if (worktree.current)
|
|
@@ -35767,7 +35803,7 @@ class WorkspaceGit {
|
|
|
35767
35803
|
path: item.path,
|
|
35768
35804
|
...item.branch ? { branch: item.branch } : {},
|
|
35769
35805
|
...item.detached ? { detached: true } : {},
|
|
35770
|
-
current: item.path
|
|
35806
|
+
current: worktreePathsEqual(item.path, currentRoot, this.platform),
|
|
35771
35807
|
linked: index !== 0
|
|
35772
35808
|
}));
|
|
35773
35809
|
}
|
|
@@ -57,13 +57,20 @@ export interface GitWorktreeCreateResult {
|
|
|
57
57
|
branch: string;
|
|
58
58
|
linked: true;
|
|
59
59
|
}
|
|
60
|
+
export declare function worktreePathsEqual(left: string, right: string, platform?: NodeJS.Platform): boolean;
|
|
61
|
+
export declare function worktreePathIsWithin(parent: string, child: string, platform?: NodeJS.Platform): boolean;
|
|
62
|
+
export interface WorkspaceGitOptions {
|
|
63
|
+
managedWorktreesRoot?: string;
|
|
64
|
+
platform?: NodeJS.Platform;
|
|
65
|
+
runGit?: (root: string, args: string[]) => Promise<string>;
|
|
66
|
+
}
|
|
60
67
|
export declare class WorkspaceGit {
|
|
61
68
|
private readonly listWorkspaces;
|
|
62
69
|
private readonly managedWorktreesRoot;
|
|
70
|
+
private readonly platform;
|
|
71
|
+
private readonly runGitOverride;
|
|
63
72
|
private readonly writeTails;
|
|
64
|
-
constructor(listWorkspaces: () => GitWorkspaceRef[], options?:
|
|
65
|
-
managedWorktreesRoot?: string;
|
|
66
|
-
});
|
|
73
|
+
constructor(listWorkspaces: () => GitWorkspaceRef[], options?: WorkspaceGitOptions);
|
|
67
74
|
private rootFor;
|
|
68
75
|
private run;
|
|
69
76
|
private runRaw;
|