defmodule Mix.Tasks.Stevedore.Sync do
@shortdoc "Bulk-copy images from a spec file"
@moduledoc """
Copy many images from a declarative spec file. Each non-blank line is `SRC DST` (lines starting
with `#` are comments).
mix stevedore.sync SPEC [--scheme http|https]
## Example spec
docker://alpine:3.20 oci:./mirror/alpine:3.20
docker://debian:12 oci:./mirror/debian:12
"""
use Mix.Task
alias Stevedore.CLI
@switches [scheme: :string]
@impl true
def run(argv) do
{opts, args, _} = OptionParser.parse(argv, switches: @switches)
case args do
[spec] ->
CLI.start_app()
jobs = spec |> File.read!() |> parse_jobs()
{:ok, results} = Stevedore.sync(jobs, Keyword.take(opts, [:scheme]))
Enum.each(results, &report/1)
_ ->
Mix.raise("usage: mix stevedore.sync SPEC")
end
end
defp parse_jobs(contents) do
for line <- String.split(contents, "\n", trim: true),
trimmed = String.trim(line),
trimmed != "" and not String.starts_with?(trimmed, "#"),
[src, dst] <- [String.split(trimmed, ~r/\s+/, parts: 2)] do
{src, dst}
end
end
defp report({{src, dst}, {:ok, %{digest: digest}}}),
do: Mix.shell().info("#{src} -> #{dst} #{digest}")
defp report({{src, dst}, {:error, reason}}),
do: Mix.shell().error("#{src} -> #{dst} FAILED: #{CLI.format_error(reason)}")
end