neiam
/gitgud
Git Gud
public · Issues · Pulls · Labels · Forks · Compare · Actions success · Badges · Packages
⭐
1
Log in to mark this repository.
Badges: mirrors are what sync, and package alt text names the format
a0aa462 · gmorell · 2026-11-10 01:18
Message
{commit_body(@commit)}
Files changed
modified
lib/git_gud/badges.ex
+22
−5
@@ -420,17 +420,34 @@ defmodule GitGud.Badges do
| 420 | 420 | end) |
| 421 | 421 | end |
| 422 | 422 | |
| 423 | + @doc """ | |
| 424 | + Whether `repo` follows an upstream: one it syncs from on a schedule, | |
| 425 | + or has synced from, or tried to. A repository imported once from | |
| 426 | + another forge also keeps its `upstream_url`, but having never synced | |
| 427 | + and not being set to, it's developed here and isn't a mirror. | |
| 428 | + """ | |
| 429 | + @spec mirror?(Repository.t()) :: boolean() | |
| 430 | + def mirror?(%Repository{upstream_url: nil}), do: false | |
| 431 | + | |
| 432 | + def mirror?(%Repository{} = repo) do | |
| 433 | + repo.upstream_auto_sync == true or not is_nil(repo.upstream_synced_at) or | |
| 434 | + not is_nil(repo.upstream_sync_error) | |
| 435 | + end | |
| 436 | + | |
| 423 | 437 | @doc "The `mirror` badge for `repo` as of `now`." |
| 424 | − def mirror(%Repository{upstream_url: nil}, _now), | |
| 425 | − do: %{label: "mirror", value: "not a mirror", slot: "muted"} | |
| 438 | + def mirror(%Repository{} = repo, now) do | |
| 439 | + if mirror?(repo), do: mirror_state(repo, now), else: not_a_mirror() | |
| 440 | + end | |
| 441 | + | |
| 442 | + defp not_a_mirror, do: %{label: "mirror", value: "not a mirror", slot: "muted"} | |
| 426 | 443 | |
| 427 | − def mirror(%Repository{upstream_sync_error: error}, _now) when is_binary(error), | |
| 444 | + defp mirror_state(%Repository{upstream_sync_error: error}, _now) when is_binary(error), | |
| 428 | 445 | do: %{label: "mirror", value: "sync failing", slot: "error"} |
| 429 | 446 | |
| 430 | − def mirror(%Repository{upstream_synced_at: nil}, _now), | |
| 447 | + defp mirror_state(%Repository{upstream_synced_at: nil}, _now), | |
| 431 | 448 | do: %{label: "mirror", value: "never synced", slot: "warning"} |
| 432 | 449 | |
| 433 | − def mirror(%Repository{upstream_synced_at: at}, now), | |
| 450 | + defp mirror_state(%Repository{upstream_synced_at: at}, now), | |
| 434 | 451 | do: mirror_age(max(DateTime.diff(now, at, :second), 0)) |
| 435 | 452 | |
| 436 | 453 | defp mirror_age(seconds) do |
modified
lib/git_gud_web/badge_catalog.ex
+9
−4
@@ -90,7 +90,7 @@ defmodule GitGudWeb.BadgeCatalog do
| 90 | 90 | @doc """ |
| 91 | 91 | Every badge `repo` has, grouped (status, activity, project, mark) and |
| 92 | 92 | in display order within each group. A mirror badge only for a |
| 93 | − repository that follows an upstream; a workflow badge for each | |
| 93 | + repository that follows an upstream (`Badges.mirror?/1`); a workflow badge for each | |
| 94 | 94 | workflow that has run on the default branch; a package badge for each |
| 95 | 95 | package. |
| 96 | 96 | """ |
@@ -126,8 +126,9 @@ defmodule GitGudWeb.BadgeCatalog do
| 126 | 126 | |> Enum.sort_by(&group_rank(&1.group)) |
| 127 | 127 | end |
| 128 | 128 | |
| 129 | − defp plain_kinds(%Repository{upstream_url: nil}), do: @kinds -- ["mirror"] | |
| 130 | − defp plain_kinds(_repo), do: @kinds | |
| 129 | + # A mirror badge only for a repository that really follows an upstream, | |
| 130 | + # not one imported once and developed here since (`Badges.mirror?/1`). | |
| 131 | + defp plain_kinds(repo), do: if(Badges.mirror?(repo), do: @kinds, else: @kinds -- ["mirror"]) | |
| 131 | 132 | |
| 132 | 133 | defp item(key, content, title, hint) do |
| 133 | 134 | {kind, _name, _registry} = split_key(key) |
@@ -260,7 +261,11 @@ defmodule GitGudWeb.BadgeCatalog do
| 260 | 261 | def alt(%Spec{kind: "last-commit"}), do: "last commit" |
| 261 | 262 | def alt(%Spec{kind: "coverage"}), do: "coverage" |
| 262 | 263 | def alt(%Spec{kind: "workflow", name: name}), do: "#{name} status" |
| 263 | − def alt(%Spec{kind: "package", name: name}), do: "install #{name}" | |
| 264 | + # The format too: a package published as both deb and rpm has a badge | |
| 265 | + # for each, and they shouldn't read the same. | |
| 266 | + def alt(%Spec{kind: "package", name: name, registry: registry}), | |
| 267 | + do: "install #{name} (#{registry})" | |
| 268 | + | |
| 264 | 269 | def alt(%Spec{kind: "issues"}), do: "open issues" |
| 265 | 270 | def alt(%Spec{kind: "pulls"}), do: "open pull requests" |
| 266 | 271 | def alt(%Spec{kind: "commits"}), do: "commits" |
modified
test/git_gud/badges_test.exs
+8
−1
@@ -447,7 +447,14 @@ defmodule GitGud.BadgesTest do
| 447 | 447 | mirror = %{repo | upstream_url: "https://example.com/x.git"} |
| 448 | 448 | |
| 449 | 449 | assert %{value: "not a mirror", slot: "muted"} = Badges.mirror(repo, now) |
| 450 | − assert %{value: "never synced", slot: "warning"} = Badges.mirror(mirror, now) | |
| 450 | + | |
| 451 | + # Imported once and never synced since: developed here, not a mirror. | |
| 452 | + refute Badges.mirror?(mirror) | |
| 453 | + assert %{value: "not a mirror"} = Badges.mirror(mirror, now) | |
| 454 | + | |
| 455 | + # Set to sync, but hasn't yet. | |
| 456 | + assert %{value: "never synced", slot: "warning"} = | |
| 457 | + Badges.mirror(%{mirror | upstream_auto_sync: true}, now) | |
| 451 | 458 | |
| 452 | 459 | assert %{value: "synced 3h ago", slot: "success"} = |
| 453 | 460 | Badges.mirror(%{mirror | upstream_synced_at: ~U[2026-11-09 09:00:00Z]}, now) |
modified
test/git_gud_web/controllers/api/mobile/mobile_badges_test.exs
+11
−0
@@ -87,4 +87,15 @@ defmodule GitGudWeb.Api.Mobile.MobileBadgesTest do
| 87 | 87 | {stranger, _} = repository_fixture() |
| 88 | 88 | assert conn |> as(token_for(stranger, ["repo:read"])) |> get(path) |> json_response(404) |
| 89 | 89 | end |
| 90 | + | |
| 91 | + test "a package's deb and rpm badges say which is which" do | |
| 92 | + alias GitGud.Badges.Spec | |
| 93 | + alias GitGudWeb.BadgeCatalog | |
| 94 | + | |
| 95 | + deb = BadgeCatalog.spec(%Spec{}, "package:deb:neiam-branding", "auto", "svg") | |
| 96 | + rpm = BadgeCatalog.spec(%Spec{}, "package:rpm:neiam-branding", "auto", "svg") | |
| 97 | + | |
| 98 | + assert BadgeCatalog.alt(deb) == "install neiam-branding (deb)" | |
| 99 | + assert BadgeCatalog.alt(rpm) == "install neiam-branding (rpm)" | |
| 100 | + end | |
| 90 | 101 | end |
Parents: 308b64e