Show the detected licence on the stats page

fd8f955 · Gabriel Morell · 2026-09-22 13:46

9 files +108 -0
Message
{commit_body(@commit)}

Files changed

modified lib/git_gud_web/live/repo_live/languages.ex
+33 −0
@@ -80,6 +80,8 @@ defmodule GitGudWeb.RepoLive.Languages do
80 80 <% end %>
81 81 </p>
82 82
83 + <.license repo={@repo} handle={@handle} />
84 +
83 85 <%= case @status do %>
84 86 <% :empty -> %>
85 87 <p class="text-sm opacity-70">This branch or repository is empty.</p>
@@ -136,6 +138,37 @@ defmodule GitGudWeb.RepoLive.Languages do
136 138 """
137 139 end
138 140
141 + attr :repo, :map, required: true
142 + attr :handle, :string, required: true
143 +
144 + # Detected from the licence file at the default branch's tip, so it is
145 + # labelled with that branch rather than with whichever ref the stats
146 + # on this page are for — the two can differ, and quietly showing one
147 + # branch's licence under another's name would be a lie.
148 + defp license(assigns) do
149 + ~H"""
150 + <p class="text-sm flex items-center gap-2">
151 + <%= if @repo.license do %>
152 + <span class="badge badge-sm badge-outline">{@repo.license}</span>
153 + <.link
154 + :if={@repo.license_file}
155 + navigate={
156 + ~p"/r/#{@handle}/#{@repo.name}/blob/#{@repo.default_branch}/#{@repo.license_file}"
157 + }
158 + class="link link-hover text-xs opacity-70 font-mono"
159 + >
160 + {@repo.license_file}
161 + </.link>
162 + <span class="text-xs opacity-50">on {@repo.default_branch}</span>
163 + <% else %>
164 + <span class="text-xs opacity-60">
165 + No licence detected on {@repo.default_branch}.
166 + </span>
167 + <% end %>
168 + </p>
169 + """
170 + end
171 +
139 172 attr :stats, :map, required: true
140 173
141 174 defp bar(assigns) do
added test/git_gud_web/live/stats_license_test.exs
+75 −0
@@ -0,0 +1,75 @@
1 +defmodule GitGudWeb.StatsLicenseTest do
2 + @moduledoc """
3 + The detected licence on `/r/:owner/:name/stats/languages`.
4 +
5 + It is labelled with the default branch rather than with whichever ref
6 + the stats are for: detection follows the default branch's tip, and
7 + the two can differ.
8 + """
9 + use GitGudWeb.ConnCase, async: false
10 +
11 + import Ecto.Query, only: [from: 2]
12 + import Phoenix.LiveViewTest
13 + import GitGud.ForgeFixtures
14 +
15 + alias GitGud.Repositories
16 + alias GitGud.Repositories.Repository
17 +
18 + setup %{conn: conn} do
19 + {user, repo} = repository_fixture(%{visibility: "public"})
20 + seed_main_branch(repo, user)
21 + %{conn: log_in_user(conn, user), user: user, repo: repo, handle: user.handle}
22 + end
23 +
24 + test "shows the licence and links to the file it came from", %{
25 + conn: conn,
26 + user: user,
27 + repo: repo,
28 + handle: handle
29 + } do
30 + sha = seed_file(repo, "main", "LICENSE.md", File.read!("LICENSE.md"), user)
31 + assert {:ok, "AGPL-3.0"} = Repositories.detect_and_store_license(repo, sha)
32 +
33 + {:ok, _view, html} = live(conn, ~p"/r/#{handle}/#{repo.name}/stats/languages")
34 +
35 + assert html =~ "AGPL-3.0"
36 + assert html =~ "LICENSE.md"
37 + assert html =~ "/r/#{handle}/#{repo.name}/blob/main/LICENSE.md"
38 + end
39 +
40 + test "says so when nothing was detected", %{conn: conn, repo: repo, handle: handle} do
41 + {:ok, _view, html} = live(conn, ~p"/r/#{handle}/#{repo.name}/stats/languages")
42 +
43 + assert html =~ "No licence detected"
44 + refute html =~ "badge-outline\">AGPL"
45 + end
46 +
47 + test "an unrecognised licence file reads as undetected, not as a guess", %{
48 + conn: conn,
49 + user: user,
50 + repo: repo,
51 + handle: handle
52 + } do
53 + sha = seed_file(repo, "main", "LICENSE", "Be excellent to each other.\n", user)
54 + assert {:ok, nil} = Repositories.detect_and_store_license(repo, sha)
55 +
56 + {:ok, _view, html} = live(conn, ~p"/r/#{handle}/#{repo.name}/stats/languages")
57 +
58 + assert html =~ "No licence detected"
59 + end
60 +
61 + test "renders a licence with no recorded file", %{conn: conn, repo: repo, handle: handle} do
62 + # Possible for a row written before `license_file` existed: the
63 + # badge still shows, with nothing to link to.
64 + {1, _} =
65 + GitGud.Repo.update_all(
66 + from(r in Repository, where: r.id == ^repo.id),
67 + set: [license: "MIT", license_file: nil]
68 + )
69 +
70 + {:ok, _view, html} = live(conn, ~p"/r/#{handle}/#{repo.name}/stats/languages")
71 +
72 + assert html =~ "MIT"
73 + refute html =~ "/blob/main/"
74 + end
75 +end

Parents: 53f3a6c