1:- module(bc_dep, [
    2    bc_check_dependencies/0
    3]).

Checks the dependency versions

*/

    8:- use_module(library(error)).    9
   10bc_check_dependencies:-
   11    check_swi,
   12    check_installed(smtp, v(0, 9, 4)),
   13    check_installed(docstore, v(2, 0, 2)),
   14    check_installed(arouter, v(2, 0, 0)),
   15    check_installed(simple_template, v(1, 0, 1)),
   16    check_installed(sort_dict, v(0, 0, 3)),
   17    check_installed(dict_schema, v(0, 0, 2)),
   18    check_installed(markdown, v(0, 0, 2)).
   19
   20check_swi:-
   21    current_prolog_flag(version, Version),
   22    (   Version < 70722
   23    ->  throw(error(bc_dep:old_swi_version(Version), _))
   24    ;   true).
   25
   26% Checks that the given version is
   27% installed. Throws an error when
   28% it is not.
   29
   30check_installed(Pack, Pattern):-
   31    must_be(atom, Pack),
   32    (   pack_property(Pack, version(Atom))
   33    ->  true
   34    ;   throw(error(bc_dep:pack_not_installed(Pack), _))),
   35    parse_version(Pack, Atom, Version),
   36    (   check_version(Pattern, Version)
   37    ->  true
   38    ;   throw(error(bc_dep:pack_version_mismatch(
   39            Pack, Pattern, Version), _))).
   40
   41% Checks that the version matches the
   42% pattern.
   43
   44check_version(Pattern, Version):-
   45    must_be(nonvar, Pattern),
   46    must_be(nonvar, Version),
   47    Pattern = v(Major, Minor, Patch),
   48    Version = v(CheckMajor, CheckMinor, CheckPatch),
   49    (   nonvar(Major)
   50    ->  CheckMajor = Major,
   51        (   nonvar(Minor)
   52        ->  (   CheckMinor = Minor
   53            ->  (   nonvar(Patch)
   54                ->  CheckPatch >= Patch
   55                ;   true)
   56            ;   (   CheckMinor < Minor
   57                ->  fail
   58                ;   true))
   59        ;   true)
   60    ;   true).
   61
   62% Parses version string like '0.0.9'
   63% into a term v(0, 0, 9).
   64
   65parse_version(Pack, Atom, Term):-
   66    must_be(atom, Pack),
   67    must_be(atom, Atom),
   68    (   atomic_list_concat(Tokens, '.', Atom),
   69        Tokens = [MajorAtom, MinorAtom, PatchAtom],
   70        atom_number(MajorAtom, Major),
   71        atom_number(MinorAtom, Minor),
   72        atom_number(PatchAtom, Patch),
   73        integer(Major),
   74        integer(Minor),
   75        integer(Patch)
   76    ->  Term = v(Major, Minor, Patch)
   77    ;   throw(error(bc_dep:invalid_pack_version(Pack, Atom), _))).
   78
   79% Provides messages to terminal.
   80
   81:- multifile(prolog:message//1).   82
   83% When pack is not installed at all.
   84
   85prolog:message(error(bc_dep:pack_not_installed(
   86        Pack), _)) -->
   87    ['Pack ~w is not installed.'-[Pack]].
   88
   89% When pack is installed but it has
   90% non-parseable version.
   91
   92prolog:message(error(bc_dep:invalid_pack_version(
   93        Pack, Atom), _)) -->
   94    ['Pack ~w has invalid version ~w.'-[Pack, Atom]].
   95
   96% When the SWI-Prolog has too old version.
   97
   98prolog:message(error(bc_dep:old_swi_version(
   99        Version), _)) -->
  100    {   Major is Version div 10000,
  101        Minor is (Version - Major * 10000) div 100,
  102        Patch is Version rem 100 },
  103    ['SWI-Prolog version ~w.~w.~w is too old.'-[Major, Minor, Patch]].
  104
  105% When the pack does not satisfy the
  106% required version.
  107
  108prolog:message(error(bc_dep:pack_version_mismatch(
  109        Pack, Pattern, Version), _)) -->
  110    ['Pack ~w has version ~w but required is ~w.'-[Pack, Version, Pattern]]