diff --git a/.awconfig b/.awconfig new file mode 100644 index 0000000..ed97d53 --- /dev/null +++ b/.awconfig @@ -0,0 +1 @@ +--- diff --git a/CHANGELOG.md b/CHANGELOG.md index b05335b..ecadf66 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ **Closed issues:** +- Bump version to 0.1.0 [\#49](https://github.com/inaka/cowboy-trails/issues/49) - Add Meta Testing [\#46](https://github.com/inaka/cowboy-trails/issues/46) - Allow the user to set a global api-root path [\#42](https://github.com/inaka/cowboy-trails/issues/42) - Improve Example [\#27](https://github.com/inaka/cowboy-trails/issues/27) @@ -16,6 +17,7 @@ **Merged pull requests:** +- \[Fix \#49\] Bump version to 0.1.0 [\#51](https://github.com/inaka/cowboy-trails/pull/51) ([harenson](https://github.com/harenson)) - \[Fix \#19\] Allow more than one server running on the same node [\#50](https://github.com/inaka/cowboy-trails/pull/50) ([harenson](https://github.com/harenson)) - \[Fix \#46\] Add meta testing [\#48](https://github.com/inaka/cowboy-trails/pull/48) ([harenson](https://github.com/harenson)) - Allow the user to set and get global api-root path [\#47](https://github.com/inaka/cowboy-trails/pull/47) ([harenson](https://github.com/harenson)) diff --git a/Makefile b/Makefile index f17a5aa..9438106 100644 --- a/Makefile +++ b/Makefile @@ -1,27 +1,24 @@ PROJECT = trails DEPS = cowboy ranch -TEST_DEPS = xref_runner katana mixer elvis meck +TEST_DEPS = katana mixer meck SHELL_DEPS = sync +BUILD_DEPS = inaka_mk hexer_mk dep_cowboy = git https://github.com/ninenines/cowboy.git 1.0.4 dep_ranch = git https://github.com/ninenines/ranch.git 1.2.0 -dep_sync = git https://github.com/rustyio/sync.git 9c78e7b -dep_xref_runner = git https://github.com/inaka/xref_runner.git 0.2.2 +dep_sync = git https://github.com/rustyio/sync.git 9c78e7b dep_mixer = git https://github.com/inaka/mixer.git 0.1.4 -dep_elvis = git https://github.com/inaka/elvis.git b69eea4 -dep_katana = git https://github.com/inaka/erlang-katana.git 07efe94 -dep_meck = git https://github.com/eproxus/meck 0.8.3 +dep_katana = hex 0.2.18 +dep_meck = hex 0.8.4 +dep_inaka_mk = git https://github.com/inaka/inaka.mk.git 1.0.0 +dep_hexer_mk = git https://github.com/inaka/hexer.mk.git 1.0.0 -include erlang.mk - -CT_OPTS = -cover test/trails.coverspec -erl_args +DEP_PLUGINS = inaka_mk hexer_mk -LOCAL_DEPS := xmerl tools compiler syntax_tools common_test inets crypto ssl public_key test_server dialyzer wx -DIALYZER_DIRS := ebin/ test/ -DIALYZER_OPTS := --verbose --statistics -Wunmatched_returns +include erlang.mk -ERLC_OPTS += +warn_unused_vars +warn_export_all +warn_shadow_vars +warn_unused_import +warn_unused_function +ERLC_OPTS := +warn_unused_vars +warn_export_all +warn_shadow_vars +warn_unused_import +warn_unused_function ERLC_OPTS += +warn_bif_clash +warn_unused_record +warn_deprecated_function +warn_obsolete_guard +strict_validation ERLC_OPTS += +warn_export_vars +warn_exported_vars +warn_missing_spec +warn_untyped_record +debug_info @@ -29,17 +26,4 @@ TEST_ERLC_OPTS += +debug_info SHELL_OPTS = -s sync -quicktests: app - @$(MAKE) --no-print-directory app-build test-dir ERLC_OPTS="$(TEST_ERLC_OPTS)" - $(verbose) mkdir -p $(CURDIR)/logs/ - $(gen_verbose) $(CT_RUN) -suite $(addsuffix _SUITE,$(CT_SUITES)) $(CT_OPTS) - -test-build-plt: ERLC_OPTS=$(TEST_ERLC_OPTS) -test-build-plt: - @$(MAKE) --no-print-directory test-dir ERLC_OPTS="$(TEST_ERLC_OPTS)" - $(gen_verbose) touch ebin/test - -plt-all: PLT_APPS := $(TEST_DEPS) -plt-all: test-deps test-build-plt plt - -dialyze-all: app test-build-plt dialyze +CT_OPTS = -cover test/cover.spec diff --git a/elvis.config b/elvis.config index bd2d558..c7594d6 100644 --- a/elvis.config +++ b/elvis.config @@ -17,7 +17,7 @@ {elvis_style, nesting_level, #{level => 3}}, {elvis_style, god_modules, #{limit => 25}}, {elvis_style, no_if_expression}, - {elvis_style, invalid_dynamic_call, #{ignore => [elvis]}}, + {elvis_style, invalid_dynamic_call}, {elvis_style, used_ignored_variable}, {elvis_style, no_behavior_info}, { @@ -26,20 +26,26 @@ #{regex => "^([a-z][a-z0-9]*_?)*(_SUITE)?$", ignore => []} }, + { + elvis_style, + function_naming_convention, + #{regex => "^([a-z][a-z0-9]*_?)*$"} + }, {elvis_style, state_record_and_type}, {elvis_style, no_spec_with_records}, - {elvis_style, dont_repeat_yourself, #{min_complexity => 10}} + {elvis_style, dont_repeat_yourself, #{min_complexity => 10}}, + {elvis_style, no_debug_call} ] }, #{dirs => ["."], filter => "Makefile", - rules => [{elvis_project, no_deps_master_erlang_mk, #{ignore => []}}, - {elvis_project, git_for_deps_erlang_mk, #{regex => "^https://.*"}}] + rules => [{elvis_project, no_deps_master_erlang_mk}, + {elvis_project, protocol_for_deps_erlang_mk, #{regex => "(https://.*|[0-9]+([.][0-9]+)*)"}}] }, #{dirs => ["."], filter => "rebar.config", - rules => [{elvis_project, no_deps_master_rebar, #{ignore => []}}, - {elvis_project, git_for_deps_rebar, #{regex => "^https://.*"}}] + rules => [{elvis_project, no_deps_master_rebar}, + {elvis_project, protocol_for_deps_rebar}] }, #{dirs => ["."], filter => "elvis.config", diff --git a/erlang.mk b/erlang.mk index bf13c4d..b60edb3 100644 --- a/erlang.mk +++ b/erlang.mk @@ -16,7 +16,7 @@ ERLANG_MK_FILENAME := $(realpath $(lastword $(MAKEFILE_LIST))) -ERLANG_MK_VERSION = 2.0.0-pre.2-12-g9703566 +ERLANG_MK_VERSION = 2.0.0-pre.2-60-g1e6fc7b # Core configuration. @@ -84,7 +84,7 @@ all:: deps app rel rel:: $(verbose) : -check:: clean app tests +check:: tests clean:: clean-crashdump @@ -883,14 +883,6 @@ pkg_dh_date_fetch = git pkg_dh_date_repo = https://github.com/daleharvey/dh_date pkg_dh_date_commit = master -PACKAGES += dhtcrawler -pkg_dhtcrawler_name = dhtcrawler -pkg_dhtcrawler_description = dhtcrawler is a DHT crawler written in erlang. It can join a DHT network and crawl many P2P torrents. -pkg_dhtcrawler_homepage = https://github.com/kevinlynx/dhtcrawler -pkg_dhtcrawler_fetch = git -pkg_dhtcrawler_repo = https://github.com/kevinlynx/dhtcrawler -pkg_dhtcrawler_commit = master - PACKAGES += dirbusterl pkg_dirbusterl_name = dirbusterl pkg_dirbusterl_description = DirBuster successor in Erlang @@ -1137,7 +1129,7 @@ pkg_elvis_description = Erlang Style Reviewer pkg_elvis_homepage = https://github.com/inaka/elvis pkg_elvis_fetch = git pkg_elvis_repo = https://github.com/inaka/elvis -pkg_elvis_commit = 0.2.4 +pkg_elvis_commit = master PACKAGES += emagick pkg_emagick_name = emagick @@ -1779,6 +1771,14 @@ pkg_geef_fetch = git pkg_geef_repo = https://github.com/carlosmn/geef pkg_geef_commit = master +PACKAGES += gen_coap +pkg_gen_coap_name = gen_coap +pkg_gen_coap_description = Generic Erlang CoAP Client/Server +pkg_gen_coap_homepage = https://github.com/gotthardp/gen_coap +pkg_gen_coap_fetch = git +pkg_gen_coap_repo = https://github.com/gotthardp/gen_coap +pkg_gen_coap_commit = master + PACKAGES += gen_cycle pkg_gen_cycle_name = gen_cycle pkg_gen_cycle_description = Simple, generic OTP behaviour for recurring tasks @@ -1979,6 +1979,14 @@ pkg_hyper_fetch = git pkg_hyper_repo = https://github.com/GameAnalytics/hyper pkg_hyper_commit = master +PACKAGES += i18n +pkg_i18n_name = i18n +pkg_i18n_description = International components for unicode from Erlang (unicode, date, string, number, format, locale, localization, transliteration, icu4e) +pkg_i18n_homepage = https://github.com/erlang-unicode/i18n +pkg_i18n_fetch = git +pkg_i18n_repo = https://github.com/erlang-unicode/i18n +pkg_i18n_commit = master + PACKAGES += ibrowse pkg_ibrowse_name = ibrowse pkg_ibrowse_description = Erlang HTTP client @@ -2499,6 +2507,14 @@ pkg_merl_fetch = git pkg_merl_repo = https://github.com/richcarl/merl pkg_merl_commit = master +PACKAGES += mimerl +pkg_mimerl_name = mimerl +pkg_mimerl_description = library to handle mimetypes +pkg_mimerl_homepage = https://github.com/benoitc/mimerl +pkg_mimerl_fetch = git +pkg_mimerl_repo = https://github.com/benoitc/mimerl +pkg_mimerl_commit = master + PACKAGES += mimetypes pkg_mimetypes_name = mimetypes pkg_mimetypes_description = Erlang MIME types library @@ -2731,14 +2747,6 @@ pkg_oauth2_fetch = git pkg_oauth2_repo = https://github.com/kivra/oauth2 pkg_oauth2_commit = master -PACKAGES += oauth2c -pkg_oauth2c_name = oauth2c -pkg_oauth2c_description = Erlang OAuth2 Client -pkg_oauth2c_homepage = https://github.com/kivra/oauth2_client -pkg_oauth2c_fetch = git -pkg_oauth2c_repo = https://github.com/kivra/oauth2_client -pkg_oauth2c_commit = master - PACKAGES += octopus pkg_octopus_name = octopus pkg_octopus_description = Small and flexible pool manager written in Erlang @@ -3905,7 +3913,7 @@ pkg_xref_runner_description = Erlang Xref Runner (inspired in rebar xref) pkg_xref_runner_homepage = https://github.com/inaka/xref_runner pkg_xref_runner_fetch = git pkg_xref_runner_repo = https://github.com/inaka/xref_runner -pkg_xref_runner_commit = 0.2.0 +pkg_xref_runner_commit = 0.2.3 PACKAGES += yamerl pkg_yamerl_name = yamerl @@ -4090,7 +4098,10 @@ endif # While Makefile file could be GNUmakefile or makefile, # in practice only Makefile is needed so far. define dep_autopatch - if [ -f $(DEPS_DIR)/$(1)/Makefile ]; then \ + if [ -f $(DEPS_DIR)/$(1)/erlang.mk ]; then \ + $(call erlang,$(call dep_autopatch_appsrc.erl,$(1))); \ + $(call dep_autopatch_erlang_mk,$(1)); \ + elif [ -f $(DEPS_DIR)/$(1)/Makefile ]; then \ if [ 0 != `grep -c "include ../\w*\.mk" $(DEPS_DIR)/$(1)/Makefile` ]; then \ $(call dep_autopatch2,$(1)); \ elif [ 0 != `grep -ci rebar $(DEPS_DIR)/$(1)/Makefile` ]; then \ @@ -4098,12 +4109,7 @@ define dep_autopatch elif [ -n "`find $(DEPS_DIR)/$(1)/ -type f -name \*.mk -not -name erlang.mk -exec grep -i rebar '{}' \;`" ]; then \ $(call dep_autopatch2,$(1)); \ else \ - if [ -f $(DEPS_DIR)/$(1)/erlang.mk ]; then \ - $(call erlang,$(call dep_autopatch_appsrc.erl,$(1))); \ - $(call dep_autopatch_erlang_mk,$(1)); \ - else \ - $(call erlang,$(call dep_autopatch_app.erl,$(1))); \ - fi \ + $(call erlang,$(call dep_autopatch_app.erl,$(1))); \ fi \ else \ if [ ! -d $(DEPS_DIR)/$(1)/src/ ]; then \ @@ -4115,8 +4121,11 @@ define dep_autopatch endef define dep_autopatch2 + if [ -f $(DEPS_DIR)/$1/src/$1.app.src.script ]; then \ + $(call erlang,$(call dep_autopatch_appsrc_script.erl,$(1))); \ + fi; \ $(call erlang,$(call dep_autopatch_appsrc.erl,$(1))); \ - if [ -f $(DEPS_DIR)/$(1)/rebar.config -o -f $(DEPS_DIR)/$(1)/rebar.config.script ]; then \ + if [ -f $(DEPS_DIR)/$(1)/rebar -o -f $(DEPS_DIR)/$(1)/rebar.config -o -f $(DEPS_DIR)/$(1)/rebar.config.script ]; then \ $(call dep_autopatch_fetch_rebar); \ $(call dep_autopatch_rebar,$(1)); \ else \ @@ -4254,57 +4263,6 @@ define dep_autopatch_rebar.erl Write(io_lib:format("COMPILE_FIRST +=~s\n", [Names])) end end(), - FindFirst = fun(F, Fd) -> - case io:parse_erl_form(Fd, undefined) of - {ok, {attribute, _, compile, {parse_transform, PT}}, _} -> - [PT, F(F, Fd)]; - {ok, {attribute, _, compile, CompileOpts}, _} when is_list(CompileOpts) -> - case proplists:get_value(parse_transform, CompileOpts) of - undefined -> [F(F, Fd)]; - PT -> [PT, F(F, Fd)] - end; - {ok, {attribute, _, include, Hrl}, _} -> - case file:open("$(call core_native_path,$(DEPS_DIR)/$1/include/)" ++ Hrl, [read]) of - {ok, HrlFd} -> [F(F, HrlFd), F(F, Fd)]; - _ -> - case file:open("$(call core_native_path,$(DEPS_DIR)/$1/src/)" ++ Hrl, [read]) of - {ok, HrlFd} -> [F(F, HrlFd), F(F, Fd)]; - _ -> [F(F, Fd)] - end - end; - {ok, {attribute, _, include_lib, "$(1)/include/" ++ Hrl}, _} -> - {ok, HrlFd} = file:open("$(call core_native_path,$(DEPS_DIR)/$1/include/)" ++ Hrl, [read]), - [F(F, HrlFd), F(F, Fd)]; - {ok, {attribute, _, include_lib, Hrl}, _} -> - case file:open("$(call core_native_path,$(DEPS_DIR)/$1/include/)" ++ Hrl, [read]) of - {ok, HrlFd} -> [F(F, HrlFd), F(F, Fd)]; - _ -> [F(F, Fd)] - end; - {ok, {attribute, _, import, {Imp, _}}, _} -> - case file:open("$(call core_native_path,$(DEPS_DIR)/$1/src/)" ++ atom_to_list(Imp) ++ ".erl", [read]) of - {ok, ImpFd} -> [Imp, F(F, ImpFd), F(F, Fd)]; - _ -> [F(F, Fd)] - end; - {eof, _} -> - file:close(Fd), - []; - _ -> - F(F, Fd) - end - end, - fun() -> - ErlFiles = filelib:wildcard("$(call core_native_path,$(DEPS_DIR)/$1/src/)*.erl"), - First0 = lists:usort(lists:flatten([begin - {ok, Fd} = file:open(F, [read]), - FindFirst(FindFirst, Fd) - end || F <- ErlFiles])), - First = lists:flatten([begin - {ok, Fd} = file:open("$(call core_native_path,$(DEPS_DIR)/$1/src/)" ++ atom_to_list(M) ++ ".erl", [read]), - FindFirst(FindFirst, Fd) - end || M <- First0, lists:member("$(call core_native_path,$(DEPS_DIR)/$1/src/)" ++ atom_to_list(M) ++ ".erl", ErlFiles)]) ++ First0, - Write(["COMPILE_FIRST +=", [[" ", atom_to_list(M)] || M <- First, - lists:member("$(call core_native_path,$(DEPS_DIR)/$1/src/)" ++ atom_to_list(M) ++ ".erl", ErlFiles)], "\n"]) - end(), Write("\n\nrebar_dep: preprocess pre-deps deps pre-app app\n"), Write("\npreprocess::\n"), Write("\npre-deps::\n"), @@ -4417,9 +4375,10 @@ define dep_autopatch_rebar.erl Output, ": $$\(foreach ext,.c .C .cc .cpp,", "$$\(patsubst %$$\(ext),%.o,$$\(filter %$$\(ext),$$\(wildcard", Input, "))))\n", "\t$$\(CC) -o $$\@ $$\? $$\(LDFLAGS) $$\(ERL_LDFLAGS) $$\(DRV_LDFLAGS) $$\(EXE_LDFLAGS)", - case filename:extension(Output) of - [] -> "\n"; - _ -> " -shared\n" + case {filename:extension(Output), $(PLATFORM)} of + {[], _} -> "\n"; + {_, darwin} -> "\n"; + _ -> " -shared\n" end]) end, [PortSpec(S) || S <- PortSpecs] @@ -4488,6 +4447,15 @@ define dep_autopatch_app.erl halt() endef +define dep_autopatch_appsrc_script.erl + AppSrc = "$(call core_native_path,$(DEPS_DIR)/$1/src/$1.app.src)", + AppSrcScript = AppSrc ++ ".script", + Bindings = erl_eval:new_bindings(), + {ok, Conf} = file:script(AppSrcScript, Bindings), + ok = file:write_file(AppSrc, io_lib:format("~p.~n", [Conf])), + halt() +endef + define dep_autopatch_appsrc.erl AppSrcOut = "$(call core_native_path,$(DEPS_DIR)/$1/src/$1.app.src)", AppSrcIn = case filelib:is_regular(AppSrcOut) of false -> "$(call core_native_path,$(DEPS_DIR)/$1/ebin/$1.app)"; true -> AppSrcOut end, @@ -4574,10 +4542,11 @@ $(DEPS_DIR)/$(call dep_name,$1): exit 17; \ fi $(verbose) mkdir -p $(DEPS_DIR) - $(dep_verbose) $(call dep_fetch_$(strip $(call dep_fetch,$1)),$1) - $(verbose) if [ -f $(DEPS_DIR)/$(DEP_NAME)/configure.ac -o -f $(DEPS_DIR)/$(DEP_NAME)/configure.in ]; then \ - echo " AUTO " $(DEP_STR); \ - cd $(DEPS_DIR)/$(DEP_NAME) && autoreconf -Wall -vif -I m4; \ + $(dep_verbose) $(call dep_fetch_$(strip $(call dep_fetch,$(1))),$(1)) + $(verbose) if [ -f $(DEPS_DIR)/$(1)/configure.ac -o -f $(DEPS_DIR)/$(1)/configure.in ] \ + && [ ! -f $(DEPS_DIR)/$(1)/configure ]; then \ + echo " AUTO " $(1); \ + cd $(DEPS_DIR)/$(1) && autoreconf -Wall -vif -I m4; \ fi - $(verbose) if [ -f $(DEPS_DIR)/$(DEP_NAME)/configure ]; then \ echo " CONF " $(DEP_STR); \ @@ -4661,6 +4630,20 @@ dtl_verbose = $(dtl_verbose_$(V)) # Core targets. +DTL_FILES = $(sort $(call core_find,$(DTL_PATH),*.dtl)) + +ifneq ($(DTL_FILES),) + +ifdef DTL_FULL_PATH +BEAM_FILES += $(addprefix ebin/,$(patsubst %.dtl,%_dtl.beam,$(subst /,_,$(DTL_FILES:$(DTL_PATH)%=%)))) +else +BEAM_FILES += $(addprefix ebin/,$(patsubst %.dtl,%_dtl.beam,$(notdir $(DTL_FILES)))) +endif + +# Rebuild templates when the Makefile changes. +$(DTL_FILES): $(MAKEFILE_LIST) + @touch $@ + define erlydtl_compile.erl [begin Module0 = case "$(strip $(DTL_FULL_PATH))" of @@ -4679,23 +4662,10 @@ define erlydtl_compile.erl halt(). endef -ifneq ($(wildcard src/),) - -DTL_FILES = $(sort $(call core_find,$(DTL_PATH),*.dtl)) - -ifdef DTL_FULL_PATH -BEAM_FILES += $(addprefix ebin/,$(patsubst %.dtl,%_dtl.beam,$(subst /,_,$(DTL_FILES:$(DTL_PATH)%=%)))) -else -BEAM_FILES += $(addprefix ebin/,$(patsubst %.dtl,%_dtl.beam,$(notdir $(DTL_FILES)))) -endif - -# Rebuild templates when the Makefile changes. -$(DTL_FILES): $(MAKEFILE_LIST) - @touch $@ - -ebin/$(PROJECT).app:: $(DTL_FILES) +ebin/$(PROJECT).app:: $(DTL_FILES) | ebin/ $(if $(strip $?),\ - $(dtl_verbose) $(call erlang,$(call erlydtl_compile.erl,$?,-pa ebin/ $(DEPS_DIR)/erlydtl/ebin/))) + $(dtl_verbose) $(call erlang,$(call erlydtl_compile.erl,$?),-pa ebin/ $(DEPS_DIR)/erlydtl/ebin/)) + endif # Copyright (c) 2015, Loïc Hoguin @@ -4869,51 +4839,79 @@ $(PROJECT).d:: $(XRL_FILES) $(YRL_FILES) # Erlang and Core Erlang files. define makedep.erl + E = ets:new(makedep, [bag]), + G = digraph:new([acyclic]), ErlFiles = lists:usort(string:tokens("$(ERL_FILES)", " ")), - Modules = [{filename:basename(F, ".erl"), F} || F <- ErlFiles], - Add = fun (Dep, Acc) -> - case lists:keyfind(atom_to_list(Dep), 1, Modules) of - {_, DepFile} -> [DepFile|Acc]; - false -> Acc + Modules = [{list_to_atom(filename:basename(F, ".erl")), F} || F <- ErlFiles], + Add = fun (Mod, Dep) -> + case lists:keyfind(Dep, 1, Modules) of + false -> ok; + {_, DepFile} -> + {_, ModFile} = lists:keyfind(Mod, 1, Modules), + ets:insert(E, {ModFile, DepFile}), + digraph:add_vertex(G, Mod), + digraph:add_vertex(G, Dep), + digraph:add_edge(G, Mod, Dep) end end, - AddHd = fun (Dep, Acc) -> - case {Dep, lists:keymember(Dep, 2, Modules)} of - {"src/" ++ _, false} -> [Dep|Acc]; - {"include/" ++ _, false} -> [Dep|Acc]; - _ -> Acc + AddHd = fun (F, Mod, DepFile) -> + case file:open(DepFile, [read]) of + {error, enoent} -> ok; + {ok, Fd} -> + F(F, Fd, Mod), + {_, ModFile} = lists:keyfind(Mod, 1, Modules), + ets:insert(E, {ModFile, DepFile}) end end, - CompileFirst = fun (Deps) -> - First0 = [case filename:extension(D) of - ".erl" -> filename:basename(D, ".erl"); - _ -> [] - end || D <- Deps], - case lists:usort(First0) of - [] -> []; - [[]] -> []; - First -> ["COMPILE_FIRST +=", [[" ", F] || F <- First], "\n"] - end + Attr = fun + (F, Mod, behavior, Dep) -> Add(Mod, Dep); + (F, Mod, behaviour, Dep) -> Add(Mod, Dep); + (F, Mod, compile, {parse_transform, Dep}) -> Add(Mod, Dep); + (F, Mod, compile, Opts) when is_list(Opts) -> + case proplists:get_value(parse_transform, Opts) of + undefined -> ok; + Dep -> Add(Mod, Dep) + end; + (F, Mod, include, Hrl) -> + case filelib:is_file("include/" ++ Hrl) of + true -> AddHd(F, Mod, "include/" ++ Hrl); + false -> + case filelib:is_file("src/" ++ Hrl) of + true -> AddHd(F, Mod, "src/" ++ Hrl); + false -> false + end + end; + (F, Mod, include_lib, "$1/include/" ++ Hrl) -> AddHd(F, Mod, "include/" ++ Hrl); + (F, Mod, include_lib, Hrl) -> AddHd(F, Mod, "include/" ++ Hrl); + (F, Mod, import, {Imp, _}) -> + case filelib:is_file("src/" ++ atom_to_list(Imp) ++ ".erl") of + false -> ok; + true -> Add(Mod, Imp) + end; + (_, _, _, _) -> ok end, - Depend = [begin - case epp:parse_file(F, ["include/"], []) of - {ok, Forms} -> - Deps = lists:usort(lists:foldl(fun - ({attribute, _, behavior, Dep}, Acc) -> Add(Dep, Acc); - ({attribute, _, behaviour, Dep}, Acc) -> Add(Dep, Acc); - ({attribute, _, compile, {parse_transform, Dep}}, Acc) -> Add(Dep, Acc); - ({attribute, _, file, {Dep, _}}, Acc) -> AddHd(Dep, Acc); - (_, Acc) -> Acc - end, [], Forms)), - case Deps of - [] -> ""; - _ -> [F, "::", [[" ", D] || D <- Deps], "; @touch \$$@\n", CompileFirst(Deps)] - end; - {error, enoent} -> - [] + MakeDepend = fun(F, Fd, Mod) -> + case io:parse_erl_form(Fd, undefined) of + {ok, {attribute, _, Key, Value}, _} -> + Attr(F, Mod, Key, Value), + F(F, Fd, Mod); + {eof, _} -> + file:close(Fd); + _ -> + F(F, Fd, Mod) end + end, + [begin + Mod = list_to_atom(filename:basename(F, ".erl")), + {ok, Fd} = file:open(F, [read]), + MakeDepend(MakeDepend, Fd, Mod) end || F <- ErlFiles], - ok = file:write_file("$(1)", Depend), + Depend = sofs:to_external(sofs:relation_to_family(sofs:relation(ets:tab2list(E)))), + CompileFirst = [X || X <- lists:reverse(digraph_utils:topsort(G)), [] =/= digraph:in_neighbours(G, X)], + ok = file:write_file("$(1)", [ + [[F, "::", [[" ", D] || D <- Deps], "; @touch \$$@\n"] || {F, Deps} <- Depend], + "\nCOMPILE_FIRST +=", [[" ", atom_to_list(CF)] || CF <- CompileFirst], "\n" + ]), halt() endef @@ -5040,6 +5038,11 @@ test-dir: $(call core_find,$(TEST_DIR)/,*.erl) -pa ebin/ endif +ifeq ($(wildcard src),) +test-build:: ERLC_OPTS=$(TEST_ERLC_OPTS) +test-build:: clean deps test-deps + $(verbose) $(MAKE) --no-print-directory test-dir ERLC_OPTS="$(TEST_ERLC_OPTS)" +else ifeq ($(wildcard ebin/test),) test-build:: ERLC_OPTS=$(TEST_ERLC_OPTS) test-build:: clean deps test-deps $(PROJECT).d @@ -5057,6 +5060,7 @@ clean-test-dir: ifneq ($(wildcard $(TEST_DIR)/*.beam),) $(gen_verbose) rm -f $(TEST_DIR)/*.beam endif +endif # Copyright (c) 2015, Loïc Hoguin # This file is part of erlang.mk and subject to the terms of the ISC License. @@ -5185,6 +5189,8 @@ define bs_appsrc_lib ]}. endef +# To prevent autocompletion issues with ZSH, we add "include erlang.mk" +# separately during the actual bootstrap. ifdef SP define bs_Makefile PROJECT = $p @@ -5194,17 +5200,21 @@ PROJECT_VERSION = 0.0.1 # Whitespace to be used when creating files from templates. SP = $(SP) -include erlang.mk endef else define bs_Makefile PROJECT = $p -include erlang.mk +PROJECT_DESCRIPTION = New project +PROJECT_VERSION = 0.0.1 + endef endif define bs_apps_Makefile PROJECT = $p +PROJECT_DESCRIPTION = New project +PROJECT_VERSION = 0.0.1 + include $(call core_relpath,$(dir $(ERLANG_MK_FILENAME)),$(APPS_DIR)/app)/erlang.mk endef @@ -5498,6 +5508,7 @@ endif $(eval p := $(PROJECT)) $(eval n := $(PROJECT)_sup) $(call render_template,bs_Makefile,Makefile) + $(verbose) echo "include erlang.mk" >> Makefile $(verbose) mkdir src/ ifdef LEGACY $(call render_template,bs_appsrc,src/$(PROJECT).app.src) @@ -5511,6 +5522,7 @@ ifneq ($(wildcard src/),) endif $(eval p := $(PROJECT)) $(call render_template,bs_Makefile,Makefile) + $(verbose) echo "include erlang.mk" >> Makefile $(verbose) mkdir src/ ifdef LEGACY $(call render_template,bs_appsrc_lib,src/$(PROJECT).app.src) @@ -5591,12 +5603,32 @@ list-templates: C_SRC_DIR ?= $(CURDIR)/c_src C_SRC_ENV ?= $(C_SRC_DIR)/env.mk -C_SRC_OUTPUT ?= $(CURDIR)/priv/$(PROJECT).so +C_SRC_OUTPUT ?= $(CURDIR)/priv/$(PROJECT) C_SRC_TYPE ?= shared # System type and C compiler/flags. -ifeq ($(PLATFORM),darwin) +ifeq ($(PLATFORM),msys2) + C_SRC_OUTPUT_EXECUTABLE_EXTENSION ?= .exe + C_SRC_OUTPUT_SHARED_EXTENSION ?= .dll +else + C_SRC_OUTPUT_EXECUTABLE_EXTENSION ?= + C_SRC_OUTPUT_SHARED_EXTENSION ?= .so +endif + +ifeq ($(C_SRC_TYPE),shared) + C_SRC_OUTPUT_FILE = $(C_SRC_OUTPUT)$(C_SRC_OUTPUT_SHARED_EXTENSION) +else + C_SRC_OUTPUT_FILE = $(C_SRC_OUTPUT)$(C_SRC_OUTPUT_EXECUTABLE_EXTENSION) +endif + +ifeq ($(PLATFORM),msys2) +# We hardcode the compiler used on MSYS2. The default CC=cc does +# not produce working code. The "gcc" MSYS2 package also doesn't. + CC = /mingw64/bin/gcc + CFLAGS ?= -O3 -std=c99 -finline-functions -Wall -Wmissing-prototypes + CXXFLAGS ?= -O3 -finline-functions -Wall +else ifeq ($(PLATFORM),darwin) CC ?= cc CFLAGS ?= -O3 -std=c99 -arch x86_64 -finline-functions -Wall -Wmissing-prototypes CXXFLAGS ?= -O3 -arch x86_64 -finline-functions -Wall @@ -5611,10 +5643,15 @@ else ifeq ($(PLATFORM),linux) CXXFLAGS ?= -O3 -finline-functions -Wall endif -CFLAGS += -fPIC -I $(ERTS_INCLUDE_DIR) -I $(ERL_INTERFACE_INCLUDE_DIR) -CXXFLAGS += -fPIC -I $(ERTS_INCLUDE_DIR) -I $(ERL_INTERFACE_INCLUDE_DIR) +ifneq ($(PLATFORM),msys2) + CFLAGS += -fPIC + CXXFLAGS += -fPIC +endif + +CFLAGS += -I"$(ERTS_INCLUDE_DIR)" -I"$(ERL_INTERFACE_INCLUDE_DIR)" +CXXFLAGS += -I"$(ERTS_INCLUDE_DIR)" -I"$(ERL_INTERFACE_INCLUDE_DIR)" -LDLIBS += -L $(ERL_INTERFACE_LIB_DIR) -lerl_interface -lei +LDLIBS += -L"$(ERL_INTERFACE_LIB_DIR)" -lerl_interface -lei # Verbosity. @@ -5651,15 +5688,15 @@ OBJECTS = $(addsuffix .o, $(basename $(SOURCES))) COMPILE_C = $(c_verbose) $(CC) $(CFLAGS) $(CPPFLAGS) -c COMPILE_CPP = $(cpp_verbose) $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c -app:: $(C_SRC_ENV) $(C_SRC_OUTPUT) +app:: $(C_SRC_ENV) $(C_SRC_OUTPUT_FILE) -test-build:: $(C_SRC_ENV) $(C_SRC_OUTPUT) +test-build:: $(C_SRC_ENV) $(C_SRC_OUTPUT_FILE) -$(C_SRC_OUTPUT): $(OBJECTS) +$(C_SRC_OUTPUT_FILE): $(OBJECTS) $(verbose) mkdir -p priv/ $(link_verbose) $(CC) $(OBJECTS) \ $(LDFLAGS) $(if $(filter $(C_SRC_TYPE),shared),-shared) $(LDLIBS) \ - -o $(C_SRC_OUTPUT) + -o $(C_SRC_OUTPUT_FILE) %.o: %.c $(COMPILE_C) $(OUTPUT_OPTION) $< @@ -5676,13 +5713,13 @@ $(C_SRC_OUTPUT): $(OBJECTS) clean:: clean-c_src clean-c_src: - $(gen_verbose) rm -f $(C_SRC_OUTPUT) $(OBJECTS) + $(gen_verbose) rm -f $(C_SRC_OUTPUT_FILE) $(OBJECTS) endif ifneq ($(wildcard $(C_SRC_DIR)),) $(C_SRC_ENV): - $(verbose) $(ERL) -eval "file:write_file(\"$(C_SRC_ENV)\", \ + $(verbose) $(ERL) -eval "file:write_file(\"$(call core_native_path,$(C_SRC_ENV))\", \ io_lib:format( \ \"ERTS_INCLUDE_DIR ?= ~s/erts-~s/include/~n\" \ \"ERL_INTERFACE_INCLUDE_DIR ?= ~s~n\" \ @@ -5860,7 +5897,7 @@ endif # Copyright (c) 2013-2015, Loïc Hoguin # This file is part of erlang.mk and subject to the terms of the ISC License. -.PHONY: ct distclean-ct +.PHONY: ct apps-ct distclean-ct # Configuration. @@ -5895,17 +5932,33 @@ CT_RUN = ct_run \ -logdir $(CURDIR)/logs ifeq ($(CT_SUITES),) -ct: +ct: $(if $(IS_APP),,apps-ct) else -ct: test-build +ct: test-build $(if $(IS_APP),,apps-ct) $(verbose) mkdir -p $(CURDIR)/logs/ $(gen_verbose) $(CT_RUN) -suite $(addsuffix _SUITE,$(CT_SUITES)) $(CT_OPTS) endif +ifneq ($(ALL_APPS_DIRS),) +apps-ct: + $(verbose) for app in $(ALL_APPS_DIRS); do $(MAKE) -C $$app ct IS_APP=1; done +endif + +ifndef t +CT_EXTRA = +else +ifeq (,$(findstring :,$t)) +CT_EXTRA = -group $t +else +t_words = $(subst :, ,$t) +CT_EXTRA = -group $(firstword $(t_words)) -case $(lastword $(t_words)) +endif +endif + define ct_suite_target ct-$(1): test-build $(verbose) mkdir -p $(CURDIR)/logs/ - $(gen_verbose) $(CT_RUN) -suite $(addsuffix _SUITE,$(1)) $(CT_OPTS) + $(gen_verbose) $(CT_RUN) -suite $(addsuffix _SUITE,$(1)) $(CT_EXTRA) $(CT_OPTS) endef $(foreach test,$(CT_SUITES),$(eval $(call ct_suite_target,$(test)))) @@ -5924,9 +5977,8 @@ DIALYZER_PLT ?= $(CURDIR)/.$(PROJECT).plt export DIALYZER_PLT PLT_APPS ?= -DIALYZER_DIRS ?= --src -r src -DIALYZER_OPTS ?= -Werror_handling -Wrace_conditions \ - -Wunmatched_returns # -Wunderspecs +DIALYZER_DIRS ?= --src -r $(wildcard src) $(ALL_APPS_DIRS) +DIALYZER_OPTS ?= -Werror_handling -Wrace_conditions -Wunmatched_returns # -Wunderspecs # Core targets. @@ -5942,6 +5994,18 @@ help:: # Plugin-specific targets. +define filter_opts.erl + Opts = binary:split(<<"$1">>, <<"-">>, [global]), + Filtered = lists:reverse(lists:foldl(fun + (O = <<"pa ", _/bits>>, Acc) -> [O|Acc]; + (O = <<"D ", _/bits>>, Acc) -> [O|Acc]; + (O = <<"I ", _/bits>>, Acc) -> [O|Acc]; + (_, Acc) -> Acc + end, [], Opts)), + io:format("~s~n", [[["-", O] || O <- Filtered]]), + halt(). +endef + $(DIALYZER_PLT): deps app $(verbose) dialyzer --build_plt --apps erts kernel stdlib $(PLT_APPS) $(OTP_DEPS) $(LOCAL_DEPS) $(DEPS) @@ -5955,7 +6019,7 @@ dialyze: else dialyze: $(DIALYZER_PLT) endif - $(verbose) dialyzer --no_native $(DIALYZER_DIRS) $(DIALYZER_OPTS) + $(verbose) dialyzer --no_native `$(call erlang,$(call filter_opts.erl,$(ERLC_OPTS)))` $(DIALYZER_DIRS) $(DIALYZER_OPTS) # Copyright (c) 2013-2015, Loïc Hoguin # This file is part of erlang.mk and subject to the terms of the ISC License. @@ -5980,46 +6044,6 @@ edoc: doc-deps distclean-edoc: $(gen_verbose) rm -f doc/*.css doc/*.html doc/*.png doc/edoc-info -# Copyright (c) 2015, Erlang Solutions Ltd. -# This file is part of erlang.mk and subject to the terms of the ISC License. - -.PHONY: elvis distclean-elvis - -# Configuration. - -ELVIS_CONFIG ?= $(CURDIR)/elvis.config - -ELVIS ?= $(CURDIR)/elvis -export ELVIS - -ELVIS_URL ?= https://github.com/inaka/elvis/releases/download/0.2.5/elvis -ELVIS_CONFIG_URL ?= https://github.com/inaka/elvis/releases/download/0.2.5/elvis.config -ELVIS_OPTS ?= - -# Core targets. - -help:: - $(verbose) printf "%s\n" "" \ - "Elvis targets:" \ - " elvis Run Elvis using the local elvis.config or download the default otherwise" - -distclean:: distclean-elvis - -# Plugin-specific targets. - -$(ELVIS): - $(gen_verbose) $(call core_http_get,$(ELVIS),$(ELVIS_URL)) - $(verbose) chmod +x $(ELVIS) - -$(ELVIS_CONFIG): - $(verbose) $(call core_http_get,$(ELVIS_CONFIG),$(ELVIS_CONFIG_URL)) - -elvis: $(ELVIS) $(ELVIS_CONFIG) - $(verbose) $(ELVIS) rock -c $(ELVIS_CONFIG) $(ELVIS_OPTS) - -distclean-elvis: - $(gen_verbose) rm -rf $(ELVIS) - # Copyright (c) 2014 Dave Cottlehuber # This file is part of erlang.mk and subject to the terms of the ISC License. @@ -6089,11 +6113,12 @@ distclean-escript: # Copyright (c) 2015, Loïc Hoguin # This file is contributed to erlang.mk and subject to the terms of the ISC License. -.PHONY: eunit +.PHONY: eunit apps-eunit # Configuration EUNIT_OPTS ?= +EUNIT_ERL_OPTS ?= # Core targets. @@ -6115,7 +6140,7 @@ define eunit.erl _ -> ok end end, - case eunit:test([$(call comma_list,$(1))], [$(EUNIT_OPTS)]) of + case eunit:test($1, [$(EUNIT_OPTS)]) of ok -> ok; error -> halt(2) end, @@ -6127,14 +6152,30 @@ define eunit.erl halt() endef +EUNIT_ERL_OPTS += -pa $(TEST_DIR) $(DEPS_DIR)/*/ebin $(APPS_DIR)/*/ebin ebin + +ifdef t +ifeq (,$(findstring :,$(t))) +eunit: test-build + $(gen_verbose) $(call erlang,$(call eunit.erl,['$(t)']),$(EUNIT_ERL_OPTS)) +else +eunit: test-build + $(gen_verbose) $(call erlang,$(call eunit.erl,fun $(t)/0),$(EUNIT_ERL_OPTS)) +endif +else EUNIT_EBIN_MODS = $(notdir $(basename $(call core_find,ebin/,*.beam))) EUNIT_TEST_MODS = $(notdir $(basename $(call core_find,$(TEST_DIR)/,*.beam))) EUNIT_MODS = $(foreach mod,$(EUNIT_EBIN_MODS) $(filter-out \ - $(patsubst %,%_tests,$(EUNIT_EBIN_MODS)),$(EUNIT_TEST_MODS)),{module,'$(mod)'}) + $(patsubst %,%_tests,$(EUNIT_EBIN_MODS)),$(EUNIT_TEST_MODS)),'$(mod)') -eunit: test-build - $(gen_verbose) $(ERL) -pa $(TEST_DIR) $(DEPS_DIR)/*/ebin ebin \ - -eval "$(subst $(newline),,$(subst ",\",$(call eunit.erl,$(EUNIT_MODS))))" +eunit: test-build $(if $(IS_APP),,apps-eunit) + $(gen_verbose) $(call erlang,$(call eunit.erl,[$(call comma_list,$(EUNIT_MODS))]),$(EUNIT_ERL_OPTS)) + +ifneq ($(ALL_APPS_DIRS),) +apps-eunit: + $(verbose) for app in $(ALL_APPS_DIRS); do $(MAKE) -C $$app eunit IS_APP=1; done +endif +endif # Copyright (c) 2013-2015, Loïc Hoguin # This file is part of erlang.mk and subject to the terms of the ISC License. diff --git a/rebar.config b/rebar.config index a4df8a5..029e43c 100644 --- a/rebar.config +++ b/rebar.config @@ -8,9 +8,8 @@ {deps_dir, "deps"}. {deps, [ - {cowboy, ".*", {git, "https://github.com/ninenines/cowboy.git", "1.0.1"}}, - {cowlib, ".*", {git, "https://github.com/ninenines/cowlib.git", "1.0.0"}}, - {ranch, ".*", {git, "https://github.com/ninenines/ranch.git", "1.0.0"}} + {cowboy, ".*", {git, "https://github.com/ninenines/cowboy.git", "1.0.4"}}, + {ranch, ".*", {git, "https://github.com/ninenines/ranch.git", "1.2.0"}} ] }. diff --git a/src/trails.app.src b/src/trails.app.src index dbd3382..83c71d0 100644 --- a/src/trails.app.src +++ b/src/trails.app.src @@ -2,13 +2,21 @@ [ {description, "A couple of improvements over Cowboy Routes"}, - {vsn, "0.1.0"}, + {vsn, "0.1.1"}, {applications, [kernel, stdlib ]}, {modules, []}, {mod, {trails_app, []}}, - {registered, []} + {registered, []}, + {maintainers,["Inaka"]}, + {licenses,["Apache 2.0"]}, + {links,[ {"Github","https://github.com/inaka/cowboy-trails"}, + {"Docs", "http://inaka.github.io/cowboy-trails/"}, + {"Blog", "http://inaka.net/blog/2015/07/20/cowboy-trails/"}, + {"Example", "https://github.com/inaka/cowboy-trails/tree/master/example"} + ]}, + {build_tools,["make", "rebar"]} ] }. diff --git a/src/trails.erl b/src/trails.erl index 836c0e3..c64edc7 100644 --- a/src/trails.erl +++ b/src/trails.erl @@ -119,27 +119,27 @@ trail(PathMatch, ModuleHandler, Options, MetaData, Constraints) -> %% @doc Gets the `path_match' from the given `trail'. -spec path_match(trail()) -> cowboy_router:route_match(). path_match(Trail) -> - maps:get(path_match, Trail, []). + maps:get(path_match, Trail, []). %% @doc Gets the `handler' from the given `trail'. -spec handler(trail()) -> module(). handler(Trail) -> - maps:get(handler, Trail, []). + maps:get(handler, Trail, []). %% @doc Gets the `options' from the given `trail'. -spec options(trail()) -> any(). options(Trail) -> - maps:get(options, Trail, []). + maps:get(options, Trail, []). %% @doc Gets the `metadata' from the given `trail'. -spec metadata(trail()) -> map(). metadata(Trail) -> - maps:get(metadata, Trail, #{}). + maps:get(metadata, Trail, #{}). %% @doc Gets the `constraints' from the given `trail'. -spec constraints(trail()) -> cowboy_router:constraints(). constraints(Trail) -> - maps:get(constraints, Trail, []). + maps:get(constraints, Trail, []). %% @doc This function allows you to define the routes on each resource handler, %% instead of defining them all in one place (as you're required to do diff --git a/test/trails.coverspec b/test/cover.spec similarity index 53% rename from test/trails.coverspec rename to test/cover.spec index 1f5cccf..9e84a00 100644 --- a/test/trails.coverspec +++ b/test/cover.spec @@ -1,5 +1,5 @@ %% Specific modules to include in cover. { incl_mods, - [trails] + [trails, trails_app, trails_handler, trails_sup] }. diff --git a/test/xref_SUITE.erl b/test/xref_SUITE.erl deleted file mode 100644 index f8941ce..0000000 --- a/test/xref_SUITE.erl +++ /dev/null @@ -1,17 +0,0 @@ --module(xref_SUITE). --author('elbrujohalcon@inaka.net'). - --export([all/0]). --export([xref/1]). - --spec all() -> [xref]. -all() -> [xref]. - --spec xref(lsl_test_utils:config()) -> {comment, []}. -xref(_Config) -> - Dirs = [filename:absname("../../ebin")], - [] = xref_runner:check(undefined_function_calls, #{dirs => Dirs}), - [] = xref_runner:check(locals_not_used, #{dirs => Dirs}), - [] = xref_runner:check(deprecated_function_calls, #{dirs => Dirs}), - [] = xref_runner:check(deprecated_functions, #{dirs => Dirs}), - {comment, ""}.