# HG changeset patch # User Carlo de Falco # Date 1331808001 -3600 # Node ID 0fab7b9e622672e2f78b95f7bc167db90cfb4456 # Parent bec37a92cb3bd070d7c0dceb9d9f39235287b114 refactoring of the package manager * pkg.m: move all sub-functions to private/ * pkg/private/absolute_pathname.m * pkg/private/build.m * pkg/private/configure_make.m * pkg/private/copy_files.m * pkg/private/create_pkgadddel.m * pkg/private/describe.m * pkg/private/dirempty.m * pkg/private/extract_pkg.m * pkg/private/finish_installation.m * pkg/private/fix_depends.m * pkg/private/fix_version.m * pkg/private/generate_lookfor_cache.m * pkg/private/get_description.m * pkg/private/get_forge_download.m * pkg/private/get_forge_pkg.m * pkg/private/getarch.m * pkg/private/getarchdir.m * pkg/private/getarchprefix.m * pkg/private/get_unsatisfied_deps.m * pkg/private/install.m * pkg/private/installed_packages.m * pkg/private/is_architecture_dependent.m * pkg/private/isautoload.m * pkg/private/issuperuser.m * pkg/private/list_forge_packages.m * pkg/private/load_package_dirs.m * pkg/private/load_packages.m * pkg/private/load_packages_and_dependencies.m * pkg/private/packinfo_copy_file.m * pkg/private/parse_pkg_idx.m * pkg/private/prepare_installation.m * pkg/private/print_package_description.m * pkg/private/rebuild.m * pkg/private/repackage.m * pkg/private/rm_rf.m * pkg/private/rstrip.m * pkg/private/save_order.m * pkg/private/shell.m * pkg/private/split_by.m * pkg/private/strip.m * pkg/private/uninstall.m * pkg/private/unload_packages.m * pkg/private/verify_directory.m * pkg/private/write_index.m diff -r bec37a92cb3b -r 0fab7b9e6226 scripts/pkg/module.mk --- a/scripts/pkg/module.mk Wed Mar 14 18:26:24 2012 -0400 +++ b/scripts/pkg/module.mk Thu Mar 15 11:40:01 2012 +0100 @@ -1,7 +1,51 @@ FCN_FILE_DIRS += pkg pkg_PRIVATE_FCN_FILES = \ - pkg/private/get_forge_pkg.m + pkg/private/absolute_pathname.m \ + pkg/private/build.m \ + pkg/private/configure_make.m \ + pkg/private/copy_files.m \ + pkg/private/create_pkgadddel.m \ + pkg/private/describe.m \ + pkg/private/dirempty.m \ + pkg/private/extract_pkg.m \ + pkg/private/finish_installation.m \ + pkg/private/fix_depends.m \ + pkg/private/fix_version.m \ + pkg/private/generate_lookfor_cache.m \ + pkg/private/get_description.m \ + pkg/private/get_forge_download.m \ + pkg/private/get_forge_pkg.m \ + pkg/private/getarch.m \ + pkg/private/getarchdir.m \ + pkg/private/getarchprefix.m \ + pkg/private/get_unsatisfied_deps.m \ + pkg/private/install.m \ + pkg/private/installed_packages.m \ + pkg/private/is_architecture_dependent.m \ + pkg/private/isautoload.m \ + pkg/private/issuperuser.m \ + pkg/private/list_forge_packages.m \ + pkg/private/load_package_dirs.m \ + pkg/private/load_packages.m \ + pkg/private/load_packages_and_dependencies.m \ + pkg/private/packinfo_copy_file.m \ + pkg/private/parse_pkg_idx.m \ + pkg/private/prepare_installation.m \ + pkg/private/print_package_description.m \ + pkg/private/rebuild.m \ + pkg/private/repackage.m \ + pkg/private/rm_rf.m \ + pkg/private/rstrip.m \ + pkg/private/save_order.m \ + pkg/private/shell.m \ + pkg/private/split_by.m \ + pkg/private/strip.m \ + pkg/private/uninstall.m \ + pkg/private/unload_packages.m \ + pkg/private/verify_directory.m \ + pkg/private/write_index.m + pkg_FCN_FILES = \ pkg/pkg.m \ diff -r bec37a92cb3b -r 0fab7b9e6226 scripts/pkg/pkg.m --- a/scripts/pkg/pkg.m Wed Mar 14 18:26:24 2012 -0400 +++ b/scripts/pkg/pkg.m Thu Mar 15 11:40:01 2012 +0100 @@ -1,5 +1,6 @@ ## Copyright (C) 2005-2012 S�ren Hauberg ## Copyright (C) 2010 VZLU Prague, a.s. +## Copyright (C) 2012 Carlo de Falco ## ## This file is part of Octave. ## @@ -533,1905 +534,3 @@ error ("you must specify a valid action for 'pkg'. See 'help pkg' for details"); endswitch endfunction - -function descriptions = rebuild (prefix, archprefix, list, files, auto, verbose) - if (isempty (files)) - [dirlist, err, msg] = readdir (prefix); - if (err) - error ("couldn't read directory %s: %s", prefix, msg); - endif - ## the two first entries of dirlist are "." and ".." - dirlist([1,2]) = []; - else - old_descriptions = installed_packages (list, list); - wd = pwd (); - unwind_protect - cd (prefix); - dirlist = glob (cellfun(@(x) cstrcat(x, '-*'), files, 'uniformoutput', 0)); - unwind_protect_cleanup - cd (wd); - end_unwind_protect - endif - descriptions = {}; - for k = 1:length (dirlist) - descfile = fullfile (prefix, dirlist{k}, "packinfo", "DESCRIPTION"); - if (verbose) - printf ("recreating package description from %s\n", dirlist{k}); - endif - if (exist (descfile, "file")) - desc = get_description (descfile); - desc.dir = fullfile (prefix, dirlist{k}); - desc.archprefix = fullfile (archprefix, cstrcat (desc.name, "-", - desc.version)); - if (auto != 0) - if (exist (fullfile (desc.dir, "packinfo", ".autoload"), "file")) - unlink (fullfile (desc.dir, "packinfo", ".autoload")); - endif - if (auto < 0) - desc.autoload = 0; - elseif (auto > 0) - desc.autoload = 1; - fclose (fopen (fullfile (desc.dir, "packinfo", ".autoload"), "wt")); - endif - else - if (exist (fullfile (desc.dir, "packinfo", ".autoload"), "file")) - desc.autoload = 1; - else - desc.autoload = 0; - endif - endif - descriptions{end + 1} = desc; - elseif (verbose) - warning ("directory %s is not a valid package", dirlist{k}); - endif - endfor - - if (! isempty (files)) - ## We are rebuilding for a particular package(s) so we should take - ## care to keep the other untouched packages in the descriptions - descriptions = {descriptions{:}, old_descriptions{:}}; - - dup = []; - for i = 1:length (descriptions) - if (find (dup, i)) - continue; - endif - for j = (i+1):length (descriptions) - if (find (dup, j)) - continue; - endif - if (strcmp (descriptions{i}.name, descriptions{j}.name)) - dup = [dup, j]; - endif - endfor - endfor - if (! isempty (dup)) - descriptions (dup) = []; - endif - endif -endfunction - -function build (files, handle_deps, autoload, verbose) - if (length (files) < 1) - error ("insufficient number of files"); - endif - builddir = files{1}; - if (! exist (builddir, "dir")) - warning ("creating build directory %s", builddir); - [status, msg] = mkdir (builddir); - if (status != 1) - error ("could not create installation directory: %s", msg); - endif - endif - builddir = absolute_pathname (builddir); - installdir = fullfile (builddir, "install"); - if (! exist (installdir, "dir")) - [status, msg] = mkdir (installdir); - if (status != 1) - error ("could not create installation directory: %s", msg); - endif - endif - files(1) = []; - buildlist = fullfile (builddir, "octave_packages"); - install (files, handle_deps, autoload, installdir, installdir, verbose, - buildlist, "", false); - unwind_protect - repackage (builddir, buildlist); - unwind_protect_cleanup - unload_packages ({"all"}, handle_deps, buildlist, ""); - if (exist (installdir, "dir")) - rm_rf (installdir); - endif - if (exist (buildlist, "file")) - unlink (buildlist); - endif - end_unwind_protect -endfunction - -function install (files, handle_deps, autoload, prefix, archprefix, verbose, - local_list, global_list, global_install) - - ## Check that the directory in prefix exist. If it doesn't: create it! - if (! exist (prefix, "dir")) - warning ("creating installation directory %s", prefix); - [status, msg] = mkdir (prefix); - if (status != 1) - error ("could not create installation directory: %s", msg); - endif - endif - - ## Get the list of installed packages. - [local_packages, global_packages] = installed_packages (local_list, - global_list); - - installed_pkgs_lst = {local_packages{:}, global_packages{:}}; - - if (global_install) - packages = global_packages; - else - packages = local_packages; - endif - - ## Uncompress the packages and read the DESCRIPTION files. - tmpdirs = packdirs = descriptions = {}; - try - ## Warn about non existent files. - for i = 1:length (files) - if (isempty (glob(files{i}))) - warning ("file %s does not exist", files{i}); - endif - endfor - - ## Unpack the package files and read the DESCRIPTION files. - files = glob (files); - packages_to_uninstall = []; - for i = 1:length (files) - tgz = files{i}; - - if (exist (tgz, "file")) - ## Create a temporary directory. - tmpdir = tmpnam (); - tmpdirs{end+1} = tmpdir; - if (verbose) - printf ("mkdir (%s)\n", tmpdir); - endif - [status, msg] = mkdir (tmpdir); - if (status != 1) - error ("couldn't create temporary directory: %s", msg); - endif - - ## Uncompress the package. - if (verbose) - printf ("untar (%s, %s)\n", tgz, tmpdir); - endif - untar (tgz, tmpdir); - - ## Get the name of the directories produced by tar. - [dirlist, err, msg] = readdir (tmpdir); - if (err) - error ("couldn't read directory produced by tar: %s", msg); - endif - - if (length (dirlist) > 3) - error ("bundles of packages are not allowed"); - endif - endif - - ## The filename pointed to an uncompressed package to begin with. - if (exist (tgz, "dir")) - dirlist = {".", "..", tgz}; - endif - - if (exist (tgz, "file") || exist (tgz, "dir")) - ## The two first entries of dirlist are "." and "..". - if (exist (tgz, "file")) - packdir = fullfile (tmpdir, dirlist{3}); - else - packdir = fullfile (pwd(), dirlist{3}); - endif - packdirs{end+1} = packdir; - - ## Make sure the package contains necessary files. - verify_directory (packdir); - - ## Read the DESCRIPTION file. - filename = fullfile (packdir, "DESCRIPTION"); - desc = get_description (filename); - - ## Verify that package name corresponds with filename. - [dummy, nm] = fileparts (tgz); - if ((length (nm) >= length (desc.name)) - && ! strcmp (desc.name, nm(1:length(desc.name)))) - error ("package name '%s' doesn't correspond to its filename '%s'", - desc.name, nm); - endif - - ## Set default installation directory. - desc.dir = fullfile (prefix, cstrcat (desc.name, "-", desc.version)); - - ## Set default architectire dependent installation directory. - desc.archprefix = fullfile (archprefix, cstrcat (desc.name, "-", - desc.version)); - - ## Save desc. - descriptions{end+1} = desc; - - ## Are any of the new packages already installed? - ## If so we'll remove the old version. - for j = 1:length (packages) - if (strcmp (packages{j}.name, desc.name)) - packages_to_uninstall(end+1) = j; - endif - endfor - endif - endfor - catch - ## Something went wrong, delete tmpdirs. - for i = 1:length (tmpdirs) - rm_rf (tmpdirs{i}); - endfor - rethrow (lasterror ()); - end_try_catch - - ## Check dependencies. - if (handle_deps) - ok = true; - error_text = ""; - for i = 1:length (descriptions) - desc = descriptions{i}; - idx2 = setdiff (1:length(descriptions), i); - if (global_install) - ## Global installation is not allowed to have dependencies on locally - ## installed packages. - idx1 = setdiff (1:length(global_packages), packages_to_uninstall); - pseudo_installed_packages = {global_packages{idx1}, ... - descriptions{idx2}}; - else - idx1 = setdiff (1:length(local_packages), packages_to_uninstall); - pseudo_installed_packages = {local_packages{idx1}, ... - global_packages{:}, ... - descriptions{idx2}}; - endif - bad_deps = get_unsatisfied_deps (desc, pseudo_installed_packages); - ## Are there any unsatisfied dependencies? - if (! isempty (bad_deps)) - ok = false; - for i = 1:length (bad_deps) - dep = bad_deps{i}; - error_text = cstrcat (error_text, " ", desc.name, " needs ", - dep.package, " ", dep.operator, " ", - dep.version, "\n"); - endfor - endif - endfor - - ## Did we find any unsatisfied dependencies? - if (! ok) - error ("the following dependencies where unsatisfied:\n %s", error_text); - endif - endif - - ## Prepare each package for installation. - try - for i = 1:length (descriptions) - desc = descriptions{i}; - pdir = packdirs{i}; - prepare_installation (desc, pdir); - configure_make (desc, pdir, verbose); - endfor - catch - ## Something went wrong, delete tmpdirs. - for i = 1:length (tmpdirs) - rm_rf (tmpdirs{i}); - endfor - rethrow (lasterror ()); - end_try_catch - - ## Uninstall the packages that will be replaced. - try - for i = packages_to_uninstall - if (global_install) - uninstall ({global_packages{i}.name}, false, verbose, local_list, - global_list, global_install); - else - uninstall ({local_packages{i}.name}, false, verbose, local_list, - global_list, global_install); - endif - endfor - catch - ## Something went wrong, delete tmpdirs. - for i = 1:length (tmpdirs) - rm_rf (tmpdirs{i}); - endfor - rethrow (lasterror ()); - end_try_catch - - ## Install each package. - try - for i = 1:length (descriptions) - desc = descriptions{i}; - pdir = packdirs{i}; - copy_files (desc, pdir, global_install); - create_pkgadddel (desc, pdir, "PKG_ADD", global_install); - create_pkgadddel (desc, pdir, "PKG_DEL", global_install); - finish_installation (desc, pdir, global_install); - generate_lookfor_cache (desc); - endfor - catch - ## Something went wrong, delete tmpdirs. - for i = 1:length (tmpdirs) - rm_rf (tmpdirs{i}); - endfor - for i = 1:length (descriptions) - rm_rf (descriptions{i}.dir); - rm_rf (getarchdir (descriptions{i})); - endfor - rethrow (lasterror ()); - end_try_catch - - ## Check if the installed directory is empty. If it is remove it - ## from the list. - for i = length (descriptions):-1:1 - if (dirempty (descriptions{i}.dir, {"packinfo", "doc"}) - && dirempty (getarchdir (descriptions{i}))) - warning ("package %s is empty\n", descriptions{i}.name); - rm_rf (descriptions{i}.dir); - rm_rf (getarchdir (descriptions{i})); - descriptions(i) = []; - endif - endfor - - ## If the package requested that it is autoloaded, or the installer - ## requested that it is, then mark the package as autoloaded. - for i = length (descriptions):-1:1 - if (autoload > 0 || (autoload == 0 && isautoload (descriptions(i)))) - fclose (fopen (fullfile (descriptions{i}.dir, "packinfo", - ".autoload"), "wt")); - descriptions{i}.autoload = 1; - endif - endfor - - ## Add the packages to the package list. - try - if (global_install) - idx = setdiff (1:length(global_packages), packages_to_uninstall); - global_packages = save_order ({global_packages{idx}, descriptions{:}}); - save (global_list, "global_packages"); - installed_pkgs_lst = {local_packages{:}, global_packages{:}}; - else - idx = setdiff (1:length(local_packages), packages_to_uninstall); - local_packages = save_order ({local_packages{idx}, descriptions{:}}); - save (local_list, "local_packages"); - installed_pkgs_lst = {local_packages{:}, global_packages{:}}; - endif - catch - ## Something went wrong, delete tmpdirs. - for i = 1:length (tmpdirs) - rm_rf (tmpdirs{i}); - endfor - for i = 1:length (descriptions) - rm_rf (descriptions{i}.dir); - endfor - if (global_install) - printf ("error: couldn't append to %s\n", global_list); - else - printf ("error: couldn't append to %s\n", local_list); - endif - rethrow (lasterror ()); - end_try_catch - - ## All is well, let's clean up. - for i = 1:length (tmpdirs) - [status, msg] = rm_rf (tmpdirs{i}); - if (status != 1) - warning ("couldn't clean up after my self: %s\n", msg); - endif - endfor - - ## Add the newly installed packages to the path, so the user - ## can begin using them. Only load them if they are marked autoload. - if (length (descriptions) > 0) - idx = []; - for i = 1:length (descriptions) - if (isautoload (descriptions(i))) - nm = descriptions{i}.name; - for j = 1:length (installed_pkgs_lst) - if (strcmp (nm, installed_pkgs_lst{j}.name)) - idx (end + 1) = j; - break; - endif - endfor - endif - endfor - load_packages_and_dependencies (idx, handle_deps, installed_pkgs_lst, - global_install); - endif - - ## If there's a NEWS file, mention it - ## we are checking if desc exists too because it's possible to ge to this point - ## without creating it such as giving an invalid filename for the package - if (exist ("desc", "var") && exist (fullfile (desc.dir, "packinfo", "NEWS"), "file")) - printf ("For information about changes from previous versions of the %s package, run 'news (\"%s\")'.\n", - desc.name, desc.name); - endif - -endfunction - -function uninstall (pkgnames, handle_deps, verbose, local_list, - global_list, global_install) - ## Get the list of installed packages. - [local_packages, global_packages] = installed_packages(local_list, - global_list); - if (global_install) - installed_pkgs_lst = {local_packages{:}, global_packages{:}}; - else - installed_pkgs_lst = local_packages; - endif - - num_packages = length (installed_pkgs_lst); - delete_idx = []; - for i = 1:num_packages - cur_name = installed_pkgs_lst{i}.name; - if (any (strcmp (cur_name, pkgnames))) - delete_idx(end+1) = i; - endif - endfor - - ## Are all the packages that should be uninstalled already installed? - if (length (delete_idx) != length (pkgnames)) - if (global_install) - ## Try again for a locally installed package. - installed_pkgs_lst = local_packages; - - num_packages = length (installed_pkgs_lst); - delete_idx = []; - for i = 1:num_packages - cur_name = installed_pkgs_lst{i}.name; - if (any (strcmp (cur_name, pkgnames))) - delete_idx(end+1) = i; - endif - endfor - if (length (delete_idx) != length (pkgnames)) - ## FIXME: We should have a better error message. - warning ("some of the packages you want to uninstall are not installed"); - endif - else - ## FIXME: We should have a better error message. - warning ("some of the packages you want to uninstall are not installed"); - endif - endif - - ## Compute the packages that will remain installed. - idx = setdiff (1:num_packages, delete_idx); - remaining_packages = {installed_pkgs_lst{idx}}; - - ## Check dependencies. - if (handle_deps) - error_text = ""; - for i = 1:length (remaining_packages) - desc = remaining_packages{i}; - bad_deps = get_unsatisfied_deps (desc, remaining_packages); - - ## Will the uninstallation break any dependencies? - if (! isempty (bad_deps)) - for i = 1:length (bad_deps) - dep = bad_deps{i}; - error_text = cstrcat (error_text, " ", desc.name, " needs ", - dep.package, " ", dep.operator, " ", - dep.version, "\n"); - endfor - endif - endfor - - if (! isempty (error_text)) - error ("the following dependencies where unsatisfied:\n %s", error_text); - endif - endif - - ## Delete the directories containing the packages. - for i = delete_idx - desc = installed_pkgs_lst{i}; - ## If an 'on_uninstall.m' exist, call it! - if (exist (fullfile (desc.dir, "packinfo", "on_uninstall.m"), "file")) - wd = pwd (); - cd (fullfile (desc.dir, "packinfo")); - on_uninstall (desc); - cd (wd); - endif - ## Do the actual deletion. - if (desc.loaded) - rmpath (desc.dir); - if (exist (getarchdir (desc))) - rmpath (getarchdir (desc)); - endif - endif - if (exist (desc.dir, "dir")) - [status, msg] = rm_rf (desc.dir); - if (status != 1) - error ("couldn't delete directory %s: %s", desc.dir, msg); - endif - [status, msg] = rm_rf (getarchdir (desc)); - if (status != 1) - error ("couldn't delete directory %s: %s", getarchdir (desc), msg); - endif - if (dirempty (desc.archprefix)) - rm_rf (desc.archprefix); - endif - else - warning ("directory %s previously lost", desc.dir); - endif - endfor - - ## Write a new ~/.octave_packages. - if (global_install) - if (length (remaining_packages) == 0) - unlink (global_list); - else - global_packages = save_order (remaining_packages); - save (global_list, "global_packages"); - endif - else - if (length (remaining_packages) == 0) - unlink (local_list); - else - local_packages = save_order (remaining_packages); - save (local_list, "local_packages"); - endif - endif - -endfunction - -function [pkg_desc_list, flag] = describe (pkgnames, verbose, - local_list, global_list) - - ## Get the list of installed packages. - installed_pkgs_lst = installed_packages(local_list, global_list); - num_packages = length (installed_pkgs_lst); - - - describe_all = false; - if (any (strcmp ("all", pkgnames))) - describe_all = true; - flag(1:num_packages) = {"Not Loaded"}; - num_pkgnames = num_packages; - else - num_pkgnames = length (pkgnames); - flag(1:num_pkgnames) = {"Not installed"}; - endif - - for i = 1:num_packages - curr_name = installed_pkgs_lst{i}.name; - if (describe_all) - name_pos = i; - else - name_pos = find(strcmp (curr_name, pkgnames)); - endif - - if (! isempty (name_pos)) - if (installed_pkgs_lst{i}.loaded) - flag{name_pos} = "Loaded"; - else - flag{name_pos} = "Not loaded"; - endif - - pkg_desc_list{name_pos}.name = installed_pkgs_lst{i}.name; - pkg_desc_list{name_pos}.version = installed_pkgs_lst{i}.version; - pkg_desc_list{name_pos}.description = installed_pkgs_lst{i}.description; - pkg_desc_list{name_pos}.provides = parse_pkg_idx (installed_pkgs_lst{i}.dir); - - endif - endfor - - non_inst = find (strcmp (flag, "Not installed")); - if (! isempty (non_inst)) - if (nargout < 2) - non_inst_str = sprintf (" %s ", pkgnames{non_inst}); - error ("some packages are not installed: %s", non_inst_str); - else - pkg_desc_list{non_inst} = struct ("name", {}, "description", - {}, "provides", {}); - endif - endif - - if (nargout == 0) - for i = 1:num_pkgnames - print_package_description (pkg_desc_list{i}.name, - pkg_desc_list{i}.version, - pkg_desc_list{i}.provides, - pkg_desc_list{i}.description, - flag{i}, verbose); - endfor - endif - -endfunction - -## AUXILIARY FUNCTIONS - -## Read an INDEX file. -function [pkg_idx_struct] = parse_pkg_idx (packdir) - - index_file = fullfile (packdir, "packinfo", "INDEX"); - - if (! exist (index_file, "file")) - error ("could not find any INDEX file in directory %s, try 'pkg rebuild all' to generate missing INDEX files", packdir); - endif - - - [fid, msg] = fopen (index_file, "r"); - if (fid == -1) - error ("the INDEX file %s could not be read: %s", - index_file, msg); - endif - - cat_num = 1; - pkg_idx_struct{1}.category = "Uncategorized"; - pkg_idx_struct{1}.functions = {}; - - line = fgetl (fid); - while (isempty (strfind (line, ">>")) && ! feof (fid)) - line = fgetl (fid); - endwhile - - while (! feof (fid) || line != -1) - if (! any (! isspace (line)) || line(1) == "#" || any (line == "=")) - ## Comments, blank lines or comments about unimplemented - ## functions: do nothing - ## FIXME: probably comments and pointers to external functions - ## could be treated better when printing to screen? - elseif (! isempty (strfind (line, ">>"))) - ## Skip package name and description as they are in DESCRIPTION - ## already. - elseif (! isspace (line(1))) - ## Category. - if (! isempty (pkg_idx_struct{cat_num}.functions)) - pkg_idx_struct{++cat_num}.functions = {}; - endif - pkg_idx_struct{cat_num}.category = deblank (line); - else - ## Function names. - while (any (! isspace (line))) - [fun_name, line] = strtok (line); - pkg_idx_struct{cat_num}.functions{end+1} = deblank (fun_name); - endwhile - endif - line = fgetl (fid); - endwhile - fclose (fid); -endfunction - -function print_package_description (pkg_name, pkg_ver, pkg_idx_struct, - pkg_desc, status, verbose) - - printf ("---\nPackage name:\n\t%s\n", pkg_name); - printf ("Version:\n\t%s\n", pkg_ver); - printf ("Short description:\n\t%s\n", pkg_desc); - printf ("Status:\n\t%s\n", status); - if (verbose) - printf ("---\nProvides:\n"); - for i = 1:length(pkg_idx_struct) - if (! isempty (pkg_idx_struct{i}.functions)) - printf ("%s\n", pkg_idx_struct{i}.category); - for j = 1:length(pkg_idx_struct{i}.functions) - printf ("\t%s\n", pkg_idx_struct{i}.functions{j}); - endfor - endif - endfor - endif - -endfunction - - -function pth = absolute_pathname (pth) - [status, msg, msgid] = fileattrib (pth); - if (status != 1) - error ("could not find the file or path %s", pth); - else - pth = msg.Name; - endif -endfunction - -function repackage (builddir, buildlist) - packages = installed_packages (buildlist, buildlist); - - wd = pwd(); - for i = 1 : length(packages) - pack = packages{i}; - unwind_protect - cd (builddir); - mkdir (pack.name); - mkdir (fullfile (pack.name, "inst")); - copyfile (fullfile (pack.dir, "*"), fullfile (pack.name, "inst")); - movefile (fullfile (pack.name, "inst","packinfo", "*"), pack.name); - if (exist (fullfile (pack.name, "inst","packinfo", ".autoload"), "file")) - unlink (fullfile (pack.name, "inst","packinfo", ".autoload")); - endif - rmdir (fullfile (pack.name, "inst", "packinfo")); - if (exist (fullfile (pack.name, "inst", "doc"), "dir")) - movefile (fullfile (pack.name, "inst", "doc"), pack.name); - endif - if (exist (fullfile (pack.name, "inst", "bin"), "dir")) - movefile (fullfile (pack.name, "inst", "bin"), pack.name); - endif - archdir = fullfile (pack.archprefix, cstrcat (pack.name, "-", - pack.version), getarch ()); - if (exist (archdir, "dir")) - if (exist (fullfile (pack.name, "inst", "PKG_ADD"), "file")) - unlink (fullfile (pack.name, "inst", "PKG_ADD")); - endif - if (exist (fullfile (pack.name, "inst", "PKG_DEL"), "file")) - unlink (fullfile (pack.name, "inst", "PKG_DEL")); - endif - if (exist (fullfile (archdir, "PKG_ADD"), "file")) - movefile (fullfile (archdir, "PKG_ADD"), - fullfile (pack.name, "PKG_ADD")); - endif - if (exist (fullfile (archdir, "PKG_DEL"), "file")) - movefile (fullfile (archdir, "PKG_DEL"), - fullfile (pack.name, "PKG_DEL")); - endif - else - if (exist (fullfile (pack.name, "inst", "PKG_ADD"), "file")) - movefile (fullfile (pack.name, "inst", "PKG_ADD"), - fullfile (pack.name, "PKG_ADD")); - endif - if (exist (fullfile (pack.name, "inst", "PKG_DEL"), "file")) - movefile (fullfile (pack.name, "inst", "PKG_DEL"), - fullfile (pack.name, "PKG_DEL")); - endif - endif - tfile = cstrcat (pack.name, "-", pack.version, ".tar"); - tar (tfile, pack.name); - try - gzip (tfile); - unlink (tfile); - catch - warning ("failed to compress %s", tfile); - end_try_catch - unwind_protect_cleanup - if (exist (pack.name, "dir")) - rm_rf (pack.name); - endif - cd (wd); - end_unwind_protect - endfor -endfunction - -function auto = isautoload (desc) - auto = false; - if (isfield (desc{1}, "autoload")) - a = desc{1}.autoload; - if ((isnumeric (a) && a > 0) - || (ischar (a) && (strcmpi (a, "true") - || strcmpi (a, "on") - || strcmpi (a, "yes") - || strcmpi (a, "1")))) - auto = true; - endif - endif -endfunction - -function prepare_installation (desc, packdir) - ## Is there a pre_install to call? - if (exist (fullfile (packdir, "pre_install.m"), "file")) - wd = pwd (); - try - cd (packdir); - pre_install (desc); - cd (wd); - catch - cd (wd); - rethrow (lasterror ()); - end_try_catch - endif - - ## If the directory "inst" doesn't exist, we create it. - inst_dir = fullfile (packdir, "inst"); - if (! exist (inst_dir, "dir")) - [status, msg] = mkdir (inst_dir); - if (status != 1) - rm_rf (desc.dir); - error ("the 'inst' directory did not exist and could not be created: %s", - msg); - endif - endif -endfunction - -function configure_make (desc, packdir, verbose) - ## Perform ./configure, make, make install in "src". - if (exist (fullfile (packdir, "src"), "dir")) - src = fullfile (packdir, "src"); - octave_bindir = octave_config_info ("bindir"); - ver = version (); - mkoctfile = fullfile (octave_bindir, sprintf ("mkoctfile-%s", ver)); - octave_config = fullfile (octave_bindir, sprintf ("octave-config-%s", ver)); - octave_binary = fullfile (octave_bindir, sprintf ("octave-%s", ver)); - cenv = {"MKOCTFILE"; mkoctfile; - "OCTAVE_CONFIG"; octave_config; - "OCTAVE"; octave_binary; - "INSTALLDIR"; desc.dir}; - scenv = sprintf ("%s=\"%s\" ", cenv{:}); - ## Configure. - if (exist (fullfile (src, "configure"), "file")) - flags = ""; - if (isempty (getenv ("CC"))) - flags = cstrcat (flags, " CC=\"", octave_config_info ("CC"), "\""); - endif - if (isempty (getenv ("CXX"))) - flags = cstrcat (flags, " CXX=\"", octave_config_info ("CXX"), "\""); - endif - if (isempty (getenv ("AR"))) - flags = cstrcat (flags, " AR=\"", octave_config_info ("AR"), "\""); - endif - if (isempty (getenv ("RANLIB"))) - flags = cstrcat (flags, " RANLIB=\"", octave_config_info ("RANLIB"), "\""); - endif - [status, output] = shell (cstrcat ("cd '", src, "'; ", scenv, - "./configure --prefix=\"", - desc.dir, "\"", flags)); - if (status != 0) - rm_rf (desc.dir); - error ("the configure script returned the following error: %s", output); - elseif (verbose) - printf("%s", output); - endif - - endif - - ## Make. - if (exist (fullfile (src, "Makefile"), "file")) - [status, output] = shell (cstrcat (scenv, "make -C '", src, "'")); - if (status != 0) - rm_rf (desc.dir); - error ("'make' returned the following error: %s", output); - elseif (verbose) - printf("%s", output); - endif - endif - - ## Copy files to "inst" and "inst/arch" (this is instead of 'make - ## install'). - files = fullfile (src, "FILES"); - instdir = fullfile (packdir, "inst"); - archdir = fullfile (packdir, "inst", getarch ()); - - ## Get file names. - if (exist (files, "file")) - [fid, msg] = fopen (files, "r"); - if (fid < 0) - error ("couldn't open %s: %s", files, msg); - endif - filenames = char (fread (fid))'; - fclose (fid); - if (filenames(end) == "\n") - filenames(end) = []; - endif - filenames = split_by (filenames, "\n"); - delete_idx = []; - for i = 1:length (filenames) - if (! all (isspace (filenames{i}))) - filenames{i} = fullfile (src, filenames{i}); - else - delete_idx(end+1) = i; - endif - endfor - filenames(delete_idx) = []; - else - m = dir (fullfile (src, "*.m")); - oct = dir (fullfile (src, "*.oct")); - mex = dir (fullfile (src, "*.mex")); - - filenames = cellfun (@(x) fullfile (src, x), - {m.name, oct.name, mex.name}, - "uniformoutput", false); - endif - - ## Split into architecture dependent and independent files. - if (isempty (filenames)) - idx = []; - else - idx = cellfun ("is_architecture_dependent", filenames); - endif - archdependent = filenames (idx); - archindependent = filenames (!idx); - - ## Copy the files. - if (! all (isspace ([filenames{:}]))) - if (! exist (instdir, "dir")) - mkdir (instdir); - endif - if (! all (isspace ([archindependent{:}]))) - if (verbose) - printf ("copyfile"); - printf (" %s", archindependent{:}); - printf ("%s\n", instdir); - endif - [status, output] = copyfile (archindependent, instdir); - if (status != 1) - rm_rf (desc.dir); - error ("Couldn't copy files from 'src' to 'inst': %s", output); - endif - endif - if (! all (isspace ([archdependent{:}]))) - if (verbose) - printf ("copyfile"); - printf (" %s", archdependent{:}); - printf (" %s\n", archdir); - endif - if (! exist (archdir, "dir")) - mkdir (archdir); - endif - [status, output] = copyfile (archdependent, archdir); - if (status != 1) - rm_rf (desc.dir); - error ("Couldn't copy files from 'src' to 'inst': %s", output); - endif - endif - endif - endif -endfunction - -function pkg = extract_pkg (nm, pat) - fid = fopen (nm, "rt"); - pkg = ""; - if (fid >= 0) - while (! feof (fid)) - ln = fgetl (fid); - if (ln > 0) - t = regexp (ln, pat, "tokens"); - if (! isempty (t)) - pkg = cstrcat (pkg, "\n", t{1}{1}); - endif - endif - endwhile - if (! isempty (pkg)) - pkg = cstrcat (pkg, "\n"); - endif - fclose (fid); - endif -endfunction - -function create_pkgadddel (desc, packdir, nm, global_install) - instpkg = fullfile (desc.dir, nm); - instfid = fopen (instpkg, "wt"); - ## If it is exists, most of the PKG_* file should go into the - ## architecture dependent directory so that the autoload/mfilename - ## commands work as expected. The only part that doesn't is the - ## part in the main directory. - archdir = fullfile (getarchprefix (desc), cstrcat (desc.name, "-", - desc.version), getarch ()); - if (exist (getarchdir (desc, global_install), "dir")) - archpkg = fullfile (getarchdir (desc, global_install), nm); - archfid = fopen (archpkg, "at"); - else - archpkg = instpkg; - archfid = instfid; - endif - - if (archfid >= 0 && instfid >= 0) - ## Search all dot-m files for PKG commands. - lst = dir (fullfile (packdir, "inst", "*.m")); - for i = 1:length (lst) - nam = fullfile (packdir, "inst", lst(i).name); - fwrite (instfid, extract_pkg (nam, ['^[#%][#%]* *' nm ': *(.*)$'])); - endfor - - ## Search all C++ source files for PKG commands. - lst = dir (fullfile (packdir, "src", "*.cc")); - for i = 1:length (lst) - nam = fullfile (packdir, "src", lst(i).name); - fwrite (archfid, extract_pkg (nam, ['^//* *' nm ': *(.*)$'])); - fwrite (archfid, extract_pkg (nam, ['^/\** *' nm ': *(.*) *\*/$'])); - endfor - - ## Add developer included PKG commands. - packdirnm = fullfile (packdir, nm); - if (exist (packdirnm, "file")) - fid = fopen (packdirnm, "rt"); - if (fid >= 0) - while (! feof (fid)) - ln = fgets (fid); - if (ln > 0) - fwrite (archfid, ln); - endif - endwhile - fclose (fid); - endif - endif - - ## If the files is empty remove it. - fclose (instfid); - t = dir (instpkg); - if (t.bytes <= 0) - unlink (instpkg); - endif - - if (instfid != archfid) - fclose (archfid); - t = dir (archpkg); - if (t.bytes <= 0) - unlink (archpkg); - endif - endif - endif -endfunction - -function copy_files (desc, packdir, global_install) - ## Create the installation directory. - if (! exist (desc.dir, "dir")) - [status, output] = mkdir (desc.dir); - if (status != 1) - error ("couldn't create installation directory %s : %s", - desc.dir, output); - endif - endif - - octfiledir = getarchdir (desc); - - ## Copy the files from "inst" to installdir. - instdir = fullfile (packdir, "inst"); - if (! dirempty (instdir)) - [status, output] = copyfile (fullfile (instdir, "*"), desc.dir); - if (status != 1) - rm_rf (desc.dir); - error ("couldn't copy files to the installation directory"); - endif - if (exist (fullfile (desc.dir, getarch ()), "dir") - && ! strcmp (fullfile (desc.dir, getarch ()), octfiledir)) - if (! exist (octfiledir, "dir")) - ## Can be required to create upto three levels of dirs. - octm1 = fileparts (octfiledir); - if (! exist (octm1, "dir")) - octm2 = fileparts (octm1); - if (! exist (octm2, "dir")) - octm3 = fileparts (octm2); - if (! exist (octm3, "dir")) - [status, output] = mkdir (octm3); - if (status != 1) - rm_rf (desc.dir); - error ("couldn't create installation directory %s : %s", - octm3, output); - endif - endif - [status, output] = mkdir (octm2); - if (status != 1) - rm_rf (desc.dir); - error ("couldn't create installation directory %s : %s", - octm2, output); - endif - endif - [status, output] = mkdir (octm1); - if (status != 1) - rm_rf (desc.dir); - error ("couldn't create installation directory %s : %s", - octm1, output); - endif - endif - [status, output] = mkdir (octfiledir); - if (status != 1) - rm_rf (desc.dir); - error ("couldn't create installation directory %s : %s", - octfiledir, output); - endif - endif - [status, output] = movefile (fullfile (desc.dir, getarch (), "*"), - octfiledir); - rm_rf (fullfile (desc.dir, getarch ())); - - if (status != 1) - rm_rf (desc.dir); - rm_rf (octfiledir); - error ("couldn't copy files to the installation directory"); - endif - endif - - endif - - ## Create the "packinfo" directory. - packinfo = fullfile (desc.dir, "packinfo"); - [status, msg] = mkdir (packinfo); - if (status != 1) - rm_rf (desc.dir); - rm_rf (octfiledir); - error ("couldn't create packinfo directory: %s", msg); - endif - - packinfo_copy_file ("DESCRIPTION", "required", packdir, packinfo, desc, octfiledir); - packinfo_copy_file ("COPYING", "required", packdir, packinfo, desc, octfiledir); - - packinfo_copy_file ("NEWS", "optional", packdir, packinfo, desc, octfiledir); - packinfo_copy_file ("ONEWS", "optional", packdir, packinfo, desc, octfiledir); - packinfo_copy_file ("ChangeLog", "optional", packdir, packinfo, desc, octfiledir); - - ## Is there an INDEX file to copy or should we generate one? - index_file = fullfile (packdir, "INDEX"); - if (exist(index_file, "file")) - packinfo_copy_file ("INDEX", "required", packdir, packinfo, desc, octfiledir); - else - try - write_index (desc, fullfile (packdir, "inst"), - fullfile (packinfo, "INDEX"), global_install); - catch - rm_rf (desc.dir); - rm_rf (octfiledir); - rethrow (lasterror ()); - end_try_catch - endif - - ## Is there an 'on_uninstall.m' to install? - packinfo_copy_file ("on_uninstall.m", "optional", packdir, packinfo, desc, octfiledir); - - ## Is there a doc/ directory that needs to be installed? - docdir = fullfile (packdir, "doc"); - if (exist (docdir, "dir") && ! dirempty (docdir)) - [status, output] = copyfile (docdir, desc.dir); - endif - - ## Is there a bin/ directory that needs to be installed? - ## FIXME: Need to treat architecture dependent files in bin/ - bindir = fullfile (packdir, "bin"); - if (exist (bindir, "dir") && ! dirempty (bindir)) - [status, output] = copyfile (bindir, desc.dir); - endif -endfunction - -function packinfo_copy_file (filename, requirement, packdir, packinfo, desc, octfiledir) - filepath = fullfile (packdir, filename); - if (!exist (filepath, "file") && strcmpi (requirement, "optional")) - ## do nothing, it's still OK - else - [status, output] = copyfile (filepath, packinfo); - if (status != 1) - rm_rf (desc.dir); - rm_rf (octfiledir); - error ("Couldn't copy %s file: %s", filename, output); - endif - endif -endfunction - -function finish_installation (desc, packdir, global_install) - ## Is there a post-install to call? - if (exist (fullfile (packdir, "post_install.m"), "file")) - wd = pwd (); - try - cd (packdir); - post_install (desc); - cd (wd); - catch - cd (wd); - rm_rf (desc.dir); - rm_rf (getarchdir (desc), global_install); - rethrow (lasterror ()); - end_try_catch - endif -endfunction - -function generate_lookfor_cache (desc) - dirs = split_by (genpath (desc.dir), pathsep ()); - for i = 1 : length (dirs) - gen_doc_cache (fullfile (dirs{i}, "doc-cache"), dirs{i}); - endfor -endfunction - -## Make sure the package contains the essential files. -function verify_directory (dir) - needed_files = {"COPYING", "DESCRIPTION"}; - for f = needed_files - if (! exist (fullfile (dir, f{1}), "file")) - error ("package is missing file: %s", f{1}); - endif - endfor -endfunction - -## Parse the DESCRIPTION file. -function desc = get_description (filename) - [fid, msg] = fopen (filename, "r"); - if (fid == -1) - error ("the DESCRIPTION file %s could not be read: %s", filename, msg); - endif - - desc = struct (); - - line = fgetl (fid); - while (line != -1) - if (line(1) == "#") - ## Comments, do nothing. - elseif (isspace(line(1))) - ## Continuation lines - if (exist ("keyword", "var") && isfield (desc, keyword)) - desc.(keyword) = cstrcat (desc.(keyword), " ", rstrip(line)); - endif - else - ## Keyword/value pair - colon = find (line == ":"); - if (length (colon) == 0) - disp ("skipping line"); - else - colon = colon(1); - keyword = tolower (strip (line(1:colon-1))); - value = strip (line (colon+1:end)); - if (length (value) == 0) - fclose (fid); - error ("The keyword `%s' of the package `%s' has an empty value", - keyword, desc.name); - endif - desc.(keyword) = value; - endif - endif - line = fgetl (fid); - endwhile - fclose (fid); - - ## Make sure all is okay. - needed_fields = {"name", "version", "date", "title", ... - "author", "maintainer", "description"}; - for f = needed_fields - if (! isfield (desc, f{1})) - error ("description is missing needed field %s", f{1}); - endif - endfor - desc.version = fix_version (desc.version); - if (isfield (desc, "depends")) - desc.depends = fix_depends (desc.depends); - else - desc.depends = ""; - endif - desc.name = tolower (desc.name); -endfunction - -## Make sure the version string v is a valid x.y.z version string -## Examples: "0.1" => "0.1.0", "monkey" => error(...). -function out = fix_version (v) - dots = find (v == "."); - if (length (dots) == 1) - major = str2num (v(1:dots-1)); - minor = str2num (v(dots+1:end)); - if (length (major) != 0 && length (minor) != 0) - out = sprintf ("%d.%d.0", major, minor); - return; - endif - elseif (length (dots) == 2) - major = str2num (v(1:dots(1)-1)); - minor = str2num (v(dots(1)+1:dots(2)-1)); - rev = str2num (v(dots(2)+1:end)); - if (length (major) != 0 && length (minor) != 0 && length (rev) != 0) - out = sprintf ("%d.%d.%d", major, minor, rev); - return; - endif - endif - error ("bad version string: %s", v); -endfunction - -## Make sure the depends field is of the right format. -## This function returns a cell of structures with the following fields: -## package, version, operator -function deps_cell = fix_depends (depends) - deps = split_by (tolower (depends), ","); - deps_cell = cell (1, length (deps)); - - ## For each dependency. - for i = 1:length (deps) - dep = deps{i}; - lpar = find (dep == "("); - rpar = find (dep == ")"); - ## Does the dependency specify a version - ## Example: package(>= version). - if (length (lpar) == 1 && length (rpar) == 1) - package = tolower (strip (dep(1:lpar-1))); - sub = dep(lpar(1)+1:rpar(1)-1); - parts = strsplit (sub, " ", true); - if (length (parts) != 2) - error ("incorrect syntax for dependency `%s' in the DESCRIPTION file\n", - dep); - endif - operator = parts{1}; - if (! any (strcmp (operator, {">", ">=", "<=", "<", "=="}))) - error ("unsupported operator: %s", operator); - endif - version = fix_version (parts{2}); - - ## If no version is specified for the dependency - ## we say that the version should be greater than - ## or equal to "0.0.0". - else - package = tolower (strip (dep)); - operator = ">="; - version = "0.0.0"; - endif - deps_cell{i} = struct ("package", package, "operator", operator, - "version", version); - endfor -endfunction - -## Strip the text of spaces from the right -## Example: " hello world " => " hello world" -## FIXME -- is this the same as deblank? -function text = rstrip (text) - chars = find (! isspace (text)); - if (length (chars) > 0) - ## FIXME: shouldn't it be text = text(1:chars(end)); - text = text (chars(1):end); - else - text = ""; - endif -endfunction - -## Strip the text of spaces from the left and the right. -## Example: " hello world " => "hello world" -function text = strip (text) - chars = find (! isspace (text)); - if (length (chars) > 0) - text = text(chars(1):chars(end)); - else - text = ""; - endif -endfunction - -## Split the text into a cell array of strings by sep. -## Example: "A, B" => {"A", "B"} (with sep = ",") -function out = split_by (text, sep) - out = strtrim (strsplit (text, sep)); -endfunction - -## Create an INDEX file for a package that doesn't provide one. -## 'desc' describes the package. -## 'dir' is the 'inst' directory in temporary directory. -## 'index_file' is the name (including path) of resulting INDEX file. -function write_index (desc, dir, index_file, global_install) - ## Get names of functions in dir - [files, err, msg] = readdir (dir); - if (err) - error ("couldn't read directory %s: %s", dir, msg); - endif - - ## Get classes in dir - class_idx = find (strncmp (files, '@', 1)); - for k = 1:length (class_idx) - class_name = files {class_idx (k)}; - class_dir = fullfile (dir, class_name); - if (exist (class_dir, "dir")) - [files2, err, msg] = readdir (class_dir); - if (err) - error ("couldn't read directory %s: %s", class_dir, msg); - endif - files2 = strcat (class_name, filesep (), files2); - files = [files; files2]; - endif - endfor - - ## Check for architecture dependent files. - tmpdir = getarchdir (desc); - if (exist (tmpdir, "dir")) - [files2, err, msg] = readdir (tmpdir); - if (err) - error ("couldn't read directory %s: %s", tmpdir, msg); - endif - files = [files; files2]; - endif - - functions = {}; - for i = 1:length (files) - file = files{i}; - lf = length (file); - if (lf > 2 && strcmp (file(end-1:end), ".m")) - functions{end+1} = file(1:end-2); - elseif (lf > 4 && strcmp (file(end-3:end), ".oct")) - functions{end+1} = file(1:end-4); - endif - endfor - - ## Does desc have a categories field? - if (! isfield (desc, "categories")) - error ("the DESCRIPTION file must have a Categories field, when no INDEX file is given"); - endif - categories = split_by (desc.categories, ","); - if (length (categories) < 1) - error ("the Category field is empty"); - endif - - ## Write INDEX. - fid = fopen (index_file, "w"); - if (fid == -1) - error ("couldn't open %s for writing", index_file); - endif - fprintf (fid, "%s >> %s\n", desc.name, desc.title); - fprintf (fid, "%s\n", categories{1}); - fprintf (fid, " %s\n", functions{:}); - fclose (fid); -endfunction - -function bad_deps = get_unsatisfied_deps (desc, installed_pkgs_lst) - bad_deps = {}; - - ## For each dependency. - for i = 1:length (desc.depends) - dep = desc.depends{i}; - - ## Is the current dependency Octave? - if (strcmp (dep.package, "octave")) - if (! compare_versions (OCTAVE_VERSION, dep.version, dep.operator)) - bad_deps{end+1} = dep; - endif - ## Is the current dependency not Octave? - else - ok = false; - for i = 1:length (installed_pkgs_lst) - cur_name = installed_pkgs_lst{i}.name; - cur_version = installed_pkgs_lst{i}.version; - if (strcmp (dep.package, cur_name) - && compare_versions (cur_version, dep.version, dep.operator)) - ok = true; - break; - endif - endfor - if (! ok) - bad_deps{end+1} = dep; - endif - endif - endfor -endfunction - -function [out1, out2] = installed_packages (local_list, global_list) - ## Get the list of installed packages. - try - local_packages = load (local_list).local_packages; - catch - local_packages = {}; - end_try_catch - try - global_packages = load (global_list).global_packages; - catch - global_packages = {}; - end_try_catch - installed_pkgs_lst = {local_packages{:}, global_packages{:}}; - - ## Eliminate duplicates in the installed package list. - ## Locally installed packages take precedence. - dup = []; - for i = 1:length (installed_pkgs_lst) - if (find (dup, i)) - continue; - endif - for j = (i+1):length (installed_pkgs_lst) - if (find (dup, j)) - continue; - endif - if (strcmp (installed_pkgs_lst{i}.name, installed_pkgs_lst{j}.name)) - dup = [dup, j]; - endif - endfor - endfor - if (! isempty(dup)) - installed_pkgs_lst(dup) = []; - endif - - ## Now check if the package is loaded. - tmppath = strrep (path(), "\\", "/"); - for i = 1:length (installed_pkgs_lst) - if (strfind (tmppath, strrep (installed_pkgs_lst{i}.dir, '\', '/'))) - installed_pkgs_lst{i}.loaded = true; - else - installed_pkgs_lst{i}.loaded = false; - endif - endfor - for i = 1:length (local_packages) - if (strfind (tmppath, strrep (local_packages{i}.dir, '\', '/'))) - local_packages{i}.loaded = true; - else - local_packages{i}.loaded = false; - endif - endfor - for i = 1:length (global_packages) - if (strfind (tmppath, strrep (global_packages{i}.dir, '\', '/'))) - global_packages{i}.loaded = true; - else - global_packages{i}.loaded = false; - endif - endfor - - ## Should we return something? - if (nargout == 2) - out1 = local_packages; - out2 = global_packages; - return; - elseif (nargout == 1) - out1 = installed_pkgs_lst; - return; - endif - - ## We shouldn't return something, so we'll print something. - num_packages = length (installed_pkgs_lst); - if (num_packages == 0) - printf ("no packages installed.\n"); - return; - endif - - ## Compute the maximal lengths of name, version, and dir. - h1 = "Package Name"; - h2 = "Version"; - h3 = "Installation directory"; - max_name_length = length (h1); - max_version_length = length (h2); - names = cell (num_packages, 1); - for i = 1:num_packages - max_name_length = max (max_name_length, - length (installed_pkgs_lst{i}.name)); - max_version_length = max (max_version_length, - length (installed_pkgs_lst{i}.version)); - names{i} = installed_pkgs_lst{i}.name; - endfor - max_dir_length = terminal_size()(2) - max_name_length - ... - max_version_length - 7; - if (max_dir_length < 20) - max_dir_length = Inf; - endif - - h1 = postpad (h1, max_name_length + 1, " "); - h2 = postpad (h2, max_version_length, " ");; - - ## Print a header. - header = sprintf("%s | %s | %s\n", h1, h2, h3); - printf (header); - tmp = sprintf (repmat ("-", 1, length(header)-1)); - tmp(length(h1)+2) = "+"; - tmp(length(h1)+length(h2)+5) = "+"; - printf ("%s\n", tmp); - - ## Print the packages. - format = sprintf ("%%%ds %%1s| %%%ds | %%s\n", max_name_length, - max_version_length); - [dummy, idx] = sort (names); - for i = 1:num_packages - cur_name = installed_pkgs_lst{idx(i)}.name; - cur_version = installed_pkgs_lst{idx(i)}.version; - cur_dir = installed_pkgs_lst{idx(i)}.dir; - if (length (cur_dir) > max_dir_length) - first_char = length (cur_dir) - max_dir_length + 4; - first_filesep = strfind (cur_dir(first_char:end), filesep()); - if (! isempty (first_filesep)) - cur_dir = cstrcat ("...", - cur_dir((first_char + first_filesep(1) - 1):end)); - else - cur_dir = cstrcat ("...", cur_dir(first_char:end)); - endif - endif - if (installed_pkgs_lst{idx(i)}.loaded) - cur_loaded = "*"; - else - cur_loaded = " "; - endif - printf (format, cur_name, cur_loaded, cur_version, cur_dir); - endfor -endfunction - -function load_packages (files, handle_deps, local_list, global_list) - installed_pkgs_lst = installed_packages (local_list, global_list); - num_packages = length (installed_pkgs_lst); - - ## Read package names and installdirs into a more convenient format. - pnames = pdirs = cell (1, num_packages); - for i = 1:num_packages - pnames{i} = installed_pkgs_lst{i}.name; - pdirs{i} = installed_pkgs_lst{i}.dir; - endfor - - ## Load all. - if (length (files) == 1 && strcmp (files{1}, "all")) - idx = [1:length(installed_pkgs_lst)]; - ## Load auto. - elseif (length (files) == 1 && strcmp (files{1}, "auto")) - idx = []; - for i = 1:length (installed_pkgs_lst) - if (exist (fullfile (pdirs{i}, "packinfo", ".autoload"), "file")) - idx (end + 1) = i; - endif - endfor - ## Load package_name1 ... - else - idx = []; - for i = 1:length (files) - idx2 = find (strcmp (pnames, files{i})); - if (! any (idx2)) - error ("package %s is not installed", files{i}); - endif - idx (end + 1) = idx2; - endfor - endif - - ## Load the packages, but take care of the ordering of dependencies. - load_packages_and_dependencies (idx, handle_deps, installed_pkgs_lst, true); -endfunction - -function unload_packages (files, handle_deps, local_list, global_list) - installed_pkgs_lst = installed_packages (local_list, global_list); - num_packages = length (installed_pkgs_lst); - - ## Read package names and installdirs into a more convenient format. - pnames = pdirs = cell (1, num_packages); - for i = 1:num_packages - pnames{i} = installed_pkgs_lst{i}.name; - pdirs{i} = installed_pkgs_lst{i}.dir; - pdeps{i} = installed_pkgs_lst{i}.depends; - endfor - - ## Get the current octave path. - p = split_by (path(), pathsep ()); - - if (length (files) == 1 && strcmp (files{1}, "all")) - ## Unload all. - dirs = pdirs; - desc = installed_pkgs_lst; - else - ## Unload package_name1 ... - dirs = {}; - desc = {}; - for i = 1:length (files) - idx = strcmp (pnames, files{i}); - if (! any (idx)) - error ("package %s is not installed", files{i}); - endif - dirs{end+1} = pdirs{idx}; - desc{end+1} = installed_pkgs_lst{idx}; - endfor - endif - - ## Check for architecture dependent directories. - archdirs = {}; - for i = 1:length (dirs) - tmpdir = getarchdir (desc{i}); - if (exist (tmpdir, "dir")) - archdirs{end+1} = dirs{i}; - archdirs{end+1} = tmpdir; - else - archdirs{end+1} = dirs{i}; - endif - endfor - - ## Unload the packages. - for i = 1:length (archdirs) - d = archdirs{i}; - idx = strcmp (p, d); - if (any (idx)) - rmpath (d); - ## FIXME: We should also check if we need to remove items from - ## EXEC_PATH. - endif - endfor -endfunction - -function [status_out, msg_out] = rm_rf (dir) - if (exist (dir)) - crr = confirm_recursive_rmdir (false, "local"); - [status, msg] = rmdir (dir, "s"); - else - status = 1; - msg = ""; - endif - if (nargout > 0) - status_out = status; - endif - if (nargout > 1) - msg_out = msg; - endif -endfunction - -function emp = dirempty (nm, ign) - if (exist (nm, "dir")) - if (nargin < 2) - ign = {".", ".."}; - else - ign = [{".", ".."}, ign]; - endif - l = dir (nm); - for i = 1:length (l) - found = false; - for j = 1:length (ign) - if (strcmp (l(i).name, ign{j})) - found = true; - break; - endif - endfor - if (! found) - emp = false; - return - endif - endfor - emp = true; - else - emp = true; - endif -endfunction - -function arch = getarch () - persistent _arch = cstrcat (octave_config_info ("canonical_host_type"), - "-", octave_config_info ("api_version")); - arch = _arch; -endfunction - -function archprefix = getarchprefix (desc, global_install) - if ((nargin == 2 && global_install) || (nargin < 2 && issuperuser ())) - archprefix = fullfile (octave_config_info ("libdir"), "octave", - "packages", cstrcat(desc.name, "-", desc.version)); - else - archprefix = desc.dir; - endif -endfunction - -function archdir = getarchdir (desc) - archdir = fullfile (desc.archprefix, getarch()); -endfunction - -function s = issuperuser () - if ((ispc () && ! isunix ()) || (geteuid() == 0)) - s = true; - else - s = false; - endif -endfunction - -function [status, output] = shell (cmd) - persistent have_sh; - - cmd = strrep (cmd, "\\", "/"); - if (ispc () && ! isunix ()) - if (isempty(have_sh)) - if (system("sh.exe -c \"exit\"")) - have_sh = false; - else - have_sh = true; - endif - endif - if (have_sh) - [status, output] = system (cstrcat ("sh.exe -c \"", cmd, "\"")); - else - error ("Can not find the command shell"); - endif - else - [status, output] = system (cmd); - endif -endfunction - -function newdesc = save_order (desc) - newdesc = {}; - for i = 1 : length(desc) - deps = desc{i}.depends; - if (isempty (deps) - || (length (deps) == 1 && strcmp(deps{1}.package, "octave"))) - newdesc {end + 1} = desc{i}; - else - tmpdesc = {}; - for k = 1 : length (deps) - for j = 1 : length (desc) - if (strcmp (desc{j}.name, deps{k}.package)) - tmpdesc{end+1} = desc{j}; - break; - endif - endfor - endfor - if (! isempty (tmpdesc)) - newdesc = {newdesc{:}, save_order(tmpdesc){:}, desc{i}}; - else - newdesc{end+1} = desc{i}; - endif - endif - endfor - ## Eliminate the duplicates. - idx = []; - for i = 1 : length (newdesc) - for j = (i + 1) : length (newdesc) - if (strcmp (newdesc{i}.name, newdesc{j}.name)) - idx (end + 1) = j; - endif - endfor - endfor - newdesc(idx) = []; -endfunction - -function load_packages_and_dependencies (idx, handle_deps, installed_pkgs_lst, - global_install) - idx = load_package_dirs (idx, [], handle_deps, installed_pkgs_lst); - dirs = {}; - execpath = EXEC_PATH (); - for i = idx; - ndir = installed_pkgs_lst{i}.dir; - dirs{end+1} = ndir; - if (exist (fullfile (dirs{end}, "bin"), "dir")) - execpath = cstrcat (execpath, pathsep (), fullfile (dirs{end}, "bin")); - endif - tmpdir = getarchdir (installed_pkgs_lst{i}); - if (exist (tmpdir, "dir")) - dirs{end + 1} = tmpdir; - if (exist (fullfile (dirs{end}, "bin"), "dir")) - execpath = cstrcat (execpath, pathsep (), fullfile (dirs{end}, "bin")); - endif - endif - endfor - - ## Load the packages. - if (length (dirs) > 0) - addpath (dirs{:}); - endif - - ## Add the binaries to exec_path. - if (! strcmp (EXEC_PATH, execpath)) - EXEC_PATH (execpath); - endif -endfunction - -function idx = load_package_dirs (lidx, idx, handle_deps, installed_pkgs_lst) - for i = lidx - if (isfield (installed_pkgs_lst{i}, "loaded") - && installed_pkgs_lst{i}.loaded) - continue; - else - if (handle_deps) - deps = installed_pkgs_lst{i}.depends; - if ((length (deps) > 1) - || (length (deps) == 1 && ! strcmp(deps{1}.package, "octave"))) - tmplidx = []; - for k = 1 : length (deps) - for j = 1 : length (installed_pkgs_lst) - if (strcmp (installed_pkgs_lst{j}.name, deps{k}.package)) - tmplidx (end + 1) = j; - break; - endif - endfor - endfor - idx = load_package_dirs (tmplidx, idx, handle_deps, - installed_pkgs_lst); - endif - endif - if (isempty (find(idx == i))) - idx (end + 1) = i; - endif - endif - endfor -endfunction - -function dep = is_architecture_dependent (nm) - persistent archdepsuffix = {".oct",".mex",".a",".lib",".so",".so.*",".dll","dylib"}; - - dep = false; - for i = 1 : length (archdepsuffix) - ext = archdepsuffix{i}; - if (ext(end) == "*") - isglob = true; - ext(end) = []; - else - isglob = false; - endif - pos = strfind (nm, ext); - if (pos) - if (! isglob && (length(nm) - pos(end) != length(ext) - 1)) - continue; - endif - dep = true; - break; - endif - endfor -endfunction - -function [url, local_file] = get_forge_download (name) - [ver, url] = get_forge_pkg (name); - local_file = [name, "-", ver, ".tar.gz"]; -endfunction - -function list = list_forge_packages () - [list, succ] = urlread ("http://octave.sourceforge.net/list_packages.php"); - if (succ) - list = strsplit (list, " \n\t", true); - else - error ("pkg: could not read URL, please verify internet connection"); - endif - if (nargout == 0) - page_screen_output (false, "local"); - puts ("OctaveForge provides these packages:\n"); - for i = 1:length (list) - try - ver = get_forge_pkg (list{i}); - catch - ver = "unknown"; - end_try_catch - printf (" %s %s\n", list{i}, ver); - endfor - endif -endfunction diff -r bec37a92cb3b -r 0fab7b9e6226 scripts/pkg/private/absolute_pathname.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/pkg/private/absolute_pathname.m Thu Mar 15 11:40:01 2012 +0100 @@ -0,0 +1,33 @@ +## Copyright (C) 2005-2012 S�ren Hauberg +## Copyright (C) 2010 VZLU Prague, a.s. +## +## This file is part of Octave. +## +## Octave is free software; you can redistribute it and/or modify it +## under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 3 of the License, or (at +## your option) any later version. +## +## Octave is distributed in the hope that it will be useful, but +## WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with Octave; see the file COPYING. If not, see +## . + +## -*- texinfo -*- +## @deftypefn {Function File} address@hidden =} absolute_pathname (@var{pth}) +## Undocumented internal function. +## @end deftypefn + +function pth = absolute_pathname (pth) + [status, msg, msgid] = fileattrib (pth); + if (status != 1) + error ("could not find the file or path %s", pth); + else + pth = msg.Name; + endif +endfunction + diff -r bec37a92cb3b -r 0fab7b9e6226 scripts/pkg/private/build.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/pkg/private/build.m Thu Mar 15 11:40:01 2012 +0100 @@ -0,0 +1,60 @@ +## Copyright (C) 2005-2012 S�ren Hauberg +## Copyright (C) 2010 VZLU Prague, a.s. +## +## This file is part of Octave. +## +## Octave is free software; you can redistribute it and/or modify it +## under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 3 of the License, or (at +## your option) any later version. +## +## Octave is distributed in the hope that it will be useful, but +## WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with Octave; see the file COPYING. If not, see +## . + +## -*- texinfo -*- +## @deftypefn {Function File} {} build (@var{files}, @var{handle_deps}, @var{autoload}, @var{verbose}) +## Undocumented internal function. +## @end deftypefn + +function build (files, handle_deps, autoload, verbose) + if (length (files) < 1) + error ("insufficient number of files"); + endif + builddir = files{1}; + if (! exist (builddir, "dir")) + warning ("creating build directory %s", builddir); + [status, msg] = mkdir (builddir); + if (status != 1) + error ("could not create installation directory: %s", msg); + endif + endif + builddir = absolute_pathname (builddir); + installdir = fullfile (builddir, "install"); + if (! exist (installdir, "dir")) + [status, msg] = mkdir (installdir); + if (status != 1) + error ("could not create installation directory: %s", msg); + endif + endif + files(1) = []; + buildlist = fullfile (builddir, "octave_packages"); + install (files, handle_deps, autoload, installdir, installdir, verbose, + buildlist, "", false); + unwind_protect + repackage (builddir, buildlist); + unwind_protect_cleanup + unload_packages ({"all"}, handle_deps, buildlist, ""); + if (exist (installdir, "dir")) + rm_rf (installdir); + endif + if (exist (buildlist, "file")) + unlink (buildlist); + endif + end_unwind_protect +endfunction diff -r bec37a92cb3b -r 0fab7b9e6226 scripts/pkg/private/configure_make.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/pkg/private/configure_make.m Thu Mar 15 11:40:01 2012 +0100 @@ -0,0 +1,159 @@ +## Copyright (C) 2005-2012 S�ren Hauberg +## Copyright (C) 2010 VZLU Prague, a.s. +## +## This file is part of Octave. +## +## Octave is free software; you can redistribute it and/or modify it +## under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 3 of the License, or (at +## your option) any later version. +## +## Octave is distributed in the hope that it will be useful, but +## WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with Octave; see the file COPYING. If not, see +## . + +## -*- texinfo -*- +## @deftypefn {Function File} {} configure_make (@var{desc}, @var{packdir},@ +## @var{verbose}) +## Undocumented internal function. +## @end deftypefn + +function configure_make (desc, packdir, verbose) + ## Perform ./configure, make, make install in "src". + if (exist (fullfile (packdir, "src"), "dir")) + src = fullfile (packdir, "src"); + octave_bindir = octave_config_info ("bindir"); + ver = version (); + mkoctfile = fullfile (octave_bindir, sprintf ("mkoctfile-%s", ver)); + octave_config = fullfile (octave_bindir, sprintf ("octave-config-%s", ver)); + octave_binary = fullfile (octave_bindir, sprintf ("octave-%s", ver)); + cenv = {"MKOCTFILE"; mkoctfile; + "OCTAVE_CONFIG"; octave_config; + "OCTAVE"; octave_binary; + "INSTALLDIR"; desc.dir}; + scenv = sprintf ("%s=\"%s\" ", cenv{:}); + ## Configure. + if (exist (fullfile (src, "configure"), "file")) + flags = ""; + if (isempty (getenv ("CC"))) + flags = cstrcat (flags, " CC=\"", octave_config_info ("CC"), "\""); + endif + if (isempty (getenv ("CXX"))) + flags = cstrcat (flags, " CXX=\"", octave_config_info ("CXX"), "\""); + endif + if (isempty (getenv ("AR"))) + flags = cstrcat (flags, " AR=\"", octave_config_info ("AR"), "\""); + endif + if (isempty (getenv ("RANLIB"))) + flags = cstrcat (flags, " RANLIB=\"", octave_config_info ("RANLIB"), "\""); + endif + [status, output] = shell (cstrcat ("cd '", src, "'; ", scenv, + "./configure --prefix=\"", + desc.dir, "\"", flags)); + if (status != 0) + rm_rf (desc.dir); + error ("the configure script returned the following error: %s", output); + elseif (verbose) + printf("%s", output); + endif + + endif + + ## Make. + if (exist (fullfile (src, "Makefile"), "file")) + [status, output] = shell (cstrcat (scenv, "make -C '", src, "'")); + if (status != 0) + rm_rf (desc.dir); + error ("'make' returned the following error: %s", output); + elseif (verbose) + printf("%s", output); + endif + endif + + ## Copy files to "inst" and "inst/arch" (this is instead of 'make + ## install'). + files = fullfile (src, "FILES"); + instdir = fullfile (packdir, "inst"); + archdir = fullfile (packdir, "inst", getarch ()); + + ## Get file names. + if (exist (files, "file")) + [fid, msg] = fopen (files, "r"); + if (fid < 0) + error ("couldn't open %s: %s", files, msg); + endif + filenames = char (fread (fid))'; + fclose (fid); + if (filenames(end) == "\n") + filenames(end) = []; + endif + filenames = split_by (filenames, "\n"); + delete_idx = []; + for i = 1:length (filenames) + if (! all (isspace (filenames{i}))) + filenames{i} = fullfile (src, filenames{i}); + else + delete_idx(end+1) = i; + endif + endfor + filenames(delete_idx) = []; + else + m = dir (fullfile (src, "*.m")); + oct = dir (fullfile (src, "*.oct")); + mex = dir (fullfile (src, "*.mex")); + + filenames = cellfun (@(x) fullfile (src, x), + {m.name, oct.name, mex.name}, + "uniformoutput", false); + endif + + ## Split into architecture dependent and independent files. + if (isempty (filenames)) + idx = []; + else + idx = cellfun ("is_architecture_dependent", filenames); + endif + archdependent = filenames (idx); + archindependent = filenames (!idx); + + ## Copy the files. + if (! all (isspace ([filenames{:}]))) + if (! exist (instdir, "dir")) + mkdir (instdir); + endif + if (! all (isspace ([archindependent{:}]))) + if (verbose) + printf ("copyfile"); + printf (" %s", archindependent{:}); + printf ("%s\n", instdir); + endif + [status, output] = copyfile (archindependent, instdir); + if (status != 1) + rm_rf (desc.dir); + error ("Couldn't copy files from 'src' to 'inst': %s", output); + endif + endif + if (! all (isspace ([archdependent{:}]))) + if (verbose) + printf ("copyfile"); + printf (" %s", archdependent{:}); + printf (" %s\n", archdir); + endif + if (! exist (archdir, "dir")) + mkdir (archdir); + endif + [status, output] = copyfile (archdependent, archdir); + if (status != 1) + rm_rf (desc.dir); + error ("Couldn't copy files from 'src' to 'inst': %s", output); + endif + endif + endif + endif +endfunction + diff -r bec37a92cb3b -r 0fab7b9e6226 scripts/pkg/private/copy_files.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/pkg/private/copy_files.m Thu Mar 15 11:40:01 2012 +0100 @@ -0,0 +1,144 @@ +## Copyright (C) 2005-2012 S�ren Hauberg +## Copyright (C) 2010 VZLU Prague, a.s. +## +## This file is part of Octave. +## +## Octave is free software; you can redistribute it and/or modify it +## under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 3 of the License, or (at +## your option) any later version. +## +## Octave is distributed in the hope that it will be useful, but +## WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with Octave; see the file COPYING. If not, see +## . + +## -*- texinfo -*- +## @deftypefn {Function File} {} copy_files (@var{desc}, @var{packdir},@ +## @var{global_install}) +## Undocumented internal function. +## @end deftypefn + +function copy_files (desc, packdir, global_install) + ## Create the installation directory. + if (! exist (desc.dir, "dir")) + [status, output] = mkdir (desc.dir); + if (status != 1) + error ("couldn't create installation directory %s : %s", + desc.dir, output); + endif + endif + + octfiledir = getarchdir (desc); + + ## Copy the files from "inst" to installdir. + instdir = fullfile (packdir, "inst"); + if (! dirempty (instdir)) + [status, output] = copyfile (fullfile (instdir, "*"), desc.dir); + if (status != 1) + rm_rf (desc.dir); + error ("couldn't copy files to the installation directory"); + endif + if (exist (fullfile (desc.dir, getarch ()), "dir") + && ! strcmp (fullfile (desc.dir, getarch ()), octfiledir)) + if (! exist (octfiledir, "dir")) + ## Can be required to create upto three levels of dirs. + octm1 = fileparts (octfiledir); + if (! exist (octm1, "dir")) + octm2 = fileparts (octm1); + if (! exist (octm2, "dir")) + octm3 = fileparts (octm2); + if (! exist (octm3, "dir")) + [status, output] = mkdir (octm3); + if (status != 1) + rm_rf (desc.dir); + error ("couldn't create installation directory %s : %s", + octm3, output); + endif + endif + [status, output] = mkdir (octm2); + if (status != 1) + rm_rf (desc.dir); + error ("couldn't create installation directory %s : %s", + octm2, output); + endif + endif + [status, output] = mkdir (octm1); + if (status != 1) + rm_rf (desc.dir); + error ("couldn't create installation directory %s : %s", + octm1, output); + endif + endif + [status, output] = mkdir (octfiledir); + if (status != 1) + rm_rf (desc.dir); + error ("couldn't create installation directory %s : %s", + octfiledir, output); + endif + endif + [status, output] = movefile (fullfile (desc.dir, getarch (), "*"), + octfiledir); + rm_rf (fullfile (desc.dir, getarch ())); + + if (status != 1) + rm_rf (desc.dir); + rm_rf (octfiledir); + error ("couldn't copy files to the installation directory"); + endif + endif + + endif + + ## Create the "packinfo" directory. + packinfo = fullfile (desc.dir, "packinfo"); + [status, msg] = mkdir (packinfo); + if (status != 1) + rm_rf (desc.dir); + rm_rf (octfiledir); + error ("couldn't create packinfo directory: %s", msg); + endif + + packinfo_copy_file ("DESCRIPTION", "required", packdir, packinfo, desc, octfiledir); + packinfo_copy_file ("COPYING", "required", packdir, packinfo, desc, octfiledir); + + packinfo_copy_file ("NEWS", "optional", packdir, packinfo, desc, octfiledir); + packinfo_copy_file ("ONEWS", "optional", packdir, packinfo, desc, octfiledir); + packinfo_copy_file ("ChangeLog", "optional", packdir, packinfo, desc, octfiledir); + + ## Is there an INDEX file to copy or should we generate one? + index_file = fullfile (packdir, "INDEX"); + if (exist(index_file, "file")) + packinfo_copy_file ("INDEX", "required", packdir, packinfo, desc, octfiledir); + else + try + write_index (desc, fullfile (packdir, "inst"), + fullfile (packinfo, "INDEX"), global_install); + catch + rm_rf (desc.dir); + rm_rf (octfiledir); + rethrow (lasterror ()); + end_try_catch + endif + + ## Is there an 'on_uninstall.m' to install? + packinfo_copy_file ("on_uninstall.m", "optional", packdir, packinfo, desc, octfiledir); + + ## Is there a doc/ directory that needs to be installed? + docdir = fullfile (packdir, "doc"); + if (exist (docdir, "dir") && ! dirempty (docdir)) + [status, output] = copyfile (docdir, desc.dir); + endif + + ## Is there a bin/ directory that needs to be installed? + ## FIXME: Need to treat architecture dependent files in bin/ + bindir = fullfile (packdir, "bin"); + if (exist (bindir, "dir") && ! dirempty (bindir)) + [status, output] = copyfile (bindir, desc.dir); + endif +endfunction + diff -r bec37a92cb3b -r 0fab7b9e6226 scripts/pkg/private/create_pkgadddel.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/pkg/private/create_pkgadddel.m Thu Mar 15 11:40:01 2012 +0100 @@ -0,0 +1,90 @@ +## Copyright (C) 2005-2012 S�ren Hauberg +## Copyright (C) 2010 VZLU Prague, a.s. +## +## This file is part of Octave. +## +## Octave is free software; you can redistribute it and/or modify it +## under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 3 of the License, or (at +## your option) any later version. +## +## Octave is distributed in the hope that it will be useful, but +## WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with Octave; see the file COPYING. If not, see +## . + +## -*- texinfo -*- +## @deftypefn {Function File} {} create_pkgadddel (@var{desc}, @var{packdir},@ +## @var{nm}, @var{global_install}) +## Undocumented internal function. +## @end deftypefn + +function create_pkgadddel (desc, packdir, nm, global_install) + instpkg = fullfile (desc.dir, nm); + instfid = fopen (instpkg, "wt"); + ## If it is exists, most of the PKG_* file should go into the + ## architecture dependent directory so that the autoload/mfilename + ## commands work as expected. The only part that doesn't is the + ## part in the main directory. + archdir = fullfile (getarchprefix (desc), cstrcat (desc.name, "-", + desc.version), getarch ()); + if (exist (getarchdir (desc, global_install), "dir")) + archpkg = fullfile (getarchdir (desc, global_install), nm); + archfid = fopen (archpkg, "at"); + else + archpkg = instpkg; + archfid = instfid; + endif + + if (archfid >= 0 && instfid >= 0) + ## Search all dot-m files for PKG commands. + lst = dir (fullfile (packdir, "inst", "*.m")); + for i = 1:length (lst) + nam = fullfile (packdir, "inst", lst(i).name); + fwrite (instfid, extract_pkg (nam, ['^[#%][#%]* *' nm ': *(.*)$'])); + endfor + + ## Search all C++ source files for PKG commands. + lst = dir (fullfile (packdir, "src", "*.cc")); + for i = 1:length (lst) + nam = fullfile (packdir, "src", lst(i).name); + fwrite (archfid, extract_pkg (nam, ['^//* *' nm ': *(.*)$'])); + fwrite (archfid, extract_pkg (nam, ['^/\** *' nm ': *(.*) *\*/$'])); + endfor + + ## Add developer included PKG commands. + packdirnm = fullfile (packdir, nm); + if (exist (packdirnm, "file")) + fid = fopen (packdirnm, "rt"); + if (fid >= 0) + while (! feof (fid)) + ln = fgets (fid); + if (ln > 0) + fwrite (archfid, ln); + endif + endwhile + fclose (fid); + endif + endif + + ## If the files is empty remove it. + fclose (instfid); + t = dir (instpkg); + if (t.bytes <= 0) + unlink (instpkg); + endif + + if (instfid != archfid) + fclose (archfid); + t = dir (archpkg); + if (t.bytes <= 0) + unlink (archpkg); + endif + endif + endif +endfunction + diff -r bec37a92cb3b -r 0fab7b9e6226 scripts/pkg/private/describe.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/pkg/private/describe.m Thu Mar 15 11:40:01 2012 +0100 @@ -0,0 +1,88 @@ +## Copyright (C) 2005-2012 S�ren Hauberg +## Copyright (C) 2010 VZLU Prague, a.s. +## +## This file is part of Octave. +## +## Octave is free software; you can redistribute it and/or modify it +## under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 3 of the License, or (at +## your option) any later version. +## +## Octave is distributed in the hope that it will be useful, but +## WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with Octave; see the file COPYING. If not, see +## . + +## -*- texinfo -*- +## @deftypefn {Function File} address@hidden, @var{flag}] =}@ +## describe (@var{pkgnames}, @var{verbose}, @var{local_list}, @var{global_list}) +## Undocumented internal function. +## @end deftypefn + +function [pkg_desc_list, flag] = describe (pkgnames, verbose, + local_list, global_list) + + ## Get the list of installed packages. + installed_pkgs_lst = installed_packages(local_list, global_list); + num_packages = length (installed_pkgs_lst); + + + describe_all = false; + if (any (strcmp ("all", pkgnames))) + describe_all = true; + flag(1:num_packages) = {"Not Loaded"}; + num_pkgnames = num_packages; + else + num_pkgnames = length (pkgnames); + flag(1:num_pkgnames) = {"Not installed"}; + endif + + for i = 1:num_packages + curr_name = installed_pkgs_lst{i}.name; + if (describe_all) + name_pos = i; + else + name_pos = find(strcmp (curr_name, pkgnames)); + endif + + if (! isempty (name_pos)) + if (installed_pkgs_lst{i}.loaded) + flag{name_pos} = "Loaded"; + else + flag{name_pos} = "Not loaded"; + endif + + pkg_desc_list{name_pos}.name = installed_pkgs_lst{i}.name; + pkg_desc_list{name_pos}.version = installed_pkgs_lst{i}.version; + pkg_desc_list{name_pos}.description = installed_pkgs_lst{i}.description; + pkg_desc_list{name_pos}.provides = parse_pkg_idx (installed_pkgs_lst{i}.dir); + + endif + endfor + + non_inst = find (strcmp (flag, "Not installed")); + if (! isempty (non_inst)) + if (nargout < 2) + non_inst_str = sprintf (" %s ", pkgnames{non_inst}); + error ("some packages are not installed: %s", non_inst_str); + else + pkg_desc_list{non_inst} = struct ("name", {}, "description", + {}, "provides", {}); + endif + endif + + if (nargout == 0) + for i = 1:num_pkgnames + print_package_description (pkg_desc_list{i}.name, + pkg_desc_list{i}.version, + pkg_desc_list{i}.provides, + pkg_desc_list{i}.description, + flag{i}, verbose); + endfor + endif + +endfunction diff -r bec37a92cb3b -r 0fab7b9e6226 scripts/pkg/private/dirempty.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/pkg/private/dirempty.m Thu Mar 15 11:40:01 2012 +0100 @@ -0,0 +1,50 @@ +## Copyright (C) 2005-2012 S�ren Hauberg +## Copyright (C) 2010 VZLU Prague, a.s. +## +## This file is part of Octave. +## +## Octave is free software; you can redistribute it and/or modify it +## under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 3 of the License, or (at +## your option) any later version. +## +## Octave is distributed in the hope that it will be useful, but +## WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with Octave; see the file COPYING. If not, see +## . + +## -*- texinfo -*- +## @deftypefn {Function File} address@hidden =} dirempty (@var{nm}, @var{ign}) +## Undocumented internal function. +## @end deftypefn + +function emp = dirempty (nm, ign) + if (exist (nm, "dir")) + if (nargin < 2) + ign = {".", ".."}; + else + ign = [{".", ".."}, ign]; + endif + l = dir (nm); + for i = 1:length (l) + found = false; + for j = 1:length (ign) + if (strcmp (l(i).name, ign{j})) + found = true; + break; + endif + endfor + if (! found) + emp = false; + return + endif + endfor + emp = true; + else + emp = true; + endif +endfunction diff -r bec37a92cb3b -r 0fab7b9e6226 scripts/pkg/private/extract_pkg.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/pkg/private/extract_pkg.m Thu Mar 15 11:40:01 2012 +0100 @@ -0,0 +1,44 @@ +## Copyright (C) 2005-2012 S�ren Hauberg +## Copyright (C) 2010 VZLU Prague, a.s. +## +## This file is part of Octave. +## +## Octave is free software; you can redistribute it and/or modify it +## under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 3 of the License, or (at +## your option) any later version. +## +## Octave is distributed in the hope that it will be useful, but +## WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with Octave; see the file COPYING. If not, see +## . + +## -*- texinfo -*- +## @deftypefn {Function File} address@hidden =} extract_pkg (@var{nm}, @var{pat}) +## Undocumented internal function. +## @end deftypefn + +function pkg = extract_pkg (nm, pat) + fid = fopen (nm, "rt"); + pkg = ""; + if (fid >= 0) + while (! feof (fid)) + ln = fgetl (fid); + if (ln > 0) + t = regexp (ln, pat, "tokens"); + if (! isempty (t)) + pkg = cstrcat (pkg, "\n", t{1}{1}); + endif + endif + endwhile + if (! isempty (pkg)) + pkg = cstrcat (pkg, "\n"); + endif + fclose (fid); + endif +endfunction + diff -r bec37a92cb3b -r 0fab7b9e6226 scripts/pkg/private/finish_installation.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/pkg/private/finish_installation.m Thu Mar 15 11:40:01 2012 +0100 @@ -0,0 +1,42 @@ +## Copyright (C) 2005-2012 S�ren Hauberg +## Copyright (C) 2010 VZLU Prague, a.s. +## +## This file is part of Octave. +## +## Octave is free software; you can redistribute it and/or modify it +## under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 3 of the License, or (at +## your option) any later version. +## +## Octave is distributed in the hope that it will be useful, but +## WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with Octave; see the file COPYING. If not, see +## . + +## -*- texinfo -*- +## @deftypefn {Function File} {} finish_installation (@var{desc},@ +## @var{packdir}, @var{global_install}) +## Undocumented internal function. +## @end deftypefn + +function finish_installation (desc, packdir, global_install) + ## Is there a post-install to call? + if (exist (fullfile (packdir, "post_install.m"), "file")) + wd = pwd (); + try + cd (packdir); + post_install (desc); + cd (wd); + catch + cd (wd); + rm_rf (desc.dir); + rm_rf (getarchdir (desc), global_install); + rethrow (lasterror ()); + end_try_catch + endif +endfunction + diff -r bec37a92cb3b -r 0fab7b9e6226 scripts/pkg/private/fix_depends.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/pkg/private/fix_depends.m Thu Mar 15 11:40:01 2012 +0100 @@ -0,0 +1,65 @@ +## Copyright (C) 2005-2012 S�ren Hauberg +## Copyright (C) 2010 VZLU Prague, a.s. +## +## This file is part of Octave. +## +## Octave is free software; you can redistribute it and/or modify it +## under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 3 of the License, or (at +## your option) any later version. +## +## Octave is distributed in the hope that it will be useful, but +## WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with Octave; see the file COPYING. If not, see +## . + +## -*- texinfo -*- +## @deftypefn {Function File} address@hidden =} fix_depends (@var{depends}) +## Undocumented internal function. +## @end deftypefn + +## Make sure the depends field is of the right format. +## This function returns a cell of structures with the following fields: +## package, version, operator +function deps_cell = fix_depends (depends) + deps = split_by (tolower (depends), ","); + deps_cell = cell (1, length (deps)); + + ## For each dependency. + for i = 1:length (deps) + dep = deps{i}; + lpar = find (dep == "("); + rpar = find (dep == ")"); + ## Does the dependency specify a version + ## Example: package(>= version). + if (length (lpar) == 1 && length (rpar) == 1) + package = tolower (strip (dep(1:lpar-1))); + sub = dep(lpar(1)+1:rpar(1)-1); + parts = strsplit (sub, " ", true); + if (length (parts) != 2) + error ("incorrect syntax for dependency `%s' in the DESCRIPTION file\n", + dep); + endif + operator = parts{1}; + if (! any (strcmp (operator, {">", ">=", "<=", "<", "=="}))) + error ("unsupported operator: %s", operator); + endif + version = fix_version (parts{2}); + + ## If no version is specified for the dependency + ## we say that the version should be greater than + ## or equal to "0.0.0". + else + package = tolower (strip (dep)); + operator = ">="; + version = "0.0.0"; + endif + deps_cell{i} = struct ("package", package, "operator", operator, + "version", version); + endfor +endfunction + diff -r bec37a92cb3b -r 0fab7b9e6226 scripts/pkg/private/fix_version.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/pkg/private/fix_version.m Thu Mar 15 11:40:01 2012 +0100 @@ -0,0 +1,47 @@ +## Copyright (C) 2005-2012 S�ren Hauberg +## Copyright (C) 2010 VZLU Prague, a.s. +## +## This file is part of Octave. +## +## Octave is free software; you can redistribute it and/or modify it +## under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 3 of the License, or (at +## your option) any later version. +## +## Octave is distributed in the hope that it will be useful, but +## WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with Octave; see the file COPYING. If not, see +## . + +## -*- texinfo -*- +## @deftypefn {Function File} address@hidden =} fix_version (@var{v}) +## Undocumented internal function. +## @end deftypefn + +## Make sure the version string v is a valid x.y.z version string +## Examples: "0.1" => "0.1.0", "monkey" => error(...). +function out = fix_version (v) + dots = find (v == "."); + if (length (dots) == 1) + major = str2num (v(1:dots-1)); + minor = str2num (v(dots+1:end)); + if (length (major) != 0 && length (minor) != 0) + out = sprintf ("%d.%d.0", major, minor); + return; + endif + elseif (length (dots) == 2) + major = str2num (v(1:dots(1)-1)); + minor = str2num (v(dots(1)+1:dots(2)-1)); + rev = str2num (v(dots(2)+1:end)); + if (length (major) != 0 && length (minor) != 0 && length (rev) != 0) + out = sprintf ("%d.%d.%d", major, minor, rev); + return; + endif + endif + error ("bad version string: %s", v); +endfunction + diff -r bec37a92cb3b -r 0fab7b9e6226 scripts/pkg/private/generate_lookfor_cache.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/pkg/private/generate_lookfor_cache.m Thu Mar 15 11:40:01 2012 +0100 @@ -0,0 +1,31 @@ +## Copyright (C) 2005-2012 S�ren Hauberg +## Copyright (C) 2010 VZLU Prague, a.s. +## +## This file is part of Octave. +## +## Octave is free software; you can redistribute it and/or modify it +## under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 3 of the License, or (at +## your option) any later version. +## +## Octave is distributed in the hope that it will be useful, but +## WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with Octave; see the file COPYING. If not, see +## . + +## -*- texinfo -*- +## @deftypefn {Function File} {} generate_lookfor_cache (@var{desc}) +## Undocumented internal function. +## @end deftypefn + +function generate_lookfor_cache (desc) + dirs = split_by (genpath (desc.dir), pathsep ()); + for i = 1 : length (dirs) + gen_doc_cache (fullfile (dirs{i}, "doc-cache"), dirs{i}); + endfor +endfunction + diff -r bec37a92cb3b -r 0fab7b9e6226 scripts/pkg/private/get_description.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/pkg/private/get_description.m Thu Mar 15 11:40:01 2012 +0100 @@ -0,0 +1,80 @@ +## Copyright (C) 2005-2012 S�ren Hauberg +## Copyright (C) 2010 VZLU Prague, a.s. +## +## This file is part of Octave. +## +## Octave is free software; you can redistribute it and/or modify it +## under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 3 of the License, or (at +## your option) any later version. +## +## Octave is distributed in the hope that it will be useful, but +## WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with Octave; see the file COPYING. If not, see +## . + +## -*- texinfo -*- +## @deftypefn {Function File} address@hidden =} get_description (@var{filename}) +## Undocumented internal function. +## @end deftypefn + +## Parse the DESCRIPTION file. +function desc = get_description (filename) + [fid, msg] = fopen (filename, "r"); + if (fid == -1) + error ("the DESCRIPTION file %s could not be read: %s", filename, msg); + endif + + desc = struct (); + + line = fgetl (fid); + while (line != -1) + if (line(1) == "#") + ## Comments, do nothing. + elseif (isspace(line(1))) + ## Continuation lines + if (exist ("keyword", "var") && isfield (desc, keyword)) + desc.(keyword) = cstrcat (desc.(keyword), " ", rstrip(line)); + endif + else + ## Keyword/value pair + colon = find (line == ":"); + if (length (colon) == 0) + disp ("skipping line"); + else + colon = colon(1); + keyword = tolower (strip (line(1:colon-1))); + value = strip (line (colon+1:end)); + if (length (value) == 0) + fclose (fid); + error ("The keyword `%s' of the package `%s' has an empty value", + keyword, desc.name); + endif + desc.(keyword) = value; + endif + endif + line = fgetl (fid); + endwhile + fclose (fid); + + ## Make sure all is okay. + needed_fields = {"name", "version", "date", "title", ... + "author", "maintainer", "description"}; + for f = needed_fields + if (! isfield (desc, f{1})) + error ("description is missing needed field %s", f{1}); + endif + endfor + desc.version = fix_version (desc.version); + if (isfield (desc, "depends")) + desc.depends = fix_depends (desc.depends); + else + desc.depends = ""; + endif + desc.name = tolower (desc.name); +endfunction + diff -r bec37a92cb3b -r 0fab7b9e6226 scripts/pkg/private/get_forge_download.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/pkg/private/get_forge_download.m Thu Mar 15 11:40:01 2012 +0100 @@ -0,0 +1,28 @@ +## Copyright (C) 2005-2012 S�ren Hauberg +## Copyright (C) 2010 VZLU Prague, a.s. +## +## This file is part of Octave. +## +## Octave is free software; you can redistribute it and/or modify it +## under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 3 of the License, or (at +## your option) any later version. +## +## Octave is distributed in the hope that it will be useful, but +## WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with Octave; see the file COPYING. If not, see +## . + +## -*- texinfo -*- +## @deftypefn {Function File} address@hidden, @var{local_file}] =} list_forge_packages () +## Undocumented internal function. +## @end deftypefn + +function [url, local_file] = get_forge_download (name) + [ver, url] = get_forge_pkg (name); + local_file = [name, "-", ver, ".tar.gz"]; +endfunction diff -r bec37a92cb3b -r 0fab7b9e6226 scripts/pkg/private/get_unsatisfied_deps.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/pkg/private/get_unsatisfied_deps.m Thu Mar 15 11:40:01 2012 +0100 @@ -0,0 +1,55 @@ +## Copyright (C) 2005-2012 S�ren Hauberg +## Copyright (C) 2010 VZLU Prague, a.s. +## +## This file is part of Octave. +## +## Octave is free software; you can redistribute it and/or modify it +## under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 3 of the License, or (at +## your option) any later version. +## +## Octave is distributed in the hope that it will be useful, but +## WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with Octave; see the file COPYING. If not, see +## . + +## -*- texinfo -*- +## @deftypefn {Function File} address@hidden =} get_unsatisfied_deps (@var{desc},@ +## @var{installed_pkgs_lst}) +## Undocumented internal function. +## @end deftypefn + +function bad_deps = get_unsatisfied_deps (desc, installed_pkgs_lst) + bad_deps = {}; + + ## For each dependency. + for i = 1:length (desc.depends) + dep = desc.depends{i}; + + ## Is the current dependency Octave? + if (strcmp (dep.package, "octave")) + if (! compare_versions (OCTAVE_VERSION, dep.version, dep.operator)) + bad_deps{end+1} = dep; + endif + ## Is the current dependency not Octave? + else + ok = false; + for i = 1:length (installed_pkgs_lst) + cur_name = installed_pkgs_lst{i}.name; + cur_version = installed_pkgs_lst{i}.version; + if (strcmp (dep.package, cur_name) + && compare_versions (cur_version, dep.version, dep.operator)) + ok = true; + break; + endif + endfor + if (! ok) + bad_deps{end+1} = dep; + endif + endif + endfor +endfunction diff -r bec37a92cb3b -r 0fab7b9e6226 scripts/pkg/private/getarch.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/pkg/private/getarch.m Thu Mar 15 11:40:01 2012 +0100 @@ -0,0 +1,30 @@ +## Copyright (C) 2005-2012 S�ren Hauberg +## Copyright (C) 2010 VZLU Prague, a.s. +## +## This file is part of Octave. +## +## Octave is free software; you can redistribute it and/or modify it +## under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 3 of the License, or (at +## your option) any later version. +## +## Octave is distributed in the hope that it will be useful, but +## WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with Octave; see the file COPYING. If not, see +## . + +## -*- texinfo -*- +## @deftypefn {Function File} address@hidden =} getarch () +## Undocumented internal function. +## @end deftypefn + +function arch = getarch () + persistent _arch = cstrcat (octave_config_info ("canonical_host_type"), + "-", octave_config_info ("api_version")); + arch = _arch; +endfunction + diff -r bec37a92cb3b -r 0fab7b9e6226 scripts/pkg/private/getarchdir.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/pkg/private/getarchdir.m Thu Mar 15 11:40:01 2012 +0100 @@ -0,0 +1,28 @@ +## Copyright (C) 2005-2012 S�ren Hauberg +## Copyright (C) 2010 VZLU Prague, a.s. +## +## This file is part of Octave. +## +## Octave is free software; you can redistribute it and/or modify it +## under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 3 of the License, or (at +## your option) any later version. +## +## Octave is distributed in the hope that it will be useful, but +## WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with Octave; see the file COPYING. If not, see +## . + +## -*- texinfo -*- +## @deftypefn {Function File} address@hidden =} getarchdir (@var{desc}) +## Undocumented internal function. +## @end deftypefn + +function archdir = getarchdir (desc) + archdir = fullfile (desc.archprefix, getarch()); +endfunction + diff -r bec37a92cb3b -r 0fab7b9e6226 scripts/pkg/private/getarchprefix.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/pkg/private/getarchprefix.m Thu Mar 15 11:40:01 2012 +0100 @@ -0,0 +1,34 @@ +## Copyright (C) 2005-2012 S�ren Hauberg +## Copyright (C) 2010 VZLU Prague, a.s. +## +## This file is part of Octave. +## +## Octave is free software; you can redistribute it and/or modify it +## under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 3 of the License, or (at +## your option) any later version. +## +## Octave is distributed in the hope that it will be useful, but +## WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with Octave; see the file COPYING. If not, see +## . + +## -*- texinfo -*- +## @deftypefn {Function File} address@hidden =}@ +## getarchprefix (@var{desc}, @var{global_install}) +## Undocumented internal function. +## @end deftypefn + +function archprefix = getarchprefix (desc, global_install) + if ((nargin == 2 && global_install) || (nargin < 2 && issuperuser ())) + archprefix = fullfile (octave_config_info ("libdir"), "octave", + "packages", cstrcat(desc.name, "-", desc.version)); + else + archprefix = desc.dir; + endif +endfunction + diff -r bec37a92cb3b -r 0fab7b9e6226 scripts/pkg/private/install.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/pkg/private/install.m Thu Mar 15 11:40:01 2012 +0100 @@ -0,0 +1,334 @@ +## Copyright (C) 2005-2012 S�ren Hauberg +## Copyright (C) 2010 VZLU Prague, a.s. +## +## This file is part of Octave. +## +## Octave is free software; you can redistribute it and/or modify it +## under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 3 of the License, or (at +## your option) any later version. +## +## Octave is distributed in the hope that it will be useful, but +## WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with Octave; see the file COPYING. If not, see +## . + +## -*- texinfo -*- +## @deftypefn {Function File} {} install (@var{files}, @var{handle_deps}, @var{autoload},@ +## @var{prefix}, @var{archprefix}, @var{verbose},@ +## @var{local_list}, @var{global_list}, @var{global_install}) +## Undocumented internal function. +## @end deftypefn + +function install (files, handle_deps, autoload, prefix, archprefix, verbose, + local_list, global_list, global_install) + + ## Check that the directory in prefix exist. If it doesn't: create it! + if (! exist (prefix, "dir")) + warning ("creating installation directory %s", prefix); + [status, msg] = mkdir (prefix); + if (status != 1) + error ("could not create installation directory: %s", msg); + endif + endif + + ## Get the list of installed packages. + [local_packages, global_packages] = installed_packages (local_list, + global_list); + + installed_pkgs_lst = {local_packages{:}, global_packages{:}}; + + if (global_install) + packages = global_packages; + else + packages = local_packages; + endif + + ## Uncompress the packages and read the DESCRIPTION files. + tmpdirs = packdirs = descriptions = {}; + try + ## Warn about non existent files. + for i = 1:length (files) + if (isempty (glob(files{i}))) + warning ("file %s does not exist", files{i}); + endif + endfor + + ## Unpack the package files and read the DESCRIPTION files. + files = glob (files); + packages_to_uninstall = []; + for i = 1:length (files) + tgz = files{i}; + + if (exist (tgz, "file")) + ## Create a temporary directory. + tmpdir = tmpnam (); + tmpdirs{end+1} = tmpdir; + if (verbose) + printf ("mkdir (%s)\n", tmpdir); + endif + [status, msg] = mkdir (tmpdir); + if (status != 1) + error ("couldn't create temporary directory: %s", msg); + endif + + ## Uncompress the package. + if (verbose) + printf ("untar (%s, %s)\n", tgz, tmpdir); + endif + untar (tgz, tmpdir); + + ## Get the name of the directories produced by tar. + [dirlist, err, msg] = readdir (tmpdir); + if (err) + error ("couldn't read directory produced by tar: %s", msg); + endif + + if (length (dirlist) > 3) + error ("bundles of packages are not allowed"); + endif + endif + + ## The filename pointed to an uncompressed package to begin with. + if (exist (tgz, "dir")) + dirlist = {".", "..", tgz}; + endif + + if (exist (tgz, "file") || exist (tgz, "dir")) + ## The two first entries of dirlist are "." and "..". + if (exist (tgz, "file")) + packdir = fullfile (tmpdir, dirlist{3}); + else + packdir = fullfile (pwd(), dirlist{3}); + endif + packdirs{end+1} = packdir; + + ## Make sure the package contains necessary files. + verify_directory (packdir); + + ## Read the DESCRIPTION file. + filename = fullfile (packdir, "DESCRIPTION"); + desc = get_description (filename); + + ## Verify that package name corresponds with filename. + [dummy, nm] = fileparts (tgz); + if ((length (nm) >= length (desc.name)) + && ! strcmp (desc.name, nm(1:length(desc.name)))) + error ("package name '%s' doesn't correspond to its filename '%s'", + desc.name, nm); + endif + + ## Set default installation directory. + desc.dir = fullfile (prefix, cstrcat (desc.name, "-", desc.version)); + + ## Set default architectire dependent installation directory. + desc.archprefix = fullfile (archprefix, cstrcat (desc.name, "-", + desc.version)); + + ## Save desc. + descriptions{end+1} = desc; + + ## Are any of the new packages already installed? + ## If so we'll remove the old version. + for j = 1:length (packages) + if (strcmp (packages{j}.name, desc.name)) + packages_to_uninstall(end+1) = j; + endif + endfor + endif + endfor + catch + ## Something went wrong, delete tmpdirs. + for i = 1:length (tmpdirs) + rm_rf (tmpdirs{i}); + endfor + rethrow (lasterror ()); + end_try_catch + + ## Check dependencies. + if (handle_deps) + ok = true; + error_text = ""; + for i = 1:length (descriptions) + desc = descriptions{i}; + idx2 = setdiff (1:length(descriptions), i); + if (global_install) + ## Global installation is not allowed to have dependencies on locally + ## installed packages. + idx1 = setdiff (1:length(global_packages), packages_to_uninstall); + pseudo_installed_packages = {global_packages{idx1}, ... + descriptions{idx2}}; + else + idx1 = setdiff (1:length(local_packages), packages_to_uninstall); + pseudo_installed_packages = {local_packages{idx1}, ... + global_packages{:}, ... + descriptions{idx2}}; + endif + bad_deps = get_unsatisfied_deps (desc, pseudo_installed_packages); + ## Are there any unsatisfied dependencies? + if (! isempty (bad_deps)) + ok = false; + for i = 1:length (bad_deps) + dep = bad_deps{i}; + error_text = cstrcat (error_text, " ", desc.name, " needs ", + dep.package, " ", dep.operator, " ", + dep.version, "\n"); + endfor + endif + endfor + + ## Did we find any unsatisfied dependencies? + if (! ok) + error ("the following dependencies where unsatisfied:\n %s", error_text); + endif + endif + + ## Prepare each package for installation. + try + for i = 1:length (descriptions) + desc = descriptions{i}; + pdir = packdirs{i}; + prepare_installation (desc, pdir); + configure_make (desc, pdir, verbose); + endfor + catch + ## Something went wrong, delete tmpdirs. + for i = 1:length (tmpdirs) + rm_rf (tmpdirs{i}); + endfor + rethrow (lasterror ()); + end_try_catch + + ## Uninstall the packages that will be replaced. + try + for i = packages_to_uninstall + if (global_install) + uninstall ({global_packages{i}.name}, false, verbose, local_list, + global_list, global_install); + else + uninstall ({local_packages{i}.name}, false, verbose, local_list, + global_list, global_install); + endif + endfor + catch + ## Something went wrong, delete tmpdirs. + for i = 1:length (tmpdirs) + rm_rf (tmpdirs{i}); + endfor + rethrow (lasterror ()); + end_try_catch + + ## Install each package. + try + for i = 1:length (descriptions) + desc = descriptions{i}; + pdir = packdirs{i}; + copy_files (desc, pdir, global_install); + create_pkgadddel (desc, pdir, "PKG_ADD", global_install); + create_pkgadddel (desc, pdir, "PKG_DEL", global_install); + finish_installation (desc, pdir, global_install); + generate_lookfor_cache (desc); + endfor + catch + ## Something went wrong, delete tmpdirs. + for i = 1:length (tmpdirs) + rm_rf (tmpdirs{i}); + endfor + for i = 1:length (descriptions) + rm_rf (descriptions{i}.dir); + rm_rf (getarchdir (descriptions{i})); + endfor + rethrow (lasterror ()); + end_try_catch + + ## Check if the installed directory is empty. If it is remove it + ## from the list. + for i = length (descriptions):-1:1 + if (dirempty (descriptions{i}.dir, {"packinfo", "doc"}) + && dirempty (getarchdir (descriptions{i}))) + warning ("package %s is empty\n", descriptions{i}.name); + rm_rf (descriptions{i}.dir); + rm_rf (getarchdir (descriptions{i})); + descriptions(i) = []; + endif + endfor + + ## If the package requested that it is autoloaded, or the installer + ## requested that it is, then mark the package as autoloaded. + for i = length (descriptions):-1:1 + if (autoload > 0 || (autoload == 0 && isautoload (descriptions(i)))) + fclose (fopen (fullfile (descriptions{i}.dir, "packinfo", + ".autoload"), "wt")); + descriptions{i}.autoload = 1; + endif + endfor + + ## Add the packages to the package list. + try + if (global_install) + idx = setdiff (1:length(global_packages), packages_to_uninstall); + global_packages = save_order ({global_packages{idx}, descriptions{:}}); + save (global_list, "global_packages"); + installed_pkgs_lst = {local_packages{:}, global_packages{:}}; + else + idx = setdiff (1:length(local_packages), packages_to_uninstall); + local_packages = save_order ({local_packages{idx}, descriptions{:}}); + save (local_list, "local_packages"); + installed_pkgs_lst = {local_packages{:}, global_packages{:}}; + endif + catch + ## Something went wrong, delete tmpdirs. + for i = 1:length (tmpdirs) + rm_rf (tmpdirs{i}); + endfor + for i = 1:length (descriptions) + rm_rf (descriptions{i}.dir); + endfor + if (global_install) + printf ("error: couldn't append to %s\n", global_list); + else + printf ("error: couldn't append to %s\n", local_list); + endif + rethrow (lasterror ()); + end_try_catch + + ## All is well, let's clean up. + for i = 1:length (tmpdirs) + [status, msg] = rm_rf (tmpdirs{i}); + if (status != 1) + warning ("couldn't clean up after my self: %s\n", msg); + endif + endfor + + ## Add the newly installed packages to the path, so the user + ## can begin using them. Only load them if they are marked autoload. + if (length (descriptions) > 0) + idx = []; + for i = 1:length (descriptions) + if (isautoload (descriptions(i))) + nm = descriptions{i}.name; + for j = 1:length (installed_pkgs_lst) + if (strcmp (nm, installed_pkgs_lst{j}.name)) + idx (end + 1) = j; + break; + endif + endfor + endif + endfor + load_packages_and_dependencies (idx, handle_deps, installed_pkgs_lst, + global_install); + endif + + ## If there's a NEWS file, mention it + ## we are checking if desc exists too because it's possible to ge to this point + ## without creating it such as giving an invalid filename for the package + if (exist ("desc", "var") && exist (fullfile (desc.dir, "packinfo", "NEWS"), "file")) + printf ("For information about changes from previous versions of the %s package, run 'news (\"%s\")'.\n", + desc.name, desc.name); + endif + +endfunction diff -r bec37a92cb3b -r 0fab7b9e6226 scripts/pkg/private/installed_packages.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/pkg/private/installed_packages.m Thu Mar 15 11:40:01 2012 +0100 @@ -0,0 +1,158 @@ +## Copyright (C) 2005-2012 S�ren Hauberg +## Copyright (C) 2010 VZLU Prague, a.s. +## +## This file is part of Octave. +## +## Octave is free software; you can redistribute it and/or modify it +## under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 3 of the License, or (at +## your option) any later version. +## +## Octave is distributed in the hope that it will be useful, but +## WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with Octave; see the file COPYING. If not, see +## . + +## -*- texinfo -*- +## @deftypefn {Function File} address@hidden, @var{out2}] =}@ +## installed_packages (@var{local_list}, @var{global_list}) +## Undocumented internal function. +## @end deftypefn + +function [out1, out2] = installed_packages (local_list, global_list) + ## Get the list of installed packages. + try + local_packages = load (local_list).local_packages; + catch + local_packages = {}; + end_try_catch + try + global_packages = load (global_list).global_packages; + catch + global_packages = {}; + end_try_catch + installed_pkgs_lst = {local_packages{:}, global_packages{:}}; + + ## Eliminate duplicates in the installed package list. + ## Locally installed packages take precedence. + dup = []; + for i = 1:length (installed_pkgs_lst) + if (find (dup, i)) + continue; + endif + for j = (i+1):length (installed_pkgs_lst) + if (find (dup, j)) + continue; + endif + if (strcmp (installed_pkgs_lst{i}.name, installed_pkgs_lst{j}.name)) + dup = [dup, j]; + endif + endfor + endfor + if (! isempty(dup)) + installed_pkgs_lst(dup) = []; + endif + + ## Now check if the package is loaded. + tmppath = strrep (path(), "\\", "/"); + for i = 1:length (installed_pkgs_lst) + if (strfind (tmppath, strrep (installed_pkgs_lst{i}.dir, '\', '/'))) + installed_pkgs_lst{i}.loaded = true; + else + installed_pkgs_lst{i}.loaded = false; + endif + endfor + for i = 1:length (local_packages) + if (strfind (tmppath, strrep (local_packages{i}.dir, '\', '/'))) + local_packages{i}.loaded = true; + else + local_packages{i}.loaded = false; + endif + endfor + for i = 1:length (global_packages) + if (strfind (tmppath, strrep (global_packages{i}.dir, '\', '/'))) + global_packages{i}.loaded = true; + else + global_packages{i}.loaded = false; + endif + endfor + + ## Should we return something? + if (nargout == 2) + out1 = local_packages; + out2 = global_packages; + return; + elseif (nargout == 1) + out1 = installed_pkgs_lst; + return; + endif + + ## We shouldn't return something, so we'll print something. + num_packages = length (installed_pkgs_lst); + if (num_packages == 0) + printf ("no packages installed.\n"); + return; + endif + + ## Compute the maximal lengths of name, version, and dir. + h1 = "Package Name"; + h2 = "Version"; + h3 = "Installation directory"; + max_name_length = length (h1); + max_version_length = length (h2); + names = cell (num_packages, 1); + for i = 1:num_packages + max_name_length = max (max_name_length, + length (installed_pkgs_lst{i}.name)); + max_version_length = max (max_version_length, + length (installed_pkgs_lst{i}.version)); + names{i} = installed_pkgs_lst{i}.name; + endfor + max_dir_length = terminal_size()(2) - max_name_length - ... + max_version_length - 7; + if (max_dir_length < 20) + max_dir_length = Inf; + endif + + h1 = postpad (h1, max_name_length + 1, " "); + h2 = postpad (h2, max_version_length, " ");; + + ## Print a header. + header = sprintf("%s | %s | %s\n", h1, h2, h3); + printf (header); + tmp = sprintf (repmat ("-", 1, length(header)-1)); + tmp(length(h1)+2) = "+"; + tmp(length(h1)+length(h2)+5) = "+"; + printf ("%s\n", tmp); + + ## Print the packages. + format = sprintf ("%%%ds %%1s| %%%ds | %%s\n", max_name_length, + max_version_length); + [dummy, idx] = sort (names); + for i = 1:num_packages + cur_name = installed_pkgs_lst{idx(i)}.name; + cur_version = installed_pkgs_lst{idx(i)}.version; + cur_dir = installed_pkgs_lst{idx(i)}.dir; + if (length (cur_dir) > max_dir_length) + first_char = length (cur_dir) - max_dir_length + 4; + first_filesep = strfind (cur_dir(first_char:end), filesep()); + if (! isempty (first_filesep)) + cur_dir = cstrcat ("...", + cur_dir((first_char + first_filesep(1) - 1):end)); + else + cur_dir = cstrcat ("...", cur_dir(first_char:end)); + endif + endif + if (installed_pkgs_lst{idx(i)}.loaded) + cur_loaded = "*"; + else + cur_loaded = " "; + endif + printf (format, cur_name, cur_loaded, cur_version, cur_dir); + endfor +endfunction + diff -r bec37a92cb3b -r 0fab7b9e6226 scripts/pkg/private/is_architecture_dependent.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/pkg/private/is_architecture_dependent.m Thu Mar 15 11:40:01 2012 +0100 @@ -0,0 +1,46 @@ +## Copyright (C) 2005-2012 S�ren Hauberg +## Copyright (C) 2010 VZLU Prague, a.s. +## +## This file is part of Octave. +## +## Octave is free software; you can redistribute it and/or modify it +## under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 3 of the License, or (at +## your option) any later version. +## +## Octave is distributed in the hope that it will be useful, but +## WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with Octave; see the file COPYING. If not, see +## . + +## -*- texinfo -*- +## @deftypefn {Function File} address@hidden is_architecture_dependent (@var{nm}) +## Undocumented internal function. +## @end deftypefn + +function dep = is_architecture_dependent (nm) + persistent archdepsuffix = {".oct",".mex",".a",".lib",".so",".so.*",".dll","dylib"}; + + dep = false; + for i = 1 : length (archdepsuffix) + ext = archdepsuffix{i}; + if (ext(end) == "*") + isglob = true; + ext(end) = []; + else + isglob = false; + endif + pos = strfind (nm, ext); + if (pos) + if (! isglob && (length(nm) - pos(end) != length(ext) - 1)) + continue; + endif + dep = true; + break; + endif + endfor +endfunction diff -r bec37a92cb3b -r 0fab7b9e6226 scripts/pkg/private/isautoload.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/pkg/private/isautoload.m Thu Mar 15 11:40:01 2012 +0100 @@ -0,0 +1,38 @@ +## Copyright (C) 2005-2012 S�ren Hauberg +## Copyright (C) 2010 VZLU Prague, a.s. +## +## This file is part of Octave. +## +## Octave is free software; you can redistribute it and/or modify it +## under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 3 of the License, or (at +## your option) any later version. +## +## Octave is distributed in the hope that it will be useful, but +## WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with Octave; see the file COPYING. If not, see +## . + +## -*- texinfo -*- +## @deftypefn {Function File} address@hidden =} isautoload (@var{desc}) +## Undocumented internal function. +## @end deftypefn + +function auto = isautoload (desc) + auto = false; + if (isfield (desc{1}, "autoload")) + a = desc{1}.autoload; + if ((isnumeric (a) && a > 0) + || (ischar (a) && (strcmpi (a, "true") + || strcmpi (a, "on") + || strcmpi (a, "yes") + || strcmpi (a, "1")))) + auto = true; + endif + endif +endfunction + diff -r bec37a92cb3b -r 0fab7b9e6226 scripts/pkg/private/issuperuser.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/pkg/private/issuperuser.m Thu Mar 15 11:40:01 2012 +0100 @@ -0,0 +1,32 @@ +## Copyright (C) 2005-2012 S�ren Hauberg +## Copyright (C) 2010 VZLU Prague, a.s. +## +## This file is part of Octave. +## +## Octave is free software; you can redistribute it and/or modify it +## under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 3 of the License, or (at +## your option) any later version. +## +## Octave is distributed in the hope that it will be useful, but +## WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with Octave; see the file COPYING. If not, see +## . + +## -*- texinfo -*- +## @deftypefn {Function File} address@hidden =} issuperuser () +## Undocumented internal function. +## @end deftypefn + +function s = issuperuser () + if ((ispc () && ! isunix ()) || (geteuid() == 0)) + s = true; + else + s = false; + endif +endfunction + diff -r bec37a92cb3b -r 0fab7b9e6226 scripts/pkg/private/list_forge_packages.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/pkg/private/list_forge_packages.m Thu Mar 15 11:40:01 2012 +0100 @@ -0,0 +1,44 @@ +## Copyright (C) 2005-2012 S�ren Hauberg +## Copyright (C) 2010 VZLU Prague, a.s. +## +## This file is part of Octave. +## +## Octave is free software; you can redistribute it and/or modify it +## under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 3 of the License, or (at +## your option) any later version. +## +## Octave is distributed in the hope that it will be useful, but +## WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with Octave; see the file COPYING. If not, see +## . + +## -*- texinfo -*- +## @deftypefn {Function File} address@hidden =} list_forge_packages () +## Undocumented internal function. +## @end deftypefn + +function list = list_forge_packages () + [list, succ] = urlread ("http://octave.sourceforge.net/list_packages.php"); + if (succ) + list = strsplit (list, " \n\t", true); + else + error ("pkg: could not read URL, please verify internet connection"); + endif + if (nargout == 0) + page_screen_output (false, "local"); + puts ("OctaveForge provides these packages:\n"); + for i = 1:length (list) + try + ver = get_forge_pkg (list{i}); + catch + ver = "unknown"; + end_try_catch + printf (" %s %s\n", list{i}, ver); + endfor + endif +endfunction diff -r bec37a92cb3b -r 0fab7b9e6226 scripts/pkg/private/load_package_dirs.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/pkg/private/load_package_dirs.m Thu Mar 15 11:40:01 2012 +0100 @@ -0,0 +1,55 @@ +## Copyright (C) 2005-2012 S�ren Hauberg +## Copyright (C) 2010 VZLU Prague, a.s. +## +## This file is part of Octave. +## +## Octave is free software; you can redistribute it and/or modify it +## under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 3 of the License, or (at +## your option) any later version. +## +## Octave is distributed in the hope that it will be useful, but +## WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with Octave; see the file COPYING. If not, see +## . + +## -*- texinfo -*- +## @deftypefn {Function File} address@hidden = } load_package_dirs@ +## (@var{lidx}, @var{idx}, @var{handle_deps}, @var{installed_pkgs_lst}) +## Undocumented internal function. +## @end deftypefn + +function idx = load_package_dirs (lidx, idx, handle_deps, installed_pkgs_lst) + for i = lidx + if (isfield (installed_pkgs_lst{i}, "loaded") + && installed_pkgs_lst{i}.loaded) + continue; + else + if (handle_deps) + deps = installed_pkgs_lst{i}.depends; + if ((length (deps) > 1) + || (length (deps) == 1 && ! strcmp(deps{1}.package, "octave"))) + tmplidx = []; + for k = 1 : length (deps) + for j = 1 : length (installed_pkgs_lst) + if (strcmp (installed_pkgs_lst{j}.name, deps{k}.package)) + tmplidx (end + 1) = j; + break; + endif + endfor + endfor + idx = load_package_dirs (tmplidx, idx, handle_deps, + installed_pkgs_lst); + endif + endif + if (isempty (find(idx == i))) + idx (end + 1) = i; + endif + endif + endfor +endfunction + diff -r bec37a92cb3b -r 0fab7b9e6226 scripts/pkg/private/load_packages.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/pkg/private/load_packages.m Thu Mar 15 11:40:01 2012 +0100 @@ -0,0 +1,63 @@ +## Copyright (C) 2005-2012 S�ren Hauberg +## Copyright (C) 2010 VZLU Prague, a.s. +## +## This file is part of Octave. +## +## Octave is free software; you can redistribute it and/or modify it +## under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 3 of the License, or (at +## your option) any later version. +## +## Octave is distributed in the hope that it will be useful, but +## WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with Octave; see the file COPYING. If not, see +## . + +## -*- texinfo -*- +## @deftypefn {Function File} {} load_packages (@var{files}, @var{handle_deps},@ +## @var{local_list}, @var{global_list}) +## Undocumented internal function. +## @end deftypefn + +function load_packages (files, handle_deps, local_list, global_list) + installed_pkgs_lst = installed_packages (local_list, global_list); + num_packages = length (installed_pkgs_lst); + + ## Read package names and installdirs into a more convenient format. + pnames = pdirs = cell (1, num_packages); + for i = 1:num_packages + pnames{i} = installed_pkgs_lst{i}.name; + pdirs{i} = installed_pkgs_lst{i}.dir; + endfor + + ## Load all. + if (length (files) == 1 && strcmp (files{1}, "all")) + idx = [1:length(installed_pkgs_lst)]; + ## Load auto. + elseif (length (files) == 1 && strcmp (files{1}, "auto")) + idx = []; + for i = 1:length (installed_pkgs_lst) + if (exist (fullfile (pdirs{i}, "packinfo", ".autoload"), "file")) + idx (end + 1) = i; + endif + endfor + ## Load package_name1 ... + else + idx = []; + for i = 1:length (files) + idx2 = find (strcmp (pnames, files{i})); + if (! any (idx2)) + error ("package %s is not installed", files{i}); + endif + idx (end + 1) = idx2; + endfor + endif + + ## Load the packages, but take care of the ordering of dependencies. + load_packages_and_dependencies (idx, handle_deps, installed_pkgs_lst, true); +endfunction + diff -r bec37a92cb3b -r 0fab7b9e6226 scripts/pkg/private/load_packages_and_dependencies.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/pkg/private/load_packages_and_dependencies.m Thu Mar 15 11:40:01 2012 +0100 @@ -0,0 +1,56 @@ +## Copyright (C) 2005-2012 S�ren Hauberg +## Copyright (C) 2010 VZLU Prague, a.s. +## +## This file is part of Octave. +## +## Octave is free software; you can redistribute it and/or modify it +## under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 3 of the License, or (at +## your option) any later version. +## +## Octave is distributed in the hope that it will be useful, but +## WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with Octave; see the file COPYING. If not, see +## . + +## -*- texinfo -*- +## @deftypefn {Function File} {} load_packages_and_dependencies (@var{idx},@ +## @var{handle_deps}, @var{installed_pkgs_lst}, @var{global_install}) +## Undocumented internal function. +## @end deftypefn + +function load_packages_and_dependencies (idx, handle_deps, installed_pkgs_lst, + global_install) + idx = load_package_dirs (idx, [], handle_deps, installed_pkgs_lst); + dirs = {}; + execpath = EXEC_PATH (); + for i = idx; + ndir = installed_pkgs_lst{i}.dir; + dirs{end+1} = ndir; + if (exist (fullfile (dirs{end}, "bin"), "dir")) + execpath = cstrcat (execpath, pathsep (), fullfile (dirs{end}, "bin")); + endif + tmpdir = getarchdir (installed_pkgs_lst{i}); + if (exist (tmpdir, "dir")) + dirs{end + 1} = tmpdir; + if (exist (fullfile (dirs{end}, "bin"), "dir")) + execpath = cstrcat (execpath, pathsep (), fullfile (dirs{end}, "bin")); + endif + endif + endfor + + ## Load the packages. + if (length (dirs) > 0) + addpath (dirs{:}); + endif + + ## Add the binaries to exec_path. + if (! strcmp (EXEC_PATH, execpath)) + EXEC_PATH (execpath); + endif +endfunction + diff -r bec37a92cb3b -r 0fab7b9e6226 scripts/pkg/private/packinfo_copy_file.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/pkg/private/packinfo_copy_file.m Thu Mar 15 11:40:01 2012 +0100 @@ -0,0 +1,39 @@ +## Copyright (C) 2005-2012 S�ren Hauberg +## Copyright (C) 2010 VZLU Prague, a.s. +## +## This file is part of Octave. +## +## Octave is free software; you can redistribute it and/or modify it +## under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 3 of the License, or (at +## your option) any later version. +## +## Octave is distributed in the hope that it will be useful, but +## WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with Octave; see the file COPYING. If not, see +## . + +## -*- texinfo -*- +## @deftypefn {Function File} {} packinfo_copy_file (@var{filename},@ +## @var{requirement}, @var{packdir}, @var{packinfo}, @var{desc}, @var{octfiledir}) +## Undocumented internal function. +## @end deftypefn + +function packinfo_copy_file (filename, requirement, packdir, packinfo, desc, octfiledir) + filepath = fullfile (packdir, filename); + if (!exist (filepath, "file") && strcmpi (requirement, "optional")) + ## do nothing, it's still OK + else + [status, output] = copyfile (filepath, packinfo); + if (status != 1) + rm_rf (desc.dir); + rm_rf (octfiledir); + error ("Couldn't copy %s file: %s", filename, output); + endif + endif +endfunction + diff -r bec37a92cb3b -r 0fab7b9e6226 scripts/pkg/private/parse_pkg_idx.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/pkg/private/parse_pkg_idx.m Thu Mar 15 11:40:01 2012 +0100 @@ -0,0 +1,77 @@ +## Copyright (C) 2005-2012 S�ren Hauberg +## Copyright (C) 2010 VZLU Prague, a.s. +## +## This file is part of Octave. +## +## Octave is free software; you can redistribute it and/or modify it +## under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 3 of the License, or (at +## your option) any later version. +## +## Octave is distributed in the hope that it will be useful, but +## WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with Octave; see the file COPYING. If not, see +## . + +## -*- texinfo -*- +## @deftypefn {Function File} address@hidden = } parse_pkg_idx (@var{packdir}) +## Undocumented internal function. +## @end deftypefn + + +## Read an INDEX file. +function pkg_idx_struct = parse_pkg_idx (packdir) + + index_file = fullfile (packdir, "packinfo", "INDEX"); + + if (! exist (index_file, "file")) + error ("could not find any INDEX file in directory %s, try 'pkg rebuild all' to generate missing INDEX files", packdir); + endif + + + [fid, msg] = fopen (index_file, "r"); + if (fid == -1) + error ("the INDEX file %s could not be read: %s", + index_file, msg); + endif + + cat_num = 1; + pkg_idx_struct{1}.category = "Uncategorized"; + pkg_idx_struct{1}.functions = {}; + + line = fgetl (fid); + while (isempty (strfind (line, ">>")) && ! feof (fid)) + line = fgetl (fid); + endwhile + + while (! feof (fid) || line != -1) + if (! any (! isspace (line)) || line(1) == "#" || any (line == "=")) + ## Comments, blank lines or comments about unimplemented + ## functions: do nothing + ## FIXME: probably comments and pointers to external functions + ## could be treated better when printing to screen? + elseif (! isempty (strfind (line, ">>"))) + ## Skip package name and description as they are in DESCRIPTION + ## already. + elseif (! isspace (line(1))) + ## Category. + if (! isempty (pkg_idx_struct{cat_num}.functions)) + pkg_idx_struct{++cat_num}.functions = {}; + endif + pkg_idx_struct{cat_num}.category = deblank (line); + else + ## Function names. + while (any (! isspace (line))) + [fun_name, line] = strtok (line); + pkg_idx_struct{cat_num}.functions{end+1} = deblank (fun_name); + endwhile + endif + line = fgetl (fid); + endwhile + fclose (fid); +endfunction + diff -r bec37a92cb3b -r 0fab7b9e6226 scripts/pkg/private/prepare_installation.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/pkg/private/prepare_installation.m Thu Mar 15 11:40:01 2012 +0100 @@ -0,0 +1,50 @@ +## Copyright (C) 2005-2012 S�ren Hauberg +## Copyright (C) 2010 VZLU Prague, a.s. +## +## This file is part of Octave. +## +## Octave is free software; you can redistribute it and/or modify it +## under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 3 of the License, or (at +## your option) any later version. +## +## Octave is distributed in the hope that it will be useful, but +## WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with Octave; see the file COPYING. If not, see +## . + +## -*- texinfo -*- +## @deftypefn {Function File} {} prepare_installation (@var{desc}, @var{packdir}) +## Undocumented internal function. +## @end deftypefn + +function prepare_installation (desc, packdir) + ## Is there a pre_install to call? + if (exist (fullfile (packdir, "pre_install.m"), "file")) + wd = pwd (); + try + cd (packdir); + pre_install (desc); + cd (wd); + catch + cd (wd); + rethrow (lasterror ()); + end_try_catch + endif + + ## If the directory "inst" doesn't exist, we create it. + inst_dir = fullfile (packdir, "inst"); + if (! exist (inst_dir, "dir")) + [status, msg] = mkdir (inst_dir); + if (status != 1) + rm_rf (desc.dir); + error ("the 'inst' directory did not exist and could not be created: %s", + msg); + endif + endif +endfunction + diff -r bec37a92cb3b -r 0fab7b9e6226 scripts/pkg/private/print_package_description.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/pkg/private/print_package_description.m Thu Mar 15 11:40:01 2012 +0100 @@ -0,0 +1,47 @@ +## Copyright (C) 2005-2012 S�ren Hauberg +## Copyright (C) 2010 VZLU Prague, a.s. +## +## This file is part of Octave. +## +## Octave is free software; you can redistribute it and/or modify it +## under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 3 of the License, or (at +## your option) any later version. +## +## Octave is distributed in the hope that it will be useful, but +## WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with Octave; see the file COPYING. If not, see +## . + +## -*- texinfo -*- +## @deftypefn {Function File} {} print_package_description (@var{pkg_name},@ +## @var{pkg_ver}, @var{pkg_idx_struct}, @var{pkg_desc}, @var{status}, @var{verbose}) +## Undocumented internal function. +## @end deftypefn + +function print_package_description (pkg_name, pkg_ver, pkg_idx_struct, + pkg_desc, status, verbose) + + printf ("---\nPackage name:\n\t%s\n", pkg_name); + printf ("Version:\n\t%s\n", pkg_ver); + printf ("Short description:\n\t%s\n", pkg_desc); + printf ("Status:\n\t%s\n", status); + if (verbose) + printf ("---\nProvides:\n"); + for i = 1:length(pkg_idx_struct) + if (! isempty (pkg_idx_struct{i}.functions)) + printf ("%s\n", pkg_idx_struct{i}.category); + for j = 1:length(pkg_idx_struct{i}.functions) + printf ("\t%s\n", pkg_idx_struct{i}.functions{j}); + endfor + endif + endfor + endif + +endfunction + + diff -r bec37a92cb3b -r 0fab7b9e6226 scripts/pkg/private/rebuild.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/pkg/private/rebuild.m Thu Mar 15 11:40:01 2012 +0100 @@ -0,0 +1,101 @@ +## Copyright (C) 2005-2012 S�ren Hauberg +## Copyright (C) 2010 VZLU Prague, a.s. +## +## This file is part of Octave. +## +## Octave is free software; you can redistribute it and/or modify it +## under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 3 of the License, or (at +## your option) any later version. +## +## Octave is distributed in the hope that it will be useful, but +## WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with Octave; see the file COPYING. If not, see +## . + +## -*- texinfo -*- +## @deftypefn {Function File} address@hidden =} rebuild (@var{prefix},@ +## @var{archprefix}, @var{list}, @var{files}, @var{auto}, @var{verbose}) +## Undocumented internal function. +## @end deftypefn + +function descriptions = rebuild (prefix, archprefix, list, files, auto, verbose) + if (isempty (files)) + [dirlist, err, msg] = readdir (prefix); + if (err) + error ("couldn't read directory %s: %s", prefix, msg); + endif + ## the two first entries of dirlist are "." and ".." + dirlist([1,2]) = []; + else + old_descriptions = installed_packages (list, list); + wd = pwd (); + unwind_protect + cd (prefix); + dirlist = glob (cellfun(@(x) cstrcat(x, '-*'), files, 'uniformoutput', 0)); + unwind_protect_cleanup + cd (wd); + end_unwind_protect + endif + descriptions = {}; + for k = 1:length (dirlist) + descfile = fullfile (prefix, dirlist{k}, "packinfo", "DESCRIPTION"); + if (verbose) + printf ("recreating package description from %s\n", dirlist{k}); + endif + if (exist (descfile, "file")) + desc = get_description (descfile); + desc.dir = fullfile (prefix, dirlist{k}); + desc.archprefix = fullfile (archprefix, cstrcat (desc.name, "-", + desc.version)); + if (auto != 0) + if (exist (fullfile (desc.dir, "packinfo", ".autoload"), "file")) + unlink (fullfile (desc.dir, "packinfo", ".autoload")); + endif + if (auto < 0) + desc.autoload = 0; + elseif (auto > 0) + desc.autoload = 1; + fclose (fopen (fullfile (desc.dir, "packinfo", ".autoload"), "wt")); + endif + else + if (exist (fullfile (desc.dir, "packinfo", ".autoload"), "file")) + desc.autoload = 1; + else + desc.autoload = 0; + endif + endif + descriptions{end + 1} = desc; + elseif (verbose) + warning ("directory %s is not a valid package", dirlist{k}); + endif + endfor + + if (! isempty (files)) + ## We are rebuilding for a particular package(s) so we should take + ## care to keep the other untouched packages in the descriptions + descriptions = {descriptions{:}, old_descriptions{:}}; + + dup = []; + for i = 1:length (descriptions) + if (find (dup, i)) + continue; + endif + for j = (i+1):length (descriptions) + if (find (dup, j)) + continue; + endif + if (strcmp (descriptions{i}.name, descriptions{j}.name)) + dup = [dup, j]; + endif + endfor + endfor + if (! isempty (dup)) + descriptions (dup) = []; + endif + endif +endfunction diff -r bec37a92cb3b -r 0fab7b9e6226 scripts/pkg/private/repackage.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/pkg/private/repackage.m Thu Mar 15 11:40:01 2012 +0100 @@ -0,0 +1,91 @@ +## Copyright (C) 2005-2012 S�ren Hauberg +## Copyright (C) 2010 VZLU Prague, a.s. +## +## This file is part of Octave. +## +## Octave is free software; you can redistribute it and/or modify it +## under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 3 of the License, or (at +## your option) any later version. +## +## Octave is distributed in the hope that it will be useful, but +## WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with Octave; see the file COPYING. If not, see +## . + +## -*- texinfo -*- +## @deftypefn {Function File} {} repackage (@var{builddir},@ +## @vat{buildlist}) +## Undocumented internal function. +## @end deftypefn + +function repackage (builddir, buildlist) + packages = installed_packages (buildlist, buildlist); + + wd = pwd(); + for i = 1 : length(packages) + pack = packages{i}; + unwind_protect + cd (builddir); + mkdir (pack.name); + mkdir (fullfile (pack.name, "inst")); + copyfile (fullfile (pack.dir, "*"), fullfile (pack.name, "inst")); + movefile (fullfile (pack.name, "inst","packinfo", "*"), pack.name); + if (exist (fullfile (pack.name, "inst","packinfo", ".autoload"), "file")) + unlink (fullfile (pack.name, "inst","packinfo", ".autoload")); + endif + rmdir (fullfile (pack.name, "inst", "packinfo")); + if (exist (fullfile (pack.name, "inst", "doc"), "dir")) + movefile (fullfile (pack.name, "inst", "doc"), pack.name); + endif + if (exist (fullfile (pack.name, "inst", "bin"), "dir")) + movefile (fullfile (pack.name, "inst", "bin"), pack.name); + endif + archdir = fullfile (pack.archprefix, cstrcat (pack.name, "-", + pack.version), getarch ()); + if (exist (archdir, "dir")) + if (exist (fullfile (pack.name, "inst", "PKG_ADD"), "file")) + unlink (fullfile (pack.name, "inst", "PKG_ADD")); + endif + if (exist (fullfile (pack.name, "inst", "PKG_DEL"), "file")) + unlink (fullfile (pack.name, "inst", "PKG_DEL")); + endif + if (exist (fullfile (archdir, "PKG_ADD"), "file")) + movefile (fullfile (archdir, "PKG_ADD"), + fullfile (pack.name, "PKG_ADD")); + endif + if (exist (fullfile (archdir, "PKG_DEL"), "file")) + movefile (fullfile (archdir, "PKG_DEL"), + fullfile (pack.name, "PKG_DEL")); + endif + else + if (exist (fullfile (pack.name, "inst", "PKG_ADD"), "file")) + movefile (fullfile (pack.name, "inst", "PKG_ADD"), + fullfile (pack.name, "PKG_ADD")); + endif + if (exist (fullfile (pack.name, "inst", "PKG_DEL"), "file")) + movefile (fullfile (pack.name, "inst", "PKG_DEL"), + fullfile (pack.name, "PKG_DEL")); + endif + endif + tfile = cstrcat (pack.name, "-", pack.version, ".tar"); + tar (tfile, pack.name); + try + gzip (tfile); + unlink (tfile); + catch + warning ("failed to compress %s", tfile); + end_try_catch + unwind_protect_cleanup + if (exist (pack.name, "dir")) + rm_rf (pack.name); + endif + cd (wd); + end_unwind_protect + endfor +endfunction + diff -r bec37a92cb3b -r 0fab7b9e6226 scripts/pkg/private/rm_rf.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/pkg/private/rm_rf.m Thu Mar 15 11:40:01 2012 +0100 @@ -0,0 +1,41 @@ +## Copyright (C) 2005-2012 S�ren Hauberg +## Copyright (C) 2010 VZLU Prague, a.s. +## +## This file is part of Octave. +## +## Octave is free software; you can redistribute it and/or modify it +## under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 3 of the License, or (at +## your option) any later version. +## +## Octave is distributed in the hope that it will be useful, but +## WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with Octave; see the file COPYING. If not, see +## . + +## -*- texinfo -*- +## @deftypefn {Function File} address@hidden, @var{msg_out}] =}@ +## rm_rf (@var{dir}) +## Undocumented internal function. +## @end deftypefn + +function [status_out, msg_out] = rm_rf (dir) + if (exist (dir)) + crr = confirm_recursive_rmdir (false, "local"); + [status, msg] = rmdir (dir, "s"); + else + status = 1; + msg = ""; + endif + if (nargout > 0) + status_out = status; + endif + if (nargout > 1) + msg_out = msg; + endif +endfunction + diff -r bec37a92cb3b -r 0fab7b9e6226 scripts/pkg/private/rstrip.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/pkg/private/rstrip.m Thu Mar 15 11:40:01 2012 +0100 @@ -0,0 +1,37 @@ +## Copyright (C) 2005-2012 S�ren Hauberg +## Copyright (C) 2010 VZLU Prague, a.s. +## +## This file is part of Octave. +## +## Octave is free software; you can redistribute it and/or modify it +## under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 3 of the License, or (at +## your option) any later version. +## +## Octave is distributed in the hope that it will be useful, but +## WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with Octave; see the file COPYING. If not, see +## . + +## -*- texinfo -*- +## @deftypefn {Function File} address@hidden =} rstrip (@var{text}) +## Undocumented internal function. +## @end deftypefn + +## Strip the text of spaces from the right +## Example: " hello world " => " hello world" +## FIXME -- is this the same as deblank? +function text = rstrip (text) + chars = find (! isspace (text)); + if (length (chars) > 0) + ## FIXME: shouldn't it be text = text(1:chars(end)); + text = text (chars(1):end); + else + text = ""; + endif +endfunction + diff -r bec37a92cb3b -r 0fab7b9e6226 scripts/pkg/private/save_order.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/pkg/private/save_order.m Thu Mar 15 11:40:01 2012 +0100 @@ -0,0 +1,60 @@ +## Copyright (C) 2005-2012 S�ren Hauberg +## Copyright (C) 2010 VZLU Prague, a.s. +## +## This file is part of Octave. +## +## Octave is free software; you can redistribute it and/or modify it +## under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 3 of the License, or (at +## your option) any later version. +## +## Octave is distributed in the hope that it will be useful, but +## WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with Octave; see the file COPYING. If not, see +## . + +## -*- texinfo -*- +## @deftypefn {Function File} address@hidden = } save_order (@var{desc}) +## Undocumented internal function. +## @end deftypefn + +function newdesc = save_order (desc) + newdesc = {}; + for i = 1 : length(desc) + deps = desc{i}.depends; + if (isempty (deps) + || (length (deps) == 1 && strcmp(deps{1}.package, "octave"))) + newdesc {end + 1} = desc{i}; + else + tmpdesc = {}; + for k = 1 : length (deps) + for j = 1 : length (desc) + if (strcmp (desc{j}.name, deps{k}.package)) + tmpdesc{end+1} = desc{j}; + break; + endif + endfor + endfor + if (! isempty (tmpdesc)) + newdesc = {newdesc{:}, save_order(tmpdesc){:}, desc{i}}; + else + newdesc{end+1} = desc{i}; + endif + endif + endfor + ## Eliminate the duplicates. + idx = []; + for i = 1 : length (newdesc) + for j = (i + 1) : length (newdesc) + if (strcmp (newdesc{i}.name, newdesc{j}.name)) + idx (end + 1) = j; + endif + endfor + endfor + newdesc(idx) = []; +endfunction + diff -r bec37a92cb3b -r 0fab7b9e6226 scripts/pkg/private/shell.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/pkg/private/shell.m Thu Mar 15 11:40:01 2012 +0100 @@ -0,0 +1,46 @@ +## Copyright (C) 2005-2012 S�ren Hauberg +## Copyright (C) 2010 VZLU Prague, a.s. +## +## This file is part of Octave. +## +## Octave is free software; you can redistribute it and/or modify it +## under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 3 of the License, or (at +## your option) any later version. +## +## Octave is distributed in the hope that it will be useful, but +## WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with Octave; see the file COPYING. If not, see +## . + +## -*- texinfo -*- +## @deftypefn {Function File} address@hidden, @var{output}] =} shell (@var{cmd}) +## Undocumented internal function. +## @end deftypefn + +function [status, output] = shell (cmd) + persistent have_sh; + + cmd = strrep (cmd, "\\", "/"); + if (ispc () && ! isunix ()) + if (isempty(have_sh)) + if (system("sh.exe -c \"exit\"")) + have_sh = false; + else + have_sh = true; + endif + endif + if (have_sh) + [status, output] = system (cstrcat ("sh.exe -c \"", cmd, "\"")); + else + error ("Can not find the command shell"); + endif + else + [status, output] = system (cmd); + endif +endfunction + diff -r bec37a92cb3b -r 0fab7b9e6226 scripts/pkg/private/split_by.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/pkg/private/split_by.m Thu Mar 15 11:40:01 2012 +0100 @@ -0,0 +1,30 @@ +## Copyright (C) 2005-2012 S�ren Hauberg +## Copyright (C) 2010 VZLU Prague, a.s. +## +## This file is part of Octave. +## +## Octave is free software; you can redistribute it and/or modify it +## under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 3 of the License, or (at +## your option) any later version. +## +## Octave is distributed in the hope that it will be useful, but +## WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with Octave; see the file COPYING. If not, see +## . + +## -*- texinfo -*- +## @deftypefn {Function File} address@hidden =} split_by (@var{text}, @var{sep}) +## Undocumented internal function. +## @end deftypefn + +## Split the text into a cell array of strings by sep. +## Example: "A, B" => {"A", "B"} (with sep = ",") +function out = split_by (text, sep) + out = strtrim (strsplit (text, sep)); +endfunction + diff -r bec37a92cb3b -r 0fab7b9e6226 scripts/pkg/private/strip.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/pkg/private/strip.m Thu Mar 15 11:40:01 2012 +0100 @@ -0,0 +1,36 @@ +## Copyright (C) 2005-2012 S�ren Hauberg +## Copyright (C) 2010 VZLU Prague, a.s. +## +## This file is part of Octave. +## +## Octave is free software; you can redistribute it and/or modify it +## under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 3 of the License, or (at +## your option) any later version. +## +## Octave is distributed in the hope that it will be useful, but +## WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with Octave; see the file COPYING. If not, see +## . + +## -*- texinfo -*- +## @deftypefn {Function File} {text =} strip (@var{text}) +## Undocumented internal function. +## @end deftypefn + + +## Strip the text of spaces from the left and the right. +## Example: " hello world " => "hello world" +function text = strip (text) + chars = find (! isspace (text)); + if (length (chars) > 0) + text = text(chars(1):chars(end)); + else + text = ""; + endif +endfunction + diff -r bec37a92cb3b -r 0fab7b9e6226 scripts/pkg/private/uninstall.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/pkg/private/uninstall.m Thu Mar 15 11:40:01 2012 +0100 @@ -0,0 +1,148 @@ +## Copyright (C) 2005-2012 S�ren Hauberg +## Copyright (C) 2010 VZLU Prague, a.s. +## +## This file is part of Octave. +## +## Octave is free software; you can redistribute it and/or modify it +## under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 3 of the License, or (at +## your option) any later version. +## +## Octave is distributed in the hope that it will be useful, but +## WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with Octave; see the file COPYING. If not, see +## . + +## -*- texinfo -*- +## @deftypefn {Function File} {} uninstall (@var{pkgnames}, @var{handle_deps}, +## @var{verbose}, @var{local_list}, @var{global_list}, @var{global_install}) +## Undocumented internal function. +## @end deftypefn + +function uninstall (pkgnames, handle_deps, verbose, local_list, + global_list, global_install) + ## Get the list of installed packages. + [local_packages, global_packages] = installed_packages(local_list, + global_list); + if (global_install) + installed_pkgs_lst = {local_packages{:}, global_packages{:}}; + else + installed_pkgs_lst = local_packages; + endif + + num_packages = length (installed_pkgs_lst); + delete_idx = []; + for i = 1:num_packages + cur_name = installed_pkgs_lst{i}.name; + if (any (strcmp (cur_name, pkgnames))) + delete_idx(end+1) = i; + endif + endfor + + ## Are all the packages that should be uninstalled already installed? + if (length (delete_idx) != length (pkgnames)) + if (global_install) + ## Try again for a locally installed package. + installed_pkgs_lst = local_packages; + + num_packages = length (installed_pkgs_lst); + delete_idx = []; + for i = 1:num_packages + cur_name = installed_pkgs_lst{i}.name; + if (any (strcmp (cur_name, pkgnames))) + delete_idx(end+1) = i; + endif + endfor + if (length (delete_idx) != length (pkgnames)) + ## FIXME: We should have a better error message. + warning ("some of the packages you want to uninstall are not installed"); + endif + else + ## FIXME: We should have a better error message. + warning ("some of the packages you want to uninstall are not installed"); + endif + endif + + ## Compute the packages that will remain installed. + idx = setdiff (1:num_packages, delete_idx); + remaining_packages = {installed_pkgs_lst{idx}}; + + ## Check dependencies. + if (handle_deps) + error_text = ""; + for i = 1:length (remaining_packages) + desc = remaining_packages{i}; + bad_deps = get_unsatisfied_deps (desc, remaining_packages); + + ## Will the uninstallation break any dependencies? + if (! isempty (bad_deps)) + for i = 1:length (bad_deps) + dep = bad_deps{i}; + error_text = cstrcat (error_text, " ", desc.name, " needs ", + dep.package, " ", dep.operator, " ", + dep.version, "\n"); + endfor + endif + endfor + + if (! isempty (error_text)) + error ("the following dependencies where unsatisfied:\n %s", error_text); + endif + endif + + ## Delete the directories containing the packages. + for i = delete_idx + desc = installed_pkgs_lst{i}; + ## If an 'on_uninstall.m' exist, call it! + if (exist (fullfile (desc.dir, "packinfo", "on_uninstall.m"), "file")) + wd = pwd (); + cd (fullfile (desc.dir, "packinfo")); + on_uninstall (desc); + cd (wd); + endif + ## Do the actual deletion. + if (desc.loaded) + rmpath (desc.dir); + if (exist (getarchdir (desc))) + rmpath (getarchdir (desc)); + endif + endif + if (exist (desc.dir, "dir")) + [status, msg] = rm_rf (desc.dir); + if (status != 1) + error ("couldn't delete directory %s: %s", desc.dir, msg); + endif + [status, msg] = rm_rf (getarchdir (desc)); + if (status != 1) + error ("couldn't delete directory %s: %s", getarchdir (desc), msg); + endif + if (dirempty (desc.archprefix)) + rm_rf (desc.archprefix); + endif + else + warning ("directory %s previously lost", desc.dir); + endif + endfor + + ## Write a new ~/.octave_packages. + if (global_install) + if (length (remaining_packages) == 0) + unlink (global_list); + else + global_packages = save_order (remaining_packages); + save (global_list, "global_packages"); + endif + else + if (length (remaining_packages) == 0) + unlink (local_list); + else + local_packages = save_order (remaining_packages); + save (local_list, "local_packages"); + endif + endif + +endfunction diff -r bec37a92cb3b -r 0fab7b9e6226 scripts/pkg/private/unload_packages.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/pkg/private/unload_packages.m Thu Mar 15 11:40:01 2012 +0100 @@ -0,0 +1,82 @@ +## Copyright (C) 2005-2012 S�ren Hauberg +## Copyright (C) 2010 VZLU Prague, a.s. +## +## This file is part of Octave. +## +## Octave is free software; you can redistribute it and/or modify it +## under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 3 of the License, or (at +## your option) any later version. +## +## Octave is distributed in the hope that it will be useful, but +## WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with Octave; see the file COPYING. If not, see +## . + +## -*- texinfo -*- +## @deftypefn {Function File} {} unload_packages (@var{files},@ +## @var{handle_deps}, @var{local_list}, @{global_list}) +## Undocumented internal function. +## @end deftypefn + +function unload_packages (files, handle_deps, local_list, global_list) + installed_pkgs_lst = installed_packages (local_list, global_list); + num_packages = length (installed_pkgs_lst); + + ## Read package names and installdirs into a more convenient format. + pnames = pdirs = cell (1, num_packages); + for i = 1:num_packages + pnames{i} = installed_pkgs_lst{i}.name; + pdirs{i} = installed_pkgs_lst{i}.dir; + pdeps{i} = installed_pkgs_lst{i}.depends; + endfor + + ## Get the current octave path. + p = split_by (path(), pathsep ()); + + if (length (files) == 1 && strcmp (files{1}, "all")) + ## Unload all. + dirs = pdirs; + desc = installed_pkgs_lst; + else + ## Unload package_name1 ... + dirs = {}; + desc = {}; + for i = 1:length (files) + idx = strcmp (pnames, files{i}); + if (! any (idx)) + error ("package %s is not installed", files{i}); + endif + dirs{end+1} = pdirs{idx}; + desc{end+1} = installed_pkgs_lst{idx}; + endfor + endif + + ## Check for architecture dependent directories. + archdirs = {}; + for i = 1:length (dirs) + tmpdir = getarchdir (desc{i}); + if (exist (tmpdir, "dir")) + archdirs{end+1} = dirs{i}; + archdirs{end+1} = tmpdir; + else + archdirs{end+1} = dirs{i}; + endif + endfor + + ## Unload the packages. + for i = 1:length (archdirs) + d = archdirs{i}; + idx = strcmp (p, d); + if (any (idx)) + rmpath (d); + ## FIXME: We should also check if we need to remove items from + ## EXEC_PATH. + endif + endfor +endfunction + diff -r bec37a92cb3b -r 0fab7b9e6226 scripts/pkg/private/verify_directory.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/pkg/private/verify_directory.m Thu Mar 15 11:40:01 2012 +0100 @@ -0,0 +1,34 @@ +## Copyright (C) 2005-2012 S�ren Hauberg +## Copyright (C) 2010 VZLU Prague, a.s. +## +## This file is part of Octave. +## +## Octave is free software; you can redistribute it and/or modify it +## under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 3 of the License, or (at +## your option) any later version. +## +## Octave is distributed in the hope that it will be useful, but +## WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with Octave; see the file COPYING. If not, see +## . + +## -*- texinfo -*- +## @deftypefn {Function File} {} verify_directory (@var{dir}) +## Undocumented internal function. +## @end deftypefn + +## Make sure the package contains the essential files. +function verify_directory (dir) + needed_files = {"COPYING", "DESCRIPTION"}; + for f = needed_files + if (! exist (fullfile (dir, f{1}), "file")) + error ("package is missing file: %s", f{1}); + endif + endfor +endfunction + diff -r bec37a92cb3b -r 0fab7b9e6226 scripts/pkg/private/write_index.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/pkg/private/write_index.m Thu Mar 15 11:40:01 2012 +0100 @@ -0,0 +1,93 @@ +## Copyright (C) 2005-2012 S�ren Hauberg +## Copyright (C) 2010 VZLU Prague, a.s. +## +## This file is part of Octave. +## +## Octave is free software; you can redistribute it and/or modify it +## under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 3 of the License, or (at +## your option) any later version. +## +## Octave is distributed in the hope that it will be useful, but +## WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with Octave; see the file COPYING. If not, see +## . + +## -*- texinfo -*- +## @deftypefn {Function File} {} write_index (@var{desc}, @var{dir},@ +## @var{index_file}, @var{global_install}) +## Undocumented internal function. +## @end deftypefn + +## Create an INDEX file for a package that doesn't provide one. +## 'desc' describes the package. +## 'dir' is the 'inst' directory in temporary directory. +## 'index_file' is the name (including path) of resulting INDEX file. + +function write_index (desc, dir, index_file, global_install) + ## Get names of functions in dir + [files, err, msg] = readdir (dir); + if (err) + error ("couldn't read directory %s: %s", dir, msg); + endif + + ## Get classes in dir + class_idx = find (strncmp (files, '@', 1)); + for k = 1:length (class_idx) + class_name = files {class_idx (k)}; + class_dir = fullfile (dir, class_name); + if (exist (class_dir, "dir")) + [files2, err, msg] = readdir (class_dir); + if (err) + error ("couldn't read directory %s: %s", class_dir, msg); + endif + files2 = strcat (class_name, filesep (), files2); + files = [files; files2]; + endif + endfor + + ## Check for architecture dependent files. + tmpdir = getarchdir (desc); + if (exist (tmpdir, "dir")) + [files2, err, msg] = readdir (tmpdir); + if (err) + error ("couldn't read directory %s: %s", tmpdir, msg); + endif + files = [files; files2]; + endif + + functions = {}; + for i = 1:length (files) + file = files{i}; + lf = length (file); + if (lf > 2 && strcmp (file(end-1:end), ".m")) + functions{end+1} = file(1:end-2); + elseif (lf > 4 && strcmp (file(end-3:end), ".oct")) + functions{end+1} = file(1:end-4); + endif + endfor + + ## Does desc have a categories field? + if (! isfield (desc, "categories")) + error ("the DESCRIPTION file must have a Categories field, when no INDEX file is given"); + endif + categories = split_by (desc.categories, ","); + if (length (categories) < 1) + error ("the Category field is empty"); + endif + + ## Write INDEX. + fid = fopen (index_file, "w"); + if (fid == -1) + error ("couldn't open %s for writing", index_file); + endif + fprintf (fid, "%s >> %s\n", desc.name, desc.title); + fprintf (fid, "%s\n", categories{1}); + fprintf (fid, " %s\n", functions{:}); + fclose (fid); +endfunction +