From 31e219f6b3430b5748a0d12fe9305328a807e3a3 Mon Sep 17 00:00:00 2001 From: Dmitry Selyutin Date: Fri, 1 Dec 2017 10:26:13 +0300 Subject: [PATCH] support multiple override directories --- pygnulib.py | 47 +++++++++++++++++++++++++++++----------------- pygnulib/config.py | 27 ++++++++++++++++---------- pygnulib/parser.py | 20 ++++++++++++++------ pygnulib/vfs.py | 6 +++--- 4 files changed, 64 insertions(+), 36 deletions(-) diff --git a/pygnulib.py b/pygnulib.py index 4222a4887b..7bcc0950d3 100755 --- a/pygnulib.py +++ b/pygnulib.py @@ -44,6 +44,16 @@ IGNORED_LICENSES = { "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 @@ def import_hook(script, gnulib, namespace, verbosity, options, *args, **kwargs): 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 @@ def import_hook(script, gnulib, namespace, verbosity, options, *args, **kwargs): # 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 diff --git a/pygnulib/config.py b/pygnulib/config.py index 7dba24f246..dd92ac61fe 100644 --- a/pygnulib/config.py +++ b/pygnulib/config.py @@ -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 @@ class Base: """gnulib generic configuration""" _TABLE = { "root" : ".", - "local" : "", + "overrides" : set(), "source_base" : "lib", "m4_base" : "m4", "po_base" : "po", @@ -125,14 +126,19 @@ class Base: @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 @@ class Cache(Base): "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 @@ class Cache(Base): 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) diff --git a/pygnulib/parser.py b/pygnulib/parser.py index 4256d9c24b..b8e8e50542 100644 --- a/pygnulib/parser.py +++ b/pygnulib/parser.py @@ -93,7 +93,6 @@ class CommandLine: 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 @@ class CommandLine: 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 @@ class CommandLine: 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 @@ class CommandLine: 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 @@ class CommandLine: "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 @@ class CommandLine: options = dict(namespace) options.setdefault("dry_run", False) options.setdefault("single_configure", False) + namespace["overrides"] = list(reversed(namespace["overrides"])) return (namespace, mode, verbosity, options) diff --git a/pygnulib/vfs.py b/pygnulib/vfs.py index 346788c829..724f4823c3 100644 --- a/pygnulib/vfs.py +++ b/pygnulib/vfs.py @@ -67,7 +67,7 @@ class Base: 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 @@ class GnulibGit(Base): _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 @@ class GnulibGit(Base): 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: -- 2.39.5