diff --git a/.changeset/fix-server-crash-and-cred-path.md b/.changeset/fix-server-crash-and-cred-path.md new file mode 100644 index 0000000..3242e42 --- /dev/null +++ b/.changeset/fix-server-crash-and-cred-path.md @@ -0,0 +1,5 @@ +--- +"@enbox/gitd": patch +--- + +Fix daemon crash when cloning nonexistent repos (process.exit in server context) and resolve credential helper by absolute path so push auth works without PATH setup. diff --git a/src/cli/repo-context.ts b/src/cli/repo-context.ts index d8af075..e43731f 100644 --- a/src/cli/repo-context.ts +++ b/src/cli/repo-context.ts @@ -43,8 +43,7 @@ export async function getRepoContext( }); if (records.length === 0) { - console.error(`Repository "${repoName}" not found. Run \`gitd init ${repoName}\` first.`); - process.exit(1); + throw new Error(`Repository "${repoName}" not found. Run \`gitd init ${repoName}\` first.`); } return extractContext(records[0], repoName); @@ -54,13 +53,11 @@ export async function getRepoContext( const { records } = await ctx.repo.records.query('repo'); if (records.length === 0) { - console.error('No repository found. Run `gitd init ` first.'); - process.exit(1); + throw new Error('No repository found. Run `gitd init ` first.'); } if (records.length > 1) { - console.error('Multiple repositories exist. Specify one with --repo , GITD_REPO env, or `git config enbox.repo `.'); - process.exit(1); + throw new Error('Multiple repositories exist. Specify one with --repo , GITD_REPO env, or `git config enbox.repo `.'); } const data = await records[0].data.json(); @@ -85,8 +82,7 @@ export async function getRepoContextId( function extractContext(record: any, name: string): RepoContext { const contextId = record.contextId; if (!contextId) { - console.error('Repository record has no contextId — this should not happen.'); - process.exit(1); + throw new Error('Repository record has no contextId — this should not happen.'); } const visibility = (record.tags?.visibility as 'public' | 'private') ?? 'public'; diff --git a/src/git-remote/main.ts b/src/git-remote/main.ts index 2aded30..46d62cc 100644 --- a/src/git-remote/main.ts +++ b/src/git-remote/main.ts @@ -20,11 +20,19 @@ * @module */ +import { fileURLToPath } from 'node:url'; +import { resolve } from 'node:path'; import { spawn } from 'node:child_process'; import { parseDidUrl } from './parse-url.js'; import { resolveGitEndpoint } from './resolve.js'; +/** Resolve the absolute path to the credential helper binary (sibling file). */ +function resolveCredentialHelper(): string { + const thisFile = fileURLToPath(import.meta.url); + return resolve(thisFile, '..', 'credential-main.js'); +} + // --------------------------------------------------------------------------- // Main // --------------------------------------------------------------------------- @@ -67,8 +75,12 @@ async function main(): Promise { ? 'remote-https' : 'remote-http'; + // The credential helper is a sibling .js file with a bun shebang. + // Use git's `!` syntax to invoke it via bun, which avoids + // needing the file to be +x or on PATH. + const credHelper = resolveCredentialHelper(); const child = spawn('git', [ - '-c', 'credential.helper=git-remote-did-credential', + '-c', `credential.helper=!bun '${credHelper}'`, '-c', 'credential.useHttpPath=true', helper, remoteName, endpoint.url, ], {