Merge origin/main into dev (second round)
Resolve 21 conflicts from latest main (provider profiles, Windows fixes, 0.1.55-rc.1). Fix all type errors and syntax issues from merge artifacts.
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { exec, execFile, spawn } from "child_process";
|
||||
import { execFile, spawn } from "child_process";
|
||||
import { promisify } from "util";
|
||||
import { existsSync, mkdirSync, readFileSync, realpathSync, rmSync, statSync } from "fs";
|
||||
import { join, basename, dirname, resolve, sep } from "path";
|
||||
@@ -15,6 +15,7 @@ import {
|
||||
writePaseoWorktreeMetadata,
|
||||
writePaseoWorktreeRuntimeMetadata,
|
||||
} from "./worktree-metadata.js";
|
||||
import { runGitCommand } from "./run-git-command.js";
|
||||
import { resolvePaseoHome } from "../server/paseo-home.js";
|
||||
import { ensureNodePtySpawnHelperExecutableForCurrentPlatform } from "../terminal/terminal.js";
|
||||
|
||||
@@ -34,7 +35,6 @@ interface PaseoConfig {
|
||||
>;
|
||||
}
|
||||
|
||||
const execAsync = promisify(exec);
|
||||
const execFileAsync = promisify(execFile);
|
||||
const READ_ONLY_GIT_ENV: NodeJS.ProcessEnv = {
|
||||
...process.env,
|
||||
@@ -255,7 +255,11 @@ export function getScriptConfigs(repoRoot: string): Map<string, ScriptConfig> {
|
||||
}
|
||||
: { command };
|
||||
|
||||
if (isServiceScript(scriptConfig) && typeof entry.port === "number" && Number.isFinite(entry.port)) {
|
||||
if (
|
||||
isServiceScript(scriptConfig) &&
|
||||
typeof entry.port === "number" &&
|
||||
Number.isFinite(entry.port)
|
||||
) {
|
||||
scriptConfig.port = entry.port;
|
||||
}
|
||||
|
||||
@@ -325,6 +329,7 @@ async function execSetupCommand(
|
||||
const { stdout, stderr } = await execFileAsync(shellInvocation.shell, shellInvocation.args, {
|
||||
cwd: options.cwd,
|
||||
env: options.env,
|
||||
...(process.platform === "win32" ? {} : { shell: "/bin/bash" }),
|
||||
});
|
||||
return {
|
||||
command,
|
||||
@@ -525,10 +530,13 @@ async function inferRepoRootPathFromWorktreePath(worktreePath: string): Promise<
|
||||
} catch {
|
||||
// Fallback: best-effort resolve toplevel (will be the worktree root in typical cases)
|
||||
try {
|
||||
const { stdout } = await execAsync("git rev-parse --path-format=absolute --show-toplevel", {
|
||||
cwd: worktreePath,
|
||||
env: READ_ONLY_GIT_ENV,
|
||||
});
|
||||
const { stdout } = await runGitCommand(
|
||||
["rev-parse", "--path-format=absolute", "--show-toplevel"],
|
||||
{
|
||||
cwd: worktreePath,
|
||||
env: READ_ONLY_GIT_ENV,
|
||||
},
|
||||
);
|
||||
const topLevel = stdout.trim();
|
||||
if (topLevel) {
|
||||
return normalizePathForOwnership(topLevel);
|
||||
@@ -586,8 +594,9 @@ export async function runWorktreeSetupCommands(options: {
|
||||
if (result.exitCode !== 0) {
|
||||
if (options.cleanupOnFailure) {
|
||||
try {
|
||||
await execAsync(`git worktree remove "${options.worktreePath}" --force`, {
|
||||
await runGitCommand(["worktree", "remove", options.worktreePath, "--force"], {
|
||||
cwd: options.worktreePath,
|
||||
timeout: 120_000,
|
||||
});
|
||||
} catch {
|
||||
rmSync(options.worktreePath, { recursive: true, force: true });
|
||||
@@ -605,7 +614,7 @@ export async function runWorktreeSetupCommands(options: {
|
||||
|
||||
async function resolveBranchNameForWorktreePath(worktreePath: string): Promise<string> {
|
||||
try {
|
||||
const { stdout } = await execAsync("git branch --show-current", {
|
||||
const { stdout } = await runGitCommand(["branch", "--show-current"], {
|
||||
cwd: worktreePath,
|
||||
env: READ_ONLY_GIT_ENV,
|
||||
});
|
||||
@@ -708,10 +717,13 @@ export async function runWorktreeTeardownCommands(options: {
|
||||
* This is where refs, objects, etc. are stored.
|
||||
*/
|
||||
export async function getGitCommonDir(cwd: string): Promise<string> {
|
||||
const { stdout } = await execAsync("git rev-parse --path-format=absolute --git-common-dir", {
|
||||
cwd,
|
||||
env: READ_ONLY_GIT_ENV,
|
||||
});
|
||||
const { stdout } = await runGitCommand(
|
||||
["rev-parse", "--path-format=absolute", "--git-common-dir"],
|
||||
{
|
||||
cwd,
|
||||
env: READ_ONLY_GIT_ENV,
|
||||
},
|
||||
);
|
||||
const commonDir = stdout.trim();
|
||||
if (!commonDir) {
|
||||
throw new Error("Not in a git repository");
|
||||
@@ -941,7 +953,7 @@ export async function listPaseoWorktrees({
|
||||
paseoHome?: string;
|
||||
}): Promise<PaseoWorktreeInfo[]> {
|
||||
const worktreesRoot = await getPaseoWorktreesRoot(cwd, paseoHome);
|
||||
const { stdout } = await execAsync("git worktree list --porcelain", {
|
||||
const { stdout } = await runGitCommand(["worktree", "list", "--porcelain"], {
|
||||
cwd,
|
||||
env: READ_ONLY_GIT_ENV,
|
||||
});
|
||||
@@ -972,10 +984,13 @@ export async function resolvePaseoWorktreeRootForCwd(
|
||||
|
||||
let worktreeRoot: string | null = null;
|
||||
try {
|
||||
const { stdout } = await execAsync("git rev-parse --path-format=absolute --show-toplevel", {
|
||||
cwd,
|
||||
env: READ_ONLY_GIT_ENV,
|
||||
});
|
||||
const { stdout } = await runGitCommand(
|
||||
["rev-parse", "--path-format=absolute", "--show-toplevel"],
|
||||
{
|
||||
cwd,
|
||||
env: READ_ONLY_GIT_ENV,
|
||||
},
|
||||
);
|
||||
const trimmed = stdout.trim();
|
||||
worktreeRoot = trimmed.length > 0 ? trimmed : null;
|
||||
} catch {
|
||||
@@ -1038,8 +1053,9 @@ export async function deletePaseoWorktree({
|
||||
worktreePath: resolvedWorktree,
|
||||
});
|
||||
|
||||
await execAsync(`git worktree remove "${resolvedWorktree}" --force`, {
|
||||
await runGitCommand(["worktree", "remove", resolvedWorktree, "--force"], {
|
||||
cwd,
|
||||
timeout: 120_000,
|
||||
});
|
||||
|
||||
if (existsSync(resolvedWorktree)) {
|
||||
@@ -1075,11 +1091,11 @@ export async function createWorktree({
|
||||
// Resolve the base branch - prefer origin/{branch}, then fall back to local
|
||||
let resolvedBaseBranch = normalizedBaseBranch;
|
||||
try {
|
||||
await execAsync(`git rev-parse --verify origin/${normalizedBaseBranch}`, { cwd });
|
||||
await runGitCommand(["rev-parse", "--verify", `origin/${normalizedBaseBranch}`], { cwd });
|
||||
resolvedBaseBranch = `origin/${normalizedBaseBranch}`;
|
||||
} catch {
|
||||
try {
|
||||
await execAsync(`git rev-parse --verify ${normalizedBaseBranch}`, { cwd });
|
||||
await runGitCommand(["rev-parse", "--verify", normalizedBaseBranch], { cwd });
|
||||
} catch {
|
||||
throw new Error(`Base branch not found: ${normalizedBaseBranch}`);
|
||||
}
|
||||
@@ -1094,7 +1110,9 @@ export async function createWorktree({
|
||||
// Check if branch already exists
|
||||
let branchExists = false;
|
||||
try {
|
||||
await execAsync(`git show-ref --verify --quiet refs/heads/${branchName}`, { cwd });
|
||||
await runGitCommand(["show-ref", "--verify", "--quiet", `refs/heads/${branchName}`], {
|
||||
cwd,
|
||||
});
|
||||
branchExists = true;
|
||||
} catch {
|
||||
branchExists = false;
|
||||
@@ -1111,7 +1129,9 @@ export async function createWorktree({
|
||||
let suffix = 1;
|
||||
while (true) {
|
||||
try {
|
||||
await execAsync(`git show-ref --verify --quiet refs/heads/${newBranchName}`, { cwd });
|
||||
await runGitCommand(["show-ref", "--verify", "--quiet", `refs/heads/${newBranchName}`], {
|
||||
cwd,
|
||||
});
|
||||
// Branch exists, try with suffix
|
||||
newBranchName = `${candidateBranch}-${suffix}`;
|
||||
suffix++;
|
||||
@@ -1128,8 +1148,10 @@ export async function createWorktree({
|
||||
pathSuffix++;
|
||||
}
|
||||
|
||||
const command = `git worktree add "${finalWorktreePath}" -b "${newBranchName}" "${base}"`;
|
||||
await execAsync(command, { cwd });
|
||||
await runGitCommand(["worktree", "add", finalWorktreePath, "-b", newBranchName, base], {
|
||||
cwd,
|
||||
timeout: 120_000,
|
||||
});
|
||||
worktreePath = normalizePathForOwnership(finalWorktreePath);
|
||||
|
||||
writePaseoWorktreeMetadata(worktreePath, { baseRefName: normalizedBaseBranch });
|
||||
|
||||
Reference in New Issue
Block a user