1 ## Copyright (C) 2005-2012 S�ren Hauberg
2 ## Copyright (C) 2010 VZLU Prague, a.s.
4 ## This file is part of Octave.
6 ## Octave is free software; you can redistribute it and/or modify it
7 ## under the terms of the GNU General Public License as published by
8 ## the Free Software Foundation; either version 3 of the License, or (at
9 ## your option) any later version.
11 ## Octave is distributed in the hope that it will be useful, but
12 ## WITHOUT ANY WARRANTY; without even the implied warranty of
13 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 ## General Public License for more details.
16 ## You should have received a copy of the GNU General Public License
17 ## along with Octave; see the file COPYING. If not, see
18 ## <http://www.gnu.org/licenses/>.
21 ## @deftypefn {Command} {} pkg @var{command} @var{pkg_name}
22 ## @deftypefnx {Command} {} pkg @var{command} @var{option} @var{pkg_name}
23 ## Manage packages (groups of add-on functions) for Octave. Different actions
24 ## are available depending on the value of @var{command}.
26 ## Available commands:
31 ## Install named packages. For example,
34 ## pkg install image-1.0.0.tar.gz
38 ## installs the package found in the file @file{image-1.0.0.tar.gz}.
40 ## The @var{option} variable can contain options that affect the manner
41 ## in which a package is installed. These options can be one or more of
45 ## The package manager will disable dependency checking. With this option it
46 ## is possible to install a package even when it depends on another package
47 ## which is not installed on the system. @strong{Use this option with care.}
50 ## The package manager will not automatically load the installed package
51 ## when starting Octave. This overrides any setting within the package.
54 ## The package manager will automatically load the installed package when
55 ## starting Octave. This overrides any setting within the package.
58 ## A local installation (package available only to current user) is forced,
59 ## even if the user has system privileges.
62 ## A global installation (package available to all users) is forced, even if
63 ## the user doesn't normally have system privileges.
66 ## Install a package directly from the Octave-Forge repository. This
67 ## requires an internet connection and the cURL library.
70 ## The package manager will print the output of all commands as
71 ## they are performed.
75 ## Check installed Octave-Forge packages against repository and update any
76 ## outdated items. This requires an internet connection and the cURL library.
84 ## Uninstall named packages. For example,
87 ## pkg uninstall image
91 ## removes the @code{image} package from the system. If another installed
92 ## package depends on the @code{image} package an error will be issued.
93 ## The package can be uninstalled anyway by using the @option{-nodeps} option.
96 ## Add named packages to the path. After loading a package it is
97 ## possible to use the functions provided by the package. For example,
104 ## adds the @code{image} package to the path. It is possible to load all
105 ## installed packages at once with the keyword @samp{all}. Usage:
112 ## Remove named packages from the path. After unloading a package it is
113 ## no longer possible to use the functions provided by the package. It is
114 ## possible to unload all installed packages at once with the keyword
115 ## @samp{all}. Usage:
122 ## Show the list of currently installed packages. For example,
125 ## installed_packages = pkg ("list")
129 ## returns a cell array containing a structure for each installed package.
131 ## If two output arguments are requested @code{pkg} splits the list of
132 ## installed packages into those which were installed by the current user,
133 ## and those which were installed by the system administrator.
136 ## [user_packages, system_packages] = pkg ("list")
139 ## The option '-forge' lists packages available at the Octave-Forge repository.
140 ## This requires an internet connection and the cURL library. For example:
143 ## oct_forge_pkgs = pkg ("list", "-forge")
147 ## Show a short description of the named installed packages, with the option
148 ## '-verbose' also list functions provided by the package. For example,
151 ## pkg describe -verbose all
155 ## will describe all installed packages and the functions they provide.
156 ## If one output is requested a cell of structure containing the
157 ## description and list of functions of each package is returned as
158 ## output rather than printed on screen:
161 ## desc = pkg ("describe", "secs1d", "image")
165 ## If any of the requested packages is not installed, pkg returns an
166 ## error, unless a second output is requested:
169 ## [desc, flag] = pkg ("describe", "secs1d", "image")
173 ## @var{flag} will take one of the values "Not installed", "Loaded" or
174 ## "Not loaded" for each of the named packages.
177 ## Set the installation prefix directory. For example,
180 ## pkg prefix ~/my_octave_packages
184 ## sets the installation prefix to @file{~/my_octave_packages}.
185 ## Packages will be installed in this directory.
187 ## It is possible to get the current installation prefix by requesting an
188 ## output argument. For example:
191 ## pfx = pkg ("prefix")
194 ## The location in which to install the architecture dependent files can be
195 ## independently specified with an addition argument. For example:
198 ## pkg prefix ~/my_octave_packages ~/my_arch_dep_pkgs
202 ## Set the file in which to look for information on locally
203 ## installed packages. Locally installed packages are those that are
204 ## available only to the current user. For example:
207 ## pkg local_list ~/.octave_packages
210 ## It is possible to get the current value of local_list with the following
217 ## Set the file in which to look for information on globally
218 ## installed packages. Globally installed packages are those that are
219 ## available to all users. For example:
222 ## pkg global_list /usr/share/octave/octave_packages
225 ## It is possible to get the current value of global_list with the following
232 ## Build a binary form of a package or packages. The binary file produced
233 ## will itself be an Octave package that can be installed normally with
234 ## @code{pkg}. The form of the command to build a binary package is
237 ## pkg build builddir image-1.0.0.tar.gz @dots{}
241 ## where @code{builddir} is the name of a directory where the temporary
242 ## installation will be produced and the binary packages will be found.
243 ## The options @option{-verbose} and @option{-nodeps} are respected, while
244 ## all other options are ignored.
247 ## Rebuild the package database from the installed directories. This can
248 ## be used in cases where the package database has been corrupted.
249 ## It can also take the @option{-auto} and @option{-noauto} options to allow the
250 ## autoloading state of a package to be changed. For example,
253 ## pkg rebuild -noauto image
257 ## will remove the autoloading status of the image package.
262 function [local_packages, global_packages] = pkg (varargin)
263 ## Installation prefix (FIXME: what should these be on windows?)
264 persistent user_prefix = false;
265 persistent prefix = -1;
266 persistent archprefix = -1;
267 persistent local_list = tilde_expand (fullfile ("~", ".octave_packages"));
268 persistent global_list = fullfile (OCTAVE_HOME (), "share", "octave",
272 global_install = issuperuser ();
276 prefix = fullfile (OCTAVE_HOME (), "share", "octave", "packages");
277 archprefix = fullfile (octave_config_info ("libdir"),
278 "octave", "packages");
280 prefix = fullfile ("~", "octave");
283 prefix = tilde_expand (prefix);
284 archprefix = tilde_expand (archprefix);
287 available_actions = {"list", "install", "uninstall", "load", ...
288 "unload", "prefix", "local_list", ...
289 "global_list", "rebuild", "build", ...
290 "describe", "update"};
292 if (length (varargin) == 0 || ! iscellstr (varargin))
300 octave_forge = false;
301 for i = 1:length (varargin)
311 ## Send verbose output to pager immediately. Change setting locally.
312 page_output_immediately (true, "local");
316 global_install = false;
318 prefix = tilde_expand (fullfile ("~", "octave"));
322 global_install = true;
324 prefix = fullfile (OCTAVE_HOME (), "share", "octave", "packages");
325 archprefix = fullfile (octave_config_info ("libdir"),
326 "octave", "packages");
328 case available_actions
329 if (strcmp (action, "none"))
330 action = varargin{i};
332 error ("more than one action specified");
335 files{end+1} = varargin{i};
339 if (octave_forge && ! any (strcmp (action, {"install", "list"})))
340 error ("-forge can only be used with install or list");
348 local_packages = list_forge_packages ();
350 list_forge_packages ();
354 installed_packages (local_list, global_list);
355 elseif (nargout == 1)
356 local_packages = installed_packages (local_list, global_list);
357 elseif (nargout == 2)
358 [local_packages, global_packages] = installed_packages (local_list,
361 error ("too many output arguments requested");
366 if (length (files) == 0)
367 error ("you must specify at least one filename when calling 'pkg install'");
374 [urls, local_files] = cellfun ("get_forge_download", files, "uniformoutput", false);
375 [files, succ] = cellfun ("urlwrite", urls, local_files, "uniformoutput", false);
378 i = find (! succ, 1);
379 error ("could not download file %s from url %s", local_files{i}, urls{i});
383 install (files, deps, auto, prefix, archprefix, verbose, local_list,
384 global_list, global_install);
386 unwind_protect_cleanup
387 cellfun ("unlink", local_files);
391 if (length (files) == 0)
392 error ("you must specify at least one package when calling 'pkg uninstall'");
394 uninstall (files, deps, verbose, local_list,
395 global_list, global_install);
398 if (length (files) == 0)
399 error ("you must specify at least one package, 'all' or 'auto' when calling 'pkg load'");
401 load_packages (files, deps, local_list, global_list);
404 if (length (files) == 0)
405 error ("you must specify at least one package or 'all' when calling 'pkg unload'");
407 unload_packages (files, deps, local_list, global_list);
410 if (length (files) == 0 && nargout == 0)
411 printf ("Installation prefix: %s\n", prefix);
412 printf ("Architecture dependent prefix: %s\n", archprefix);
413 elseif (length (files) == 0 && nargout >= 1)
414 local_packages = prefix;
415 global_packages = archprefix;
416 elseif (length (files) >= 1 && nargout <= 2 && ischar (files{1}))
418 prefix = absolute_pathname (prefix);
419 local_packages = prefix;
421 if (length (files) >= 2 && ischar (files{2}))
422 archprefix = files{2};
424 archprefix = absolute_pathname (archprefix);
427 warning ("creating the directory %s\n", archprefix);
428 archprefix = absolute_pathname (archprefix);
430 global_packages = archprefix;
433 error ("you must specify a prefix directory, or request an output argument");
437 if (length (files) == 0 && nargout == 0)
439 elseif (length (files) == 0 && nargout == 1)
440 local_packages = local_list;
441 elseif (length (files) == 1 && nargout == 0 && ischar (files{1}))
443 local_list = absolute_pathname (files{1});
445 ## Force file to be created
446 fclose (fopen (files{1}, "wt"));
447 local_list = absolute_pathname (files{1});
450 error ("you must specify a local_list file, or request an output argument");
454 if (length (files) == 0 && nargout == 0)
456 elseif (length (files) == 0 && nargout == 1)
457 local_packages = global_list;
458 elseif (length (files) == 1 && nargout == 0 && ischar (files{1}))
460 global_list = absolute_pathname (files{1});
462 ## Force file to be created
463 fclose (fopen (files{1}, "wt"));
464 global_list = absolute_pathname (files{1});
467 error ("you must specify a global_list file, or request an output argument");
472 global_packages = rebuild (prefix, archprefix, global_list, files,
474 global_packages = save_order (global_packages);
475 save (global_list, "global_packages");
477 local_packages = global_packages;
480 local_packages = rebuild (prefix, archprefix, local_list, files, auto,
482 local_packages = save_order (local_packages);
483 save (local_list, "local_packages");
485 clear ("local_packages");
490 if (length (files) < 2)
491 error ("you must specify at least the build directory and one filename\nwhen calling 'pkg build'");
493 build (files, deps, auto, verbose);
496 if (length (files) == 0)
497 error ("you must specify at least one package or 'all' when calling 'pkg describe'");
499 ## FIXME: the name of the output variables is inconsistent
500 ## with their content
503 describe (files, verbose, local_list, global_list);
505 pkg_desc_list = describe (files, verbose, local_list, ...
507 local_packages = pkg_desc_list;
509 [pkg_desc_list, flag] = describe (files, verbose, local_list, ...
511 local_packages = pkg_desc_list;
512 global_packages = flag;
514 error ("you can request at most two outputs when calling 'pkg describe'");
519 installed_pkgs_lst = installed_packages (local_list, global_list);
520 for i = 1:length (installed_pkgs_lst)
521 installed_pkg_name = installed_pkgs_lst{i}.name;
522 installed_pkg_version = installed_pkgs_lst{i}.version;
523 forge_pkg_version = get_forge_pkg (installed_pkg_name);
524 if (compare_versions (forge_pkg_version, installed_pkg_version, ">"))
525 feval (@pkg, "install", "-forge", installed_pkg_name);
529 error ("no output arguments available");
533 error ("you must specify a valid action for 'pkg'. See 'help pkg' for details");
537 function descriptions = rebuild (prefix, archprefix, list, files, auto, verbose)
539 [dirlist, err, msg] = readdir (prefix);
541 error ("couldn't read directory %s: %s", prefix, msg);
543 ## the two first entries of dirlist are "." and ".."
546 old_descriptions = installed_packages (list, list);
550 dirlist = glob (cellfun(@(x) cstrcat(x, '-*'), files, 'uniformoutput', 0));
551 unwind_protect_cleanup
556 for k = 1:length (dirlist)
557 descfile = fullfile (prefix, dirlist{k}, "packinfo", "DESCRIPTION");
559 printf ("recreating package description from %s\n", dirlist{k});
561 if (exist (descfile, "file"))
562 desc = get_description (descfile);
563 desc.dir = fullfile (prefix, dirlist{k});
564 desc.archprefix = fullfile (archprefix, cstrcat (desc.name, "-",
567 if (exist (fullfile (desc.dir, "packinfo", ".autoload"), "file"))
568 unlink (fullfile (desc.dir, "packinfo", ".autoload"));
574 fclose (fopen (fullfile (desc.dir, "packinfo", ".autoload"), "wt"));
577 if (exist (fullfile (desc.dir, "packinfo", ".autoload"), "file"))
583 descriptions{end + 1} = desc;
585 warning ("directory %s is not a valid package", dirlist{k});
589 if (! isempty (files))
590 ## We are rebuilding for a particular package(s) so we should take
591 ## care to keep the other untouched packages in the descriptions
592 descriptions = {descriptions{:}, old_descriptions{:}};
595 for i = 1:length (descriptions)
599 for j = (i+1):length (descriptions)
603 if (strcmp (descriptions{i}.name, descriptions{j}.name))
609 descriptions (dup) = [];
614 function build (files, handle_deps, autoload, verbose)
615 if (length (files) < 1)
616 error ("insufficient number of files");
619 if (! exist (builddir, "dir"))
620 warning ("creating build directory %s", builddir);
621 [status, msg] = mkdir (builddir);
623 error ("could not create installation directory: %s", msg);
626 builddir = absolute_pathname (builddir);
627 installdir = fullfile (builddir, "install");
628 if (! exist (installdir, "dir"))
629 [status, msg] = mkdir (installdir);
631 error ("could not create installation directory: %s", msg);
635 buildlist = fullfile (builddir, "octave_packages");
636 install (files, handle_deps, autoload, installdir, installdir, verbose,
637 buildlist, "", false);
639 repackage (builddir, buildlist);
640 unwind_protect_cleanup
641 unload_packages ({"all"}, handle_deps, buildlist, "");
642 if (exist (installdir, "dir"))
645 if (exist (buildlist, "file"))
651 function install (files, handle_deps, autoload, prefix, archprefix, verbose,
652 local_list, global_list, global_install)
654 ## Check that the directory in prefix exist. If it doesn't: create it!
655 if (! exist (prefix, "dir"))
656 warning ("creating installation directory %s", prefix);
657 [status, msg] = mkdir (prefix);
659 error ("could not create installation directory: %s", msg);
663 ## Get the list of installed packages.
664 [local_packages, global_packages] = installed_packages (local_list,
667 installed_pkgs_lst = {local_packages{:}, global_packages{:}};
670 packages = global_packages;
672 packages = local_packages;
675 ## Uncompress the packages and read the DESCRIPTION files.
676 tmpdirs = packdirs = descriptions = {};
678 ## Warn about non existent files.
679 for i = 1:length (files)
680 if (isempty (glob(files{i})))
681 warning ("file %s does not exist", files{i});
685 ## Unpack the package files and read the DESCRIPTION files.
686 files = glob (files);
687 packages_to_uninstall = [];
688 for i = 1:length (files)
691 if (exist (tgz, "file"))
692 ## Create a temporary directory.
694 tmpdirs{end+1} = tmpdir;
696 printf ("mkdir (%s)\n", tmpdir);
698 [status, msg] = mkdir (tmpdir);
700 error ("couldn't create temporary directory: %s", msg);
703 ## Uncompress the package.
704 if (!exist(tgz, "dir"))
706 printf ("untar (%s, %s)\n", tgz, tmpdir);
710 ## Get the name of the directories produced by tar.
711 [dirlist, err, msg] = readdir (tmpdir);
713 error ("couldn't read directory produced by tar: %s", msg);
716 if (length (dirlist) > 3)
717 error ("bundles of packages are not allowed");
720 ## we are dealing with a directory, so just copy the files
722 printf ("Copying directory (%s, %s)\n", tgz, tmpdir);
724 [status, msg, msgid] = copyfile (tgz, tmpdir);
728 dirlist = {".", "..", tgz};
732 if (exist (tgz, "file") || exist (tgz, "dir"))
733 ## The two first entries of dirlist are "." and "..".
734 if (exist (tgz, "file"))
735 packdir = fullfile (tmpdir, dirlist{3});
737 packdir = fullfile (pwd(), dirlist{3});
739 packdirs{end+1} = packdir;
741 ## Make sure the package contains necessary files.
742 verify_directory (packdir);
744 ## Read the DESCRIPTION file.
745 filename = fullfile (packdir, "DESCRIPTION");
746 desc = get_description (filename);
748 ## Verify that package name corresponds with filename.
749 [dummy, nm] = fileparts (tgz);
750 if ((length (nm) >= length (desc.name))
751 && ! strcmp (desc.name, nm(1:length(desc.name))))
752 error ("package name '%s' doesn't correspond to its filename '%s'",
756 ## Set default installation directory.
757 desc.dir = fullfile (prefix, cstrcat (desc.name, "-", desc.version));
759 ## Set default architectire dependent installation directory.
760 desc.archprefix = fullfile (archprefix, cstrcat (desc.name, "-",
764 descriptions{end+1} = desc;
766 ## Are any of the new packages already installed?
767 ## If so we'll remove the old version.
768 for j = 1:length (packages)
769 if (strcmp (packages{j}.name, desc.name))
770 packages_to_uninstall(end+1) = j;
776 ## Something went wrong, delete tmpdirs.
777 for i = 1:length (tmpdirs)
780 rethrow (lasterror ());
783 ## Check dependencies.
787 for i = 1:length (descriptions)
788 desc = descriptions{i};
789 idx2 = setdiff (1:length(descriptions), i);
791 ## Global installation is not allowed to have dependencies on locally
792 ## installed packages.
793 idx1 = setdiff (1:length(global_packages), packages_to_uninstall);
794 pseudo_installed_packages = {global_packages{idx1}, ...
797 idx1 = setdiff (1:length(local_packages), packages_to_uninstall);
798 pseudo_installed_packages = {local_packages{idx1}, ...
799 global_packages{:}, ...
802 bad_deps = get_unsatisfied_deps (desc, pseudo_installed_packages);
803 ## Are there any unsatisfied dependencies?
804 if (! isempty (bad_deps))
806 for i = 1:length (bad_deps)
808 error_text = cstrcat (error_text, " ", desc.name, " needs ",
809 dep.package, " ", dep.operator, " ",
815 ## Did we find any unsatisfied dependencies?
817 error ("the following dependencies where unsatisfied:\n %s", error_text);
821 ## Prepare each package for installation.
823 for i = 1:length (descriptions)
824 desc = descriptions{i};
826 prepare_installation (desc, pdir);
827 configure_make (desc, pdir, verbose);
830 ## Something went wrong, delete tmpdirs.
831 for i = 1:length (tmpdirs)
834 rethrow (lasterror ());
837 ## Uninstall the packages that will be replaced.
839 for i = packages_to_uninstall
841 uninstall ({global_packages{i}.name}, false, verbose, local_list,
842 global_list, global_install);
844 uninstall ({local_packages{i}.name}, false, verbose, local_list,
845 global_list, global_install);
849 ## Something went wrong, delete tmpdirs.
850 for i = 1:length (tmpdirs)
853 rethrow (lasterror ());
856 ## Install each package.
858 for i = 1:length (descriptions)
859 desc = descriptions{i};
861 copy_files (desc, pdir, global_install);
862 create_pkgadddel (desc, pdir, "PKG_ADD", global_install);
863 create_pkgadddel (desc, pdir, "PKG_DEL", global_install);
864 finish_installation (desc, pdir, global_install);
865 generate_lookfor_cache (desc);
868 ## Something went wrong, delete tmpdirs.
869 for i = 1:length (tmpdirs)
872 for i = 1:length (descriptions)
873 rm_rf (descriptions{i}.dir);
874 rm_rf (getarchdir (descriptions{i}));
876 rethrow (lasterror ());
879 ## Check if the installed directory is empty. If it is remove it
881 for i = length (descriptions):-1:1
882 if (dirempty (descriptions{i}.dir, {"packinfo", "doc"})
883 && dirempty (getarchdir (descriptions{i})))
884 warning ("package %s is empty\n", descriptions{i}.name);
885 rm_rf (descriptions{i}.dir);
886 rm_rf (getarchdir (descriptions{i}));
887 descriptions(i) = [];
891 ## If the package requested that it is autoloaded, or the installer
892 ## requested that it is, then mark the package as autoloaded.
893 for i = length (descriptions):-1:1
894 if (autoload > 0 || (autoload == 0 && isautoload (descriptions(i))))
895 fclose (fopen (fullfile (descriptions{i}.dir, "packinfo",
896 ".autoload"), "wt"));
897 descriptions{i}.autoload = 1;
901 ## Add the packages to the package list.
904 idx = setdiff (1:length(global_packages), packages_to_uninstall);
905 global_packages = save_order ({global_packages{idx}, descriptions{:}});
906 save (global_list, "global_packages");
907 installed_pkgs_lst = {local_packages{:}, global_packages{:}};
909 idx = setdiff (1:length(local_packages), packages_to_uninstall);
910 local_packages = save_order ({local_packages{idx}, descriptions{:}});
911 save (local_list, "local_packages");
912 installed_pkgs_lst = {local_packages{:}, global_packages{:}};
915 ## Something went wrong, delete tmpdirs.
916 for i = 1:length (tmpdirs)
919 for i = 1:length (descriptions)
920 rm_rf (descriptions{i}.dir);
923 printf ("error: couldn't append to %s\n", global_list);
925 printf ("error: couldn't append to %s\n", local_list);
927 rethrow (lasterror ());
930 ## All is well, let's clean up.
931 for i = 1:length (tmpdirs)
932 [status, msg] = rm_rf (tmpdirs{i});
934 warning ("couldn't clean up after my self: %s\n", msg);
938 ## Add the newly installed packages to the path, so the user
939 ## can begin using them. Only load them if they are marked autoload.
940 if (length (descriptions) > 0)
942 for i = 1:length (descriptions)
943 if (isautoload (descriptions(i)))
944 nm = descriptions{i}.name;
945 for j = 1:length (installed_pkgs_lst)
946 if (strcmp (nm, installed_pkgs_lst{j}.name))
953 load_packages_and_dependencies (idx, handle_deps, installed_pkgs_lst,
957 ## If there's a NEWS file, mention it
958 ## we are checking if desc exists too because it's possible to ge to this point
959 ## without creating it such as giving an invalid filename for the package
960 if (exist ("desc", "var") && exist (fullfile (desc.dir, "packinfo", "NEWS"), "file"))
961 printf ("For information about changes from previous versions of the %s package, run 'news (\"%s\")'.\n",
962 desc.name, desc.name);
967 function uninstall (pkgnames, handle_deps, verbose, local_list,
968 global_list, global_install)
969 ## Get the list of installed packages.
970 [local_packages, global_packages] = installed_packages(local_list,
973 installed_pkgs_lst = {local_packages{:}, global_packages{:}};
975 installed_pkgs_lst = local_packages;
978 num_packages = length (installed_pkgs_lst);
980 for i = 1:num_packages
981 cur_name = installed_pkgs_lst{i}.name;
982 if (any (strcmp (cur_name, pkgnames)))
983 delete_idx(end+1) = i;
987 ## Are all the packages that should be uninstalled already installed?
988 if (length (delete_idx) != length (pkgnames))
990 ## Try again for a locally installed package.
991 installed_pkgs_lst = local_packages;
993 num_packages = length (installed_pkgs_lst);
995 for i = 1:num_packages
996 cur_name = installed_pkgs_lst{i}.name;
997 if (any (strcmp (cur_name, pkgnames)))
998 delete_idx(end+1) = i;
1001 if (length (delete_idx) != length (pkgnames))
1002 ## FIXME: We should have a better error message.
1003 warning ("some of the packages you want to uninstall are not installed");
1006 ## FIXME: We should have a better error message.
1007 warning ("some of the packages you want to uninstall are not installed");
1011 ## Compute the packages that will remain installed.
1012 idx = setdiff (1:num_packages, delete_idx);
1013 remaining_packages = {installed_pkgs_lst{idx}};
1015 ## Check dependencies.
1018 for i = 1:length (remaining_packages)
1019 desc = remaining_packages{i};
1020 bad_deps = get_unsatisfied_deps (desc, remaining_packages);
1022 ## Will the uninstallation break any dependencies?
1023 if (! isempty (bad_deps))
1024 for i = 1:length (bad_deps)
1026 error_text = cstrcat (error_text, " ", desc.name, " needs ",
1027 dep.package, " ", dep.operator, " ",
1033 if (! isempty (error_text))
1034 error ("the following dependencies where unsatisfied:\n %s", error_text);
1038 ## Delete the directories containing the packages.
1040 desc = installed_pkgs_lst{i};
1041 ## If an 'on_uninstall.m' exist, call it!
1042 if (exist (fullfile (desc.dir, "packinfo", "on_uninstall.m"), "file"))
1044 cd (fullfile (desc.dir, "packinfo"));
1045 on_uninstall (desc);
1048 ## Do the actual deletion.
1051 if (exist (getarchdir (desc)))
1052 rmpath (getarchdir (desc));
1055 if (exist (desc.dir, "dir"))
1056 [status, msg] = rm_rf (desc.dir);
1058 error ("couldn't delete directory %s: %s", desc.dir, msg);
1060 [status, msg] = rm_rf (getarchdir (desc));
1062 error ("couldn't delete directory %s: %s", getarchdir (desc), msg);
1064 if (dirempty (desc.archprefix))
1065 rm_rf (desc.archprefix);
1068 warning ("directory %s previously lost", desc.dir);
1072 ## Write a new ~/.octave_packages.
1074 if (length (remaining_packages) == 0)
1075 unlink (global_list);
1077 global_packages = save_order (remaining_packages);
1078 save (global_list, "global_packages");
1081 if (length (remaining_packages) == 0)
1082 unlink (local_list);
1084 local_packages = save_order (remaining_packages);
1085 save (local_list, "local_packages");
1091 function [pkg_desc_list, flag] = describe (pkgnames, verbose,
1092 local_list, global_list)
1094 ## Get the list of installed packages.
1095 installed_pkgs_lst = installed_packages(local_list, global_list);
1096 num_packages = length (installed_pkgs_lst);
1099 describe_all = false;
1100 if (any (strcmp ("all", pkgnames)))
1101 describe_all = true;
1102 flag(1:num_packages) = {"Not Loaded"};
1103 num_pkgnames = num_packages;
1105 num_pkgnames = length (pkgnames);
1106 flag(1:num_pkgnames) = {"Not installed"};
1109 for i = 1:num_packages
1110 curr_name = installed_pkgs_lst{i}.name;
1114 name_pos = find(strcmp (curr_name, pkgnames));
1117 if (! isempty (name_pos))
1118 if (installed_pkgs_lst{i}.loaded)
1119 flag{name_pos} = "Loaded";
1121 flag{name_pos} = "Not loaded";
1124 pkg_desc_list{name_pos}.name = installed_pkgs_lst{i}.name;
1125 pkg_desc_list{name_pos}.version = installed_pkgs_lst{i}.version;
1126 pkg_desc_list{name_pos}.description = installed_pkgs_lst{i}.description;
1127 pkg_desc_list{name_pos}.provides = parse_pkg_idx (installed_pkgs_lst{i}.dir);
1132 non_inst = find (strcmp (flag, "Not installed"));
1133 if (! isempty (non_inst))
1135 non_inst_str = sprintf (" %s ", pkgnames{non_inst});
1136 error ("some packages are not installed: %s", non_inst_str);
1138 pkg_desc_list{non_inst} = struct ("name", {}, "description",
1139 {}, "provides", {});
1144 for i = 1:num_pkgnames
1145 print_package_description (pkg_desc_list{i}.name,
1146 pkg_desc_list{i}.version,
1147 pkg_desc_list{i}.provides,
1148 pkg_desc_list{i}.description,
1155 ## AUXILIARY FUNCTIONS
1157 ## Read an INDEX file.
1158 function [pkg_idx_struct] = parse_pkg_idx (packdir)
1160 index_file = fullfile (packdir, "packinfo", "INDEX");
1162 if (! exist (index_file, "file"))
1163 error ("could not find any INDEX file in directory %s, try 'pkg rebuild all' to generate missing INDEX files", packdir);
1167 [fid, msg] = fopen (index_file, "r");
1169 error ("the INDEX file %s could not be read: %s",
1174 pkg_idx_struct{1}.category = "Uncategorized";
1175 pkg_idx_struct{1}.functions = {};
1178 while (isempty (strfind (line, ">>")) && ! feof (fid))
1182 while (! feof (fid) || line != -1)
1183 if (! any (! isspace (line)) || line(1) == "#" || any (line == "="))
1184 ## Comments, blank lines or comments about unimplemented
1185 ## functions: do nothing
1186 ## FIXME: probably comments and pointers to external functions
1187 ## could be treated better when printing to screen?
1188 elseif (! isempty (strfind (line, ">>")))
1189 ## Skip package name and description as they are in DESCRIPTION
1191 elseif (! isspace (line(1)))
1193 if (! isempty (pkg_idx_struct{cat_num}.functions))
1194 pkg_idx_struct{++cat_num}.functions = {};
1196 pkg_idx_struct{cat_num}.category = deblank (line);
1199 while (any (! isspace (line)))
1200 [fun_name, line] = strtok (line);
1201 pkg_idx_struct{cat_num}.functions{end+1} = deblank (fun_name);
1209 function print_package_description (pkg_name, pkg_ver, pkg_idx_struct,
1210 pkg_desc, status, verbose)
1212 printf ("---\nPackage name:\n\t%s\n", pkg_name);
1213 printf ("Version:\n\t%s\n", pkg_ver);
1214 printf ("Short description:\n\t%s\n", pkg_desc);
1215 printf ("Status:\n\t%s\n", status);
1217 printf ("---\nProvides:\n");
1218 for i = 1:length(pkg_idx_struct)
1219 if (! isempty (pkg_idx_struct{i}.functions))
1220 printf ("%s\n", pkg_idx_struct{i}.category);
1221 for j = 1:length(pkg_idx_struct{i}.functions)
1222 printf ("\t%s\n", pkg_idx_struct{i}.functions{j});
1231 function pth = absolute_pathname (pth)
1232 [status, msg, msgid] = fileattrib (pth);
1234 error ("could not find the file or path %s", pth);
1240 function repackage (builddir, buildlist)
1241 packages = installed_packages (buildlist, buildlist);
1244 for i = 1 : length(packages)
1249 mkdir (fullfile (pack.name, "inst"));
1250 copyfile (fullfile (pack.dir, "*"), fullfile (pack.name, "inst"));
1251 movefile (fullfile (pack.name, "inst","packinfo", "*"), pack.name);
1252 if (exist (fullfile (pack.name, "inst","packinfo", ".autoload"), "file"))
1253 unlink (fullfile (pack.name, "inst","packinfo", ".autoload"));
1255 rmdir (fullfile (pack.name, "inst", "packinfo"));
1256 if (exist (fullfile (pack.name, "inst", "doc"), "dir"))
1257 movefile (fullfile (pack.name, "inst", "doc"), pack.name);
1259 if (exist (fullfile (pack.name, "inst", "bin"), "dir"))
1260 movefile (fullfile (pack.name, "inst", "bin"), pack.name);
1262 archdir = fullfile (pack.archprefix, cstrcat (pack.name, "-",
1263 pack.version), getarch ());
1264 if (exist (archdir, "dir"))
1265 if (exist (fullfile (pack.name, "inst", "PKG_ADD"), "file"))
1266 unlink (fullfile (pack.name, "inst", "PKG_ADD"));
1268 if (exist (fullfile (pack.name, "inst", "PKG_DEL"), "file"))
1269 unlink (fullfile (pack.name, "inst", "PKG_DEL"));
1271 if (exist (fullfile (archdir, "PKG_ADD"), "file"))
1272 movefile (fullfile (archdir, "PKG_ADD"),
1273 fullfile (pack.name, "PKG_ADD"));
1275 if (exist (fullfile (archdir, "PKG_DEL"), "file"))
1276 movefile (fullfile (archdir, "PKG_DEL"),
1277 fullfile (pack.name, "PKG_DEL"));
1280 if (exist (fullfile (pack.name, "inst", "PKG_ADD"), "file"))
1281 movefile (fullfile (pack.name, "inst", "PKG_ADD"),
1282 fullfile (pack.name, "PKG_ADD"));
1284 if (exist (fullfile (pack.name, "inst", "PKG_DEL"), "file"))
1285 movefile (fullfile (pack.name, "inst", "PKG_DEL"),
1286 fullfile (pack.name, "PKG_DEL"));
1289 tfile = cstrcat (pack.name, "-", pack.version, ".tar");
1290 tar (tfile, pack.name);
1295 warning ("failed to compress %s", tfile);
1297 unwind_protect_cleanup
1298 if (exist (pack.name, "dir"))
1306 function auto = isautoload (desc)
1308 if (isfield (desc{1}, "autoload"))
1309 a = desc{1}.autoload;
1310 if ((isnumeric (a) && a > 0)
1311 || (ischar (a) && (strcmpi (a, "true")
1312 || strcmpi (a, "on")
1313 || strcmpi (a, "yes")
1314 || strcmpi (a, "1"))))
1320 function prepare_installation (desc, packdir)
1321 ## Is there a pre_install to call?
1322 if (exist (fullfile (packdir, "pre_install.m"), "file"))
1330 rethrow (lasterror ());
1334 ## If the directory "inst" doesn't exist, we create it.
1335 inst_dir = fullfile (packdir, "inst");
1336 if (! exist (inst_dir, "dir"))
1337 [status, msg] = mkdir (inst_dir);
1340 error ("the 'inst' directory did not exist and could not be created: %s",
1346 function configure_make (desc, packdir, verbose)
1347 ## Perform ./configure, make, make install in "src".
1348 if (exist (fullfile (packdir, "src"), "dir"))
1349 src = fullfile (packdir, "src");
1350 octave_bindir = octave_config_info ("bindir");
1351 mkoctfile = fullfile (octave_bindir, "mkoctfile");
1352 octave_config = fullfile (octave_bindir, "octave-config");
1353 octave_binary = fullfile (octave_bindir, "octave");
1354 cenv = {"MKOCTFILE"; mkoctfile;
1355 "OCTAVE_CONFIG"; octave_config;
1356 "OCTAVE"; octave_binary;
1357 "INSTALLDIR"; desc.dir};
1358 scenv = sprintf ("%s=\"%s\" ", cenv{:});
1360 if (exist (fullfile (src, "configure"), "file"))
1362 if (isempty (getenv ("CC")))
1363 flags = cstrcat (flags, " CC=\"", octave_config_info ("CC"), "\"");
1365 if (isempty (getenv ("CXX")))
1366 flags = cstrcat (flags, " CXX=\"", octave_config_info ("CXX"), "\"");
1368 if (isempty (getenv ("AR")))
1369 flags = cstrcat (flags, " AR=\"", octave_config_info ("AR"), "\"");
1371 if (isempty (getenv ("RANLIB")))
1372 flags = cstrcat (flags, " RANLIB=\"", octave_config_info ("RANLIB"), "\"");
1374 [status, output] = shell (cstrcat ("cd '", src, "'; ", scenv,
1375 "./configure --prefix=\"",
1376 desc.dir, "\"", flags));
1379 error ("the configure script returned the following error: %s", output);
1381 printf("%s", output);
1387 if (exist (fullfile (src, "Makefile"), "file"))
1388 [status, output] = shell (cstrcat (scenv, "make -C '", src, "'"));
1391 error ("'make' returned the following error: %s", output);
1393 printf("%s", output);
1397 ## Copy files to "inst" and "inst/arch" (this is instead of 'make
1399 files = fullfile (src, "FILES");
1400 instdir = fullfile (packdir, "inst");
1401 archdir = fullfile (packdir, "inst", getarch ());
1404 if (exist (files, "file"))
1405 [fid, msg] = fopen (files, "r");
1407 error ("couldn't open %s: %s", files, msg);
1409 filenames = char (fread (fid))';
1411 if (filenames(end) == "\n")
1412 filenames(end) = [];
1414 filenames = split_by (filenames, "\n");
1416 for i = 1:length (filenames)
1417 if (! all (isspace (filenames{i})))
1418 filenames{i} = fullfile (src, filenames{i});
1420 delete_idx(end+1) = i;
1423 filenames(delete_idx) = [];
1425 m = dir (fullfile (src, "*.m"));
1426 oct = dir (fullfile (src, "*.oct"));
1427 mex = dir (fullfile (src, "*.mex"));
1429 filenames = cellfun (@(x) fullfile (src, x),
1430 {m.name, oct.name, mex.name},
1431 "uniformoutput", false);
1434 ## Split into architecture dependent and independent files.
1435 if (isempty (filenames))
1438 idx = cellfun ("is_architecture_dependent", filenames);
1440 archdependent = filenames (idx);
1441 archindependent = filenames (!idx);
1444 if (! all (isspace ([filenames{:}])))
1445 if (! exist (instdir, "dir"))
1448 if (! all (isspace ([archindependent{:}])))
1450 printf ("copyfile");
1451 printf (" %s", archindependent{:});
1452 printf ("%s\n", instdir);
1454 [status, output] = copyfile (archindependent, instdir);
1457 error ("Couldn't copy files from 'src' to 'inst': %s", output);
1460 if (! all (isspace ([archdependent{:}])))
1462 printf ("copyfile");
1463 printf (" %s", archdependent{:});
1464 printf (" %s\n", archdir);
1466 if (! exist (archdir, "dir"))
1469 [status, output] = copyfile (archdependent, archdir);
1472 error ("Couldn't copy files from 'src' to 'inst': %s", output);
1479 function pkg = extract_pkg (nm, pat)
1480 fid = fopen (nm, "rt");
1483 while (! feof (fid))
1486 t = regexp (ln, pat, "tokens");
1488 pkg = cstrcat (pkg, "\n", t{1}{1});
1492 if (! isempty (pkg))
1493 pkg = cstrcat (pkg, "\n");
1499 function create_pkgadddel (desc, packdir, nm, global_install)
1500 instpkg = fullfile (desc.dir, nm);
1501 instfid = fopen (instpkg, "wt");
1502 ## If it is exists, most of the PKG_* file should go into the
1503 ## architecture dependent directory so that the autoload/mfilename
1504 ## commands work as expected. The only part that doesn't is the
1505 ## part in the main directory.
1506 archdir = fullfile (getarchprefix (desc), cstrcat (desc.name, "-",
1507 desc.version), getarch ());
1508 if (exist (getarchdir (desc, global_install), "dir"))
1509 archpkg = fullfile (getarchdir (desc, global_install), nm);
1510 archfid = fopen (archpkg, "at");
1516 if (archfid >= 0 && instfid >= 0)
1517 ## Search all dot-m files for PKG commands.
1518 lst = dir (fullfile (packdir, "inst", "*.m"));
1519 for i = 1:length (lst)
1520 nam = fullfile (packdir, "inst", lst(i).name);
1521 fwrite (instfid, extract_pkg (nam, ['^[#%][#%]* *' nm ': *(.*)$']));
1524 ## Search all C++ source files for PKG commands.
1525 lst = dir (fullfile (packdir, "src", "*.cc"));
1526 for i = 1:length (lst)
1527 nam = fullfile (packdir, "src", lst(i).name);
1528 fwrite (archfid, extract_pkg (nam, ['^//* *' nm ': *(.*)$']));
1529 fwrite (archfid, extract_pkg (nam, ['^/\** *' nm ': *(.*) *\*/$']));
1532 ## Add developer included PKG commands.
1533 packdirnm = fullfile (packdir, nm);
1534 if (exist (packdirnm, "file"))
1535 fid = fopen (packdirnm, "rt");
1537 while (! feof (fid))
1540 fwrite (archfid, ln);
1547 ## If the files is empty remove it.
1554 if (instfid != archfid)
1564 function copy_files (desc, packdir, global_install)
1565 ## Create the installation directory.
1566 if (! exist (desc.dir, "dir"))
1567 [status, output] = mkdir (desc.dir);
1569 error ("couldn't create installation directory %s : %s",
1574 octfiledir = getarchdir (desc);
1576 ## Copy the files from "inst" to installdir.
1577 instdir = fullfile (packdir, "inst");
1578 if (! dirempty (instdir))
1579 [status, output] = copyfile (fullfile (instdir, "*"), desc.dir);
1582 error ("couldn't copy files to the installation directory");
1584 if (exist (fullfile (desc.dir, getarch ()), "dir")
1585 && ! strcmp (fullfile (desc.dir, getarch ()), octfiledir))
1586 if (! exist (octfiledir, "dir"))
1587 ## Can be required to create upto three levels of dirs.
1588 octm1 = fileparts (octfiledir);
1589 if (! exist (octm1, "dir"))
1590 octm2 = fileparts (octm1);
1591 if (! exist (octm2, "dir"))
1592 octm3 = fileparts (octm2);
1593 if (! exist (octm3, "dir"))
1594 [status, output] = mkdir (octm3);
1597 error ("couldn't create installation directory %s : %s",
1601 [status, output] = mkdir (octm2);
1604 error ("couldn't create installation directory %s : %s",
1608 [status, output] = mkdir (octm1);
1611 error ("couldn't create installation directory %s : %s",
1615 [status, output] = mkdir (octfiledir);
1618 error ("couldn't create installation directory %s : %s",
1619 octfiledir, output);
1622 [status, output] = movefile (fullfile (desc.dir, getarch (), "*"),
1624 rm_rf (fullfile (desc.dir, getarch ()));
1629 error ("couldn't copy files to the installation directory");
1635 ## Create the "packinfo" directory.
1636 packinfo = fullfile (desc.dir, "packinfo");
1637 [status, msg] = mkdir (packinfo);
1641 error ("couldn't create packinfo directory: %s", msg);
1644 packinfo_copy_file ("DESCRIPTION", "required", packdir, packinfo, desc, octfiledir);
1645 packinfo_copy_file ("COPYING", "required", packdir, packinfo, desc, octfiledir);
1647 packinfo_copy_file ("NEWS", "optional", packdir, packinfo, desc, octfiledir);
1648 packinfo_copy_file ("ONEWS", "optional", packdir, packinfo, desc, octfiledir);
1649 packinfo_copy_file ("ChangeLog", "optional", packdir, packinfo, desc, octfiledir);
1651 ## Is there an INDEX file to copy or should we generate one?
1652 index_file = fullfile (packdir, "INDEX");
1653 if (exist(index_file, "file"))
1654 packinfo_copy_file ("INDEX", "required", packdir, packinfo, desc, octfiledir);
1657 write_index (desc, fullfile (packdir, "inst"),
1658 fullfile (packinfo, "INDEX"), global_install);
1662 rethrow (lasterror ());
1666 ## Is there an 'on_uninstall.m' to install?
1667 packinfo_copy_file ("on_uninstall.m", "optional", packdir, packinfo, desc, octfiledir);
1669 ## Is there a doc/ directory that needs to be installed?
1670 docdir = fullfile (packdir, "doc");
1671 if (exist (docdir, "dir") && ! dirempty (docdir))
1672 [status, output] = copyfile (docdir, desc.dir);
1675 ## Is there a bin/ directory that needs to be installed?
1676 ## FIXME: Need to treat architecture dependent files in bin/
1677 bindir = fullfile (packdir, "bin");
1678 if (exist (bindir, "dir") && ! dirempty (bindir))
1679 [status, output] = copyfile (bindir, desc.dir);
1683 function packinfo_copy_file (filename, requirement, packdir, packinfo, desc, octfiledir)
1684 filepath = fullfile (packdir, filename);
1685 if (!exist (filepath, "file") && strcmpi (requirement, "optional"))
1686 ## do nothing, it's still OK
1688 [status, output] = copyfile (filepath, packinfo);
1692 error ("Couldn't copy %s file: %s", filename, output);
1697 function finish_installation (desc, packdir, global_install)
1698 ## Is there a post-install to call?
1699 if (exist (fullfile (packdir, "post_install.m"), "file"))
1703 post_install (desc);
1708 rm_rf (getarchdir (desc), global_install);
1709 rethrow (lasterror ());
1714 function generate_lookfor_cache (desc)
1715 dirs = split_by (genpath (desc.dir), pathsep ());
1716 for i = 1 : length (dirs)
1717 gen_doc_cache (fullfile (dirs{i}, "doc-cache"), dirs{i});
1721 ## Make sure the package contains the essential files.
1722 function verify_directory (dir)
1723 needed_files = {"COPYING", "DESCRIPTION"};
1724 for f = needed_files
1725 if (! exist (fullfile (dir, f{1}), "file"))
1726 error ("package is missing file: %s", f{1});
1731 ## Parse the DESCRIPTION file.
1732 function desc = get_description (filename)
1733 [fid, msg] = fopen (filename, "r");
1735 error ("the DESCRIPTION file %s could not be read: %s", filename, msg);
1743 ## Comments, do nothing.
1744 elseif (isspace(line(1)))
1745 ## Continuation lines
1746 if (exist ("keyword", "var") && isfield (desc, keyword))
1747 desc.(keyword) = cstrcat (desc.(keyword), " ", rstrip(line));
1750 ## Keyword/value pair
1751 colon = find (line == ":");
1752 if (length (colon) == 0)
1753 disp ("skipping line");
1756 keyword = tolower (strip (line(1:colon-1)));
1757 value = strip (line (colon+1:end));
1758 if (length (value) == 0)
1760 error ("The keyword `%s' of the package `%s' has an empty value",
1761 keyword, desc.name);
1763 desc.(keyword) = value;
1770 ## Make sure all is okay.
1771 needed_fields = {"name", "version", "date", "title", ...
1772 "author", "maintainer", "description"};
1773 for f = needed_fields
1774 if (! isfield (desc, f{1}))
1775 error ("description is missing needed field %s", f{1});
1778 desc.version = fix_version (desc.version);
1779 if (isfield (desc, "depends"))
1780 desc.depends = fix_depends (desc.depends);
1784 desc.name = tolower (desc.name);
1787 ## Make sure the version string v is a valid x.y.z version string
1788 ## Examples: "0.1" => "0.1.0", "monkey" => error(...).
1789 function out = fix_version (v)
1790 dots = find (v == ".");
1791 if (length (dots) == 1)
1792 major = str2num (v(1:dots-1));
1793 minor = str2num (v(dots+1:end));
1794 if (length (major) != 0 && length (minor) != 0)
1795 out = sprintf ("%d.%d.0", major, minor);
1798 elseif (length (dots) == 2)
1799 major = str2num (v(1:dots(1)-1));
1800 minor = str2num (v(dots(1)+1:dots(2)-1));
1801 rev = str2num (v(dots(2)+1:end));
1802 if (length (major) != 0 && length (minor) != 0 && length (rev) != 0)
1803 out = sprintf ("%d.%d.%d", major, minor, rev);
1807 error ("bad version string: %s", v);
1810 ## Make sure the depends field is of the right format.
1811 ## This function returns a cell of structures with the following fields:
1812 ## package, version, operator
1813 function deps_cell = fix_depends (depends)
1814 deps = split_by (tolower (depends), ",");
1815 deps_cell = cell (1, length (deps));
1817 ## For each dependency.
1818 for i = 1:length (deps)
1820 lpar = find (dep == "(");
1821 rpar = find (dep == ")");
1822 ## Does the dependency specify a version
1823 ## Example: package(>= version).
1824 if (length (lpar) == 1 && length (rpar) == 1)
1825 package = tolower (strip (dep(1:lpar-1)));
1826 sub = dep(lpar(1)+1:rpar(1)-1);
1827 parts = strsplit (sub, " ", true);
1828 if (length (parts) != 2)
1829 error ("incorrect syntax for dependency `%s' in the DESCRIPTION file\n",
1832 operator = parts{1};
1833 if (! any (strcmp (operator, {">", ">=", "<=", "<", "=="})))
1834 error ("unsupported operator: %s", operator);
1836 version = fix_version (parts{2});
1838 ## If no version is specified for the dependency
1839 ## we say that the version should be greater than
1840 ## or equal to "0.0.0".
1842 package = tolower (strip (dep));
1846 deps_cell{i} = struct ("package", package, "operator", operator,
1847 "version", version);
1851 ## Strip the text of spaces from the right
1852 ## Example: " hello world " => " hello world"
1853 ## FIXME -- is this the same as deblank?
1854 function text = rstrip (text)
1855 chars = find (! isspace (text));
1856 if (length (chars) > 0)
1857 ## FIXME: shouldn't it be text = text(1:chars(end));
1858 text = text (chars(1):end);
1864 ## Strip the text of spaces from the left and the right.
1865 ## Example: " hello world " => "hello world"
1866 function text = strip (text)
1867 chars = find (! isspace (text));
1868 if (length (chars) > 0)
1869 text = text(chars(1):chars(end));
1875 ## Split the text into a cell array of strings by sep.
1876 ## Example: "A, B" => {"A", "B"} (with sep = ",")
1877 function out = split_by (text, sep)
1878 out = strtrim (strsplit (text, sep));
1881 ## Create an INDEX file for a package that doesn't provide one.
1882 ## 'desc' describes the package.
1883 ## 'dir' is the 'inst' directory in temporary directory.
1884 ## 'index_file' is the name (including path) of resulting INDEX file.
1885 function write_index (desc, dir, index_file, global_install)
1886 ## Get names of functions in dir
1887 [files, err, msg] = readdir (dir);
1889 error ("couldn't read directory %s: %s", dir, msg);
1892 ## Get classes in dir
1893 class_idx = strmatch ("@", files);
1894 for k = 1:length (class_idx)
1895 class_name = files {class_idx (k)};
1896 class_dir = fullfile (dir, class_name);
1897 if (exist (class_dir, "dir"))
1898 [files2, err, msg] = readdir (class_dir);
1900 error ("couldn't read directory %s: %s", class_dir, msg);
1902 files2 = strcat (class_name, filesep (), files2);
1903 files = [files; files2];
1907 ## Check for architecture dependent files.
1908 tmpdir = getarchdir (desc);
1909 if (exist (tmpdir, "dir"))
1910 [files2, err, msg] = readdir (tmpdir);
1912 error ("couldn't read directory %s: %s", tmpdir, msg);
1914 files = [files; files2];
1918 for i = 1:length (files)
1921 if (lf > 2 && strcmp (file(end-1:end), ".m"))
1922 functions{end+1} = file(1:end-2);
1923 elseif (lf > 4 && strcmp (file(end-3:end), ".oct"))
1924 functions{end+1} = file(1:end-4);
1928 ## Does desc have a categories field?
1929 if (! isfield (desc, "categories"))
1930 error ("the DESCRIPTION file must have a Categories field, when no INDEX file is given");
1932 categories = split_by (desc.categories, ",");
1933 if (length (categories) < 1)
1934 error ("the Category field is empty");
1938 fid = fopen (index_file, "w");
1940 error ("couldn't open %s for writing", index_file);
1942 fprintf (fid, "%s >> %s\n", desc.name, desc.title);
1943 fprintf (fid, "%s\n", categories{1});
1944 fprintf (fid, " %s\n", functions{:});
1948 function bad_deps = get_unsatisfied_deps (desc, installed_pkgs_lst)
1951 ## For each dependency.
1952 for i = 1:length (desc.depends)
1953 dep = desc.depends{i};
1955 ## Is the current dependency Octave?
1956 if (strcmp (dep.package, "octave"))
1957 if (! compare_versions (OCTAVE_VERSION, dep.version, dep.operator))
1958 bad_deps{end+1} = dep;
1960 ## Is the current dependency not Octave?
1963 for i = 1:length (installed_pkgs_lst)
1964 cur_name = installed_pkgs_lst{i}.name;
1965 cur_version = installed_pkgs_lst{i}.version;
1966 if (strcmp (dep.package, cur_name)
1967 && compare_versions (cur_version, dep.version, dep.operator))
1973 bad_deps{end+1} = dep;
1979 function [out1, out2] = installed_packages (local_list, global_list)
1980 ## Get the list of installed packages.
1982 local_packages = load (local_list).local_packages;
1984 local_packages = {};
1987 global_packages = load (global_list).global_packages;
1989 global_packages = {};
1991 installed_pkgs_lst = {local_packages{:}, global_packages{:}};
1993 ## Eliminate duplicates in the installed package list.
1994 ## Locally installed packages take precedence.
1996 for i = 1:length (installed_pkgs_lst)
2000 for j = (i+1):length (installed_pkgs_lst)
2004 if (strcmp (installed_pkgs_lst{i}.name, installed_pkgs_lst{j}.name))
2010 installed_pkgs_lst(dup) = [];
2013 ## Now check if the package is loaded.
2014 tmppath = strrep (path(), "\\", "/");
2015 for i = 1:length (installed_pkgs_lst)
2016 if (findstr (tmppath, strrep (installed_pkgs_lst{i}.dir, "\\", "/")))
2017 installed_pkgs_lst{i}.loaded = true;
2019 installed_pkgs_lst{i}.loaded = false;
2022 for i = 1:length (local_packages)
2023 if (findstr (tmppath, strrep (local_packages{i}.dir, "\\", "/")))
2024 local_packages{i}.loaded = true;
2026 local_packages{i}.loaded = false;
2029 for i = 1:length (global_packages)
2030 if (findstr (tmppath, strrep (global_packages{i}.dir, "\\", "/")))
2031 global_packages{i}.loaded = true;
2033 global_packages{i}.loaded = false;
2037 ## Should we return something?
2039 out1 = local_packages;
2040 out2 = global_packages;
2042 elseif (nargout == 1)
2043 out1 = installed_pkgs_lst;
2047 ## We shouldn't return something, so we'll print something.
2048 num_packages = length (installed_pkgs_lst);
2049 if (num_packages == 0)
2050 printf ("no packages installed.\n");
2054 ## Compute the maximal lengths of name, version, and dir.
2055 h1 = "Package Name";
2057 h3 = "Installation directory";
2058 max_name_length = length (h1);
2059 max_version_length = length (h2);
2060 names = cell (num_packages, 1);
2061 for i = 1:num_packages
2062 max_name_length = max (max_name_length,
2063 length (installed_pkgs_lst{i}.name));
2064 max_version_length = max (max_version_length,
2065 length (installed_pkgs_lst{i}.version));
2066 names{i} = installed_pkgs_lst{i}.name;
2068 max_dir_length = terminal_size()(2) - max_name_length - ...
2069 max_version_length - 7;
2070 if (max_dir_length < 20)
2071 max_dir_length = Inf;
2074 h1 = postpad (h1, max_name_length + 1, " ");
2075 h2 = postpad (h2, max_version_length, " ");;
2078 header = sprintf("%s | %s | %s\n", h1, h2, h3);
2080 tmp = sprintf (repmat ("-", 1, length(header)-1));
2081 tmp(length(h1)+2) = "+";
2082 tmp(length(h1)+length(h2)+5) = "+";
2083 printf ("%s\n", tmp);
2085 ## Print the packages.
2086 format = sprintf ("%%%ds %%1s| %%%ds | %%s\n", max_name_length,
2087 max_version_length);
2088 [dummy, idx] = sort (names);
2089 for i = 1:num_packages
2090 cur_name = installed_pkgs_lst{idx(i)}.name;
2091 cur_version = installed_pkgs_lst{idx(i)}.version;
2092 cur_dir = installed_pkgs_lst{idx(i)}.dir;
2093 if (length (cur_dir) > max_dir_length)
2094 first_char = length (cur_dir) - max_dir_length + 4;
2095 first_filesep = strfind (cur_dir(first_char:end), filesep());
2096 if (! isempty (first_filesep))
2097 cur_dir = cstrcat ("...",
2098 cur_dir((first_char + first_filesep(1) - 1):end));
2100 cur_dir = cstrcat ("...", cur_dir(first_char:end));
2103 if (installed_pkgs_lst{idx(i)}.loaded)
2108 printf (format, cur_name, cur_loaded, cur_version, cur_dir);
2112 function load_packages (files, handle_deps, local_list, global_list)
2113 installed_pkgs_lst = installed_packages (local_list, global_list);
2114 num_packages = length (installed_pkgs_lst);
2116 ## Read package names and installdirs into a more convenient format.
2117 pnames = pdirs = cell (1, num_packages);
2118 for i = 1:num_packages
2119 pnames{i} = installed_pkgs_lst{i}.name;
2120 pdirs{i} = installed_pkgs_lst{i}.dir;
2124 if (length (files) == 1 && strcmp (files{1}, "all"))
2125 idx = [1:length(installed_pkgs_lst)];
2127 elseif (length (files) == 1 && strcmp (files{1}, "auto"))
2129 for i = 1:length (installed_pkgs_lst)
2130 if (exist (fullfile (pdirs{i}, "packinfo", ".autoload"), "file"))
2134 ## Load package_name1 ...
2137 for i = 1:length (files)
2138 idx2 = find (strcmp (pnames, files{i}));
2140 error ("package %s is not installed", files{i});
2142 idx (end + 1) = idx2;
2146 ## Load the packages, but take care of the ordering of dependencies.
2147 load_packages_and_dependencies (idx, handle_deps, installed_pkgs_lst, true);
2150 function unload_packages (files, handle_deps, local_list, global_list)
2151 installed_pkgs_lst = installed_packages (local_list, global_list);
2152 num_packages = length (installed_pkgs_lst);
2154 ## Read package names and installdirs into a more convenient format.
2155 pnames = pdirs = cell (1, num_packages);
2156 for i = 1:num_packages
2157 pnames{i} = installed_pkgs_lst{i}.name;
2158 pdirs{i} = installed_pkgs_lst{i}.dir;
2159 pdeps{i} = installed_pkgs_lst{i}.depends;
2162 ## Get the current octave path.
2163 p = split_by (path(), pathsep ());
2165 if (length (files) == 1 && strcmp (files{1}, "all"))
2168 desc = installed_pkgs_lst;
2170 ## Unload package_name1 ...
2173 for i = 1:length (files)
2174 idx = strcmp (pnames, files{i});
2176 error ("package %s is not installed", files{i});
2178 dirs{end+1} = pdirs{idx};
2179 desc{end+1} = installed_pkgs_lst{idx};
2183 ## Check for architecture dependent directories.
2185 for i = 1:length (dirs)
2186 tmpdir = getarchdir (desc{i});
2187 if (exist (tmpdir, "dir"))
2188 archdirs{end+1} = dirs{i};
2189 archdirs{end+1} = tmpdir;
2191 archdirs{end+1} = dirs{i};
2195 ## Unload the packages.
2196 for i = 1:length (archdirs)
2198 idx = strcmp (p, d);
2201 ## FIXME: We should also check if we need to remove items from
2207 function [status_out, msg_out] = rm_rf (dir)
2209 crr = confirm_recursive_rmdir (false, "local");
2210 [status, msg] = rmdir (dir, "s");
2216 status_out = status;
2223 function emp = dirempty (nm, ign)
2224 if (exist (nm, "dir"))
2228 ign = [{".", ".."}, ign];
2231 for i = 1:length (l)
2233 for j = 1:length (ign)
2234 if (strcmp (l(i).name, ign{j}))
2250 function arch = getarch ()
2251 persistent _arch = cstrcat (octave_config_info ("canonical_host_type"),
2252 "-", octave_config_info ("api_version"));
2256 function archprefix = getarchprefix (desc, global_install)
2257 if ((nargin == 2 && global_install) || (nargin < 2 && issuperuser ()))
2258 archprefix = fullfile (octave_config_info ("libdir"), "octave",
2259 "packages", cstrcat(desc.name, "-", desc.version));
2261 archprefix = desc.dir;
2265 function archdir = getarchdir (desc)
2266 archdir = fullfile (desc.archprefix, getarch());
2269 function s = issuperuser ()
2270 if ((ispc () && ! isunix ()) || (geteuid() == 0))
2277 function [status, output] = shell (cmd)
2280 cmd = strrep (cmd, "\\", "/");
2281 if (ispc () && ! isunix ())
2282 if (isempty(have_sh))
2283 if (system("sh.exe -c \"exit\""))
2290 [status, output] = system (cstrcat ("sh.exe -c \"", cmd, "\""));
2292 error ("Can not find the command shell");
2295 [status, output] = system (cmd);
2299 function newdesc = save_order (desc)
2301 for i = 1 : length(desc)
2302 deps = desc{i}.depends;
2304 || (length (deps) == 1 && strcmp(deps{1}.package, "octave")))
2305 newdesc {end + 1} = desc{i};
2308 for k = 1 : length (deps)
2309 for j = 1 : length (desc)
2310 if (strcmp (desc{j}.name, deps{k}.package))
2311 tmpdesc{end+1} = desc{j};
2316 if (! isempty (tmpdesc))
2317 newdesc = {newdesc{:}, save_order(tmpdesc){:}, desc{i}};
2319 newdesc{end+1} = desc{i};
2323 ## Eliminate the duplicates.
2325 for i = 1 : length (newdesc)
2326 for j = (i + 1) : length (newdesc)
2327 if (strcmp (newdesc{i}.name, newdesc{j}.name))
2335 function load_packages_and_dependencies (idx, handle_deps, installed_pkgs_lst,
2337 idx = load_package_dirs (idx, [], handle_deps, installed_pkgs_lst);
2339 execpath = EXEC_PATH ();
2341 ndir = installed_pkgs_lst{i}.dir;
2343 if (exist (fullfile (dirs{end}, "bin"), "dir"))
2344 execpath = cstrcat (execpath, pathsep (), fullfile (dirs{end}, "bin"));
2346 tmpdir = getarchdir (installed_pkgs_lst{i});
2347 if (exist (tmpdir, "dir"))
2348 dirs{end + 1} = tmpdir;
2349 if (exist (fullfile (dirs{end}, "bin"), "dir"))
2350 execpath = cstrcat (execpath, pathsep (), fullfile (dirs{end}, "bin"));
2355 ## Load the packages.
2356 if (length (dirs) > 0)
2360 ## Add the binaries to exec_path.
2361 if (! strcmp (EXEC_PATH, execpath))
2362 EXEC_PATH (execpath);
2366 function idx = load_package_dirs (lidx, idx, handle_deps, installed_pkgs_lst)
2368 if (isfield (installed_pkgs_lst{i}, "loaded")
2369 && installed_pkgs_lst{i}.loaded)
2373 deps = installed_pkgs_lst{i}.depends;
2374 if ((length (deps) > 1)
2375 || (length (deps) == 1 && ! strcmp(deps{1}.package, "octave")))
2377 for k = 1 : length (deps)
2378 for j = 1 : length (installed_pkgs_lst)
2379 if (strcmp (installed_pkgs_lst{j}.name, deps{k}.package))
2380 tmplidx (end + 1) = j;
2385 idx = load_package_dirs (tmplidx, idx, handle_deps,
2386 installed_pkgs_lst);
2389 if (isempty (find(idx == i)))
2396 function dep = is_architecture_dependent (nm)
2397 persistent archdepsuffix = {".oct",".mex",".a",".lib",".so",".so.*",".dll","dylib"};
2400 for i = 1 : length (archdepsuffix)
2401 ext = archdepsuffix{i};
2402 if (ext(end) == "*")
2408 pos = findstr (nm, ext);
2410 if (! isglob && (length(nm) - pos(end) != length(ext) - 1))
2419 function [url, local_file] = get_forge_download (name)
2420 [ver, url] = get_forge_pkg (name);
2421 local_file = [name, "-", ver, ".tar.gz"];
2424 function list = list_forge_packages ()
2425 [list, succ] = urlread ("http://octave.sourceforge.net/list_packages.php");
2427 list = strsplit (list, " \n\t", true);
2429 error ("pkg: could not read URL, please verify internet connection");
2432 page_screen_output (false, "local");
2433 puts ("OctaveForge provides these packages:\n");
2434 for i = 1:length (list)
2436 ver = get_forge_pkg (list{i});
2440 printf (" %s %s\n", list{i}, ver);