Something went wrong. Try again.
This repository has no description
Something went wrong. Try again.
5.5 kB · 198 lines
Elixir
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199defmodule GitSyncWeb.SourceController do use GitSyncWeb, :controller
import Phoenix.Component, only: [to_form: 1]
alias GitSync.Connection alias GitSync.Connections alias GitSync.Destination alias GitSync.Forge alias GitSync.Runs alias GitSync.Source alias GitSync.Sources alias GitSync.Sync alias GitSyncWeb.SourceHTML alias GitSyncWeb.SSE
def index(conn, _params), do: render_index(conn, blank_source(), blank_destination())
def create(conn, %{"source" => source_params, "destination" => destination_params}) do case Sources.create_with_destination(source_params, destination_params) do {:ok, source} -> Sync.reconcile(source)
conn |> register_webhook(source) |> redirect(to: ~p"/sources/#{source}")
{:error, %Ecto.Changeset{data: %Source{}} = changeset} -> render_index( conn, changeset, Destination.form_changeset(%Destination{}, destination_params) )
{:error, %Ecto.Changeset{data: %Destination{}} = changeset} -> render_index(conn, Source.changeset(%Source{}, source_params), changeset) end end
def show(conn, %{"id" => id}) do source = Sources.get(id)
render(conn, :show, source: source, runs: Runs.list(source.id), form: to_form(Destination.form_changeset(%Destination{}, %{})), connection_options: connection_options(), destination_repos: nil ) end
def update(conn, %{"id" => id, "source" => params}) do source = Sources.get(id)
case Sources.update(source, params) do {:ok, source} -> Sync.reconcile(source)
conn |> put_flash(:info, "Source updated.") |> redirect(to: ~p"/sources/#{source}")
{:error, _changeset} -> conn |> put_flash(:error, "That change was refused.") |> redirect(to: ~p"/sources/#{source}") end end
def sync(conn, %{"id" => id}) do source = Sources.get(id) Sync.sync_now(source.id)
conn |> put_flash(:info, "Syncing now.") |> redirect(to: ~p"/sources/#{source}") end
def delete(conn, %{"id" => id}) do source = Sources.get(id) Sync.stop_runner(source.id) {:ok, _source} = Sources.delete(source)
conn |> put_flash(:info, "Source removed.") |> redirect(to: ~p"/sources") end
@doc """ Repaints whichever repository pickers the page is showing, for the forges it now names. """ def repos(conn, params) do signals = JSON.decode!(params["datastar"] || "{}")
conn |> SSE.open() |> patch_repo_field("source-repo-field", source_field(), "Source repository", signals) |> patch_repo_field( "destination-repo-field", destination_field(), "Destination repository", signals ) end
@doc """ Streams run updates for one source until the browser goes away. """ def events(conn, %{"id" => id}) do source = Sources.get(id) :ok = Runs.subscribe(source.id)
conn |> SSE.open() |> SSE.stream(&handle_run/2) end
@doc """ The `events/2` stream handler: every run update repaints the run list. """ def handle_run({:run, run}, conn) do case SSE.patch_elements(conn, runs_markup(run.source_id)) do {:ok, conn} -> {:cont, conn} {:error, _reason} -> {:halt, conn} end end
defp source_field, do: to_form(blank_source())[:repo] defp destination_field, do: to_form(blank_destination())[:repo]
defp blank_source, do: Source.changeset(%Source{}, %{}) defp blank_destination, do: Destination.form_changeset(%Destination{}, %{})
defp patch_repo_field(conn, id, field, label, signals) do signal = "#{field.form.name}_connection_id"
if Map.has_key?(signals, signal) do markup = markup( SourceHTML.repo_field(%{ id: id, field: field, label: label, repos: list_repos(signals[signal]) }) )
case SSE.patch_elements(conn, markup) do {:ok, conn} -> conn {:error, _reason} -> conn end else conn end end
defp list_repos(connection_id) when connection_id in [nil, ""], do: nil
defp list_repos(connection_id) do case Connections.get_by_id(connection_id) do %Connection{} = connection -> Forge.list_repos(connection) nil -> nil end end
defp runs_markup(source_id), do: markup(SourceHTML.runs(%{runs: Runs.list(source_id)}))
defp markup(rendered) do rendered |> Phoenix.HTML.Safe.to_iodata() |> IO.iodata_to_binary() end
defp render_index(conn, source_changeset, destination_changeset) do render(conn, :index, sources: Sources.list(), form: to_form(source_changeset), destination_form: to_form(destination_changeset), connection_options: connection_options(), source_repos: list_repos(Ecto.Changeset.get_field(source_changeset, :connection_id)), destination_repos: list_repos(Ecto.Changeset.get_field(destination_changeset, :connection_id)) ) end
defp connection_options, do: Enum.map(Connections.list(), &connection_option/1)
defp connection_option(%Connection{} = connection), do: {"#{connection.kind} — #{connection.base_url}", connection.id}
defp register_webhook(conn, %Source{} = source) do case Sources.register_webhook(source, url(~p"/")) do {:ok, _source} -> put_flash(conn, :info, "Source added.") {:error, reason} -> put_flash(conn, :error, "Source added, but #{reason}") end endend