import { enforceRateLimit, requestIp } from "../limits";
import { HttpError } from "../errors";
import { hasPermission, loadRepo } from "../repos";
import { scopedRepoPermission, tokenCredential } from "../token-scope";
import { directUpdateViolation, loadProtections, protectionFor } from "../protection";
import { triggerPush } from "../events/push-trigger";
import { scanPushBody } from "../security/push-protection";
import { basicAuthHeader, repoTokenSecret } from "./artifacts";
import { concatBytes, packetText, parseAllPackets, readUntilFlush, reportStatusResponse } from "./pktline";
import { invalidateRefs } from "./refs";
import { ZERO_SHA } from "./store";
import type { Permission, RepoRow, Viewer } from "~/lib/types";
const GIT_PATH = /^\/([^/]+)\/([^/]+?)(?:\.git)?\/(info\/refs|git-upload-pack|git-receive-pack)$/;
const MAX_COMMAND_BYTES = 1024 * 1024;
const MAX_PUSH_COMMANDS = 1000;
const MAX_TRIGGERED_REFS = 100;
const FORWARDED_REQUEST_HEADERS = ["content-type", "accept", "content-encoding", "git-protocol", "user-agent"];
const FORWARDED_RESPONSE_HEADERS = ["content-type", "cache-control", "expires", "pragma"];
const SIDEBAND_DATA = 1;
const decoder = new TextDecoder();
type GitService = "git-upload-pack" | "git-receive-pack";
type GitRoute = { owner: string; repo: string; action: "info/refs" | GitService };
type Command = { oldSha: string; newSha: string; ref: string };
export function matchGitRoute(url: URL): GitRoute | null {
const match = GIT_PATH.exec(url.pathname);
if (!match) return null;
const [, owner, repo, action] = match;
if (action !== "info/refs" && action !== "git-upload-pack" && action !== "git-receive-pack") return null;
return { owner, repo, action };
}
function challenge(message: string): Response {
return new Response(`${message}\n`, {
status: 401,
headers: { "www-authenticate": 'Basic realm="stig"', "content-type": "text/plain" },
});
}