]> Savannah Git Hosting - gnulib.git/commitdiff
gnulib-tool.py: Follow gnulib-tool changes, part 19.
authorBruno Haible <bruno@clisp.org>
Sun, 31 Jul 2022 16:39:19 +0000 (18:39 +0200)
committerBruno Haible <bruno@clisp.org>
Sun, 31 Jul 2022 21:52:27 +0000 (23:52 +0200)
Follow gnulib-tool changes
2015-12-09  Pavel Raiskup  <praiskup@redhat.com>
gnulib-tool: allow multiple --local-dir usage
2019-02-14  Bruno Haible  <bruno@clisp.org>
gnulib-tool: Improve handling of multiple --local-dir options.

* gnulib-tool (func_reconstruct_cached_dir): When the argument is
absolute, return it unmodified.
(func_compute_relative_local_gnulib_path): Renamed from
func_count_relative_local_gnulib_path. Add comment.
* gnulib-tool.py: Accept multiple --local-dir options and collect the
values into localpath.
* pygnulib/GLConfig.py: Take a localpath argument instead of a localdir
argument.
(getLocalDir, setLocalDir, resetLocalDir): Remove methods.
(getLocalPath, setLocalPath, resetLocalPath): New methods.
* pygnulib/GLFileSystem.py (CopyAction): New class.
(GLFileSystem.lookup): Consider all dirs in localpath.
(GLFileSystem.shouldLink): New method.
(GLFileAssistant): Use shouldLink.
* pygnulib/GLModuleSystem.py (GLModuleSystem.exists): Iterate over all
dirs in localpath.
(GLModuleSystem.list): Likewise.
* pygnulib/GLEmiter.py: Update.
* pygnulib/GLImport.py (GLImport.__init__): Put the argument of
gl_LOCAL_DIR into localpath, not localdir.
(GLImport.actioncmd): Consider all dirs in localpath.
(GLImport.relative_to_destdir, GLImport.relative_to_currdir): New
methods.
(GLImport.gnulib_cache): Combine all dirs in localpath. Use
self.relative_to_destdir.
* pygnulib/GLTestDir.py (GLTestDir.execute): Use shouldLink.

ChangeLog
gnulib-tool
gnulib-tool.py
gnulib-tool.py.TODO
pygnulib/GLConfig.py
pygnulib/GLEmiter.py
pygnulib/GLFileSystem.py
pygnulib/GLImport.py
pygnulib/GLModuleSystem.py
pygnulib/GLTestDir.py

index 78ba9e6b796fcc03e6405390fb74960a9557f9bb..f5af88387b184b791076950d0d20fae9d7992059 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,38 @@
 2022-07-31  Bruno Haible  <bruno@clisp.org>
 
+       gnulib-tool.py: Follow gnulib-tool changes, part 19.
+       Follow gnulib-tool changes
+       2015-12-09  Pavel Raiskup  <praiskup@redhat.com>
+       gnulib-tool: allow multiple --local-dir usage
+       2019-02-14  Bruno Haible  <bruno@clisp.org>
+       gnulib-tool: Improve handling of multiple --local-dir options.
+       * gnulib-tool (func_reconstruct_cached_dir): When the argument is
+       absolute, return it unmodified.
+       (func_compute_relative_local_gnulib_path): Renamed from
+       func_count_relative_local_gnulib_path. Add comment.
+       * gnulib-tool.py: Accept multiple --local-dir options and collect the
+       values into localpath.
+       * pygnulib/GLConfig.py: Take a localpath argument instead of a localdir
+       argument.
+       (getLocalDir, setLocalDir, resetLocalDir): Remove methods.
+       (getLocalPath, setLocalPath, resetLocalPath): New methods.
+       * pygnulib/GLFileSystem.py (CopyAction): New class.
+       (GLFileSystem.lookup): Consider all dirs in localpath.
+       (GLFileSystem.shouldLink): New method.
+       (GLFileAssistant): Use shouldLink.
+       * pygnulib/GLModuleSystem.py (GLModuleSystem.exists): Iterate over all
+       dirs in localpath.
+       (GLModuleSystem.list): Likewise.
+       * pygnulib/GLEmiter.py: Update.
+       * pygnulib/GLImport.py (GLImport.__init__): Put the argument of
+       gl_LOCAL_DIR into localpath, not localdir.
+       (GLImport.actioncmd): Consider all dirs in localpath.
+       (GLImport.relative_to_destdir, GLImport.relative_to_currdir): New
+       methods.
+       (GLImport.gnulib_cache): Combine all dirs in localpath. Use
+       self.relative_to_destdir.
+       * pygnulib/GLTestDir.py (GLTestDir.execute): Use shouldLink.
+
        gnulib-tool.py: Improve the primitives for relative file names.
        * pygnulib/constants.py (relativize): Don't attempt to handle absolute
        file names. Fix bug with relativize('../foo/bar', '../foo/bla/zut').
