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:
Mohamed Boudra
2026-04-14 04:07:36 +07:00
249 changed files with 9118 additions and 4973 deletions
+47 -25
View File
@@ -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 });