From: Mikael Magnusson <[email protected]>
Signed-off-by: Mikael Magnusson <[email protected]>
---
server/sinan/src/sin_resolver.erl | 344 +++++++++++++++++++++++++++++++++++++
1 files changed, 344 insertions(+), 0 deletions(-)
create mode 100644 server/sinan/src/sin_resolver.erl
diff --git a/server/sinan/src/sin_resolver.erl
b/server/sinan/src/sin_resolver.erl
new file mode 100644
index 0000000..203bb9a
--- /dev/null
+++ b/server/sinan/src/sin_resolver.erl
@@ -0,0 +1,344 @@
+%%%-------------------------------------------------------------------
+%%% Copyright (c) 2007 Eric Merritt, Martin Logan
+%%%
+%%% Permission is hereby granted, free of charge, to any
+%%% person obtaining a copy of this software and associated
+%%% documentation files (the "Software"), to deal in the
+%%% Software without restriction, including without limitation
+%%% the rights to use, copy, modify, merge, publish, distribute,
+%%% sublicense, and/or sell copies of the Software, and to permit
+%%% persons to whom the Software is furnished to do so, subject to
+%%% the following conditions:
+%%%
+%%% The above copyright notice and this permission notice shall
+%%% be included in all copies or substantial portions of the Software.
+%%%
+%%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+%%% EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+%%% OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+%%% NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+%%% HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+%%% WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+%%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+%%% OTHER DEALINGS IN THE SOFTWARE.
+%%%-------------------------------------------------------------------
+%%% @doc
+%%% Resolves individual items for the dependency engine.
+%%% @copyright Erlware 2007
+%%% @end
+%%%-------------------------------------------------------------------
+-module(sin_resolver).
+
+-include("eunit.hrl").
+
+%% API
+-export([package_versions/3,
+ package_dependencies/4,
+ find_package_location/4,
+ gather_version_info/2]).
+
+
+
+%%====================================================================
+%% API
+%%====================================================================
+%%--------------------------------------------------------------------
+%% @doc
+%% Get the list of versions available for the specified package.
+%%
+%% @spec (Prefix, ErtsVersion, Package) -> VersionList
+%% @end
+%%--------------------------------------------------------------------
+package_versions(Prefix, ErtsVersion, Package) when is_atom(Package) ->
+ VList = gather_version_info(Prefix, ErtsVersion),
+ get_package_versions(Package,
+ Prefix,
+ VList,
+ []);
+package_versions(_, _, _) ->
+ throw({error, "Package name must be an atom"}).
+
+%%--------------------------------------------------------------------
+%% @doc
+%% Get the list of dependencies for the specified package and the
+%% specified version.
+%%
+%% @spec (Prefix, ErtsVersion, Package, Version) -> Deps | Error
+%% @end
+%%--------------------------------------------------------------------
+package_dependencies(Prefix, ErtsVersion, Package, Version) ->
+ VList = gather_version_info(Prefix, ErtsVersion),
+ NPackage = atom_to_list(Package),
+ NDeps = get_package_dependencies(NPackage,
+ Version,
+ Prefix,
+ VList),
+ NDeps.
+
+
+%%--------------------------------------------------------------------
+%% @doc
+%% Get the dependencies for a package and version.
+%%
+%% @spec (Package, Version, Prefix, Versions) -> Location
+%% @end
+%%--------------------------------------------------------------------
+find_package_location(Prefix, ErtsVersion, Package, Version) ->
+ VList = gather_version_info(Prefix, ErtsVersion),
+ find_package_location_across_versions(Package, Version, Prefix, VList).
+
+
+%%====================================================================
+%%% Internal functions
+%%====================================================================
+%%--------------------------------------------------------------------
+%% @doc
+%% Get the list of subdirectories for the current directory
+%%
+%% @spec (Dir) -> ListOfDirs
+%% @end
+%%--------------------------------------------------------------------
+list_subdirectories(Dir) ->
+ lists:filter(fun(X) -> filelib:is_dir(X) end,
+ filelib:wildcard(Dir ++ "/*")).
+
+%%--------------------------------------------------------------------
+%% @doc
+%% Get the dependencies for a package and version.
+%%
+%% @spec (Package, Version, Prefix, Versions) -> Location
+%% @end
+%%--------------------------------------------------------------------
+find_package_location_across_versions(Package, Version,
+ Prefix, [ErtsVersion | ErtsVersions]) ->
+ PackageName = lists:flatten([Package, "-", Version]),
+ FileName = filename:join([Prefix, "packages", ErtsVersion,
+ "lib", PackageName]),
+ case filelib:is_dir(FileName) of
+ true ->
+ FileName;
+ false ->
+ find_package_location_across_versions(Package, Version,
+ Prefix, ErtsVersions)
+ end;
+find_package_location_across_versions(_, _, _, []) ->
+ throw({error, "Unable to find location for package"}).
+
+%%--------------------------------------------------------------------
+%% @doc
+%% Get all versions that share the same major.minor version
+%% with the current erts. Thats erts version, not app version
+%%
+%% @spec gather_version_info(Prefix, ErtsVersion) -> ErtsVersions
+%% @end
+%%--------------------------------------------------------------------
+gather_version_info(Prefix, ErtsVersion) ->
+ ErtsVersions = lists:reverse(
+ lists:sort(
+ lists:map(fun(File) ->
+ filename:basename(File)
+ end,
+ list_subdirectories(
+ filename:join([Prefix, "packages"]))))),
+ NewErtsVersion = get_major_minor(ErtsVersion, 0, []),
+ lists:filter(fun(X) ->
+ starts_with(NewErtsVersion, X)
+ end,
+ ErtsVersions).
+
+%%--------------------------------------------------------------------
+%% @doc
+%% Check that list1 is the same as the first part of list2
+%%
+%% @spec (List1, List2) -> true | false
+%% @end
+%%--------------------------------------------------------------------
+starts_with([C1 | Rest1], [C1 | Rest2]) ->
+ starts_with(Rest1, Rest2);
+starts_with([], _) ->
+ true;
+starts_with(_, _) ->
+ false.
+
+%%--------------------------------------------------------------------
+%% @doc
+%% Get the major.minor version from version string.
+%%
+%% @spec (Name, Count, Acc) -> MajorMinor
+%% @end
+%%--------------------------------------------------------------------
+get_major_minor([$. | _], 1, Acc) ->
+ lists:reverse(Acc);
+get_major_minor([$. | Rest], 0, Acc) ->
+ get_major_minor(Rest, 1, [$. | Acc]);
+get_major_minor([Head | Rest], Count, Acc) ->
+ get_major_minor(Rest, Count, [Head | Acc]);
+get_major_minor([], _, Acc) ->
+ lists:reverse(Acc).
+
+%%--------------------------------------------------------------------
+%% @doc
+%% Get the version from an app-version
+%%
+%% @spec (Name) -> Version
+%% @end
+%%--------------------------------------------------------------------
+get_version([$- | Rest]) ->
+ Rest;
+get_version([_ | Rest]) ->
+ get_version(Rest);
+get_version([]) ->
+ throw({error, "Unable to find package version"}).
+
+%%--------------------------------------------------------------------
+%% @doc
+%% Acc is a set. It this just makes sure only one entry is in the set
+%%
+%% @spec (Name, In, Acc) -> NewAcc
+%% @end
+%%--------------------------------------------------------------------
+add_to_acc([Name | Rest1] , [Name | _], Acc) ->
+ add_to_acc(Rest1, Acc, Acc);
+add_to_acc(All, [_ | Rest], Acc) ->
+ add_to_acc(All, Rest, Acc);
+add_to_acc([Name | Rest], [], Acc) ->
+ NewAcc = [Name | Acc],
+ add_to_acc(Rest, NewAcc, NewAcc);
+add_to_acc([], [], Acc) ->
+ lists:reverse(Acc).
+
+%%--------------------------------------------------------------------
+%% @doc
+%% Get all the versions for a package, search across all
+%% relavent major/minor versions.
+%%
+%% @spec (Package, Prefix, Versions, Acc) -> Versions
+%% @end
+%%--------------------------------------------------------------------
+get_package_versions(Package, Prefix, [ErtsVersion | ErtsVersions], Acc) ->
+ FileName = filename:join([Prefix, "packages", ErtsVersion,
+ "lib"]),
+ AppVersions = lists:filter(fun(X) ->
+ starts_with(atom_to_list(Package)
+ ++ "-", filename:basename(X))
+ end,
+ list_subdirectories(FileName)),
+ Versions = lists:map(fun(X) ->
+ get_version(X)
+ end,
+ AppVersions),
+ get_package_versions(Package, Prefix, ErtsVersions,
+ add_to_acc(Versions, Acc, Acc));
+get_package_versions(_, _, [], Acc) ->
+ Acc.
+
+%%--------------------------------------------------------------------
+%% @doc
+%% Get the dependencies for a package and version.
+%%
+%% @spec (Package, Version, Prefix, Versions) -> Deps
+%% @end
+%%--------------------------------------------------------------------
+get_package_dependencies(Package, Version, Prefix,
+ [ErtsVersion | ErtsVersions]) ->
+ DotAppName = lists:flatten([Package, ".app"]),
+ AppName = lists:flatten([Package, "-", Version]),
+ case file:consult(filename:join([Prefix, "packages",
+ ErtsVersion, "lib", AppName,
+ "ebin", DotAppName])) of
+ {ok, [Term]} ->
+ handle_parse_output(Term);
+ {error, _} ->
+ get_package_dependencies(Package, Version, Prefix,
+ [ErtsVersion | ErtsVersions])
+ end;
+get_package_dependencies(_, _, _, []) ->
+ throw({error, "Unable to find dependencies for package"}).
+
+
+
+
+%%--------------------------------------------------------------------
+%% @doc
+%% get the version the deps and the versioned deps from an *.app
+%% term.
+%%
+%% @spec handle_parse_output(AppTerm) -> {Vsn, VersionedDeps, Deps} | {error,
Reason}
+%% @end
+%%--------------------------------------------------------------------
+handle_parse_output({application, _, Ops}) ->
+ lists:umerge(lists:sort(get_deps(Ops)),
+ lists:sort(get_ideps(Ops)));
+handle_parse_output(_) ->
+ throw({error, "Invalid dependency info"}).
+
+
+
+%%--------------------------------------------------------------------
+%% @doc
+%% Get the list of non-versioned dependencies from the oplist. This
+%% is specifed in the applications entry.
+%% @spec get_deps(OpList) -> Dependencies
+%% @end
+%% @private
+%%--------------------------------------------------------------------
+get_deps([{applications, List} | _T]) ->
+ List;
+get_deps([_ | T]) ->
+ get_deps(T);
+get_deps([]) ->
+ [].
+
+
+%%--------------------------------------------------------------------
+%% @doc
+%% Get the list of included applications.
+%% @spec get_ideps(OpList) -> IncludedDependencies
+%% @end
+%% @private
+%%--------------------------------------------------------------------
+get_ideps([{included_applications, List} | _T]) ->
+ List;
+get_ideps([_ | T]) ->
+ get_ideps(T);
+get_ideps([]) ->
+ [].
+
+%%====================================================================
+%% tests
+%%====================================================================
+handle_parse_output_test() ->
+ Data = {application, testapp,
+ [{vsn, "0.1.0"},
+ {description, "test test test"},
+ {versioned_dependencies,
+ [{app1, "0.1.0"}, {app2, "0.33.1", gte},
+ {app3, "33.11.3"}]},
+ {applications, [app1, app2, app3, app4, app5]}]},
+ ?assertMatch([{app3, [33, 11, 3]}, {app2, [0, 33, 1],gte},
+ {app1, [0, 1, 0]}, app5, app4],
+ handle_parse_output(Data)).
+
+starts_with_test() ->
+ ?assertMatch(true, starts_with("onetwo", "onetwothree")),
+ ?assertMatch(false, starts_with("onetwo", "threetwoone")).
+
+get_major_minor_test() ->
+ ?assertMatch("5.6", get_major_minor("5.6.3", 0, [])),
+ ?assertMatch("5.5", get_major_minor("5.5.5", 0, [])).
+
+get_version_test() ->
+ ?assertMatch("1.0", get_version("sinan-1.0")),
+ ?assertMatch("1.3.2.2", get_version("bah-1.3.2.2")).
+
+add_to_acc_test() ->
+ Start = ["one", "two", "one", "three", "four", "two"],
+ ?assertMatch(["one", "two", "three", "four"], add_to_acc(Start, [], [])).
+
+gather_version_info_test() ->
+ Prefix = "/usr/local/erlware",
+ Version = "5.6.3",
+ ?assertMatch([Version], gather_version_info(Prefix, Version)).
+
+get_package_versions_test() ->
+ ?assertMatch(["10.0.1"], get_package_versions(sinan, "/usr/local/erlware",
["5.6.3"], [])).
--
1.5.6.3
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"erlware-dev" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/erlware-dev?hl=en
-~----------~----~----~----~------~----~------~--~---