From 07a54bb518049aeefe4a883bc3d06dfb54ad6880 Mon Sep 17 00:00:00 2001 From: Eric Merritt Date: Fri, 22 Apr 2011 09:30:03 -0500 Subject: [PATCH] add specs and exported types where needed This patch exports types that are needed and adds specs where they did not previously exist. It also cleans up and expands the specs where they needed to be cleaned up. --- src/ec_file.erl | 41 ++++++++++++++++++++++++++--------------- src/ec_semver.erl | 24 +++++++++++++++++++++++- src/ec_string.erl | 18 ++++++++++++++---- 3 files changed, 63 insertions(+), 20 deletions(-) diff --git a/src/ec_file.erl b/src/ec_file.erl index 399dd1a..5261ef1 100644 --- a/src/ec_file.erl +++ b/src/ec_file.erl @@ -22,7 +22,10 @@ consult/1 ]). --export_type([path/0]). +-export_type([ + path/0, + option/0 + ]). -include_lib("kernel/include/file.hrl"). @@ -34,19 +37,20 @@ Exception, lists:flatten(io_lib:fwrite(UMSG, UVARS))}}). --define(CHECK_PERMS_MSG, +-define(CHECK_PERMS_MSG, "Try checking that you have the correct permissions and try again~n"). %%============================================================================ %% Types %%============================================================================ -type path() :: string(). +-type option() :: [atom()]. %%%=================================================================== %%% API %%%=================================================================== %% @doc copy an entire directory to another location. --spec copy(path(), path(), Options::list()) -> ok. +-spec copy(path(), path(), Options::[option()]) -> ok. copy(From, To, []) -> copy(From, To); copy(From, To, [recursive] = Options) -> @@ -77,7 +81,7 @@ md5sum(Value) -> %%
 %% Example: remove("./tmp_dir", [recursive]).
 %% 
--spec remove(path(), Options::list()) -> ok | {error, Reason::term()}. +-spec remove(path(), Options::[option()]) -> ok | {error, Reason::term()}. remove(Path, Options) -> try ok = ec_file_remove(Path, Options) @@ -85,7 +89,7 @@ remove(Path, Options) -> _C:E -> throw(?UEX({remove_failed, E}, ?CHECK_PERMS_MSG, [])) end. -%% @doc delete a file. +%% @doc delete a file. -spec remove(path()) -> ok | {error, Reason::term()}. remove(Path) -> remove(Path, []). @@ -100,7 +104,7 @@ is_symlink(Path) -> false end. -%% @doc make a unique temorory directory. Similar function to BSD stdlib +%% @doc make a unique temorory directory. Similar function to BSD stdlib %% function of the same name. -spec mkdtemp() -> TmpDirPath::path(). mkdtemp() -> @@ -128,11 +132,11 @@ mkdir_path(Path) -> catch _C:E -> throw(?UEX({mkdir_path_failed, E}, ?CHECK_PERMS_MSG, [])) end. - - + + %% @doc consult an erlang term file from the file system. %% Provide user readible exeption on failure. --spec consult(FilePath::string()) -> term(). +-spec consult(FilePath::path()) -> term(). consult(FilePath) -> case file:consult(FilePath) of {ok, [Term]} -> @@ -181,7 +185,7 @@ write_term(FileName, Term) -> %% @doc Finds files and directories that match the regexp supplied in %% the TargetPattern regexp. --spec find(FromDir::path(), TargetPattern::string()) -> list(). +-spec find(FromDir::path(), TargetPattern::string()) -> [path()]. find([], _) -> []; find(FromDir, TargetPattern) -> @@ -202,6 +206,7 @@ find(FromDir, TargetPattern) -> %%%=================================================================== %%% Internal Functions %%%=================================================================== +-spec find_in_subdirs(path(), string()) -> [path()]. find_in_subdirs(FromDir, TargetPattern) -> lists:foldl(fun(CheckFromDir, Acc) when CheckFromDir == FromDir -> @@ -214,7 +219,8 @@ find_in_subdirs(FromDir, TargetPattern) -> end, [], filelib:wildcard(filename:join(FromDir, "*"))). - + +-spec ec_file_remove(path(), [{atom(), any()}]) -> ok. ec_file_remove(Path, Options) -> case lists:member(recursive, Options) of false -> file:delete(Path); @@ -233,6 +239,7 @@ remove_recursive(Path, Options) -> ok = file:del_dir(Path) end. +-spec tmp() -> path(). tmp() -> case erlang:system_info(system_architecture) of "win32" -> @@ -243,19 +250,22 @@ tmp() -> end. %% Copy the subfiles of the From directory to the to directory. +-spec copy_subfiles(path(), path(), [option()]) -> ok. copy_subfiles(From, To, Options) -> - Fun = + Fun = fun(ChildFrom) -> ChildTo = filename:join([To, filename:basename(ChildFrom)]), copy(ChildFrom, ChildTo, Options) end, lists:foreach(Fun, filelib:wildcard(filename:join(From, "*"))). +-spec ec_file_copy(path(), path()) -> ok. ec_file_copy(From, To) -> {ok, _} = file:copy(From, To), {ok, FileInfo} = file:read_file_info(From), ok = file:write_file_info(To, FileInfo). +-spec make_dir_if_dir(path()) -> ok. make_dir_if_dir(File) -> case filelib:is_dir(File) of true -> ok; @@ -263,6 +273,7 @@ make_dir_if_dir(File) -> end. %% @doc convert a list of integers into hex. +-spec hex(string() | non_neg_integer()) -> string(). hex(L) when is_list (L) -> lists:flatten([hex(I) || I <- L]); hex(I) when I > 16#f -> @@ -295,10 +306,10 @@ setup_test() -> mkdir_path("/tmp/ec_file/dir"), ?assertMatch(false, is_symlink("/tmp/ec_file/dir")), ?assertMatch(true, filelib:is_dir("/tmp/ec_file/dir")). - - + + md5sum_test() -> - ?assertMatch("cfcd208495d565ef66e7dff9f98764da", md5sum("0")). + ?assertMatch("cfcd208495d565ef66e7dff9f98764da", md5sum("0")). file_test() -> TermFile = "/tmp/ec_file/dir/file.term", diff --git a/src/ec_semver.erl b/src/ec_semver.erl index 8f4ec72..b41a701 100644 --- a/src/ec_semver.erl +++ b/src/ec_semver.erl @@ -11,6 +11,20 @@ compare/2 ]). +-export_type([ + semvar/0 + ]). + +%%%=================================================================== +%%% Public Types +%%%=================================================================== + +-type semvar() :: string(). +-type parsed_semvar() :: {MajorVsn::string(), + MinorVsn::string(), + PatchVsn::string(), + PathString::string()}. + %%%=================================================================== %%% API %%%=================================================================== @@ -26,15 +40,20 @@ compare(VsnA, VsnB) -> %%%=================================================================== %%% Internal Functions %%%=================================================================== +-spec tokens(semvar()) -> parsed_semvar(). tokens(Vsn) -> [MajorVsn, MinorVsn, RawPatch] = string:tokens(Vsn, "."), {PatchVsn, PatchString} = split_patch(RawPatch), {MajorVsn, MinorVsn, PatchVsn, PatchString}. +-spec split_patch(string()) -> + {PatchVsn::string(), PatchStr::string()}. split_patch(RawPatch) -> {PatchVsn, PatchStr} = split_patch(RawPatch, {"", ""}), {lists:reverse(PatchVsn), PatchStr}. +-spec split_patch(string(), {AccPatchVsn::string(), AccPatchStr::string()}) -> + {PatchVsn::string(), PatchStr::string()}. split_patch([], Acc) -> Acc; split_patch([Dig|T], {PatchVsn, PatchStr}) when Dig >= $0 andalso Dig =< $9 -> @@ -42,10 +61,12 @@ split_patch([Dig|T], {PatchVsn, PatchStr}) when Dig >= $0 andalso Dig =< $9 -> split_patch(PatchStr, {PatchVsn, ""}) -> {PatchVsn, PatchStr}. +-spec compare_toks(parsed_semvar(), parsed_semvar()) -> boolean(). compare_toks({MajA, MinA, PVA, PSA}, {MajB, MinB, PVB, PSB}) -> compare_toks2({to_int(MajA), to_int(MinA), to_int(PVA), PSA}, {to_int(MajB), to_int(MinB), to_int(PVB), PSB}). +-spec compare_toks2(parsed_semvar(), parsed_semvar()) -> boolean(). compare_toks2({MajA, _MinA, _PVA, _PSA}, {MajB, _MinB, _PVB, _PSB}) when MajA > MajB -> true; compare_toks2({_Maj, MinA, _PVA, _PSA}, {_Maj, MinB, _PVB, _PSB}) when MinA > MinB -> @@ -60,7 +81,8 @@ compare_toks2({_Maj, _Min, _PV, PSA}, {_Maj, _Min, _PV, PSB}) when PSA > PSB -> true; compare_toks2(_ToksA, _ToksB) -> false. - + +-spec to_int(string()) -> integer(). to_int(String) -> case catch list_to_integer(String) of Integer when is_integer(Integer) -> diff --git a/src/ec_string.erl b/src/ec_string.erl index 1dcba81..f730b81 100644 --- a/src/ec_string.erl +++ b/src/ec_string.erl @@ -17,7 +17,7 @@ %% Valid version string elements are either separated by . or - or both. %% Final version string elements may have a numeric followed directly by an %% alpha numeric and will be compared separately as in 12alpha. -%% +%% %%
 %% Example: compare_versions("3-2-5-alpha", "3.10.6") will return false
 %%          compare_versions("3-2-alpha", "3.2.1-alpha") will return false
@@ -34,14 +34,15 @@ compare_versions(VsnA, VsnB) ->
 %%% Internal Functions
 %%%===================================================================
 
+-spec compare(string(), string()) -> boolean().
 compare([Str|TA], [Str|TB]) ->
     compare(TA, TB);
 compare([StrA|TA], [StrB|TB]) ->
     fine_compare(split_numeric_alpha(StrA), TA,
 		 split_numeric_alpha(StrB), TB);
-compare([], [Str]) -> 
+compare([], [Str]) ->
     not compare_against_nothing(Str);
-compare([Str], []) -> 
+compare([Str], []) ->
     compare_against_nothing(Str);
 compare([], [_,_|_]) ->
     false;
@@ -50,6 +51,7 @@ compare([_,_|_], []) ->
 compare([], []) ->
     false.
 
+-spec compare_against_nothing(string()) -> boolean().
 compare_against_nothing(Str) ->
     case split_numeric_alpha(Str) of
 	{_StrDig, ""} -> true;
@@ -57,6 +59,9 @@ compare_against_nothing(Str) ->
 	{_StrDig, _StrAlpha} -> true
     end.
 
+-spec fine_compare({string(), string()}, string(),
+		   {string(), string()}, string()) ->
+    boolean().
 fine_compare({_StrDigA, StrA}, TA, {_StrDigB, _StrB}, _TB) when StrA /= "", TA /= [] ->
     throw(invalid_version_string);
 fine_compare({_StrDigA, _StrA}, _TA, {_StrDigB, StrB}, TB) when StrB /= "", TB /= [] ->
@@ -74,12 +79,17 @@ fine_compare({StrDig, StrA}, _TA, {StrDig, StrB}, _TB) ->
 fine_compare({StrDigA, _StrA}, _TA, {StrDigB, _StrB}, _TB) ->
     list_to_integer(StrDigA) > list_to_integer(StrDigB).
 
-%% In the case of a version sub part with a numeric then an alpha, 
+%% In the case of a version sub part with a numeric then an alpha,
 %% split out the numeric and alpha "24alpha" becomes {"24", "alpha"}
+-spec split_numeric_alpha(string()) ->
+    {PatchVsn::string(), PatchStr::string()}.
 split_numeric_alpha(RawVsn) ->
     {Num, Str} = split_numeric_alpha(RawVsn, {"", ""}),
     {lists:reverse(Num), Str}.
 
+-spec split_numeric_alpha(string(), {PatchVsnAcc::string(),
+				     PatchStrAcc::string()}) ->
+    {PatchVsn::string(), PatchStr::string()}.
 split_numeric_alpha([], Acc) ->
     Acc;
 split_numeric_alpha([Dig|T], {PatchVsn, PatchStr})