// The default branch of a repository whose HEAD dangles (its first push had no main). Run with `bun test`.
import assert from "node:assert/strict";
import { execFileSync } from "node:child_process";
import { mkdtempSync, rmSync } from "node:fs";
import os from "node:os";
import path from "node:path";
import { after, before, test } from "node:test";
const tmp = mkdtempSync(path.join(os.tmpdir(), "vectrum-default-branch-test-"));
process.env.DATA_ROOT = path.join(tmp, "data");
const sh = (cwd: string, ...args: string[]) => execFileSync("git", args, { cwd, encoding: "utf8", stdio: "pipe" });
let git: typeof import("./git");
let repo: string;
let work: string;
/** Commits on `branch` in the work tree and pushes it, a second later than the last so dates order them. */
let clock = 1_700_000_000;
function pushBranch(branch: string) {
sh(work, "checkout", "-q", "-B", branch);
const date = `${clock++} +0000`;
execFileSync("git", ["-c", "user.name=a", "-c", "user.email=a@x", "commit", "-q", "--allow-empty", "-m", branch], {
cwd: work,
env: { ...process.env, GIT_AUTHOR_DATE: date, GIT_COMMITTER_DATE: date },
});
sh(work, "push", "-q", repo, `${branch}:refs/heads/${branch}`);
}
before(async () => {
git = await import("./git");
repo = path.join(tmp, "srv.git");
await git.initBareRepo(repo);
work = path.join(tmp, "work");
sh(tmp, "init", "-q", "-b", "start", work);
});
after(() => rmSync(tmp, { recursive: true, force: true }));
test("without main, master wins over a more recently changed branch, and gets pinned", async () => {
pushBranch("feature");
await git.pinDefaultBranch(repo);
assert.equal(await git.defaultBranch(repo), "feature");
assert.equal(sh(repo, "symbolic-ref", "HEAD").trim(), "refs/heads/main", "HEAD stays dangling without main or master");
pushBranch("master");
pushBranch("settings-parity");
assert.equal(await git.defaultBranch(repo), "master");
await git.pinDefaultBranch(repo);
assert.equal(sh(repo, "symbolic-ref", "HEAD").trim(), "refs/heads/master");
// Once pinned, a later main doesn't take over.
pushBranch("main");
await git.pinDefaultBranch(repo);
assert.equal(await git.defaultBranch(repo), "master");
});
test("the default branch can be changed, but only to a branch that exists", async () => {
await git.setDefaultBranch(repo, "feature");
assert.equal(await git.defaultBranch(repo), "feature");
await git.pinDefaultBranch(repo);
assert.equal(await git.defaultBranch(repo), "feature");
await assert.rejects(git.setDefaultBranch(repo, "nope"), git.GitError);
await assert.rejects(git.setDefaultBranch(repo, "--output=/tmp/x"), git.GitError);
assert.equal(await git.defaultBranch(repo), "feature");
});