34
35:- module('$pack',
36 [ attach_packs/0,
37 attach_packs/1, 38 '$pack_detach'/2, 39 '$pack_attach'/1 40 ]).
41
42:- multifile user:file_search_path/2.
43:- dynamic user:file_search_path/2.
44
45:- dynamic
46 pack_dir/3, 47 pack/2. 48:- volatile
49 pack_dir/3,
50 pack/2.
51
52
53user:file_search_path(pack, app_data(pack)).
54user:file_search_path(pack, swi(pack)).
55
56user:file_search_path(library, PackLib) :-
57 pack_dir(_Name, prolog, PackLib).
58user:file_search_path(foreign, PackLib) :-
59 pack_dir(_Name, foreign, PackLib).
60
65
66'$pack_detach'(Name, Dir) :-
67 ( atom(Name)
68 -> true
69 ; throw(error(type_error(atom, Name), _))
70 ),
71 ( retract(pack(Name, Dir))
72 -> retractall(pack_dir(Name, _, _)),
73 reload_library_index
74 ; throw(error(existence_error(pack, Name), _))
75 ).
76
80
81'$pack_attach'(Dir) :-
82 attach_package(Dir),
83 !.
84'$pack_attach'(Dir) :-
85 ( exists_directory(Dir)
86 -> throw(error(existence_error(directory, Dir), _))
87 ; throw(error(domain_error(pack, Dir), _))
88 ).
89
93
94attach_packs :-
95 findall(PackDir, absolute_file_name(pack(.), PackDir,
96 [ file_type(directory),
97 access(read),
98 solutions(all)
99 ]),
100 PackDirs),
101 ( PackDirs \== []
102 -> remove_dups(PackDirs, UniquePackDirs, []),
103 forall('$member'(PackDir, UniquePackDirs),
104 attach_packs(PackDir))
105 ; true
106 ).
107
111
112remove_dups([], [], _).
113remove_dups([H|T0], T, Seen) :-
114 memberchk(H, Seen),
115 !,
116 remove_dups(T0, T, Seen).
117remove_dups([H|T0], [H|T], Seen) :-
118 remove_dups(T0, T, [H|Seen]).
119
120
124
125attach_packs(Dir) :-
126 catch(directory_files(Dir, Entries), _, fail),
127 !,
128 ensure_slash(Dir, SDir),
129 attach_packages(Entries, SDir).
130attach_packs(_).
131
132attach_packages([], _).
133attach_packages([H|T], Dir) :-
134 attach_package(H, Dir),
135 attach_packages(T, Dir).
136
137attach_package(Entry, Dir) :-
138 \+ special(Entry),
139 atom_concat(Dir, Entry, PackDir),
140 attach_package(PackDir),
141 !.
142attach_package(_, _).
143
144special(.).
145special(..).
146
147
151
152attach_package(PackDir) :-
153 atomic_list_concat([PackDir, '/pack.pl'], InfoFile),
154 access_file(InfoFile, read),
155 file_base_name(PackDir, Pack),
156 check_existing(Pack, PackDir),
157 foreign_dir(Pack, PackDir, ForeignDir),
158 prolog_dir(PackDir, PrologDir),
159 !,
160 assertz(pack(Pack, PackDir)),
161 assertz(pack_dir(Pack, prolog, PrologDir)),
162 update_autoload(PrologDir),
163 ( ForeignDir \== (-)
164 -> assertz(pack_dir(Pack, foreign, ForeignDir))
165 ; true
166 ),
167 print_message(silent, pack(attached(Pack, PackDir))).
168
169
173
174check_existing(Entry, Dir) :-
175 retract(pack(Entry, Dir)), 176 !,
177 retractall(pack_dir(Entry, _, _)).
178check_existing(Entry, Dir) :-
179 pack(Entry, OldDir),
180 !,
181 print_message(warning, pack(duplicate(Entry, OldDir, Dir))),
182 fail.
183check_existing(_, _).
184
185
186prolog_dir(PackDir, PrologDir) :-
187 atomic_list_concat([PackDir, '/prolog'], PrologDir),
188 exists_directory(PrologDir).
189
190update_autoload(PrologDir) :-
191 atom_concat(PrologDir, '/INDEX.pl', IndexFile),
192 ( exists_file(IndexFile)
193 -> reload_library_index
194 ; true
195 ).
196
197foreign_dir(Pack, PackDir, ForeignDir) :-
198 current_prolog_flag(arch, Arch),
199 atomic_list_concat([PackDir, '/lib'], ForeignBaseDir),
200 exists_directory(ForeignBaseDir),
201 !,
202 atomic_list_concat([PackDir, '/lib/', Arch], ForeignDir),
203 ( exists_directory(ForeignDir)
204 -> assertz(pack_dir(Pack, foreign, ForeignDir))
205 ; print_message(warning, pack(no_arch(Pack, Arch))),
206 fail
207 ).
208foreign_dir(_, _, (-)).
209
210ensure_slash(Dir, SDir) :-
211 ( sub_atom(Dir, _, _, 0, /)
212 -> SDir = Dir
213 ; atom_concat(Dir, /, SDir)
214 ).