neiam /gitgud
Git Gud
public · Issues · Pulls · Labels · Forks · Compare · Actions success · Packages
Log in to mark this repository.
Add Pulls to the repo header with an open count; refuse no-op PRs
719deae · Gabriel Morell · 2026-09-09 21:06
Message
{commit_body(@commit)}
Files changed
modified
lib/git_gud/pull_requests.ex
+34
−1
| 51 | 51 | Enum.map(prs, &Map.put(&1, :labels, Map.get(labels_by_id, &1.id, []))) |
| 52 | 52 | end |
| 53 | 53 | |
| 54 | + @doc "How many pull requests are open against this repo." | |
| 55 | + def count_open(%Repository{id: rid}) do | |
| 56 | + PullRequest | |
| 57 | + |> where([p], p.repository_id == ^rid and p.state == "open") | |
| 58 | + |> Repo.aggregate(:count) | |
| 59 | + end | |
| 60 | + | |
| 54 | 61 | defp filter_state(q, "all"), do: q |
| 55 | 62 | |
| 56 | 63 | defp filter_state(q, s) when s in ["open", "closed", "merged"], |
| 118 | 125 | # the target's object database before merge_base / merge_tree |
| 119 | 126 | # can see both SHAs from one repo's perspective. |
| 120 | 127 | :ok <- maybe_fetch_cross_repo(cross_repo?, repo, source_repo, source_ref), |
| 121 | − {:ok, base_sha} <- Git.merge_base(repo.disk_path, head_sha, target_sha) do | |
| 128 | + {:ok, base_sha} <- Git.merge_base(repo.disk_path, head_sha, target_sha), | |
| 129 | + :ok <- | |
| 130 | + ensure_something_to_merge( | |
| 131 | + head_sha, | |
| 132 | + target_sha, | |
| 133 | + base_sha, | |
| 134 | + not cross_repo? and source_ref == target_ref | |
| 135 | + ) do | |
| 122 | 136 | Repo.transaction(fn -> |
| 123 | 137 | next = Numbering.next_for(repo.id) |
| 124 | 138 |
| 152 | 166 | end |
| 153 | 167 | end) |
| 154 | 168 | else |
| 169 | + # Don't re-wrap what is already an error tuple — callers were | |
| 170 | + # getting `{:error, {:error, :no_such_ref}}`. | |
| 171 | + {:error, reason} -> {:error, reason} | |
| 155 | 172 | err -> {:error, err} |
| 156 | 173 | end |
| 157 | 174 |
| 330 | 347 | ) |
| 331 | 348 | end |
| 332 | 349 | |
| 350 | + # Nothing to open a PR for when the two tips are the same commit, or | |
| 351 | + # when the head is already an ancestor of the base — the merge-base | |
| 352 | + # being the head itself means the base already contains every commit | |
| 353 | + # the head has. | |
| 354 | + # A branch onto itself is the changeset's business — it has a precise | |
| 355 | + # message for that, and it renders on the field rather than as a flash. | |
| 356 | + defp ensure_something_to_merge(_head, _target, _base, true), do: :ok | |
| 357 | + | |
| 358 | + defp ensure_something_to_merge(head_sha, target_sha, base_sha, _same_ref?) do | |
| 359 | + cond do | |
| 360 | + head_sha == target_sha -> {:error, :no_changes} | |
| 361 | + head_sha == base_sha -> {:error, :no_changes} | |
| 362 | + true -> :ok | |
| 363 | + end | |
| 364 | + end | |
| 365 | + | |
| 333 | 366 | defp resolve_source_repo(target_repo, nil), do: {target_repo, false} |
| 334 | 367 | |
| 335 | 368 | defp resolve_source_repo(target_repo, id) when is_integer(id) or is_binary(id) do |
modified
lib/git_gud_web/live/branch_protection_live/index.ex
+8
−1
| 67 | 67 | has_packages?={@has_packages?} |
| 68 | 68 | can_admin?={@can_admin?} |
| 69 | 69 | latest_run={@latest_run} |
| 70 | + open_pulls={@open_pulls} | |
| 70 | 71 | /> |
| 71 | 72 | <.repo_settings_header handle={@handle} repo={@repo} current={:branches} /> |
| 72 | 73 | |
| 73 | − <.form for={@form} id="bp-form" phx-change="validate" phx-submit="add" class="space-y-3 max-w-2xl"> | |
| 74 | + <.form | |
| 75 | + for={@form} | |
| 76 | + id="bp-form" | |
| 77 | + phx-change="validate" | |
| 78 | + phx-submit="add" | |
| 79 | + class="space-y-3 max-w-2xl" | |
| 80 | + > | |
| 74 | 81 | <.input |
| 75 | 82 | field={@form[:pattern]} |
| 76 | 83 | label="Pattern (glob)" |
modified
lib/git_gud_web/live/deploy_key_live/index.ex
+1
−0
| 67 | 67 | has_packages?={@has_packages?} |
| 68 | 68 | can_admin?={@can_admin?} |
| 69 | 69 | latest_run={@latest_run} |
| 70 | + open_pulls={@open_pulls} | |
| 70 | 71 | /> |
| 71 | 72 | <.repo_settings_header handle={@handle} repo={@repo} current={:deploy_keys} /> |
| 72 | 73 |
modified
lib/git_gud_web/live/interaction_policy_live/edit.ex
+1
−0
| 54 | 54 | has_packages?={@has_packages?} |
| 55 | 55 | can_admin?={@can_admin?} |
| 56 | 56 | latest_run={@latest_run} |
| 57 | + open_pulls={@open_pulls} | |
| 57 | 58 | /> |
| 58 | 59 | <.repo_settings_header handle={@handle} repo={@repo} current={:interaction} /> |
| 59 | 60 |
modified
lib/git_gud_web/live/issue_live/index.ex
+1
−0
| 67 | 67 | has_packages?={@has_packages?} |
| 68 | 68 | can_admin?={@can_admin?} |
| 69 | 69 | latest_run={@latest_run} |
| 70 | + open_pulls={@open_pulls} | |
| 70 | 71 | /> |
| 71 | 72 | |
| 72 | 73 | <header class="flex items-center justify-between"> |
modified
lib/git_gud_web/live/issue_live/new.ex
+2
−2
Click to load diff…
modified
lib/git_gud_web/live/issue_live/show.ex
+6
−4
Click to load diff…
modified
lib/git_gud_web/live/label_live/index.ex
+11
−4
Click to load diff…
modified
lib/git_gud_web/live/pr_live/index.ex
+1
−0
Click to load diff…
modified
lib/git_gud_web/live/pr_live/new.ex
+9
−0
Click to load diff…
modified
lib/git_gud_web/live/pr_live/show.ex
+10
−5
Click to load diff…
modified
lib/git_gud_web/live/registry_token_live/index.ex
+33
−12
Click to load diff…
modified
lib/git_gud_web/live/repo_live/blob.ex
+1
−0
Click to load diff…
modified
lib/git_gud_web/live/repo_live/commit.ex
+1
−0
Click to load diff…
modified
lib/git_gud_web/live/repo_live/committers.ex
+1
−0
Click to load diff…
modified
lib/git_gud_web/live/repo_live/compare.ex
+1
−0
Click to load diff…
modified
lib/git_gud_web/live/repo_live/fork.ex
+1
−0
Click to load diff…
modified
lib/git_gud_web/live/repo_live/forks.ex
+1
−0
Click to load diff…
modified
lib/git_gud_web/live/repo_live/header.ex
+16
−2
Click to load diff…
modified
lib/git_gud_web/live/repo_live/languages.ex
+3
−3
Click to load diff…
modified
lib/git_gud_web/live/repo_live/log.ex
+1
−0
Click to load diff…
modified
lib/git_gud_web/live/repo_live/packages.ex
+8
−2
Click to load diff…
modified
lib/git_gud_web/live/repo_live/settings.ex
+2
−3
Click to load diff…
modified
lib/git_gud_web/live/repo_live/settings_runners.ex
+14
−6
Click to load diff…
modified
lib/git_gud_web/live/repo_live/show.ex
+1
−0
Click to load diff…
modified
lib/git_gud_web/live/repo_live/tree.ex
+1
−0
Click to load diff…
modified
lib/git_gud_web/live/secrets_live/repo.ex
+1
−0
Click to load diff…
modified
lib/git_gud_web/live/webhook_live/index.ex
+8
−1
Click to load diff…
modified
lib/git_gud_web/live/wiki_live/edit.ex
+1
−0
Click to load diff…
modified
lib/git_gud_web/live/wiki_live/index.ex
+1
−0
Click to load diff…
modified
lib/git_gud_web/live/wiki_live/show.ex
+1
−0
Click to load diff…
modified
lib/git_gud_web/live/workflow_live/index.ex
+1
−0
Click to load diff…
modified
lib/git_gud_web/live/workflow_live/show.ex
+58
−50
Click to load diff…
modified
test/git_gud_web/live/pr_live/new_cross_repo_test.exs
+80
−2
Click to load diff…
Parents: 6e19be9