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