diff --git a/lib/mix_tasks/helpers.ex b/lib/mix_tasks/helpers.ex index fa62bfd..52f8e0e 100644 --- a/lib/mix_tasks/helpers.ex +++ b/lib/mix_tasks/helpers.ex @@ -1,4 +1,43 @@ defmodule Bonfire.Common.Mix.Tasks.Helpers do + def igniter_copy(igniter, source, target, opts \\ []) + + def igniter_copy(igniter, sources, target, opts) when is_list(sources) do + IO.puts("Batch copying #{inspect(sources)} to #{target}") + + Enum.reduce(sources, igniter, fn source, igniter -> + igniter_copy(igniter, source, prepare_target_path(source, target), opts) + end) + end + + def igniter_copy(igniter, source, target, opts) do + IO.puts("Copying #{source} to #{target}") + + if File.dir?(source) do + sources = + File.ls!(source) + |> Enum.map(fn file -> Path.join(source, file) end) + + igniter_copy(igniter, sources, target, opts) + else + contents_to_copy = File.read!(source) + + Igniter.create_or_update_file(igniter, target, contents_to_copy, fn source -> + Rewrite.Source.update(source, :content, contents_to_copy) + end) + end + end + + defp prepare_target_path(source, target) do + # Remove the repeated part of source from target + if String.contains?(target, source) do + String.replace(target, source, "") + |> String.trim_leading("/") + |> (&Path.join(target, &1)).() + else + Path.join(target, Path.basename(source)) + end + end + def igniter_path_for_module( igniter, module_name, diff --git a/lib/mix_tasks/extension/copy_migrations.ex b/lib/mix_tasks/install/copy_migrations.ex similarity index 54% rename from lib/mix_tasks/extension/copy_migrations.ex rename to lib/mix_tasks/install/copy_migrations.ex index 3dbb4cd..3a52ad1 100644 --- a/lib/mix_tasks/extension/copy_migrations.ex +++ b/lib/mix_tasks/install/copy_migrations.ex @@ -1,5 +1,6 @@ -defmodule Mix.Tasks.Bonfire.Extension.CopyMigrations do - use Mix.Task +defmodule Mix.Tasks.Bonfire.Install.CopyMigrations do + use Igniter.Mix.Task + alias Bonfire.Common.Mix.Tasks.Helpers # import Macro, only: [camelize: 1, underscore: 1] # import Mix.Generator # import Mix.Ecto, except: [migrations_path: 1] @@ -9,9 +10,9 @@ defmodule Mix.Tasks.Bonfire.Extension.CopyMigrations do @shortdoc "Generates migrations for the extension" @doc """ Usage: - `just mix bonfire.extension.copy_migrations my_extension` + `just mix bonfire.install.copy_migrations my_extension` or - `just mix bonfire.extension.copy_migrations` + `just mix bonfire.install.copy_migrations` NOTE: if you don't specify what extension(s) to include, it will automatically include all extensions which: - start with `bonfire_` @@ -19,40 +20,50 @@ defmodule Mix.Tasks.Bonfire.Extension.CopyMigrations do Optional args: - --force (to not ask for confirmation before copying, or to overwrite existing migration files) + --force (to not ask for confirmation before copying, or to overwrite existing migration files - only applies when not using Igniter) --from priv/repo/migrations (to change the source repo paths, relative to each extension path) - --to priv/repo/migrations (to change the target repo path (defaults to current flavour's migrations) relative to working directory) - --repo MyRepo (to specify what repo to migrate after) + --to priv/repo/ (to change the target repo path (defaults to current flavour's migrations) relative to working directory) """ @switches [from: :string, to: :string, force: :boolean] - @default_repo_path "repo/migrations" - @default_path "priv/" <> @default_repo_path + @default_repo_path "repo" + @default_mig_path @default_repo_path <> "/migrations" - def run(args) do + def igniter(igniter, args) do IO.inspect(args, label: "Args") case OptionParser.parse(args, switches: @switches) do {opts, [], _} -> # None specified, will simply try copying any available extension. - maybe_copy(opts) + copy_all(igniter, opts) {opts, extensions, _} -> - extensions - |> maybe_copy(opts) + copy_for_extensions(igniter, extensions, opts) end + end - # repo = - # List.first(parse_repo(args)) - # |> IO.inspect(label: "repo") + def copy_all(igniter, opts) do + extensions_pattern = + Bonfire.Common.Utils.maybe_apply(Bonfire.Mixer, :multirepo_prefixes, [], + fallback_return: [] + ) ++ ["bonfire"] ++ Bonfire.Common.Config.get([:extensions_pattern], []) - # if Mix.shell().yes?("Do you want to run these migrations on #{repo}?") do - # Mix.Task.run("ecto.migrate", [repo]) - # end + extensions = + (Bonfire.Common.Utils.maybe_apply(Bonfire.Mixer, :deps_tree_flat, [], fallback_return: nil) || + Bonfire.Common.Extensions.loaded_deps_names()) + |> IO.inspect(label: "all deps") + |> Enum.map(&to_string/1) + |> Enum.filter(fn + #  FIXME: make this configurable + "bonfire_" <> _ -> true + name -> String.starts_with?(name, extensions_pattern) + end) + + copy_for_extensions(igniter, extensions, opts) end - def maybe_copy(extensions \\ nil, opts) do - # IO.inspect(opts) + def copy_for_extensions(igniter, extensions, opts) do + IO.inspect(opts, label: "Options") path = opts[:to] || Path.expand(@default_repo_path, Bonfire.Mixer.flavour_path()) @@ -60,30 +71,24 @@ defmodule Mix.Tasks.Bonfire.Extension.CopyMigrations do Path.expand(path, File.cwd!()) |> IO.inspect(label: "to path") - extensions_pattern = - Bonfire.Common.Utils.maybe_apply(Bonfire.Mixer, :multirepo_prefixes, [], - fallback_return: [] - ) ++ ["bonfire"] ++ Bonfire.Common.Config.get([:extensions_pattern], []) + extension_paths = + extensions + |> IO.inspect(label: "deps to include") + |> Bonfire.Mixer.dep_paths(opts[:from] || "priv/" <> @default_mig_path) + |> IO.inspect(label: "paths to copy") - (extensions || - (Bonfire.Common.Utils.maybe_apply(Bonfire.Mixer, :deps_tree_flat, [], fallback_return: nil) || - Bonfire.Common.Extensions.loaded_deps_names()) - |> IO.inspect(label: "all deps") - |> Enum.map(&to_string/1) - |> Enum.filter(fn - #  FIXME: make this configurable - "bonfire_" <> _ -> true - name -> String.starts_with?(name, extensions_pattern) - end)) - |> IO.inspect(label: "deps to include") - |> Bonfire.Mixer.dep_paths(opts[:from] || @default_path) - |> copy(dest_path, opts) + if igniter do + Igniter.include_glob(igniter, Path.join(dest_path, "**/*.{exs}")) + |> Helpers.igniter_copy(extension_paths, dest_path, opts) + else + simple_copy(extension_paths, dest_path, opts) + end end - def copy(extension_paths, dest_path, opts) when is_list(extension_paths), - do: Enum.each(extension_paths, ©(&1, dest_path, opts)) + def simple_copy(extension_paths, dest_path, opts) when is_list(extension_paths), + do: Enum.each(extension_paths, &simple_copy(&1, dest_path, opts)) - def copy(source_path, dest_path, opts) do + def simple_copy(source_path, dest_path, opts) do source_path |> IO.inspect() diff --git a/lib/mix_tasks/install/copy_migrations.old.ex b/lib/mix_tasks/install/copy_migrations.old.ex new file mode 100644 index 0000000..383d498 --- /dev/null +++ b/lib/mix_tasks/install/copy_migrations.old.ex @@ -0,0 +1,57 @@ +defmodule Mix.Tasks.Bonfire.Extension.CopyMigrations do + use Mix.Task + # import Macro, only: [camelize: 1, underscore: 1] + # import Mix.Generator + # import Mix.Ecto, except: [migrations_path: 1] + + # TODO: turn into an escript so it can be run without compiling the whole app? + + @shortdoc "Generates migrations for the extension" + @doc """ + Usage: + `just mix bonfire.extension.copy_migrations my_extension` + or + `just mix bonfire.extension.copy_migrations` + + NOTE: if you don't specify what extension(s) to include, it will automatically include all extensions which: + - start with `bonfire_` + - and are included in the top-level app (not dependencies of dependencies) + + Optional args: + + --force (to not ask for confirmation before copying, or to overwrite existing migration files) + --from priv/repo/migrations (to change the source repo paths, relative to each extension path) + --to priv/repo/migrations (to change the target repo path (defaults to current flavour's migrations) relative to working directory) + --repo MyRepo (to specify what repo to migrate after) + """ + + @switches [from: :string, to: :string, force: :boolean] + @default_repo_path "repo/migrations" + @default_path "priv/" <> @default_repo_path + + def run(args) do + case OptionParser.parse(args, switches: @switches) do + {opts, [], _} -> + # None specified, will simply try copying any available extension. + Mix.Tasks.Bonfire.Install.CopyMigrations.copy_all( + nil, + opts |> Keyword.put_new(:to, @default_path) + ) + + {opts, extensions, _} -> + Mix.Tasks.Bonfire.Install.CopyMigrations.copy_for_extensions( + nil, + extensions, + opts |> Keyword.put_new(:to, @default_path) + ) + end + + # repo = + # List.first(parse_repo(args)) + # |> IO.inspect(label: "repo") + + # if Mix.shell().yes?("Do you want to run these migrations on #{repo}?") do + # Mix.Task.run("ecto.migrate", [repo]) + # end + end +end