Skip to content

Commit

Permalink
Merge 0fed0b7 into 83145e6
Browse files Browse the repository at this point in the history
  • Loading branch information
bearmug committed Jan 30, 2019
2 parents 83145e6 + 0fed0b7 commit a68fef3
Show file tree
Hide file tree
Showing 8 changed files with 171 additions and 150 deletions.
5 changes: 5 additions & 0 deletions Makefile
Expand Up @@ -4,6 +4,8 @@ all: clean code-checks test cover

travis: all coveralls

local: all format

clean:
$(REBAR) clean

Expand All @@ -22,3 +24,6 @@ cover:

coveralls:
$(REBAR) as test coveralls send

format:
$(REBAR) fmt
30 changes: 30 additions & 0 deletions elvis.config
@@ -0,0 +1,30 @@
[
{
elvis,
[
{config,
#{src_dirs => ["src"],
rules => [{elvis_style, line_length, [120]},
{elvis_style, no_tabs, []},
{elvis_style, macro_names, []},
{elvis_style, macro_module_names, []},
{elvis_style, operator_spaces, [{right, ","},
{right, "++"},
{left, "++"}]},
{elvis_style, nesting_level, [3]},
{elvis_style, god_modules, [25]},
{elvis_style, no_if_expression, []},
{elvis_style, invalid_dynamic_call, [elvis]},
{elvis_style, used_ignored_variable, []},
{elvis_style, no_behavior_info, []},
{
elvis_style,
module_naming_convention,
["^([a-z][a-z0-9]*_?)*(_SUITE)?$", []]
}
]
}
}
]
}
].
54 changes: 20 additions & 34 deletions rebar.config
@@ -1,36 +1,22 @@
{profiles, [
{test, [
{deps, [
{erlexec, {git, "https://github.com/saleyn/erlexec.git", {ref, "576fb5d"}}}
]},
{eunit_opts , [verbose]},
{cover_enabled , true},
{cover_print_enabled , true},
{cover_export_enabled , true},
{coveralls_coverdata , "_build/test/cover/ct.coverdata"},
{coveralls_service_name , "travis-ci"},
{plugins , [coveralls]}
]},
{lint, [
{plugins, [rebar3_lint]}
]}
]}.

{elvis,
[#{dirs => ["src"],
include_dirs => [],
filter => "*.erl",
ruleset => erl_files,
rules =>
[{elvis_style, line_length, #{limit => 120}},
{elvis_style, god_modules, #{limit => 40}},
{elvis_style, state_record_and_type, disable} % epgsql_sock
]}
]
}.


{test, [
{deps, [
{erlexec, {git, "https://github.com/saleyn/erlexec.git", {ref, "576fb5d"}}}
]},
{eunit_opts , [verbose]},
{cover_enabled , true},
{cover_print_enabled , true},
{cover_export_enabled , true},
{coveralls_coverdata , "_build/test/cover/ct.coverdata"},
{coveralls_service_name , "travis-ci"},
{plugins , [coveralls]}
]},
{lint, [
{plugins, [rebar3_lint]}
]}
]}.
{plugins, [rebar3_fmt]}.
{dialyzer,
[
{plt_location, "_build/plt"}
]}.
[
{plt_location, "_build/plt"}
]}.
12 changes: 6 additions & 6 deletions rebar.config.script
@@ -1,7 +1,7 @@
case os:getenv("TRAVIS") of
"true" ->
JobId = os:getenv("TRAVIS_JOB_ID"),
lists:keystore(coveralls_service_job_id, 1, CONFIG, {coveralls_service_job_id, JobId});
_ ->
CONFIG
end.
"true" ->
JobId = os:getenv("TRAVIS_JOB_ID"),
lists:keystore(coveralls_service_job_id, 1, CONFIG, {coveralls_service_job_id, JobId});
_ ->
CONFIG
end.
6 changes: 3 additions & 3 deletions src/dialect_postgres.erl
Expand Up @@ -3,11 +3,11 @@
-export([init/0, migrations_names/0, save_migration/2, latest_existing_version/0]).

init() ->
"CREATE TABLE IF NOT EXISTS database_migrations_history (
"CREATE TABLE IF NOT EXISTS database_migrations_history (
version INTEGER NOT NULL PRIMARY KEY,
filename TEXT NOT NULL,
creation_timestamp TIMESTAMP NOT NULL DEFAULT NOW()
)".
)".

migrations_names() ->
"SELECT version, filename FROM database_migrations_history".
Expand All @@ -18,4 +18,4 @@ save_migration(Version, Filename) ->
[Version, Filename])).

