CodeIssuesDiscussionsWikiPull RequestsProjectsCommitsActionsReleasesContributorsPulse● GatesSecuritySettingsDeploymentsPipelineInsightsAgents✨ Explain✨ Ask AI✨ Workspace✨ Spec✨ Tests▓ Debt Map✨ NL Search🏛 Archaeology
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 | /**
* Git Smart HTTP Protocol implementation.
*
* Handles the server side of:
* - GET /:owner/:repo.git/info/refs?service=git-upload-pack
* - GET /:owner/:repo.git/info/refs?service=git-receive-pack
* - POST /:owner/:repo.git/git-upload-pack
* - POST /:owner/:repo.git/git-receive-pack
*
* Reference: https://git-scm.com/docs/http-protocol
*/
import { getRepoPath } from "./repository";
function pktLine(data: string): string {
const len = (data.length + 4).toString(16).padStart(4, "0");
return `${len}${data}`;
}
function pktFlush(): string {
return "0000";
}
export function infoRefsResponse(
service: string,
advertise: string
): Response {
const body = pktLine(`# service=${service}\n`) + pktFlush() + advertise;
return new Response(body, {
headers: {
"Content-Type": `application/x-${service}-advertisement`,
"Cache-Control": "no-cache",
},
});
}
export async function getInfoRefs(
owner: string,
repo: string,
service: string
): Promise<Response> {
const repoDir = getRepoPath(owner, repo);
const proc = Bun.spawn([service, "--stateless-rpc", "--advertise-refs", repoDir], {
stdout: "pipe",
stderr: "pipe",
});
const stdout = await new Response(proc.stdout).text();
await proc.exited;
return infoRefsResponse(service, stdout);
}
export async function serviceRpc(
owner: string,
repo: string,
service: string,
body: ReadableStream<Uint8Array> | ArrayBuffer | null,
extraEnv?: Record<string, string>
): Promise<Response> {
const repoDir = getRepoPath(owner, repo);
const inputBytes = body
? body instanceof ArrayBuffer
? new Uint8Array(body)
: new Uint8Array(await new Response(body).arrayBuffer())
: new Uint8Array();
const proc = Bun.spawn([service, "--stateless-rpc", repoDir], {
stdin: "pipe",
stdout: "pipe",
stderr: "pipe",
env: extraEnv ? { ...process.env, ...extraEnv } : process.env,
});
proc.stdin.write(inputBytes);
proc.stdin.end();
const stdout = await new Response(proc.stdout).arrayBuffer();
await proc.exited;
return new Response(stdout, {
headers: {
"Content-Type": `application/x-${service}-result`,
"Cache-Control": "no-cache",
},
});
}
|