Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save pertsevds/ab27499cad9c93a9742ce2df1d5ec258 to your computer and use it in GitHub Desktop.
Save pertsevds/ab27499cad9c93a9742ce2df1d5ec258 to your computer and use it in GitHub Desktop.
Compare Phoenix Versions with extra custom steps like mix phx.gen.live Accounts User users name:string
#
# Usage:
# elixir <this_script_name.exs> 1.7.2
#
# The script grabs a Phoenix version and places it
# under `phoenix/<version>` subfolder. It attempts to call
# a diff GUI, if there's another version found in `phoenix`.
# It picks the closest older version, if more than one found.
#
# Feel free to modify PhoenixCompareConfig
# to bring in your diff tool and add additional
# steps after blank project creation.
#
#
defmodule PhoenixCompareConfig do
@doc "project name to pass to mix phx.new <project_name>"
def project_name, do: "project"
@doc "Additional steps to execute on a phoenix new project. Caller expects :ok on success."
def run(into_path, project_name) do
{_, 0} =
cmd(["mix phx.gen.live Accounts User users name:string"],
cd: Path.join(into_path, project_name),
stderr_to_stdout: true
)
:ok
end
def maybe_diff(previous, current) do
case previous do
nil ->
IO.puts(
"Skipping diff: no version < #{current} is found processed. Request it with this script and try again."
)
_ ->
IO.puts("#{previous} <-> #{current}")
case :os.type() do
{:win32, _} ->
Task.async(fn ->
cmd([
~S<C:\Program Files (x86)\WinMerge\WinMergeU.exe>,
"/r",
# Titles
"/dl",
"#{previous}",
"/dr",
"#{current}",
# Read only
"/wl",
"/wr",
Path.join("phoenix", [previous, "/", project_name()]),
Path.join("phoenix", [current, "/", project_name()])
])
end)
_ ->
IO.puts("Skipping diff: not implemented for #{:os.type()} yet. Please PR!")
end
end
end
def cmd([_ | _] = what, options \\ []) do
{cmd, args, options} =
case :os.type() do
{:win32, _} ->
{"cmd", ["/c"] ++ what, options}
# _os_name
# ------------
# :darwin
# ...
{:unix, _os_name} ->
[head | tail] = what
{head, tail, options}
end
stream = IO.binstream(:standard_io, :line)
options = Keyword.put_new(options, :into, stream)
System.cmd(cmd, args, options)
end
end
defmodule Execute do
import PhoenixCompareConfig
def already_exists_fail(is_force) do
path = phoenix_version_path()
case File.stat(path) do
{:ok, _stat} ->
case is_force do
true ->
case File.rm_rf(path) do
{:ok, _} -> :ok
{:error, reason, file} -> {:error, "#{file} failed to delete due to #{reason}"}
end
false ->
{:error, "#{path} already exists. Add --force to force deletion"}
end
{:error, _reason} ->
:ok
end
end
def get_phx_new do
version = argv_as_version()
{_, 0} =
cmd(["mix", "archive.install", "--force", "hex", "phx_new", "#{Version.to_string(version)}"])
:ok
end
def recreate_path do
path = phoenix_version_path()
File.rm_rf!(path)
:ok = File.mkdir_p(path)
{:ok, path}
end
def initiate_phx_new(into_path, project_name) do
# mix phx.new <project_name>
{_, 0} =
cmd(["mix phx.new #{project_name} --no-install"],
cd: into_path,
stderr_to_stdout: true
)
{_, 0} =
cmd(["mix deps.get"],
cd: Path.join(into_path, project_name),
stderr_to_stdout: true
)
run(into_path, project_name)
end
def argv_as_version do
if length(System.argv()) == 0 do
raise "Phoenix version number required"
end
[h | _] = System.argv()
{:ok, version} = Version.parse(h)
version
end
def argv_is_force do
Enum.find_index(System.argv(), fn v -> v == "--force" end) != nil
end
def phoenix_version_path do
version = argv_as_version()
Path.join("phoenix", "#{version}")
end
def build(src) do
{_, 0} = cmd(["npm run build"], cd: src)
:ok
end
def available_prev_version(%Version{} = version) do
{:ok, versions} = File.ls("phoenix")
sorted = Enum.sort(versions, fn a, b -> Version.compare(a, b) == :lt end)
idx = Enum.find_index(sorted, fn v -> v == Version.to_string(version) end)
cond do
idx > 0 -> Enum.at(sorted, idx - 1)
true -> nil
end
end
def maybe_diff(previous, current), do: PhoenixCompareConfig.maybe_diff(previous, current)
end
version = Execute.argv_as_version()
is_force = Execute.argv_is_force()
case Execute.already_exists_fail(is_force) do
:ok ->
:ok = Execute.get_phx_new()
{:ok, path} = Execute.recreate_path()
:ok = Execute.initiate_phx_new(path, PhoenixCompareConfig.project_name())
{:error, reason} ->
IO.puts(reason)
end
previous = Execute.available_prev_version(version)
current = Version.to_string(version)
Execute.maybe_diff(previous, current)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment