Current section

Files

Jump to
scales_cms lib mix tasks generate_migrations.ex
Raw

lib/mix/tasks/generate_migrations.ex

if Code.ensure_loaded?(Ecto) do
defmodule Mix.Tasks.ScalesCms.GenerateMigrations do
@moduledoc """
Copies pending ScalesCMS migrations into the host app.
"""
use Mix.Task
import Mix.Generator
import Mix.Ecto, except: [migrations_path: 1]
@shortdoc "Copies pending ScalesCMS migrations"
@doc false
@dialyzer {:no_return, run: 1}
def run(args) do
no_umbrella!("scales_cms.generate_migrations")
repos = parse_repo(args)
Enum.each(repos, fn repo ->
ensure_repo(repo, args)
target_path = migrations_path(repo)
source_path = package_migrations_path()
create_directory(target_path)
source_migrations = migrations_in_dir(source_path)
target_migrations = migrations_in_dir(target_path)
migrated_versions = migrated_versions(repo)
existing_versions =
MapSet.union(
MapSet.new(Map.keys(target_migrations)),
MapSet.new(migrated_versions)
)
pending =
source_migrations
|> Enum.reject(fn {version, _file} -> MapSet.member?(existing_versions, version) end)
if pending == [] do
Mix.shell().info("No pending ScalesCMS migrations found for #{inspect(repo)}")
else
copy_pending_migrations(pending, target_path)
end
end)
end
defp copy_pending_migrations(pending, target_path) do
Enum.each(pending, fn {_version, source_file} ->
destination_file = Path.join(target_path, Path.basename(source_file))
copy_file(source_file, destination_file)
Mix.shell().info("Copied #{Path.basename(source_file)}")
end)
Mix.shell().info("""
ScalesCMS migrations copied.
Next step:
mix ecto.migrate
""")
end
defp package_migrations_path do
:scales_cms
|> :code.priv_dir()
|> to_string()
|> Path.join("repo/migrations")
end
defp migrations_in_dir(path) do
path
|> Path.join("*.exs")
|> Path.wildcard()
|> Enum.map(fn file ->
{extract_version!(file), file}
end)
|> Map.new()
end
defp extract_version!(file) do
file
|> Path.basename()
|> String.split("_", parts: 2)
|> List.first()
end
defp migrated_versions(repo) do
if Code.ensure_loaded?(Ecto.Migrator) &&
function_exported?(Ecto.Migrator, :migrated_versions, 2) do
Ecto.Migrator.migrated_versions(repo, migrations_path(repo))
|> Enum.map(&to_string/1)
else
[]
end
rescue
_ -> []
end
if Code.ensure_loaded?(Ecto.Migrator) &&
function_exported?(Ecto.Migrator, :migrations_path, 1) do
def migrations_path(repo), do: Ecto.Migrator.migrations_path(repo)
end
if Code.ensure_loaded?(Mix.Ecto) && function_exported?(Mix.Ecto, :migrations_path, 1) do
def migrations_path(repo), do: Mix.Ecto.migrations_path(repo)
end
end
end