changeset 39069:0a08c52592c7

support multiple override directories
author Dmitry Selyutin <ghostmansd@gmail.com>
date Fri, 01 Dec 2017 10:26:13 +0300
parents c81774c414ed
children 3e176eb72d48
files pygnulib.py pygnulib/config.py pygnulib/parser.py pygnulib/vfs.py
diffstat 4 files changed, 64 insertions(+), 36 deletions(-) [+]
line wrap: on
line diff
--- a/pygnulib.py	Thu Nov 30 23:10:59 2017 +0300
+++ b/pygnulib.py	Fri Dec 01 10:26:13 2017 +0300
@@ -44,6 +44,16 @@
     "unlimited",
     "unmodifiable license text",
 }
+SUBSTITUTION_RULES = {
+    "build-aux": "auxdir",
+    "doc": "doc_base",
+    "lib": "source_base",
+    "m4": "m4_base",
+    "tests": "tests_base",
+    "tests=lib": "tests_base",
+    "po": "po_base",
+    "top": "",
+}
 
 
 
@@ -161,28 +171,25 @@
                 print("  ", file, file=sys.stdout, sep="")
 
 
-    table = {
-        "build-aux": "auxdir",
-        "doc": "doc_base",
-        "lib": "source_base",
-        "m4": "m4_base",
-        "tests": "tests_base",
-        "tests=lib": "tests_base",
-        "po": "po_base",
-        "top": "",
-    }
+    overrides = []
+    root = config.root
+    table = {k:config[v] for (k, v) in SUBSTITUTION_RULES.items() if v}
+    for override in config.overrides:
+        vfs = BaseVFS(override, **table)
+        overrides.append(vfs)
+    project = BaseVFS(root, **table)
+
     old_files = set(cache.files)
-    project = BaseVFS(config.root, **{k:config[v] for (k, v) in table.items() if v})
-    override = BaseVFS(config.local, **{k:config[v] for (k, v) in table.items() if v})
     if "m4/gnulib-tool.m4" in project:
         old_files |= set(["m4/gnulib-tool.m4"])
-    with BaseVFS(config.root, **{k:cache[v] for (k, v) in table.items() if v}) as vfs:
+    table = {k:cache[v] for (k, v) in SUBSTITUTION_RULES.items() if v}
+    with BaseVFS(config.root, **table) as vfs:
         old_files = frozenset({vfs[file] for file in old_files})
     new_files = frozenset(files | set(["m4/gnulib-tool.m4"]))
-    dry_run = options["dry_run"]
 
 
-    def remove_file(file):
+    dry_run = options["dry_run"]
+    def remove_file(project, file):
         action = ("Removing", "Remove")[dry_run]
         fmt = (action + " file {file} (backup in {file}~)")
         if not dry_run:
@@ -210,20 +217,26 @@
 
     # First the files that are in old-files, but not in new-files.
     removed_files = {file for file in old_files if file not in new_files}
+    for file in sorted(removed_files):
+        remove_file(project, file)
 
     # Then the files that are in new-files, but not in old-files.
     added_files = {file for file in new_files if file not in old_files}
     for dst in sorted(added_files):
+        match = [override for override in overrides if dst in override]
+        override = match[0] if len(match) else gnulib
         (vfs, src) = lookup(dst, gnulib, override, patch="patch")
         action = update_file if exists(project, dst) else add_file
-        action(project, override, vfs, src, project, dst, present=False)
+        action(vfs, src, project, dst, present=False)
 
     # Then the files that are in new-files and in old-files.
     kept_files = (old_files & new_files)
     for dst in sorted(kept_files):
+        match = [override for override in overrides if dst in override]
+        override = match[0] if len(match) else gnulib
         (vfs, src) = lookup(dst, gnulib, override, patch="patch")
         action = update_file if exists(project, dst) else add_file
-        action(project, override, vfs, src, project, dst, present=True)
+        action(vfs, src, project, dst, present=True)
 
     return os.EX_OK
 
--- a/pygnulib/config.py	Thu Nov 30 23:10:59 2017 +0300
+++ b/pygnulib/config.py	Fri Dec 01 10:26:13 2017 +0300
@@ -7,6 +7,7 @@
 import codecs as _codecs
 import os as _os
 import re as _re
+from collections import OrderedDict as _OrderedDict
 
 
 from .error import type_assert as _type_assert
