254 lines · 10.6 KB
import { advertisement, artifactsSource, relayPack, RelayScreenRejected } from "../git/relay";
import type { RelaySource } from "../git/relay";
import type { AdvertisedRef, RefCommand } from "../git/ref-sync-protocol";
import { withStore } from "../git/store";
import type { GitStore } from "../git/store";
import type { RawObject } from "../git/objects";
import { pushToArtifacts } from "../git/writer";
import { sourceAuthorization } from "../git/ref-sync";
import { scanPushBody } from "../security/push-protection";
import { badRequest } from "../errors";
import { conflictRef, CONFLICT_PREFIX, decideRef, isMirroredRef, STAGING_PREFIX, stagingRef, ZERO_SHA } from "./plan";
import type { Relation } from "./plan";
import type { ConflictStrategy, MirrorDirection, SyncReport } from "~/lib/mirror";
import { mergeTips, relate } from "./merge";
import { applyLocal, applyRemote } from "./apply";
import type { RepoRow } from "~/lib/types";

const MAX_STAGE_REFS = 200;
const MAX_STAGE_BYTES = 1024 * 1024 * 1024;
const MAX_COMPARISONS = 100;
const MAX_MERGES = 10;

export type MirrorSettings = {
  remoteUrl: string;
  username: string | null;
  direction: MirrorDirection;
  strategy: ConflictStrategy;
  /** Branch globs (`!` excludes); empty mirrors every branch. */
  branches: string[];
  syncTags: boolean;
  propagateDeletes: boolean;
  /** The admin who configured the mirror; every run acts as them and re-checks their access. */
  createdBy: string;
};

export type SyncResult = { report: SyncReport; synced: Record<string, string>; written: Record<string, string> };

export type Plan = {
  local: RefCommand[];
  remote: RefCommand[];