Skip to content

Commit cc2decb

Browse files
greg-rychlewskiGreg Rychlewski
andauthored
--to-exclusive (#370)
Co-authored-by: Greg Rychlewski <grychle@Gregs-MacBook-Pro.local>
1 parent f7b9602 commit cc2decb

5 files changed

Lines changed: 49 additions & 4 deletions

File tree

lib/ecto/migrator.ex

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -376,7 +376,7 @@ defmodule Ecto.Migrator do
376376
377377
Ecto.Migrator.run(Repo, [{0, MyApp.Migration1}, {1, MyApp.Migration2}, ...], :up, opts)
378378
379-
A strategy (which is one of `:all`, `:step` or `:to`) must be given as
379+
A strategy (which is one of `:all`, `:step`, `:to`, or `:to_exclusive`) must be given as
380380
an option.
381381
382382
## Execution model
@@ -401,6 +401,9 @@ defmodule Ecto.Migrator do
401401
* `:to` - runs all until the supplied version is reached
402402
(including the version given in `:to`)
403403
404+
* `:to_exclusive` - runs all until the supplied version is reached
405+
(excluding the version given in `:to_exclusive`)
406+
404407
Plus all other options described in `up/4`.
405408
"""
406409
@spec run(Ecto.Repo.t, String.t | [String.t] | [{integer, module}], atom, Keyword.t) :: [integer]
@@ -422,10 +425,12 @@ defmodule Ecto.Migrator do
422425
pending_all(versions, migration_source, direction)
423426
to = opts[:to] ->
424427
pending_to(versions, migration_source, direction, to)
428+
to_exclusive = opts[:to_exclusive] ->
429+
pending_to_exclusive(versions, migration_source, direction, to_exclusive)
425430
step = opts[:step] ->
426431
pending_step(versions, migration_source, direction, step)
427432
true ->
428-
{:error, ArgumentError.exception("expected one of :all, :to, or :step strategies")}
433+
{:error, ArgumentError.exception("expected one of :all, :to, :to_exclusive, or :step strategies")}
429434
end
430435
end
431436

@@ -562,6 +567,18 @@ defmodule Ecto.Migrator do
562567
|> Enum.take_while(&(within_target_version?.(&1, target, direction)))
563568
end
564569

570+
defp pending_to_exclusive(versions, migration_source, direction, target) do
571+
within_target_version? = fn
572+
{version, _, _}, target, :up ->
573+
version < target
574+
{version, _, _}, target, :down ->
575+
version > target
576+
end
577+
578+
pending_in_direction(versions, migration_source, direction)
579+
|> Enum.take_while(&(within_target_version?.(&1, target, direction)))
580+
end
581+
565582
defp pending_step(versions, migration_source, direction, count) do
566583
pending_in_direction(versions, migration_source, direction)
567584
|> Enum.take(count)

lib/mix/tasks/ecto.migrate.ex

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ defmodule Mix.Tasks.Ecto.Migrate do
1414
all: :boolean,
1515
step: :integer,
1616
to: :integer,
17+
to_exclusive: :integer,
1718
quiet: :boolean,
1819
prefix: :string,
1920
pool_size: :integer,
@@ -102,6 +103,8 @@ defmodule Mix.Tasks.Ecto.Migrate do
102103
103104
* `--to` - run all migrations up to and including version
104105
106+
* `--to-exclusive` - revert all migrations down to and excluding version
107+
105108
"""
106109

107110
@impl true
@@ -110,7 +113,7 @@ defmodule Mix.Tasks.Ecto.Migrate do
110113
{opts, _} = OptionParser.parse! args, strict: @switches, aliases: @aliases
111114

112115
opts =
113-
if opts[:to] || opts[:step] || opts[:all],
116+
if opts[:to] || opts[:to_exclusive] || opts[:step] || opts[:all],
114117
do: opts,
115118
else: Keyword.put(opts, :all, true)
116119

lib/mix/tasks/ecto.rollback.ex

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ defmodule Mix.Tasks.Ecto.Rollback do
1414
all: :boolean,
1515
step: :integer,
1616
to: :integer,
17+
to_exclusive: :integer,
1718
quiet: :boolean,
1819
prefix: :string,
1920
pool_size: :integer,
@@ -98,6 +99,8 @@ defmodule Mix.Tasks.Ecto.Rollback do
9899
99100
* `--to` - revert all migrations down to and including version
100101
102+
* `--to-exclusive` - revert all migrations down to and excluding version
103+
101104
"""
102105

103106
@impl true
@@ -106,7 +109,7 @@ defmodule Mix.Tasks.Ecto.Rollback do
106109
{opts, _} = OptionParser.parse!(args, strict: @switches, aliases: @aliases)
107110

108111
opts =
109-
if opts[:to] || opts[:step] || opts[:all],
112+
if opts[:to] || opts[:to_exclusive] || opts[:step] || opts[:all],
110113
do: opts,
111114
else: Keyword.put(opts, :step, 1)
112115

test/mix/tasks/ecto.migrate_test.exs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,4 +135,15 @@ defmodule Mix.Tasks.Ecto.MigrateTest do
135135
run ["-r", to_string(Repo), "--migrations-path", path1, "--migrations-path", path2],
136136
fn Repo, [^path1, ^path2], _, _ -> [] end
137137
end
138+
139+
test "runs the migrator with --to_exclusive" do
140+
run ["-r", to_string(Repo), "--to-exclusive", "12345"], fn repo, [path], direction, opts ->
141+
assert repo == Repo
142+
refute path =~ ~r/_build/
143+
assert direction == :up
144+
assert opts == [repo: "Elixir.Mix.Tasks.Ecto.MigrateTest.Repo", to_exclusive: 12345]
145+
[]
146+
end
147+
assert Process.get(:started)
148+
end
138149
end

test/mix/tasks/ecto.rollback_test.exs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,4 +99,15 @@ defmodule Mix.Tasks.Ecto.RollbackTest do
9999
run ["-r", to_string(Repo), "--migrations-path", path1, "--migrations-path", path2],
100100
fn Repo, [^path1, ^path2], _, _ -> [] end
101101
end
102+
103+
test "runs the migrator with --to_exclusive" do
104+
run ["-r", to_string(Repo), "--to-exclusive", "12345"], fn repo, [path], direction, opts ->
105+
assert repo == Repo
106+
refute path =~ ~r/_build/
107+
assert direction == :down
108+
assert opts == [repo: "Elixir.Mix.Tasks.Ecto.RollbackTest.Repo", to_exclusive: 12345]
109+
[]
110+
end
111+
assert Process.get(:started)
112+
end
102113
end

0 commit comments

Comments
 (0)