index bee85856f434491a825d27d09903344de48b4edf..f1665f4002688847a335b35bf94f0ea879683cbd 100755 (executable)
@@ -4846,12 +4846,13 @@ func_reconstruct_cached_dir ()
 {
   cached_dir=$1
   if test -n "$cached_dir"; then
-    case "$destdir" in
+    case "$cached_dir" in
       /*)
-        func_path_append local_gnulib_path "$destdir/$cached_dir" ;;
+        func_path_append local_gnulib_path "$cached_dir" ;;
       *)
-        case "$cached_dir" in
+        case "$destdir" in
           /*)
+            # XXX This doesn't look right.
             func_path_append local_gnulib_path "$destdir/$cached_dir" ;;
           *)
             func_relconcat "$destdir" "$cached_dir"
@@ -5835,14 +5836,14 @@ s,//*$,/,'
     fi
   fi
 
-  # func_count_relative_local_gnulib_path
+  # func_compute_relative_local_gnulib_path
   # gl_LOCAL_DIR requires local_gnulib_path to be set relatively to destdir
   # Input:
   # - local_gnulib_path  from --local-dir
   # - destdir           from --dir
   # Output:
   # - relative_local_dir  path to be stored into gl_LOCAL_DIR
-  func_count_relative_local_gnulib_path ()
+  func_compute_relative_local_gnulib_path ()
   {
     relative_local_gnulib_path=
     save_IFS="$IFS"
@@ -5856,7 +5857,9 @@ s,//*$,/,'
           relative_local_dir="$local_dir" ;;
         * )
           case "$destdir" in
-            /*) relative_local_dir="$local_dir" ;;
+            /*)
+              # XXX This doesn't look right.
+              relative_local_dir="$local_dir" ;;
             *)
               # destdir, local_dir are both relative.
               func_relativize "$destdir" "$local_dir"
@@ -5883,7 +5886,7 @@ s,//*$,/,'
     printf '%s\n' "$actioncmd"
     echo
     echo "# Specification in the form of a few gnulib-tool.m4 macro invocations:"
-    func_count_relative_local_gnulib_path
+    func_compute_relative_local_gnulib_path
     echo "gl_LOCAL_DIR([$relative_local_gnulib_path])"
     echo "gl_MODULES(["
     echo "$specified_modules" | sed -e 's/^/  /g'
index 523de7769e5d46d5ebb6c3b29ed74bef6d8106a7..0b2f8669204c900f70128ec30dfbe624bb79d038 100755 (executable)
@@ -24,7 +24,7 @@
 # - Line length is not limited to 79 characters.
 # - Line breaking before or after binary operators? Better before, like in GNU.
 # You can use this command to check the style:
-#   $ pycodestyle --max-line-length=128 --ignore=E265,W503,E241,E711,E712 gnulib-tool.py pygnulib/*.py
+#   $ pycodestyle --max-line-length=128 --ignore=E265,W503,E241,E711,E712,E201,E202 gnulib-tool.py pygnulib/*.py
 
 
 #===============================================================================
@@ -66,7 +66,7 @@ def main():
     # Reset arguments
     mode = None
     destdir = None
-    localdir = None
+    localpath = None
     modcache = None
     verbose = None
     auxdir = None
@@ -224,11 +224,12 @@ def main():
                         dest='destdir',
                         default=None,
                         nargs=1)
-    # localdir
+    # localpath
     parser.add_argument('-ld', '--local-dir',
-                        dest='localdir',
+                        action='append',
+                        dest='localpath',
                         default=None,
-                        nargs=1)
+                        nargs='?')
     # verbose
     parser.add_argument('-v', '--verbose',
                         default=0,
@@ -458,9 +459,7 @@ def main():
     destdir = cmdargs.destdir
     if destdir != None:
         destdir = cmdargs.destdir[0]
-    localdir = cmdargs.localdir
-    if localdir != None:
-        localdir = cmdargs.localdir[0]
+    localpath = cmdargs.localpath
     libname = cmdargs.libname
     if libname != None:
         libname = cmdargs.libname[0]
@@ -514,7 +513,7 @@ def main():
     # Create pygnulib configuration.
     config = classes.GLConfig(
         destdir=destdir,
-        localdir=localdir,
+        localpath=localpath,
         m4base=m4base,
         auxdir=auxdir,
         modules=modules,
index c0a2c975f3a8c751dd70e8bd7f68c1f093e427d4..26c59c53532f3ec7a549914a07c50dcd32802e24 100644 (file)
@@ -15,6 +15,37 @@ The following commits to gnulib-tool have not yet been reflected in
 
 --------------------------------------------------------------------------------
 
+Implement the options:
+  --find
+  --without-tests
+  --without-c++-tests
+  --without-longrunning-tests
+  --without-privileged-tests
+  --without-unportable-tests
+  --single-configure
+  --conditional-dependencies
+  --no-conditional-dependencies
+  --gnu-make
+  --tests-makefile-name
+  --automake-subdir
+  --no-libtool
+  --macro-prefix
+  --po-domain
+  --witness-c-macro
+  --vc-files
+  --no-vc-files
+  --no-changelog
+  -s | --symbolic
+  --local-symlink
+  -h | --hardlink
+  --local-hardlink
+  -S | --more-symlinks
+  -H | --more-hardlinks
+  --help (same output)
+  --version
+
+--------------------------------------------------------------------------------
+
 commit 76c7703cb2e9e0e803d1296618d8ab9e86e13d6c
 Author: Akim Demaille <akim.demaille@gmail.com>
 Date:   Mon Jul 4 07:18:07 2022 +0200
@@ -1079,65 +1110,6 @@ Date:   Wed May 1 13:39:22 2013 +0900
 
 --------------------------------------------------------------------------------
 
-commit 49137e3bc6a2b3fd83c502a514e4a3b89fc1571c
-Author: Bruno Haible <bruno@clisp.org>
-Date:   Thu Feb 14 20:50:57 2019 +0100
-
-    gnulib-tool: Improve handling of multiple --local-dir options.
-
-    * doc/gnulib.texi (Extending Gnulib): Explain how multiple --local-dir
-    options work.
-    * gnulib-tool (func_path_prepend): Remove function.
-    (func_path_foreach): Make IFS handling more robust.
-    (local_gnulib_path): Collect --local-dir values using func_path_append,
-    not func_path_prepend.
-    (func_determine_path_separator): Make IFS handling more robust.
-    (func_lookup_file_cb): New function.
-    (func_lookup_file): Rewritten to use func_lookup_file_cb instead of
-    func_lookup_local_file. Apply the patches in the reverse order of their
-    origin in $local_gnulib_path.
-    (func_count_relative_local_gnulib_path): Make IFS handling more robust.
-    * NEWS: Mention that the first --local-dir option is the one with
-    highest priority.
-
-commit 55c6f22b8043843aa7cf6843326eb4abed4de75c
-Author: Pavel Raiskup <praiskup@redhat.com>
-Date:   Sat Nov 21 14:09:15 2015 +0100
-
-    gnulib-tool: allow multiple --local-dir usage
-
-    * gnulib-tool: Use --local-dir to construct compound
-    $local_gnulib_path path instead of $local_gnulib_dir.  Determine
-    PATH_SEPARATOR early.
-    (local_gnulib_dir): Rename into $local_gnulib_path everywhere.
-    (func_gnulib_dir): Cut out PATH_SEPARATOR detection code into
-    func_determine_path_separator because that needs to be detected
-    earlier now.
-    (func_determine_path_separator): New function.
-    (func_path_foreach, func_path_foreach_inner): New functions.
-    (func_path_prepend, func_path_append): Likewise.
-    (func_lookup_local_file, func_lookup_local_file_cb): Likewise.
-    (func_lookup_file, func_all_modules): Use new functions to work
-    with local_gnulib_path.
-    (func_modules_in_dir, func_exists_module): New callbacks for
-    func_path_foreach.
-    (func_exists_module, func_get_tests_module): Likewise.
-    (func_is_local_file, func_should_symlink): New helper methods.
-    (func_add_file, func_update_file): Use new func_should_symlink
-    instead, DRY.
-    (func_reconstruct_cached_local_gnulib_path): New helper.
-    (func_reconstruct_cached_dir): New callback.
-    (func_import): The cached_local_gnulib_dir renamed to
-    cached_local_gnulib_path similarly to local_gnulib_dir.
-    Use new func_reconstruct_cached_local_gnulib_path.
-    (func_count_relative_local_gnulib_path): New sub-method.
-    (func_create_testdir): Use func_should_symlink, DRY.
-    (func_create_megatestdir): Use new functions to work with
-    local_gnulib_path correctly.
-    (func_append_local_dir): New helper.
-
---------------------------------------------------------------------------------
-
 commit 9bdf6c8a0cdeb13c12e4b65dee9538c5468dbe1d
 Author: Bruno Haible <bruno@clisp.org>
 Date:   Sun Aug 19 14:06:50 2012 +0200
index d20382042793d3ccbde1c6bfea5f5e4afe908db0..55b6cd298698eb1cd08dcbad1559fe9267455eb5 100644 (file)
@@ -56,7 +56,7 @@ class GLConfig(object):
     By default all attributes are set to empty string, empty list or zero.
     The most common value, however, is a None value.'''
 
-    def __init__(self, destdir=None, localdir=None, auxdir=None,
+    def __init__(self, destdir=None, localpath=None, auxdir=None,
                  sourcebase=None, m4base=None, pobase=None, docbase=None, testsbase=None,
                  modules=None, avoids=None, files=None, testflags=None, libname=None,
                  lgpl=None, makefile=None, libtool=None, conddeps=None, macro_prefix=None,
@@ -77,10 +77,10 @@ class GLConfig(object):
         self.resetDestDir()
         if destdir != None:
             self.setDestDir(destdir)
-        # localdir
-        self.resetLocalDir()
-        if localdir != None:
-            self.setLocalDir(localdir)
+        # localpath
+        self.resetLocalPath()
+        if localpath != None:
+            self.setLocalPath(localpath)
         # auxdir
         self.resetAuxDir()
         if auxdir != None:
@@ -402,26 +402,29 @@ class GLConfig(object):
         configure.ac can be found. Defaults to current directory.'''
         self.table['destdir'] = ''
 
-    # Define localdir methods.
-    def getLocalDir(self):
-        '''Return a local override directory where to look up files before looking
-        in gnulib's directory.'''
-        return self.table['localdir']
-
-    def setLocalDir(self, localdir):
-        '''Specify a local override directory where to look up files before looking
-        in gnulib's directory.'''
-        if type(localdir) is str:
-            if localdir:
-                self.table['localdir'] = remove_trailing_slashes(localdir)
-        else:  # if localdir has not str type
-            raise TypeError('localdir must be a string, not %s' %
-                            type(localdir).__name__)
-
-    def resetLocalDir(self):
-        '''Reset a local override directory where to look up files before looking
-        in gnulib's directory.'''
-        self.table['localdir'] = ''
+    # Define localpath methods.
+    def getLocalPath(self):
+        '''Return a list of local override directories where to look up files
+        before looking in gnulib's directory. The first one has the highest
+        priority.'''
+        return self.table['localpath']
+
+    def setLocalPath(self, localpath):
+        '''Specify a list of local override directories where to look up files
+        before looking in gnulib's directory. The first one has the highest
+        priority.'''
+        if type(localpath) is list:
+            for dir in localpath:
+                if type(dir) is not str:
+                    raise TypeError('localpath element must be a string, not %s' % type(dir).__name__)
+        else:
+            raise TypeError('localpath must be a list, not %s' % type(localpath).__name__)
+        self.table['localpath'] = [ remove_trailing_slashes(dir) for dir in localpath ]
+
+    def resetLocalPath(self):
+        '''Reset a list of local override directories where to look up files
+        before looking in gnulib's directory.'''
+        self.table['localpath'] = []
 
     # Define auxdir methods.
     def getAuxDir(self):
@@ -998,22 +1001,22 @@ class GLConfig(object):
     # Define lsymbolic methods.
     def checkLSymbolic(self):
         '''Check if pygnulib will make symbolic links instead of copying files, only
-        for files from the local override directory.'''
+        for files from the local override directories.'''
         return self.table['lsymbolic']
 
     def enableLSymbolic(self):
         '''Enable creation of symbolic links instead of copying files, only for
-        files from the local override directory.'''
+        files from the local override directories.'''
         self.table['lsymbolic'] = True
 
     def disableLSymbolic(self):
         '''Disable creation of symbolic links instead of copying files, only for
-        files from the local override directory.'''
+        files from the local override directories.'''
         self.table['lsymbolic'] = False
 
     def resetLSymbolic(self):
         '''Reset creation of symbolic links instead of copying files, only for
-        files from the local override directory.'''
+        files from the local override directories.'''
         self.table['lsymbolic'] = False
 
     # Define verbosity methods.
index c41d4c5518f52a347f6e9daed9d8b2102cf7a24e..a5a13e63fb4d30c60631aa916d49320b6e5d3d37 100644 (file)
@@ -605,7 +605,7 @@ AC_DEFUN([%V1%_LIBSOURCES], [
 
         Emit the contents of the library Makefile. Returns str and a bool
         variable which shows if subdirectories are used.
-        GLConfig: localdir, sourcebase, libname, pobase, auxdir, makefile, libtool,
+        GLConfig: localpath, sourcebase, libname, pobase, auxdir, makefile, libtool,
         macro_prefix, podomain, conddeps, witness_c_macro.
 
         destfile is a filename relative to destdir of Makefile being generated.
@@ -635,7 +635,6 @@ AC_DEFUN([%V1%_LIBSOURCES], [
             raise TypeError('for_test must be a bool, not %s' %
                             type(for_test).__name__)
         emit = ''
-        localdir = self.config['localdir']
         sourcebase = self.config['sourcebase']
         modcache = self.config['modcache']
         libname = self.config['libname']
@@ -885,7 +884,7 @@ AC_DEFUN([%V1%_LIBSOURCES], [
 
         Emit the contents of the tests Makefile. Returns str and a bool variable
         which shows if subdirectories are used.
-        GLConfig: localdir, modules, libname, auxdir, makefile, libtool,
+        GLConfig: localpath, modules, libname, auxdir, makefile, libtool,
         sourcebase, m4base, testsbase, macro_prefix, witness_c_macro,
         single_configure, libtests.
 
@@ -914,7 +913,6 @@ AC_DEFUN([%V1%_LIBSOURCES], [
             raise TypeError('for_test must be a bool, not %s' %
                             type(for_test).__name__)
         emit = ''
-        localdir = self.config['localdir']
         auxdir = self.config['auxdir']
         sourcebase = self.config['sourcebase']
         modcache = self.config['modcache']
index f17466187df6585b0feb9181980a325137fe9b90..dfb1bb903f9aee05a78bb50d194d514af88252e2 100644 (file)
@@ -23,6 +23,7 @@ import codecs
 import shutil
 import filecmp
 import subprocess as sp
+from enum import Enum
 from . import constants
 from .GLError import GLError
 from .GLConfig import GLConfig
@@ -45,18 +46,26 @@ isdir = os.path.isdir
 isfile = os.path.isfile
 
 
+#===============================================================================
+# Define CopyAction class
+#===============================================================================
+class CopyAction(Enum):
+    Copy = 0
+    Symlink = 1
+
+
 #===============================================================================
 # Define GLFileSystem class
 #===============================================================================
 class GLFileSystem(object):
-    '''GLFileSystem class is used to create virtual filesystem, which is based on
-    the gnulib directory and directory specified by localdir argument. Its main
-    method lookup(file) is used to find file in these directories or combine it
-    using Linux 'patch' utility.'''
+    '''GLFileSystem class is used to create virtual filesystem, which is based
+    on the gnulib directory and directories specified by localpath argument.
+    Its main method lookup(file) is used to find file in these directories or
+    combine it using Linux 'patch' utility.'''
 
     def __init__(self, config):
-        '''Create new GLFileSystem instance. The only argument is localdir,
-        which can be an empty string too.'''
+        '''Create new GLFileSystem instance. The only argument is localpath,
+        which can be an empty list.'''
         if type(config) is not GLConfig:
             raise TypeError('config must be a GLConfig, not %s' %
                             type(config).__name__)
@@ -70,43 +79,75 @@ class GLFileSystem(object):
     def lookup(self, name):
         '''GLFileSystem.lookup(name) -> tuple
 
-        Lookup a file in gnulib and localdir directories or combine it using Linux
+        Lookup a file in gnulib and localpath directories or combine it using
         'patch' utility. If file was found, method returns string, else it raises
         GLError telling that file was not found. Function also returns flag which
         indicates whether file is a temporary file.
-        GLConfig: localdir.'''
+        GLConfig: localpath.'''
         if type(name) is not str:
             raise TypeError(
                 'name must be a string, not %s' % type(module).__name__)
-        # If name exists in localdir, then we use it
-        path_gnulib = joinpath(DIRS['root'], name)
-        path_local = joinpath(self.config['localdir'], name)
-        path_diff = joinpath(self.config['localdir'], '%s.diff' % name)
-        path_temp = joinpath(self.config['tempdir'], name)
-        try:  # Try to create directories
-            os.makedirs(os.path.dirname(path_temp))
-        except OSError as error:
-            pass  # Skip errors if directory exists
-        if isfile(path_temp):
-            os.remove(path_temp)
-        if self.config['localdir'] and isfile(path_local):
-            result = (path_local, False)
-        else:  # if path_local does not exist
-            if isfile(path_gnulib):
-                if self.config['localdir'] and isfile(path_diff):
-                    shutil.copy(path_gnulib, path_temp)
-                    command = 'patch -s "%s" < "%s" >&2' % (path_temp, path_diff)
+        localpath = self.config['localpath']
+        # Each element in localpath is a directory whose contents overrides
+        # or amends the result of the lookup in the rest of localpath and
+        # the gnulib dir. So, the first element of localpath is the highest
+        # priority one.
+        lookedupFile = None
+        lookedupPatches = []
+        for localdir in localpath:
+            file_in_localdir = joinpath(localdir, name)
+            if isfile(file_in_localdir):
+                lookedupFile = file_in_localdir
+                break
+            diff_in_localdir = joinpath(localdir, '%s.diff' % name)
+            if isfile(diff_in_localdir):
+                lookedupPatches.append(diff_in_localdir)
+        # Treat the gnulib dir like a lowest-priority --local-dir, except that
+        # here we don't look for .diff files.
+        if lookedupFile == None:
+            file_in_localdir = joinpath(DIRS['root'], name)
+            if isfile(file_in_localdir):
+                lookedupFile = file_in_localdir
+        if lookedupFile != None:
+            if len(lookedupPatches) > 0:
+                # Apply the patches, from lowest-priority to highest-priority.
+                tempFile = joinpath(self.config['tempdir'], name)
+                try:  # Try to create directories
+                    os.makedirs(os.path.dirname(tempFile))
+                except OSError as error:
+                    pass  # Skip errors if directory exists
+                if isfile(tempFile):
+                    os.remove(tempFile)
+                shutil.copy(lookedupFile, tempFile)
+                for diff_in_localdir in reversed(lookedupPatches):
+                    command = 'patch -s "%s" < "%s" >&2' % (tempFile, diff_in_localdir)
                     try:  # Try to apply patch
                         sp.check_call(command, shell=True)
                     except sp.CalledProcessError as error:
                         raise GLError(2, name)
-                    result = (path_temp, True)
-                else:  # if path_diff does not exist
-                    result = (path_gnulib, False)
-            else:  # if path_gnulib does not exist
-                raise GLError(1, name)
+                result = (tempFile, True)
+            else:
+                result = (lookedupFile, False)
+        else:
+            raise GLError(1, name)
         return result
 
+    def shouldLink(self, original, lookedup):
+        '''GLFileSystem.shouldLink(original, lookedup)
+
+        Determines whether the original file should be copied or symlinked.
+        Returns a CopyAction.'''
+        symbolic = self.config['symbolic']
+        lsymbolic = self.config['lsymbolic']
+        localpath = self.config['localpath']
+        if symbolic:
+            return CopyAction.Symlink
+        if lsymbolic:
+            for localdir in localpath:
+                if lookedup == joinpath(localdir, original):
+                    return CopyAction.Symlink
+        return CopyAction.Copy
+
 
 #===============================================================================
 # Define GLFileAssistant class
@@ -212,16 +253,13 @@ class GLFileAssistant(object):
         original = self.original
         rewritten = self.rewritten
         destdir = self.config['destdir']
-        symbolic = self.config['symbolic']
-        lsymbolic = self.config['lsymbolic']
         if original == None:
             raise TypeError('original must be set before applying the method')
-        elif rewritten == None:
+        if rewritten == None:
             raise TypeError('rewritten must be set before applying the method')
         if not self.config['dryrun']:
             print('Copying file %s' % rewritten)
-            loriginal = joinpath(self.config['localdir'], original)
-            if (symbolic or (lsymbolic and lookedup == loriginal)) \
+            if self.filesystem.shouldLink(original, lookedup) == CopyAction.Symlink \
                     and not tmpflag and filecmp.cmp(lookedup, tmpfile):
                 constants.link_if_changed(
                     lookedup, joinpath(destdir, rewritten))
@@ -242,11 +280,9 @@ class GLFileAssistant(object):
         original = self.original
         rewritten = self.rewritten
         destdir = self.config['destdir']
-        symbolic = self.config['symbolic']
-        lsymbolic = self.config['lsymbolic']
         if original == None:
             raise TypeError('original must be set before applying the method')
-        elif rewritten == None:
+        if rewritten == None:
             raise TypeError('rewritten must be set before applying the method')
         if type(lookedup) is not str:
             raise TypeError('lookedup must be a string, not %s' %
@@ -274,8 +310,7 @@ class GLFileAssistant(object):
                     shutil.move(basepath, backuppath)
                 except Exception as error:
                     raise GLError(17, original)
-                loriginal = joinpath(self.config['localdir'], original)
-                if (symbolic or (lsymbolic and lookedup == loriginal)) \
+                if self.filesystem.shouldLink(original, lookedup) == CopyAction.Symlink \
                         and not tmpflag and filecmp.cmp(lookedup, tmpfile):
                     constants.link_if_changed(lookedup, basepath)
                 else:  # if any of these conditions is not met
index b2691a976db0b80c1ac71a3449ad5105b3bdec27..2b16ce0ea4c1a7a2a0fd3c39d3177bc6df955945 100644 (file)
@@ -52,7 +52,6 @@ TESTS = constants.TESTS
 compiler = constants.compiler
 joinpath = constants.joinpath
 cleaner = constants.cleaner
-relpath = constants.relativize
 isabs = os.path.isabs
 isdir = os.path.isdir
 isfile = os.path.isfile
@@ -181,7 +180,7 @@ class GLImport(object):
             if tempdict['gl_LIB']:
                 self.cache.setLibName(cleaner(tempdict['gl_LIB']))
             if tempdict['gl_LOCAL_DIR']:
-                self.cache.setLocalDir(cleaner(tempdict['gl_LOCAL_DIR']))
+                self.cache.setLocalPath(cleaner(tempdict['gl_LOCAL_DIR']).split(':'))
             if tempdict['gl_MODULES']:
                 self.cache.setModules(cleaner(tempdict['gl_MODULES'].split()))
             if tempdict['gl_AVOID']:
@@ -217,23 +216,14 @@ class GLImport(object):
                 pattern = compiler(regex, re.S | re.M)
                 self.cache.setFiles(pattern.findall(data)[-1].strip().split())
 
-        # The self.config['localdir'] defaults to the cached one. Recall that the
-        # cached one is relative to $destdir, whereas the one we use is relative
-        # to . or absolute.
-        if not self.config['localdir']:
-            if self.cache['localdir']:
-                if isabs(self.config['destdir']):
-                    localdir = joinpath(
-                        self.config['destdir'], self.cache['localdir'])
-                else:  # if not isabs(self.config['destdir'])
-                    if isabs(self.cache['localdir']):
-                        localdir = joinpath(
-                            self.config['destdir'], self.cache['localdir'])
-                    else:  # if not isabs(self.cache['localdir'])
-                        # NOTE: I NEED TO IMPLEMENT RELATIVE_CONCAT
-                        localdir = os.path.relpath(joinpath(self.config['destdir'],
-                                                            self.cache['localdir']))
-                self.config.setLocalDir(localdir)
+        # The self.config['localpath'] defaults to the cached one. Recall that
+        # the cached one is relative to self.config['destdir'], whereas the one
+        # we use is relative to . or absolute.
+        if len(self.config['localpath']) == 0:
+            if len(self.cache['localpath']) > 0:
+                localpath = [ self.relative_to_currdir(localdir)
+                              for localdir in self.cache['localpath'] ]
+                self.config.setLocalPath(localpath)
 
         if self.mode != MODES['import']:
             if self.cache['m4base'] and \
@@ -367,7 +357,7 @@ class GLImport(object):
         modules = self.config.getModules()
         avoids = self.config.getAvoids()
         destdir = self.config.getDestDir()
-        localdir = self.config.getLocalDir()
+        localpath = self.config.getLocalPath()
         auxdir = self.config.getAuxDir()
         sourcebase = self.config.getSourceBase()
         m4base = self.config.getM4Base()
@@ -389,7 +379,7 @@ class GLImport(object):
         # Create command-line invocation comment.
         actioncmd = 'gnulib-tool --import'
         actioncmd += ' --dir=%s' % destdir
-        if localdir:
+        for localdir in localpath:
             actioncmd += ' --local-dir=%s' % localdir
         actioncmd += ' --lib=%s' % libname
         actioncmd += ' --source-base=%s' % sourcebase
@@ -443,17 +433,49 @@ class GLImport(object):
         actioncmd += ' '.join(modules)
         return actioncmd
 
+    def relative_to_destdir(self, dir):
+        '''GLImport.relative_to_destdir(dir) -> str
+
+        Convert a filename that represents dir, relative to the current directory,
+        to a filename relative to destdir.
+        GLConfig: destdir.'''
+        destdir = self.config['destdir']
+        if dir.startswith('/'):
+            return dir
+        else:
+            if destdir.startswith('/'):
+                # XXX This doesn't look right.
+                return dir
+            else:
+                return constants.relativize(destdir, dir)
+
+    def relative_to_currdir(self, dir):
+        '''GLImport.relative_to_currdir(dir) -> str
+
+        The opposite of GLImport.relative_to_destdir:
+        Convert a filename that represents dir, relative to destdir,
+        to a filename relative to the current directory.
+        GLConfig: destdir.'''
+        destdir = self.config['destdir']
+        if dir.startswith('/'):
+            return dir
+        else:
+            if destdir.startswith('/'):
+                # XXX This doesn't look right.
+                return joinpath(destdir, dir)
+            else:
+                return constants.relconcat(destdir, dir)
+
     def gnulib_cache(self):
         '''GLImport.gnulib_cache() -> str
 
         Emit the contents of generated $m4base/gnulib-cache.m4 file.
-        GLConfig: destdir, localdir, tests, sourcebase, m4base, pobase, docbase,
+        GLConfig: destdir, localpath, tests, sourcebase, m4base, pobase, docbase,
         testsbase, conddeps, libtool, macro_prefix, podomain, vc_files.'''
         emit = ''
         moduletable = self.moduletable
         actioncmd = self.actioncmd()
-        destdir = self.config['destdir']
-        localdir = self.config['localdir']
+        localpath = self.config['localpath']
         testflags = list(self.config['testflags'])
         sourcebase = self.config['sourcebase']
         m4base = self.config['m4base']
@@ -482,13 +504,11 @@ class GLImport(object):
 # Specification in the form of a command-line invocation:
 #   %s
 
-# Specification in the form of a few \
-gnulib-tool.m4 macro invocations:\n''' % actioncmd
-        if not localdir or localdir.startswith('/'):
-            relative_localdir = localdir
-        else:  # if localdir or not localdir.startswith('/')
-            relative_localdir = constants.relativize(destdir, localdir)
-        emit += 'gl_LOCAL_DIR([%s])\n' % relative_localdir
+# Specification in the form of a few gnulib-tool.m4 macro invocations:\n''' % actioncmd
+        # Store the localpath relative to destdir.
+        relative_localpath = [ self.relative_to_destdir(localdir)
+                               for localdir in localpath ]
+        emit += 'gl_LOCAL_DIR([%s])\n' % ':'.join(relative_localpath)
         emit += 'gl_MODULES([\n'
         emit += '  %s\n' % '\n  '.join(modules)
         emit += '])\n'
@@ -532,13 +552,12 @@ gnulib-tool.m4 macro invocations:\n''' % actioncmd
         '''GLImport.gnulib_comp(files) -> str
 
         Emit the contents of generated $m4base/gnulib-comp.m4 file.
-        GLConfig: destdir, localdir, tests, sourcebase, m4base, pobase, docbase,
+        GLConfig: destdir, localpath, tests, sourcebase, m4base, pobase, docbase,
         testsbase, conddeps, libtool, macro_prefix, podomain, vc_files.'''
         emit = ''
         assistant = self.assistant
         moduletable = self.moduletable
         destdir = self.config['destdir']
-        localdir = self.config['localdir']
         auxdir = self.config['auxdir']
         testflags = list(self.config['testflags'])
         sourcebase = self.config['sourcebase']
@@ -740,7 +759,6 @@ AC_DEFUN([%s_FILE_LIST], [\n''' % macro_prefix
         '''Make all preparations before the execution of the code.
         Returns filetable and sed transformers, which change the license.'''
         destdir = self.config['destdir']
-        localdir = self.config['localdir']
         auxdir = self.config['auxdir']
         modules = list(self.config['modules'])
         avoids = list(self.config['avoids'])
@@ -963,7 +981,6 @@ AC_DEFUN([%s_FILE_LIST], [\n''' % macro_prefix
             if key not in filetable:
                 raise KeyError('filetable must contain key %s' % repr(key))
         destdir = self.config['destdir']
-        localdir = self.config['localdir']
         auxdir = self.config['auxdir']
         modules = list(self.config['modules'])
         avoids = list(self.config['avoids'])
index 48515ce36d554b748da423a30e541179a11acde7..00b2c5f035d4b8ca9b80bf78cb696866e3b02d09 100644 (file)
@@ -60,7 +60,7 @@ class GLModuleSystem(object):
         '''GLModuleSystem.__init__(config) -> GLModuleSystem
 
         Create new GLModuleSystem instance. Some functions use GLFileSystem class
-        to look up a file in localdir or gnulib directories, or combine it through
+        to look up a file in localpath or gnulib directories, or combine it through
         'patch' utility.'''
         self.args = dict()
         if type(config) is not GLConfig:
@@ -78,22 +78,22 @@ class GLModuleSystem(object):
         '''GLModuleSystem.exists(module) -> bool
 
         Check whether the given module exists.
-        GLConfig: localdir.'''
+        GLConfig: localpath.'''
         if type(module) is not str:
             raise TypeError(
                 'module must be a string, not %s' % type(module).__name__)
-        result = bool()
+        localpath = self.config['localpath']
+        result = False
         badnames = ['ChangeLog', 'COPYING', 'README', 'TEMPLATE',
                     'TEMPLATE-EXTENDED', 'TEMPLATE-TESTS']
-        if isfile(joinpath(DIRS['modules'], module)) or \
-                all([  # Begin all(iterable) function
-                    self.config['localdir'],
-                    isdir(joinpath(self.config['localdir'], 'modules')),
-                    isfile(
-                        joinpath(self.config['localdir'], 'modules', module))
-                ]):  # Close all(iterable) function
-            if module not in badnames:
-                result = True
+        if module not in badnames:
+            result = isfile(joinpath(DIRS['modules'], module))
+            if not result:
+                for localdir in localpath:
+                    if isdir(joinpath(localdir, 'modules')) \
+                       and isfile(joinpath(localdir, 'modules', module)):
+                        result = True
+                        break
         return result
 
     def find(self, module):
@@ -122,7 +122,7 @@ class GLModuleSystem(object):
         complete, so this version uses subprocess to run shell commands.'''
         result = ''
         listing = list()
-        localdir = self.config['localdir']
+        localpath = self.config['localpath']
         find_args = ['find', 'modules', '-type', 'f', '-print']
         sed_args = \
             [
@@ -146,16 +146,18 @@ class GLModuleSystem(object):
         os.chdir(constants.DIRS['root'])
         find = sp.Popen(find_args, stdout=sp.PIPE)
         result += find.stdout.read().decode("UTF-8")
+        os.chdir(DIRS['cwd'])
 
-        # Read modules from local directory.
-        if localdir and isdir(joinpath(localdir, 'modules')):
-            os.chdir(localdir)
-            find = sp.Popen(find_args, stdout=sp.PIPE)
-            result += find.stdout.read().decode("UTF-8")
+        # Read modules from local directories.
+        if len(localpath) > 0:
+            for localdir in localpath:
+                os.chdir(localdir)
+                find = sp.Popen(find_args, stdout=sp.PIPE)
+                result += find.stdout.read().decode("UTF-8")
+                os.chdir(DIRS['cwd'])
             sed_args += ['-e', r's,\.diff$,,']
 
         # Save the list of the modules to file.
-        os.chdir(DIRS['cwd'])
         path = joinpath(self.config['tempdir'], 'list')
         with codecs.open(path, 'wb', 'UTF-8') as file:
             file.write(result)
@@ -538,8 +540,7 @@ Include:|Link:|License:|Maintainer:)'
         '''GLModule.getDependencies() -> list
 
         Return list of dependencies.
-        GLConfig: localdir.'''
-        localdir = self.config['localdir']
+        GLConfig: localpath.'''
         result = list()
         section = 'Depends-on:'
         if 'dependencies' not in self.cache:
@@ -871,7 +872,7 @@ class GLModuleTable(object):
         included in the final modules list. If testflags iterable is enabled, then
         don't add module which status is in the testflags. If conddeps are enabled,
         then store condition for each dependency if it has a condition.
-        The only necessary argument is localdir, which is needed just to create
+        The only necessary argument is localpath, which is needed just to create
         modulesystem instance to look for dependencies.'''
         self.avoids = list()  # Avoids
         self.dependers = dict()  # Dependencies
index 79f67a8fdcaba6e999d4134d54717a2f9ed460fd..7a7f5c52fb4d2ae44271656a8f6601823ec54db6 100644 (file)
@@ -30,6 +30,7 @@ from .GLConfig import GLConfig
 from .GLModuleSystem import GLModule
 from .GLModuleSystem import GLModuleTable
 from .GLModuleSystem import GLModuleSystem
+from .GLFileSystem import CopyAction
 from .GLFileSystem import GLFileSystem
 from .GLFileSystem import GLFileAssistant
 from .GLMakefileTable import GLMakefileTable
@@ -143,7 +144,6 @@ class GLTestDir(object):
         '''GLTestDir.execute()
 
         Create a scratch package with the given modules.'''
-        localdir = self.config['localdir']
         auxdir = self.config['auxdir']
         testflags = list(self.config['testflags'])
         sourcebase = self.config['sourcebase']
@@ -154,8 +154,6 @@ class GLTestDir(object):
         libname = self.config['libname']
         libtool = self.config['libtool']
         witness_c_macro = self.config['witness_c_macro']
-        symbolic = self.config['symbolic']
-        lsymbolic = self.config['lsymbolic']
         single_configure = self.config['single_configure']
         include_guard_prefix = self.config['include_guard_prefix']
         macro_prefix = self.config['macro_prefix']
@@ -337,7 +335,7 @@ class GLTestDir(object):
             if flag:
                 shutil.copy(lookedup, destpath)
             else:  # if not flag
-                if symbolic or (lsymbolic and lookedup == joinpath(localdir, src)):
+                if self.filesystem.shouldLink(src, lookedup) == CopyAction.Symlink:
                     constants.link_relative(lookedup, destpath)
                 else:
                     shutil.copy(lookedup, destpath)