octave-maintainers
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Making forge-packages installation relocatable


From: Benjamin Lindner
Subject: Making forge-packages installation relocatable
Date: Tue, 27 Oct 2009 22:10:47 +0100
User-agent: Thunderbird 2.0.0.22 (Windows/20090605)

Hello all,

One item on my personal todo list for octave has long been to make the octave forge package installation via pkg.m relocatable, i.e. allowing an installed octave directory structure to be moved elsewhere and having everything work as before (thus making octave a truly portable application).

Currently this works for octave itself, but not if forge packages are installed.

This is, because installed packages are referred to by their absolute path at the time of installation. My idea is to remove the absolute path and store only the package's actual subdirectory and restore the absolute path at runtime based on OCTAVE_HOME().

Thinking about it I realised that this makes sense only for globally installed packages - not locally installed ones.

I have attached a first attempt to achieve this.

I'm not entirely satisified by the solution, but it is a first attempt and it does work for me for octave-3.2.3 on windows.

comments and suggestions are very welcome.

I see that the package list structure contains actually two directory paths:
 .dir
 .archprefix

In the attached patch I actually only deal with the .dir field, by creating a new function getdir() (similar to getarchdir()) and replacing all explicit references to the field .dir by a call to this new function.

The situation with .archprefix is different, as currently, this field is not referenced directly, rather than through the function getsrchdir(). So I modified this function to generate the actual absolute path at runtime.

But actually the field .archprefix is redundant, because this directory can be (and is) created from the package's description and version at runtime, so couldn't it be removed anyway?

benjamin
diff -r d5ba49ddea77 scripts/pkg/pkg.m
--- a/scripts/pkg/pkg.m Sun Oct 25 19:31:34 2009 +0100
+++ b/scripts/pkg/pkg.m Tue Oct 27 21:50:50 2009 +0100
@@ -205,7 +205,7 @@
                                     "octave_packages");
   mlock ();
 
-  global_install = issuperuser ();
+  global_install = issuperuser ()
 
   if (prefix == -1)
     if (global_install)
@@ -370,7 +370,7 @@
     case "rebuild"
       if (global_install)
        global_packages = rebuild (prefix, archprefix, global_list, files, 
-                                  auto, verbose);
+                                  auto, verbose, global_install);
        global_packages = save_order (global_packages);
        save (global_list, "global_packages");
        if (nargout > 0)
@@ -378,7 +378,7 @@
        endif
       else
        local_packages = rebuild (prefix, archprefix, local_list, files, auto, 
-                                 verbose);
+                                 verbose, global_install);
        local_packages = save_order (local_packages);
        save (local_list, "local_packages");
        if (nargout == 0)
@@ -419,7 +419,7 @@
   endswitch
 endfunction
 
-function descriptions = rebuild (prefix, archprefix, list, files, auto, 
verbose)
+function descriptions = rebuild (prefix, archprefix, list, files, auto, 
verbose, global_install)
   if (isempty (files))
     [dirlist, err, msg] = readdir (prefix);
     if (err)
@@ -445,21 +445,27 @@
     endif
     if (exist (descfile, "file"))
       desc = get_description (descfile);
-      desc.dir = fullfile (prefix, dirlist{k});
+      if (global_install)
+       desc.dir = dirlist{k};
+       desc.dir_is_relative = true;
+      else
+       desc.dir = fullfile (prefix, dirlist{k});
+       desc.dir_is_relative = false;
+      endif
       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"));
+       if (exist (fullfile (getdir (desc), "packinfo", ".autoload"), "file"))
+         unlink (fullfile (getdir (desc), "packinfo", ".autoload"));
        endif
         if (auto < 0)
          desc.autoload = 0;
        elseif (auto > 0)
          desc.autoload = 1;
-         fclose (fopen (fullfile (desc.dir, "packinfo", ".autoload"), "wt"));
+         fclose (fopen (fullfile (getdir (desc), "packinfo", ".autoload"), 
"wt"));
        endif
       else
