cpack_repository/commit
First draft of API to server package installation data
author | Jan Wielemaker |
---|---|
Wed Nov 17 11:48:53 2010 +0100 | |
committer | Jan Wielemaker |
Wed Nov 17 11:48:53 2010 +0100 | |
commit | 45c67556cf922cc8e509ba241c8d388fe7eb4133 |
tree | f9ded57fdf677a50a63d6e8bf6ec7eb65eb68bbd |
parent | 22261f7d6c7e2f7e780831ececaa15752b065cc1 |
Diff style: patch stat
diff --git a/api/cpack.pl b/api/cpack.pl index ee14eb2..a544881 100644 --- a/api/cpack.pl +++ b/api/cpack.pl @@ -31,6 +31,10 @@ :- module(api_cpack, [ ]). +:- use_module(library(cpack/dependency)). +:- use_module(library(semweb/rdf_db)). +:- use_module(library(semweb/rdf_label)). +:- use_module(library(http/http_dispatch)). /** <module> CPACK API for installing packages @@ -61,5 +65,74 @@ To *discover* a package, we will search for * Exported predicates (exact) */ - - +:- http_handler(root('cpack/'), cpack_install_data, [prefix]). + +%% cpack_install_data(+Request) +% +% Return installation info for installing Pack. The data is +% returned as a Prolog term. + +cpack_install_data(Request) :- + memberchk(path_info(PackName), Request), + ( rdf_has(Pack, cpack:packageName, literal(PackName)) + -> pack_install_data(Pack, Data), + format('Content-type: application/x-prolog~n~n'), + format('% Installation data for CPACK "~w"~n~n', [PackName]), + format('pack(~q, ~q).~n', [PackName, Data]) + ; format('Content-type: application/x-prolog~n~n'), + format('% Installation data for CPACK "~w"~n~n', [PackName]), + format('no_pack(~q).~n', [PackName]) + ). + + +%% pack_install_data(+Pack, -Data) is det. +% +% Provides the information to install Pack. Data is a list of +% packages. Each element is a term pack(Name, Options). The +% packages are topologically sorted on their dependency. +% +% The option list for each package may hold the following +% information: +% +% * title(Title) +% * license(License) +% * pack_repository(git(URL,Options)) +% * author_repository(git(URL,Options)) +% Options include: +% - branch(Branch) +% - hash(Hash) +% - tag(Tag) +% * files(ListOfFile) +% Each file is a term file(Path, Options), where options is +% - module(Module) + +pack_install_data(Pack, Data) :- + cpack_list(Pack, List), + maplist(pack_info, List, Data). + +pack_info(Pack, pack(Name, Options)) :- + rdf_has(Pack, cpack:packageName, literal(Name)), + findall(O, pack_option(Pack, O), Options). + +pack_option(Pack, title(Title)) :- + rdf_has(Pack, dcterms:title, Literal), + literal_text(Literal, Title). +pack_option(Pack, pack_repository(Git)) :- + rdf_has(Pack, cpack:mirrorRepository, Mirror), + rdf_git_repo(Mirror, Git). +pack_option(Pack, author_repository(Git)) :- + rdf_has(Pack, cpack:clonedRepository, Mirror), + rdf_git_repo(Mirror, Git). +pack_option(Pack, files(FileData)) :- + findall(F, rdf_has(F, cpack:inPack, Pack), Files), + maplist(file_info, Files, FileData). + +rdf_git_repo(URI, git(GitURL,Options)) :- + rdf_has(URI, cpack:gitURL, GitURL), + findall(O, repo_info(URI,O), Options). + +repo_info(URI, branch(Branch)) :- + rdf_has(URI, cpack:branch, literal(Branch)). + +file_info(URI, module(M)) :- + rdf_has(URI, cpack:module, literal(M)). diff --git a/components/cpack.pl b/components/cpack.pl index bc4c4f7..2f9d062 100644 --- a/components/cpack.pl +++ b/components/cpack.pl @@ -96,7 +96,8 @@ cpack(Pack, _Options) --> \p_row(Pack, cpack:submittedDate), \p_row(Pack, cpack:requires), \p_row(Pack, cpack:clonedRepository), - \p_row(Pack, cpack:mirrorRepository) + \p_row(Pack, cpack:mirrorRepository), + \install_url_row(Pack) ]), br([class('after-ptable')]), div(class(description), @@ -110,6 +111,16 @@ cpack(Pack, _Options) --> ])). +%% install_url_row(+Pack)// + +install_url_row(Pack) --> + { rdf_has(Pack, cpack:packageName, literal(Name)), + cpack_uri(pack, Name, URL) + }, + html(tr([th('Install URL:'), td(a(href(URL), URL))])). + + + %% git_shortlog(+Pack, +Options)// % % Component that show the top-N most recent changes in Pack. diff --git a/components/cpack/graphs.pl b/components/cpack/graphs.pl index e9512c0..84005ac 100644 --- a/components/cpack/graphs.pl +++ b/components/cpack/graphs.pl @@ -46,6 +46,7 @@ % Show a package and its dependencies cpack_dependency_graph(URI, _Options) --> + { related(URI, _, _) }, !, html([ h3('Dependency graph'), \graphviz_graph(dependency_graph(URI), [ object_attributes([width('100%')]), @@ -55,6 +56,8 @@ cpack_dependency_graph(URI, _Options) --> shape_hook(shape(URI)) ]) ]). +cpack_dependency_graph(_URI, _Options) --> + []. %% shape(+Start, +URI, -Shape) is semidet. diff --git a/config-available/DEFAULTS b/config-available/DEFAULTS index ea13ea5..aee3b90 100644 --- a/config-available/DEFAULTS +++ b/config-available/DEFAULTS @@ -1 +1,2 @@ config(cpack_repository, link). +config(cpack_server, link). diff --git a/config-available/cpack_server.pl b/config-available/cpack_server.pl new file mode 100644 index 0000000..52e9529 --- /dev/null +++ b/config-available/cpack_server.pl @@ -0,0 +1,5 @@ +:- module(conf_cpack_server, []). +:- use_module(api(cpack)). + +/** <module> Enable CPACK package services +*/ diff --git a/lib/cpack/dependency.pl b/lib/cpack/dependency.pl index 84fa509..9c46abe 100644 --- a/lib/cpack/dependency.pl +++ b/lib/cpack/dependency.pl @@ -32,10 +32,13 @@ [ file_used_by_file_in_package/3, % +File, -UsedBy, -Package cpack_requires/3, % +Package, -Package, -Why cpack_conflicts/3, % +Package, -Package, -Why + cpack_list/2, % +Package, -ListOfImplied cpack_not_satisfied/2, % +Package, -Reasons file_not_satisfied/2, % +File, -Reasons file_imports_from/3 % +File, -Imports, -From ]). +:- use_module(library(assoc)). +:- use_module(library(ugraphs)). :- use_module(library(semweb/rdf_db)). :- use_module(library(semweb/rdfs)). :- use_module(repository). @@ -51,6 +54,7 @@ high-level dependencies between objects. Currently, we keep track of: * Conflict reasons - Packages holding files that provide the same module - Packages holding files with the same path + * Satisfied status @tbd Extend reasoning */ @@ -125,6 +129,54 @@ cpack_conflicts_by(Package, Conflict, same_file(Path,File1,File2)) :- rdf_has(Package, cpack:in_file, File1), rdf_has(Conflict, cpack:in_file, File2). + + /******************************* + * GRAPH * + *******************************/ + +%% cpack_list(+Pack, -PackList) is det. +% +% PackList is a list of all packages that need to be installed to +% get Pack working. This list is ensured to contain Pack. +% +% @tbd Toplogical sorting may not be possible. As ordering is +% not always necessary, we should try to relax +% dependencies if a topological sort is not possible due +% to cycles. There are two heuristics here. First of +% all, explicit (token) dependencies may be removed and +% second, libraries must be loaded before applications. + +cpack_list(Pack, Packs) :- + dependency_ugraph(Pack, Ugraph), + ( top_sort(Ugraph, Packs) + -> true + ; domain_error(non_cyclic_dependency_structure, Ugraph) + ). + + +%% dependency_ugraph(+Pack, -Ugraph) is det. +% +% Create a full dependency graph for pack as a ugraph. + +dependency_ugraph(Pack, Ugraph) :- + empty_assoc(Visited), + dependency_ugraph([Pack], Visited, Ugraph). + +dependency_ugraph([], _, []). +dependency_ugraph([H|T], Visited, Graph) :- + ( get_assoc(H, Visited, _) + -> dependency_ugraph(T, Visited, Graph) + ; findall(Required, cpack_requires(H, Required, _), RList), + Graph = [H-RList|More], + put_assoc(H, Visited, true, Visited2), + dependency_ugraph(T, Visited2, More) + ). + + + /******************************* + * SATISFIED * + *******************************/ + %% cpack_not_satisfied(+Package, -WhyNot) is semidet. % % True when WhyNot describes why Package is not satisfied. diff --git a/lib/cpack/repository.pl b/lib/cpack/repository.pl index eb43dc3..c3d1a31 100644 --- a/lib/cpack/repository.pl +++ b/lib/cpack/repository.pl @@ -41,6 +41,7 @@ :- use_module(library(lists)). :- use_module(library(record)). :- use_module(library(git)). +:- use_module(library(uri)). :- use_module(library(settings)). :- use_module(library(semweb/rdf_db)). :- use_module(library(semweb/rdf_turtle)). @@ -296,14 +297,22 @@ cpack_uri(Type, Name, URI) :- http_current_host(Request, Host, Port, [ global(true) ]), - format(atom(URI), 'http://~w:~w/cpack/~w~w', - [ Host, Port, Root, Name ]). - -type_root(package, 'packs/'). -type_root(file_ref, 'file_ref/'). -type_root(graph, 'graph/'). -type_root(prolog, 'prolog/'). -type_root(cliopatria, 'cliopatria/'). + uri_authority_data(host, AD, Host), + uri_authority_data(port, AD, Port), + uri_authority_components(Authority, AD), + uri_data(scheme, Data, http), + uri_data(authority, Data, Authority), + uri_data(path, Data, Root), + uri_components(Start, Data), + atom_concat(Start, Name, URI). + + +type_root(package, '/packs/'). +type_root(pack, '/cpack/'). % Sync with api(cpack)! +type_root(file_ref, '/file_ref/'). +type_root(graph, '/graph/'). +type_root(prolog, '/prolog/'). +type_root(cliopatria, '/cliopatria/'). package_graph(Package, Graph) :- cpack_uri(package, Package, Graph).