Current section
Files
Jump to
Current section
Files
lib/mix/tasks/ecto_rollback_guard.preview.ex
defmodule Mix.Tasks.EctoRollbackGuard.Preview do
@shortdoc "Preview the impact of rolling back Ecto migrations"
@moduledoc """
Preview which operations would execute and what data would be lost
when rolling back to a target migration version.
$ mix ecto_rollback_guard.preview --to 20230101120000
## Options
- `--to VERSION` — target migration version (required)
- `--repo MyApp.Repo` — repo module (defaults to app's configured repo)
- `--no-enrich` — skip database row count queries
- `--format FORMAT` — output format: `terminal` (default) or `json`
"""
use Mix.Task
alias EctoRollbackGuard.Reporter
@impl Mix.Task
def run(args) do
{opts, _, _} =
OptionParser.parse(args,
strict: [to: :integer, repo: :string, enrich: :boolean, format: :string],
aliases: [t: :to, r: :repo, f: :format]
)
version = opts[:to] || Mix.raise("--to VERSION is required")
format = opts[:format] || "terminal"
enrich? = Keyword.get(opts, :enrich, true)
repo = resolve_repo(opts[:repo])
Mix.Task.run("app.start")
case EctoRollbackGuard.preview(repo, version, enrich: enrich?) do
{:ok, impacts} ->
output =
case format do
"json" -> Reporter.format_json(impacts)
_ -> Reporter.format_terminal(impacts)
end
Mix.shell().info(output)
{:error, reason} ->
Mix.raise("Preview failed: #{inspect(reason)}")
end
end
defp resolve_repo(nil) do
# Look for ecto_repos in the host application's config
app = Mix.Project.config()[:app]
case Application.get_env(app, :ecto_repos, []) do
[repo | _] -> repo
[] -> Mix.raise("No repo configured. Use --repo MyApp.Repo or configure :ecto_repos")
end
end
defp resolve_repo(repo_string) do
Module.concat([repo_string])
end
end