changeset 29467:280defaf2023

pkg.m: Install local packages in version dependent path (bug #58299). * scripts/pkg/pkg.m: Store local package list in (platform-specific) version dependent path. * scripts/pkg/private/default_prefix.m: Change the default local package installation location to a (platform-specific) version dependent path. * doc/interpreter/package.txi: Adapt documentation. * scripts/pkg/private/install.m: Create directory for local package list if it doesn't exist yet. * libinterp/corefcn/toplev.cc (__octave_config_info__): Add OCTAVE_MAJOR_VERSION, OCTAVE_MINOR_VERSION, and OCTAVE_PATCH_VERSION to output. * libinterp/corefcn/defaults.cc (Fuser_config_dir, Fuser_data_dir): Add new functions to query platform-specific path for user data and user configuration files. * doc/interpreter/system.txi: Add docstrings of new functions to manual.
author Markus Mützel <markus.muetzel@gmx.de>
date Sun, 21 Mar 2021 18:10:14 +0100
parents df641f946202
children 09767c20dec9
files doc/interpreter/package.txi doc/interpreter/system.txi libinterp/corefcn/defaults.cc libinterp/corefcn/toplev.cc scripts/pkg/pkg.m scripts/pkg/private/default_prefix.m scripts/pkg/private/install.m
diffstat 7 files changed, 82 insertions(+), 22 deletions(-) [+]
line wrap: on
line diff
--- a/doc/interpreter/package.txi	Mon Mar 22 21:09:04 2021 +1100
+++ b/doc/interpreter/package.txi	Sun Mar 21 18:10:14 2021 +0100
@@ -135,16 +135,18 @@
 @node Administrating Packages
 @section Administrating Packages
 
-On UNIX-like systems it is possible to make both per-user and
-system-wide installations of a package.  If the user performing the
-installation is @code{root} the packages will be installed in a
-system-wide directory that defaults to
-@file{OCTAVE_HOME/share/octave/packages/}.  If the user is not
-@code{root} the default installation directory is
-@file{~/octave/}.  Packages will be installed in a subdirectory of the
-installation directory that will be named after the package.  It is
-possible to change the installation directory by using the
-@code{pkg prefix} command
+It is possible to make both per-user (local) and system-wide (global)
+installations of a package.  If the user performing the installation is
+@code{root} (or Administrator with elevated rights on Windows), the
+packages by default install in a system-wide directory that defaults to
+@file{@var{OCTAVE_HOME}/share/octave/packages/}.  If the user is not
+@code{root} (or without elevated rights), packages are installed
+locally.  The default installation directory for local packages is
+@file{@var{user_data_dir}/octave/@var{OCTAVE_MAJOR_VERSION}/packages}.
+Packages will be installed in a subdirectory of the installation
+directory that will be named after the package.  It is possible to
+change the installation directory by using the @code{pkg prefix}
+command:
 
 @example
 pkg prefix new_installation_directory
@@ -157,21 +159,24 @@
 current_installation_directory = pkg ("prefix")
 @end example
 
-To function properly the package manager needs to keep some
-information about the installed packages.  For per-user packages this
-information is by default stored in the file @file{~/.octave_packages}
-and for system-wide installations it is stored in
-@file{OCTAVE_HOME/share/octave/octave_packages}.  The path to the
-per-user file can be changed with the @code{pkg local_list} command
+The package manager stores some information about the installed
+packages in configuration files.  For per-user (local) packages, this
+information is stored in the file
+@file{@var{user_config_dir}/octave/@var{OCTAVE_MAJOR_VERSION}/octave_packages}
+by default.  For system-wide (global) installations, it is stored in
+@file{@var{OCTAVE_HOME}/share/octave/octave_packages}.  The path to the
+per-user file can be changed with the @code{pkg local_list} command:
 
 @example
 pkg local_list /path/to/new_file
 @end example
 
 @noindent
-For system-wide installations this can be changed in the same way
-using the @code{pkg global_list} command.  If these commands are
-called without a new path, the current path will be returned.
+For system-wide installations, this can be changed in the same way
+using the @code{pkg global_list} command.  If these commands are called
+without a new path, the current path will be returned.  To retain these
+settings between sessions, they can be set in one of the startup files,
+see @ref{Startup Files}.
 
 @node Creating Packages
 @section Creating Packages
--- a/doc/interpreter/system.txi	Mon Mar 22 21:09:04 2021 +1100
+++ b/doc/interpreter/system.txi	Sun Mar 21 18:10:14 2021 +0100
@@ -546,6 +546,10 @@
 
 @DOCSTRING(matlabroot)
 
+@DOCSTRING(user_config_dir)
+
+@DOCSTRING(user_data_dir)
+
 @DOCSTRING(OCTAVE_VERSION)
 
 @DOCSTRING(version)
--- a/libinterp/corefcn/defaults.cc	Mon Mar 22 21:09:04 2021 +1100
+++ b/libinterp/corefcn/defaults.cc	Sun Mar 21 18:10:14 2021 +0100
@@ -507,3 +507,40 @@
 %!assert (ischar (OCTAVE_VERSION ()))
 %!error OCTAVE_VERSION (1)
 */
+
+DEFUN (user_config_dir, args, ,
+       doc: /* -*- texinfo -*-
+@deftypefn {} {cfg_dir = } user_config_dir ()
+Return the (platform-specific) directory for user configuration.
+@seealso{user_data_dir}
+@end deftypefn */)
+{
+  if (args.length () != 0)
+    print_usage ();
+
+  return ovl (octave::sys::env::get_user_config_directory ());
+}
+
+/*
+%!assert (ischar (user_config_dir ()))
+%!error user_config_dir (1)
+*/
+
+DEFUN (user_data_dir, args, ,
+       doc: /* -*- texinfo -*-
+@deftypefn {} {data_dir = } user_data_dir ()
+Return the (platform-specific) directory for user data.
+@seealso{user_config_dir}
+@end deftypefn */)
+{
+  if (args.length () != 0)
+    print_usage ();
+
+  return ovl (octave::sys::env::get_user_data_directory ());
+}
+
+/*
+%!assert (ischar (user_data_dir ()))
+%!error user_data_dir (1)
+*/
+
--- a/libinterp/corefcn/toplev.cc	Mon Mar 22 21:09:04 2021 +1100
+++ b/libinterp/corefcn/toplev.cc	Sun Mar 21 18:10:14 2021 +0100
@@ -72,6 +72,9 @@
 #  define SHELL_PATH "/bin/sh"
 #endif
 
+#define STRINGIFY(s) STRINGIFY1(s)
+#define STRINGIFY1(s) #s
+
 DEFUN (warranty, , ,
        doc: /* -*- texinfo -*-
 @deftypefn {} {} warranty ()
@@ -423,9 +426,11 @@
            { "localverarchlibdir", octave::config::local_ver_arch_lib_dir () },
            { "localverfcnfiledir", octave::config::local_ver_fcn_file_dir () },
            { "localveroctfiledir", octave::config::local_ver_oct_file_dir () },
+           { "major_version", STRINGIFY (OCTAVE_MAJOR_VERSION) },
            { "man1dir", octave::config::man1_dir () },
            { "man1ext", octave::config::man1_ext () },
            { "mandir", octave::config::man_dir () },
+           { "minor_version", STRINGIFY (OCTAVE_MINOR_VERSION) },
            { "octdatadir", octave::config::oct_data_dir () },
            { "octdocdir", octave::config::oct_doc_dir () },
            { "octetcdir", octave::config::oct_etc_dir () },
@@ -434,6 +439,7 @@
            { "octincludedir", octave::config::oct_include_dir () },
            { "octlibdir", octave::config::oct_lib_dir () },
            { "octtestsdir", octave::config::oct_tests_dir () },
+           { "patch_version", STRINGIFY (OCTAVE_PATCH_VERSION) },
            { "release_date", OCTAVE_RELEASE_DATE },
            { "startupfiledir", octave::config::startupfile_dir () },
            { "version", OCTAVE_VERSION }};
--- a/scripts/pkg/pkg.m	Mon Mar 22 21:09:04 2021 +1100
+++ b/scripts/pkg/pkg.m	Sun Mar 21 18:10:14 2021 +0100
@@ -384,8 +384,10 @@
   persistent user_prefix = false;
   persistent prefix = false;
   persistent archprefix = -1;
-  persistent local_list = tilde_expand (fullfile ("~", ".octave_packages"));
-  persistent global_list = fullfile (OCTAVE_HOME (), "share", "octave",
+  persistent local_list = fullfile (user_config_dir (), "octave", ...
+                                    __octave_config_info__ ("major_version"), ...
+                                    "octave_packages");
+  persistent global_list = fullfile (OCTAVE_HOME (), "share", "octave", ...
                                      "octave_packages");
 
   ## If user is superuser (posix) or the process has elevated rights (Windows),
--- a/scripts/pkg/private/default_prefix.m	Mon Mar 22 21:09:04 2021 +1100
+++ b/scripts/pkg/private/default_prefix.m	Sun Mar 21 18:10:14 2021 +0100
@@ -41,7 +41,8 @@
                              "packages");
     endif
   else
-    prefix = tilde_expand (fullfile ("~", "octave"));
+    prefix = fullfile (user_data_dir (), "octave", ...
+                       __octave_config_info__ ("major_version"), "packages");
     archprefix = prefix;
   endif
 
--- a/scripts/pkg/private/install.m	Mon Mar 22 21:09:04 2021 +1100
+++ b/scripts/pkg/private/install.m	Sun Mar 21 18:10:14 2021 +0100
@@ -282,6 +282,11 @@
       if (ispc)
         local_packages = standardize_paths (local_packages);
       endif
+      if (! exist (fileparts (local_list), "dir")
+          && ! mkdir (fileparts (local_list)))
+        error ("Octave:pkg:install:local-dir", ...
+               "pkg: Could not create directory for local package configuration");
+      endif
       save (local_list, "local_packages");
       installed_pkgs_lst = {local_packages{:}, global_packages{:}};
     endif