From: Dmitry Selyutin Date: Sun, 17 Dec 2017 20:06:10 +0000 (+0300) Subject: miscellaneousfixes; po files and gnulib-cache generation X-Git-Url: https://gitweb.git.savannah.gnu.org/gitweb/?a=commitdiff_plain;h=ff3a5a6407c30efb83fbf2dc101f77d7ebb2e1bc;p=gnulib.git miscellaneousfixes; po files and gnulib-cache generation --- diff --git a/pygnulib.py b/pygnulib.py index dbde3102f6..e1f90c9bc8 100755 --- a/pygnulib.py +++ b/pygnulib.py @@ -8,7 +8,9 @@ import os import re import stat import sys +import tempfile import traceback +import subprocess as sp from pygnulib.error import CommandLineError from pygnulib.error import UnknownModuleError @@ -17,7 +19,9 @@ from pygnulib.config import Base as BaseConfig from pygnulib.config import Cache as CacheConfig from pygnulib.generator import CommandLine as CommandLineGenerator +from pygnulib.generator import GnulibCache as GnulibCacheGenerator from pygnulib.generator import LibMakefile as LibMakefileGenerator +from pygnulib.generator import POMakevars as POMakevarsGenerator from pygnulib.module import filelist from pygnulib.module import dummy_required @@ -26,15 +30,16 @@ from pygnulib.module import transitive_closure from pygnulib.parser import CommandLine as CommandLineParser -from pygnulib.vfs import backup -from pygnulib.vfs import compare -from pygnulib.vfs import copy -from pygnulib.vfs import exists -from pygnulib.vfs import hardlink -from pygnulib.vfs import lookup -from pygnulib.vfs import move -from pygnulib.vfs import symlink -from pygnulib.vfs import unlink +from pygnulib.vfs import backup as vfs_backup +from pygnulib.vfs import compare as vfs_compare +from pygnulib.vfs import copy as vfs_copy +from pygnulib.vfs import exists as vfs_exists +from pygnulib.vfs import hardlink as vfs_hardlink +from pygnulib.vfs import lookup as vfs_lookup +from pygnulib.vfs import move as vfs_move +from pygnulib.vfs import iostream as vfs_iostream +from pygnulib.vfs import symlink as vfs_symlink +from pygnulib.vfs import unlink as vfs_unlink from pygnulib.vfs import Base as BaseVFS from pygnulib.vfs import GnulibGit as GnulibGitVFS @@ -47,6 +52,11 @@ IGNORED_LICENSES = { "unlimited", "unmodifiable license text", } +TRANSFER_MODES = { + None: vfs_copy, + "hardlink": vfs_hardlink, + "symlink": vfs_symlink, +} SUBSTITUTION_RULES = { "build-aux": "auxdir", "doc": "doc_base", @@ -57,13 +67,15 @@ SUBSTITUTION_RULES = { "po": "po_base", "top": "", } +TP_URL = "http://translationproject.org/latest/" +TP_RSYNC_URI = "translationproject.org::tp/latest/" def list_hook(gnulib, *args, **kwargs): (_, _) = (args, kwargs) for module in sorted(gnulib.modules(full=False)): - print(module.name) + print(module.name, file=sys.stdout) return os.EX_OK @@ -186,8 +198,6 @@ def import_hook(script, gnulib, namespace, explicit, verbosity, options, *args, old_files |= set(["m4/gnulib-tool.m4"]) for (tbl_key, cfg_key) in SUBSTITUTION_RULES.items(): table[tbl_key] = cache[cfg_key] if cfg_key else "" - 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"] @@ -197,39 +207,38 @@ def import_hook(script, gnulib, namespace, explicit, verbosity, options, *args, def transfer_file(local, src_vfs, src_name, dst_vfs, dst_name): args = (src_vfs, src_name, dst_vfs, dst_name) if src_vfs is None: - return copy(*args) - table = {None: copy, "hardlink": hardlink, "symlink": symlink} - action = table[local_copymode if local else gnulib_copymode] + return vfs_copy(*args) + action = TRANSFER_MODES[local_copymode if local else gnulib_copymode] try: return action(*args) except OSError as error: if error.errno == errno.EXDEV: - return copy(*args) + return vfs_copy(*args) raise error def remove_file(project, file): action = ("Removing", "Remove")[dry_run] fmt = (action + " file {file} (backup in {file}~)") if not dry_run: - unlink(project, file, backup=True) - print(fmt.format(file=file)) + vfs_unlink(project, file, backup=True) + print(fmt.format(file=file), file=sys.stdout) def update_file(local, src_vfs, src_name, dst_vfs, dst_name, present): - if not compare(src_vfs, src_name, dst_vfs, dst_name): + if not vfs_compare(src_vfs, src_name, dst_vfs, dst_name): action = (("Replacing", "Replace"), ("Updating", "Update"))[present][dry_run] message = ("(non-gnulib code backed up in {file}~) !!", "(backup in {file}~)")[present] fmt = (action + " file {file} " + message) if not dry_run: - backup(dst_vfs, dst_name) + vfs_backup(dst_vfs, dst_name) transfer_file(local, src_vfs, src_name, dst_vfs, dst_name) - print(fmt.format(file=dst_name)) + print(fmt.format(file=dst_name), file=sys.stdout) def add_file(local, src_vfs, src_name, dst_vfs, dst_name, present): action = ("Copying", "Copy")[dry_run] fmt = (action + " file {file}") if not dry_run: transfer_file(local, src_vfs, src_name, dst_vfs, dst_name) - print(fmt.format(file=dst_name)) + print(fmt.format(file=dst_name), file=sys.stdout) # First the files that are in old_files, but not in new_files. # Then the files that are in new_files, but not in old_files. @@ -241,14 +250,138 @@ def import_hook(script, gnulib, namespace, explicit, verbosity, options, *args, remove_file(project, file) for (present, files) in ((False, added_files), (True, kept_files)): for dst in sorted(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 + match = tuple(override for override in overrides if dst in override) + override = match[0] if match else gnulib + (vfs, src) = vfs_lookup(dst, gnulib, override, patch="patch") + action = update_file if vfs_exists(project, dst) else add_file + action(bool(match), vfs, src, project, dst, present) + + mkedits = [] + if config.makefile_name == "Makefile.am": + dirname = os.path.dirname(config.source_base) + basename = os.path.basename(config.source_base) + dirname = "" if dirname == "." else (dirname + os.path.sep) + mkedits.append((dirname, "SUBDIRS", basename)) + if "po_base" in explicit: + dirname = os.path.dirname(config.po_base) + basename = os.path.basename(config.po_base) + dirname = "" if dirname == "." else dirname + mkedits.append((dirname, "SUBDIRS", basename)) + if config.tests and config.makefile_name == "Makefile.am": + dirname = os.path.dirname(config.tests_base) + basename = os.path.basename(config.tests_base) + dirname = "" if dirname == "." else (dirname + os.path.sep) + mkedits.append((dirname, "SUBDIRS", basename)) + mkedits.append(("", "ACLOCAL_AMFLAGS", "-I {}".format(config.m4_base))) + + # Find the first parent directory of m4_base that contains or will contain a Makefile.am. + (dir1, dir2) = (config.m4_base, "") + source_base_makefile = os.path.join(config.source_base, config.makefile_name) + tests_base_makefile = os.path.join(config.tests_base, config.makefile_name) + while dir1 != ".": + path = os.path.join(dir1, "Makefile.am") + if vfs_exists(project, os.path.join(config.root, dir1, "Makefile.am")) \ + or (config.tests and path in (source_base_makefile, tests_base_makefile)): + break + dir2 = os.path.join(os.path.basename(dir1), dir2) + dir1 = os.path.dirname(dir1) + mkedits.append((dir1, "EXTRA_DIST", os.path.join(dir2, "gnulib-cache.m4"))) + + # Generate the contents of library makefile. + path = os.path.join(config.source_base, config.makefile_name) + with tempfile.NamedTemporaryFile("w", encoding="UTF-8", delete=False) as tmp: + for line in LibMakefileGenerator(config, explicit, path, main, mkedits, False): + tmp.write(line + "\n") + (src, dst) = (tmp.name, path) + present = vfs_exists(project, dst) + if present: + added_files.add(dst) + action = update_file if present else add_file + action(False, None, src, project, dst, present) + os.unlink(tmp.name) + + # Generate po makefile and directories. + url = (TP_RSYNC_URI + "gnulib/") + if "po_base" in explicit: + for file in ("Makefile.in.in", "remove-potcdate.sin"): + path = os.path.join("build-aux", "po", file) + match = tuple(override for override in overrides if file in override) + override = match[0] if match else gnulib + (vfs, src) = vfs_lookup(path, gnulib, override, patch="patch") + dst = os.path.join("po", file) + present = vfs_exists(project, dst) + if present: + added_files.add(dst) + action = update_file if present else add_file action(bool(match), vfs, src, project, dst, present) + # Create po makefile parameterization, part 1. + with tempfile.NamedTemporaryFile("w", encoding="UTF-8", delete=False) as tmp: + for line in POMakevarsGenerator(config): + tmp.write(line + "\n") + (src, dst) = (tmp.name, "po/Makevars") + present = vfs_exists(project, dst) + if present: + added_files.add(dst) + action = update_file if present else add_file + action(False, None, src, project, dst, present) + os.unlink(tmp.name) + # Create po makefile parameterization, part 2. + with tempfile.NamedTemporaryFile("w", encoding="UTF-8", delete=False) as tmp: + for line in POMakevarsGenerator(config): + tmp.write(line + "\n") + (src, dst) = (tmp.name, "po/POTFILES.in") + present = vfs_exists(project, dst) + if present: + added_files.add(dst) + action = update_file if present else add_file + action(False, None, src, project, dst, present) + os.unlink(tmp.name) + # Fetch PO files. + po_root = os.path.join(project.absolute, project["po"]) + fmt = ("{} gnulib PO files from " + TP_URL) + print(fmt.format("Fetching", "Fetch")[dry_run], file=sys.stdout) + if not dry_run: + # Prefer rsync over wget if it is available, since it consumes + # less network bandwidth, due to compression. + url = (TP_RSYNC_URI + "gnulib/") + cmdargs = ("rsync", "--delete", "--exclude", "*.s1", "-Lrtz", url, ".") + with sp.Popen(cmdargs, cwd=po_root, stdout=sp.PIPE, stderr=sp.PIPE) as process: + (stdout, stderr) = process.communicate() + stdout = stdout.decode("UTF-8") + stderr = stderr.decode("UTF-8") + returncode = process.returncode + if process.returncode == 0: + raise sp.CalledProcessError(returncode, cmdargs, stdout, stderr) + print(stdout, file=sys.stdout) + print(stderr, file=sys.stderr) + # Create po/LINGUAS. + languages = set() + for root, _, files in os.walk(po_root): + languages.update(file[:-3] for file in files if file.endswith(".po")) + with tempfile.NamedTemporaryFile("w", encoding="UTF-8", delete=False) as tmp: + tmp.write("# Set of available languages.\n") + for line in sorted(languages): + tmp.write(line + "\n") + (src, dst) = (tmp.name, "po/LINGUAS") + present = vfs_exists(project, dst) + if present: + added_files.add(dst) + action = update_file if present else add_file + action(False, None, src, project, dst, present) + os.unlink(tmp.name) + + # Create m4/gnulib-cache.m4. + with tempfile.NamedTemporaryFile("w", encoding="UTF-8", delete=False) as tmp: + for line in GnulibCacheGenerator(config): + tmp.write(line + "\n") + (src, dst) = (tmp.name, "m4/gnulib-cache.m4") + present = vfs_exists(project, dst) + if present: + added_files.add(dst) + action = update_file if present else add_file + action(False, None, src, project, dst, present) + os.unlink(tmp.name) - actioncmd = " ".join(CommandLineGenerator(config, explicit)) - libMakefile = LibMakefileGenerator(config, explicit, main, False, actioncmd=actioncmd) return os.EX_OK diff --git a/pygnulib/config.py b/pygnulib/config.py index ecaadbf183..524ec5ce2f 100644 --- a/pygnulib/config.py +++ b/pygnulib/config.py @@ -20,7 +20,7 @@ def _compile(regex): return _re.compile(regex, _re.S | _re.M) -_ITERABLES = (list, tuple, set, frozenset) +_ITERABLES = frozenset((list, tuple, set, frozenset, type({}.keys()), type({}.values()))) @@ -50,7 +50,7 @@ class Base: "doc_base" : "doc", "tests_base" : "tests", "auxdir" : "", - "lib" : "libgnu", + "libname" : "libgnu", "makefile_name" : "Makefile.am", "macro_prefix" : "gl", "po_domain" : "", @@ -228,14 +228,14 @@ class Base: @property - def lib(self): + def libname(self): """library name; defaults to 'libgnu'""" - return self.__table["lib"] + return self.__table["libname"] - @lib.setter - def lib(self, value): - _type_assert("lib", value, str) - self.__table["lib"] = value if value else "libgnu" + @libname.setter + def libname(self, value): + _type_assert("libname", value, str) + self.__table["libname"] = value if value else "libgnu" @property @@ -498,7 +498,7 @@ class Base: """include guard prefix""" prefix = self.__table["macro_prefix"].upper() default = Base._TABLE["macro_prefix"].upper() - return "GL_{0}".format(prefix) if prefix == default else "GL" + return "GL" if prefix == default else "GL_{0}".format(prefix) @property @@ -616,7 +616,7 @@ class Cache(Base): "macro_prefix" : (str, _compile(r"gl_MACRO_PREFIX\(\[(.*?)\]\)")), "po_domain" : (str, _compile(r"gl_PO_DOMAIN\(\[(.*?)\]\)")), "witness_c_macro" : (str, _compile(r"gl_WITNESS_C_MACRO\(\[(.*?)\]\)")), - "lib" : (str, _compile(r"gl_LIB\(\[(.*?)\]\)")), + "libname" : (str, _compile(r"gl_LIB\(\[(.*?)\]\)")), "modules" : (list, _compile(r"gl_MODULES\(\[(.*?)\]\)")), "avoids" : (list, _compile(r"gl_AVOID\(\[(.*?)\]\)")), "licenses" : (str, _compile(r"gl_LGPL\(\[(.*?)\]\)")), diff --git a/pygnulib/generator.py b/pygnulib/generator.py index d25e270454..0d58dd73fa 100644 --- a/pygnulib/generator.py +++ b/pygnulib/generator.py @@ -21,7 +21,14 @@ from .config import LGPL_LICENSE as _LGPL_LICENSE -_ITERABLES = (list, tuple, set, frozenset, type({}.keys()), type({}.values())) + +_LGPL = { + _LGPLv2_LICENSE: "2", + _LGPLv3_LICENSE: "3", + _LGPL_LICENSE: "yes", + (_GPLv2_LICENSE | _LGPLv3_LICENSE): "3orGPLv2", +} +_ITERABLES = frozenset((list, tuple, set, frozenset, type({}.keys()), type({}.values()))) @@ -76,7 +83,7 @@ class Generator: -class POMakefile(Generator): +class POMakevars(Generator): """PO Makefile parameterization""" _TEMPLATE = ( "# These options get passed to xgettext.", @@ -156,7 +163,7 @@ class POMakefile(Generator): yield "# These two variables depend on the location of this directory." yield "subdir = {}".format(self.po_domain) yield "top_subdir = {}".format("/".join(".." for _ in self.po_base.split(_os.path.sep))) - for line in POMakefile._TEMPLATE: + for line in POMakevars._TEMPLATE: yield line @@ -468,28 +475,85 @@ class InitMacroDone(InitMacro): +class CommandLine(Generator): + """gnulib command-line invocation generator""" + _TESTS = { + "tests": "tests", + "obsolete": "obsolete", + "cxx_tests": "c++-tests", + "longrunning_tests": "longrunning-tests", + "privileged_tests": "privileged-tests", + "unportable_tests": "unportable-tests", + } + + def __init__(self, config, explicit): + _type_assert("config", config, _BaseConfig) + _type_assert("explicit", explicit, _ITERABLES) + self.__config = config + self.__explicit = explicit + + + def __iter__(self): + config = self.__config + explicit = self.__explicit + yield "gnulib-tool --import" + for path in config.overrides: + yield "--local-dir={}".format(path) + yield "--lib={}".format(config.libname) + yield "--source-base={}".format(config.source_base) + yield "--m4-base={}".format(config.m4_base) + if "po_base" in explicit: + yield "--po-base={}".format(config.po_base) + yield "--doc-base={}".format(config.doc_base) + yield "--tests-base={}".format(config.tests_base) + yield "--aux-dir={}".format(config.auxdir) + for (key, value) in CommandLine._TESTS.items(): + if config[key]: + yield "--with-{}".format(value) + if config.all_tests: + yield "--with-all-tests" + for module in config.avoids: + yield "--avoid={}".format(module) + if config.licenses in _LGPL: + lgpl = _LGPL[config.licenses] + yield "--lgpl={}".format(lgpl) if lgpl != "yes" else "--lgpl" + if config.gnumake: + yield "--gnu-make" + if "makefile_name" in explicit: + yield "--makefile-name={}".format(config.makefile_name) + yield "--{}conditional-dependencies".format("" if config.conddeps else "no-") + yield "--{}libtool".format("" if config.libtool else "no-") + yield "--macro-prefix={}".format(config.macro_prefix) + if "po_domain" in explicit: + yield "--po-domain={}".format(config.po_domain) + if "witness_c_macro" in explicit: + yield "--witness-c-macro={}".format(config.witness_c_macro) + if "vc_files" in explicit: + yield "--{}vc-files".format("" if config.vc_files else "no-") + for module in sorted(config.modules): + yield "{}".format(module) + + + class LibMakefile(Generator): _LDFLAGS = _re.compile(r"^lib_LDFLAGS\s*\+\=.*?$", _re.S) _LIBNAME = _re.compile(r"lib_([A-Z][A-Z]*)", _re.S) _GNUMAKE = _re.compile(r"^if (.*?)$", _re.S) - def __init__(self, config, explicit, modules, for_test, - autoconf="autoconf", configure_ac="configure.ac", actioncmd=""): + def __init__(self, config, explicit, path, modules, mkedits, for_test): _type_assert("config", config, _BaseConfig) _type_assert("explicit", explicit, _ITERABLES) + _type_assert("path", path, str) _type_assert("modules", modules, _ITERABLES) + _type_assert("mkedits", mkedits, _ITERABLES) _type_assert("for_test", for_test, bool) - _type_assert("actioncmd", actioncmd, str) - _type_assert("autoconf", autoconf, str) - _type_assert("configure_ac", configure_ac, str) self.__config = config self.__explicit = explicit + self.__path = path self.__modules = modules + self.__mkedits = mkedits self.__for_test = for_test - self.__actioncmd = actioncmd - self.__autoconf = autoconf - self.__configure_ac = configure_ac def __iter__(self): @@ -497,13 +561,12 @@ class LibMakefile(Generator): config = self.__config explicit = self.__explicit for_test = self.__for_test - actioncmd = self.__actioncmd modules = self.__modules gnumake = config.gnumake libtool = config.libtool kwargs = { - "libname": config.lib, + "libname": config.libname, "macro_prefix": config.macro_prefix, "libext": "la" if libtool else "a", "perhaps_LT": "LT" if libtool else "", @@ -527,6 +590,7 @@ class LibMakefile(Generator): # that is to be preprocessed by config.status is 3070. config.status uses # awk, and the HP-UX 11.00 awk fails if a line has length >= 3071; # similarly, the IRIX 6.5 awk fails if a line has length >= 3072. + actioncmd = " ".join(CommandLine(config, explicit)) if len(actioncmd) <= 3000: yield "# Reproduce by: {}".format(actioncmd) yield "" @@ -579,7 +643,7 @@ class LibMakefile(Generator): if transform_check_PROGRAMS: conditional = conditional.replace("check_PROGRAMS", "noinst_PROGRAMS") conditional = conditional.replace(r"${gl_include_guard_prefix}", config.include_guard_prefix) - unconditional = module.unconditional_automake_snippet + unconditional = module.unconditional_automake_snippet(config.auxdir) unconditional = LibMakefile._LIBNAME.sub("{libname}_{libext}_\\1".format(**kwargs), unconditional) if (conditional + unconditional).strip(): lines.append("## begin gnulib module {}".format(module.name)) @@ -622,22 +686,28 @@ class LibMakefile(Generator): if gnumake: yield "# Start of GNU Make output." + self.__autoconf = "autoconf" + self.__configure_ac = "configure.ac" cmdargs = (self.__autoconf, "-t", "AC_SUBST:$1 = @$1@", self.__configure_ac) - process = _sp.Popen(cmdargs, stdout=_sp.PIPE, stderr=_sp.PIPE) - (stdout, stderr) = process.communicate() - stdout = stdout.decode("UTF-8") - stderr = stderr.decode("UTF-8") - if process.returncode == 0: - for line in sorted(stdout.splitlines()): - yield line - else: - yield "== gnulib-tool GNU Make output failed as follows ==" - for line in stderr.splitlines(): - yield "# stderr: {}".format(line) + with _sp.Popen(cmdargs, stdout=_sp.PIPE, stderr=_sp.PIPE) as process: + (stdout, stderr) = process.communicate() + stdout = stdout.decode("UTF-8") + stderr = stderr.decode("UTF-8") + if process.returncode == 0: + for line in sorted(stdout.splitlines()): + yield line + else: + yield "== gnulib-tool GNU Make output failed as follows ==" + for line in stderr.splitlines(): + yield "# stderr: {}".format(line) yield "# End of GNU Make output." else: yield "# No GNU Make output." + for (directory, key, value) in self.__mkedits: + if key and _os.path.join(directory, "Makefile.am") == self.__path: + yield f"{key} += {value}" + cppflags = "".join(( " -D{}=1".format(config.witness_c_macro) if "witness_c_macro" in explicit else "", " -DGNULIB_STRICT_CHECKING=1" if for_test else "", @@ -706,66 +776,64 @@ class LibMakefile(Generator): -class CommandLine(Generator): - """gnulib command-line invocation generator""" - _TESTS = { - "tests": "tests", - "obsolete": "obsolete", - "cxx_tests": "c++-tests", - "longrunning_tests": "longrunning-tests", - "privileged_tests": "privileged-tests", - "unportable_tests": "unportable-tests", - } - _LGPL = { - _LGPLv2_LICENSE: "2", - _LGPLv3_LICENSE: "3", - _LGPL_LICENSE: "yes", - (_GPLv2_LICENSE | _LGPLv3_LICENSE): "3orGPLv2", - } - - def __init__(self, config, explicit): +class GnulibCache(Generator): + def __init__(self, config): _type_assert("config", config, _BaseConfig) - _type_assert("explicit", explicit, _ITERABLES) self.__config = config - self.__explicit = explicit def __iter__(self): + date = _datetime.now() config = self.__config - explicit = self.__explicit - yield "gnulib-tool --import" - for path in config.overrides: - yield "--local-dir={}".format(path) - yield "--lib={}".format(config.lib) - yield "--source-base={}".format(config.source_base) - yield "--m4-base={}".format(config.m4_base) - if "po_base" in explicit: - yield "--po-base={}".format(config.po_base) - yield "--doc-base={}".format(config.doc_base) - yield "--tests-base={}".format(config.tests_base) - yield "--aux-dir={}".format(config.auxdir) - for (key, value) in CommandLine._TESTS.items(): - if config[key]: - yield "--with-{}".format(value) - if config.all_tests: - yield "--with-all-tests" - for module in config.avoids: - yield "--avoid={}".format(module) - if config.licenses in CommandLine._LGPL: - lgpl = CommandLine._LGPL[config.licenses] - yield "--lgpl={}".format(lgpl) if lgpl == "yes" else " --lgpl" - if config.gnumake: - yield "--gnu-make" - if "makefile_name" in explicit: - yield "--makefile-name={}".format(config.makefile_name) - yield "--{}conditional-dependencies".format("" if config.conddeps else "no-") - yield "--{}libtool".format("" if config.libtool else "no-") - yield "--macro-prefix={}".format(config.macro_prefix) - if "po_domain" in explicit: - yield "--po-domain={}".format(config.po_domain) - if "witness_c_macro" in explicit: - yield "--witness-c-macro={}".format(config.witness_c_macro) - if "vc_files" in explicit: - yield "--{}vc-files".format("" if config.vc_files else "no-") + yield "## DO NOT EDIT! GENERATED AUTOMATICALLY!" + yield "## Process this file with automake to produce Makefile.in." + yield "# Copyright (C) 2002-{} Free Software Foundation, Inc.".format(date.year) + for line in super().__iter__(): + yield line + yield "#" + yield "# This file represents the specification of how gnulib-tool is used." + yield "# It acts as a cache: It is written and read by gnulib-tool." + yield "# In projects that use version control, this file is meant to be put under" + yield "# version control, like the configure.ac and various Makefile.am files." + yield "" + yield "" + yield "# Specification in the form of a command-line invocation:" + yield "gl_LOCAL_DIR([$relative_local_gnulib_path])" + yield "gl_MODULES([" for module in sorted(config.modules): - yield "{}".format(module) + yield " {}".format(module) + yield "])" + if config.obsolete: + yield "gl_WITH_OBSOLETE" + if config.cxx_tests: + yield "gl_WITH_CXX_TESTS" + if config.longrunning_tests: + yield "gl_WITH_LONGRUNNING_TESTS" + if config.privileged_tests: + yield "gl_WITH_PRIVILEGED_TESTS" + if config.unportable_tests: + yield "gl_WITH_UNPORTABLE_TESTS" + if config.all_tests: + yield "gl_WITH_ALL_TESTS" + yield "gl_AVOID([{}])".format(" ".join(sorted(config.avoids))) + yield "gl_SOURCE_BASE([{}])".format(config.source_base) + yield "gl_M4_BASE([{}])".format(config.m4_base) + yield "gl_PO_BASE([{}])".format(config.po_base) + yield "gl_DOC_BASE([{}])".format(config.doc_base) + yield "gl_TESTS_BASE([{}])".format(config.tests_base) + if config.tests: + yield "gl_WITH_TESTS" + yield "gl_LIB([{}])".format(config.libname) + if config.licenses in _LGPL: + lgpl = _LGPL[config.licenses] + yield "gl_LGPL([{}])".format(lgpl) if lgpl != "yes" else "gl_LGPL" + yield "gl_MAKEFILE_NAME([{}])".format(config.makefile_name) + if config.conddeps: + yield "gl_CONDITIONAL_DEPENDENCIES" + if config.libtool: + yield "gl_LIBTOOL" + yield "gl_MACRO_PREFIX([{}])".format(config.macro_prefix) + yield "gl_PO_DOMAIN([{}])".format(config.po_domain) + yield "gl_WITNESS_C_MACRO([{}])".format(config.witness_c_macro) + if config.vc_files: + yield "gl_VC_FILES([{}])".format(" ".join(sorted(config.vc_files))) diff --git a/pygnulib/module.py b/pygnulib/module.py index 939f975afd..674abfbc1f 100644 --- a/pygnulib/module.py +++ b/pygnulib/module.py @@ -16,7 +16,7 @@ from .error import UnknownModuleError as _UnknownModuleError -_ITERABLES = (list, tuple, set, frozenset) +_ITERABLES = frozenset((list, tuple, set, frozenset, type({}.keys()), type({}.values()))) @@ -276,8 +276,7 @@ class Base: self.__table["conditional_automake_snippet"] = value - @property - def unconditional_automake_snippet(self): + def unconditional_automake_snippet(self, auxdir): """Makefile.am snippet that must stay outside of Automake conditionals""" if "unconditional_automake_snippet" in self.__table: return self.__table["unconditional_automake_snippet"] @@ -314,9 +313,6 @@ class Base: mentioned_files = tuple(_collections.OrderedDict.fromkeys(mentioned_files)) lib_files = tuple(file[len("lib/"):] for file in all_files if file.startswith("lib/")) extra_files = tuple(file for file in lib_files if file not in mentioned_files) - import sys - if self.name == "getprogname": - print(mentioned_files, file=sys.stderr) if extra_files: result += ("EXTRA_DIST += {}".format(" ".join(sorted(extra_files))) + "\n") @@ -337,8 +333,9 @@ class Base: result += ("EXTRA_lib_SOURCES += {}".format(" ".join(sorted(extra_files))) + "\n") # Synthesize an EXTRA_DIST augmentation also for the files in build-aux/. + prefix = _os.path.join("$(top_srcdir)", auxdir) buildaux_files = (file for file in all_files if file.startswith("build-aux/")) - buildaux_files = tuple("$(top_srcdir)/{auxdir}/" + file[len("build-aux/"):] for file in buildaux_files) + buildaux_files = tuple(_os.path.join(prefix, file[len("build-aux/"):]) for file in buildaux_files) if buildaux_files: result += ("EXTRA_DIST += {}".format(" ".join(sorted(buildaux_files))) + "\n") self.__table["unconditional_automake_snippet"] = result @@ -650,4 +647,4 @@ def filelist(modules, ac_version): files.add("m4/gnulib-common.m4") if ac_version == 2.59: files.add("m4/onceonly.m4") - return frozenset(files) + return files diff --git a/pygnulib/vfs.py b/pygnulib/vfs.py index 57e47b780c..bbb0257b0c 100644 --- a/pygnulib/vfs.py +++ b/pygnulib/vfs.py @@ -131,6 +131,7 @@ def lookup(name, primary, secondary, patch="patch"): def mkdir(root, name): """Create a leaf directory and all intermediate ones recursively.""" root = Base(".") if root is None else root + path = name if _os.path.isabs(name) else _os.path.join(root.absolute, root[name]) _os.makedirs(root[name], exist_ok=True) @@ -150,8 +151,11 @@ def compare(lhs_root, lhs_name, rhs_root, rhs_name): """Compare the given files; return True if files contain the same data.""" lhs_root = Base(".") if lhs_root is None else lhs_root rhs_root = Base(".") if rhs_root is None else rhs_root - lhs_path = _os.path.join(lhs_root.absolute, lhs_root[lhs_name]) - rhs_path = _os.path.join(rhs_root.absolute, rhs_root[rhs_name]) + (lhs_path, rhs_path) = (lhs_name, rhs_name) + if not _os.path.isabs(lhs_name): + lhs_path = _os.path.join(lhs_root.absolute, lhs_root[lhs_name]) + if not _os.path.isabs(rhs_name): + rhs_path = _os.path.join(rhs_root.absolute, rhs_root[rhs_name]) return _filecmp.cmp(lhs_path, rhs_path, shallow=False) @@ -165,8 +169,11 @@ def copy(src_root, src_name, dst_root, dst_name): src_root = Base(".") if src_root is None else src_root dst_root = Base(".") if dst_root is None else dst_root mkdir(dst_root, _os.path.dirname(dst_name)) - src_path = _os.path.join(src_root.absolute, src_root[src_name]) - dst_path = _os.path.join(dst_root.absolute, dst_root[dst_name]) + (src_path, dst_path) = (src_name, dst_name) + if not _os.path.isabs(src_name): + src_path = _os.path.join(src_root.absolute, src_root[src_name]) + if not _os.path.isabs(dst_name): + dst_path = _os.path.join(dst_root.absolute, dst_root[dst_name]) with _codecs.open(src_path, "rb") as istream: with _codecs.open(dst_path, "wb") as ostream: while 1: @@ -179,7 +186,7 @@ def copy(src_root, src_name, dst_root, dst_name): def exists(root, name): """Check whether the given file exists.""" root = Base(".") if root is None else root - path = _os.path.join(root.absolute, root[name]) + path = name if _os.path.isabs(name) else _os.path.join(root.absolute, root[name]) return _os.path.exists(path) @@ -193,8 +200,11 @@ def hardlink(src_root, src_name, dst_root, dst_name): dst_root = Base(".") if dst_root is None else dst_root mkdir(src_root, _os.path.dirname(src_name)) mkdir(dst_root, _os.path.dirname(dst_name)) - src_path = _os.path.join(src_root.absolute, src_root[src_name]) - dst_path = _os.path.join(dst_root.absolute, dst_root[dst_name]) + (src_path, dst_path) = (src_name, dst_name) + if not _os.path.isabs(src_name): + src_path = _os.path.join(src_root.absolute, src_root[src_name]) + if not _os.path.isabs(dst_name): + dst_path = _os.path.join(dst_root.absolute, dst_root[dst_name]) _os.link(src_path, dst_path) @@ -207,16 +217,26 @@ def move(src_root, src_name, dst_root, dst_name): src_root = Base(".") if src_root is None else src_root dst_root = Base(".") if dst_root is None else dst_root mkdir(dst_root, _os.path.dirname(dst_name)) - src_path = _os.path.join(src_root.absolute, src_root[src_name]) - dst_path = _os.path.join(dst_root.absolute, dst_root[dst_name]) + (src_path, dst_path) = (src_name, dst_name) + if not _os.path.isabs(src_name): + src_path = _os.path.join(src_root.absolute, src_root[src_name]) + if not _os.path.isabs(dst_name): + dst_path = _os.path.join(dst_root.absolute, dst_root[dst_name]) _os.rename(src_path, dst_path) +def iostream(root, name, mode="r", encoding=None): + """Open file and return a stream. Raise IOError upon failure.""" + root = Base(".") if root is None else root + path = name if _os.path.isabs(name) else _os.path.join(root.absolute, root[name]) + return _codecs.open(path, mode, encoding) + + def readlink(root, name): """Obtain the path to which the symbolic link points.""" root = Base(".") if root is None else root mkdir(root, _os.path.dirname(name)) - path = _os.path.join(root.absolute, root[name]) + path = name if _os.path.isabs(name) else _os.path.join(root.absolute, root[name]) return _os.readlink(path) @@ -230,8 +250,11 @@ def symlink(src_root, src_name, dst_root, dst_name, relative=True): dst_root = Base(".") if dst_root is None else dst_root mkdir(dst_root, _os.path.dirname(dst_name)) if not relative: - src_path = _os.path.join(src_root.absolute, src_root[src_name]) - dst_path = _os.path.join(dst_root.absolute, dst_root[dst_name]) + (src_path, dst_path) = (src_name, dst_name) + if not _os.path.isabs(src_name): + src_path = _os.path.join(src_root.absolute, src_root[src_name]) + if not _os.path.isabs(dst_name): + dst_path = _os.path.join(dst_root.absolute, dst_root[dst_name]) else: src_path = _os.path.join(src_root.relative, src_root[src_name]) dst_path = _os.path.join(dst_root.relative, dst_root[dst_name]) @@ -246,7 +269,7 @@ def unlink(root, name, backup=True): """Unlink a file, backing it up if necessary.""" root = Base(".") if root is None else root mkdir(root, _os.path.dirname(name)) - path = _os.path.join(root.absolute, root[name]) + path = name if _os.path.isabs(name) else _os.path.join(root.absolute, root[name]) _os.unlink(path)