latest_existing_version() ->
"SELECT max(version) FROM database_migrations_history".
"SELECT max(version) FROM database_migrations_history".
68 changes: 34 additions & 34 deletions src/engine.erl
Expand Up @@ -5,50 +5,50 @@
-type error() :: {error, Type :: atom(), Details :: any()}.

-spec migrate(
Path :: nonempty_string(),
FTx :: fun((F) -> ok | error()),
FQuery :: fun((nonempty_string()) -> ok | list(string()) | integer() | error())) -> R
when
F :: fun(() -> ok | error()),
R :: fun(() -> ok | error()).
Path :: nonempty_string(),
FTx :: fun((F) -> ok | error()),
FQuery :: fun((nonempty_string()) -> ok | list(string()) | integer() | error())) -> R
when
F :: fun(() -> ok | error()),
R :: fun(() -> ok | error()).
migrate(Path, FTx, FQuery) ->
ok = FQuery(dialect_postgres:init()),
fun() -> FTx(flatten(
map(
find_migrations(Path, FQuery),
fun({V, F}) -> do_migration(Path, FQuery, {V, F}) end),
fun(M)-> ok = M() end))
end.
ok = FQuery(dialect_postgres:init()),
fun() -> FTx(flatten(
map(
find_migrations(Path, FQuery),
fun({V, F}) -> do_migration(Path, FQuery, {V, F}) end),
fun(M)-> ok = M() end))
end.

do_migration(Path, FQuery, {Version, FileName}) ->
Version = FQuery(dialect_postgres:latest_existing_version()) + 1,
ScriptPath = filename:join(Path, FileName),
compose(
fun() -> file:read_file(ScriptPath) end,
fun({ok, ScriptBody}) ->
ok = FQuery(ScriptBody),
ok = FQuery(dialect_postgres:save_migration(Version, FileName))
end
).
Version = FQuery(dialect_postgres:latest_existing_version()) + 1,
ScriptPath = filename:join(Path, FileName),
compose(
fun() -> file:read_file(ScriptPath) end,
fun({ok, ScriptBody}) ->
ok = FQuery(ScriptBody),
ok = FQuery(dialect_postgres:save_migration(Version, FileName))
end
).

find_migrations(ScriptsLocation, FQuery) ->
MigrationsDone = sets:from_list(FQuery(dialect_postgres:migrations_names())),
compose(
fun() -> file:list_dir_all(ScriptsLocation) end,
fun({ok, Files}) -> lists:filter(
fun(N) -> not sets:is_element(N, MigrationsDone) end,
lists:keysort(1, [
{list_to_integer(head(string:split(F, "_"))), F} || F <- Files]))
end
).
MigrationsDone = sets:from_list(FQuery(dialect_postgres:migrations_names())),
compose(
fun() -> file:list_dir_all(ScriptsLocation) end,
fun({ok, Files}) -> lists:filter(
fun(N) -> not sets:is_element(N, MigrationsDone) end,
lists:keysort(1, [
{list_to_integer(head(string:split(F, "_"))), F} || F <- Files]))
end
).

head([H|_]) -> H.

compose(F1, F2) ->
fun() -> F2(F1()) end.
fun() -> F2(F1()) end.

map(Generate, Map) ->
fun() -> [Map(R) || R <- Generate()] end.
fun() -> [Map(R) || R <- Generate()] end.

flatten(Generate, Flatten) ->
fun() -> [Flatten(R) || R <- Generate()] end.
fun() -> [Flatten(R) || R <- Generate()] end.
22 changes: 11 additions & 11 deletions src/pure_migrations.app.src
@@ -1,12 +1,12 @@
{application, pure_migrations,
[{description, "Database Pure Migration Tool"},
{vsn, "0.1"},
{licenses, ["MIT"]},
{registered, []},
{modules, []},
{applications, [
kernel,
stdlib
]},
{env, []}
]}.
[{description, "Database Pure Migration Tool"},
{vsn, "0.1"},
{licenses, ["MIT"]},
{registered, []},
{modules, []},
{applications, [
kernel,
stdlib
]},
{env, []}
]}.
124 changes: 62 additions & 62 deletions test/pure_migrations_SUITE.erl
Expand Up @@ -6,81 +6,81 @@
-compile(export_all).

all() -> [
wrong_filename_test,
regular_upgrade_test,
rewrite_version_test,
faulty_script_test,
start_not_from_zero_test,
versions_gap_test,
negative_version_test
].
wrong_filename_test,
regular_upgrade_test,
rewrite_version_test,
faulty_script_test,
start_not_from_zero_test,
versions_gap_test,
negative_version_test
].

