#!/usr/bin/env python3 # # Copyright (C) 2002-2024 Free Software Foundation, Inc. # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # # This program is meant for authors or maintainers which want to import # modules from gnulib into their packages. # CODING STYLE for this file and its companions: # Like PEP 8 , except # - Line length is not limited to 79 characters. # - Line breaking before or after binary operators? Better before, like in GNU. # - Place line breaks to help reading the code: # Avoid line breaks inside expressions, if they can be avoided. # Do use line breaks to separate the parts of [ ... for ... ] iterations. # You can use this command to check the style: # $ pycodestyle --max-line-length=136 --ignore=E265,W503,E241,E711,E712,E201,E202,E221 gnulib-tool.py pygnulib/*.py # You can use this command to check for mistakes: # $ pylint --disable=C0103,C0114,C0121,C0209,C0301,C0302,R0902,R0912,R0913,R0914,R0915,R1705,R1702,R1720 gnulib-tool.py pygnulib/*.py #=============================================================================== # Define global imports #=============================================================================== import os import re import sys import codecs import random import argparse import subprocess as sp import shlex from tempfile import mktemp from pygnulib import constants from pygnulib import classes #=============================================================================== # Define global constants #=============================================================================== APP = constants.APP DIRS = constants.DIRS ENCS = constants.ENCS UTILS = constants.UTILS MODES = constants.MODES TESTS = constants.TESTS joinpath = constants.joinpath copyfile = constants.copyfile isabs = os.path.isabs isdir = os.path.isdir isfile = os.path.isfile #=============================================================================== # Define main part #=============================================================================== def main(): info = classes.GLInfo() parser = argparse.ArgumentParser( prog=constants.APP['name'], usage='gnulib-tool.py --help', add_help=False) # Here we list the options in the order they are listed in the --help output. # list parser.add_argument('--list', dest='mode_list', default=None, action='store_true') # find parser.add_argument('--find', dest='mode_find', default=None, action='store_true') # import parser.add_argument('--import', dest='mode_import', default=None, action='store_true') # add-import parser.add_argument('--add-import', dest='mode_add_import', default=None, action='store_true') # remove-import parser.add_argument('--remove-import', dest='mode_remove_import', default=None, action='store_true') # update parser.add_argument('--update', dest='mode_update', default=None, action='store_true') # create-testdir parser.add_argument('--create-testdir', dest='mode_create_testdir', default=None, action='store_true') # create-megatestdir parser.add_argument('--create-megatestdir', dest='mode_create_megatestdir', default=None, action='store_true') # test parser.add_argument('--test', dest='mode_test', default=None, action='store_true') # megatest parser.add_argument('--megatest', dest='mode_megatest', default=None, action='store_true') # extract-* parser.add_argument('--extract-description', dest='mode_xdescription', default=None, action='store_true') parser.add_argument('--extract-comment', dest='mode_xcomment', default=None, action='store_true') parser.add_argument('--extract-status', dest='mode_xstatus', default=None, action='store_true') parser.add_argument('--extract-notice', dest='mode_xnotice', default=None, action='store_true') parser.add_argument('--extract-applicability', dest='mode_xapplicability', default=None, action='store_true') parser.add_argument('--extract-filelist', dest='mode_xfilelist', default=None, action='store_true') parser.add_argument('--extract-dependencies', dest='mode_xdependencies', default=None, action='store_true') parser.add_argument('--extract-autoconf-snippet', dest='mode_xautoconf', default=None, action='store_true') parser.add_argument('--extract-automake-snippet', dest='mode_xautomake', default=None, action='store_true') parser.add_argument('--extract-include-directive', dest='mode_xinclude', default=None, action='store_true') parser.add_argument('--extract-link-directive', dest='mode_xlink', default=None, action='store_true') parser.add_argument('--extract-license', dest='mode_xlicense', default=None, action='store_true') parser.add_argument('--extract-maintainer', dest='mode_xmaintainer', default=None, action='store_true') parser.add_argument('--extract-tests-module', dest='mode_xtests', default=None, action='store_true') # copy-file parser.add_argument('--copy-file', dest='mode_copy_file', default=None, action='store_true') # help parser.add_argument('--help', '--hel', '--he', '--h', dest='help', default=None, action='store_true') # version parser.add_argument('--version', '--versio', '--versi', '--vers', dest='version', default=None, action='store_true') # no-changelog: a no-op for backward compatibility parser.add_argument('--no-changelog', dest='changelog', default=None, action='store_false') # destdir parser.add_argument('--dir', dest='destdir', default=None, nargs=1) # localpath parser.add_argument('--local-dir', action='append', dest='localpath', default=None, nargs=1) # cache-modules: a no-op for backward compatibility parser.add_argument('--cache-modules', dest='cache_modules', default=None, action='store_true') parser.add_argument('--no-cache-modules', dest='cache_modules', default=None, action='store_false') # verbose parser.add_argument('--verbose', default=0, action='count') # quiet parser.add_argument('--quiet', default=0, action='count') # dryrun parser.add_argument('--dry-run', dest='dryrun', default=None, action='store_true') # inctests parser.add_argument('--with-tests', dest='inctests', default=None, action='store_true') parser.add_argument('--without-tests', dest='inctests', default=None, action='store_false') # obsolete parser.add_argument('--with-obsolete', dest='obsolete', default=None, action='store_true') # c++-tests parser.add_argument('--with-c++-tests', dest='inc_cxx_tests', default=None, action='store_true') parser.add_argument('--without-c++-tests', dest='excl_cxx_tests', default=None, action='store_true') # longrunning-tests parser.add_argument('--with-longrunning-tests', dest='inc_longrunning_tests', default=None, action='store_true') parser.add_argument('--without-longrunning-tests', dest='excl_longrunning_tests', default=None, action='store_true') # privileged-tests parser.add_argument('--with-privileged-tests', dest='inc_privileged_tests', default=None, action='store_true') parser.add_argument('--without-privileged-tests', dest='excl_privileged_tests', default=None, action='store_true') # unportable-tests parser.add_argument('--with-unportable-tests', dest='inc_unportable_tests', default=None, action='store_true') parser.add_argument('--without-unportable-tests', dest='excl_unportable_tests', default=None, action='store_true') # all-tests parser.add_argument('--with-all-tests', dest='alltests', default=None, action='store_true') # avoids parser.add_argument('--avoid', dest='avoids', default=None, action='append', nargs=1) # conditional-dependencies parser.add_argument('--conditional-dependencies', dest='cond_dependencies', default=None, action="store_true") parser.add_argument('--no-conditional-dependencies', dest='cond_dependencies', default=None, action="store_false") # libtool parser.add_argument('--libtool', dest='libtool', default=None, action="store_true") parser.add_argument('--no-libtool', dest='libtool', default=None, action="store_false") # libname parser.add_argument('--lib', dest='libname', default=None, nargs=1) # sourcebase parser.add_argument('--source-base', dest='sourcebase', default=None, nargs=1) # m4base parser.add_argument('--m4-base', dest='m4base', default=None, nargs=1) # pobase parser.add_argument('--po-base', dest='pobase', default=None, nargs=1) # docbase parser.add_argument('--doc-base', dest='docbase', default=None, nargs=1) # testsbase parser.add_argument('--tests-base', dest='testsbase', default=None, nargs=1) # auxdir parser.add_argument('--aux-dir', dest='auxdir', default=None, nargs=1) # lgpl parser.add_argument('--lgpl', dest='lgpl', default=None, action='append', choices=['2', '3orGPLv2', '3'], nargs='?') # makefile-name parser.add_argument('--makefile-name', dest='makefile_name', default=None, nargs=1) # macro-prefix parser.add_argument('--macro-prefix', dest='macro_prefix', default=None, nargs=1) # po-domain parser.add_argument('--po-domain', dest='podomain', default=None, nargs=1) # witness-c-macro parser.add_argument('--witness-c-macro', dest='witness_c_macro', default=None, nargs=1) # vc-files parser.add_argument('--vc-files', dest='vc_files', default=None, action='store_true') parser.add_argument('--no-vc-files', dest='vc_files', default=None, action='store_false') # single-configure parser.add_argument('--single-configure', dest='single_configure', default=None, action='store_true') # symlink parser.add_argument('-s', '--symbolic', '--symlink', dest='symlink', default=None, action='store_true') # local-symlink parser.add_argument('--local-symlink', dest='lsymlink', default=None, action='store_true') # All other arguments are collected. parser.add_argument("non_option_arguments", nargs='*') # Parse the given arguments. Don't signal an error if non-option arguments # occur between or after options. cmdargs, unhandled = parser.parse_known_args() # Handle --help and --version, ignoring all other options. if cmdargs.help != None: print(info.usage()) sys.exit(0) if cmdargs.version != None: version = info.version() if version != '': version = ' ' + version message = '''gnulib-tool (%s %s)%s\n%s\n%s\n\nWritten by %s.''' \ % (info.package(), info.date(), version, info.copyright(), info.license(), info.authors()) print(message) sys.exit(0) # Report unhandled arguments. for arg in unhandled: if arg.startswith('-'): message = '%s: Unrecognized option \'%s\'.\n' % (constants.APP['name'], arg) message += 'Try \'gnulib-tool --help\' for more information.\n' sys.stderr.write(message) sys.exit(1) # By now, all unhandled arguments were non-options. cmdargs.non_option_arguments += unhandled # Determine when user tries to combine modes. args = [ cmdargs.mode_list, cmdargs.mode_find, cmdargs.mode_import, cmdargs.mode_add_import, cmdargs.mode_remove_import, cmdargs.mode_update, cmdargs.mode_create_testdir, cmdargs.mode_create_megatestdir, cmdargs.mode_test, cmdargs.mode_megatest, cmdargs.mode_xdescription, cmdargs.mode_xcomment, cmdargs.mode_xstatus, cmdargs.mode_xnotice, cmdargs.mode_xapplicability, cmdargs.mode_xfilelist, cmdargs.mode_xdependencies, cmdargs.mode_xautoconf, cmdargs.mode_xautomake, cmdargs.mode_xinclude, cmdargs.mode_xlink, cmdargs.mode_xlicense, cmdargs.mode_xmaintainer, cmdargs.mode_xtests, cmdargs.mode_copy_file, ] overflow = [ arg for arg in args if arg != None ] if len(overflow) > 1: message = '%s: Unable to combine different modes of work.\n' % constants.APP['name'] message += 'Try \'gnulib-tool --help\' for more information.\n' sys.stderr.write(message) sys.exit(1) # Determine selected mode. mode = None modules = None files = None if cmdargs.mode_list != None: mode = 'list' if cmdargs.mode_find != None: mode = 'find' files = list(cmdargs.non_option_arguments) if cmdargs.mode_import != None: mode = 'import' modules = list(cmdargs.non_option_arguments) if cmdargs.mode_add_import != None: mode = 'add-import' modules = list(cmdargs.non_option_arguments) if cmdargs.mode_remove_import != None: mode = 'remove-import' modules = list(cmdargs.non_option_arguments) if cmdargs.mode_update != None: mode = 'update' if len(cmdargs.non_option_arguments) > 0: message = '%s: too many arguments in \'update\' mode\n' message += 'Try \'gnulib-tool --help\' for more information.\n' message += 'If you really want to modify the gnulib configuration of your project,\n' message += 'you need to use \'gnulib-tool --import\' - at your own risk!\n' sys.stderr.write(message) sys.exit(1) if cmdargs.mode_create_testdir != None: mode = 'create-testdir' modules = list(cmdargs.non_option_arguments) if cmdargs.mode_create_megatestdir != None: mode = 'create-megatestdir' modules = list(cmdargs.non_option_arguments) if cmdargs.mode_test != None: mode = 'test' modules = list(cmdargs.non_option_arguments) if cmdargs.mode_megatest != None: mode = 'megatest' modules = list(cmdargs.non_option_arguments) if cmdargs.mode_xdescription != None: mode = 'extract-description' modules = list(cmdargs.non_option_arguments) if cmdargs.mode_xcomment != None: mode = 'extract-comment' modules = list(cmdargs.non_option_arguments) if cmdargs.mode_xstatus != None: mode = 'extract-status' modules = list(cmdargs.non_option_arguments) if cmdargs.mode_xnotice != None: mode = 'extract-notice' modules = list(cmdargs.non_option_arguments) if cmdargs.mode_xapplicability != None: mode = 'extract-applicability' modules = list(cmdargs.non_option_arguments) if cmdargs.mode_xfilelist != None: mode = 'extract-filelist' modules = list(cmdargs.non_option_arguments) if cmdargs.mode_xautoconf != None: mode = 'extract-autoconf-snippet' modules = list(cmdargs.non_option_arguments) if cmdargs.mode_xautomake != None: mode = 'extract-automake-snippet' modules = list(cmdargs.non_option_arguments) if cmdargs.mode_xdependencies != None: mode = 'extract-dependencies' modules = list(cmdargs.non_option_arguments) if cmdargs.mode_xinclude != None: mode = 'extract-include-directive' modules = list(cmdargs.non_option_arguments) if cmdargs.mode_xlink != None: mode = 'extract-link-directive' modules = list(cmdargs.non_option_arguments) if cmdargs.mode_xlicense != None: mode = 'extract-license' modules = list(cmdargs.non_option_arguments) if cmdargs.mode_xmaintainer != None: mode = 'extract-maintainer' modules = list(cmdargs.non_option_arguments) if cmdargs.mode_xtests != None: mode = 'extract-tests-module' modules = list(cmdargs.non_option_arguments) if cmdargs.mode_copy_file != None: mode = 'copy-file' if len(cmdargs.non_option_arguments) < 1 or len(cmdargs.non_option_arguments) > 2: message = '%s: *** ' % constants.APP['name'] message += 'invalid number of arguments for --%s\n' % mode message += 'Try \'gnulib-tool --help\' for more information.\n' message += '%s: *** Stop.\n' % constants.APP['name'] sys.stderr.write(message) sys.exit(1) files = list(cmdargs.non_option_arguments) if ((mode in ['import', 'add-import', 'remove-import'] and (cmdargs.excl_cxx_tests or cmdargs.excl_longrunning_tests or cmdargs.excl_privileged_tests or cmdargs.excl_unportable_tests or cmdargs.single_configure)) or (mode == 'update' and (cmdargs.localpath != None or cmdargs.libname != None or cmdargs.sourcebase != None or cmdargs.m4base != None or cmdargs.pobase != None or cmdargs.docbase != None or cmdargs.testsbase != None or cmdargs.auxdir != None or cmdargs.inctests != None or cmdargs.obsolete != None or cmdargs.inc_cxx_tests != None or cmdargs.inc_longrunning_tests != None or cmdargs.inc_privileged_tests != None or cmdargs.inc_unportable_tests != None or cmdargs.alltests != None or cmdargs.excl_cxx_tests != None or cmdargs.excl_longrunning_tests != None or cmdargs.excl_privileged_tests != None or cmdargs.excl_unportable_tests != None or cmdargs.avoids != None or cmdargs.lgpl != None or cmdargs.makefile_name != None or cmdargs.macro_prefix != None or cmdargs.podomain != None or cmdargs.witness_c_macro != None or cmdargs.vc_files != None))): message = '%s: *** ' % constants.APP['name'] message += 'invalid options for --%s mode\n' % mode message += 'Try \'gnulib-tool --help\' for more information.\n' message += '%s: *** Stop.\n' % constants.APP['name'] sys.stderr.write(message) sys.exit(1) if cmdargs.pobase != None and cmdargs.podomain == None: message = '%s: *** ' % constants.APP['name'] message += 'together with --po-base, you need to specify --po-domain\n' message += 'Try \'gnulib-tool --help\' for more information.\n' message += '%s: *** Stop.\n' % constants.APP['name'] sys.stderr.write(message) sys.exit(1) if cmdargs.pobase == None and cmdargs.podomain != None: message = '%s: warning: --po-domain has no effect without a --po-base option\n' % constants.APP['name'] sys.stderr.write(message) # Determine specific settings. destdir = cmdargs.destdir if destdir != None: destdir = cmdargs.destdir[0] localpath = cmdargs.localpath if localpath != None: localpath = [ dir for list1 in localpath for dir in list1 ] libname = cmdargs.libname if libname != None: libname = cmdargs.libname[0] auxdir = cmdargs.auxdir if auxdir != None: auxdir = cmdargs.auxdir[0] sourcebase = cmdargs.sourcebase if sourcebase != None: sourcebase = cmdargs.sourcebase[0] m4base = cmdargs.m4base if m4base != None: m4base = cmdargs.m4base[0] pobase = cmdargs.pobase if pobase != None: pobase = cmdargs.pobase[0] testsbase = cmdargs.testsbase if testsbase != None: testsbase = cmdargs.testsbase[0] dryrun = cmdargs.dryrun verbose = -cmdargs.quiet + cmdargs.verbose inctests = cmdargs.inctests # Canonicalize the inctests variable. if inctests == None: if mode in ['import', 'add-import', 'remove-import', 'update']: inctests = False elif mode in ['create-testdir', 'create-megatestdir', 'test', 'megatest']: inctests = True incl_test_categories = [] if inctests: incl_test_categories += [constants.TESTS['tests']] if cmdargs.obsolete: incl_test_categories += [constants.TESTS['obsolete']] if cmdargs.inc_cxx_tests: incl_test_categories += [constants.TESTS['cxx-tests']] if cmdargs.inc_longrunning_tests: incl_test_categories += [constants.TESTS['longrunning-tests']] if cmdargs.inc_privileged_tests: incl_test_categories += [constants.TESTS['privileged-tests']] if cmdargs.inc_unportable_tests: incl_test_categories += [constants.TESTS['unportable-tests']] if cmdargs.alltests: incl_test_categories += [constants.TESTS['all-tests']] excl_test_categories = [] if cmdargs.excl_cxx_tests: excl_test_categories += [constants.TESTS['cxx-tests']] if cmdargs.excl_longrunning_tests: excl_test_categories += [constants.TESTS['longrunning-tests']] if cmdargs.excl_privileged_tests: excl_test_categories += [constants.TESTS['privileged-tests']] if cmdargs.excl_unportable_tests: excl_test_categories += [constants.TESTS['unportable-tests']] lgpl = cmdargs.lgpl if lgpl != None: lgpl = lgpl[-1] if lgpl == None: lgpl = True cond_dependencies = cmdargs.cond_dependencies libtool = cmdargs.libtool makefile_name = cmdargs.makefile_name if makefile_name != None: makefile_name = makefile_name[0] macro_prefix = cmdargs.macro_prefix if macro_prefix != None: macro_prefix = macro_prefix[0] podomain = cmdargs.podomain if podomain != None: podomain = podomain[0] witness_c_macro = cmdargs.witness_c_macro if witness_c_macro != None: witness_c_macro = witness_c_macro[0] vc_files = cmdargs.vc_files avoids = cmdargs.avoids if avoids != None: avoids = [ module for list1 in avoids for module in list1 ] symlink = cmdargs.symlink == True lsymlink = cmdargs.lsymlink == True single_configure = cmdargs.single_configure docbase = None # Create pygnulib configuration. config = classes.GLConfig( destdir=destdir, localpath=localpath, m4base=m4base, auxdir=auxdir, modules=modules, avoids=avoids, sourcebase=sourcebase, pobase=pobase, docbase=docbase, testsbase=testsbase, incl_test_categories=incl_test_categories, excl_test_categories=excl_test_categories, libname=libname, lgpl=lgpl, makefile_name=makefile_name, libtool=libtool, conddeps=cond_dependencies, macro_prefix=macro_prefix, podomain=podomain, witness_c_macro=witness_c_macro, vc_files=vc_files, symbolic=symlink, lsymbolic=lsymlink, single_configure=single_configure, verbose=verbose, dryrun=dryrun, ) # Work in the given mode. if mode == 'list': modulesystem = classes.GLModuleSystem(config) listing = modulesystem.list() result = '\n'.join(listing) os.rmdir(config['tempdir']) print(result) elif mode == 'find': modulesystem = classes.GLModuleSystem(config) for filename in files: if (isfile(joinpath(DIRS['root'], filename)) or (localpath != None and any([ isfile(joinpath(localdir, filename)) for localdir in localpath ]))): # Convert the file name to a POSIX basic regex. # Needs to handle . [ \ * ^ $. filename_regex = filename.replace('\\', '\\\\').replace('[', '\\[').replace('^', '\\^') filename_regex = re.compile('([.*$])').sub('[\\1]', filename_regex) filename_line_regex = '^' + filename_regex + '$' # Read module candidates from gnulib root directory. command = "find modules -type f -print | xargs -n 100 grep -l %s /dev/null | sed -e 's,^modules/,,'" % shlex.quote(filename_line_regex) os.chdir(constants.DIRS['root']) with sp.Popen(command, shell=True, stdout=sp.PIPE) as proc: result = proc.stdout.read().decode("UTF-8") os.chdir(DIRS['cwd']) # Read module candidates from local directories. if localpath != None and len(localpath) > 0: command = "find modules -type f -print | xargs -n 100 grep -l %s /dev/null | sed -e 's,^modules/,,' -e 's,\\.diff$,,'" % shlex.quote(filename_line_regex) for localdir in localpath: os.chdir(localdir) with sp.Popen(command, shell=True, stdout=sp.PIPE) as proc: result += proc.stdout.read().decode("UTF-8") os.chdir(DIRS['cwd']) listing = [ line for line in result.split('\n') if line.strip() ] # Remove modules/ prefix from each file name. pattern = re.compile('^modules/') listing = [ pattern.sub('', line) for line in listing ] # Filter out undesired file names. listing = [ line for line in listing if modulesystem.file_is_module(line) ] candidates = sorted(set(listing)) for name in candidates: module = modulesystem.find(name) if module: # Ignore module candidates that don't actually exist. if module.getFiles(): print(name) else: message = '%s: warning: file %s does not exist\n' % (constants.APP['name'], filename) sys.stderr.write(message) elif mode in ['import', 'add-import', 'remove-import', 'update']: mode = MODES[mode] if not destdir: destdir = '.' config.setDestDir(destdir) if mode == MODES['import']: # Set variables to default values. if not sourcebase: sourcebase = 'lib' if not m4base: m4base = 'm4' if not docbase: docbase = 'doc' if not testsbase: testsbase = 'tests' if not macro_prefix: macro_prefix = 'gl' config.setSourceBase(sourcebase) config.setM4Base(m4base) config.setDocBase(docbase) config.setTestsBase(testsbase) config.setMacroPrefix(macro_prefix) # Perform GLImport actions. importer = classes.GLImport(config, mode) filetable, transformers = importer.prepare() importer.execute(filetable, transformers) else: # if mode != MODE['--import'] if m4base: if not isfile(joinpath(destdir, m4base, 'gnulib-cache.m4')): if not sourcebase: sourcebase = 'lib' if not docbase: docbase = 'doc' if not testsbase: testsbase = 'tests' if not macro_prefix: macro_prefix = 'gl' config.setSourceBase(sourcebase) config.setM4Base(m4base) config.setDocBase(docbase) config.setTestsBase(testsbase) config.setMacroPrefix(macro_prefix) # Perform GLImport actions. importer = classes.GLImport(config, mode) filetable, transformers = importer.prepare() importer.execute(filetable, transformers) else: # if not m4base m4dirs = list() dirisnext = bool() filepath = joinpath(destdir, 'Makefile.am') if isfile(filepath): with codecs.open(filepath, 'rb', 'UTF-8') as file: data = file.read() data = data.split('ACLOCAL_AMFLAGS')[1] data = data[data.find('=') + 1:data.find('\n')] aclocal_amflags = data.split() for aclocal_amflag in aclocal_amflags: if dirisnext: if not isabs(aclocal_amflag): m4dirs += [aclocal_amflag] else: # if not dirisnext if aclocal_amflag == '-I': dirisnext = True else: # if aclocal_amflag != '-I' dirisnext = False else: # if not isfile(filepath) filepath = joinpath(destdir, 'aclocal.m4') if isfile(filepath): pattern = re.compile(r'm4_include\(\[(.*?)\]\)') with codecs.open(filepath, 'rb', 'UTF-8') as file: m4dirs = pattern.findall(file.read()) m4dirs = [ os.path.dirname(m4dir) for m4dir in m4dirs ] m4dirs = [ m4dir for m4dir in m4dirs if isfile(joinpath(destdir, m4dir, 'gnulib-cache.m4')) ] m4dirs = sorted(set(m4dirs)) if len(m4dirs) == 0: # First use of gnulib in a package. # Any number of additional modules can be given. if not sourcebase: sourcebase = 'lib' m4base = 'm4' if not docbase: docbase = 'doc' if not testsbase: testsbase = 'tests' if not macro_prefix: macro_prefix = 'gl' config.setSourceBase(sourcebase) config.setM4Base(m4base) config.setDocBase(docbase) config.setTestsBase(testsbase) config.setMacroPrefix(macro_prefix) # Perform GLImport actions. importer = classes.GLImport(config, mode) filetable, transformers = importer.prepare() importer.execute(filetable, transformers) elif len(m4dirs) == 1: m4base = m4dirs[-1] config.setM4Base(m4base) # Perform GLImport actions. importer = classes.GLImport(config, mode) filetable, transformers = importer.prepare() importer.execute(filetable, transformers) else: # if len(m4dirs) > 1 for m4base in m4dirs: config.setM4Base(m4base) # Perform GLImport actions. importer = classes.GLImport(config, mode) filetable, transformers = importer.prepare() importer.execute(filetable, transformers) elif mode == 'create-testdir': if not destdir: message = '%s: *** ' % constants.APP['name'] message += 'please specify --dir option\n' message += '%s: *** Stop.\n' % constants.APP['name'] sys.stderr.write(message) sys.exit(1) if not auxdir: auxdir = 'build-aux' config.setAuxDir(auxdir) testdir = classes.GLTestDir(config, destdir) testdir.execute() elif mode == 'create-megatestdir': if not destdir: message = '%s: *** ' % constants.APP['name'] message += 'please specify --dir option\n' message += '%s: *** Stop.\n' % constants.APP['name'] sys.stderr.write(message) sys.exit(1) if not auxdir: auxdir = 'build-aux' config.setAuxDir(auxdir) testdir = classes.GLMegaTestDir(config, destdir) testdir.execute() elif mode == 'test': if not destdir: destdir = 'testdir%04d' % random.randrange(0, 9999) if not auxdir: auxdir = 'build-aux' config.setAuxDir(auxdir) testdir = classes.GLTestDir(config, destdir) testdir.execute() os.chdir(destdir) os.mkdir('build') os.chdir('build') try: # Try to execute commands sp.call(['../configure']) sp.call([UTILS['make']]) sp.call([UTILS['make'], 'check']) sp.call([UTILS['make'], 'distclean']) except Exception as error: sys.exit(1) args = ['find', '.', '-type', 'f', '-print'] remaining = sp.check_output(args).decode(ENCS['shell']) lines = [ line.strip() for line in remaining.split('\n') if line.strip() ] remaining = ' '.join(lines) if remaining: message = 'Remaining files: %s\n' % remaining message += 'gnulib-tool: *** Stop.\n' sys.stderr.write(message) sys.exit(1) os.chdir('../..') sp.call(['rm', '-rf', destdir], shell=False) elif mode == 'megatest': if not destdir: destdir = 'testdir %04d' % random.randrange(0, 9999) if not auxdir: auxdir = 'build-aux' config.setAuxDir(auxdir) testdir = classes.GLMegaTestDir(config, destdir) testdir.execute() os.chdir(destdir) os.mkdir('build') os.chdir('build') sp.call(['../configure']) sp.call([UTILS['make']]) sp.call([UTILS['make'], 'check']) sp.call([UTILS['make'], 'distclean']) args = ['find', '.', '-type', 'f', '-print'] remaining = sp.check_output(args).decode(ENCS['shell']) lines = [ line.strip() for line in remaining.split('\n') if line.strip() ] remaining = ' '.join(lines) if remaining: message = 'Remaining files: %s\n' % remaining message += 'gnulib-tool: *** Stop.\n' sys.stderr.write(message) sys.exit(1) os.chdir('../..') sp.call(['rm', '-rf', destdir], shell=False) elif mode == 'extract-description': modulesystem = classes.GLModuleSystem(config) for name in modules: module = modulesystem.find(name) if module: sys.stdout.write(module.getDescription()) elif mode == 'extract-comment': modulesystem = classes.GLModuleSystem(config) for name in modules: module = modulesystem.find(name) if module: sys.stdout.write(module.getComment()) elif mode == 'extract-status': modulesystem = classes.GLModuleSystem(config) for name in modules: module = modulesystem.find(name) if module: sys.stdout.write(module.getStatus()) elif mode == 'extract-notice': modulesystem = classes.GLModuleSystem(config) for name in modules: module = modulesystem.find(name) if module: sys.stdout.write(module.getNotice()) elif mode == 'extract-applicability': modulesystem = classes.GLModuleSystem(config) for name in modules: module = modulesystem.find(name) if module: print(module.getApplicability()) elif mode == 'extract-filelist': modulesystem = classes.GLModuleSystem(config) for name in modules: module = modulesystem.find(name) if module: files = module.getFiles() print('\n'.join(files)) elif mode == 'extract-dependencies': if avoids: message = '%s: *** ' % constants.APP['name'] message += 'cannot combine --avoid and --extract-dependencies\n' message += '%s: *** Stop.\n' % constants.APP['name'] sys.stderr.write(message) sys.exit(1) modulesystem = classes.GLModuleSystem(config) for name in modules: module = modulesystem.find(name) if module: sys.stdout.write(module.getDependencies()) elif mode == 'extract-autoconf-snippet': modulesystem = classes.GLModuleSystem(config) for name in modules: module = modulesystem.find(name) if module: sys.stdout.write(module.getAutoconfSnippet()) elif mode == 'extract-automake-snippet': modulesystem = classes.GLModuleSystem(config) for name in modules: module = modulesystem.find(name) if module: sys.stdout.write(module.getAutomakeSnippet()) elif mode == 'extract-include-directive': modulesystem = classes.GLModuleSystem(config) for name in modules: module = modulesystem.find(name) if module: sys.stdout.write(module.getInclude()) elif mode == 'extract-link-directive': modulesystem = classes.GLModuleSystem(config) for name in modules: module = modulesystem.find(name) if module: sys.stdout.write(module.getLink()) elif mode == 'extract-license': modulesystem = classes.GLModuleSystem(config) for name in modules: module = modulesystem.find(name) if module: print(module.getLicense()) elif mode == 'extract-maintainer': modulesystem = classes.GLModuleSystem(config) for name in modules: module = modulesystem.find(name) if module: sys.stdout.write(module.getMaintainer()) elif mode == 'extract-tests-module': modulesystem = classes.GLModuleSystem(config) for name in modules: module = modulesystem.find(name) if module: if module.getTestsModule(): print(module.getTestsName()) elif mode == 'copy-file': srcpath = files[0] # The second argument is the destination; either a directory ot a file. # It defaults to the current directory. if len(files) == 2: dest = files[1] else: # if len(files) < 2 dest = '.' if not auxdir: auxdir = 'build-aux' if not sourcebase: sourcebase = 'lib' if not m4base: m4base = 'm4' if not docbase: docbase = 'doc' if not testsbase: testsbase = 'tests' config.setAuxDir(auxdir) config.setSourceBase(sourcebase) config.setM4Base(m4base) config.setDocBase(docbase) config.setTestsBase(testsbase) filesystem = classes.GLFileSystem(config) lookedup, flag = filesystem.lookup(srcpath) if isdir(dest): destdir = dest if srcpath.startswith('build-aux/'): destpath = constants.substart('build-aux/', '%s/' % auxdir, srcpath) elif srcpath.startswith('doc/'): destpath = constants.substart('doc/', '%s/' % docbase, srcpath) elif srcpath.startswith('lib/'): destpath = constants.substart('lib/', '%s/' % sourcebase, srcpath) elif srcpath.startswith('m4/'): destpath = constants.substart('m4/', '%s/' % m4base, srcpath) elif srcpath.startswith('tests/'): destpath = constants.substart('tests/', '%s/' % testsbase, srcpath) elif srcpath.startswith('top/'): destpath = constants.substart('top/', '', srcpath) else: # either case destpath = srcpath else: # if not isdir(dest) destdir = os.path.dirname(dest) destpath = os.path.basename(dest) # Create the directory for destfile. dirname = os.path.dirname(joinpath(destdir, destpath)) if not config['dryrun']: if dirname and not isdir(dirname): try: # Try to create directories os.makedirs(dirname) except FileExistsError: pass # Copy the file. assistant = classes.GLFileAssistant(config) tmpfile = assistant.tmpfilename(destpath) copyfile(lookedup, tmpfile) assistant.setOriginal(srcpath) assistant.config.setDestDir(destdir) assistant.setRewritten(destpath) if isfile(joinpath(destdir, destpath)): # The file already exists. assistant.update(lookedup, flag, tmpfile, True) else: # if not isfile(joinpath(destdir, destpath)) # Install the file. # Don't protest if the file should be there but isn't: it happens # frequently that developers don't put autogenerated files under # version control. assistant.add(lookedup, flag, tmpfile) if isfile(tmpfile): os.remove(tmpfile) else: message = '%s: *** ' % constants.APP['name'] message += 'no mode specified\n' message += '%s: *** Stop.\n' % constants.APP['name'] sys.stderr.write(message) sys.exit(1) if __name__ == '__main__': try: # Try to execute main() except classes.GLError as error: errmode = 0 # gnulib-style errors errno = error.errno errinfo = error.errinfo if errmode == 0: message = '%s: *** ' % constants.APP['name'] if errinfo == None: errinfo = '' if errno == 1: message += 'file %s not found' % errinfo elif errno == 2: message += 'patch file %s didn\'t apply cleanly' % errinfo elif errno == 3: message += 'cannot find %s - make sure you run gnulib-tool from within your package\'s directory' % errinfo elif errno == 4: message += 'minimum supported autoconf version is 2.59. Try adding' message += 'AC_PREREQ([%s])' % constants.DEFAULT_AUTOCONF_MINVERSION message += ' to your configure.ac.' elif errno == 5: message += '%s is expected to contain gl_M4_BASE([%s])' % (repr(os.path.join(errinfo, 'gnulib-comp.m4')), repr(errinfo)) elif errno == 6: message += 'missing --source-base option' elif errno == 7: message += 'missing --doc-base option. --doc-base has been introduced ' message += 'on 2006-07-11; if your last invocation of \'gnulib-tool ' message += '--import\' is before that date, you need to run' message += '\'gnulib-tool --import\' once, with a --doc-base option.' elif errno == 8: message += 'missing --tests-base option' elif errno == 9: message += 'missing --lib option' elif errno == 10: message = 'gnulib-tool: option --conditional-dependencies is not supported with --with-tests' elif errno == 11: incompatibilities = '' message += 'incompatible license on modules:%s' % constants.NL for pair in errinfo: incompatibilities += pair[0] incompatibilities += ' %s' % pair[1] incompatibilities += constants.NL tempname = mktemp() with codecs.open(tempname, 'wb', 'UTF-8') as file: file.write(incompatibilities) sed_table = 's,^\\([^ ]*\\) ,\\1' + ' ' * 51 + ',\n' sed_table += 's,^\\(' + '.' * 49 + '[^ ]*\\) *,' + ' ' * 17 + '\\1 ,' args = ['sed', '-e', sed_table, tempname] incompatibilities = sp.check_output(args).decode(ENCS['default']) message += incompatibilities os.remove(tempname) elif errno == 12: message += 'refusing to do nothing' elif errno == 13: message += 'could not create directory %s' % errinfo elif errno == 14: message += 'could not delete file %s' % errinfo elif errno == 15: message += 'could not create file %s' % errinfo elif errno == 16: message += 'could not transform file %s' % errinfo elif errno == 17: message += 'could not update file %s' % errinfo elif errno == 18: message += 'module %s lacks a license' % errinfo elif errno == 19: message += 'could not create destination directory: %s' % errinfo message += '\n%s: *** Stop.\n' % constants.APP['name'] sys.stderr.write(message) sys.exit(1)