mirror of
https://github.com/UzixLS/migresia.git
synced 2025-07-19 07:11:28 +03:00
Clean up and reorganize the code + store timestamps as integers + extract the function to create new migrations to a separate script
This commit is contained in:
51
priv/new_migration.esh
Executable file
51
priv/new_migration.esh
Executable file
@ -0,0 +1,51 @@
|
|||||||
|
#!/usr/bin/env escript
|
||||||
|
%% -*- erlang -*-
|
||||||
|
%%! -smp enable
|
||||||
|
|
||||||
|
template(Name) ->
|
||||||
|
[
|
||||||
|
"-module('" ++ Name ++ "').",
|
||||||
|
"-behavior(db_migration).",
|
||||||
|
"-export([up/0, down/0]).",
|
||||||
|
"",
|
||||||
|
"up() ->",
|
||||||
|
" ok.",
|
||||||
|
"",
|
||||||
|
"down() ->",
|
||||||
|
" ok."
|
||||||
|
].
|
||||||
|
|
||||||
|
usage() ->
|
||||||
|
[
|
||||||
|
"************************************************************************",
|
||||||
|
"This script can be used to create a new migration from a template.",
|
||||||
|
"It automatically calculates a new timestamp to use with the migration",
|
||||||
|
"and appends the provided description to the name of the migration.",
|
||||||
|
"",
|
||||||
|
"Usage:",
|
||||||
|
" new_migration.esh [ -h | description ]",
|
||||||
|
"",
|
||||||
|
" -h",
|
||||||
|
" This help.",
|
||||||
|
"",
|
||||||
|
" description",
|
||||||
|
" Will be added as the file name after the timestamp, e.g.:",
|
||||||
|
" 20130731163300_convert_permissions.erl",
|
||||||
|
"************************************************************************"
|
||||||
|
].
|
||||||
|
|
||||||
|
main([]) -> print_usage();
|
||||||
|
main(["-h"]) -> print_usage();
|
||||||
|
main([Description]) ->
|
||||||
|
{{Year, Month, Day}, {Hour, Minute, Second}} = calendar:local_time(),
|
||||||
|
Args = [Year, Month, Day, Hour, Minute, Second, Description],
|
||||||
|
Name = "~w~2.2.0w~2.2.0w~2.2.0w~2.2.0w~2.2.0w_~s",
|
||||||
|
Module = lists:flatten(io_lib:format(Name, Args)),
|
||||||
|
FileName = Module ++ ".erl",
|
||||||
|
io:format("Creating new migration: '~p'~n", [FileName]),
|
||||||
|
Template = [X ++ "\n" || X <- template(Module)],
|
||||||
|
ok = file:write_file(FileName, Template),
|
||||||
|
io:format("Done.~n", []).
|
||||||
|
|
||||||
|
print_usage() ->
|
||||||
|
[io:format(X ++ "~n", []) || X <- usage()].
|
@ -27,7 +27,7 @@
|
|||||||
{application, migresia,
|
{application, migresia,
|
||||||
[
|
[
|
||||||
{description, "Simple mnesia database migration tool"},
|
{description, "Simple mnesia database migration tool"},
|
||||||
{vsn, "0.0.1"},
|
{vsn, "0.0.2"},
|
||||||
{registered, []},
|
{registered, []},
|
||||||
{applications, [kernel, stdlib]}
|
{applications, [kernel, stdlib]}
|
||||||
]
|
]
|
||||||
|
163
src/migresia.erl
163
src/migresia.erl
@ -1,4 +1,4 @@
|
|||||||
%% Copyright (c) 2013, Grzegorz Junka
|
%% Copyright (c) 2015, Grzegorz Junka
|
||||||
%% All rights reserved.
|
%% All rights reserved.
|
||||||
%%
|
%%
|
||||||
%% Redistribution and use in source and binary forms, with or without
|
%% Redistribution and use in source and binary forms, with or without
|
||||||
@ -24,102 +24,91 @@
|
|||||||
|
|
||||||
-module(migresia).
|
-module(migresia).
|
||||||
|
|
||||||
-export([create_new_migration/2, check/1, migrate/1, rollback/2, list_nodes/0, ensure_started/1]).
|
-export([start_all_mnesia/0,
|
||||||
|
ensure_started/1,
|
||||||
|
check/1,
|
||||||
|
migrate/1,
|
||||||
|
rollback/2,
|
||||||
|
list_nodes/0]).
|
||||||
|
|
||||||
-define(TABLE, schema_migrations).
|
%%------------------------------------------------------------------------------
|
||||||
|
|
||||||
-spec create_new_migration(atom(), string()) -> any().
|
-spec start_all_mnesia() -> ok | {error, any()}.
|
||||||
create_new_migration(App, Description) ->
|
start_all_mnesia() ->
|
||||||
{{Year, Month, Day}, {Hour, Minute, Second}} = calendar:local_time(),
|
|
||||||
Filename = lists:flatten(io_lib:format("~w~2.2.0w~2.2.0w~2.2.0w~2.2.0w~2.2.0w_", [Year, Month, Day, Hour, Minute, Second]) ++ Description),
|
|
||||||
Path = migresia_migrations:get_priv_dir(App),
|
|
||||||
FullPathAndExtension = filename:join(Path, Filename ++ ".erl"),
|
|
||||||
io:format("Creating new migration: ~p~n", [FullPathAndExtension]),
|
|
||||||
ok = filelib:ensure_dir(<<Path/binary, <<"/">>/binary>>),
|
|
||||||
ok = file:write_file(FullPathAndExtension, io_lib:fwrite("-module(~p).~n-behavior(db_migration).~n-export([up/0, down/0]). ~n~nup() -> ok.~n~ndown() -> throw(<<\"Downgraders not implemented.\">>).", [list_to_atom(Filename)])),
|
|
||||||
io:format("Migration written.~n~n").
|
|
||||||
|
|
||||||
-spec check(atom()) -> ok | {error, any()}.
|
|
||||||
check(App) ->
|
|
||||||
case start_mnesia(false) of
|
|
||||||
ok ->
|
|
||||||
Loaded = migresia_migrations:list_unapplied_ups(App),
|
|
||||||
if Loaded == [] ->
|
|
||||||
[];
|
|
||||||
true ->
|
|
||||||
[ [X||{X,_} <- Loaded] ]
|
|
||||||
end;
|
|
||||||
{error, Error} -> {error, Error}
|
|
||||||
end.
|
|
||||||
|
|
||||||
-spec migrate(atom()) -> ok | {error, any()}.
|
|
||||||
migrate(App) ->
|
|
||||||
case start_mnesia(true) of
|
|
||||||
ok ->
|
|
||||||
case migresia_migrations:ensure_schema_table_exists() of
|
|
||||||
ok ->
|
|
||||||
io:format("Waiting for tables (max timeout 2 minutes)...", []),
|
|
||||||
ok = mnesia:wait_for_tables(mnesia:system_info(tables), 120000),
|
|
||||||
rpc:multicall(migresia_migrations, list_unapplied_ups, [App]), %Basically just to ensure everybody has loaded all the migrations, which is necessary in distributed Mnesia transforms.
|
|
||||||
Loaded = migresia_migrations:list_unapplied_ups(App),
|
|
||||||
lists:foreach(fun execute_up/1, Loaded);
|
|
||||||
{error, Error} -> Error
|
|
||||||
end;
|
|
||||||
{error, Error} -> {error, Error}
|
|
||||||
end.
|
|
||||||
|
|
||||||
-spec rollback(atom(), integer()) -> ok | {error, any()}.
|
|
||||||
rollback(App, Time) ->
|
|
||||||
case start_mnesia(true) of
|
|
||||||
ok ->
|
|
||||||
case migresia_migrations:ensure_schema_table_exists() of
|
|
||||||
ok ->
|
|
||||||
io:format("Waiting for tables (max timeout 2 minutes)...", []),
|
|
||||||
ok = mnesia:wait_for_tables(mnesia:system_info(tables), 120000),
|
|
||||||
rpc:multicall(migresia_migrations, list_all_ups, [App]), %Basically just to ensure everybody has loaded all the migrations, which is necessary in distributed Mnesia transforms.
|
|
||||||
ToRollBack = lists:reverse([X || X<- migresia_migrations:list_all_ups(App), binary_to_integer(element(2, X)) > Time]),
|
|
||||||
lists:foreach(fun execute_down/1, ToRollBack);
|
|
||||||
{error, Error} -> Error
|
|
||||||
end;
|
|
||||||
{error, Error} -> {error, Error}
|
|
||||||
end.
|
|
||||||
|
|
||||||
execute_up({Module, Short}) ->
|
|
||||||
io:format("Executing up in ~s...~n", [Module]),
|
|
||||||
Module:up(),
|
|
||||||
mnesia:dirty_write(schema_migrations, {schema_migrations, Short, true}),
|
|
||||||
io:format(" => done~n", []).
|
|
||||||
|
|
||||||
execute_down({Module, Time}) ->
|
|
||||||
io:format("Executing down in ~s...~n", [Module]),
|
|
||||||
Module:down(),
|
|
||||||
mnesia:dirty_delete(schema_migrations, Time),
|
|
||||||
io:format(" => done~n", []).
|
|
||||||
|
|
||||||
-spec start_mnesia(boolean()) -> ok | {error, any()}.
|
|
||||||
start_mnesia(RemoteToo) ->
|
|
||||||
io:format("Starting Mnesia...~n", []),
|
io:format("Starting Mnesia...~n", []),
|
||||||
case ensure_started(mnesia) of
|
case ensure_started(mnesia) of
|
||||||
Other when Other /= ok -> io:format(" => Error:~p~n", [Other]), Other;
|
ok ->
|
||||||
ok ->
|
ensure_started_on_remotes(list_nodes());
|
||||||
case RemoteToo of
|
Err ->
|
||||||
false -> ok;
|
io:format(" => Error:~p~n", [Err]),
|
||||||
true -> {ResultList, BadNodes} = rpc:multicall(list_nodes(), migresia, ensure_started, [mnesia]),
|
Err
|
||||||
BadStatuses = [X || X <- ResultList, X /= ok],
|
|
||||||
if BadNodes /= [] -> io:format(" => Error:~p~n", [not_all_nodes_running]), {error, not_all_nodes_running};
|
|
||||||
BadStatuses /= [] -> io:format(" => Error:~p~n", [BadStatuses]), {error, BadStatuses};
|
|
||||||
true -> io:format(" => started~n", []), ok
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end.
|
end.
|
||||||
|
|
||||||
list_nodes() ->
|
list_nodes() ->
|
||||||
mnesia:table_info(schema, disc_copies).
|
mnesia:table_info(schema, disc_copies).
|
||||||
|
|
||||||
|
ensure_started_on_remotes(Nodes) ->
|
||||||
|
io:format("Ensuring Mnesia is running on nodes:~n~p~n", [Nodes]),
|
||||||
|
{ResL, BadNodes} = rpc:multicall(Nodes, migresia, ensure_started, [mnesia]),
|
||||||
|
handle_err([X || X <- ResL, X /= ok], BadNodes).
|
||||||
|
|
||||||
|
handle_err([], []) ->
|
||||||
|
io:format(" => started~n", []),
|
||||||
|
ok;
|
||||||
|
handle_err(Results, Bad) ->
|
||||||
|
if Results /= [] -> io:format(" => Error, received: ~p~n", [Results]) end,
|
||||||
|
if Bad /= [] -> io:format(" => Error, bad nodes: ~p~n", [Bad]) end,
|
||||||
|
{error, mnesia_not_started}.
|
||||||
|
|
||||||
-spec ensure_started(atom()) -> ok | {error, any()}.
|
-spec ensure_started(atom()) -> ok | {error, any()}.
|
||||||
ensure_started(App) ->
|
ensure_started(App) ->
|
||||||
case application:start(App) of
|
case application:start(App) of
|
||||||
ok -> ok;
|
ok -> ok;
|
||||||
{error,{already_started,App}} -> ok;
|
{error, {already_started, App}} -> ok;
|
||||||
A -> A
|
{error, _} = Err -> Err
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
%%------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-spec check(atom()) -> ok | {error, any()}.
|
||||||
|
check(App) ->
|
||||||
|
case migresia_migrations:list_unapplied_ups(App) of
|
||||||
|
[] -> [];
|
||||||
|
{error, _} = Err -> Err;
|
||||||
|
Loaded -> [X || {X, _} <- Loaded]
|
||||||
|
end.
|
||||||
|
|
||||||
|
%%------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-spec migrate(atom()) -> ok | {error, any()}.
|
||||||
|
migrate(App) ->
|
||||||
|
migrate(migresia_migrations:init_migrations(), App).
|
||||||
|
|
||||||
|
migrate(ok, App) ->
|
||||||
|
io:format("Waiting for tables (max timeout 2 minutes)...", []),
|
||||||
|
ok = mnesia:wait_for_tables(mnesia:system_info(tables), 120000),
|
||||||
|
Loaded = migresia_migrations:list_unapplied_ups(App),
|
||||||
|
%% Load the transform function on all nodes, see:
|
||||||
|
%% http://toddhalfpenny.com/2012/05/21/possible-erlang-bad-transform-function-solution/
|
||||||
|
rpc:multicall(nodes(), migresia_migrations, list_unapplied_ups, [App]),
|
||||||
|
lists:foreach(fun migresia_migrations:execute_up/1, Loaded);
|
||||||
|
migrate({error, _} = Err, _) ->
|
||||||
|
Err.
|
||||||
|
|
||||||
|
%%------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-spec rollback(atom(), integer()) -> ok | {error, any()}.
|
||||||
|
rollback(App, Time) ->
|
||||||
|
rollback(migresia_migrations:init_migrations(), App, Time).
|
||||||
|
|
||||||
|
rollback(ok, App, Time) ->
|
||||||
|
io:format("Waiting for tables (max timeout 2 minutes)...", []),
|
||||||
|
ok = mnesia:wait_for_tables(mnesia:system_info(tables), 120000),
|
||||||
|
Ups = migresia_migrations:list_all_ups(App),
|
||||||
|
%% Load the transform function on all nodes, see:
|
||||||
|
%% http://toddhalfpenny.com/2012/05/21/possible-erlang-bad-transform-function-solution/
|
||||||
|
rpc:multicall(nodes(), migresia_migrations, list_all_ups, [App]),
|
||||||
|
ToRollBack = lists:reverse([X || {_, Ts, _} = X <- Ups, Ts > Time]),
|
||||||
|
lists:foreach(fun migresia_migrations:execute_down/1, ToRollBack);
|
||||||
|
rollback({error, _} = Err, _App, _Time) ->
|
||||||
|
Err.
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
%% Copyright (c) 2013, Grzegorz Junka
|
%% Copyright (c) 2015, Grzegorz Junka
|
||||||
%% All rights reserved.
|
%% All rights reserved.
|
||||||
%%
|
%%
|
||||||
%% Redistribution and use in source and binary forms, with or without
|
%% Redistribution and use in source and binary forms, with or without
|
||||||
@ -24,57 +24,69 @@
|
|||||||
|
|
||||||
-module(migresia_migrations).
|
-module(migresia_migrations).
|
||||||
|
|
||||||
-export([list_unapplied_ups/1, list_all_ups/1, get_priv_dir/1, ensure_schema_table_exists/0]).
|
-export([init_migrations/0,
|
||||||
|
list_unapplied_ups/1,
|
||||||
|
list_all_ups/1,
|
||||||
|
get_priv_dir/1,
|
||||||
|
execute_up/1,
|
||||||
|
execute_down/1]).
|
||||||
|
|
||||||
-define(DIR, <<"migrate">>).
|
-define(DIR, <<"migrate">>).
|
||||||
-define(TABLE, schema_migrations).
|
-define(TABLE, schema_migrations).
|
||||||
|
|
||||||
-spec list_unapplied_ups(atom()) -> [{module(), binary()}].
|
-type error() :: {error, any()}.
|
||||||
|
-type mod_bin_list() :: [{module(), binary()}].
|
||||||
|
|
||||||
|
%%------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-spec init_migrations() -> ok | error().
|
||||||
|
init_migrations() ->
|
||||||
|
case lists:member(?TABLE, mnesia:system_info(tables)) of
|
||||||
|
true ->
|
||||||
|
ok;
|
||||||
|
false ->
|
||||||
|
io:format("Table schema_migration not found, creating...~n", []),
|
||||||
|
Attr = [{type, ordered_set}, {disc_copies, migresia:list_nodes()}],
|
||||||
|
case mnesia:create_table(?TABLE, Attr) of
|
||||||
|
{atomic, ok} -> io:format(" => created~n", []), ok;
|
||||||
|
{aborted, Reason} -> {error, Reason}
|
||||||
|
end
|
||||||
|
end.
|
||||||
|
|
||||||
|
%%------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-spec list_unapplied_ups(atom()) -> mod_bin_list() | error().
|
||||||
list_unapplied_ups(App) ->
|
list_unapplied_ups(App) ->
|
||||||
get_migrations(get_priv_dir(App)).
|
get_migrations(get_priv_dir(App)).
|
||||||
|
|
||||||
|
-spec list_all_ups(atom()) -> mod_bin_list() | error().
|
||||||
list_all_ups(App) ->
|
list_all_ups(App) ->
|
||||||
get_all_migrations(get_priv_dir(App)).
|
get_all_migrations(get_priv_dir(App)).
|
||||||
|
|
||||||
-spec get_priv_dir(atom()) -> binary().
|
-spec get_priv_dir(atom()) -> string() | binary() | error().
|
||||||
get_priv_dir(App) ->
|
get_priv_dir(App) ->
|
||||||
case application:load(App) of
|
case application:load(App) of
|
||||||
ok -> filename:join(code:priv_dir(App), ?DIR);
|
ok ->
|
||||||
{error, {already_loaded, App}} -> filename:join(code:priv_dir(App), ?DIR);
|
filename:join(code:priv_dir(App), ?DIR);
|
||||||
Error -> Error
|
{error, {already_loaded, App}} ->
|
||||||
|
filename:join(code:priv_dir(App), ?DIR);
|
||||||
|
{error, _} = Err ->
|
||||||
|
Err
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
-spec get_migrations({error, any()} | binary()) -> mod_bin_list() | error().
|
||||||
-spec ensure_schema_table_exists() -> ok | {error, any()}.
|
|
||||||
ensure_schema_table_exists() ->
|
|
||||||
case lists:member(?TABLE, mnesia:system_info(tables)) of
|
|
||||||
true -> ok;
|
|
||||||
false -> io:format("Table schema_migration not found, creating...~n", []),
|
|
||||||
Attr = [{type, ordered_set}, {disc_copies, migresia:list_nodes()}],
|
|
||||||
case mnesia:create_table(?TABLE, Attr) of
|
|
||||||
{atomic, ok} -> io:format(" => created~n", []), ok;
|
|
||||||
{aborted, Reason} -> {error, Reason}
|
|
||||||
end
|
|
||||||
end.
|
|
||||||
|
|
||||||
-spec get_migrations({error, any()} | binary()) -> list().
|
|
||||||
get_migrations({error, _} = Err) ->
|
get_migrations({error, _} = Err) ->
|
||||||
{error, Err};
|
Err;
|
||||||
get_migrations(Dir) ->
|
get_migrations(Dir) ->
|
||||||
ToApply = check_dir(file:list_dir(Dir)),
|
ToApply = check_dir(file:list_dir(Dir)),
|
||||||
case check_table() of
|
case check_table() of
|
||||||
{error, Error} -> {error, Error};
|
{error, _} = Err -> Err;
|
||||||
Applied when is_list(Applied) ->
|
Applied -> compile_and_load(Dir, ToApply, Applied)
|
||||||
ToExecute = compile_unapplied(Dir, ToApply, Applied, []),
|
|
||||||
Fun = fun({Module, Short, Binary}) -> load_migration(Module, Short, Binary) end,
|
|
||||||
lists:map(Fun, ToExecute)
|
|
||||||
end.
|
end.
|
||||||
|
|
||||||
get_all_migrations(Dir) ->
|
get_all_migrations(Dir) ->
|
||||||
ToApply = lists:sort(check_dir(file:list_dir(Dir))),
|
ToApply = lists:sort(check_dir(file:list_dir(Dir))),
|
||||||
ToExecute = compile_unapplied(Dir, ToApply, [], []),
|
compile_and_load(Dir, ToApply, []).
|
||||||
Fun = fun({Module, Short, Binary}) -> load_migration(Module, Short, Binary) end,
|
|
||||||
lists:map(Fun, ToExecute).
|
|
||||||
|
|
||||||
check_dir({error, Reason}) ->
|
check_dir({error, Reason}) ->
|
||||||
throw({file, list_dir, Reason});
|
throw({file, list_dir, Reason});
|
||||||
@ -84,9 +96,11 @@ check_dir({ok, Filenames}) ->
|
|||||||
normalize_names([<<Short:14/bytes, ".erl">>|T], Acc) ->
|
normalize_names([<<Short:14/bytes, ".erl">>|T], Acc) ->
|
||||||
normalize_names(T, [{Short, Short}|Acc]);
|
normalize_names(T, [{Short, Short}|Acc]);
|
||||||
normalize_names([<<Short:14/bytes, $_, R/binary>> = Name|T], Acc)
|
normalize_names([<<Short:14/bytes, $_, R/binary>> = Name|T], Acc)
|
||||||
when size(R) >= 4 andalso erlang:binary_part(R, size(R) - 4, 4) == <<".erl">> ->
|
when size(R) >= 4
|
||||||
|
andalso erlang:binary_part(R, size(R) - 4, 4) == <<".erl">> ->
|
||||||
Base = erlang:binary_part(Name, 0, size(Name) - 4),
|
Base = erlang:binary_part(Name, 0, size(Name) - 4),
|
||||||
normalize_names(T, [{Short, Base}|Acc]);
|
Int = list_to_integer(binary_to_list(Short)),
|
||||||
|
normalize_names(T, [{Int, Base}|Acc]);
|
||||||
normalize_names([Name|T], Acc) when is_list(Name) ->
|
normalize_names([Name|T], Acc) when is_list(Name) ->
|
||||||
normalize_names([list_to_binary(Name)|T], Acc);
|
normalize_names([list_to_binary(Name)|T], Acc);
|
||||||
normalize_names([Name|T], Acc) ->
|
normalize_names([Name|T], Acc) ->
|
||||||
@ -95,7 +109,6 @@ normalize_names([Name|T], Acc) ->
|
|||||||
normalize_names([], Acc) ->
|
normalize_names([], Acc) ->
|
||||||
lists:sort(Acc).
|
lists:sort(Acc).
|
||||||
|
|
||||||
|
|
||||||
check_table() ->
|
check_table() ->
|
||||||
case lists:member(?TABLE, mnesia:system_info(tables)) of
|
case lists:member(?TABLE, mnesia:system_info(tables)) of
|
||||||
false ->
|
false ->
|
||||||
@ -107,11 +120,22 @@ check_table() ->
|
|||||||
io:format(" => done~n", []),
|
io:format(" => done~n", []),
|
||||||
Select = [{{?TABLE,'_','_'},[],['$_']}],
|
Select = [{{?TABLE,'_','_'},[],['$_']}],
|
||||||
List = mnesia:dirty_select(?TABLE, Select),
|
List = mnesia:dirty_select(?TABLE, Select),
|
||||||
[ X || {schema_migrations, X, true} <- List ];
|
[ X || {?TABLE, X, true} <- List ];
|
||||||
Error -> {error, Error}
|
{error, _} = Err ->
|
||||||
|
Err;
|
||||||
|
Error ->
|
||||||
|
{error, Error}
|
||||||
end
|
end
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
compile_and_load(Dir, ToApply, Applied) ->
|
||||||
|
ToExecute = compile_unapplied(Dir, ToApply, Applied, []),
|
||||||
|
Fun = fun({Module, Short, Binary}) ->
|
||||||
|
load_migration(Module, Short, Binary)
|
||||||
|
end,
|
||||||
|
lists:map(Fun, ToExecute).
|
||||||
|
|
||||||
|
%%------------------------------------------------------------------------------
|
||||||
|
|
||||||
compile_unapplied(Dir, [{Short, Module}|TN], [] = Old, Acc) ->
|
compile_unapplied(Dir, [{Short, Module}|TN], [] = Old, Acc) ->
|
||||||
compile_unapplied(Dir, TN, Old, [compile_file(Dir, Short, Module)|Acc]);
|
compile_unapplied(Dir, TN, Old, [compile_file(Dir, Short, Module)|Acc]);
|
||||||
@ -137,19 +161,30 @@ compile_file(Dir, Short, Name) ->
|
|||||||
{ok, Module, Binary, Warnings} ->
|
{ok, Module, Binary, Warnings} ->
|
||||||
io:format("Warnings: ~p~n", [Warnings]),
|
io:format("Warnings: ~p~n", [Warnings]),
|
||||||
{Module, Short, Binary};
|
{Module, Short, Binary};
|
||||||
{error, Errors, Warnings} ->
|
{error, Err, Warn} ->
|
||||||
io:format("Warnings: ~p~nErrors: ~p~nExiting...~n", [Warnings, Errors]),
|
io:format("Warnings: ~p~nErrors: ~p~nAborting...~n", [Warn, Err]),
|
||||||
throw(Errors);
|
throw({compile, compile_error, Err});
|
||||||
error ->
|
error ->
|
||||||
io:format("Unknown error encoutered, Exiting...~n", []),
|
io:format("Unknown error encoutered, Aborting...~n", []),
|
||||||
throw({compile, file, error})
|
throw({compile, unknown_error, File})
|
||||||
end.
|
end.
|
||||||
|
|
||||||
load_migration(Module, Short, Binary) ->
|
load_migration(Module, Short, Binary) ->
|
||||||
case code:load_binary(Module, Module, Binary) of
|
case code:load_binary(Module, Module, Binary) of
|
||||||
{module, Module} ->
|
{module, Module} -> {Module, Short};
|
||||||
{Module, Short};
|
{error, What} -> throw({code, load_binary, What})
|
||||||
{error, What} ->
|
|
||||||
throw({code, load_binary, What})
|
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
%%------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
execute_up({Module, Ts}) ->
|
||||||
|
io:format("Executing up in ~s...~n", [Module]),
|
||||||
|
Module:up(),
|
||||||
|
mnesia:dirty_write(?TABLE, {?TABLE, Ts, true}),
|
||||||
|
io:format(" => done~n", []).
|
||||||
|
|
||||||
|
execute_down({Module, Ts}) ->
|
||||||
|
io:format("Executing down in ~s...~n", [Module]),
|
||||||
|
Module:down(),
|
||||||
|
mnesia:dirty_delete(?TABLE, Ts),
|
||||||
|
io:format(" => done~n", []).
|
||||||
|
Reference in New Issue
Block a user