tarakan/lib/tarakan_web/repository_paths.ex
Maxfield Luke af6077b9c3
All checks were successful
CI and deploy / Test (push) Successful in 4m52s
CI and deploy / Deploy production (push) Successful in 23s
Initial commit on Forgejo
Fresh repository history for elektrine/tarakan hosted at
https://git.elektrine.com/elektrine/tarakan.
2026-07-29 04:43:40 -04:00

83 lines
2.7 KiB
Elixir

defmodule TarakanWeb.RepositoryPaths do
@moduledoc """
Builds repository-scoped paths from a repository's stored host, so no view
or controller hardcodes a single source host into its links.
Remote repositories live under their host domain (`/github.com/owner/name`),
so a source URL pastes directly onto Tarakan. Hosted repositories live at
GitHub-style bare paths (`/handle/name`); `TarakanWeb.Plugs.HostedRoutes`
maps that form onto the internal `/hosted` route scope.
"""
use TarakanWeb, :verified_routes
alias Tarakan.Repositories.Repository
def repository_path(repository) do
repository_root(repository)
end
def repository_security_path(repository) do
repository_root(repository) <> "/security"
end
def repository_commits_path(repository) do
repository_root(repository) <> "/commits"
end
def repository_commit_path(repository, commit_sha) do
repository_commits_path(repository) <> "/" <> encode_path_segment(commit_sha)
end
def repository_code_path(repository, commit_sha, path_segments \\ []) do
root = repository_root(repository) <> "/code/" <> encode_path_segment(commit_sha)
case path_segments do
[] -> root
segments -> root <> "/" <> Enum.map_join(segments, "/", &encode_path_segment/1)
end
end
@doc """
Clone URLs for a Tarakan-hosted repository, or nil for external hosts.
The HTTPS URL derives from the endpoint's public URL; the SSH URL is
included only while the SSH daemon is enabled.
"""
def clone_urls(repository) do
if Repository.hosted?(repository) do
base = TarakanWeb.Endpoint.url()
path = "#{repository.owner}/#{repository.name}.git"
%{https: "#{base}/#{path}", ssh: ssh_clone_url(URI.parse(base).host, path)}
end
end
defp ssh_clone_url(host, path) do
config = Application.get_env(:tarakan, Tarakan.GitSSH, [])
if Keyword.get(config, :enabled, false) do
case Keyword.get(config, :port, 22) do
22 -> "ssh://git@#{host}/#{path}"
port -> "ssh://git@#{host}:#{port}/#{path}"
end
end
end
defp repository_root(%{owner: owner, name: name} = repository) do
if hosted?(repository) do
"/" <> encode_path_segment(owner) <> "/" <> encode_path_segment(name)
else
"/" <>
encode_path_segment(repository.host) <>
"/" <> encode_path_segment(owner) <> "/" <> encode_path_segment(name)
end
end
# Projection rows (infestation graph, instance ledger) carry host/owner/name as
# plain maps rather than loaded structs.
defp hosted?(%Repository{} = repository), do: Repository.hosted?(repository)
defp hosted?(%{host: host}), do: host == Repository.hosted_host()
defp encode_path_segment(segment), do: URI.encode(segment, &URI.char_unreserved?/1)
end