mirror of
https://github.com/getpaseo/paseo.git
synced 2026-10-22 17:22:47 +00:00
* fix(daemon): keep lifecycle operations on the selected instance Restart reconstructed launch inputs and address fallback could redirect a home-selected shutdown to another daemon. Let supervisors publish bound endpoints, retain their worker restart contract, and share captured local lifecycle ownership between CLI and Desktop. * test(daemon): verify bounded desktop readiness and cancellable artifacts * test(cli): verify reload target hints and durable offline pairing * test(daemon): align lifecycle fixtures with ownership and targeting * fix(daemon): preserve reachability when status details time out Provider discovery can outlast a status request after authentication succeeds. Keep local connection facts separate from unavailable details, while explicit remote queries retain their error outcome. Migrate CLI and packaged Desktop fixtures to persistent managed configuration and explicit targets. Isolate generic Git observation from forge discovery and reuse disposable CLI homes on Windows. * test(daemon): observe restart through the worker status RPC The bounded CLI status observation may omit worker details while an authenticated connection remains healthy. Exercise the app-style restart through its full RPC and retain the replacement observation, with a real slow provider probe covering the distinction.
91 lines
2.8 KiB
TypeScript
91 lines
2.8 KiB
TypeScript
import type { Command } from "commander";
|
|
import { isCompleteGitRemote } from "@getpaseo/protocol/git-remote";
|
|
import { connectToDaemon } from "../utils/client.js";
|
|
import type { CommandError, OutputSchema, SingleResult } from "../output/index.js";
|
|
import type { CommandOptions } from "../output/with-output.js";
|
|
|
|
type CloneProtocol = "https" | "ssh";
|
|
|
|
interface CloneCommandOptions extends CommandOptions {
|
|
protocol?: CloneProtocol;
|
|
}
|
|
|
|
export interface CloneResult {
|
|
repo: string;
|
|
checkoutPath: string;
|
|
projectId: string;
|
|
projectName: string;
|
|
}
|
|
|
|
export const cloneSchema: OutputSchema<CloneResult> = {
|
|
idField: "projectId",
|
|
columns: [
|
|
{ header: "REPO", field: "repo", width: 28 },
|
|
{ header: "PROJECT", field: "projectName", width: 28 },
|
|
{ header: "PATH", field: "checkoutPath", width: 56 },
|
|
],
|
|
};
|
|
|
|
function cmdError(code: string, message: string, details?: string): CommandError {
|
|
return details ? { code, message, details } : { code, message };
|
|
}
|
|
|
|
export async function runCloneCommand(
|
|
repo: string,
|
|
options: CloneCommandOptions,
|
|
_command: Command,
|
|
): Promise<SingleResult<CloneResult>> {
|
|
const targetDirectory = typeof options.dir === "string" ? options.dir.trim() : "";
|
|
if (!targetDirectory) {
|
|
throw cmdError("INVALID_ARGUMENT", "--dir is required");
|
|
}
|
|
const repoIsCompleteRemote = isCompleteGitRemote(repo);
|
|
if (!repoIsCompleteRemote && !options.protocol) {
|
|
throw cmdError("INVALID_ARGUMENT", "--protocol is required for owner/repo repository names");
|
|
}
|
|
|
|
const client = await connectToDaemon({ target: options.daemonTarget });
|
|
|
|
if (client.getLastServerInfoMessage()?.features?.projectGithubClone !== true) {
|
|
await client.close().catch(() => {});
|
|
throw cmdError(
|
|
"UNSUPPORTED_BY_HOST",
|
|
"This daemon does not support cloning GitHub repos.",
|
|
"Update the host to a newer Paseo version.",
|
|
);
|
|
}
|
|
|
|
try {
|
|
const response = await client.cloneGithubProject({
|
|
repo,
|
|
targetDirectory,
|
|
...(repoIsCompleteRemote ? {} : { cloneProtocol: options.protocol }),
|
|
});
|
|
if (response.error || !response.project || !response.checkoutPath) {
|
|
throw cmdError(
|
|
"CLONE_FAILED",
|
|
`Failed to clone GitHub repo: ${response.error ?? "no project returned"}`,
|
|
);
|
|
}
|
|
|
|
return {
|
|
type: "single",
|
|
data: {
|
|
repo: response.repo,
|
|
checkoutPath: response.checkoutPath,
|
|
projectId: response.project.projectId,
|
|
projectName: response.project.projectDisplayName,
|
|
},
|
|
schema: cloneSchema,
|
|
};
|
|
} catch (err) {
|
|
if (err && typeof err === "object" && "code" in err) {
|
|
throw err;
|
|
}
|
|
const message = err instanceof Error ? err.message : String(err);
|
|
throw cmdError("CLONE_FAILED", `Failed to clone GitHub repo: ${message}`);
|
|
} finally {
|
|
await client.close().catch(() => {});
|
|
}
|
|
}
|