api: default_branch on repo create (DB + HEAD) + delete endpoint

10b7f9d · gmorell · 2026-06-25 23:05

3 files +40 -0
Message
{commit_body(@commit)}

Files changed

modified lib/git_gud/repositories.ex
+18 −0
@@ -568,6 +568,11 @@ defmodule GitGud.Repositories do
568 568 {:ok, repo} ->
569 569 case init_function(fk).(disk_path) do
570 570 :ok ->
571 + # A freshly `git init`'d bare repo HEADs at `main`; point it
572 + # at the repo's actual default branch so the first push of
573 + # that branch isn't orphaned (UI/clone follow HEAD). Skip
574 + # for clones/forks — they inherit the source HEAD.
575 + if init_empty?(fk), do: set_default_head(disk_path, repo.default_branch)
571 576 install_hooks(disk_path)
572 577 configure_git(disk_path)
573 578 repo
@@ -582,6 +587,19 @@ defmodule GitGud.Repositories do
582 587 end)
583 588 end
584 589
590 + defp init_empty?(fk),
591 + do: not Map.has_key?(fk, :clone_from) and not Map.has_key?(fk, :clone_from_url)
592 +
593 + defp set_default_head(_path, nil), do: :ok
594 +
595 + defp set_default_head(path, branch) when is_binary(branch) do
596 + System.cmd("git", ["-C", path, "symbolic-ref", "HEAD", "refs/heads/" <> branch],
597 + stderr_to_stdout: true
598 + )
599 +
600 + :ok
601 + end
602 +
585 603 defp init_function(%{clone_from_url: url}) when is_binary(url) do
586 604 fn dest -> clone_mirror(url, dest) end
587 605 end
modified lib/git_gud_web/controllers/api/v1/org_controller.ex
+21 −0
@@ -27,6 +27,7 @@ defmodule GitGudWeb.Api.V1.OrgController do
27 27 "name" => params["name"],
28 28 "description" => params["description"],
29 29 "visibility" => params["visibility"] || "private",
30 + "default_branch" => params["default_branch"],
30 31 "clone_addr" => params["clone_addr"]
31 32 }
32 33
@@ -52,6 +53,26 @@ defmodule GitGudWeb.Api.V1.OrgController do
52 53 end
53 54 end
54 55
56 + def delete_repo(conn, %{"org" => handle, "name" => name}) do
57 + with {:ok, user} <- authenticate(conn, "repo"),
58 + %_{} = org <- Organizations.get_organization_by_handle(handle),
59 + %_{} = repo <- get_repo(handle, name),
60 + true <- Organizations.org_admin?(org, user) do
61 + _ = Repositories.delete_repository(repo)
62 + send_resp(conn, 204, "")
63 + else
64 + :error -> send_error(conn, 401, "invalid token or missing 'repo' scope")
65 + false -> send_error(conn, 403, "must be an admin of #{handle}")
66 + nil -> send_error(conn, 404, "organization or repository not found")
67 + end
68 + end
69 +
70 + defp get_repo(handle, name) do
71 + Repositories.get_repository_by_path!(handle, name)
72 + rescue
73 + Ecto.NoResultsError -> nil
74 + end
75 +
55 76 defp authenticate(conn, scope) do
56 77 with token when is_binary(token) <- bearer(conn),
57 78 {:ok, user, scopes} <- Accounts.verify_personal_access_token(token),
modified lib/git_gud_web/router.ex
+1 −0
@@ -235,6 +235,7 @@ defmodule GitGudWeb.Router do
235 235
236 236 # Write endpoints — Personal Access Token auth (handled in-controller).
237 237 post "/orgs/:org/repos", OrgController, :create_repo
238 + delete "/orgs/:org/repos/:name", OrgController, :delete_repo
238 239 end
239 240
240 241 # Enable LiveDashboard and Swoosh mailbox preview in development

Parents: aa56cab