-       if (exist (fullfile (desc.dir, "packinfo", ".autoload"), "file"))
+       if (exist (fullfile (getdir (desc), "packinfo", ".autoload"), "file"))
          desc.autoload = 1;
        else
          desc.autoload = 0;
@@ -632,7 +638,13 @@
        endif
        
        ## Set default installation directory.
-       desc.dir = fullfile (prefix, cstrcat (desc.name, "-", desc.version));
+       if (global_install)
+           desc.dir = cstrcat (desc.name, "-", desc.version);
+           desc.dir_is_relative = true;
+       else
+           desc.dir = fullfile (prefix, cstrcat (desc.name, "-", 
desc.version));
+           desc.dir_is_relative = false;
+       endif
        
        ## Set default architectire dependent installation directory.
        desc.archprefix = fullfile (archprefix, cstrcat (desc.name, "-",
@@ -750,7 +762,7 @@
       rm_rf (tmpdirs{i});
     endfor
     for i = 1:length (descriptions)
-      rm_rf (descriptions{i}.dir);
+      rm_rf (getdir (descriptions{i}.dir));
       rm_rf (getarchdir (descriptions{i}));
     endfor
     rethrow (lasterror ());
@@ -759,10 +771,11 @@
   ## 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"}) &&
+    descriptions{i}
+    if (dirempty (getdir (descriptions{i}), {"packinfo", "doc"}) &&
        dirempty (getarchdir (descriptions{i})))
       warning ("package %s is empty\n", descriptions{i}.name);
-      rm_rf (descriptions{i}.dir);
+      rm_rf (getdir (descriptions{i}));
       rm_rf (getarchdir (descriptions{i}));
       descriptions(i) = [];
     endif
@@ -771,8 +784,9 @@
   ## 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
+    disp(descriptions{i})
     if (autoload > 0 || (autoload == 0 && isautoload (descriptions(i))))
-      fclose (fopen (fullfile (descriptions{i}.dir, "packinfo", 
+      fclose (fopen (fullfile (getdir (descriptions{i}), "packinfo", 
                               ".autoload"), "wt"));
       descriptions{i}.autoload = 1;
     endif
@@ -797,7 +811,7 @@
       rm_rf (tmpdirs{i});
     endfor
     for i = 1:length (descriptions)
-      rm_rf (descriptions{i}.dir);
+      rm_rf (getdir (descriptions{i}));
     endfor
     if (global_install)
       printf ("error: couldn't append to %s\n", global_list);
@@ -910,23 +924,23 @@
   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"))
+    if (exist (fullfile (getdir (desc), "packinfo", "on_uninstall.m"), "file"))
       wd = pwd ();
-      cd (fullfile (desc.dir, "packinfo"));
+      cd (fullfile (getdir (desc), "packinfo"));
       on_uninstall (desc);
       cd (wd);
     endif
     ## Do the actual deletion.
     if (desc.loaded)
-      rmpath (desc.dir);
+      rmpath (getdir (desc));
       if (exist (getarchdir (desc)))
        rmpath (getarchdir (desc));
       endif
     endif
-    if (exist (desc.dir, "dir"))
-      [status, msg] = rm_rf (desc.dir);
+    if (exist (getdir (desc), "dir"))
+      [status, msg] = rm_rf (getdir (desc));
       if (status != 1)
-       error ("couldn't delete directory %s: %s", desc.dir, msg);
+       error ("couldn't delete directory %s: %s", getdir (desc), msg);
       endif
       [status, msg] = rm_rf (getarchdir (desc));
       if (status != 1)
@@ -936,7 +950,7 @@
        rm_rf (desc.archprefix);
       endif
     else
-      warning ("directory %s previously lost", desc.dir);
+      warning ("directory %s previously lost", getdir (desc));
     endif
   endfor
 
@@ -995,7 +1009,7 @@
       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);
+      pkg_desc_list{name_pos}.provides = parse_pkg_idx (getdir 
(installed_pkgs_lst{i}));
 
     endif
   endfor
@@ -1207,7 +1221,7 @@
   if (! exist (inst_dir, "dir"))
     [status, msg] = mkdir (inst_dir);
     if (status != 1)
-      rm_rf (desc.dir);
+      rm_rf (getdir (desc));
       error ("the 'inst' directory did not exist and could not be created: 
%s", 
             msg);
     endif
@@ -1236,9 +1250,9 @@
       flags = strcat( flags, " LDFLAGS=-L\"", fullfile(OCTAVE_HOME,"lib"), 
"\"" );
       flags = strcat( flags, " CPPFLAGS=-I\"", 
fullfile(OCTAVE_HOME,"include"), "\"" );
       [status, output] = shell (strcat ("cd '", src, "'; ./configure 
--prefix=\"",
-                                        desc.dir, "\"", flags));
+                                        getdir (desc), "\"", flags));
       if (status != 0)
-       rm_rf (desc.dir);
+       rm_rf (getdir (desc));
        error ("the configure script returned the following error: %s", output);
       elseif (verbose)
        printf("%s", output);
@@ -1248,10 +1262,10 @@
 
     ## Make.
     if (exist (fullfile (src, "Makefile"), "file"))
-      [status, output] = shell (cstrcat ("export INSTALLDIR=\"", desc.dir,
+      [status, output] = shell (cstrcat ("export INSTALLDIR=\"", getdir (desc),
                                         "\"; make -C '", src, "'"));
       if (status != 0)
-       rm_rf (desc.dir);
+       rm_rf (getdir (desc));
        error ("'make' returned the following error: %s", output);
       elseif (verbose)
        printf("%s", output);
@@ -1317,7 +1331,7 @@
          endif
          [status, output] = copyfile (archindependent, instdir);
          if (status != 1)
-           rm_rf (desc.dir);
+           rm_rf (getdir (desc));
            error ("Couldn't copy files from 'src' to 'inst': %s", output);
          endif
         endif
@@ -1332,7 +1346,7 @@
          endif
          [status, output] = copyfile (archdependent, archdir);
          if (status != 1)
-           rm_rf (desc.dir);
+           rm_rf (getdir (desc));
            error ("Couldn't copy files from 'src' to 'inst': %s", output);
          endif
         endif
@@ -1361,7 +1375,7 @@
 endfunction
 
 function create_pkgadddel (desc, packdir, nm, global_install)
-  instpkg = fullfile (desc.dir, nm);
+  instpkg = fullfile (getdir (desc), 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 
@@ -1427,11 +1441,11 @@
 
 function copy_files (desc, packdir, global_install)
   ## Create the installation directory.
-  if (! exist (desc.dir, "dir"))
-    [status, output] = mkdir (desc.dir);
+  if (! exist (getdir (desc), "dir"))
+    [status, output] = mkdir (getdir (desc));
     if (status != 1)
       error ("couldn't create installation directory %s : %s", 
-      desc.dir, output);
+      getdir (desc), output);
     endif
   endif
 
@@ -1440,13 +1454,13 @@
   ## Copy the files from "inst" to installdir.
   instdir = fullfile (packdir, "inst");
   if (! dirempty (instdir))
-    [status, output] = copyfile (fullfile (instdir, "*"), desc.dir);
+    [status, output] = copyfile (fullfile (instdir, "*"), getdir (desc));
     if (status != 1)
-      rm_rf (desc.dir);
+      rm_rf (getdir (desc));
       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 (fullfile (getdir (desc), getarch ()), "dir") &&
+       ! strcmp (fullfile (getdir (desc), getarch ()), octfiledir))
       if (! exist (octfiledir, "dir"))
         ## Can be required to create upto three levels of dirs.
         octm1 = fileparts (octfiledir);
@@ -1457,38 +1471,38 @@
             if (! exist (octm3, "dir"))
               [status, output] = mkdir (octm3);
               if (status != 1)
-                rm_rf (desc.dir);
+                rm_rf (getdir (desc));
                 error ("couldn't create installation directory %s : %s", 
                        octm3, output);
               endif
             endif
             [status, output] = mkdir (octm2);
             if (status != 1)
-              rm_rf (desc.dir);
+              rm_rf (getdir (desc));
               error ("couldn't create installation directory %s : %s", 
                      octm2, output);
             endif
           endif
           [status, output] = mkdir (octm1);
           if (status != 1)
-            rm_rf (desc.dir);
+            rm_rf (getdir (desc));
             error ("couldn't create installation directory %s : %s", 
                    octm1, output);
           endif
         endif
         [status, output] = mkdir (octfiledir);
         if (status != 1)
-          rm_rf (desc.dir);
+          rm_rf (getdir (desc));
           error ("couldn't create installation directory %s : %s", 
           octfiledir, output);
         endif
       endif
-      [status, output] = movefile (fullfile (desc.dir, getarch (), "*"), 
+      [status, output] = movefile (fullfile (getdir (desc), getarch (), "*"), 
                                   octfiledir);
-      rm_rf (fullfile (desc.dir, getarch ()));
+      rm_rf (fullfile (getdir (desc), getarch ()));
 
       if (status != 1)
-        rm_rf (desc.dir);
+        rm_rf (getdir (desc));
         rm_rf (octfiledir);
         error ("couldn't copy files to the installation directory");
       endif
@@ -1497,10 +1511,10 @@
   endif
 
   ## Create the "packinfo" directory.
-  packinfo = fullfile (desc.dir, "packinfo");
+  packinfo = fullfile (getdir (desc), "packinfo");
   [status, msg] = mkdir (packinfo);
   if (status != 1)
-    rm_rf (desc.dir);
+    rm_rf (getdir (desc));
     rm_rf (octfiledir);
     error ("couldn't create packinfo directory: %s", msg);
   endif
@@ -1508,7 +1522,7 @@
   ## Copy DESCRIPTION.
   [status, output] = copyfile (fullfile (packdir, "DESCRIPTION"), packinfo);
   if (status != 1)
-    rm_rf (desc.dir);
+    rm_rf (getdir (desc));
     rm_rf (octfiledir);
     error ("couldn't copy DESCRIPTION: %s", output);
   endif
@@ -1516,7 +1530,7 @@
   ## Copy COPYING.
   [status, output] = copyfile (fullfile (packdir, "COPYING"), packinfo);
   if (status != 1)
-    rm_rf (desc.dir);
+    rm_rf (getdir (desc));
     rm_rf (octfiledir);
     error ("couldn't copy COPYING: %s", output);
   endif
@@ -1526,7 +1540,7 @@
   if (exist (changelog_file, "file"))
     [status, output] = copyfile (changelog_file, packinfo);
     if (status != 1)
-      rm_rf (desc.dir);
+      rm_rf (getdir (desc));
       rm_rf (octfiledir);
       error ("couldn't copy ChangeLog file: %s", output);
     endif
@@ -1537,7 +1551,7 @@
   if (exist(index_file, "file"))
     [status, output] = copyfile (index_file, packinfo);
     if (status != 1)
-      rm_rf (desc.dir);
+      rm_rf (getdir (desc));
       rm_rf (octfiledir);
       error ("couldn't copy INDEX file: %s", output);
     endif
@@ -1546,7 +1560,7 @@
       write_index (desc, fullfile (packdir, "inst"),
                   fullfile (packinfo, "INDEX"), global_install);
     catch
-      rm_rf (desc.dir);
+      rm_rf (getdir (desc));
       rm_rf (octfiledir);
       rethrow (lasterror ());
     end_try_catch
@@ -1557,7 +1571,7 @@
   if (exist (fon_uninstall, "file"))
     [status, output] = copyfile (fon_uninstall, packinfo);
     if (status != 1)
-      rm_rf (desc.dir);
+      rm_rf (getdir (desc));
       rm_rf (octfiledir);
       error ("couldn't copy on_uninstall.m: %s", output);
     endif
@@ -1566,14 +1580,14 @@
   ## 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);
+    [status, output] = copyfile (docdir, getdir (desc));
   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);
+    [status, output] = copyfile (bindir, getdir (desc));
   endif
 endfunction
 
@@ -1587,7 +1601,7 @@
       cd (wd);
     catch
       cd (wd);
-      rm_rf (desc.dir);
+      rm_rf (getdir (desc));
       rm_rf (getarchdir (desc), global_install);
       rethrow (lasterror ());
     end_try_catch
@@ -1595,7 +1609,7 @@
 endfunction
 
 function generate_lookfor_cache (desc)
-  dirs = split_by (genpath (desc.dir), pathsep ());
+  dirs = split_by (genpath (getdir (desc)), pathsep ());
   for i = 1 : length (dirs)
     gen_doc_cache (fullfile (dirs{i}, "doc-cache"), dirs{i});
   endfor
@@ -1880,21 +1894,21 @@
   ## Now check if the package is loaded.
   tmppath = strrep (path(), "\\", "/");
   for i = 1:length (installed_pkgs_lst)
-    if (findstr (tmppath, strrep (installed_pkgs_lst{i}.dir, "\\", "/")))
+    if (findstr (tmppath, strrep (getdir (installed_pkgs_lst{i}), "\\", "/")))
       installed_pkgs_lst{i}.loaded = true;
     else
       installed_pkgs_lst{i}.loaded = false;
     endif
   endfor
   for i = 1:length (local_packages)
-    if (findstr (tmppath, strrep (local_packages{i}.dir, "\\", "/")))
+    if (findstr (tmppath, strrep (getdir (local_packages{i}), "\\", "/")))
       local_packages{i}.loaded = true;
     else
       local_packages{i}.loaded = false;
     endif
   endfor
   for i = 1:length (global_packages)
-    if (findstr (tmppath, strrep (global_packages{i}.dir, "\\", "/")))
+    if (findstr (tmppath, strrep (getdir (global_packages{i}), "\\", "/")))
       global_packages{i}.loaded = true;
     else
       global_packages{i}.loaded = false;
@@ -1956,7 +1970,7 @@
   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;
+    cur_dir = getdir (installed_pkgs_lst{idx(i)});
     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());
@@ -1984,7 +1998,7 @@
   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;
+    pdirs{i} = getdir (installed_pkgs_lst{i});
   endfor
 
   ## Load all.
@@ -2022,7 +2036,7 @@
   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;
+    pdirs{i} = getdir (installed_pkgs_lst{i});
     pdeps{i} = installed_pkgs_lst{i}.depends;
   endfor
 
@@ -2135,7 +2149,15 @@
 endfunction
 
 function archdir = getarchdir (desc)
-  archdir = fullfile (desc.archprefix, getarch());
+  archdir = fullfile (getarchprefix (desc), getarch());
+endfunction
+
+function d = getdir (desc)
+  if (isfield (desc, "dir_is_relative") && desc.dir_is_relative)
+     d = fullfile (OCTAVE_HOME(), "share", "octave", "packages", desc.dir);
+  else
+     d = desc.dir;
+  endif
 endfunction
 
 function s = issuperuser ()
@@ -2210,7 +2232,7 @@
   dirs = {};
   execpath = EXEC_PATH ();
   for i = idx;
-    ndir = installed_pkgs_lst{i}.dir;
+    ndir = getdir (installed_pkgs_lst{i});
     dirs{end+1} = ndir;
     if (exist (fullfile (dirs{end}, "bin"), "dir"))
       execpath = cstrcat (fullfile (dirs{end}, "bin"), ":", execpath);

reply via email to

[Prev in Thread] Current Thread [Next in Thread]