defmodule Mix.Tasks.Ecto.Migrations do
use Mix.Task
import Mix.Ecto
import Mix.EctoSQL
@shortdoc "Displays the repository migration status"
@aliases [
r: :repo
]
@switches [
repo: [:keep, :string],
no_compile: :boolean,
no_deps_check: :boolean,
migrations_path: :keep,
prefix: :string
]
@moduledoc """
Displays the up / down migration status for the given repository.
The repository must be set under `:ecto_repos` in the
current app configuration or given via the `-r` option.
By default, migrations are expected at "priv/YOUR_REPO/migrations"
directory of the current application but it can be configured
by specifying the `:priv` key under the repository configuration.
If the repository has not been started yet, one will be
started outside our application supervision tree and shutdown
afterwards.
## Examples
$ mix ecto.migrations
$ mix ecto.migrations -r Custom.Repo
## Command line options
* `--migrations-path` - the path to load the migrations from, defaults to
`"priv/repo/migrations"`. This option may be given multiple times in which
case the migrations are loaded from all the given directories and sorted as
if they were in the same one.
Note, if you have previously run migrations from paths `a/` and `b/`, and now
run `mix ecto.migrations --migrations-path a/` (omitting path `b/`), the
migrations from the path `b/` will be shown in the output as `** FILE NOT FOUND **`.
* `--no-compile` - does not compile applications before running
* `--no-deps-check` - does not check dependencies before running
* `--prefix` - the prefix to check migrations on
* `-r`, `--repo` - the repo to obtain the status for
"""
@impl true
def run(args, migrations \\ &Ecto.Migrator.migrations/3, puts \\ &IO.puts/1) do
repos = parse_repo(args)
{opts, _} = OptionParser.parse!(args, strict: @switches, aliases: @aliases)
for repo <- repos do
ensure_repo(repo, args)
paths = ensure_migrations_paths(repo, opts)
case Ecto.Migrator.with_repo(repo, &migrations.(&1, paths, opts), mode: :temporary) do
{:ok, repo_status, _} ->
puts.(
"""
Repo: #{inspect(repo)}
Status Migration ID Migration Name
--------------------------------------------------
""" <>
Enum.map_join(repo_status, "\n", fn {status, number, description} ->
" #{format(status, 10)}#{format(number, 16)}#{description}"
end) <> "\n"
)
{:error, error} ->
Mix.raise("Could not start repo #{inspect(repo)}, error: #{inspect(error)}")
end
end
:ok
end
defp format(content, pad) do
content
|> to_string
|> String.pad_trailing(pad)
end
end