119 lines · 4.0 KB
import { env, waitUntil } from "cloudflare:workers";
import type { GitStore } from "./store";
import type { CommitSummary } from "~/lib/types";

const MAX_WALK = 1500;
const MAX_RETURNED_COMMITS = 250;
const COMPARISON_CACHE_SECONDS = 60 * 60 * 24 * 7;
const FROM_HEAD = 1;
const FROM_BASE = 2;
const BOTH = FROM_HEAD | FROM_BASE;

type Reader = (sha: string) => Promise<CommitSummary | null>;

function readerFor(stores: GitStore[]): Reader {
  return async (sha) => {
    for (const store of stores) {
      const commit = await store.commit(sha);
      if (commit) return commit;
    }
    return null;
  };
}

export type Comparison = {
  mergeBase: string | null;
  /** Commits reachable from head but not from base, newest first. */
  commits: CommitSummary[];
  /** Number of commits reachable from base but not head (how far head is behind). */
  behindBy: number;
  truncated: boolean;
};

/**
 * Paints commits reachable from head and base in committer-date order (like `git rev-list`),
 * yielding the head-only commits and the first commit reachable from both sides as merge base.
 */
export async function compareCommits(
  baseStore: GitStore,
  baseSha: string,
  headStore: GitStore,