35
36:- module(swish_version_service, []). 37:- use_module(library(http/http_dispatch)). 38:- use_module(library(http/http_json)). 39:- use_module(library(http/http_parameters)). 40:- use_module(library(http/html_write)). 41:- use_module(library(git)). 42:- use_module(library(apply)). 43
44:- use_module(version). 45:- use_module(markdown).
54:- http_handler(swish(versions), versions, [id(versions)]). 55:- http_handler(swish(changes), changes, [id(changes)]). 56:- http_handler(swish(changelog), changelog, [id(changelog)]). 57
58versions(_Request) :-
59 prolog_version_atom(SWIVersion),
60 module_version_data(swish, SWISHVersion),
61 reply_json_dict(json{ prolog:
62 json{ brand: "SWI-Prolog",
63 version: SWIVersion
64 },
65 swish:SWISHVersion
66 }).
67
68module_version_data(Module, Dict) :-
69 findall(Name-Value, module_version_data(Module, Name, Value), Pairs),
70 dict_pairs(Dict, json, Pairs).
71
72module_version_data(Module, Name, Value) :-
73 git_module_property(Module, Term),
74 Term =.. [Name,Value].
82:- dynamic change_cache/3. 83:- volatile change_cache/3. 84
85:- multifile
86 user:message_hook/3. 87
88user:message_hook(make(done(_)), _, _) :-
89 retractall(change_cache(_,_,_)),
90 fail.
91
92changes(Request) :-
93 http_parameters(Request,
94 [ commit(Commit, [default(last)]),
95 show(Show, [oneof([tagged, all]), default(tagged)])
96 ]),
97 changes(Commit, Show, Changes),
98 reply_json_dict(Changes).
99
100changes(Commit, Show, Changes) :-
101 change_cache(Commit, Show, Changes),
102 !.
103changes(Commit, Show, Changes) :-
104 changes_nc(Commit, Show, Changes),
105 asserta(change_cache(Commit, Show, Changes)).
106
107changes_nc(Commit, Show, Changes) :-
108 Commit \== last,
109 git_module_property(swish, directory(Dir)),
110 atom_concat(Commit, '..', Revisions),
111 git_shortlog(Dir, ShortLog, [ revisions(Revisions) ]),
112 last_change(ShortLog, LastCommit, LastModified),
113 !,
114 include(filter_change(Show), ShortLog, ShowLog),
115 length(ShowLog, Count),
116 Changes = json{ commit: LastCommit,
117 date: LastModified,
118 changes: Count
119 }.
120changes_nc(_, _Show, Changes) :-
121 git_module_property(swish, directory(Dir)),
122 git_shortlog(Dir, ShortLog, [limit(1)]),
123 last_change(ShortLog, LastCommit, LastModified),
124 !,
125 Changes = json{ commit: LastCommit,
126 date: LastModified,
127 changes: 0
128 }.
129changes_nc(_Commit, _Show, Changes) :-
130 Changes = json{ changes: 0
131 }.
132
133
134last_change([LastEntry|_], LastCommit, LastModified) :-
135 git_log_data(commit_hash, LastEntry, LastCommit),
136 git_log_data(committer_date_unix, LastEntry, LastModified).
137
138filter_change(all, _Change).
139filter_change(tagged, Change) :-
140 git_log_data(subject, Change, Message0),
141 sub_string(Message0, Pre, _, _, ":"),
142 Pre > 0,
143 !,
144 sub_string(Message0, 0, Pre, _, Tag),
145 string_upper(Tag, Tag).
152changelog(Request) :-
153 http_parameters(Request,
154 [ commit(Since, [optional(true)]),
155 last(Count, [default(10)]),
156 show(Show, [oneof([tagged, all]), default(tagged)])
157 ]),
158 git_module_property(swish, directory(Dir)),
159 ( nonvar(Since)
160 -> atom_concat(Since, '..', Revisions),
161 Options = [ revisions(Revisions) ]
162 ; Options = [ limit(Count) ]
163 ),
164 git_shortlog(Dir, ShortLog, Options),
165 ( ShortLog = [LastEntry|_]
166 -> git_log_data(commit_hash, LastEntry, LastCommit),
167 git_log_data(committer_date_unix, LastEntry, LastModified),
168 convlist(changelog(Show), ShortLog, ChangeLog),
169 reply_json_dict(json{ commit: LastCommit,
170 date: LastModified,
171 changelog: ChangeLog
172 })
173 ; reply_json_dict(json{ message: "No changes"
174 })
175 ).
176
177changelog(Show, Entry,
178 json{commit:Commit,
179 author: Author,
180 committer_date_relative: When,
181 message: Message}) :-
182 git_log_data(subject, Entry, Message0),
183 format_commit_message(Show, Message0, Message),
184 git_log_data(commit_hash, Entry, Commit),
185 git_log_data(author_name, Entry, Author),
186 git_log_data(committer_date_relative, Entry, When).
187
188
189format_commit_message(tagged, Message0, Message) :-
190 sub_string(Message0, Pre, _, Post, ":"),
191 Pre > 0,
192 !,
193 sub_string(Message0, 0, Pre, _, Tag),
194 string_upper(Tag, Tag),
195 sub_string(Message0, _, Post, 0, Msg),
196 string_codes(Msg, Codes),
197 wiki_file_codes_to_dom(Codes, '/', DOM),
198 phrase(wiki_html(div(class('v-changelog-entry'),
199 [ span(class('v-changelog-tag'), Tag)
200 | DOM
201 ])),
202 Tokens),
203 with_output_to(string(Message), print_html(Tokens)).
204format_commit_message(all, Message0, Message) :-
205 format_commit_message(tagged, Message0, Message),
206 !.
207format_commit_message(all, Message0, Message) :-
208 string_codes(Message0, Codes),
209 wiki_file_codes_to_dom(Codes, '/', DOM),
210 phrase(wiki_html(div(class('v-changelog-entry'),
211 DOM)),
212 Tokens),
213 with_output_to(string(Message), print_html(Tokens)).
214
215 218
220
221:- if(\+catch(check_predicate_option(git:git_shortlog/3, 3, revisions(a)),
222 error(_,_), fail)). 223:- abolish(git:git_shortlog/3). 224git:(
225git_shortlog(Dir, ShortLog, Options) :-
226 ( option(revisions(Range), Options)
227 -> RangeSpec = [Range]
228 ; option(limit(Limit), Options, 10),
229 RangeSpec = ['-n', Limit]
230 ),
231 ( option(git_path(Path), Options)
232 -> Extra = ['--', Path]
233 ; option(path(Path), Options)
234 -> relative_file_name(Path, Dir, RelPath),
235 Extra = ['--', RelPath]
236 ; Extra = []
237 ),
238 git_format_string(git_log, Fields, Format),
239 append([[log, Format], RangeSpec, Extra], GitArgv),
240 git_process_output(GitArgv,
241 read_git_formatted(git_log, Fields, ShortLog),
242 [directory(Dir)])).
243:- endif.
Serve version details over HTTP
This module serves SWISH and Prolog version details over HTTP. This is file is normally loaded though the config file
version_info.pl
. This file is not loaded by default for security reasons. */