@@ -42,7 +43,7 @@
     """gnulib generic configuration"""
     _TABLE = {
         "root"              : ".",
-        "local"             : "",
+        "overrides"         : set(),
         "source_base"       : "lib",
         "m4_base"           : "m4",
         "po_base"           : "po",
@@ -125,14 +126,19 @@
 
 
     @property
-    def local(self):
-        """local override directory"""
-        return self.__table["local"]
+    def overrides(self):
+        """local override directories"""
+        return self.__table["overrides"]
 
-    @local.setter
-    def local(self, value):
-        _type_assert("local", value, str)
-        self.__table["local"] = _os.path.normpath(value) if value else ""
+    @overrides.setter
+    def overrides(self, value):
+        _type_assert("overrides", value, _ITERABLES)
+        result = list()
+        for item in value:
+            _type_assert("override", item, str)
+            result.append(_os.path.normpath(item))
+        result = _OrderedDict.fromkeys(result)
+        self.__table["overrides"] = tuple(result)
 
 
     @property
@@ -574,7 +580,7 @@
         "libtool"  : _compile(r"A[CM]_PROG_LIBTOOL")
     }
     _GNULIB_CACHE = {
-        "local"             : (str, _compile(r"gl_LOCAL_DIR\(\[(.*?)\]\)")),
+        "overrides"         : (list, _compile(r"gl_LOCAL_DIR\(\[(.*?)\]\)")),
         "libtool"           : (bool, _compile(r"gl_LIBTOOL\(\[(.*?)\]\)")),
         "conddeps"          : (bool, _compile(r"gl_CONDITIONAL_DEPENDENCIES\(\[(.*?)\]\)")),
         "vc_files"          : (bool, _compile(r"gl_VC_FILES\(\[(.*?)\]\)")),
@@ -649,7 +655,8 @@
                 elif typeid is str:
                     self[key] = match[-1].strip()
                 else:
-                    self[key] = [_.strip() for _ in match[-1].split("\n") if _.strip()]
+                    sep = None if key == "overrides" else "\n"
+                    self[key] = [_.strip() for _ in match[-1].split(sep) if _.strip()]
         if m4_base != self.m4_base:
             raise _M4BaseMismatchError(path, m4_base, self.m4_base)
 
--- a/pygnulib/parser.py	Thu Nov 30 23:10:59 2017 +0300
+++ b/pygnulib/parser.py	Fri Dec 01 10:26:13 2017 +0300
@@ -93,7 +93,6 @@
             self.__options = kwargs["option_strings"]
             super().__init__(default=_argparse.SUPPRESS, *args, **kwargs)
 
-
         def __call__(self, parser, namespace, value, option=None):
             if hasattr(namespace, "mode"):
                 mode = getattr(namespace, "mode")
@@ -109,7 +108,6 @@
             self.__const = kwargs.pop("const")
             super().__init__(nargs=0, *args, **kwargs)
 
-
         def __call__(self, parser, namespace, value, option=None):
             args = (parser, namespace, self.__const, option)
             setattr(parser, self.dest, self.__const)
@@ -146,7 +144,6 @@
                 kwargs["metavar"] = "SRC [DST]"
             super().__init__(*args, **kwargs)
 
-
         def __call__(self, parser, namespace, value, option=None):
             if not hasattr(namespace, self.dest):
                 setattr(namespace, self.dest, 0)
@@ -182,11 +179,21 @@
             super().__call__(parser, namespace, value, option)
 
 
+    class _OverrideOption(_Option):
+        def __init__(self, *args, **kwargs):
+            super().__init__(*args, **kwargs)
+
+        def __call__(self, parser, namespace, value, option=None):
+            if not hasattr(namespace, self.dest):
+                setattr(namespace, self.dest, list())
+            overrides = getattr(namespace, self.dest)
+            overrides.append(value)
+
+
     class _VerbosityOption(_Option):
         def __init__(self, *args, **kwargs):
             super().__init__(nargs=0, *args, **kwargs)
 
-
         def __call__(self, parser, namespace, value, option=None):
             if not hasattr(namespace, self.dest):
                 setattr(namespace, self.dest, 0)
@@ -438,8 +445,8 @@
                         "pecify a local override directory where to look",
                         "up files before looking in gnulib's directory",
                     ),
-                    "action": _Option,
-                    "dest": "local",
+                    "action": _OverrideOption,
+                    "dest": "overrides",
                     "metavar": "DIRECTORY",
                 }),
                 (["-v", "--verbose"], {
@@ -944,4 +951,5 @@
         options = dict(namespace)
         options.setdefault("dry_run", False)
         options.setdefault("single_configure", False)
+        namespace["overrides"] = list(reversed(namespace["overrides"]))
         return (namespace, mode, verbosity, options)
--- a/pygnulib/vfs.py	Thu Nov 30 23:10:59 2017 +0300
+++ b/pygnulib/vfs.py	Fri Dec 01 10:26:13 2017 +0300
@@ -67,7 +67,7 @@
                 part = self.__table[part]
                 replaced = True
             parts += [part]
-        path = _os.path.sep.join([self.path] + parts)
+        path = _os.path.sep.join(parts)
         return _os.path.normpath(path)
 
 
@@ -269,7 +269,7 @@
         _type_assert("full", full, bool)
         if name in GnulibGit._EXCLUDE:
             raise ValueError("illegal module name")
-        path = _os.path.join(self["modules"], name)
+        path = _os.path.join(self.path, self["modules"], name)
         try:
             return _FileModule(path, name=name) if full else _BaseModule(name)
         except FileNotFoundError:
@@ -278,7 +278,7 @@
 
     def modules(self, full=True):
         """iterate over all available modules"""
-        prefix = self["modules"]
+        prefix = _os.path.join(self.path, self["modules"])
         for root, _, files in _os.walk(prefix):
             names = []
             for name in files: