Skip to content

Commit 17f7c6c

Browse files
committed
Support organization packages in the outdated diffs link
Carry the lock repository through to build_diff_link/1 so `mix hex.outdated` emits repository-qualified comparisons (ORG/name:from:to) for organization packages and skips packages from custom repositories that hex.pm cannot diff. Repository-qualified links are never shortened, so organization and package names are not exposed through an unauthenticated short-URL redirect.
1 parent e36cdf1 commit 17f7c6c

3 files changed

Lines changed: 76 additions & 14 deletions

File tree

lib/mix/tasks/hex.outdated.ex

Lines changed: 30 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ defmodule Mix.Tasks.Hex.Outdated do
140140
end
141141

142142
defp display_table(
143-
[{_package, _dep_only, current, latest, requirements, outdated?, cooldown}],
143+
[{_repo, _package, _dep_only, current, latest, requirements, outdated?, cooldown}],
144144
[_app],
145145
_opts
146146
) do
@@ -198,7 +198,7 @@ defmodule Mix.Tasks.Hex.Outdated do
198198
defp maybe_print_cooldown_legend(versions) do
199199
entries =
200200
Enum.flat_map(versions, fn
201-
{package, _, _, latest, _, _, %{eligible_on: eligible_on}} ->
201+
{_repo, package, _, _, latest, _, _, %{eligible_on: eligible_on}} ->
202202
[{package, latest, eligible_on}]
203203

204204
_ ->
@@ -223,7 +223,7 @@ defmodule Mix.Tasks.Hex.Outdated do
223223

224224
defp set_exit_code(versions, args, opts) do
225225
outdated_versions =
226-
Enum.filter(versions, fn {_p, _o, _l, _la, _r, outdated?, cooldown} ->
226+
Enum.filter(versions, fn {_repo, _p, _o, _l, _la, _r, outdated?, cooldown} ->
227227
outdated? and is_nil(cooldown)
228228
end)
229229

@@ -301,7 +301,8 @@ defmodule Mix.Tasks.Hex.Outdated do
301301
# deps can have multiple `only` values, so we separate by `,`
302302
only_values = String.split(only_value, ",", trim: true)
303303

304-
Enum.filter(versions, fn {_package, dep_only, _lock, _latest, _reqs, _outdated?, _c} ->
304+
Enum.filter(versions, fn {_repo, _package, dep_only, _lock, _latest, _reqs, _outdated?,
305+
_c} ->
305306
dep_only_parts = String.split(dep_only, ",")
306307
Enum.any?(dep_only_parts, &(&1 in only_values))
307308
end)
@@ -337,7 +338,7 @@ defmodule Mix.Tasks.Hex.Outdated do
337338
end
338339

339340
[
340-
{Atom.to_string(name), dep_only, lock_version, latest_version, requirements,
341+
{repo, Atom.to_string(name), dep_only, lock_version, latest_version, requirements,
341342
outdated?, cooldown}
342343
]
343344

@@ -385,7 +386,7 @@ defmodule Mix.Tasks.Hex.Outdated do
385386
List.last(versions)
386387
end
387388

388-
defp format_all_row({package, dep_only, lock, latest, requirements, outdated?, cooldown}) do
389+
defp format_all_row({_repo, package, dep_only, lock, latest, requirements, outdated?, cooldown}) do
389390
latest_color = if outdated?, do: :red, else: :green
390391
req_matches? = req_matches?(requirements, latest)
391392

@@ -407,15 +408,24 @@ defmodule Mix.Tasks.Hex.Outdated do
407408
]
408409
end
409410

410-
defp build_diff_link({package, _dep_only, lock, latest, requirements, outdated?, _cooldown}) do
411+
defp build_diff_link(
412+
{repo, package, _dep_only, lock, latest, requirements, outdated?, _cooldown}
413+
) do
411414
req_matches? = req_matches?(requirements, latest)
412415

413-
case {outdated?, req_matches?} do
414-
{true, true} -> "diffs[]=#{package}:#{lock}:#{latest}"
415-
{_, _} -> nil
416+
with true <- outdated?,
417+
true <- req_matches?,
418+
comparison_package when is_binary(comparison_package) <- diff_package(repo, package) do
419+
"diffs[]=#{comparison_package}:#{lock}:#{latest}"
420+
else
421+
_ -> nil
416422
end
417423
end
418424

425+
defp diff_package("hexpm", package), do: package
426+
defp diff_package("hexpm:" <> organization, package), do: "#{organization}/#{package}"
427+
defp diff_package(_repo, _package), do: nil
428+
419429
defp version_match?(_version, nil), do: true
420430
defp version_match?(version, req), do: Version.match?(version, req)
421431

@@ -435,13 +445,17 @@ defmodule Mix.Tasks.Hex.Outdated do
435445
defp diff_link(diff_links) do
436446
long_url = "https://hex.pm/diffs?" <> Enum.join(diff_links, "&")
437447

438-
if Hex.State.fetch!(:no_short_urls) do
448+
if Hex.State.fetch!(:no_short_urls) or private_comparison?(diff_links) do
439449
long_url
440450
else
441451
maybe_get_short_link(long_url)
442452
end
443453
end
444454

455+
defp private_comparison?(diff_links) do
456+
Enum.any?(diff_links, &String.contains?(&1, "/"))
457+
end
458+
445459
defp maybe_get_short_link(long_url) do
446460
case Hex.API.ShortURL.create(long_url) do
447461
:error -> long_url
@@ -450,8 +464,8 @@ defmodule Mix.Tasks.Hex.Outdated do
450464
end
451465

452466
defp any_possible_to_update?(outdated_versions) do
453-
Enum.any?(outdated_versions, fn {_package, _dep_only, _lock, latest, requirements, _outdated?,
454-
_cooldown} ->
467+
Enum.any?(outdated_versions, fn {_repo, _package, _dep_only, _lock, latest, requirements,
468+
_outdated?, _cooldown} ->
455469
req_matches?(requirements, latest)
456470
end)
457471
end
@@ -476,7 +490,9 @@ defmodule Mix.Tasks.Hex.Outdated do
476490
|> Enum.join(",")
477491
end
478492

479-
defp cast_version_map({package, dep_only, lock, latest, requirements, outdated?, cooldown}) do
493+
defp cast_version_map(
494+
{_repo, package, dep_only, lock, latest, requirements, outdated?, cooldown}
495+
) do
480496
%{
481497
package: package,
482498
only: dep_only,

test/mix/tasks/hex.outdated_test.exs

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,18 @@ defmodule Mix.Tasks.Hex.OutdatedTest do
1414
end
1515
end
1616

17+
defmodule OutdatedOrganizationDeps.MixProject do
18+
def project do
19+
[
20+
app: :outdated_app,
21+
version: "0.0.1",
22+
deps: [
23+
{:foo, "~> 0.1.0", repo: "hexpm:testorg"}
24+
]
25+
]
26+
end
27+
end
28+
1729
defmodule OutdatedBetaDeps.MixProject do
1830
def project do
1931
[
@@ -801,6 +813,39 @@ defmodule Mix.Tasks.Hex.OutdatedTest do
801813
end)
802814
end
803815

816+
test "outdated links organization diffs without shortening the URL" do
817+
Mix.Project.push(OutdatedOrganizationDeps.MixProject)
818+
819+
in_tmp(fn ->
820+
set_home_tmp()
821+
822+
suffix = System.unique_integer([:positive])
823+
824+
auth =
825+
Hexpm.new_user(
826+
"outdated_org_#{suffix}",
827+
"outdated_org_#{suffix}@mail.com",
828+
"password",
829+
"outdated_org_key_#{suffix}"
830+
)
831+
832+
repos = Hex.State.fetch!(:repos)
833+
Hex.State.put(:repos, put_in(repos["hexpm"].auth_key, auth[:key]))
834+
835+
Mix.Dep.Lock.write(%{foo: {:hex, :foo, "0.1.0", nil, nil, nil, "hexpm:testorg", nil}})
836+
837+
Mix.Task.run("deps.get")
838+
flush()
839+
840+
assert catch_throw(Mix.Task.run("hex.outdated", ["--all"])) == {:exit_code, 1}
841+
842+
lines = flush()
843+
output = Enum.map_join(lines, "\n", fn {_, _, [line]} -> line end)
844+
845+
assert output =~ "https://hex.pm/diffs?diffs[]=testorg/foo:0.1.0:0.1.1"
846+
end)
847+
end
848+
804849
defp extract_statuses(lines) do
805850
Enum.flat_map(lines, fn {_, _, [line]} ->
806851
~r/Up-to-date|Update not possible|Update possible/

test/setup_hexpm.exs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ Hexpm.new_package(
8787

8888
Hexpm.new_repo("testorg", auth)
8989
Hexpm.new_package("testorg", "foo", "0.1.0", [], pkg_meta, auth)
90+
Hexpm.new_package("testorg", "foo", "0.1.1", [], pkg_meta, auth)
9091
Hexpm.new_package("testorg", "bar", "0.1.0", [foo: "~> 0.1.0"], pkg_meta, auth)
9192

9293
Hexpm.new_repo("remote_converger_org", auth)

0 commit comments

Comments
 (0)