-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmix-checkout.ex
More file actions
91 lines (70 loc) · 2.16 KB
/
Copy pathmix-checkout.ex
File metadata and controls
91 lines (70 loc) · 2.16 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
defmodule Mix.Tasks.Checkout do
use Mix.Task
@moduledoc """
Mix task which runs migrations when switching branches.
Usage: `mix checkout branch-name`
"""
def run(new_branch) do
old_branch = current_branch()
log("On branch #{old_branch}")
new_branch = new_branch |> List.first
{:ok, old_migrations} = File.ls("priv/repo/migrations")
log("Checking out #{new_branch}...")
{_, status_code} = checkout(new_branch)
halt_for_git_errors(status_code)
{:ok, new_migrations} = File.ls("priv/repo/migrations")
if List.last(old_migrations) == List.last(new_migrations) do
log("#{old_branch} and #{new_branch} are at the same migration, done.")
else
run_migrations(old_branch, new_branch, old_migrations, new_migrations)
end
end
def run_migrations(old_branch, new_branch, old_migrations, new_migrations) do
common_ancestor_name = MapSet.intersection(
MapSet.new(old_migrations),
MapSet.new(new_migrations)
)
|> MapSet.to_list
|> Enum.sort
|> List.last
common_ancestor_version =
common_ancestor_name
|> String.split("_")
|> List.first
log("Common Ancestor: #{common_ancestor_name}")
log("Switch back to #{old_branch} to roll it back...")
checkout(old_branch)
log("Rolling back to: #{common_ancestor_version}...")
rollback_to(common_ancestor_version)
log("Checking out #{new_branch}...")
checkout(new_branch)
log("Migrating...")
migrate()
log("Done!")
end
defp rollback_to(version) do
System.cmd("mix", ["ecto.rollback", "--to", version])
end
defp migrate do
System.cmd("mix", ["ecto.migrate"])
end
defp current_branch do
{res, _} = System.cmd("git", ["rev-parse", "--abbrev-ref", "HEAD"])
res |> String.trim
end
defp checkout(branch_name) do
System.cmd("git", ["checkout", branch_name])
end
# git has a status code 1 when error, 0 when ok.
defp halt_for_git_errors(status_code) do
if status_code == 1, do: System.halt(0)
end
defp log(msg) do
IO.puts IO.ANSI.format([
:yellow,
:bright,
:black_background,
msg], true
)
end
end