Mercurial > hg > octave-lyh
annotate scripts/pkg/pkg.m @ 9220:70177bf9cc16
Fix bug when calling pkg describe to check whether a package is installed
author | Carlo de Falco <kingcrimson@tiscali.it> |
---|---|
date | Tue, 19 May 2009 15:59:37 +0200 |
parents | 5247e89688e1 |
children | a653c61ee98c |
rev | line source |
---|---|
9051
1bf0ce0930be
Grammar check TexInfo in all .m files
Rik <rdrider0-list@yahoo.com>
parents:
8942
diff
changeset
|
1 ## Copyright (C) 2005, 2006, 2007, 2008, 2009 S�ren Hauberg |
5801 | 2 ## |
6440 | 3 ## This file is part of Octave. |
4 ## | |
5 ## Octave is free software; you can redistribute it and/or modify it | |
6 ## under the terms of the GNU General Public License as published by | |
7016 | 7 ## the Free Software Foundation; either version 3 of the License, or (at |
8 ## your option) any later version. | |
6440 | 9 ## |
10 ## Octave is distributed in the hope that it will be useful, but | |
11 ## WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 ## General Public License for more details. | |
14 ## | |
5801 | 15 ## You should have received a copy of the GNU General Public License |
7016 | 16 ## along with Octave; see the file COPYING. If not, see |
17 ## <http://www.gnu.org/licenses/>. | |
5801 | 18 |
19 ## -*- texinfo -*- | |
6032 | 20 ## @deftypefn {Command} pkg @var{command} @var{pkg_name} |
21 ## @deftypefnx {Command} pkg @var{command} @var{option} @var{pkg_name} | |
9051
1bf0ce0930be
Grammar check TexInfo in all .m files
Rik <rdrider0-list@yahoo.com>
parents:
8942
diff
changeset
|
22 ## This command interacts with the package manager. Different actions will |
6378 | 23 ## be taken depending on the value of @var{command}. |
6032 | 24 ## |
25 ## @table @samp | |
26 ## @item install | |
6070 | 27 ## Install named packages. For example, |
28 ## @example | |
29 ## pkg install image-1.0.0.tar.gz | |
30 ## @end example | |
31 ## @noindent | |
32 ## installs the package found in the file @code{image-1.0.0.tar.gz}. | |
33 ## | |
6645 | 34 ## The @var{option} variable can contain options that affect the manner |
9051
1bf0ce0930be
Grammar check TexInfo in all .m files
Rik <rdrider0-list@yahoo.com>
parents:
8942
diff
changeset
|
35 ## in which a package is installed. These options can be one or more of |
6645 | 36 ## |
37 ## @table @code | |
38 ## @item -nodeps | |
9051
1bf0ce0930be
Grammar check TexInfo in all .m files
Rik <rdrider0-list@yahoo.com>
parents:
8942
diff
changeset
|
39 ## The package manager will disable the dependency checking. That way it |
6645 | 40 ## is possible to install a package even if it depends on another package |
9051
1bf0ce0930be
Grammar check TexInfo in all .m files
Rik <rdrider0-list@yahoo.com>
parents:
8942
diff
changeset
|
41 ## that's not installed on the system. @strong{Use this option with care.} |
6645 | 42 ## |
43 ## @item -noauto | |
44 ## The package manager will not automatically load the installed package | |
45 ## when starting Octave, even if the package requests that it is. | |
6258 | 46 ## |
6645 | 47 ## @item -auto |
48 ## The package manager will automatically load the installed package when | |
49 ## starting Octave, even if the package requests that it isn't. | |
50 ## | |
51 ## @item -local | |
52 ## A local installation is forced, even if the user has system privileges. | |
6258 | 53 ## |
6645 | 54 ## @item -global |
55 ## A global installation is forced, even if the user doesn't normally have | |
56 ## system privileges | |
6614 | 57 ## |
6645 | 58 ## @item -verbose |
59 ## The package manager will print the output of all of the commands that are | |
60 ## performed. | |
61 ## @end table | |
62 ## | |
6032 | 63 ## @item uninstall |
6070 | 64 ## Uninstall named packages. For example, |
65 ## @example | |
66 ## pkg uninstall image | |
67 ## @end example | |
68 ## @noindent | |
9051
1bf0ce0930be
Grammar check TexInfo in all .m files
Rik <rdrider0-list@yahoo.com>
parents:
8942
diff
changeset
|
69 ## removes the @code{image} package from the system. If another installed |
6070 | 70 ## package depends on the @code{image} package an error will be issued. |
71 ## The package can be uninstalled anyway by using the @code{-nodeps} option. | |
6032 | 72 ## @item load |
9051
1bf0ce0930be
Grammar check TexInfo in all .m files
Rik <rdrider0-list@yahoo.com>
parents:
8942
diff
changeset
|
73 ## Add named packages to the path. After loading a package it is |
1bf0ce0930be
Grammar check TexInfo in all .m files
Rik <rdrider0-list@yahoo.com>
parents:
8942
diff
changeset
|
74 ## possible to use the functions provided by the package. For example, |
6070 | 75 ## @example |
76 ## pkg load image | |
77 ## @end example | |
78 ## @noindent | |
9051
1bf0ce0930be
Grammar check TexInfo in all .m files
Rik <rdrider0-list@yahoo.com>
parents:
8942
diff
changeset
|
79 ## adds the @code{image} package to the path. It is possible to load all |
6070 | 80 ## installed packages at once with the command |
81 ## @example | |
82 ## pkg load all | |
83 ## @end example | |
6203 | 84 ## @item unload |
9051
1bf0ce0930be
Grammar check TexInfo in all .m files
Rik <rdrider0-list@yahoo.com>
parents:
8942
diff
changeset
|
85 ## Removes named packages from the path. After unloading a package it is |
6203 | 86 ## no longer possible to use the functions provided by the package. |
87 ## This command behaves like the @code{load} command. | |
6032 | 88 ## @item list |
9051
1bf0ce0930be
Grammar check TexInfo in all .m files
Rik <rdrider0-list@yahoo.com>
parents:
8942
diff
changeset
|
89 ## Show a list of the currently installed packages. By requesting one or two |
6070 | 90 ## output argument it is possible to get a list of the currently installed |
9051
1bf0ce0930be
Grammar check TexInfo in all .m files
Rik <rdrider0-list@yahoo.com>
parents:
8942
diff
changeset
|
91 ## packages. For example, |
6070 | 92 ## @example |
93 ## installed_packages = pkg list; | |
94 ## @end example | |
95 ## @noindent | |
96 ## returns a cell array containing a structure for each installed package. | |
97 ## The command | |
98 ## @example | |
99 ## [@var{user_packages}, @var{system_packages}] = pkg list | |
100 ## @end example | |
101 ## @noindent | |
102 ## splits the list of installed packages into those who are installed by | |
103 ## the current user, and those installed by the system administrator. | |
7497 | 104 ## @item describe |
105 ## Show a short description of the named installed packages, with the option | |
106 ## '-verbose' also list functions provided by the package, e.g.: | |
107 ## @example | |
108 ## pkg describe -verbose all | |
109 ## @end example | |
110 ## @noindent | |
111 ## will describe all installed packages and the functions they provide. | |
112 ## If one output is requested a cell of structure containing the | |
113 ## description and list of functions of each package is returned as | |
114 ## output rather than printed on screen: | |
115 ## @example | |
116 ## desc = pkg ("describe", "secs1d", "image") | |
117 ## @end example | |
118 ## @noindent | |
119 ## If any of the requested packages is not installed, pkg returns an | |
120 ## error, unless a second output is requested: | |
121 ## @example | |
122 ## [ desc, flag] = pkg ("describe", "secs1d", "image") | |
123 ## @end example | |
124 ## @noindent | |
125 ## @var{flag} will take one of the values "Not installed", "Loaded" or | |
126 ## "Not loaded" for each of the named packages. | |
6034 | 127 ## @item prefix |
9051
1bf0ce0930be
Grammar check TexInfo in all .m files
Rik <rdrider0-list@yahoo.com>
parents:
8942
diff
changeset
|
128 ## Set the installation prefix directory. For example, |
6070 | 129 ## @example |
130 ## pkg prefix ~/my_octave_packages | |
131 ## @end example | |
132 ## @noindent | |
133 ## sets the installation prefix to @code{~/my_octave_packages}. | |
134 ## Packages will be installed in this directory. | |
6034 | 135 ## |
6070 | 136 ## It is possible to get the current installation prefix by requesting an |
137 ## output argument. For example, | |
138 ## @example | |
139 ## p = pkg prefix | |
140 ## @end example | |
6925 | 141 ## |
142 ## The location in which to install the architecture dependent files can be | |
9051
1bf0ce0930be
Grammar check TexInfo in all .m files
Rik <rdrider0-list@yahoo.com>
parents:
8942
diff
changeset
|
143 ## independent specified with an addition argument. For example |
6925 | 144 ## |
145 ## @example | |
9153
5247e89688e1
Eliminate most overfull errors when running texi2pdf for generating pdf documentation
Rik <rdrider0-list@yahoo.com>
parents:
9079
diff
changeset
|
146 ## pkg prefix ~/my_octave_packages ~/my_arch_dep_pkgs |
6925 | 147 ## @end example |
6189 | 148 ## @item local_list |
149 ## Set the file in which to look for information on the locally | |
9051
1bf0ce0930be
Grammar check TexInfo in all .m files
Rik <rdrider0-list@yahoo.com>
parents:
8942
diff
changeset
|
150 ## installed packages. Locally installed packages are those that are |
1bf0ce0930be
Grammar check TexInfo in all .m files
Rik <rdrider0-list@yahoo.com>
parents:
8942
diff
changeset
|
151 ## typically available only to the current user. For example |
6189 | 152 ## @example |
153 ## pkg local_list ~/.octave_packages | |
154 ## @end example | |
155 ## It is possible to get the current value of local_list with the following | |
156 ## @example | |
157 ## pkg local_list | |
158 ## @end example | |
159 ## @item global_list | |
160 ## Set the file in which to look for, for information on the globally | |
9051
1bf0ce0930be
Grammar check TexInfo in all .m files
Rik <rdrider0-list@yahoo.com>
parents:
8942
diff
changeset
|
161 ## installed packages. Globally installed packages are those that are |
1bf0ce0930be
Grammar check TexInfo in all .m files
Rik <rdrider0-list@yahoo.com>
parents:
8942
diff
changeset
|
162 ## typically available to all users. For example |
6189 | 163 ## @example |
164 ## pkg global_list /usr/share/octave/octave_packages | |
165 ## @end example | |
166 ## It is possible to get the current value of global_list with the following | |
167 ## @example | |
168 ## pkg global_list | |
169 ## @end example | |
6645 | 170 ## @item rebuild |
9051
1bf0ce0930be
Grammar check TexInfo in all .m files
Rik <rdrider0-list@yahoo.com>
parents:
8942
diff
changeset
|
171 ## Rebuilds the package database from the installed directories. This can |
6645 | 172 ## be used in cases where for some reason the package database is corrupted. |
173 ## It can also take the @code{-auto} and @code{-noauto} options to allow the | |
9079
4d610aba7347
Cleanup documentation for system.texi, package.texi
Rik <rdrider0-list@yahoo.com>
parents:
9051
diff
changeset
|
174 ## autoloading state of a package to be changed. For example |
6645 | 175 ## |
176 ## @example | |
177 ## pkg rebuild -noauto image | |
178 ## @end example | |
179 ## | |
180 ## will remove the autoloading status of the image package. | |
6675 | 181 ## @item build |
9051
1bf0ce0930be
Grammar check TexInfo in all .m files
Rik <rdrider0-list@yahoo.com>
parents:
8942
diff
changeset
|
182 ## Builds a binary form of a package or packages. The binary file produced |
6675 | 183 ## will itself be an Octave package that can be installed normally with |
9051
1bf0ce0930be
Grammar check TexInfo in all .m files
Rik <rdrider0-list@yahoo.com>
parents:
8942
diff
changeset
|
184 ## @code{pkg}. The form of the command to build a binary package is |
6675 | 185 ## |
186 ## @example | |
187 ## pkg build builddir image-1.0.0.tar.gz @dots{} | |
188 ## @end example | |
189 ## | |
190 ## @noindent | |
9079
4d610aba7347
Cleanup documentation for system.texi, package.texi
Rik <rdrider0-list@yahoo.com>
parents:
9051
diff
changeset
|
191 ## where @code{builddir} is the name of a directory where the temporary |
6675 | 192 ## installation will be produced and the binary packages will be found. |
193 ## The options @code{-verbose} and @code{-nodeps} are respected, while | |
194 ## the other options are ignored. | |
6032 | 195 ## @end table |
5801 | 196 ## @end deftypefn |
5947 | 197 |
6496 | 198 function [local_packages, global_packages] = pkg (varargin) |
8202
cf59d542f33e
replace all TODOs and XXXs with FIXMEs
Jaroslav Hajek <highegg@gmail.com>
parents:
8174
diff
changeset
|
199 ## Installation prefix (FIXME: what should these be on windows?) |
6645 | 200 persistent user_prefix = false; |
6496 | 201 persistent prefix = -1; |
6925 | 202 persistent archprefix = -1; |
7498 | 203 persistent local_list = tilde_expand (fullfile ("~", ".octave_packages")); |
6496 | 204 persistent global_list = fullfile (OCTAVE_HOME (), "share", "octave", |
205 "octave_packages"); | |
206 mlock (); | |
6189 | 207 |
6925 | 208 global_install = issuperuser (); |
6683 | 209 |
6496 | 210 if (prefix == -1) |
6645 | 211 if (global_install) |
6496 | 212 prefix = fullfile (OCTAVE_HOME (), "share", "octave", "packages"); |
7498 | 213 archprefix = fullfile (octave_config_info ("libexecdir"), |
214 "octave", "packages"); | |
6496 | 215 else |
216 prefix = fullfile ("~", "octave"); | |
6925 | 217 archprefix = prefix; |
5801 | 218 endif |
6645 | 219 prefix = tilde_expand (prefix); |
6925 | 220 archprefix = tilde_expand (archprefix); |
6496 | 221 endif |
222 | |
7498 | 223 available_actions = {"list", "install", "uninstall", "load", ... |
224 "unload", "prefix", "local_list", ... | |
225 "global_list", "rebuild", "build","describe"}; | |
6496 | 226 ## Handle input |
227 if (length (varargin) == 0 || ! iscellstr (varargin)) | |
228 print_usage (); | |
229 endif | |
230 files = {}; | |
231 deps = true; | |
232 auto = 0; | |
233 action = "none"; | |
6614 | 234 verbose = false; |
6496 | 235 for i = 1:length (varargin) |
236 switch (varargin{i}) | |
237 case "-nodeps" | |
238 deps = false; | |
239 case "-noauto" | |
240 auto = -1; | |
241 case "-auto" | |
242 auto = 1; | |
6614 | 243 case "-verbose" |
244 verbose = true; | |
6645 | 245 case "-local" |
246 global_install = false; | |
247 if (! user_prefix) | |
6729 | 248 prefix = tilde_expand (fullfile ("~", "octave")); |
7739
ca9bfe159144
Set archprefix for -local and -global options to pkg
David Bateman <dbateman@free.fr>
parents:
7632
diff
changeset
|
249 archprefix = prefix; |
6645 | 250 endif |
251 case "-global" | |
252 global_install = true; | |
253 if (! user_prefix) | |
254 prefix = fullfile (OCTAVE_HOME (), "share", "octave", "packages"); | |
7739
ca9bfe159144
Set archprefix for -local and -global options to pkg
David Bateman <dbateman@free.fr>
parents:
7632
diff
changeset
|
255 archprefix = fullfile (octave_config_info ("libexecdir"), |
ca9bfe159144
Set archprefix for -local and -global options to pkg
David Bateman <dbateman@free.fr>
parents:
7632
diff
changeset
|
256 "octave", "packages"); |
6645 | 257 endif |
7497 | 258 case available_actions |
6925 | 259 if (strcmp (action, "none")) |
6687 | 260 action = varargin{i}; |
261 else | |
262 error ("more than one action specified"); | |
263 endif | |
6496 | 264 otherwise |
265 files{end+1} = varargin{i}; | |
5801 | 266 endswitch |
6496 | 267 endfor |
268 | |
269 ## Take action | |
270 switch (action) | |
271 case "list" | |
272 if (nargout == 0) | |
273 installed_packages (local_list, global_list); | |
274 elseif (nargout == 1) | |
275 local_packages = installed_packages (local_list, global_list); | |
276 elseif (nargout == 2) | |
277 [local_packages, global_packages] = installed_packages (local_list, | |
278 global_list); | |
279 else | |
280 error ("too many output arguments requested"); | |
281 endif | |
282 | |
283 case "install" | |
284 if (length (files) == 0) | |
285 error ("you must specify at least one filename when calling 'pkg install'"); | |
286 endif | |
6925 | 287 install (files, deps, auto, prefix, archprefix, verbose, local_list, |
6645 | 288 global_list, global_install); |
6496 | 289 |
290 case "uninstall" | |
291 if (length (files) == 0) | |
292 error ("you must specify at least one package when calling 'pkg uninstall'"); | |
293 endif | |
6645 | 294 uninstall (files, deps, verbose, local_list, |
295 global_list, global_install); | |
6496 | 296 |
297 case "load" | |
298 if (length (files) == 0) | |
299 error ("you must specify at least one package, 'all' or 'auto' when calling 'pkg load'"); | |
300 endif | |
301 load_packages (files, deps, local_list, global_list); | |
302 | |
303 case "unload" | |
304 if (length (files) == 0) | |
305 error ("you must specify at least one package or 'all' when calling 'pkg unload'"); | |
306 endif | |
307 unload_packages (files, deps, local_list, global_list); | |
308 | |
309 case "prefix" | |
310 if (length (files) == 0 && nargout == 0) | |
6925 | 311 printf ("Installation prefix: %s\n", prefix); |
312 printf ("Architecture dependent prefix: %s\n", archprefix); | |
313 elseif (length (files) == 0 && nargout >= 1) | |
6496 | 314 local_packages = prefix; |
6925 | 315 global_packages = archprefix; |
316 elseif (length (files) >= 1 && nargout <= 2 && ischar (files{1})) | |
6496 | 317 prefix = files{1}; |
6675 | 318 prefix = absolute_pathname (prefix); |
319 local_packages = prefix; | |
6645 | 320 user_prefix = true; |
6925 | 321 if (length (files) >= 2 && ischar (files{2})) |
322 archprefix = files{2}; | |
323 try | |
324 archprefix = absolute_pathname (archprefix); | |
325 catch | |
326 mkdir (archprefix); | |
327 warning ("creating the directory %s\n", archprefix); | |
328 archprefix = absolute_pathname (archprefix); | |
329 end_try_catch | |
330 global_packages = archprefix; | |
331 endif | |
6496 | 332 else |
333 error ("you must specify a prefix directory, or request an output argument"); | |
334 endif | |
335 | |
336 case "local_list" | |
337 if (length (files) == 0 && nargout == 0) | |
338 disp (local_list); | |
339 elseif (length (files) == 0 && nargout == 1) | |
340 local_packages = local_list; | |
341 elseif (length (files) == 1 && nargout == 0 && ischar (files{1})) | |
6729 | 342 try |
343 local_list = absolute_pathname (files{1}); | |
344 catch | |
345 ## Force file to be created | |
7498 | 346 fclose (fopen (files{1}, "wt")); |
6729 | 347 local_list = absolute_pathname (files{1}); |
348 end_try_catch | |
6496 | 349 else |
350 error ("you must specify a local_list file, or request an output argument"); | |
351 endif | |
352 | |
353 case "global_list" | |
354 if (length (files) == 0 && nargout == 0) | |
355 disp(global_list); | |
356 elseif (length (files) == 0 && nargout == 1) | |
357 local_packages = global_list; | |
358 elseif (length (files) == 1 && nargout == 0 && ischar (files{1})) | |
6729 | 359 try |
360 global_list = absolute_pathname (files{1}); | |
361 catch | |
362 ## Force file to be created | |
7498 | 363 fclose (fopen (files{1}, "wt")); |
6729 | 364 global_list = absolute_pathname (files{1}); |
365 end_try_catch | |
6496 | 366 else |
367 error ("you must specify a global_list file, or request an output argument"); | |
368 endif | |
6645 | 369 |
370 case "rebuild" | |
371 if (global_install) | |
6925 | 372 global_packages = rebuild (prefix, archprefix, global_list, files, |
373 auto, verbose); | |
6695 | 374 global_packages = save_order (global_packages); |
6645 | 375 save (global_list, "global_packages"); |
6695 | 376 if (nargout > 0) |
377 local_packages = global_packages; | |
378 endif | |
6645 | 379 else |
6925 | 380 local_packages = rebuild (prefix, archprefix, local_list, files, auto, |
381 verbose); | |
6695 | 382 local_packages = save_order (local_packages); |
6645 | 383 save (local_list, "local_packages"); |
6695 | 384 if (nargout == 0) |
385 clear ("local_packages"); | |
386 endif | |
6645 | 387 endif |
388 | |
6675 | 389 case "build" |
390 if (length (files) < 2) | |
391 error ("you must specify at least the build directory and one filename\nwhen calling 'pkg build'"); | |
392 endif | |
393 build (files, deps, auto, verbose); | |
394 | |
7497 | 395 case "describe" |
396 if (length (files) == 0) | |
397 error ("you must specify at least one package or 'all' when calling 'pkg describe'"); | |
398 endif | |
8202
cf59d542f33e
replace all TODOs and XXXs with FIXMEs
Jaroslav Hajek <highegg@gmail.com>
parents:
8174
diff
changeset
|
399 ## FIXME: the name of the output variables is inconsistent |
7497 | 400 ## with their content |
401 switch (nargout) | |
7498 | 402 case 0 |
403 describe (files, verbose, local_list, global_list); | |
404 case 1 | |
405 pkg_desc_list = describe (files, verbose, local_list, ... | |
406 global_list); | |
407 local_packages = pkg_desc_list; | |
408 case 2 | |
409 [pkg_desc_list, flag] = describe (files, verbose, local_list, ... | |
410 global_list); | |
411 local_packages = pkg_desc_list; | |
412 global_packages = flag; | |
413 otherwise | |
414 error ("you can request at most two outputs when calling 'pkg describe'"); | |
415 endswitch | |
7497 | 416 |
6496 | 417 otherwise |
418 error ("you must specify a valid action for 'pkg'. See 'help pkg' for details"); | |
419 endswitch | |
420 endfunction | |
421 | |
6925 | 422 function descriptions = rebuild (prefix, archprefix, list, files, auto, verbose) |
6645 | 423 if (isempty (files)) |
424 [dirlist, err, msg] = readdir (prefix); | |
425 if (err) | |
426 error ("couldn't read directory %s: %s", prefix, msg); | |
427 endif | |
428 ## the two first entries of dirlist are "." and ".." | |
429 dirlist([1,2]) = []; | |
430 else | |
431 old_descriptions = installed_packages (list, list); | |
432 wd = pwd (); | |
6663 | 433 unwind_protect |
434 cd (prefix); | |
7540
3422f39573b1
strcat.m: Matlab compatibility, with cstrcat.m replacing conventional strcat.m.
Ben Abbott <bpabbott@mac.com>
parents:
7498
diff
changeset
|
435 dirlist = glob (cellfun(@(x) cstrcat(x, '-*'), files, 'UniformOutput', 0)); |
6663 | 436 unwind_protect_cleanup |
437 cd (wd); | |
438 end_unwind_protect | |
6645 | 439 endif |
440 descriptions = {}; | |
441 for k = 1:length (dirlist) | |
442 descfile = fullfile (prefix, dirlist{k}, "packinfo", "DESCRIPTION"); | |
443 if (verbose) | |
444 printf ("recreating package description from %s\n", dirlist{k}); | |
445 endif | |
446 if (exist (descfile, "file")) | |
447 desc = get_description (descfile); | |
448 desc.dir = fullfile (prefix, dirlist{k}); | |
7540
3422f39573b1
strcat.m: Matlab compatibility, with cstrcat.m replacing conventional strcat.m.
Ben Abbott <bpabbott@mac.com>
parents:
7498
diff
changeset
|
449 desc.archprefix = fullfile (archprefix, cstrcat (desc.name, "-", |
6925 | 450 desc.version)); |
6645 | 451 if (auto != 0) |
452 if (exist (fullfile (desc.dir, "packinfo", ".autoload"), "file")) | |
453 unlink (fullfile (desc.dir, "packinfo", ".autoload")); | |
454 endif | |
455 if (auto < 0) | |
456 desc.autoload = 0; | |
457 elseif (auto > 0) | |
458 desc.autoload = 1; | |
459 fclose (fopen (fullfile (desc.dir, "packinfo", ".autoload"), "wt")); | |
460 endif | |
461 else | |
462 if (exist (fullfile (desc.dir, "packinfo", ".autoload"), "file")) | |
463 desc.autoload = 1; | |
464 else | |
465 desc.autoload = 0; | |
466 endif | |
467 endif | |
468 descriptions{end + 1} = desc; | |
469 elseif (verbose) | |
470 warning ("directory %s is not a valid package", dirlist{k}); | |
471 endif | |
472 endfor | |
473 | |
6663 | 474 if (! isempty (files)) |
6645 | 475 ## We are rebuilding for a particular package(s) so we should take |
476 ## care to keep the other untouched packages in the descriptions | |
6663 | 477 descriptions = {descriptions{:}, old_descriptions{:}}; |
6645 | 478 |
479 dup = []; | |
480 for i = 1:length (descriptions) | |
481 if (find (dup, i)) | |
482 continue; | |
483 endif | |
484 for j = (i+1):length (descriptions) | |
485 if (find (dup, j)) | |
486 continue; | |
487 endif | |
488 if (strcmp (descriptions{i}.name, descriptions{j}.name)) | |
489 dup = [dup, j]; | |
490 endif | |
491 endfor | |
492 endfor | |
493 if (! isempty (dup)) | |
494 descriptions (dup) = []; | |
495 endif | |
496 endif | |
497 endfunction | |
498 | |
6675 | 499 function build (files, handle_deps, autoload, verbose) |
500 if (length (files) < 1) | |
501 error ("insufficient number of files"); | |
502 endif | |
503 builddir = files{1}; | |
504 if (! exist (builddir, "dir")) | |
505 warning ("creating build directory %s", builddir); | |
506 [status, msg] = mkdir (builddir); | |
507 if (status != 1) | |
508 error ("could not create installation directory: %s", msg); | |
509 endif | |
6496 | 510 endif |
6675 | 511 builddir = absolute_pathname (builddir); |
512 installdir = fullfile (builddir, "install"); | |
513 if (! exist (installdir, "dir")) | |
514 [status, msg] = mkdir (installdir); | |
515 if (status != 1) | |
516 error ("could not create installation directory: %s", msg); | |
517 endif | |
518 endif | |
519 files(1) = []; | |
520 buildlist = fullfile (builddir, "octave_packages"); | |
6925 | 521 install (files, handle_deps, autoload, installdir, installdir, verbose, |
6675 | 522 buildlist, "", false); |
523 unwind_protect | |
524 repackage (builddir, buildlist); | |
525 unwind_protect_cleanup | |
526 unload_packages ({"all"}, handle_deps, buildlist, ""); | |
527 if (exist (installdir, "dir")) | |
528 rm_rf (installdir); | |
529 endif | |
530 if (exist (buildlist, "file")) | |
531 unlink (buildlist); | |
532 endif | |
533 end_unwind_protect | |
5801 | 534 endfunction |
535 | |
6925 | 536 function install (files, handle_deps, autoload, prefix, archprefix, verbose, |
537 local_list, global_list, global_install) | |
6496 | 538 |
8506 | 539 ## Check that the directory in prefix exist. If it doesn't: create it! |
6496 | 540 if (! exist (prefix, "dir")) |
541 warning ("creating installation directory %s", prefix); | |
542 [status, msg] = mkdir (prefix); | |
543 if (status != 1) | |
544 error ("could not create installation directory: %s", msg); | |
545 endif | |
546 endif | |
547 | |
8506 | 548 ## Get the list of installed packages. |
6496 | 549 [local_packages, global_packages] = installed_packages (local_list, |
550 global_list); | |
551 | |
6820 | 552 installed_pkgs_lst = {local_packages{:}, global_packages{:}}; |
6496 | 553 |
554 if (global_install) | |
555 packages = global_packages; | |
556 else | |
557 packages = local_packages; | |
558 endif | |
559 | |
8506 | 560 ## Uncompress the packages and read the DESCRIPTION files. |
6496 | 561 tmpdirs = packdirs = descriptions = {}; |
562 try | |
8506 | 563 ## Warn about non existent files. |
6683 | 564 for i = 1:length (files) |
565 if (isempty (glob(files{i}))) | |
566 warning ("file %s does not exist", files{i}); | |
567 endif | |
568 endfor | |
569 | |
8506 | 570 ## Unpack the package files and read the DESCRIPTION files. |
6496 | 571 files = glob (files); |
572 packages_to_uninstall = []; | |
573 for i = 1:length (files) | |
574 tgz = files{i}; | |
575 | |
6645 | 576 if (exist (tgz, "file")) |
8506 | 577 ## Create a temporary directory. |
6645 | 578 tmpdir = tmpnam (); |
579 tmpdirs{end+1} = tmpdir; | |
580 if (verbose) | |
581 printf ("mkdir (%s)\n", tmpdir); | |
582 endif | |
583 [status, msg] = mkdir (tmpdir); | |
584 if (status != 1) | |
585 error ("couldn't create temporary directory: %s", msg); | |
586 endif | |
6496 | 587 |
8506 | 588 ## Uncompress the package. |
6645 | 589 if (verbose) |
590 printf ("untar (%s, %s)\n", tgz, tmpdir); | |
591 endif | |
592 untar (tgz, tmpdir); | |
6496 | 593 |
8506 | 594 ## Get the name of the directories produced by tar. |
6645 | 595 [dirlist, err, msg] = readdir (tmpdir); |
596 if (err) | |
597 error ("couldn't read directory produced by tar: %s", msg); | |
598 endif | |
6496 | 599 |
6645 | 600 if (length (dirlist) > 3) |
601 error ("bundles of packages are not allowed") | |
6496 | 602 endif |
7632
d6e63a15cc75
Allow installation of already extracted packages
Thomas Weber <thomas.weber.mail@gmail.com>
parents:
7548
diff
changeset
|
603 endif |
6496 | 604 |
8506 | 605 ## The filename pointed to an uncompressed package to begin with. |
7632
d6e63a15cc75
Allow installation of already extracted packages
Thomas Weber <thomas.weber.mail@gmail.com>
parents:
7548
diff
changeset
|
606 if (exist (tgz, "dir")) |
d6e63a15cc75
Allow installation of already extracted packages
Thomas Weber <thomas.weber.mail@gmail.com>
parents:
7548
diff
changeset
|
607 dirlist = {".", "..", tgz}; |
d6e63a15cc75
Allow installation of already extracted packages
Thomas Weber <thomas.weber.mail@gmail.com>
parents:
7548
diff
changeset
|
608 endif |
6645 | 609 |
7632
d6e63a15cc75
Allow installation of already extracted packages
Thomas Weber <thomas.weber.mail@gmail.com>
parents:
7548
diff
changeset
|
610 if (exist (tgz, "file") || exist (tgz, "dir")) |
8506 | 611 ## The two first entries of dirlist are "." and "..". |
7632
d6e63a15cc75
Allow installation of already extracted packages
Thomas Weber <thomas.weber.mail@gmail.com>
parents:
7548
diff
changeset
|
612 if (exist (tgz, "file")) |
d6e63a15cc75
Allow installation of already extracted packages
Thomas Weber <thomas.weber.mail@gmail.com>
parents:
7548
diff
changeset
|
613 packdir = fullfile (tmpdir, dirlist{3}); |
d6e63a15cc75
Allow installation of already extracted packages
Thomas Weber <thomas.weber.mail@gmail.com>
parents:
7548
diff
changeset
|
614 else |
d6e63a15cc75
Allow installation of already extracted packages
Thomas Weber <thomas.weber.mail@gmail.com>
parents:
7548
diff
changeset
|
615 packdir = fullfile (pwd(), dirlist{3}); |
d6e63a15cc75
Allow installation of already extracted packages
Thomas Weber <thomas.weber.mail@gmail.com>
parents:
7548
diff
changeset
|
616 endif |
d6e63a15cc75
Allow installation of already extracted packages
Thomas Weber <thomas.weber.mail@gmail.com>
parents:
7548
diff
changeset
|
617 packdirs{end+1} = packdir; |
d6e63a15cc75
Allow installation of already extracted packages
Thomas Weber <thomas.weber.mail@gmail.com>
parents:
7548
diff
changeset
|
618 |
8506 | 619 ## Make sure the package contains necessary files. |
7632
d6e63a15cc75
Allow installation of already extracted packages
Thomas Weber <thomas.weber.mail@gmail.com>
parents:
7548
diff
changeset
|
620 verify_directory (packdir); |
d6e63a15cc75
Allow installation of already extracted packages
Thomas Weber <thomas.weber.mail@gmail.com>
parents:
7548
diff
changeset
|
621 |
8506 | 622 ## Read the DESCRIPTION file. |
7632
d6e63a15cc75
Allow installation of already extracted packages
Thomas Weber <thomas.weber.mail@gmail.com>
parents:
7548
diff
changeset
|
623 filename = fullfile (packdir, "DESCRIPTION"); |
d6e63a15cc75
Allow installation of already extracted packages
Thomas Weber <thomas.weber.mail@gmail.com>
parents:
7548
diff
changeset
|
624 desc = get_description (filename); |
d6e63a15cc75
Allow installation of already extracted packages
Thomas Weber <thomas.weber.mail@gmail.com>
parents:
7548
diff
changeset
|
625 |
8506 | 626 ## Verify that package name corresponds with filename. |
7632
d6e63a15cc75
Allow installation of already extracted packages
Thomas Weber <thomas.weber.mail@gmail.com>
parents:
7548
diff
changeset
|
627 [dummy, nm] = fileparts (tgz); |
d6e63a15cc75
Allow installation of already extracted packages
Thomas Weber <thomas.weber.mail@gmail.com>
parents:
7548
diff
changeset
|
628 if ((length (nm) >= length (desc.name)) |
d6e63a15cc75
Allow installation of already extracted packages
Thomas Weber <thomas.weber.mail@gmail.com>
parents:
7548
diff
changeset
|
629 && ! strcmp (desc.name, nm(1:length(desc.name)))) |
d6e63a15cc75
Allow installation of already extracted packages
Thomas Weber <thomas.weber.mail@gmail.com>
parents:
7548
diff
changeset
|
630 error ("package name '%s' doesn't correspond to its filename '%s'", |
d6e63a15cc75
Allow installation of already extracted packages
Thomas Weber <thomas.weber.mail@gmail.com>
parents:
7548
diff
changeset
|
631 desc.name, nm); |
d6e63a15cc75
Allow installation of already extracted packages
Thomas Weber <thomas.weber.mail@gmail.com>
parents:
7548
diff
changeset
|
632 endif |
d6e63a15cc75
Allow installation of already extracted packages
Thomas Weber <thomas.weber.mail@gmail.com>
parents:
7548
diff
changeset
|
633 |
8506 | 634 ## Set default installation directory. |
7632
d6e63a15cc75
Allow installation of already extracted packages
Thomas Weber <thomas.weber.mail@gmail.com>
parents:
7548
diff
changeset
|
635 desc.dir = fullfile (prefix, cstrcat (desc.name, "-", desc.version)); |
d6e63a15cc75
Allow installation of already extracted packages
Thomas Weber <thomas.weber.mail@gmail.com>
parents:
7548
diff
changeset
|
636 |
8506 | 637 ## Set default architectire dependent installation directory. |
7632
d6e63a15cc75
Allow installation of already extracted packages
Thomas Weber <thomas.weber.mail@gmail.com>
parents:
7548
diff
changeset
|
638 desc.archprefix = fullfile (archprefix, cstrcat (desc.name, "-", |
d6e63a15cc75
Allow installation of already extracted packages
Thomas Weber <thomas.weber.mail@gmail.com>
parents:
7548
diff
changeset
|
639 desc.version)); |
d6e63a15cc75
Allow installation of already extracted packages
Thomas Weber <thomas.weber.mail@gmail.com>
parents:
7548
diff
changeset
|
640 |
8506 | 641 ## Save desc. |
7632
d6e63a15cc75
Allow installation of already extracted packages
Thomas Weber <thomas.weber.mail@gmail.com>
parents:
7548
diff
changeset
|
642 descriptions{end+1} = desc; |
d6e63a15cc75
Allow installation of already extracted packages
Thomas Weber <thomas.weber.mail@gmail.com>
parents:
7548
diff
changeset
|
643 |
d6e63a15cc75
Allow installation of already extracted packages
Thomas Weber <thomas.weber.mail@gmail.com>
parents:
7548
diff
changeset
|
644 ## Are any of the new packages already installed? |
d6e63a15cc75
Allow installation of already extracted packages
Thomas Weber <thomas.weber.mail@gmail.com>
parents:
7548
diff
changeset
|
645 ## If so we'll remove the old version. |
d6e63a15cc75
Allow installation of already extracted packages
Thomas Weber <thomas.weber.mail@gmail.com>
parents:
7548
diff
changeset
|
646 for j = 1:length (packages) |
d6e63a15cc75
Allow installation of already extracted packages
Thomas Weber <thomas.weber.mail@gmail.com>
parents:
7548
diff
changeset
|
647 if (strcmp (packages{j}.name, desc.name)) |
d6e63a15cc75
Allow installation of already extracted packages
Thomas Weber <thomas.weber.mail@gmail.com>
parents:
7548
diff
changeset
|
648 packages_to_uninstall(end+1) = j; |
6496 | 649 endif |
7632
d6e63a15cc75
Allow installation of already extracted packages
Thomas Weber <thomas.weber.mail@gmail.com>
parents:
7548
diff
changeset
|
650 endfor |
6645 | 651 endif |
6496 | 652 endfor |
653 catch | |
8506 | 654 ## Something went wrong, delete tmpdirs. |
6496 | 655 for i = 1:length (tmpdirs) |
656 rm_rf (tmpdirs{i}); | |
657 endfor | |
6655 | 658 rethrow (lasterror ()); |
6496 | 659 end_try_catch |
660 | |
8506 | 661 ## Check dependencies. |
6496 | 662 if (handle_deps) |
663 ok = true; | |
664 error_text = ""; | |
665 for i = 1:length (descriptions) | |
666 desc = descriptions{i}; | |
667 idx2 = complement (i, 1:length(descriptions)); | |
6695 | 668 if (global_install) |
669 ## Global installation is not allowed to have dependencies on locally | |
8506 | 670 ## installed packages. |
6695 | 671 idx1 = complement (packages_to_uninstall, |
672 1:length(global_packages)); | |
673 pseudo_installed_packages = {global_packages{idx1}, ... | |
674 descriptions{idx2}}; | |
675 else | |
676 idx1 = complement (packages_to_uninstall, | |
677 1:length(local_packages)); | |
678 pseudo_installed_packages = {local_packages{idx1}, ... | |
679 global_packages{:}, ... | |
680 descriptions{idx2}}; | |
681 endif | |
6496 | 682 bad_deps = get_unsatisfied_deps (desc, pseudo_installed_packages); |
683 ## Are there any unsatisfied dependencies? | |
684 if (! isempty (bad_deps)) | |
685 ok = false; | |
686 for i = 1:length (bad_deps) | |
687 dep = bad_deps{i}; | |
7540
3422f39573b1
strcat.m: Matlab compatibility, with cstrcat.m replacing conventional strcat.m.
Ben Abbott <bpabbott@mac.com>
parents:
7498
diff
changeset
|
688 error_text = cstrcat (error_text, " ", desc.name, " needs ", |
6496 | 689 dep.package, " ", dep.operator, " ", |
690 dep.version, "\n"); | |
691 endfor | |
692 endif | |
693 endfor | |
694 | |
695 ## Did we find any unsatisfied dependencies? | |
696 if (! ok) | |
697 error ("the following dependencies where unsatisfied:\n %s", error_text); | |
698 endif | |
699 endif | |
700 | |
8506 | 701 ## Prepare each package for installation. |
6496 | 702 try |
703 for i = 1:length (descriptions) | |
704 desc = descriptions{i}; | |
705 pdir = packdirs{i}; | |
706 prepare_installation (desc, pdir); | |
6614 | 707 configure_make (desc, pdir, verbose); |
6496 | 708 endfor |
709 catch | |
8506 | 710 ## Something went wrong, delete tmpdirs. |
6496 | 711 for i = 1:length (tmpdirs) |
712 rm_rf (tmpdirs{i}); | |
713 endfor | |
6655 | 714 rethrow (lasterror ()); |
6496 | 715 end_try_catch |
716 | |
8506 | 717 ## Uninstall the packages that will be replaced. |
6496 | 718 try |
719 for i = packages_to_uninstall | |
6695 | 720 if (global_install) |
721 uninstall ({global_packages{i}.name}, false, verbose, local_list, | |
722 global_list, global_install); | |
723 else | |
724 uninstall ({local_packages{i}.name}, false, verbose, local_list, | |
725 global_list, global_install); | |
726 endif | |
6496 | 727 endfor |
728 catch | |
8506 | 729 ## Something went wrong, delete tmpdirs. |
6496 | 730 for i = 1:length (tmpdirs) |
731 rm_rf (tmpdirs{i}); | |
732 endfor | |
6655 | 733 rethrow (lasterror ()); |
6496 | 734 end_try_catch |
735 | |
8506 | 736 ## Install each package. |
6496 | 737 try |
738 for i = 1:length (descriptions) | |
739 desc = descriptions{i}; | |
740 pdir = packdirs{i}; | |
6925 | 741 copy_files (desc, pdir, global_install); |
742 create_pkgadddel (desc, pdir, "PKG_ADD", global_install); | |
743 create_pkgadddel (desc, pdir, "PKG_DEL", global_install); | |
8575
f134925a1cfa
m-file implementation of help system
Soren Hauberg <soren@hauberg.org>
parents:
8507
diff
changeset
|
744 finish_installation (desc, pdir, global_install); |
f134925a1cfa
m-file implementation of help system
Soren Hauberg <soren@hauberg.org>
parents:
8507
diff
changeset
|
745 generate_lookfor_cache (desc); |
6496 | 746 endfor |
747 catch | |
8506 | 748 ## Something went wrong, delete tmpdirs. |
6496 | 749 for i = 1:length (tmpdirs) |
750 rm_rf (tmpdirs{i}); | |
751 endfor | |
752 for i = 1:length (descriptions) | |
753 rm_rf (descriptions{i}.dir); | |
6925 | 754 rm_rf (getarchdir (descriptions{i})); |
6496 | 755 endfor |
6655 | 756 rethrow (lasterror ()); |
6496 | 757 end_try_catch |
758 | |
759 ## Check if the installed directory is empty. If it is remove it | |
8506 | 760 ## from the list. |
6496 | 761 for i = length (descriptions):-1:1 |
6925 | 762 if (dirempty (descriptions{i}.dir, {"packinfo", "doc"}) && |
763 dirempty (getarchdir (descriptions{i}))) | |
6655 | 764 warning ("package %s is empty\n", descriptions{i}.name); |
6496 | 765 rm_rf (descriptions{i}.dir); |
6925 | 766 rm_rf (getarchdir (descriptions{i})); |
6496 | 767 descriptions(i) = []; |
768 endif | |
769 endfor | |
770 | |
771 ## If the package requested that it is autoloaded, or the installer | |
772 ## requested that it is, then mark the package as autoloaded. | |
773 for i = length (descriptions):-1:1 | |
774 if (autoload > 0 || (autoload == 0 && isautoload (descriptions(i)))) | |
775 fclose (fopen (fullfile (descriptions{i}.dir, "packinfo", | |
776 ".autoload"), "wt")); | |
6695 | 777 descriptions{i}.autoload = 1; |
6496 | 778 endif |
779 endfor | |
780 | |
8506 | 781 ## Add the packages to the package list. |
6496 | 782 try |
783 if (global_install) | |
784 idx = complement (packages_to_uninstall, 1:length(global_packages)); | |
6695 | 785 global_packages = save_order ({global_packages{idx}, descriptions{:}}); |
6496 | 786 save (global_list, "global_packages"); |
6820 | 787 installed_pkgs_lst = {local_packages{:}, global_packages{:}}; |
6496 | 788 else |
789 idx = complement (packages_to_uninstall, 1:length(local_packages)); | |
6695 | 790 local_packages = save_order ({local_packages{idx}, descriptions{:}}); |
6496 | 791 save (local_list, "local_packages"); |
6820 | 792 installed_pkgs_lst = {local_packages{:}, global_packages{:}}; |
6496 | 793 endif |
794 catch | |
8506 | 795 ## Something went wrong, delete tmpdirs. |
6496 | 796 for i = 1:length (tmpdirs) |
797 rm_rf (tmpdirs{i}); | |
798 endfor | |
799 for i = 1:length (descriptions) | |
800 rm_rf (descriptions{i}.dir); | |
801 endfor | |
802 if (global_install) | |
6695 | 803 printf ("error: couldn't append to %s\n", global_list); |
6496 | 804 else |
6695 | 805 printf ("error: couldn't append to %s\n", local_list); |
6496 | 806 endif |
6695 | 807 rethrow (lasterror ()); |
6496 | 808 end_try_catch |
809 | |
8506 | 810 ## All is well, let's clean up. |
6496 | 811 for i = 1:length (tmpdirs) |
812 [status, msg] = rm_rf (tmpdirs{i}); | |
813 if (status != 1) | |
814 warning ("couldn't clean up after my self: %s\n", msg); | |
815 endif | |
816 endfor | |
817 | |
818 ## Add the newly installed packages to the path, so the user | |
8506 | 819 ## can begin using them. Only load them if they are marked autoload. |
6496 | 820 if (length (descriptions) > 0) |
6695 | 821 idx = []; |
6496 | 822 for i = 1:length (descriptions) |
6695 | 823 if (isautoload (descriptions(i))) |
7192 | 824 nm = descriptions{i}.name; |
825 for j = 1:length (installed_pkgs_lst) | |
826 if (strcmp (nm, installed_pkgs_lst{j}.name)) | |
827 idx (end + 1) = j; | |
828 break; | |
829 endif | |
830 endfor | |
6614 | 831 endif |
6496 | 832 endfor |
6925 | 833 load_packages_and_dependencies (idx, handle_deps, installed_pkgs_lst, |
834 global_install); | |
6496 | 835 endif |
836 endfunction | |
837 | |
6645 | 838 function uninstall (pkgnames, handle_deps, verbose, local_list, |
839 global_list, global_install) | |
8506 | 840 ## Get the list of installed packages. |
6496 | 841 [local_packages, global_packages] = installed_packages(local_list, |
842 global_list); | |
6645 | 843 if (global_install) |
6820 | 844 installed_pkgs_lst = {local_packages{:}, global_packages{:}}; |
6496 | 845 else |
6820 | 846 installed_pkgs_lst = local_packages; |
6496 | 847 endif |
848 | |
6820 | 849 num_packages = length (installed_pkgs_lst); |
6496 | 850 delete_idx = []; |
851 for i = 1:num_packages | |
6820 | 852 cur_name = installed_pkgs_lst{i}.name; |
6496 | 853 if (any (strcmp (cur_name, pkgnames))) |
854 delete_idx(end+1) = i; | |
855 endif | |
856 endfor | |
857 | |
858 ## Are all the packages that should be uninstalled already installed? | |
859 if (length (delete_idx) != length (pkgnames)) | |
6645 | 860 if (global_install) |
8506 | 861 ## Try again for a locally installed package. |
6820 | 862 installed_pkgs_lst = local_packages; |
6496 | 863 |
6820 | 864 num_packages = length (installed_pkgs_lst); |
6496 | 865 delete_idx = []; |
866 for i = 1:num_packages | |
6820 | 867 cur_name = installed_pkgs_lst{i}.name; |
6496 | 868 if (any (strcmp (cur_name, pkgnames))) |
869 delete_idx(end+1) = i; | |
870 endif | |
871 endfor | |
872 if (length (delete_idx) != length (pkgnames)) | |
8506 | 873 ## FIXME: We should have a better error message. |
6655 | 874 warning ("some of the packages you want to uninstall are not installed"); |
6496 | 875 endif |
876 else | |
8506 | 877 ## FIXME: We should have a better error message. |
8664 | 878 warning ("some of the packages you want to uninstall are not installed"); |
6496 | 879 endif |
880 endif | |
881 | |
8506 | 882 ## Compute the packages that will remain installed. |
6496 | 883 idx = complement (delete_idx, 1:num_packages); |
6820 | 884 remaining_packages = {installed_pkgs_lst{idx}}; |
6496 | 885 |
8506 | 886 ## Check dependencies. |
6496 | 887 if (handle_deps) |
888 error_text = ""; | |
889 for i = 1:length (remaining_packages) | |
890 desc = remaining_packages{i}; | |
891 bad_deps = get_unsatisfied_deps (desc, remaining_packages); | |
892 | |
893 ## Will the uninstallation break any dependencies? | |
894 if (! isempty (bad_deps)) | |
895 for i = 1:length (bad_deps) | |
896 dep = bad_deps{i}; | |
7540
3422f39573b1
strcat.m: Matlab compatibility, with cstrcat.m replacing conventional strcat.m.
Ben Abbott <bpabbott@mac.com>
parents:
7498
diff
changeset
|
897 error_text = cstrcat (error_text, " ", desc.name, " needs ", |
6496 | 898 dep.package, " ", dep.operator, " ", |
899 dep.version, "\n"); | |
900 endfor | |
901 endif | |
902 endfor | |
903 | |
904 if (! isempty (error_text)) | |
905 error ("the following dependencies where unsatisfied:\n %s", error_text); | |
906 endif | |
907 endif | |
908 | |
8506 | 909 ## Delete the directories containing the packages. |
6496 | 910 for i = delete_idx |
6820 | 911 desc = installed_pkgs_lst{i}; |
6496 | 912 ## If an 'on_uninstall.m' exist, call it! |
913 if (exist (fullfile (desc.dir, "packinfo", "on_uninstall.m"), "file")) | |
6614 | 914 wd = pwd (); |
7498 | 915 cd (fullfile (desc.dir, "packinfo")); |
6614 | 916 on_uninstall (desc); |
917 cd (wd); | |
6496 | 918 endif |
8506 | 919 ## Do the actual deletion. |
6675 | 920 if (desc.loaded) |
921 rmpath (desc.dir); | |
6925 | 922 if (exist (getarchdir (desc))) |
923 rmpath (getarchdir (desc)); | |
6675 | 924 endif |
6614 | 925 endif |
6496 | 926 if (exist (desc.dir, "dir")) |
927 [status, msg] = rm_rf (desc.dir); | |
928 if (status != 1) | |
929 error ("couldn't delete directory %s: %s", desc.dir, msg); | |
930 endif | |
6925 | 931 [status, msg] = rm_rf (getarchdir (desc)); |
932 if (status != 1) | |
933 error ("couldn't delete directory %s: %s", getarchdir (desc), msg); | |
934 endif | |
935 if (dirempty (desc.archprefix)) | |
936 rm_rf (desc.archprefix); | |
937 endif | |
6496 | 938 else |
939 warning ("directory %s previously lost", desc.dir); | |
940 endif | |
941 endfor | |
942 | |
8506 | 943 ## Write a new ~/.octave_packages. |
6645 | 944 if (global_install) |
6496 | 945 if (length (remaining_packages) == 0) |
946 unlink (global_list); | |
947 else | |
6695 | 948 global_packages = save_order (remaining_packages); |
6496 | 949 save (global_list, "global_packages"); |
950 endif | |
951 else | |
952 if (length (remaining_packages) == 0) | |
953 unlink (local_list); | |
954 else | |
6695 | 955 local_packages = save_order (remaining_packages); |
6496 | 956 save (local_list, "local_packages"); |
957 endif | |
958 endif | |
959 | |
960 endfunction | |
961 | |
7497 | 962 function [pkg_desc_list, flag] = describe (pkgnames, verbose, |
963 local_list, global_list) | |
964 | |
8506 | 965 ## Get the list of installed packages. |
7497 | 966 installed_pkgs_lst = installed_packages(local_list, global_list); |
7498 | 967 num_packages = length (installed_pkgs_lst); |
7497 | 968 |
969 | |
7498 | 970 describe_all = false; |
971 if (any (strcmp ("all", pkgnames))) | |
972 describe_all = true; | |
8455
fd11a08a9b31
disallow invalid {}-indexed assigments
Jaroslav Hajek <highegg@gmail.com>
parents:
8202
diff
changeset
|
973 flag(1:num_packages) = {"Not Loaded"}; |
7498 | 974 num_pkgnames = num_packages; |
7497 | 975 else |
7498 | 976 num_pkgnames = length (pkgnames); |
8455
fd11a08a9b31
disallow invalid {}-indexed assigments
Jaroslav Hajek <highegg@gmail.com>
parents:
8202
diff
changeset
|
977 flag(1:num_pkgnames) = {"Not installed"}; |
7498 | 978 endif |
7497 | 979 |
980 for i = 1:num_packages | |
8507 | 981 curr_name = installed_pkgs_lst{i}.name; |
7497 | 982 if (describe_all) |
983 name_pos = i; | |
984 else | |
985 name_pos = find(strcmp (curr_name, pkgnames)); | |
7498 | 986 endif |
987 | |
988 if (! isempty (name_pos)) | |
7497 | 989 if (installed_pkgs_lst{i}.loaded) |
990 flag{name_pos} = "Loaded"; | |
991 else | |
992 flag{name_pos} = "Not loaded"; | |
993 endif | |
994 | |
7498 | 995 pkg_desc_list{name_pos}.name = installed_pkgs_lst{i}.name; |
996 pkg_desc_list{name_pos}.description = installed_pkgs_lst{i}.description; | |
997 pkg_desc_list{name_pos}.provides = parse_pkg_idx (installed_pkgs_lst{i}.dir); | |
7497 | 998 |
999 endif | |
1000 endfor | |
1001 | |
7498 | 1002 non_inst = find (strcmp (flag, "Not installed")); |
9220
70177bf9cc16
Fix bug when calling pkg describe to check whether a package is installed
Carlo de Falco <kingcrimson@tiscali.it>
parents:
9153
diff
changeset
|
1003 if (! isempty (non_inst)) |
70177bf9cc16
Fix bug when calling pkg describe to check whether a package is installed
Carlo de Falco <kingcrimson@tiscali.it>
parents:
9153
diff
changeset
|
1004 if (nargout < 2) |
70177bf9cc16
Fix bug when calling pkg describe to check whether a package is installed
Carlo de Falco <kingcrimson@tiscali.it>
parents:
9153
diff
changeset
|
1005 non_inst_str = sprintf (" %s ", pkgnames{non_inst}); |
70177bf9cc16
Fix bug when calling pkg describe to check whether a package is installed
Carlo de Falco <kingcrimson@tiscali.it>
parents:
9153
diff
changeset
|
1006 error ("some packages are not installed: %s", non_inst_str); |
70177bf9cc16
Fix bug when calling pkg describe to check whether a package is installed
Carlo de Falco <kingcrimson@tiscali.it>
parents:
9153
diff
changeset
|
1007 else |
70177bf9cc16
Fix bug when calling pkg describe to check whether a package is installed
Carlo de Falco <kingcrimson@tiscali.it>
parents:
9153
diff
changeset
|
1008 pkg_desc_list{non_inst} = struct ("name", {}, "description", |
70177bf9cc16
Fix bug when calling pkg describe to check whether a package is installed
Carlo de Falco <kingcrimson@tiscali.it>
parents:
9153
diff
changeset
|
1009 {}, "provides", {}); |
70177bf9cc16
Fix bug when calling pkg describe to check whether a package is installed
Carlo de Falco <kingcrimson@tiscali.it>
parents:
9153
diff
changeset
|
1010 endif |
7497 | 1011 endif |
1012 | |
1013 if (nargout == 0) | |
7498 | 1014 for i = 1:num_pkgnames |
7497 | 1015 print_package_description (pkg_desc_list{i}.name, |
1016 pkg_desc_list{i}.provides, | |
1017 pkg_desc_list{i}.description, | |
1018 flag{i}, verbose); | |
1019 endfor | |
1020 endif | |
1021 | |
1022 endfunction | |
1023 | |
8506 | 1024 ## AUXILIARY FUNCTIONS |
6496 | 1025 |
8506 | 1026 ## Read an INDEX file. |
7498 | 1027 function [pkg_idx_struct] = parse_pkg_idx (packdir) |
7497 | 1028 |
7498 | 1029 index_file = fullfile (packdir, "packinfo", "INDEX"); |
1030 | |
1031 if (! exist (index_file, "file")) | |
1032 error ("could not find any INDEX file in directory %s, try 'pkg rebuild all' to generate missing INDEX files", packdir); | |
7497 | 1033 endif |
1034 | |
1035 | |
7498 | 1036 [fid, msg] = fopen (index_file, "r"); |
7497 | 1037 if (fid == -1) |
7498 | 1038 error ("the INDEX file %s could not be read: %s", |
1039 index_file, msg); | |
7497 | 1040 endif |
7498 | 1041 |
7497 | 1042 cat_num = 1; |
1043 pkg_idx_struct{1}.category = "Uncategorized"; | |
1044 pkg_idx_struct{1}.functions = {}; | |
1045 | |
7498 | 1046 line = fgetl (fid); |
1047 while (isempty (strfind (line, ">>")) && ! feof (fid)) | |
1048 line = fgetl (fid); | |
7497 | 1049 endwhile |
1050 | |
7498 | 1051 while (! feof (fid) || line != -1) |
1052 if (! any (! isspace (line)) || line(1) == "#" || any (line == "=")) | |
7497 | 1053 ## Comments, blank lines or comments about unimplemented |
1054 ## functions: do nothing | |
8202
cf59d542f33e
replace all TODOs and XXXs with FIXMEs
Jaroslav Hajek <highegg@gmail.com>
parents:
8174
diff
changeset
|
1055 ## FIXME: probably comments and pointers to external functions |
7497 | 1056 ## could be treated better when printing to screen? |
7498 | 1057 elseif (! isempty (strfind (line, ">>"))) |
8506 | 1058 ## Skip package name and description as they are in DESCRIPTION |
1059 ## already. | |
7498 | 1060 elseif (! isspace (line(1))) |
8506 | 1061 ## Category. |
7498 | 1062 if (! isempty (pkg_idx_struct{cat_num}.functions)) |
1063 pkg_idx_struct{++cat_num}.functions = {}; | |
7497 | 1064 endif |
7498 | 1065 pkg_idx_struct{cat_num}.category = deblank (line); |
7497 | 1066 else |
8506 | 1067 ## Function names. |
7498 | 1068 while (any (! isspace (line))) |
1069 [fun_name, line] = strtok (line); | |
1070 pkg_idx_struct{cat_num}.functions{end+1} = deblank (fun_name); | |
7497 | 1071 endwhile |
1072 endif | |
7498 | 1073 line = fgetl (fid); |
7497 | 1074 endwhile |
1075 fclose (fid); | |
1076 endfunction | |
1077 | |
1078 function print_package_description (pkg_name, pkg_idx_struct, | |
1079 pkg_desc, status, verbose) | |
1080 | |
7498 | 1081 printf ("---\nPackage name:\n\t%s\n", pkg_name); |
1082 printf ("Short description:\n\t%s\n", pkg_desc); | |
1083 printf ("Status:\n\t%s\n", status); | |
7497 | 1084 if (verbose) |
7498 | 1085 printf ("---\nProvides:\n"); |
1086 for i = 1:length(pkg_idx_struct) | |
1087 if (! isempty (pkg_idx_struct{i}.functions)) | |
1088 printf ("%s\n", pkg_idx_struct{i}.category); | |
1089 for j = 1:length(pkg_idx_struct{i}.functions) | |
1090 printf ("\t%s\n", pkg_idx_struct{i}.functions{j}); | |
7497 | 1091 endfor |
1092 endif | |
1093 endfor | |
1094 endif | |
1095 | |
1096 endfunction | |
1097 | |
1098 | |
6675 | 1099 function pth = absolute_pathname (pth) |
7498 | 1100 [status, msg, msgid] = fileattrib (pth); |
6729 | 1101 if (status != 1) |
1102 error ("could not find the file or path %s", pth); | |
1103 else | |
1104 pth = msg.Name; | |
1105 endif | |
6675 | 1106 endfunction |
1107 | |
1108 function repackage (builddir, buildlist) | |
1109 packages = installed_packages (buildlist, buildlist); | |
1110 | |
1111 wd = pwd(); | |
1112 for i = 1 : length(packages) | |
1113 pack = packages{i}; | |
1114 unwind_protect | |
1115 cd (builddir); | |
1116 mkdir (pack.name); | |
1117 mkdir (fullfile (pack.name, "inst")); | |
1118 copyfile (fullfile (pack.dir, "*"), fullfile (pack.name, "inst")); | |
1119 movefile (fullfile (pack.name, "inst","packinfo", "*"), pack.name); | |
1120 if (exist (fullfile (pack.name, "inst","packinfo", ".autoload"), "file")) | |
1121 unlink (fullfile (pack.name, "inst","packinfo", ".autoload")); | |
1122 endif | |
1123 rmdir (fullfile (pack.name, "inst", "packinfo")); | |
1124 if (exist (fullfile (pack.name, "inst", "doc"), "dir")) | |
1125 movefile (fullfile (pack.name, "inst", "doc"), pack.name); | |
1126 endif | |
1127 if (exist (fullfile (pack.name, "inst", "bin"), "dir")) | |
1128 movefile (fullfile (pack.name, "inst", "bin"), pack.name); | |
1129 endif | |
7540
3422f39573b1
strcat.m: Matlab compatibility, with cstrcat.m replacing conventional strcat.m.
Ben Abbott <bpabbott@mac.com>
parents:
7498
diff
changeset
|
1130 archdir = fullfile (pack.archprefix, cstrcat (pack.name, "-", |
6925 | 1131 pack.version), getarch ()); |
6675 | 1132 if (exist (archdir, "dir")) |
1133 if (exist (fullfile (pack.name, "inst", "PKG_ADD"), "file")) | |
1134 unlink (fullfile (pack.name, "inst", "PKG_ADD")); | |
1135 endif | |
1136 if (exist (fullfile (pack.name, "inst", "PKG_DEL"), "file")) | |
1137 unlink (fullfile (pack.name, "inst", "PKG_DEL")); | |
1138 endif | |
1139 if (exist (fullfile (archdir, "PKG_ADD"), "file")) | |
1140 movefile (fullfile (archdir, "PKG_ADD"), | |
1141 fullfile (pack.name, "PKG_ADD")); | |
1142 endif | |
1143 if (exist (fullfile (archdir, "PKG_DEL"), "file")) | |
1144 movefile (fullfile (archdir, "PKG_DEL"), | |
1145 fullfile (pack.name, "PKG_DEL")); | |
1146 endif | |
1147 else | |
1148 if (exist (fullfile (pack.name, "inst", "PKG_ADD"), "file")) | |
1149 movefile (fullfile (pack.name, "inst", "PKG_ADD"), | |
1150 fullfile (pack.name, "PKG_ADD")); | |
1151 endif | |
1152 if (exist (fullfile (pack.name, "inst", "PKG_DEL"), "file")) | |
1153 movefile (fullfile (pack.name, "inst", "PKG_DEL"), | |
1154 fullfile (pack.name, "PKG_DEL")); | |
1155 endif | |
1156 endif | |
7540
3422f39573b1
strcat.m: Matlab compatibility, with cstrcat.m replacing conventional strcat.m.
Ben Abbott <bpabbott@mac.com>
parents:
7498
diff
changeset
|
1157 tfile = cstrcat (pack.name, "-", pack.version, ".tar"); |
6675 | 1158 tar (tfile, pack.name); |
6925 | 1159 try |
1160 gzip (tfile); | |
1161 unlink (tfile); | |
1162 catch | |
1163 warning ("failed to compress %s", tfile); | |
1164 end_try_catch | |
6675 | 1165 unwind_protect_cleanup |
1166 if (exist (pack.name, "dir")) | |
1167 rm_rf (pack.name); | |
1168 endif | |
1169 cd (wd); | |
1170 end_unwind_protect | |
1171 endfor | |
1172 endfunction | |
1173 | |
1174 function auto = isautoload (desc) | |
6695 | 1175 auto = false; |
1176 if (isfield (desc{1}, "autoload")) | |
1177 a = desc{1}.autoload; | |
1178 if ((isnumeric (a) && a > 0) | |
1179 || (ischar (a) && (strcmpi (a, "true") | |
6675 | 1180 || strcmpi (a, "on") |
1181 || strcmpi (a, "yes") | |
1182 || strcmpi (a, "1")))) | |
6695 | 1183 auto = true; |
1184 endif | |
6675 | 1185 endif |
1186 endfunction | |
1187 | |
6496 | 1188 function prepare_installation (desc, packdir) |
1189 ## Is there a pre_install to call? | |
1190 if (exist (fullfile (packdir, "pre_install.m"), "file")) | |
1191 wd = pwd (); | |
1192 try | |
1193 cd (packdir); | |
1194 pre_install (desc); | |
1195 cd (wd); | |
1196 catch | |
1197 cd (wd); | |
6695 | 1198 rethrow (lasterror ()); |
6496 | 1199 end_try_catch |
1200 endif | |
1201 | |
8506 | 1202 ## If the directory "inst" doesn't exist, we create it. |
6496 | 1203 inst_dir = fullfile (packdir, "inst"); |
1204 if (! exist (inst_dir, "dir")) | |
1205 [status, msg] = mkdir (inst_dir); | |
1206 if (status != 1) | |
1207 rm_rf (desc.dir); | |
1208 error ("the 'inst' directory did not exist and could not be created: %s", | |
1209 msg); | |
6258 | 1210 endif |
1211 endif | |
1212 endfunction | |
1213 | |
6614 | 1214 function configure_make (desc, packdir, verbose) |
8506 | 1215 ## Perform ./configure, make, make install in "src". |
6496 | 1216 if (exist (fullfile (packdir, "src"), "dir")) |
1217 src = fullfile (packdir, "src"); | |
8506 | 1218 ## Configure. |
6496 | 1219 if (exist (fullfile (src, "configure"), "file")) |
7111 | 1220 flags = ""; |
1221 if (isempty (getenv ("CC"))) | |
7540
3422f39573b1
strcat.m: Matlab compatibility, with cstrcat.m replacing conventional strcat.m.
Ben Abbott <bpabbott@mac.com>
parents:
7498
diff
changeset
|
1222 flags = cstrcat (flags, " CC=\"", octave_config_info ("CC"), "\""); |
7111 | 1223 endif |
1224 if (isempty (getenv ("CXX"))) | |
7540
3422f39573b1
strcat.m: Matlab compatibility, with cstrcat.m replacing conventional strcat.m.
Ben Abbott <bpabbott@mac.com>
parents:
7498
diff
changeset
|
1225 flags = cstrcat (flags, " CXX=\"", octave_config_info ("CXX"), "\""); |
7111 | 1226 endif |
1227 if (isempty (getenv ("AR"))) | |
7540
3422f39573b1
strcat.m: Matlab compatibility, with cstrcat.m replacing conventional strcat.m.
Ben Abbott <bpabbott@mac.com>
parents:
7498
diff
changeset
|
1228 flags = cstrcat (flags, " AR=\"", octave_config_info ("AR"), "\""); |
7111 | 1229 endif |
1230 if (isempty (getenv ("RANLIB"))) | |
7540
3422f39573b1
strcat.m: Matlab compatibility, with cstrcat.m replacing conventional strcat.m.
Ben Abbott <bpabbott@mac.com>
parents:
7498
diff
changeset
|
1231 flags = cstrcat (flags, " RANLIB=\"", octave_config_info ("RANLIB"), "\""); |
7111 | 1232 endif |
8172
9ba45b125ee8
enclose building direcries in quotes in pkg.m
Benjamin Lindner <lindnerb@users.sourceforge.net>
parents:
8043
diff
changeset
|
1233 [status, output] = shell (strcat ("cd '", src, "'; ./configure --prefix=\"", |
7111 | 1234 desc.dir, "\"", flags)); |
6496 | 1235 if (status != 0) |
1236 rm_rf (desc.dir); | |
1237 error ("the configure script returned the following error: %s", output); | |
6675 | 1238 elseif (verbose) |
1239 printf("%s", output); | |
6496 | 1240 endif |
6675 | 1241 |
5801 | 1242 endif |
1243 | |
8506 | 1244 ## Make. |
6496 | 1245 if (exist (fullfile (src, "Makefile"), "file")) |
7540
3422f39573b1
strcat.m: Matlab compatibility, with cstrcat.m replacing conventional strcat.m.
Ben Abbott <bpabbott@mac.com>
parents:
7498
diff
changeset
|
1246 [status, output] = shell (cstrcat ("export INSTALLDIR=\"", desc.dir, |
8172
9ba45b125ee8
enclose building direcries in quotes in pkg.m
Benjamin Lindner <lindnerb@users.sourceforge.net>
parents:
8043
diff
changeset
|
1247 "\"; make -C '", src, "'")); |
6496 | 1248 if (status != 0) |
1249 rm_rf (desc.dir); | |
1250 error ("'make' returned the following error: %s", output); | |
6675 | 1251 elseif (verbose) |
1252 printf("%s", output); | |
6496 | 1253 endif |
5801 | 1254 endif |
1255 | |
8506 | 1256 ## Copy files to "inst" and "inst/arch" (this is instead of 'make |
1257 ## install'). | |
6496 | 1258 files = fullfile (src, "FILES"); |
1259 instdir = fullfile (packdir, "inst"); | |
6614 | 1260 archdir = fullfile (packdir, "inst", getarch ()); |
6950 | 1261 |
8506 | 1262 ## Get file names. |
6496 | 1263 if (exist (files, "file")) |
1264 [fid, msg] = fopen (files, "r"); | |
1265 if (fid < 0) | |
1266 error ("couldn't open %s: %s", files, msg); | |
5971 | 1267 endif |
6496 | 1268 filenames = char (fread (fid))'; |
1269 fclose (fid); | |
1270 if (filenames(end) == "\n") | |
1271 filenames(end) = []; | |
6258 | 1272 endif |
6655 | 1273 filenames = split_by (filenames, "\n"); |
6496 | 1274 delete_idx = []; |
6655 | 1275 for i = 1:length (filenames) |
1276 if (! all (isspace (filenames{i}))) | |
1277 filenames{i} = fullfile (src, filenames{i}); | |
6496 | 1278 else |
1279 delete_idx(end+1) = i; | |
1280 endif | |
5971 | 1281 endfor |
6655 | 1282 filenames(delete_idx) = []; |
6496 | 1283 else |
1284 m = dir (fullfile (src, "*.m")); | |
1285 oct = dir (fullfile (src, "*.oct")); | |
1286 mex = dir (fullfile (src, "*.mex")); | |
8174
ea9b5f31bfac
pkg.m: better handling of filenames with spaces
John W. Eaton <jwe@octave.org>
parents:
8172
diff
changeset
|
1287 |
ea9b5f31bfac
pkg.m: better handling of filenames with spaces
John W. Eaton <jwe@octave.org>
parents:
8172
diff
changeset
|
1288 filenames = cellfun (@(x) fullfile (src, x), |
ea9b5f31bfac
pkg.m: better handling of filenames with spaces
John W. Eaton <jwe@octave.org>
parents:
8172
diff
changeset
|
1289 {m.name, oct.name, mex.name}, |
ea9b5f31bfac
pkg.m: better handling of filenames with spaces
John W. Eaton <jwe@octave.org>
parents:
8172
diff
changeset
|
1290 "UniformOutput", false); |
5971 | 1291 endif |
5801 | 1292 |
8506 | 1293 ## Split into architecture dependent and independent files. |
7024 | 1294 if (isempty (filenames)) |
1295 idx = []; | |
1296 else | |
8043
30d15ab0ce01
avoid problematic subfunction call in an anonymous function
Jaroslav Hajek <highegg@gmail.com>
parents:
7739
diff
changeset
|
1297 idx = cellfun (@is_architecture_dependent, filenames); |
7024 | 1298 endif |
6950 | 1299 archdependent = filenames (idx); |
1300 archindependent = filenames (!idx); | |
1301 | |
8506 | 1302 ## Copy the files. |
7548
9cbf1e2011a3
pkg.m: adapt to changes in isspace for cell arrays of strings.
Michael Goffioul <michael.goffioul@gmail.com>
parents:
7540
diff
changeset
|
1303 if (! all (isspace ([filenames{:}]))) |
6655 | 1304 if (! exist (instdir, "dir")) |
1305 mkdir (instdir); | |
1306 endif | |
7548
9cbf1e2011a3
pkg.m: adapt to changes in isspace for cell arrays of strings.
Michael Goffioul <michael.goffioul@gmail.com>
parents:
7540
diff
changeset
|
1307 if (! all (isspace ([archindependent{:}]))) |
6634 | 1308 if (verbose) |
1309 printf ("copyfile"); | |
1310 printf (" %s", archindependent{:}); | |
1311 printf ("%s\n", instdir); | |
1312 endif | |
6614 | 1313 [status, output] = copyfile (archindependent, instdir); |
1314 if (status != 1) | |
6496 | 1315 rm_rf (desc.dir); |
1316 error ("Couldn't copy files from 'src' to 'inst': %s", output); | |
6614 | 1317 endif |
1318 endif | |
7548
9cbf1e2011a3
pkg.m: adapt to changes in isspace for cell arrays of strings.
Michael Goffioul <michael.goffioul@gmail.com>
parents:
7540
diff
changeset
|
1319 if (! all (isspace ([archdependent{:}]))) |
6634 | 1320 if (verbose) |
1321 printf ("copyfile"); | |
1322 printf (" %s", archdependent{:}); | |
1323 printf (" %s\n", archdir); | |
1324 endif | |
6655 | 1325 if (! exist (archdir, "dir")) |
1326 mkdir (archdir); | |
1327 endif | |
6614 | 1328 [status, output] = copyfile (archdependent, archdir); |
1329 if (status != 1) | |
1330 rm_rf (desc.dir); | |
1331 error ("Couldn't copy files from 'src' to 'inst': %s", output); | |
1332 endif | |
1333 endif | |
5801 | 1334 endif |
6496 | 1335 endif |
5801 | 1336 endfunction |
1337 | |
5971 | 1338 function pkg = extract_pkg (nm, pat) |
5955 | 1339 fid = fopen (nm, "rt"); |
5971 | 1340 pkg = ""; |
5955 | 1341 if (fid >= 0) |
6496 | 1342 while (! feof (fid)) |
5955 | 1343 ln = fgetl (fid); |
1344 if (ln > 0) | |
6496 | 1345 t = regexp (ln, pat, "tokens"); |
1346 if (! isempty (t)) | |
7540
3422f39573b1
strcat.m: Matlab compatibility, with cstrcat.m replacing conventional strcat.m.
Ben Abbott <bpabbott@mac.com>
parents:
7498
diff
changeset
|
1347 pkg = cstrcat (pkg, "\n", t{1}{1}); |
5955 | 1348 endif |
1349 endif | |
1350 endwhile | |
6496 | 1351 if (! isempty (pkg)) |
7540
3422f39573b1
strcat.m: Matlab compatibility, with cstrcat.m replacing conventional strcat.m.
Ben Abbott <bpabbott@mac.com>
parents:
7498
diff
changeset
|
1352 pkg = cstrcat (pkg, "\n"); |
5955 | 1353 endif |
1354 fclose (fid); | |
1355 endif | |
1356 endfunction | |
1357 | |
6925 | 1358 function create_pkgadddel (desc, packdir, nm, global_install) |
6675 | 1359 instpkg = fullfile (desc.dir, nm); |
1360 instfid = fopen (instpkg, "wt"); | |
1361 ## If it is exists, most of the PKG_* file should go into the | |
1362 ## architecture dependent directory so that the autoload/mfilename | |
1363 ## commands work as expected. The only part that doesn't is the | |
1364 ## part in the main directory. | |
7540
3422f39573b1
strcat.m: Matlab compatibility, with cstrcat.m replacing conventional strcat.m.
Ben Abbott <bpabbott@mac.com>
parents:
7498
diff
changeset
|
1365 archdir = fullfile (getarchprefix (desc), cstrcat (desc.name, "-", |
6925 | 1366 desc.version), getarch ()); |
1367 if (exist (getarchdir (desc, global_install), "dir")) | |
1368 archpkg = fullfile (getarchdir (desc, global_install), nm); | |
1369 archfid = fopen (archpkg, "at"); | |
6675 | 1370 else |
1371 archpkg = instpkg; | |
1372 archfid = instfid; | |
1373 endif | |
6634 | 1374 |
6675 | 1375 if (archfid >= 0 && instfid >= 0) |
8506 | 1376 ## Search all dot-m files for PKG commands. |
7498 | 1377 lst = dir (fullfile (packdir, "inst", "*.m")); |
6496 | 1378 for i = 1:length (lst) |
7498 | 1379 nam = fullfile (packdir, "inst", lst(i).name); |
6675 | 1380 fwrite (instfid, extract_pkg (nam, ['^[#%][#%]* *' nm ': *(.*)$'])); |
5955 | 1381 endfor |
1382 | |
8506 | 1383 ## Search all C++ source files for PKG commands. |
7498 | 1384 lst = dir (fullfile (packdir, "src", "*.cc")); |
6496 | 1385 for i = 1:length (lst) |
7498 | 1386 nam = fullfile (packdir, "src", lst(i).name); |
6675 | 1387 fwrite (archfid, extract_pkg (nam, ['^//* *' nm ': *(.*)$'])); |
1388 fwrite (archfid, extract_pkg (nam, ['^/\** *' nm ': *(.*) *\*/$'])); | |
5955 | 1389 endfor |
1390 | |
8506 | 1391 ## Add developer included PKG commands. |
6496 | 1392 packdirnm = fullfile (packdir, nm); |
1393 if (exist (packdirnm, "file")) | |
6675 | 1394 fid = fopen (packdirnm, "rt"); |
1395 if (fid >= 0) | |
1396 while (! feof (fid)) | |
1397 ln = fgets (fid); | |
5955 | 1398 if (ln > 0) |
6675 | 1399 fwrite (archfid, ln); |
5955 | 1400 endif |
1401 endwhile | |
6675 | 1402 fclose (fid); |
5955 | 1403 endif |
1404 endif | |
5971 | 1405 |
8506 | 1406 ## If the files is empty remove it. |
6675 | 1407 fclose (instfid); |
1408 t = dir (instpkg); | |
5971 | 1409 if (t.bytes <= 0) |
6675 | 1410 unlink (instpkg); |
1411 endif | |
1412 | |
1413 if (instfid != archfid) | |
1414 fclose (archfid); | |
1415 t = dir (archpkg); | |
1416 if (t.bytes <= 0) | |
1417 unlink (archpkg); | |
1418 endif | |
5971 | 1419 endif |
5955 | 1420 endif |
1421 endfunction | |
1422 | |
6925 | 1423 function copy_files (desc, packdir, global_install) |
8506 | 1424 ## Create the installation directory. |
6496 | 1425 if (! exist (desc.dir, "dir")) |
1426 [status, output] = mkdir (desc.dir); | |
1427 if (status != 1) | |
1428 error ("couldn't create installation directory %s : %s", | |
1429 desc.dir, output); | |
6020 | 1430 endif |
6496 | 1431 endif |
6020 | 1432 |
6925 | 1433 octfiledir = getarchdir (desc); |
1434 | |
8506 | 1435 ## Copy the files from "inst" to installdir. |
6496 | 1436 instdir = fullfile (packdir, "inst"); |
1437 if (! dirempty (instdir)) | |
1438 [status, output] = copyfile (fullfile (instdir, "*"), desc.dir); | |
1439 if (status != 1) | |
1440 rm_rf (desc.dir); | |
1441 error ("couldn't copy files to the installation directory"); | |
5801 | 1442 endif |
6925 | 1443 if (exist (fullfile (desc.dir, getarch ()), "dir") && |
1444 ! strcmp (fullfile (desc.dir, getarch ()), octfiledir)) | |
1445 if (! exist (octfiledir, "dir")) | |
8506 | 1446 ## Can be required to create upto three levels of dirs. |
6925 | 1447 octm1 = fileparts (octfiledir); |
1448 if (! exist (octm1, "dir")) | |
1449 octm2 = fileparts (octm1); | |
1450 if (! exist (octm2, "dir")) | |
1451 octm3 = fileparts (octm2); | |
1452 if (! exist (octm3, "dir")) | |
1453 [status, output] = mkdir (octm3); | |
1454 if (status != 1) | |
1455 rm_rf (desc.dir); | |
1456 error ("couldn't create installation directory %s : %s", | |
1457 octm3, output); | |
1458 endif | |
1459 endif | |
1460 [status, output] = mkdir (octm2); | |
1461 if (status != 1) | |
1462 rm_rf (desc.dir); | |
1463 error ("couldn't create installation directory %s : %s", | |
1464 octm2, output); | |
1465 endif | |
1466 endif | |
1467 [status, output] = mkdir (octm1); | |
1468 if (status != 1) | |
1469 rm_rf (desc.dir); | |
1470 error ("couldn't create installation directory %s : %s", | |
1471 octm1, output); | |
1472 endif | |
1473 endif | |
1474 [status, output] = mkdir (octfiledir); | |
1475 if (status != 1) | |
1476 rm_rf (desc.dir); | |
1477 error ("couldn't create installation directory %s : %s", | |
1478 octfiledir, output); | |
1479 endif | |
1480 endif | |
1481 [status, output] = movefile (fullfile (desc.dir, getarch (), "*"), | |
1482 octfiledir); | |
1483 rm_rf (fullfile (desc.dir, getarch ())); | |
1484 | |
1485 if (status != 1) | |
1486 rm_rf (desc.dir); | |
1487 rm_rf (octfiledir); | |
1488 error ("couldn't copy files to the installation directory"); | |
1489 endif | |
1490 endif | |
1491 | |
6496 | 1492 endif |
5801 | 1493 |
8506 | 1494 ## Create the "packinfo" directory. |
6496 | 1495 packinfo = fullfile (desc.dir, "packinfo"); |
1496 [status, msg] = mkdir (packinfo); | |
1497 if (status != 1) | |
1498 rm_rf (desc.dir); | |
6925 | 1499 rm_rf (octfiledir); |
6496 | 1500 error ("couldn't create packinfo directory: %s", msg); |
1501 endif | |
5801 | 1502 |
8506 | 1503 ## Copy DESCRIPTION. |
6496 | 1504 [status, output] = copyfile (fullfile (packdir, "DESCRIPTION"), packinfo); |
1505 if (status != 1) | |
6925 | 1506 rm_rf (desc.dir); |
1507 rm_rf (octfiledir); | |
1508 error ("couldn't copy DESCRIPTION: %s", output); | |
6496 | 1509 endif |
5801 | 1510 |
8506 | 1511 ## Copy COPYING. |
6496 | 1512 [status, output] = copyfile (fullfile (packdir, "COPYING"), packinfo); |
1513 if (status != 1) | |
6925 | 1514 rm_rf (desc.dir); |
1515 rm_rf (octfiledir); | |
1516 error ("couldn't copy COPYING: %s", output); | |
6496 | 1517 endif |
5993 | 1518 |
8506 | 1519 ## If the file ChangeLog exists, copy it. |
7498 | 1520 changelog_file = fullfile (packdir, "ChangeLog"); |
1521 if (exist (changelog_file, "file")) | |
1522 [status, output] = copyfile (changelog_file, packinfo); | |
6496 | 1523 if (status != 1) |
1524 rm_rf (desc.dir); | |
6925 | 1525 rm_rf (octfiledir); |
6496 | 1526 error ("couldn't copy ChangeLog file: %s", output); |
6254 | 1527 endif |
6496 | 1528 endif |
6254 | 1529 |
6496 | 1530 ## Is there an INDEX file to copy or should we generate one? |
7498 | 1531 index_file = fullfile (packdir, "INDEX"); |
1532 if (exist(index_file, "file")) | |
1533 [status, output] = copyfile (index_file, packinfo); | |
6496 | 1534 if (status != 1) |
1535 rm_rf (desc.dir); | |
6925 | 1536 rm_rf (octfiledir); |
6496 | 1537 error ("couldn't copy INDEX file: %s", output); |
5801 | 1538 endif |
6496 | 1539 else |
1540 try | |
7498 | 1541 write_index (desc, fullfile (packdir, "inst"), |
6925 | 1542 fullfile (packinfo, "INDEX"), global_install); |
6496 | 1543 catch |
1544 rm_rf (desc.dir); | |
6925 | 1545 rm_rf (octfiledir); |
6695 | 1546 rethrow (lasterror ()); |
6496 | 1547 end_try_catch |
1548 endif | |
5971 | 1549 |
6496 | 1550 ## Is there an 'on_uninstall.m' to install? |
7498 | 1551 fon_uninstall = fullfile (packdir, "on_uninstall.m"); |
6496 | 1552 if (exist (fon_uninstall, "file")) |
1553 [status, output] = copyfile (fon_uninstall, packinfo); | |
1554 if (status != 1) | |
1555 rm_rf (desc.dir); | |
6925 | 1556 rm_rf (octfiledir); |
6496 | 1557 error ("couldn't copy on_uninstall.m: %s", output); |
5971 | 1558 endif |
6496 | 1559 endif |
5971 | 1560 |
8506 | 1561 ## Is there a doc/ directory that needs to be installed? |
6496 | 1562 docdir = fullfile (packdir, "doc"); |
1563 if (exist (docdir, "dir") && ! dirempty (docdir)) | |
6925 | 1564 [status, output] = copyfile (docdir, desc.dir); |
6496 | 1565 endif |
1566 | |
8506 | 1567 ## Is there a bin/ directory that needs to be installed? |
6950 | 1568 ## FIXME: Need to treat architecture dependent files in bin/ |
6496 | 1569 bindir = fullfile (packdir, "bin"); |
1570 if (exist (bindir, "dir") && ! dirempty (bindir)) | |
6925 | 1571 [status, output] = copyfile (bindir, desc.dir); |
6496 | 1572 endif |
5801 | 1573 endfunction |
1574 | |
6925 | 1575 function finish_installation (desc, packdir, global_install) |
6496 | 1576 ## Is there a post-install to call? |
1577 if (exist (fullfile (packdir, "post_install.m"), "file")) | |
1578 wd = pwd (); | |
1579 try | |
1580 cd (packdir); | |
1581 post_install (desc); | |
1582 cd (wd); | |
1583 catch | |
1584 cd (wd); | |
1585 rm_rf (desc.dir); | |
6925 | 1586 rm_rf (getarchdir (desc), global_install); |
6695 | 1587 rethrow (lasterror ()); |
6496 | 1588 end_try_catch |
1589 endif | |
5801 | 1590 endfunction |
1591 | |
8575
f134925a1cfa
m-file implementation of help system
Soren Hauberg <soren@hauberg.org>
parents:
8507
diff
changeset
|
1592 function generate_lookfor_cache (desc) |
8863
34a821854961
pkg.m (generate_lookfor_cache): generate a DOC file for each directory
Jason Riedy <jason@acm.org>
parents:
8746
diff
changeset
|
1593 dirs = split_by (genpath (desc.dir), pathsep ()); |
34a821854961
pkg.m (generate_lookfor_cache): generate a DOC file for each directory
Jason Riedy <jason@acm.org>
parents:
8746
diff
changeset
|
1594 for i = 1 : length (dirs) |
8942
c4383701e10d
use doc-cache instead of DOC for doc cache file name
John W. Eaton <jwe@octave.org>
parents:
8920
diff
changeset
|
1595 gen_doc_cache (fullfile (dirs{i}, "doc-cache"), dirs{i}); |
8863
34a821854961
pkg.m (generate_lookfor_cache): generate a DOC file for each directory
Jason Riedy <jason@acm.org>
parents:
8746
diff
changeset
|
1596 endfor |
8575
f134925a1cfa
m-file implementation of help system
Soren Hauberg <soren@hauberg.org>
parents:
8507
diff
changeset
|
1597 endfunction |
f134925a1cfa
m-file implementation of help system
Soren Hauberg <soren@hauberg.org>
parents:
8507
diff
changeset
|
1598 |
7498 | 1599 ## Make sure the package contains the essential files. |
6496 | 1600 function verify_directory (dir) |
1601 needed_files = {"COPYING", "DESCRIPTION"}; | |
1602 for f = needed_files | |
1603 if (! exist (fullfile (dir, f{1}), "file")) | |
1604 error ("package is missing file: %s", f{1}); | |
1605 endif | |
1606 endfor | |
5801 | 1607 endfunction |
1608 | |
8506 | 1609 ## Parse the DESCRIPTION file. |
6496 | 1610 function desc = get_description (filename) |
1611 [fid, msg] = fopen (filename, "r"); | |
1612 if (fid == -1) | |
1613 error ("the DESCRIPTION file %s could not be read: %s", filename, msg); | |
1614 endif | |
1615 | |
1616 desc = struct (); | |
5801 | 1617 |
6496 | 1618 line = fgetl (fid); |
1619 while (line != -1) | |
1620 if (line(1) == "#") | |
8506 | 1621 ## Comments, do nothing. |
6496 | 1622 elseif (isspace(line(1))) |
1623 ## Continuation lines | |
1624 if (exist ("keyword", "var") && isfield (desc, keyword)) | |
7540
3422f39573b1
strcat.m: Matlab compatibility, with cstrcat.m replacing conventional strcat.m.
Ben Abbott <bpabbott@mac.com>
parents:
7498
diff
changeset
|
1625 desc.(keyword) = cstrcat (desc.(keyword), " ", rstrip(line)); |
6496 | 1626 endif |
5801 | 1627 else |
6496 | 1628 ## Keyword/value pair |
1629 colon = find (line == ":"); | |
1630 if (length (colon) == 0) | |
1631 disp ("skipping line"); | |
1632 else | |
1633 colon = colon(1); | |
1634 keyword = tolower (strip (line(1:colon-1))); | |
7498 | 1635 value = strip (line (colon+1:end)); |
6496 | 1636 if (length (value) == 0) |
1637 fclose (fid); | |
1638 error ("the keyword %s has an empty value", desc.keywords{end}); | |
1639 endif | |
1640 desc.(keyword) = value; | |
1641 endif | |
5801 | 1642 endif |
6496 | 1643 line = fgetl (fid); |
1644 endwhile | |
1645 fclose (fid); | |
1646 | |
8506 | 1647 ## Make sure all is okay. |
6496 | 1648 needed_fields = {"name", "version", "date", "title", ... |
1649 "author", "maintainer", "description"}; | |
1650 for f = needed_fields | |
1651 if (! isfield (desc, f{1})) | |
1652 error ("description is missing needed field %s", f{1}); | |
1653 endif | |
1654 endfor | |
1655 desc.version = fix_version (desc.version); | |
1656 if (isfield (desc, "depends")) | |
1657 desc.depends = fix_depends (desc.depends); | |
1658 else | |
1659 desc.depends = ""; | |
1660 endif | |
1661 desc.name = tolower (desc.name); | |
5801 | 1662 endfunction |
1663 | |
7498 | 1664 ## Make sure the version string v is a valid x.y.z version string |
8506 | 1665 ## Examples: "0.1" => "0.1.0", "monkey" => error(...). |
6496 | 1666 function out = fix_version (v) |
1667 dots = find (v == "."); | |
1668 if (length (dots) == 1) | |
1669 major = str2num (v(1:dots-1)); | |
1670 minor = str2num (v(dots+1:end)); | |
1671 if (length (major) != 0 && length (minor) != 0) | |
1672 out = sprintf ("%d.%d.0", major, minor); | |
1673 return; | |
5801 | 1674 endif |
6496 | 1675 elseif (length (dots) == 2) |
1676 major = str2num (v(1:dots(1)-1)); | |
1677 minor = str2num (v(dots(1)+1:dots(2)-1)); | |
7498 | 1678 rev = str2num (v(dots(2)+1:end)); |
6496 | 1679 if (length (major) != 0 && length (minor) != 0 && length (rev) != 0) |
1680 out = sprintf ("%d.%d.%d", major, minor, rev); | |
1681 return; | |
1682 endif | |
1683 endif | |
1684 error ("bad version string: %s", v); | |
5801 | 1685 endfunction |
1686 | |
7498 | 1687 ## Make sure the depends field is of the right format. |
5801 | 1688 ## This function returns a cell of structures with the following fields: |
1689 ## package, version, operator | |
6496 | 1690 function deps_cell = fix_depends (depends) |
1691 deps = split_by (tolower (depends), ","); | |
1692 deps_cell = cell (1, length (deps)); | |
1693 | |
8506 | 1694 ## For each dependency. |
6496 | 1695 for i = 1:length (deps) |
1696 dep = deps{i}; | |
1697 lpar = find (dep == "("); | |
1698 rpar = find (dep == ")"); | |
1699 ## Does the dependency specify a version | |
8506 | 1700 ## Example: package(>= version). |
6496 | 1701 if (length (lpar) == 1 && length (rpar) == 1) |
1702 package = tolower (strip (dep(1:lpar-1))); | |
1703 sub = dep(lpar(1)+1:rpar(1)-1); | |
8900
63ad1133d0ed
fix & simplify fix_depends pkg.m
Jaroslav Hajek <highegg@gmail.com>
parents:
8877
diff
changeset
|
1704 parts = strsplit (sub, " ", true); |
63ad1133d0ed
fix & simplify fix_depends pkg.m
Jaroslav Hajek <highegg@gmail.com>
parents:
8877
diff
changeset
|
1705 if (length (parts) != 2) |
6496 | 1706 error ("incorrect syntax for dependency `%s' in the DESCRIPTION file\n", |
1707 dep); | |
1708 endif | |
8900
63ad1133d0ed
fix & simplify fix_depends pkg.m
Jaroslav Hajek <highegg@gmail.com>
parents:
8877
diff
changeset
|
1709 operator = parts{1}; |
6496 | 1710 if (! any (strcmp (operator, {">", ">=", "<=", "<", "=="}))) |
1711 error ("unsupported operator: %s", operator); | |
1712 endif | |
8900
63ad1133d0ed
fix & simplify fix_depends pkg.m
Jaroslav Hajek <highegg@gmail.com>
parents:
8877
diff
changeset
|
1713 version = fix_version (parts{2}); |
6496 | 1714 |
1715 ## If no version is specified for the dependency | |
1716 ## we say that the version should be greater than | |
8506 | 1717 ## or equal to "0.0.0". |
6496 | 1718 else |
1719 package = tolower (strip (dep)); | |
1720 operator = ">="; | |
1721 version = "0.0.0"; | |
1722 endif | |
1723 deps_cell{i} = struct ("package", package, "operator", operator, | |
1724 "version", version); | |
1725 endfor | |
5801 | 1726 endfunction |
1727 | |
7498 | 1728 ## Strip the text of spaces from the right |
8506 | 1729 ## Example: " hello world " => " hello world" |
1730 ## FIXME -- is this the same as deblank? | |
6496 | 1731 function text = rstrip (text) |
1732 chars = find (! isspace (text)); | |
1733 if (length (chars) > 0) | |
8202
cf59d542f33e
replace all TODOs and XXXs with FIXMEs
Jaroslav Hajek <highegg@gmail.com>
parents:
8174
diff
changeset
|
1734 ## FIXME: shouldn't it be text = text(1:chars(end)); |
6496 | 1735 text = text (chars(1):end); |
1736 else | |
1737 text = ""; | |
1738 endif | |
5801 | 1739 endfunction |
1740 | |
8506 | 1741 ## Strip the text of spaces from the left and the right. |
5801 | 1742 ## Example: " hello world " => "hello world" |
6496 | 1743 function text = strip (text) |
1744 chars = find (! isspace (text)); | |
1745 if (length (chars) > 0) | |
1746 text = text(chars(1):chars(end)); | |
1747 else | |
1748 text = ""; | |
1749 endif | |
5801 | 1750 endfunction |
1751 | |
8506 | 1752 ## Split the text into a cell array of strings by sep. |
5801 | 1753 ## Example: "A, B" => {"A", "B"} (with sep = ",") |
6496 | 1754 function out = split_by (text, sep) |
8877
2c8b2399247b
implement strsplit; deprecate split
Jaroslav Hajek <highegg@gmail.com>
parents:
8863
diff
changeset
|
1755 out = strtrim (strsplit (text, sep)); |
5801 | 1756 endfunction |
1757 | |
7498 | 1758 ## Create an INDEX file for a package that doesn't provide one. |
5801 | 1759 ## 'desc' describes the package. |
7498 | 1760 ## 'dir' is the 'inst' directory in temporary directory. |
1761 ## 'index_file' is the name (including path) of resulting INDEX file. | |
1762 function write_index (desc, dir, index_file, global_install) | |
6496 | 1763 ## Get names of functions in dir |
1764 [files, err, msg] = readdir (dir); | |
1765 if (err) | |
1766 error ("couldn't read directory %s: %s", dir, msg); | |
1767 endif | |
1768 | |
8506 | 1769 ## Check for architecture dependent files. |
6925 | 1770 tmpdir = getarchdir (desc); |
6634 | 1771 if (exist (tmpdir, "dir")) |
1772 [files2, err, msg] = readdir (tmpdir); | |
1773 if (err) | |
1774 error ("couldn't read directory %s: %s", tmpdir, msg); | |
1775 endif | |
1776 files = [files; files2]; | |
1777 endif | |
1778 | |
6496 | 1779 functions = {}; |
1780 for i = 1:length (files) | |
1781 file = files{i}; | |
1782 lf = length (file); | |
1783 if (lf > 2 && strcmp (file(end-1:end), ".m")) | |
1784 functions{end+1} = file(1:end-2); | |
1785 elseif (lf > 4 && strcmp (file(end-3:end), ".oct")) | |
1786 functions{end+1} = file(1:end-4); | |
5801 | 1787 endif |
6496 | 1788 endfor |
1789 | |
1790 ## Does desc have a categories field? | |
1791 if (! isfield (desc, "categories")) | |
1792 error ("the DESCRIPTION file must have a Categories field, when no INDEX file is given"); | |
1793 endif | |
1794 categories = split_by (desc.categories, ","); | |
1795 if (length (categories) < 1) | |
1796 error ("the Category field is empty"); | |
1797 endif | |
1798 | |
8506 | 1799 ## Write INDEX. |
7498 | 1800 fid = fopen (index_file, "w"); |
6496 | 1801 if (fid == -1) |
7498 | 1802 error ("couldn't open %s for writing.", index_file); |
6496 | 1803 endif |
1804 fprintf (fid, "%s >> %s\n", desc.name, desc.title); | |
1805 fprintf (fid, "%s\n", categories{1}); | |
1806 fprintf (fid, " %s\n", functions{:}); | |
1807 fclose (fid); | |
5801 | 1808 endfunction |
1809 | |
6820 | 1810 function bad_deps = get_unsatisfied_deps (desc, installed_pkgs_lst) |
6496 | 1811 bad_deps = {}; |
5801 | 1812 |
8506 | 1813 ## For each dependency. |
6496 | 1814 for i = 1:length (desc.depends) |
1815 dep = desc.depends{i}; | |
5801 | 1816 |
6496 | 1817 ## Is the current dependency Octave? |
1818 if (strcmp (dep.package, "octave")) | |
1819 if (! compare_versions (OCTAVE_VERSION, dep.version, dep.operator)) | |
1820 bad_deps{end+1} = dep; | |
6258 | 1821 endif |
8506 | 1822 ## Is the current dependency not Octave? |
6496 | 1823 else |
1824 ok = false; | |
6820 | 1825 for i = 1:length (installed_pkgs_lst) |
1826 cur_name = installed_pkgs_lst{i}.name; | |
1827 cur_version = installed_pkgs_lst{i}.version; | |
6496 | 1828 if (strcmp (dep.package, cur_name) |
1829 && compare_versions (cur_version, dep.version, dep.operator)) | |
1830 ok = true; | |
1831 break; | |
6258 | 1832 endif |
1833 endfor | |
6496 | 1834 if (! ok) |
1835 bad_deps{end+1} = dep; | |
1836 endif | |
5801 | 1837 endif |
6496 | 1838 endfor |
1839 endfunction | |
1840 | |
1841 function [out1, out2] = installed_packages (local_list, global_list) | |
8506 | 1842 ## Get the list of installed packages. |
6496 | 1843 try |
1844 local_packages = load (local_list).local_packages; | |
1845 catch | |
1846 local_packages = {}; | |
1847 end_try_catch | |
1848 try | |
6675 | 1849 global_packages = load (global_list).global_packages; |
6496 | 1850 catch |
1851 global_packages = {}; | |
1852 end_try_catch | |
6820 | 1853 installed_pkgs_lst = {local_packages{:}, global_packages{:}}; |
6496 | 1854 |
1855 ## Eliminate duplicates in the installed package list. | |
8506 | 1856 ## Locally installed packages take precedence. |
6496 | 1857 dup = []; |
6820 | 1858 for i = 1:length (installed_pkgs_lst) |
6496 | 1859 if (find (dup, i)) |
1860 continue; | |
5801 | 1861 endif |
6820 | 1862 for j = (i+1):length (installed_pkgs_lst) |
6496 | 1863 if (find (dup, j)) |
1864 continue; | |
1865 endif | |
6820 | 1866 if (strcmp (installed_pkgs_lst{i}.name, installed_pkgs_lst{j}.name)) |
6496 | 1867 dup = [dup, j]; |
1868 endif | |
5987 | 1869 endfor |
6496 | 1870 endfor |
1871 if (! isempty(dup)) | |
6820 | 1872 installed_pkgs_lst(dup) = []; |
6496 | 1873 endif |
1874 | |
8506 | 1875 ## Now check if the package is loaded. |
6645 | 1876 tmppath = strrep (path(), "\\", "/"); |
6820 | 1877 for i = 1:length (installed_pkgs_lst) |
1878 if (findstr (tmppath, strrep (installed_pkgs_lst{i}.dir, "\\", "/"))) | |
1879 installed_pkgs_lst{i}.loaded = true; | |
6616 | 1880 else |
6820 | 1881 installed_pkgs_lst{i}.loaded = false; |
6616 | 1882 endif |
1883 endfor | |
6675 | 1884 for i = 1:length (local_packages) |
6776 | 1885 if (findstr (tmppath, strrep (local_packages{i}.dir, "\\", "/"))) |
6675 | 1886 local_packages{i}.loaded = true; |
1887 else | |
1888 local_packages{i}.loaded = false; | |
1889 endif | |
1890 endfor | |
1891 for i = 1:length (global_packages) | |
6776 | 1892 if (findstr (tmppath, strrep (global_packages{i}.dir, "\\", "/"))) |
6675 | 1893 global_packages{i}.loaded = true; |
1894 else | |
1895 global_packages{i}.loaded = false; | |
1896 endif | |
1897 endfor | |
6616 | 1898 |
6496 | 1899 ## Should we return something? |
1900 if (nargout == 2) | |
1901 out1 = local_packages; | |
1902 out2 = global_packages; | |
1903 return; | |
1904 elseif (nargout == 1) | |
6820 | 1905 out1 = installed_pkgs_lst; |
6496 | 1906 return; |
1907 endif | |
1908 | |
8506 | 1909 ## We shouldn't return something, so we'll print something. |
6820 | 1910 num_packages = length (installed_pkgs_lst); |
6496 | 1911 if (num_packages == 0) |
1912 printf ("no packages installed.\n"); | |
1913 return; | |
1914 endif | |
1915 | |
8506 | 1916 ## Compute the maximal lengths of name, version, and dir. |
6496 | 1917 h1 = "Package Name"; |
1918 h2 = "Version"; | |
1919 h3 = "Installation directory"; | |
1920 max_name_length = length (h1); | |
1921 max_version_length = length (h2); | |
1922 names = cell (num_packages, 1); | |
1923 for i = 1:num_packages | |
1924 max_name_length = max (max_name_length, | |
6820 | 1925 length (installed_pkgs_lst{i}.name)); |
6496 | 1926 max_version_length = max (max_version_length, |
6820 | 1927 length (installed_pkgs_lst{i}.version)); |
1928 names{i} = installed_pkgs_lst{i}.name; | |
6496 | 1929 endfor |
6698 | 1930 max_dir_length = terminal_size()(2) - max_name_length - ... |
1931 max_version_length - 7; | |
1932 if (max_dir_length < 20) | |
1933 max_dir_length = Inf; | |
1934 endif | |
1935 | |
6616 | 1936 h1 = postpad (h1, max_name_length + 1, " "); |
6496 | 1937 h2 = postpad (h2, max_version_length, " ");; |
1938 | |
8506 | 1939 ## Print a header. |
6496 | 1940 header = sprintf("%s | %s | %s\n", h1, h2, h3); |
1941 printf (header); | |
1942 tmp = sprintf (repmat ("-", 1, length(header)-1)); | |
1943 tmp(length(h1)+2) = "+"; | |
1944 tmp(length(h1)+length(h2)+5) = "+"; | |
1945 printf ("%s\n", tmp); | |
1946 | |
8506 | 1947 ## Print the packages. |
6616 | 1948 format = sprintf ("%%%ds %%1s| %%%ds | %%s\n", max_name_length, |
6496 | 1949 max_version_length); |
1950 [dummy, idx] = sort (names); | |
1951 for i = 1:num_packages | |
6820 | 1952 cur_name = installed_pkgs_lst{idx(i)}.name; |
1953 cur_version = installed_pkgs_lst{idx(i)}.version; | |
1954 cur_dir = installed_pkgs_lst{idx(i)}.dir; | |
6698 | 1955 if (length (cur_dir) > max_dir_length) |
1956 first_char = length (cur_dir) - max_dir_length + 4; | |
1957 first_filesep = strfind (cur_dir(first_char:end), filesep()); | |
1958 if (! isempty (first_filesep)) | |
7540
3422f39573b1
strcat.m: Matlab compatibility, with cstrcat.m replacing conventional strcat.m.
Ben Abbott <bpabbott@mac.com>
parents:
7498
diff
changeset
|
1959 cur_dir = cstrcat ("...", |
6698 | 1960 cur_dir((first_char + first_filesep(1) - 1):end)); |
1961 else | |
7540
3422f39573b1
strcat.m: Matlab compatibility, with cstrcat.m replacing conventional strcat.m.
Ben Abbott <bpabbott@mac.com>
parents:
7498
diff
changeset
|
1962 cur_dir = cstrcat ("...", cur_dir(first_char:end)); |
6698 | 1963 endif |
1964 endif | |
6820 | 1965 if (installed_pkgs_lst{idx(i)}.loaded) |
6616 | 1966 cur_loaded = "*"; |
1967 else | |
1968 cur_loaded = " "; | |
1969 endif | |
1970 printf (format, cur_name, cur_loaded, cur_version, cur_dir); | |
6496 | 1971 endfor |
5801 | 1972 endfunction |
1973 | |
6496 | 1974 function load_packages (files, handle_deps, local_list, global_list) |
6820 | 1975 installed_pkgs_lst = installed_packages (local_list, global_list); |
1976 num_packages = length (installed_pkgs_lst); | |
6496 | 1977 |
8506 | 1978 ## Read package names and installdirs into a more convenient format. |
6496 | 1979 pnames = pdirs = cell (1, num_packages); |
1980 for i = 1:num_packages | |
6820 | 1981 pnames{i} = installed_pkgs_lst{i}.name; |
1982 pdirs{i} = installed_pkgs_lst{i}.dir; | |
6496 | 1983 endfor |
1984 | |
8506 | 1985 ## Load all. |
6496 | 1986 if (length (files) == 1 && strcmp (files{1}, "all")) |
6820 | 1987 idx = [1:length(installed_pkgs_lst)]; |
8506 | 1988 ## Load auto. |
6695 | 1989 elseif (length (files) == 1 && strcmp (files{1}, "auto")) |
1990 idx = []; | |
6820 | 1991 for i = 1:length (installed_pkgs_lst) |
6496 | 1992 if (exist (fullfile (pdirs{i}, "packinfo", ".autoload"), "file")) |
6695 | 1993 idx (end + 1) = i; |
6496 | 1994 endif |
6037 | 1995 endfor |
8506 | 1996 ## Load package_name1 ... |
6496 | 1997 else |
6695 | 1998 idx = []; |
6496 | 1999 for i = 1:length (files) |
6695 | 2000 idx2 = find (strcmp (pnames, files{i})); |
2001 if (! any (idx2)) | |
6496 | 2002 error ("package %s is not installed", files{i}); |
2003 endif | |
6695 | 2004 idx (end + 1) = idx2; |
6496 | 2005 endfor |
2006 endif | |
6037 | 2007 |
8506 | 2008 ## Load the packages, but take care of the ordering of dependencies. |
6925 | 2009 load_packages_and_dependencies (idx, handle_deps, installed_pkgs_lst, true); |
5801 | 2010 endfunction |
5928 | 2011 |
6496 | 2012 function unload_packages (files, handle_deps, local_list, global_list) |
6820 | 2013 installed_pkgs_lst = installed_packages (local_list, global_list); |
2014 num_packages = length (installed_pkgs_lst); | |
6496 | 2015 |
8506 | 2016 ## Read package names and installdirs into a more convenient format. |
6496 | 2017 pnames = pdirs = cell (1, num_packages); |
2018 for i = 1:num_packages | |
6820 | 2019 pnames{i} = installed_pkgs_lst{i}.name; |
2020 pdirs{i} = installed_pkgs_lst{i}.dir; | |
2021 pdeps{i} = installed_pkgs_lst{i}.depends; | |
6496 | 2022 endfor |
2023 | |
8506 | 2024 ## Get the current octave path. |
6496 | 2025 p = split_by (path(), pathsep ()); |
6203 | 2026 |
6496 | 2027 if (length (files) == 1 && strcmp (files{1}, "all")) |
8506 | 2028 ## Unload all. |
2029 dirs = pdirs; | |
2030 desc = installed_pkgs_lst; | |
6496 | 2031 else |
8506 | 2032 ## Unload package_name1 ... |
6496 | 2033 dirs = {}; |
6925 | 2034 desc = {}; |
6496 | 2035 for i = 1:length (files) |
7208 | 2036 idx = strcmp (pnames, files{i}); |
6496 | 2037 if (! any (idx)) |
2038 error ("package %s is not installed", files{i}); | |
2039 endif | |
7208 | 2040 dirs{end+1} = pdirs{idx}; |
2041 desc{end+1} = installed_pkgs_lst{idx}; | |
6496 | 2042 endfor |
2043 endif | |
2044 | |
8506 | 2045 ## Check for architecture dependent directories. |
6614 | 2046 archdirs = {}; |
2047 for i = 1:length (dirs) | |
7208 | 2048 tmpdir = getarchdir (desc{i}); |
6614 | 2049 if (exist (tmpdir, "dir")) |
7208 | 2050 archdirs{end+1} = dirs{i}; |
2051 archdirs{end+1} = tmpdir; | |
6925 | 2052 else |
7208 | 2053 archdirs{end+1} = dirs{i}; |
6614 | 2054 endif |
2055 endfor | |
2056 | |
8506 | 2057 ## Unload the packages. |
6925 | 2058 for i = 1:length (archdirs) |
2059 d = archdirs{i}; | |
6496 | 2060 idx = strcmp (p, d); |
2061 if (any (idx)) | |
2062 rmpath (d); | |
8506 | 2063 ## FIXME: We should also check if we need to remove items from |
2064 ## EXEC_PATH. | |
6203 | 2065 endif |
6496 | 2066 endfor |
6203 | 2067 endfunction |
2068 | |
5928 | 2069 function [status_out, msg_out] = rm_rf (dir) |
6925 | 2070 if (exist (dir)) |
2071 crr = confirm_recursive_rmdir (); | |
2072 unwind_protect | |
2073 confirm_recursive_rmdir (false); | |
2074 [status, msg] = rmdir (dir, "s"); | |
2075 unwind_protect_cleanup | |
2076 confirm_recursive_rmdir (crr); | |
2077 end_unwind_protect | |
2078 else | |
2079 status = 1; | |
2080 msg = ""; | |
2081 endif | |
5928 | 2082 if (nargout > 0) |
2083 status_out = status; | |
2084 endif | |
2085 if (nargout > 1) | |
2086 msg_out = msg; | |
2087 endif | |
2088 endfunction | |
5971 | 2089 |
2090 function emp = dirempty (nm, ign) | |
6925 | 2091 if (exist (nm, "dir")) |
2092 if (nargin < 2) | |
2093 ign = {".", ".."}; | |
2094 else | |
2095 ign = [{".", ".."}, ign]; | |
2096 endif | |
2097 l = dir (nm); | |
2098 for i = 1:length (l) | |
2099 found = false; | |
2100 for j = 1:length (ign) | |
2101 if (strcmp (l(i).name, ign{j})) | |
2102 found = true; | |
2103 break; | |
2104 endif | |
2105 endfor | |
2106 if (! found) | |
2107 emp = false; | |
2108 return | |
5971 | 2109 endif |
2110 endfor | |
6925 | 2111 emp = true; |
2112 else | |
2113 emp = true; | |
2114 endif | |
5971 | 2115 endfunction |
6614 | 2116 |
2117 function arch = getarch () | |
7540
3422f39573b1
strcat.m: Matlab compatibility, with cstrcat.m replacing conventional strcat.m.
Ben Abbott <bpabbott@mac.com>
parents:
7498
diff
changeset
|
2118 persistent _arch = cstrcat (octave_config_info("canonical_host_type"), ... |
6675 | 2119 "-", octave_config_info("api_version")); |
6614 | 2120 arch = _arch; |
2121 endfunction | |
6645 | 2122 |
6925 | 2123 function archprefix = getarchprefix (desc, global_install) |
2124 if ((nargin == 2 && global_install) || (nargin < 2 && issuperuser ())) | |
2125 archprefix = fullfile (octave_config_info ("libexecdir"), "octave", | |
7540
3422f39573b1
strcat.m: Matlab compatibility, with cstrcat.m replacing conventional strcat.m.
Ben Abbott <bpabbott@mac.com>
parents:
7498
diff
changeset
|
2126 "packages", cstrcat(desc.name, "-", desc.version)); |
6925 | 2127 else |
2128 archprefix = desc.dir; | |
2129 endif | |
2130 endfunction | |
2131 | |
2132 function archdir = getarchdir (desc) | |
2133 archdir = fullfile (desc.archprefix, getarch()); | |
2134 endfunction | |
2135 | |
2136 function s = issuperuser () | |
2137 if ((ispc () && ! isunix ()) || (geteuid() == 0)) | |
2138 s = true; | |
2139 else | |
2140 s = false; | |
2141 endif | |
2142 endfunction | |
2143 | |
6645 | 2144 function [status, output] = shell (cmd) |
2145 persistent have_sh; | |
2146 | |
2147 cmd = strrep (cmd, "\\", "/"); | |
2148 if (ispc () && ! isunix ()) | |
2149 if (isempty(have_sh)) | |
2150 if (system("sh.exe -c \"exit\"")) | |
2151 have_sh = false; | |
2152 else | |
2153 have_sh = true; | |
2154 endif | |
2155 endif | |
2156 if (have_sh) | |
7540
3422f39573b1
strcat.m: Matlab compatibility, with cstrcat.m replacing conventional strcat.m.
Ben Abbott <bpabbott@mac.com>
parents:
7498
diff
changeset
|
2157 [status, output] = system (cstrcat ("sh.exe -c \"", cmd, "\"")); |
6645 | 2158 else |
2159 error ("Can not find the command shell") | |
2160 endif | |
2161 else | |
2162 [status, output] = system (cmd); | |
2163 endif | |
2164 endfunction | |
6695 | 2165 |
2166 function newdesc = save_order (desc) | |
2167 newdesc = {}; | |
2168 for i = 1 : length(desc) | |
2169 deps = desc{i}.depends; | |
2170 if (isempty (deps) || (length (deps) == 1 && | |
2171 strcmp(deps{1}.package, "octave"))) | |
2172 newdesc {end + 1} = desc{i}; | |
2173 else | |
2174 tmpdesc = {}; | |
2175 for k = 1 : length (deps) | |
2176 for j = 1 : length (desc) | |
2177 if (strcmp (desc{j}.name, deps{k}.package)) | |
7208 | 2178 tmpdesc{end+1} = desc{j}; |
6695 | 2179 break; |
2180 endif | |
2181 endfor | |
2182 endfor | |
2183 if (! isempty (tmpdesc)) | |
2184 newdesc = {newdesc{:}, save_order(tmpdesc){:}, desc{i}}; | |
2185 else | |
7208 | 2186 newdesc{end+1} = desc{i}; |
6695 | 2187 endif |
2188 endif | |
2189 endfor | |
8506 | 2190 ## Eliminate the duplicates. |
6695 | 2191 idx = []; |
2192 for i = 1 : length (newdesc) | |
2193 for j = (i + 1) : length (newdesc) | |
2194 if (strcmp (newdesc{i}.name, newdesc{j}.name)) | |
2195 idx (end + 1) = j; | |
2196 endif | |
2197 endfor | |
2198 endfor | |
2199 newdesc(idx) = []; | |
2200 endfunction | |
2201 | |
6925 | 2202 function load_packages_and_dependencies (idx, handle_deps, installed_pkgs_lst, |
2203 global_install) | |
6820 | 2204 idx = load_package_dirs (idx, [], handle_deps, installed_pkgs_lst); |
6695 | 2205 dirs = {}; |
2206 execpath = EXEC_PATH (); | |
2207 for i = idx; | |
6820 | 2208 ndir = installed_pkgs_lst{i}.dir; |
7208 | 2209 dirs{end+1} = ndir; |
6695 | 2210 if (exist (fullfile (dirs{end}, "bin"), "dir")) |
7540
3422f39573b1
strcat.m: Matlab compatibility, with cstrcat.m replacing conventional strcat.m.
Ben Abbott <bpabbott@mac.com>
parents:
7498
diff
changeset
|
2211 execpath = cstrcat (fullfile (dirs{end}, "bin"), ":", execpath); |
6695 | 2212 endif |
7208 | 2213 tmpdir = getarchdir (installed_pkgs_lst{i}); |
6695 | 2214 if (exist (tmpdir, "dir")) |
2215 dirs{end + 1} = tmpdir; | |
6950 | 2216 if (exist (fullfile (dirs{end}, "bin"), "dir")) |
7540
3422f39573b1
strcat.m: Matlab compatibility, with cstrcat.m replacing conventional strcat.m.
Ben Abbott <bpabbott@mac.com>
parents:
7498
diff
changeset
|
2217 execpath = cstrcat (fullfile (dirs{end}, "bin"), ":", execpath); |
6950 | 2218 endif |
6695 | 2219 endif |
2220 endfor | |
2221 | |
8506 | 2222 ## Load the packages. |
6695 | 2223 if (length (dirs) > 0) |
2224 addpath (dirs{:}); | |
2225 endif | |
2226 | |
8506 | 2227 ## Add the binaries to exec_path. |
6695 | 2228 if (! strcmp (EXEC_PATH, execpath)) |
2229 EXEC_PATH (execpath); | |
2230 endif | |
2231 endfunction | |
2232 | |
6820 | 2233 function idx = load_package_dirs (lidx, idx, handle_deps, installed_pkgs_lst) |
6695 | 2234 for i = lidx |
6820 | 2235 if (isfield (installed_pkgs_lst{i}, "loaded") && |
2236 installed_pkgs_lst{i}.loaded) | |
6695 | 2237 continue; |
2238 else | |
2239 if (handle_deps) | |
6820 | 2240 deps = installed_pkgs_lst{i}.depends; |
6695 | 2241 if ((length (deps) > 1) || (length (deps) == 1 && |
2242 ! strcmp(deps{1}.package, "octave"))) | |
2243 tmplidx = []; | |
2244 for k = 1 : length (deps) | |
6820 | 2245 for j = 1 : length (installed_pkgs_lst) |
2246 if (strcmp (installed_pkgs_lst{j}.name, deps{k}.package)) | |
6695 | 2247 tmplidx (end + 1) = j; |
2248 break; | |
2249 endif | |
2250 endfor | |
2251 endfor | |
2252 idx = load_package_dirs (tmplidx, idx, handle_deps, | |
6820 | 2253 installed_pkgs_lst); |
6695 | 2254 endif |
2255 endif | |
2256 if (isempty (find(idx == i))) | |
2257 idx (end + 1) = i; | |
2258 endif | |
2259 endif | |
2260 endfor | |
2261 endfunction | |
6950 | 2262 |
2263 function dep = is_architecture_dependent (nm) | |
7329 | 2264 persistent archdepsuffix = {".oct",".mex",".a",".lib",".so",".so.*",".dll","dylib"}; |
6950 | 2265 |
2266 dep = false; | |
2267 for i = 1 : length (archdepsuffix) | |
7208 | 2268 ext = archdepsuffix{i}; |
6950 | 2269 if (ext(end) == "*") |
2270 isglob = true; | |
2271 ext(end) = []; | |
2272 else | |
2273 isglob = false; | |
2274 endif | |
2275 pos = findstr (nm, ext); | |
2276 if (pos) | |
7208 | 2277 if (! isglob && (length(nm) - pos(end) != length(ext) - 1)) |
6950 | 2278 continue; |
2279 endif | |
2280 dep = true; | |
2281 break; | |
2282 endif | |
2283 endfor | |
2284 endfunction |