2.7 KiB · text History b868907
defmodule GitGud.Repositories.DefaultBranchSyncTest do
  @moduledoc """
  What a push may do to a repository's default branch: realign it with
  the bare repository's HEAD when the configured one doesn't exist (an
  empty repo made as "main", first pushed as "master") — and nothing
  when it does, however HEAD reads. A push of some other branch once
  reset a configured, existing "master" to a "main" no one had.
  """
  use GitGud.DataCase, async: false

  import GitGud.ForgeFixtures
  import GitGud.WorkflowGitHelpers

  alias GitGud.Repositories
  alias GitGud.Repositories.HookReceiver
  alias GitGud.Repositories.Repository

  @zero String.duplicate("0", 40)

  defp push(repo, branch, sha),
    do: HookReceiver.receive(repo.id, "#{@zero} #{sha} refs/heads/#{branch}\n")

  defp head(repo), do: repo.disk_path |> Path.join("HEAD") |> File.read!() |> String.trim()

  setup do
    {_owner, repo} = repository_fixture()
    main = commit!(repo, %{"a" => "a\n"}, [])
    {:ok, repo: repo, sha: main}
  end

  test "another branch's push leaves an existing default alone, and HEAD follows it", %{
    repo: repo,
    sha: sha
  } do
    repo = Repo.update!(Ecto.Changeset.change(repo, default_branch: "master"))
    git!(repo.disk_path, ["update-ref", "refs/heads/master", sha])
    git!(repo.disk_path, ["update-ref", "refs/heads/deps/security-hex", sha])
    # git's own default, as an old bare repo may still have it.
    git!(repo.disk_path, ["symbolic-ref", "HEAD", "refs/heads/main"])

    push(repo, "deps/security-hex", sha)

    assert Repo.get!(Repository, repo.id).default_branch == "master"
    assert head(repo) == "ref: refs/heads/master"
  end

  test "a default that doesn't exist is realigned with HEAD", %{repo: repo, sha: sha} do
    repo = Repo.update!(Ecto.Changeset.change(repo, default_branch: "main"))
    git!(repo.disk_path, ["update-ref", "refs/heads/master", sha])
    git!(repo.disk_path, ["symbolic-ref", "HEAD", "refs/heads/master"])

    push(repo, "master", sha)

    assert Repo.get!(Repository, repo.id).default_branch == "master"
  end

  test "…but not to a HEAD that doesn't exist either", %{repo: repo, sha: sha} do
    repo = Repo.update!(Ecto.Changeset.change(repo, default_branch: "trunk"))
    git!(repo.disk_path, ["update-ref", "refs/heads/feature", sha])
    git!(repo.disk_path, ["symbolic-ref", "HEAD", "refs/heads/main"])

    push(repo, "feature", sha)

    assert Repo.get!(Repository, repo.id).default_branch == "trunk"
  end

  test "changing the default in settings points HEAD at it", %{repo: repo, sha: sha} do
    git!(repo.disk_path, ["update-ref", "refs/heads/trunk", sha])

    {:ok, _} = Repositories.update_repository(repo, %{"default_branch" => "trunk"})

    assert head(repo) == "ref: refs/heads/trunk"
  end
end