wrong_filename_test(Opts) ->
PreparedCall = engine:migrate(
filename:join([?config(data_dir, Opts), "01-invalid-script-name"]),
fun(F) -> F() end,
query_fun([], ok)
),
?assertError(badarg, PreparedCall()).
PreparedCall = engine:migrate(
filename:join([?config(data_dir, Opts), "01-invalid-script-name"]),
fun(F) -> F() end,
query_fun([], ok)
),
?assertError(badarg, PreparedCall()).

regular_upgrade_test(Opts) ->
PreparedCall = engine:migrate(
filename:join([?config(data_dir, Opts), "02-regular-upgrade"]),
fun(F) -> F() end,
query_fun([], ok)
),
?assertEqual([ok], PreparedCall()).
PreparedCall = engine:migrate(
filename:join([?config(data_dir, Opts), "02-regular-upgrade"]),
fun(F) -> F() end,
query_fun([], ok)
),
?assertEqual([ok], PreparedCall()).

rewrite_version_test(Opts) ->
PreparedCall = engine:migrate(
filename:join([?config(data_dir, Opts), "03-rewrite-version"]),
fun(F) -> F() end,
query_fun([{0, "00_very_first_script.sql"}], ok)
),
?assertError({badmatch, 1}, PreparedCall()).
PreparedCall = engine:migrate(
filename:join([?config(data_dir, Opts), "03-rewrite-version"]),
fun(F) -> F() end,
query_fun([{0, "00_very_first_script.sql"}], ok)
),
?assertError({badmatch, 1}, PreparedCall()).

faulty_script_test(Opts) ->
PreparedCall = engine:migrate(
filename:join([?config(data_dir, Opts), "00-default"]),
fun(F) -> F() end,
query_fun([], {error, system_fault, "Please check database connectivity"})
),
?assertError({badmatch, {
error, system_fault, "Please check database connectivity"
}}, PreparedCall()).
PreparedCall = engine:migrate(
filename:join([?config(data_dir, Opts), "00-default"]),
fun(F) -> F() end,
query_fun([], {error, system_fault, "Please check database connectivity"})
),
?assertError({badmatch, {
error, system_fault, "Please check database connectivity"
}}, PreparedCall()).

start_not_from_zero_test(Opts) ->
PreparedCall = engine:migrate(
filename:join([?config(data_dir, Opts), "04-invalid-start-version"]),
fun(F) -> F() end,
query_fun([], ok)
),
?assertError({badmatch, 0}, PreparedCall()).
PreparedCall = engine:migrate(
filename:join([?config(data_dir, Opts), "04-invalid-start-version"]),
fun(F) -> F() end,
query_fun([], ok)
),
?assertError({badmatch, 0}, PreparedCall()).

versions_gap_test(Opts) ->
PreparedCall = engine:migrate(
filename:join([?config(data_dir, Opts), "04-invalid-start-version"]),
fun(F) -> F() end,
query_fun([{0, "00_very_first_script.sql"}], ok)
),
?assertError({badmatch, 1}, PreparedCall()).
PreparedCall = engine:migrate(
filename:join([?config(data_dir, Opts), "04-invalid-start-version"]),
fun(F) -> F() end,
query_fun([{0, "00_very_first_script.sql"}], ok)
),
?assertError({badmatch, 1}, PreparedCall()).

negative_version_test(Opts) ->
PreparedCall = engine:migrate(
filename:join([?config(data_dir, Opts), "05-negative-version"]),
fun(F) -> F() end,
query_fun([], ok)
),
?assertError({badmatch, 0}, PreparedCall()).
PreparedCall = engine:migrate(
filename:join([?config(data_dir, Opts), "05-negative-version"]),
fun(F) -> F() end,
query_fun([], ok)
),
?assertError({badmatch, 0}, PreparedCall()).

query_fun(ExistingVersions, MigrationResponse) ->
fun(Q) ->
case Q of
"CREATE" ++ _Tail -> ok;
"SELECT version" ++ _Tail -> ExistingVersions;
"SELECT max" ++ _Tail -> length(ExistingVersions) - 1;
"INSERT" ++ _Tail -> ok;
<<"CREATE TABLE fruit (\n name TEXT\n);">> -> MigrationResponse;
true -> throw("Unknown calls not expected")
end
end.
fun(Q) ->
case Q of
"CREATE" ++ _Tail -> ok;
"SELECT version" ++ _Tail -> ExistingVersions;
"SELECT max" ++ _Tail -> length(ExistingVersions) - 1;
"INSERT" ++ _Tail -> ok;
<<"CREATE TABLE fruit (\n name TEXT\n);">> -> MigrationResponse;
true -> throw("Unknown calls not expected")
end
end.

0 comments on commit a68fef3

Please sign in to comment.