summaryrefslogtreecommitdiff
path: root/pygnulib/GLFileSystem.py
diff options
context:
space:
mode:
authorBruno Haible <bruno@clisp.org>2022-07-31 18:39:19 +0200
committerBruno Haible <bruno@clisp.org>2022-07-31 23:52:27 +0200
commit6bdf668e5748a511082efed773b2b127e93fcb1d (patch)
tree4096874c27798c4bb6a647899436b1aa0304a3b0 /pygnulib/GLFileSystem.py
parent18dcc627ddeced96bc192e169bf19e1a38c53374 (diff)
downloadgnulib-6bdf668e5748a511082efed773b2b127e93fcb1d.tar.gz
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.
Diffstat (limited to 'pygnulib/GLFileSystem.py')
-rw-r--r--pygnulib/GLFileSystem.py117
1 files changed, 76 insertions, 41 deletions
diff --git a/pygnulib/GLFileSystem.py b/pygnulib/GLFileSystem.py
index f17466187d..dfb1bb903f 100644
--- a/pygnulib/GLFileSystem.py
+++ b/pygnulib/GLFileSystem.py
@@ -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
@@ -46,17 +47,25 @@ 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