From d1967197f677a5508f6e824bb1c87f526809b42b Mon Sep 17 00:00:00 2001 From: Dmitry Selyutin Date: Fri, 8 Sep 2017 18:34:58 +0300 Subject: [PATCH] [pygnulib] autopep8 (fixing indentation, style, etc.) --- gnulib-tool.py | 1871 ++++++++++++------------- pygnulib/GLConfig.py | 2230 +++++++++++++++--------------- pygnulib/GLEmiter.py | 1947 +++++++++++++------------- pygnulib/GLError.py | 129 +- pygnulib/GLFileSystem.py | 684 ++++----- pygnulib/GLImport.py | 2609 ++++++++++++++++++----------------- pygnulib/GLInfo.py | 155 ++- pygnulib/GLMakefileTable.py | 155 ++- pygnulib/GLModuleSystem.py | 2401 ++++++++++++++++---------------- pygnulib/GLTestDir.py | 1779 ++++++++++++------------ pygnulib/__init__.py | 1 - pygnulib/classes.py | 101 +- pygnulib/constants.py | 550 ++++---- 13 files changed, 7338 insertions(+), 7274 deletions(-) diff --git a/gnulib-tool.py b/gnulib-tool.py index f615f162b4..f787fb4d51 100755 --- a/gnulib-tool.py +++ b/gnulib-tool.py @@ -62,942 +62,951 @@ relpath = os.path.relpath # Define main part #=============================================================================== def main(): - # Reset arguments - mode = None - destdir = None - localdir = None - modcache = None - verbose = None - auxdir = None - modules = None - avoids = None - sourcebase = None - m4base = None - pobase = None - docbase = None - testsbase = None - tests = None - libname = None - lgpl = None - makefile = None - libtool = None - conddeps = None - macro_prefix = None - podomain = None - witness_c_macro = None - vc_files = None - dryrun = None - errors = None - - info = classes.GLInfo() - parser = argparse.ArgumentParser( - prog=constants.APP['name'], - usage='gnulib-tool.py --help', - add_help=False) - # help - parser.add_argument('-h', '--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') - # list - parser.add_argument('-l', '--list', '--lis', - dest='mode_list', - default=None, - action='store_true') - # find - parser.add_argument('-f', '--find', '--fin', '--fi', '--f', - dest='mode_find', - default=None, - nargs='*') - # import - parser.add_argument('-i', '--import', - dest='mode_import', - default=None, - nargs='*') - # add-import - parser.add_argument('-a', '--add-import', - dest='mode_add_import', - default=None, - nargs='+') - # remove-import - parser.add_argument('-r', '--remove-import', - dest='mode_remove_import', - default=None, - nargs='+') - # update - parser.add_argument('-u', '--update', - dest='mode_update', - default=None, - action='store_true') - # create-testdir - parser.add_argument('-td', '--create-testdir', - dest='mode_create_testdir', - default=None, - nargs='*') - # create-megatestdir - parser.add_argument('-mtd', '--create-megatestdir', - dest='mode_create_megatestdir', - default=None, - nargs='*') - # test - parser.add_argument('-t', '--test', - dest='mode_test', - default=None, - nargs='*') - # megatest - parser.add_argument('-mt', '--megatest', '--megates', '--megate', '--megat', - '--mega', '--meg', '--me', '--m', - dest='mode_megatest', - default=None, - nargs='*') - # copy-file - parser.add_argument('-c', '--copy-file', - dest='mode_copy_file', - default=None, - nargs='+') - # extract-* - parser.add_argument('-xD', '--extract-description', - dest='mode_xdescription', - default=None, - nargs='*') - parser.add_argument('-xc', '--extract-comment', - dest='mode_xcomment', - default=None, - nargs='*') - parser.add_argument('-xs', '--extract-status', - dest='mode_xstatus', - default=None, - nargs='*') - parser.add_argument('-xn', '--extract-notice', - dest='mode_xnotice', - default=None, - nargs='*') - parser.add_argument('-xa', '--extract-applicability', - dest='mode_xapplicability', - default=None, - nargs='*') - parser.add_argument('-xf', '--extract-filelist', - dest='mode_xfilelist', - default=None, - nargs='*') - parser.add_argument('-xd', '--extract-dependencies', - dest='mode_xdependencies', - default=None, - nargs='*') - parser.add_argument('-xac', '--extract-autoconf-snippet', - dest='mode_xautoconf', - default=None, - nargs='*') - parser.add_argument('-xam', '--extract-automake-snippet', - dest='mode_xautomake', - default=None, - nargs='*') - parser.add_argument('-xi', '--extract-include-directive', - dest='mode_xinclude', - default=None, - nargs='*') - parser.add_argument('-xl', '--extract-link-directive', - dest='mode_xlink', - default=None, - nargs='*') - parser.add_argument('-xL', '--extract-license', - dest='mode_xlicense', - default=None, - nargs='*') - parser.add_argument('-xm', '--extract-maintainer', - dest='mode_xmaintainer', - default=None, - nargs='*') - # no-changelog - parser.add_argument('--no-changelog', - dest='changelog', - default=None, - action='store_false') - # destdir - parser.add_argument('-d', '--destdir', - dest='destdir', - default=None, - nargs=1) - # localdir - parser.add_argument('-ld', '--local-dir', - dest='localdir', - default=None, - nargs=1) - # verbose - parser.add_argument('-v', '--verbose', - default=0, - action='count') - # quiet - parser.add_argument('-q', '--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') - # makefile - parser.add_argument("--makefile-name", - dest="makefile", - default=None, - type=str) - # obsolete - parser.add_argument('--with-obsolete', - dest='obsolete', - default=None, - action='store_true') - # c++-tests - parser.add_argument('--with-c++-tests', - dest='cxx', - default=None, - action='store_true') - # longrunning-tests - parser.add_argument('--with-longrunning-tests', - dest='longrunning', - default=None, - action='store_true') - # privileged-tests - parser.add_argument('--with-privileged-tests', - dest='privileged', - default=None, - action='store_true') - # unportable-tests - parser.add_argument('--with-unportable-tests', - dest='unportable', - default=None, - action='store_true') - # all-tests - parser.add_argument('--with-all-tests', - dest='alltests', - default=None, - action='store_true') - # auxdir - parser.add_argument('--aux-dir', - dest='auxdir', - default=None, - nargs=1) - # libname - parser.add_argument('--lib', - dest='libname', - default=None, - nargs=1) - # libtool - parser.add_argument("--libtool", - dest=libtool, - default=False, - action="store_true") - # sourcebase - parser.add_argument('-sb', '--source-base', - dest='sourcebase', - default=None, - nargs=1) - # m4base - parser.add_argument('-mb', '--m4-base', - dest='m4base', - default=None, - nargs=1) - # pobase - parser.add_argument('-pb', '--po-base', - dest='pobase', - default=None, - nargs=1) - # docbase - parser.add_argument('-db', '--doc-base', - dest='docbase', - default=None, - nargs=1) - # testsbase - parser.add_argument('-tb', '--tests-base', - dest='testsbase', - default=None, - nargs=1) - # lgpl - parser.add_argument('--lgpl', - dest='lgpl', - default=False, - type=int, - nargs='?') - # avoids - parser.add_argument('--avoid', - dest='avoids', - default=None, - nargs='+') - - # Parse the given arguments. - cmdargs = parser.parse_args() - - # Determine when user tries to combine modes. - args = [ - cmdargs.mode_list, - 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_copy_file, - 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, - ] - overflow = [arg for arg in args if arg] - if len(overflow) > 1: - message = 'gnulib-tool: Unable to combine different modes of work.\n' - message += 'Try \'gnulib-tool --help\' for more information.\n' - sys.stderr.write(message) - sys.exit(1) - - # Determine selected mode. - if cmdargs.help != None: - print(info.usage()) - sys.exit(0) - if cmdargs.version != None: - message = '''gnulib-tool (%s %s)%s\n%s\n%s\n\nWritten by %s.''' % \ - (info.package(), info.date(), info.version(), info.copyright(), - info.license(), info.authors()) - print(message) - sys.exit(0) - if cmdargs.mode_list != None: - mode = 'list' - if cmdargs.mode_import != None: - mode = 'import' - modules = list(cmdargs.mode_import) - if cmdargs.mode_add_import != None: - mode = 'add-import' - modules = list(cmdargs.mode_add_import) - if cmdargs.mode_remove_import != None: - mode = 'remove-import' - modules = list(cmdargs.mode_remove_import) - if cmdargs.mode_update != None: - mode = 'update' - if cmdargs.mode_create_testdir != None: - mode = 'create-testdir' - modules = list(cmdargs.mode_create_testdir) - if cmdargs.mode_create_megatestdir != None: - mode = 'create-megatestdir' - modules = list(cmdargs.mode_create_megatestdir) - if cmdargs.mode_test != None: - mode = 'test' - modules = list(cmdargs.mode_test) - if cmdargs.mode_megatest != None: - mode = 'megatest' - modules = list(cmdargs.mode_megatest) - if cmdargs.mode_xdescription != None: - mode = 'extract-description' - modules = list(cmdargs.mode_xdescription) - if cmdargs.mode_xcomment != None: - mode = 'extract-comment' - modules = list(cmdargs.mode_xcomment) - if cmdargs.mode_xstatus != None: - mode = 'extract-status' - modules = list(cmdargs.mode_xstatus) - if cmdargs.mode_xnotice != None: - mode = 'extract-notice' - modules = list(cmdargs.mode_xnotice) - if cmdargs.mode_xapplicability != None: - mode = 'extract-applicability' - modules = list(cmdargs.mode_xapplicability) - if cmdargs.mode_xfilelist != None: - mode = 'extract-filelist' - modules = list(cmdargs.mode_xfilelist) - if cmdargs.mode_xautoconf != None: - mode = 'extract-autoconf-snippet' - modules = list(cmdargs.mode_xautoconf) - if cmdargs.mode_xautomake != None: - mode = 'extract-automake-snippet' - modules = list(cmdargs.mode_xautomake) - if cmdargs.mode_xdependencies != None: - mode = 'extract-dependencies' - modules = list(cmdargs.mode_xdependencies) - if cmdargs.mode_xinclude != None: - mode = 'extract-include-directive' - modules = list(cmdargs.mode_xinclude) - if cmdargs.mode_xlink != None: - mode = 'extract-link-directive' - modules = list(cmdargs.mode_xlink) - if cmdargs.mode_xlicense != None: - mode = 'extract-license' - modules = list(cmdargs.mode_xlicense) - if cmdargs.mode_xmaintainer != None: - mode = 'extract-maintainer' - modules = list(cmdargs.mode_xmaintainer) - if cmdargs.mode_copy_file != None: - mode = 'copy-file' - if len(cmdargs.mode_copy_file) > 2: - message = '%s: *** ' % constants.APP['name'] - message += 'invalid number of arguments for --%s' % mode - message += '\n%s: *** Exit.\n' % constants.APP['name'] - sys.stderr.write(message) - sys.exit(1) - files = list(cmdargs.mode_copy_file) - - # Determine specific settings. - destdir = cmdargs.destdir - if destdir != None: - destdir = cmdargs.destdir[0] - localdir = cmdargs.localdir - if localdir != None: - localdir = cmdargs.localdir[0] - 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 - flags = [cmdargs.inctests, cmdargs.obsolete, cmdargs.cxx, - cmdargs.longrunning, cmdargs.privileged, cmdargs.unportable, - cmdargs.alltests] - testflags = list() - for flag in flags: - index = flags.index(flag) - if flag != None: - if flag: - if index == 0: - testflags += [constants.TESTS['tests']] - elif index == 1: - testflags += [constants.TESTS['obsolete']] - elif index == 2: - testflags += [constants.TESTS['cxx-tests']] - elif index == 3: - testflags += [constants.TESTS['longrunning-tests']] - elif index == 4: - testflags += [constants.TESTS['privileged-tests']] - elif index == 5: - testflags += [constants.TESTS['unportable-tests']] - elif index == 6: - testflags += [constants.TESTS['all-tests']] - lgpl = cmdargs.lgpl - libtool = cmdargs.libtool - makefile = cmdargs.makefile - if lgpl == None: - lgpl = True - avoids = cmdargs.avoids - - # Create pygnulib configuration. - config = classes.GLConfig\ - ( - destdir=destdir, - localdir=localdir, - m4base=m4base, - auxdir=auxdir, - modules=modules, - avoids=avoids, - sourcebase=sourcebase, - pobase=pobase, - docbase=docbase, - testsbase=testsbase, - testflags=testflags, - libname=libname, - lgpl=lgpl, - makefile=makefile, - libtool=libtool, - conddeps=conddeps, - macro_prefix=macro_prefix, - podomain=podomain, - witness_c_macro=witness_c_macro, - vc_files=vc_files, - modcache=modcache, - verbose=verbose, - dryrun=dryrun, - ) - - # Canonicalize the inctests variable. - if inctests == None: - if mode in ['import', 'add-import', 'remove-import', 'update']: - config.disableTestFlag(TESTS['tests']) - elif mode in ['create-testdir', 'create-megatestdir', 'test', 'megatest']: - config.enableTestFlag(TESTS['tests']) - - # Work in the given mode. - if mode in ['list']: - modulesystem = classes.GLModuleSystem(config) - listing = modulesystem.list() - result = '\n'.join(listing) - os.rmdir(config['tempdir']) - print(result) - - 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 = constants.compiler(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 = \ - [ # Begin filtering - m4dir for m4dir in m4dirs \ - if isfile(joinpath(destdir, m4dir, 'gnulib-cache.m4')) - ] # Finish filtering - 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: + # Reset arguments + mode = None + destdir = None + localdir = None + modcache = None + verbose = None + auxdir = None + modules = None + avoids = None + sourcebase = None + m4base = None + pobase = None + docbase = None + testsbase = None + tests = None + libname = None + lgpl = None + makefile = None + libtool = None + conddeps = None + macro_prefix = None + podomain = None + witness_c_macro = None + vc_files = None + dryrun = None + errors = None + + info = classes.GLInfo() + parser = argparse.ArgumentParser( + prog=constants.APP['name'], + usage='gnulib-tool.py --help', + add_help=False) + # help + parser.add_argument('-h', '--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') + # list + parser.add_argument('-l', '--list', '--lis', + dest='mode_list', + default=None, + action='store_true') + # find + parser.add_argument('-f', '--find', '--fin', '--fi', '--f', + dest='mode_find', + default=None, + nargs='*') + # import + parser.add_argument('-i', '--import', + dest='mode_import', + default=None, + nargs='*') + # add-import + parser.add_argument('-a', '--add-import', + dest='mode_add_import', + default=None, + nargs='+') + # remove-import + parser.add_argument('-r', '--remove-import', + dest='mode_remove_import', + default=None, + nargs='+') + # update + parser.add_argument('-u', '--update', + dest='mode_update', + default=None, + action='store_true') + # create-testdir + parser.add_argument('-td', '--create-testdir', + dest='mode_create_testdir', + default=None, + nargs='*') + # create-megatestdir + parser.add_argument('-mtd', '--create-megatestdir', + dest='mode_create_megatestdir', + default=None, + nargs='*') + # test + parser.add_argument('-t', '--test', + dest='mode_test', + default=None, + nargs='*') + # megatest + parser.add_argument('-mt', '--megatest', '--megates', '--megate', '--megat', + '--mega', '--meg', '--me', '--m', + dest='mode_megatest', + default=None, + nargs='*') + # copy-file + parser.add_argument('-c', '--copy-file', + dest='mode_copy_file', + default=None, + nargs='+') + # extract-* + parser.add_argument('-xD', '--extract-description', + dest='mode_xdescription', + default=None, + nargs='*') + parser.add_argument('-xc', '--extract-comment', + dest='mode_xcomment', + default=None, + nargs='*') + parser.add_argument('-xs', '--extract-status', + dest='mode_xstatus', + default=None, + nargs='*') + parser.add_argument('-xn', '--extract-notice', + dest='mode_xnotice', + default=None, + nargs='*') + parser.add_argument('-xa', '--extract-applicability', + dest='mode_xapplicability', + default=None, + nargs='*') + parser.add_argument('-xf', '--extract-filelist', + dest='mode_xfilelist', + default=None, + nargs='*') + parser.add_argument('-xd', '--extract-dependencies', + dest='mode_xdependencies', + default=None, + nargs='*') + parser.add_argument('-xac', '--extract-autoconf-snippet', + dest='mode_xautoconf', + default=None, + nargs='*') + parser.add_argument('-xam', '--extract-automake-snippet', + dest='mode_xautomake', + default=None, + nargs='*') + parser.add_argument('-xi', '--extract-include-directive', + dest='mode_xinclude', + default=None, + nargs='*') + parser.add_argument('-xl', '--extract-link-directive', + dest='mode_xlink', + default=None, + nargs='*') + parser.add_argument('-xL', '--extract-license', + dest='mode_xlicense', + default=None, + nargs='*') + parser.add_argument('-xm', '--extract-maintainer', + dest='mode_xmaintainer', + default=None, + nargs='*') + # no-changelog + parser.add_argument('--no-changelog', + dest='changelog', + default=None, + action='store_false') + # destdir + parser.add_argument('-d', '--destdir', + dest='destdir', + default=None, + nargs=1) + # localdir + parser.add_argument('-ld', '--local-dir', + dest='localdir', + default=None, + nargs=1) + # verbose + parser.add_argument('-v', '--verbose', + default=0, + action='count') + # quiet + parser.add_argument('-q', '--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') + # makefile + parser.add_argument("--makefile-name", + dest="makefile", + default=None, + type=str) + # obsolete + parser.add_argument('--with-obsolete', + dest='obsolete', + default=None, + action='store_true') + # c++-tests + parser.add_argument('--with-c++-tests', + dest='cxx', + default=None, + action='store_true') + # longrunning-tests + parser.add_argument('--with-longrunning-tests', + dest='longrunning', + default=None, + action='store_true') + # privileged-tests + parser.add_argument('--with-privileged-tests', + dest='privileged', + default=None, + action='store_true') + # unportable-tests + parser.add_argument('--with-unportable-tests', + dest='unportable', + default=None, + action='store_true') + # all-tests + parser.add_argument('--with-all-tests', + dest='alltests', + default=None, + action='store_true') + # auxdir + parser.add_argument('--aux-dir', + dest='auxdir', + default=None, + nargs=1) + # libname + parser.add_argument('--lib', + dest='libname', + default=None, + nargs=1) + # libtool + parser.add_argument("--libtool", + dest=libtool, + default=False, + action="store_true") + # sourcebase + parser.add_argument('-sb', '--source-base', + dest='sourcebase', + default=None, + nargs=1) + # m4base + parser.add_argument('-mb', '--m4-base', + dest='m4base', + default=None, + nargs=1) + # pobase + parser.add_argument('-pb', '--po-base', + dest='pobase', + default=None, + nargs=1) + # docbase + parser.add_argument('-db', '--doc-base', + dest='docbase', + default=None, + nargs=1) + # testsbase + parser.add_argument('-tb', '--tests-base', + dest='testsbase', + default=None, + nargs=1) + # lgpl + parser.add_argument('--lgpl', + dest='lgpl', + default=False, + type=int, + nargs='?') + # avoids + parser.add_argument('--avoid', + dest='avoids', + default=None, + nargs='+') + + # Parse the given arguments. + cmdargs = parser.parse_args() + + # Determine when user tries to combine modes. + args = [ + cmdargs.mode_list, + 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_copy_file, + 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, + ] + overflow = [arg for arg in args if arg] + if len(overflow) > 1: + message = 'gnulib-tool: Unable to combine different modes of work.\n' + message += 'Try \'gnulib-tool --help\' for more information.\n' + sys.stderr.write(message) + sys.exit(1) + + # Determine selected mode. + if cmdargs.help != None: + print(info.usage()) + sys.exit(0) + if cmdargs.version != None: + message = '''gnulib-tool (%s %s)%s\n%s\n%s\n\nWritten by %s.''' % \ + (info.package(), info.date(), info.version(), info.copyright(), + info.license(), info.authors()) + print(message) + sys.exit(0) + if cmdargs.mode_list != None: + mode = 'list' + if cmdargs.mode_import != None: + mode = 'import' + modules = list(cmdargs.mode_import) + if cmdargs.mode_add_import != None: + mode = 'add-import' + modules = list(cmdargs.mode_add_import) + if cmdargs.mode_remove_import != None: + mode = 'remove-import' + modules = list(cmdargs.mode_remove_import) + if cmdargs.mode_update != None: + mode = 'update' + if cmdargs.mode_create_testdir != None: + mode = 'create-testdir' + modules = list(cmdargs.mode_create_testdir) + if cmdargs.mode_create_megatestdir != None: + mode = 'create-megatestdir' + modules = list(cmdargs.mode_create_megatestdir) + if cmdargs.mode_test != None: + mode = 'test' + modules = list(cmdargs.mode_test) + if cmdargs.mode_megatest != None: + mode = 'megatest' + modules = list(cmdargs.mode_megatest) + if cmdargs.mode_xdescription != None: + mode = 'extract-description' + modules = list(cmdargs.mode_xdescription) + if cmdargs.mode_xcomment != None: + mode = 'extract-comment' + modules = list(cmdargs.mode_xcomment) + if cmdargs.mode_xstatus != None: + mode = 'extract-status' + modules = list(cmdargs.mode_xstatus) + if cmdargs.mode_xnotice != None: + mode = 'extract-notice' + modules = list(cmdargs.mode_xnotice) + if cmdargs.mode_xapplicability != None: + mode = 'extract-applicability' + modules = list(cmdargs.mode_xapplicability) + if cmdargs.mode_xfilelist != None: + mode = 'extract-filelist' + modules = list(cmdargs.mode_xfilelist) + if cmdargs.mode_xautoconf != None: + mode = 'extract-autoconf-snippet' + modules = list(cmdargs.mode_xautoconf) + if cmdargs.mode_xautomake != None: + mode = 'extract-automake-snippet' + modules = list(cmdargs.mode_xautomake) + if cmdargs.mode_xdependencies != None: + mode = 'extract-dependencies' + modules = list(cmdargs.mode_xdependencies) + if cmdargs.mode_xinclude != None: + mode = 'extract-include-directive' + modules = list(cmdargs.mode_xinclude) + if cmdargs.mode_xlink != None: + mode = 'extract-link-directive' + modules = list(cmdargs.mode_xlink) + if cmdargs.mode_xlicense != None: + mode = 'extract-license' + modules = list(cmdargs.mode_xlicense) + if cmdargs.mode_xmaintainer != None: + mode = 'extract-maintainer' + modules = list(cmdargs.mode_xmaintainer) + if cmdargs.mode_copy_file != None: + mode = 'copy-file' + if len(cmdargs.mode_copy_file) > 2: + message = '%s: *** ' % constants.APP['name'] + message += 'invalid number of arguments for --%s' % mode + message += '\n%s: *** Exit.\n' % constants.APP['name'] + sys.stderr.write(message) + sys.exit(1) + files = list(cmdargs.mode_copy_file) + + # Determine specific settings. + destdir = cmdargs.destdir + if destdir != None: + destdir = cmdargs.destdir[0] + localdir = cmdargs.localdir + if localdir != None: + localdir = cmdargs.localdir[0] + 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 + flags = [cmdargs.inctests, cmdargs.obsolete, cmdargs.cxx, + cmdargs.longrunning, cmdargs.privileged, cmdargs.unportable, + cmdargs.alltests] + testflags = list() + for flag in flags: + index = flags.index(flag) + if flag != None: + if flag: + if index == 0: + testflags += [constants.TESTS['tests']] + elif index == 1: + testflags += [constants.TESTS['obsolete']] + elif index == 2: + testflags += [constants.TESTS['cxx-tests']] + elif index == 3: + testflags += [constants.TESTS['longrunning-tests']] + elif index == 4: + testflags += [constants.TESTS['privileged-tests']] + elif index == 5: + testflags += [constants.TESTS['unportable-tests']] + elif index == 6: + testflags += [constants.TESTS['all-tests']] + lgpl = cmdargs.lgpl + libtool = cmdargs.libtool + makefile = cmdargs.makefile + if lgpl == None: + lgpl = True + avoids = cmdargs.avoids + + # Create pygnulib configuration. + config = classes.GLConfig( + destdir=destdir, + localdir=localdir, + m4base=m4base, + auxdir=auxdir, + modules=modules, + avoids=avoids, + sourcebase=sourcebase, + pobase=pobase, + docbase=docbase, + testsbase=testsbase, + testflags=testflags, + libname=libname, + lgpl=lgpl, + makefile=makefile, + libtool=libtool, + conddeps=conddeps, + macro_prefix=macro_prefix, + podomain=podomain, + witness_c_macro=witness_c_macro, + vc_files=vc_files, + modcache=modcache, + verbose=verbose, + dryrun=dryrun, + ) + + # Canonicalize the inctests variable. + if inctests == None: + if mode in ['import', 'add-import', 'remove-import', 'update']: + config.disableTestFlag(TESTS['tests']) + elif mode in ['create-testdir', 'create-megatestdir', 'test', 'megatest']: + config.enableTestFlag(TESTS['tests']) + + # Work in the given mode. + if mode in ['list']: + modulesystem = classes.GLModuleSystem(config) + listing = modulesystem.list() + result = '\n'.join(listing) + os.rmdir(config['tempdir']) + print(result) + + 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) - - elif mode == 'create-testdir': - if not destdir: - message = '%s: *** ' % constants.APP['name'] - message += 'please specify --dir option' - message += '\n%s: *** Exit.\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' - message += '\n%s: *** Exit.\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) - modules = [modulesystem.find(module) for module in modules] - for module in modules: - print(module.getDescription()) - - elif mode == 'extract-comment': - modulesystem = classes.GLModuleSystem(config) - modules = [modulesystem.find(module) for module in modules] - for module in modules: - print(module.getComment()) - - elif mode == 'extract-status': - modulesystem = classes.GLModuleSystem(config) - modules = [modulesystem.find(module) for module in modules] - for module in modules: - status = module.getStatus() - print('\n'.join(status)) - - elif mode == 'extract-notice': - modulesystem = classes.GLModuleSystem(config) - modules = [modulesystem.find(module) for module in modules] - for module in modules: - print(module.getNotice()) - - elif mode == 'extract-applicability': - modulesystem = classes.GLModuleSystem(config) - modules = [modulesystem.find(module) for module in modules] - for module in modules: - print(module.getApplicability()) - - elif mode == 'extract-filelist': - modulesystem = classes.GLModuleSystem(config) - modules = [modulesystem.find(module) for module in modules] - for module in modules: - files = module.getFiles() - print('\n'.join(files)) - - elif mode == 'extract-dependencies': - result = string() - if avoids: - message = '%s: *** ' % constants.APP['name'] - message += 'cannot combine --avoid and --extract-dependencies\n' - message += '%s: *** Exit.\n' % constants.APP['name'] - sys.stderr.write(message) - sys.exit(1) - modulesystem = classes.GLModuleSystem(config) - modules = [modulesystem.find(module) for module in modules] - for module in modules: - dependencies = module.getDependencies() - if dependencies: - for depmodule, condition in dependencies: - if condition == None: - result += '%s\n' % str(depmodule) - else: # if condition != None - result += '%s\t%s' % (str(depmodule), condition) - print(result) - - elif mode == 'extract-autoconf-snippet': - modulesystem = classes.GLModuleSystem(config) - modules = [modulesystem.find(module) for module in modules] - for module in modules: - print(module.getAutoconfSnippet()) - - elif mode == 'extract-automake-snippet': - modulesystem = classes.GLModuleSystem(config) - modules = [modulesystem.find(module) for module in modules] - for module in modules: - print(module.getAutomakeSnippet()) - - elif mode == 'extract-include-directive': - modulesystem = classes.GLModuleSystem(config) - modules = [modulesystem.find(module) for module in modules] - for module in modules: - print(module.getInclude()) - - elif mode == 'extract-link-directive': - modulesystem = classes.GLModuleSystem(config) - modules = [modulesystem.find(module) for module in modules] - for module in modules: - print(module.getLink()) - - elif mode == 'extract-license': - modulesystem = classes.GLModuleSystem(config) - modules = [modulesystem.find(module) for module in modules] - for module in modules: - print(module.getLicense()) - - elif mode == 'extract-maintainer': - modulesystem = classes.GLModuleSystem(config) - modules = [modulesystem.find(module) for module in modules] - for module in modules: - print(module.getMaintainer()) - - elif mode == 'extract-tests-module': - modulesystem = classes.GLModuleSystem(config) - modules = [modulesystem.find(module) for module in modules] - for module in modules: - if module.getTestsModule(): - print(module.getTestsName()) - - elif mode == 'copy-file': - srcpath = files[0] - if len(files) == 2: - dest = files[1] - else: # if len(files) != 2 - dest = '.' - if type(srcpath) is bytes: - srcpath = srcpath.decode(ENCS['default']) - if type(dest) is bytes: - dest = dest.decode(ENCS['default']) - 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 = string(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('tests=lib/'): - destpath = constants.substart('tests=lib/', '%s/' % testsbase, srcpath) - elif srcpath.startswith('top/'): - destpath = constants.substart('top/', '', srcpath) - else: # either case - destpath = srcpath - else: # if not isdir(destpath) - destdir = os.path.dirname(destpath) - destpath = os.path.basename(destpath) - # 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) + + 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 = constants.compiler( + 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 = \ + [ # Begin filtering + m4dir for m4dir in m4dirs \ + if isfile(joinpath(destdir, m4dir, 'gnulib-cache.m4')) + ] # Finish filtering + 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' + message += '\n%s: *** Exit.\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' + message += '\n%s: *** Exit.\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: - pass - # Copy the file. - assistant = classes.GLFileAssistant(config) - tmpfile = assistant.tmpfilename(destpath) - shutil.copy(lookedup, tmpfile) - already_present = True - assistant.setOriginal(srcpath) - assistant.setRewritten(destpath) - if isfile(joinpath(destdir, destpath)): - # The file already exists. - assistant.update(lookedup, flag, tmpfile, already_present) - 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' - message += '\n%s: *** Exit.\n' % constants.APP['name'] - sys.stderr.write(message) - sys.exit(1) + 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) -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 = string() - 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 ' % errinfo - message += 'you run gnulib-tool from within your package\'s directory' - 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: - "%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 ' - message += 'supported with --with-tests\n' - elif errno == 11: - incompatibilities = string() - message += 'incompatible license on modules:%s' % constants.NL - for pair in errinfo: - incompatibilities += pair[0] - incompatibilities += ' %s' % pair[1] - incompatibilities += constants.NL - tempname = tempfile.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 in [13, 14, 15, 16, 17]: - message += 'failed' - elif errno == 19: - message += 'could not create destination directory: %s' % errinfo - if errno != 10: + 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) + modules = [modulesystem.find(module) for module in modules] + for module in modules: + print(module.getDescription()) + + elif mode == 'extract-comment': + modulesystem = classes.GLModuleSystem(config) + modules = [modulesystem.find(module) for module in modules] + for module in modules: + print(module.getComment()) + + elif mode == 'extract-status': + modulesystem = classes.GLModuleSystem(config) + modules = [modulesystem.find(module) for module in modules] + for module in modules: + status = module.getStatus() + print('\n'.join(status)) + + elif mode == 'extract-notice': + modulesystem = classes.GLModuleSystem(config) + modules = [modulesystem.find(module) for module in modules] + for module in modules: + print(module.getNotice()) + + elif mode == 'extract-applicability': + modulesystem = classes.GLModuleSystem(config) + modules = [modulesystem.find(module) for module in modules] + for module in modules: + print(module.getApplicability()) + + elif mode == 'extract-filelist': + modulesystem = classes.GLModuleSystem(config) + modules = [modulesystem.find(module) for module in modules] + for module in modules: + files = module.getFiles() + print('\n'.join(files)) + + elif mode == 'extract-dependencies': + result = string() + if avoids: + message = '%s: *** ' % constants.APP['name'] + message += 'cannot combine --avoid and --extract-dependencies\n' + message += '%s: *** Exit.\n' % constants.APP['name'] + sys.stderr.write(message) + sys.exit(1) + modulesystem = classes.GLModuleSystem(config) + modules = [modulesystem.find(module) for module in modules] + for module in modules: + dependencies = module.getDependencies() + if dependencies: + for depmodule, condition in dependencies: + if condition == None: + result += '%s\n' % str(depmodule) + else: # if condition != None + result += '%s\t%s' % (str(depmodule), condition) + print(result) + + elif mode == 'extract-autoconf-snippet': + modulesystem = classes.GLModuleSystem(config) + modules = [modulesystem.find(module) for module in modules] + for module in modules: + print(module.getAutoconfSnippet()) + + elif mode == 'extract-automake-snippet': + modulesystem = classes.GLModuleSystem(config) + modules = [modulesystem.find(module) for module in modules] + for module in modules: + print(module.getAutomakeSnippet()) + + elif mode == 'extract-include-directive': + modulesystem = classes.GLModuleSystem(config) + modules = [modulesystem.find(module) for module in modules] + for module in modules: + print(module.getInclude()) + + elif mode == 'extract-link-directive': + modulesystem = classes.GLModuleSystem(config) + modules = [modulesystem.find(module) for module in modules] + for module in modules: + print(module.getLink()) + + elif mode == 'extract-license': + modulesystem = classes.GLModuleSystem(config) + modules = [modulesystem.find(module) for module in modules] + for module in modules: + print(module.getLicense()) + + elif mode == 'extract-maintainer': + modulesystem = classes.GLModuleSystem(config) + modules = [modulesystem.find(module) for module in modules] + for module in modules: + print(module.getMaintainer()) + + elif mode == 'extract-tests-module': + modulesystem = classes.GLModuleSystem(config) + modules = [modulesystem.find(module) for module in modules] + for module in modules: + if module.getTestsModule(): + print(module.getTestsName()) + + elif mode == 'copy-file': + srcpath = files[0] + if len(files) == 2: + dest = files[1] + else: # if len(files) != 2 + dest = '.' + if type(srcpath) is bytes: + srcpath = srcpath.decode(ENCS['default']) + if type(dest) is bytes: + dest = dest.decode(ENCS['default']) + 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 = string(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('tests=lib/'): + destpath = constants.substart( + 'tests=lib/', '%s/' % testsbase, srcpath) + elif srcpath.startswith('top/'): + destpath = constants.substart('top/', '', srcpath) + else: # either case + destpath = srcpath + else: # if not isdir(destpath) + destdir = os.path.dirname(destpath) + destpath = os.path.basename(destpath) + # 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 Exception as error: + pass + # Copy the file. + assistant = classes.GLFileAssistant(config) + tmpfile = assistant.tmpfilename(destpath) + shutil.copy(lookedup, tmpfile) + already_present = True + assistant.setOriginal(srcpath) + assistant.setRewritten(destpath) + if isfile(joinpath(destdir, destpath)): + # The file already exists. + assistant.update(lookedup, flag, tmpfile, already_present) + 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' message += '\n%s: *** Exit.\n' % constants.APP['name'] - sys.stderr.write(message) - sys.exit(1) + 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 = string() + 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 ' % errinfo + message += 'you run gnulib-tool from within your package\'s directory' + 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: + "%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 ' + message += 'supported with --with-tests\n' + elif errno == 11: + incompatibilities = string() + message += 'incompatible license on modules:%s' % constants.NL + for pair in errinfo: + incompatibilities += pair[0] + incompatibilities += ' %s' % pair[1] + incompatibilities += constants.NL + tempname = tempfile.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 in [13, 14, 15, 16, 17]: + message += 'failed' + elif errno == 19: + message += 'could not create destination directory: %s' % errinfo + if errno != 10: + message += '\n%s: *** Exit.\n' % constants.APP['name'] + sys.stderr.write(message) + sys.exit(1) diff --git a/pygnulib/GLConfig.py b/pygnulib/GLConfig.py index ef997179cd..4d96fcb9dd 100644 --- a/pygnulib/GLConfig.py +++ b/pygnulib/GLConfig.py @@ -50,1137 +50,1105 @@ normpath = os.path.normpath # Define GLConfig class #=============================================================================== class GLConfig(object): - '''This class is used to store intermediate settings for all pygnulib - classes. It contains all necessary attributes to setup any other class. - By default all attributes are set to empty string, empty list or zero. - The most common value, however, is a None value.''' - - def __init__(self, destdir=None, localdir=None, auxdir=None, - sourcebase=None, m4base=None, pobase=None, docbase=None, testsbase=None, - modules=None, avoids=None, files=None, testflags=None, libname=None, - lgpl=None, makefile=None, libtool=None, conddeps=None, macro_prefix=None, - podomain=None, witness_c_macro=None, vc_files=None, symbolic=None, - lsymbolic=None, modcache=None, configure_ac=None, ac_version=None, - libtests=None, single_configure=None, verbose=None, dryrun=None, - errors=None): - '''GLConfig.__init__(arguments) -> GLConfig - - Create new GLConfig instance.''' - self.table = dict() - self.table['tempdir'] = tempfile.mkdtemp() - # destdir - self.resetDestDir() - if destdir != None: - self.setDestDir(destdir) - # localdir - self.resetLocalDir() - if localdir != None: - self.setLocalDir(localdir) - # auxdir - self.resetAuxDir() - if auxdir != None: - self.setAuxDir(auxdir) - # sourcebase - self.resetSourceBase() - if sourcebase != None: - self.setSourceBase(sourcebase) - # m4base - self.resetM4Base() - if m4base != None: - self.setM4Base(m4base) - # pobase - self.resetPoBase() - if pobase != None: - self.setPoBase(pobase) - # docbase - self.resetDocBase() - if docbase != None: - self.setDocBase(docbase) - # testsbase - self.resetTestsBase() - if testsbase != None: - self.setTestsBase(testsbase) - # modules - self.resetModules() - if modules != None: - self.setModules(modules) - # avoids - self.resetAvoids() - if avoids != None: - self.setAvoids(avoids) - # files - self.resetFiles() - if files != None: - self.setFiles(files) - # testflags - self.resetTestFlags() - if testflags != None: - self.setTestFlags(testflags) - # libname - self.resetLibName() - if libname != None: - self.setLibName(libname) - # lgpl - self.resetLGPL() - if lgpl != None: - self.setLGPL(lgpl) - # makefile - self.resetMakefile() - if makefile != None: - self.setMakefile(makefile) - # libtool - self.resetLibtool() - if libtool != None: - if type(libtool) is bool: - if not libtool: - self.disableLibtool() - else: # if libtool - self.enableLibtool() - else: # if type(libtool) is not bool - raise(TypeError('libtool must be a bool, not %s' % \ - type(libtool).__name__)) - # conddeps - self.resetCondDeps() - if conddeps != None: - if type(conddeps) is bool: - if not conddeps: - self.disableCondDeps() - else: # if conddeps - self.enableCondDeps() - else: # if type(conddeps) is not bool - raise(TypeError('conddeps must be a bool, not %s' % \ - type(conddeps).__name__)) - # macro_prefix - self.resetMacroPrefix() - if macro_prefix != None: - self.setMacroPrefix(macro_prefix) - # podomain - self.resetPoDomain() - if podomain != None: - self.setPoDomain(podomain) - # witness_c_macro - self.resetWitnessCMacro() - if witness_c_macro != None: - if type(witness_c_macro) is bool: - if not witness_c_macro: - self.setWitnessCMacro() - else: # if witness_c_macro - self.resetWitnessCMacro() - else: # if type(witness_c_macro) is not bool - raise(TypeError('witness_c_macro must be a bool, not %s' % \ - type(witness_c_macro).__name__)) - # vc_files - self.resetVCFiles() - if vc_files != None: - if type(vc_files) is bool: - if not vc_files: - self.disableVCFiles() - else: # if vc_files - self.enableVCFiles() - else: # if type(vc_files) is not bool - raise(TypeError('vc_files must be a bool, not %s' % \ - type(vc_files).__name__)) - # symbolic - self.resetSymbolic() - if symbolic != None: - if type(symbolic) is bool: - if not symbolic: - self.disableSymbolic() - else: # if symbolic - self.enableSymbolic() - else: # if type(symbolic) is not bool - raise(TypeError('symbolic must be a bool, not %s' % \ - type(symbolic).__name__)) - # lsymbolic - self.resetLSymbolic() - if lsymbolic != None: - if type(lsymbolic) is bool: - if not lsymbolic: - self.disableLSymbolic() - else: # if lsymbolic - self.enableLSymbolic() - else: # if type(lsymbolic) is not bool - raise(TypeError('lsymbolic must be a bool, not %s' % \ - type(lsymbolic).__name__)) - # modcache - self.resetModuleCaching() - if modcache != None: - if type(modcache) is bool: - if not modcache: - self.disableModuleCaching() - else: # if modcache - self.enableModuleCaching() - else: # if type(modcache) is not bool - raise(TypeError('modcache must be a bool, not %s' % \ - type(modcache).__name__)) - # configure_ac - self.resetAutoconfFile() - if configure_ac != None: - self.setAutoconfFile(configure_ac) - # ac_version - self.resetAutoconfVersion() - if ac_version != None: - self.setAutoconfVersion(ac_version) - # libtests - self.resetLibtests() - if libtests != None: - if type(libtests) is bool: - if not libtests: - self.disableLibtests() - else: # if libtests - self.enableLibtests() - else: # if type(libtests) is not bool - raise(TypeError('libtests must be a bool, not %s' % \ - type(libtests).__name__)) - # single_configure - self.resetSingleConfigure() - if single_configure != None: - if type(single_configure) is bool: - if not single_configure: - self.disableSingleConfigure() - else: # if single_configure - self.enableSingleConfigure() - else: # if type(single_configure) is not bool - raise(TypeError('single_configure must be a bool, not %s' % \ - type(single_configure).__name__)) - # verbose - self.resetVerbosity() - if verbose != None: - self.setVerbosity(verbose) - # dryrun - self.resetDryRun() - if dryrun != None: - if type(dryrun) is bool: - if not dryrun: - self.disableDryRun() - else: # if dryrun - self.enableDryRun() - else: # if type(dryrun) is not bool - raise(TypeError('dryrun must be a bool, not %s' % \ - type(dryrun).__name__)) - # errors - self.resetErrors() - if errors != None: - if type(errors) is bool: - if not errors: - self.disableErrors() - else: # if errors - self.enableErrors() - else: # if type(errors) is not bool - raise(TypeError('errors must be a bool, not %s' % \ - type(errors).__name__)) - - # Define special methods. - def __repr__(self): - '''x.__repr__() <==> repr(x)''' - return('') - - def __getitem__(self, y): - '''x.__getitem__(y) <==> x[y]''' - if y in self.table: - result = self.table[y] - if type(y) is list: - result = list(self.table[y]) - if y == "auxdir": + '''This class is used to store intermediate settings for all pygnulib + classes. It contains all necessary attributes to setup any other class. + By default all attributes are set to empty string, empty list or zero. + The most common value, however, is a None value.''' + + def __init__(self, destdir=None, localdir=None, auxdir=None, + sourcebase=None, m4base=None, pobase=None, docbase=None, testsbase=None, + modules=None, avoids=None, files=None, testflags=None, libname=None, + lgpl=None, makefile=None, libtool=None, conddeps=None, macro_prefix=None, + podomain=None, witness_c_macro=None, vc_files=None, symbolic=None, + lsymbolic=None, modcache=None, configure_ac=None, ac_version=None, + libtests=None, single_configure=None, verbose=None, dryrun=None, + errors=None): + '''GLConfig.__init__(arguments) -> GLConfig + + Create new GLConfig instance.''' + self.table = dict() + self.table['tempdir'] = tempfile.mkdtemp() + # destdir + self.resetDestDir() + if destdir != None: + self.setDestDir(destdir) + # localdir + self.resetLocalDir() + if localdir != None: + self.setLocalDir(localdir) + # auxdir + self.resetAuxDir() + if auxdir != None: + self.setAuxDir(auxdir) + # sourcebase + self.resetSourceBase() + if sourcebase != None: + self.setSourceBase(sourcebase) + # m4base + self.resetM4Base() + if m4base != None: + self.setM4Base(m4base) + # pobase + self.resetPoBase() + if pobase != None: + self.setPoBase(pobase) + # docbase + self.resetDocBase() + if docbase != None: + self.setDocBase(docbase) + # testsbase + self.resetTestsBase() + if testsbase != None: + self.setTestsBase(testsbase) + # modules + self.resetModules() + if modules != None: + self.setModules(modules) + # avoids + self.resetAvoids() + if avoids != None: + self.setAvoids(avoids) + # files + self.resetFiles() + if files != None: + self.setFiles(files) + # testflags + self.resetTestFlags() + if testflags != None: + self.setTestFlags(testflags) + # libname + self.resetLibName() + if libname != None: + self.setLibName(libname) + # lgpl + self.resetLGPL() + if lgpl != None: + self.setLGPL(lgpl) + # makefile + self.resetMakefile() + if makefile != None: + self.setMakefile(makefile) + # libtool + self.resetLibtool() + if libtool != None: + if type(libtool) is bool: + if not libtool: + self.disableLibtool() + else: # if libtool + self.enableLibtool() + else: # if type(libtool) is not bool + raise(TypeError('libtool must be a bool, not %s' % + type(libtool).__name__)) + # conddeps + self.resetCondDeps() + if conddeps != None: + if type(conddeps) is bool: + if not conddeps: + self.disableCondDeps() + else: # if conddeps + self.enableCondDeps() + else: # if type(conddeps) is not bool + raise(TypeError('conddeps must be a bool, not %s' % + type(conddeps).__name__)) + # macro_prefix + self.resetMacroPrefix() + if macro_prefix != None: + self.setMacroPrefix(macro_prefix) + # podomain + self.resetPoDomain() + if podomain != None: + self.setPoDomain(podomain) + # witness_c_macro + self.resetWitnessCMacro() + if witness_c_macro != None: + if type(witness_c_macro) is bool: + if not witness_c_macro: + self.setWitnessCMacro() + else: # if witness_c_macro + self.resetWitnessCMacro() + else: # if type(witness_c_macro) is not bool + raise(TypeError('witness_c_macro must be a bool, not %s' % + type(witness_c_macro).__name__)) + # vc_files + self.resetVCFiles() + if vc_files != None: + if type(vc_files) is bool: + if not vc_files: + self.disableVCFiles() + else: # if vc_files + self.enableVCFiles() + else: # if type(vc_files) is not bool + raise(TypeError('vc_files must be a bool, not %s' % + type(vc_files).__name__)) + # symbolic + self.resetSymbolic() + if symbolic != None: + if type(symbolic) is bool: + if not symbolic: + self.disableSymbolic() + else: # if symbolic + self.enableSymbolic() + else: # if type(symbolic) is not bool + raise(TypeError('symbolic must be a bool, not %s' % + type(symbolic).__name__)) + # lsymbolic + self.resetLSymbolic() + if lsymbolic != None: + if type(lsymbolic) is bool: + if not lsymbolic: + self.disableLSymbolic() + else: # if lsymbolic + self.enableLSymbolic() + else: # if type(lsymbolic) is not bool + raise(TypeError('lsymbolic must be a bool, not %s' % + type(lsymbolic).__name__)) + # modcache + self.resetModuleCaching() + if modcache != None: + if type(modcache) is bool: + if not modcache: + self.disableModuleCaching() + else: # if modcache + self.enableModuleCaching() + else: # if type(modcache) is not bool + raise(TypeError('modcache must be a bool, not %s' % + type(modcache).__name__)) + # configure_ac + self.resetAutoconfFile() + if configure_ac != None: + self.setAutoconfFile(configure_ac) + # ac_version + self.resetAutoconfVersion() + if ac_version != None: + self.setAutoconfVersion(ac_version) + # libtests + self.resetLibtests() + if libtests != None: + if type(libtests) is bool: + if not libtests: + self.disableLibtests() + else: # if libtests + self.enableLibtests() + else: # if type(libtests) is not bool + raise(TypeError('libtests must be a bool, not %s' % + type(libtests).__name__)) + # single_configure + self.resetSingleConfigure() + if single_configure != None: + if type(single_configure) is bool: + if not single_configure: + self.disableSingleConfigure() + else: # if single_configure + self.enableSingleConfigure() + else: # if type(single_configure) is not bool + raise(TypeError('single_configure must be a bool, not %s' % + type(single_configure).__name__)) + # verbose + self.resetVerbosity() + if verbose != None: + self.setVerbosity(verbose) + # dryrun + self.resetDryRun() + if dryrun != None: + if type(dryrun) is bool: + if not dryrun: + self.disableDryRun() + else: # if dryrun + self.enableDryRun() + else: # if type(dryrun) is not bool + raise(TypeError('dryrun must be a bool, not %s' % + type(dryrun).__name__)) + # errors + self.resetErrors() + if errors != None: + if type(errors) is bool: + if not errors: + self.disableErrors() + else: # if errors + self.enableErrors() + else: # if type(errors) is not bool + raise(TypeError('errors must be a bool, not %s' % + type(errors).__name__)) + + # Define special methods. + def __repr__(self): + '''x.__repr__() <==> repr(x)''' + return('') + + def __getitem__(self, y): + '''x.__getitem__(y) <==> x[y]''' + if y in self.table: + result = self.table[y] + if type(y) is list: + result = list(self.table[y]) + if y == "auxdir": + if self.table['auxdir']: + return self.table['auxdir'] + return "build-aux" + return(self.table[y]) + else: # if y not in self.table + raise(KeyError('GLConfig does not contain key: %s' % repr(y))) + + def dictionary(self): + '''Return the configuration as a dict object.''' + return(dict(self.table)) + + def copy(self): + '''Return the copy of the configuration.''' + table = copy.deepcopy(self) + return(table) + + def update(self, dictionary): + '''Specify the dictionary whose keys will be used to update config.''' + if type(dictionary) is not GLConfig: + raise(TypeError('dictionary must be a GLConfig, not %s' % + type(dictionary).__name__)) + dictionary = dict(dictionary.table) + result = dict() + for key in dictionary: + src = self.table[key] + dest = dictionary[key] + result[key] = src + if src != dest: + if self.isdefault(key, src): + result[key] = dest + else: # if not self.isdefault(key, src) + result[key] == src + if not self.isdefault(key, dest): + if key in ['modules', 'avoids', 'tests']: + dest = sorted(set(src + dest)) + result[key] = dest + self.table = dict(result) + + def update_key(self, dictionary, key): + '''Update the given key using value from the given dictionary.''' + if key in self.table: + if type(dictionary) is not GLConfig: + raise(TypeError('dictionary must be a GLConfig, not %s' % + type(dictionary).__name__)) + dictionary = dict(dictionary.table) + self.table[key] = dictionary[key] + else: # if key not in self.table + raise(KeyError('GLConfig does not contain key: %s' % repr(key))) + + def default(self, key): + '''Return default value for the given key.''' + if key in self.table: + if key == 'libname': + return(string('libgnu')) + elif key == 'macro_prefix': + return(string('gl')) + elif key == 'include_guard_prefix': + return(string('GL')) + elif key == 'ac_version': + return(2.59) + elif key == 'verbosity': + return(0) + elif key == 'copyrights': + return(True) + elif key in ['modules', 'avoids', 'tests', 'testflags']: + return(list()) + elif key in ['libtool', 'lgpl', 'conddeps', 'modcache', 'symbolic', + 'lsymbolic', 'libtests', 'dryrun']: + return(False) + if key == 'vc_files': + return(None) + elif key == 'errors': + return(True) + else: # otherwise + return(string()) + else: # if key not in self.table + raise(KeyError('GLConfig does not contain key: %s' % repr(key))) + + def isdefault(self, key, value): + '''Check whether the value for the given key is a default value.''' + if key in self.table: + default = self.default(key) + return(value == default) + else: # if key not in self.table + raise(KeyError('GLConfig does not contain key: %s' % repr(key))) + + def keys(self): + '''Return list of keys.''' + return(list(self.table.keys())) + + def values(self): + '''Return list of values.''' + return(list(self.table.values())) + + # Define destdir methods. + def getDestDir(self): + '''Return the target directory. For --import, this specifies where your + configure.ac can be found. Defaults to current directory.''' + return(self.table['destdir']) + + def setDestDir(self, destdir): + '''Specify the target directory. For --import, this specifies where your + configure.ac can be found. Defaults to current directory.''' + if type(destdir) is bytes or type(destdir) is string: + if type(destdir) is bytes: + destdir = string(destdir, ENCS['system']) + if destdir: + self.table['destdir'] = os.path.normpath(destdir) + else: # if destdir has not bytes/string type + raise(TypeError('destdir must be a string, not %s' % + type(destdir).__name__)) + + def resetDestDir(self): + '''Reset the target directory. For --import, this specifies where your + configure.ac can be found. Defaults to current directory.''' + self.table['destdir'] = string() + + # Define localdir methods. + def getLocalDir(self): + '''Return a local override directory where to look up files before looking + in gnulib's directory.''' + return(self.table['localdir']) + + def setLocalDir(self, localdir): + '''Specify a local override directory where to look up files before looking + in gnulib's directory.''' + if type(localdir) is bytes or type(localdir) is string: + if type(localdir) is bytes: + localdir = string(localdir, ENCS['system']) + if localdir: + self.table['localdir'] = localdir + else: # if localdir has not bytes/string type + raise(TypeError('localdir must be a string, not %s' % + type(localdir).__name__)) + + def resetLocalDir(self): + '''Reset a local override directory where to look up files before looking + in gnulib's directory.''' + self.table['localdir'] = string() + + # Define auxdir methods. + def getAuxDir(self): + '''Return directory relative to --dir where auxiliary build tools are + placed. Default comes from configure.ac or configure.in.''' if self.table['auxdir']: - return self.table['auxdir'] + return self.table['auxdir'] return "build-aux" - return(self.table[y]) - else: # if y not in self.table - raise(KeyError('GLConfig does not contain key: %s' % repr(y))) - - def dictionary(self): - '''Return the configuration as a dict object.''' - return(dict(self.table)) - - def copy(self): - '''Return the copy of the configuration.''' - table = copy.deepcopy(self) - return(table) - - def update(self, dictionary): - '''Specify the dictionary whose keys will be used to update config.''' - if type(dictionary) is not GLConfig: - raise(TypeError('dictionary must be a GLConfig, not %s' % \ - type(dictionary).__name__)) - dictionary = dict(dictionary.table) - result = dict() - for key in dictionary: - src = self.table[key] - dest = dictionary[key] - result[key] = src - if src != dest: - if self.isdefault(key, src): - result[key] = dest - else: # if not self.isdefault(key, src) - result[key] == src - if not self.isdefault(key, dest): - if key in ['modules', 'avoids', 'tests']: - dest = sorted(set(src +dest)) - result[key] = dest - self.table = dict(result) - - def update_key(self, dictionary, key): - '''Update the given key using value from the given dictionary.''' - if key in self.table: - if type(dictionary) is not GLConfig: - raise(TypeError('dictionary must be a GLConfig, not %s' % \ - type(dictionary).__name__)) - dictionary = dict(dictionary.table) - self.table[key] = dictionary[key] - else: # if key not in self.table - raise(KeyError('GLConfig does not contain key: %s' % repr(key))) - - def default(self, key): - '''Return default value for the given key.''' - if key in self.table: - if key == 'libname': - return(string('libgnu')) - elif key == 'macro_prefix': - return(string('gl')) - elif key == 'include_guard_prefix': - return(string('GL')) - elif key == 'ac_version': - return(2.59) - elif key == 'verbosity': - return(0) - elif key == 'copyrights': - return(True) - elif key in ['modules', 'avoids', 'tests', 'testflags']: - return(list()) - elif key in ['libtool', 'lgpl', 'conddeps', 'modcache', 'symbolic', - 'lsymbolic', 'libtests', 'dryrun']: - return(False) - if key == 'vc_files': - return(None) - elif key == 'errors': - return(True) - else: # otherwise - return(string()) - else: # if key not in self.table - raise(KeyError('GLConfig does not contain key: %s' % repr(key))) - - def isdefault(self, key, value): - '''Check whether the value for the given key is a default value.''' - if key in self.table: - default = self.default(key) - return(value == default) - else: # if key not in self.table - raise(KeyError('GLConfig does not contain key: %s' % repr(key))) - - def keys(self): - '''Return list of keys.''' - return(list(self.table.keys())) - - def values(self): - '''Return list of values.''' - return(list(self.table.values())) - - - # Define destdir methods. - def getDestDir(self): - '''Return the target directory. For --import, this specifies where your - configure.ac can be found. Defaults to current directory.''' - return(self.table['destdir']) - - def setDestDir(self, destdir): - '''Specify the target directory. For --import, this specifies where your - configure.ac can be found. Defaults to current directory.''' - if type(destdir) is bytes or type(destdir) is string: - if type(destdir) is bytes: - destdir = string(destdir, ENCS['system']) - if destdir: - self.table['destdir'] = os.path.normpath(destdir) - else: # if destdir has not bytes/string type - raise(TypeError('destdir must be a string, not %s' % \ - type(destdir).__name__)) - - def resetDestDir(self): - '''Reset the target directory. For --import, this specifies where your - configure.ac can be found. Defaults to current directory.''' - self.table['destdir'] = string() - - - # Define localdir methods. - def getLocalDir(self): - '''Return a local override directory where to look up files before looking - in gnulib's directory.''' - return(self.table['localdir']) - - def setLocalDir(self, localdir): - '''Specify a local override directory where to look up files before looking - in gnulib's directory.''' - if type(localdir) is bytes or type(localdir) is string: - if type(localdir) is bytes: - localdir = string(localdir, ENCS['system']) - if localdir: - self.table['localdir'] = localdir - else: # if localdir has not bytes/string type - raise(TypeError('localdir must be a string, not %s' % \ - type(localdir).__name__)) - - def resetLocalDir(self): - '''Reset a local override directory where to look up files before looking - in gnulib's directory.''' - self.table['localdir'] = string() - - - # Define auxdir methods. - def getAuxDir(self): - '''Return directory relative to --dir where auxiliary build tools are - placed. Default comes from configure.ac or configure.in.''' - if self.table['auxdir']: - return self.table['auxdir'] - return "build-aux" - - def setAuxDir(self, auxdir): - '''Specify directory relative to --dir where auxiliary build tools are - placed. Default comes from configure.ac or configure.in.''' - if type(auxdir) is bytes or type(auxdir) is string: - if type(auxdir) is bytes: - auxdir = string(auxdir, ENCS['system']) - if auxdir: - self.table['auxdir'] = auxdir - else: # if type of auxdir is not bytes or string - raise(TypeError('auxdir must be a string, not %s' % \ - type(auxdir).__name__)) - - def resetAuxDir(self): - '''Reset directory relative to --dir where auxiliary build tools are - placed. Default comes from configure.ac or configure.in.''' - self.table['auxdir'] = string() - - - # Define sourcebase methods. - def getSourceBase(self): - '''Return directory relative to destdir where source code is placed.''' - return(self.table['sourcebase']) - - def setSourceBase(self, sourcebase): - '''Specify directory relative to destdir where source code is placed.''' - if type(sourcebase) is bytes or type(sourcebase) is string: - if type(sourcebase) is bytes: - sourcebase = string(sourcebase, ENCS['system']) - if sourcebase: - self.table['sourcebase'] = sourcebase - else: # if type of sourcebase is not bytes or string - raise(TypeError('sourcebase must be a string, not %s' % \ - type(sourcebase).__name__)) - - def resetSourceBase(self): - '''Return directory relative to destdir where source code is placed.''' - self.table['sourcebase'] = string() - - - # Define m4base methods. - def getM4Base(self): - '''Return directory relative to destdir where *.m4 macros are placed.''' - return(self.table['m4base']) - - def setM4Base(self, m4base): - '''Specify directory relative to destdir where *.m4 macros are placed.''' - if type(m4base) is bytes or type(m4base) is string: - if type(m4base) is bytes: - m4base = string(m4base, ENCS['system']) - if m4base: - self.table['m4base'] = m4base - else: # if type of m4base is not bytes or string - raise(TypeError('m4base must be a string, not %s' % \ - type(m4base).__name__)) - - def resetM4Base(self): - '''Reset directory relative to destdir where *.m4 macros are placed.''' - self.table['m4base'] = string() - - - # Define pobase methods. - def getPoBase(self): - '''Return directory relative to destdir where *.po files are placed.''' - return(self.table['pobase']) - - def setPoBase(self, pobase): - '''Specify directory relative to destdir where *.po files are placed.''' - if type(pobase) is bytes or type(pobase) is string: - if type(pobase) is bytes: - pobase = string(pobase, ENCS['system']) - if pobase: - self.table['pobase'] = pobase - else: # if type of pobase is not bytes or string - raise(TypeError('pobase must be a string, not %s' % \ - type(pobase).__name__)) - - def resetPoBase(self): - '''Reset directory relative to destdir where *.po files are placed.''' - self.table['pobase'] = string() - - - # Define docbase methods. - def getDocBase(self): - '''Return directory relative to destdir where doc files are placed. - Default value for this variable is 'doc').''' - return(self.table['docbase']) - - def setDocBase(self, docbase): - '''Specify directory relative to destdir where doc files are placed. - Default value for this variable is 'doc').''' - if type(docbase) is bytes or type(docbase) is string: - if type(docbase) is bytes: - docbase = string(docbase, ENCS['system']) - if docbase: - self.table['docbase'] = docbase - else: # if type of docbase is not bytes or string - raise(TypeError('docbase must be a string, not %s' % \ - type(docbase).__name__)) - - def resetDocBase(self): - '''Reset directory relative to destdir where doc files are placed. - Default value for this variable is 'doc').''' - self.table['docbase'] = string() - - - # Define testsbase methods. - def getTestsBase(self): - '''Return directory relative to destdir where unit tests are placed. - Default value for this variable is 'tests').''' - return(self.table['testsbase']) - - def setTestsBase(self, testsbase): - '''Specify directory relative to destdir where unit tests are placed. - Default value for this variable is 'tests').''' - if type(testsbase) is bytes or type(testsbase) is string: - if type(testsbase) is bytes: - testsbase = string(testsbase, ENCS['system']) - if testsbase: - self.table['testsbase'] = testsbase - else: # if type of testsbase is not bytes or string - raise(TypeError('testsbase must be a string, not %s' % \ - type(testsbase).__name__)) - - def resetTestsBase(self): - '''Reset directory relative to destdir where unit tests are placed. - Default value for this variable is 'tests').''' - self.table['testsbase'] = string() - - - # Define modules methods. - def addModule(self, module): - '''Add the module to the modules list.''' - if type(module) is bytes or type(module) is string: - if type(module) is bytes: - module = module.decode(ENCS['default']) - if module not in self.table['modules']: - self.table['modules'] += [module] - else: # if module has not bytes or string type - raise(TypeError('module must be a string, not %s' % \ - type(module).__name__)) - - def removeModule(self, module): - '''Remove the module from the modules list.''' - if type(module) is bytes or type(module) is string: - if type(module) is bytes: - module = module.decode(ENCS['default']) - if module in self.table['modules']: - self.table['modules'].remove(module) - else: # if module has not bytes or string type - raise(TypeError('module must be a string, not %s' % \ - type(module).__name__)) - - def getModules(self): - '''Return the modules list.''' - return(list(self.table['modules'])) - - def setModules(self, modules): - '''Set the modules list.''' - if type(modules) is list or type(modules) is tuple: - old_modules = self.table['modules'] - self.table['modules'] = list() - for module in modules: - try: # Try to add each module - self.addModule(module) - except TypeError as error: - self.table['modules'] = old_modules - raise(TypeError('each module must be a string')) - except GLError as error: - self.table['modules'] = old_modules - raise(GLError(error.errno, error.errinfo)) - else: # if type of modules is not list or tuple - raise(TypeError('modules must be a list or a tuple, not %s' % \ - type(modules).__name__)) - - def resetModules(self): - '''Reset the list of the modules.''' - self.table['modules'] = list() - - - # Define avoids methods. - def addAvoid(self, module): - '''Avoid including the given module. Useful if you have code that provides - equivalent functionality.''' - if type(module) is bytes or type(module) is string: - if type(module) is bytes: - module = module.decode(ENCS['default']) - if module not in self.table['avoids']: - self.table['avoids'].append(module) - else: # if module has not bytes or string type - raise(TypeError('avoid must be a string, not %s' % \ - type(module).__name__)) - - def removeAvoid(self, module): - '''Remove the given module from the list of avoided modules.''' - if type(module) is bytes or type(module) is string: - if type(module) is bytes: - module = module.decode(ENCS['default']) - if module in self.table['avoids']: - self.table['avoids'].remove(module) - else: # if module has not bytes or string type - raise(TypeError('avoid must be a string, not %s' % \ - type(module).__name__)) - - def getAvoids(self): - '''Return the list of the avoided modules.''' - return(list(self.table['avoids'])) - - def setAvoids(self, modules): - '''Specify the modules which will be avoided.''' - if type(modules) is list or type(modules) is tuple: - old_avoids = self.table['avoids'] - self.table['avoids'] = list() - for module in modules: - try: # Try to add each module - self.addAvoid(module) - except TypeError as error: - self.table['avoids'] = old_avoids - raise(TypeError('each module must be a string')) - except GLError as error: - self.table['avoids'] = old_avoids - raise(GLError(error.errno, error.errinfo)) - else: # if type of modules is not list or tuple - raise(TypeError('modules must be a list or a tuple, not %s' % \ - type(modules).__name__)) - - def resetAvoids(self): - '''Reset the list of the avoided modules.''' - self.table['avoids'] = list() - - - # Define files methods. - def addFile(self, file): - '''Add file to the list of files.''' - if type(file) is bytes or type(file) is string: - if type(file) is bytes: - file = file.decode(ENCS['default']) - if file not in self.table['files']: - self.table['files'].append(file) - else: # if file has not bytes or string type - raise(TypeError('file must be a string, not %s' % \ - type(file).__name__)) - - def removeFile(self, file): - '''Remove the given file from the list of files.''' - if type(file) is bytes or type(file) is string: - if type(file) is bytes: - file = file.decode(ENCS['default']) - if file in self.table['files']: - self.table['files'].remove(file) - else: # if file has not bytes or string type - raise(TypeError('file must be a string, not %s' % \ - type(file).__name__)) - - def getFiles(self): - '''Return the list of the fileed files.''' - return(list(self.table['files'])) - - def setFiles(self, files): - '''Specify the list of files.''' - if type(files) is list or type(files) is tuple: - old_files = self.table['files'] - self.table['files'] = list() - for file in files: - try: # Try to add each file - self.addFile(file) - except TypeError as error: - self.table['files'] = old_files - raise(TypeError('each file must be a string')) - except GLError as error: - self.table['files'] = old_files - raise(GLError(error.errno, error.errinfo)) - else: # if type of files is not list or tuple - raise(TypeError('files must be a list or a tuple, not %s' % \ - type(files).__name__)) - - def resetFiles(self): - '''Reset the list of files.''' - self.table['files'] = list() - - - # Define tests/testflags methods - def checkTestFlag(self, flag): - '''Return the status of the test flag.''' - if flag in TESTS.values(): - return(flag in self.table['testflags']) - else: # if flag is not in TESTS - raise(TypeError('unknown flag: %s' % repr(flag))) - - def enableTestFlag(self, flag): - '''Enable test flag. You can get flags from TESTS variable.''' - if flag in TESTS.values(): - if flag not in self.table['testflags']: - self.table['testflags'].append(flag) - else: # if flag is not in TESTS - raise(TypeError('unknown flag: %s' % repr(flag))) - - def disableTestFlag(self, flag): - '''Disable test flag. You can get flags from TESTS variable.''' - if flag in TESTS.values(): - if flag in self.table['testflags']: - self.table['testflags'].remove(flag) - else: # if flag is not in TESTS - raise(TypeError('unknown flag: %s' % repr(flag))) - - def getTestFlags(self): - '''Return test flags. You can get flags from TESTS variable.''' - return(list(self.table['testflags'])) - - def setTestFlags(self, testflags): - '''Specify test flags. You can get flags from TESTS variable.''' - if type(testflags) is list or type(testflags) is tuple: - old_testflags = self.table['testflags'] - self.table['testflags'] = list() - for flag in testflags: - try: # Try to enable each flag - self.enableTestFlag(flag) - except TypeError as error: - raise(TypeError('each flag must be one of TESTS integers')) - self.table['testflags'] = testflags - else: # if type of testflags is not list or tuple - raise(TypeError('testflags must be a list or a tuple, not %s' % \ - type(testflags).__name__)) - - def resetTestFlags(self): - '''Reset test flags (only default flag will be enabled).''' - self.table['testflags'] = list() - self.table['tests'] = self.table['testflags'] - - - # Define libname methods. - def getLibName(self): - '''Return the library name.''' - return(self.table['libname']) - - def setLibName(self, libname): - '''Specify the library name.''' - if type(libname) is bytes or type(libname) is string: - if type(libname) is bytes: - libname = string(libname, ENCS['system']) - if libname: - self.table['libname'] = libname - else: # if type of libname is not bytes or string - raise(TypeError('libname must be a string, not %s' % \ - type(module).__name__)) - - def resetLibName(self): - '''Reset the library name to 'libgnu'.''' - self.table['libname'] = string('libgnu') - - - # Define libtool methods. - def checkLibtool(self): - '''Check if user enabled libtool rules.''' - return(self.table['libtool']) - - def enableLibtool(self): - '''Enable libtool rules.''' - self.table['libtool'] = True - - def disableLibtool(self): - '''Disable libtool rules.''' - self.table['libtool'] = False - - def resetLibtool(self): - '''Reset libtool rules.''' - self.table['libtool'] = False - - - # Define conddeps methods. - def checkCondDeps(self): - '''Check if user enabled cond. dependencies.''' - return(self.table['conddeps']) - - def enableCondDeps(self): - '''Enable cond. dependencies (may save configure time and object code).''' - self.table['conddeps'] = True - - def disableCondDeps(self): - '''Disable cond. dependencies (may save configure time and object code).''' - self.table['conddeps'] = False - - def resetCondDeps(self): - '''Reset cond. dependencies (may save configure time and object code).''' - self.table['conddeps'] = False - - - # Define lgpl methods. - def getLGPL(self): - '''Check for abort if modules aren't available under the LGPL. - Default value is False, which means that lgpl is disabled.''' - return(self.table['lgpl']) - - def setLGPL(self, lgpl): - '''Abort if modules aren't available under the LGPL. - Default value is False, which means that lgpl is disabled.''' - if (type(lgpl) is int and 2 <= lgpl <= 3) or type(lgpl) is bool: - self.table['lgpl'] = lgpl - else: # if lgpl is not False, 2 or 3 - raise(TypeError('invalid LGPL version: %s' % repr(lgpl))) - - def resetLGPL(self): - '''Disable abort if modules aren't available under the LGPL. - Default value is False, which means that lgpl is disabled.''' - self.table['lgpl'] = False - - - # Define macro_prefix methods. - def getIncludeGuardPrefix(self): - '''Return include_guard_prefix to use inside GLEmiter class.''' - return(self.table['include_guard_prefix']) - - def getMacroPrefix(self): - '''Return the prefix of the macros 'gl_EARLY' and 'gl_INIT'. - Default macro_prefix is 'gl'.''' - return(self.table['macro_prefix']) - - def setMacroPrefix(self, macro_prefix): - '''Specify the prefix of the macros 'gl_EARLY' and 'gl_INIT'. - Default macro_prefix is 'gl'.''' - if type(macro_prefix) is bytes or type(macro_prefix) is string: - if type(macro_prefix) is bytes: - macro_prefix = string(macro_prefix, ENCS['system']) - if macro_prefix: - self.table['macro_prefix'] = macro_prefix - else: # if type of macro_prefix is not bytes or string - raise(TypeError('macro_prefix must be a string, not %s' % \ - type(macro_prefix).__name__)) - if macro_prefix == 'gl': - include_guard_prefix = 'GL' - else: # macro_prefix != 'gl' - include_guard_prefix = 'GL_%s' % macro_prefix.upper() - if type(include_guard_prefix) is bytes: - include_guard_prefix = include_guard_prefix.decode(ENCS['default']) - self.table['include_guard_prefix'] = include_guard_prefix - - def resetMacroPrefix(self): - '''Reset the prefix of the macros 'gl_EARLY' and 'gl_INIT'. - Default macro_prefix is 'gl'.''' - self.table['macro_prefix'] = string('gl') - include_guard_prefix = string('GL') - if type(include_guard_prefix) is bytes: - include_guard_prefix = include_guard_prefix.decode(ENCS['default']) - self.table['include_guard_prefix'] = include_guard_prefix - - - # Define makefile methods. - def getMakefile(self): - '''Return the name of makefile in automake syntax in the source-base and - tests-base directories. Default is 'Makefile.am'.''' - return(self.table['makefile']) - - def setMakefile(self, makefile): - '''Specify the name of makefile in automake syntax in the source-base and - tests-base directories. Default is 'Makefile.am'.''' - if type(makefile) is bytes or type(makefile) is string: - if type(makefile) is bytes: - makefile = string(makefile, ENCS['system']) - if makefile: - self.table['makefile'] = makefile - else: # if type of makefile is not bytes or string - raise(TypeError('makefile must be a string, not %s' % - type(makefile).__name__)) - - def resetMakefile(self): - '''Reset the name of makefile in automake syntax in the source-base and - tests-base directories. Default is 'Makefile.am'.''' - self.table['makefile'] = string() - - - # Define podomain methods. - def getPoDomain(self): - '''Return the prefix of the i18n domain. Usually use the package name. - A suffix '-gnulib' is appended.''' - return(self.table['podomain']) - - def setPoDomain(self, podomain): - '''Specify the prefix of the i18n domain. Usually use the package name. - A suffix '-gnulib' is appended.''' - if type(podomain) is bytes or type(podomain) is string: - if type(podomain) is bytes: - podomain = string(podomain, ENCS['system']) - if podomain: - self.table['podomain'] = podomain - else: # if type of podomain is not bytes or string - raise(TypeError('podomain must be a string, not %s' % \ - type(podomain).__name__)) - - def resetPoDomain(self): - '''Reset the prefix of the i18n domain. Usually use the package name. - A suffix '-gnulib' is appended.''' - self.table['podomain'] = string() - - - # Define witness_c_macro methods. - def getWitnessCMacro(self): - '''Return the C macro that is defined when the sources in this directory - are compiled or used.''' - return(self.table['witness_c_macro']) - - def setWitnessCMacro(self, witness_c_macro): - '''Specify the C macro that is defined when the sources in this directory - are compiled or used.''' - if type(witness_c_macro) is bytes or type(witness_c_macro) is string: - if type(witness_c_macro) is bytes: - witness_c_macro = string(witness_c_macro, ENCS['system']) - if witness_c_macro: - self.table['witness_c_macro'] = witness_c_macro - else: # if type of witness_c_macro is not bytes or string - raise(TypeError('witness_c_macro must be a string, not %s' % - type(witness_c_macro).__name__)) - - def resetWitnessCMacro(self): - '''Return the C macro that is defined when the sources in this directory - are compiled or used.''' - self.table['witness_c_macro'] = string() - - - # Define vc_files methods. - def checkVCFiles(self): - '''Check if update of the version control files is enabled or disabled.''' - return(self.table['vc_files']) - - def enableVCFiles(self): - '''Enable update of the version control files.''' - self.table['vc_files'] = True - - def disableVCFiles(self): - '''Disable update of the version control files.''' - self.table['vc_files'] = False - - def resetVCFiles(self): - '''Reset update of the version control files and set it to None.''' - self.table['vc_files'] = None - - - # Define modcache methods. - def checkModuleCaching(self): - '''Get status of module caching optimization.''' - return(self.table['modcache']) - - def enableModuleCaching(self): - '''Enable module caching optimization.''' - self.table['modcache'] = True - - def disableModuleCaching(self): - '''Disable module caching optimization.''' - self.table['modcache'] = False - - def resetModuleCaching(self): - '''Reset module caching optimization.''' - self.table['modcache'] = False - - - # Define configure_ac methods. - def getAutoconfFile(self): - '''Return path of autoconf file relative to destdir.''' - return(self.table['configure_ac']) - - def setAutoconfFile(self, configure_ac): - '''Specify path of autoconf file relative to destdir.''' - if type(configure_ac) is bytes or type(configure_ac) is string: - if type(configure_ac) is bytes: - configure_ac = string(configure_ac, ENCS['system']) - if configure_ac: - self.table['configure_ac'] = \ - relpath(self.table['destdir'],configure_ac) - else: # if type of configure_ac is not bytes or string - raise(TypeError('configure_ac must be a string, not %s' % \ - type(configure_ac).__name__)) - - def resetAutoconfFile(self): - '''Reset path of autoconf file relative to destdir.''' - configure_ac = string() - if isfile(joinpath(self.table['destdir'], 'configure.ac')): - configure_ac = joinpath(self.table['destdir'], 'configure.ac') - elif isfile(joinpath(self.table['destdir'], 'configure.in')): - configure_ac = joinpath(self.table['destdir'], 'configure.in') - self.table['configure_ac'] = configure_ac - - - # Define ac_version methods. - def getAutoconfVersion(self): - '''Return preferred autoconf version. Default value is 2.59.''' - return(self.table['ac_version']) - - def setAutoconfVersion(self, ac_version): - '''Specify preferred autoconf version. Default value is 2.59.''' - if type(ac_version) is float or type(ac_version) is int: - self.table['ac_version'] = float(ac_version) - else: # if ac_version has not int or float type - raise(TypeError('ac_version must be an int or a float, not %s' % \ - type(ac_version).__name__)) - - def resetAutoconfVersion(self): - '''Specify preferred autoconf version. Default value is 2.59.''' - self.table['ac_version'] = 2.59 - - - # Define symbolic methods. - def checkCopyrights(self): - '''Check if copyright notices in files should be replaced.''' - return(self.table['copyrights']) - - def checkSymbolic(self): - '''Check if pygnulib will make symbolic links instead of copying files.''' - return(self.table['symbolic']) - - def enableSymbolic(self): - '''Enable creation of the symbolic links instead of copying files.''' - self.table['symbolic'] = True - self.table['copyrights'] = False - - def disableSymbolic(self): - '''Enable creation of the symbolic links instead of copying files.''' - self.table['symbolic'] = False - self.table['copyrights'] = True - - def resetSymbolic(self): - '''Reset creation of the symbolic links instead of copying files.''' - self.table['symbolic'] = False - self.table['copyrights'] = True - - - # Define lsymbolic methods. - def checkLSymbolic(self): - '''Check if pygnulib will make symbolic links instead of copying files, only - for files from the local override directory.''' - return(self.table['lsymbolic']) - - def enableLSymbolic(self): - '''Enable creation of symbolic links instead of copying files, only for - files from the local override directory.''' - self.table['lsymbolic'] = True - - def disableLSymbolic(self): - '''Disable creation of symbolic links instead of copying files, only for - files from the local override directory.''' - self.table['lsymbolic'] = False - - def resetLSymbolic(self): - '''Reset creation of symbolic links instead of copying files, only for - files from the local override directory.''' - self.table['lsymbolic'] = False - - - # Define verbosity methods. - def getVerbosity(self): - '''Get verbosity level.''' - return(self.table['verbosity']) - - def decreaseVerbosity(self): - '''Decrease verbosity level.''' - if self.table['verbosity'] > MODES['verbose-min']: - self.table['verbosity'] -= 1 - - def increaseVerbosity(self): - '''Increase verbosity level.''' - if self.table['verbosity'] < MODES['verbose-max']: - self.table['verbosity'] += 1 - - def setVerbosity(self, verbose): - '''Set verbosity level to verbose, where -2 <= verbose <= 2. - If verbosity level is less than -2, verbosity level will be set to -2. - If verbosity level is greater than 2, verbosity level will be set to 2.''' - if type(verbose) is int: - if MODES['verbose-min'] <= verbose <= MODES['verbose-max']: - self.table['verbosity'] = verbose - elif verbose < MODES['verbose-min']: - self.table['verbosity'] = MODES['verbose-min'] - elif verbose > MODES['verbose-max']: - self.table['verbosity'] = MODES['verbose-max'] - else: # if type(verbose) is not int - raise(TypeError('verbosity must be an int, not %s' % \ - type(verbose).__name__)) - - def resetVerbosity(self): - '''Reset verbosity level.''' - self.table['verbosity'] = 0 - - - # Define libtests methods. - def checkLibtests(self): - '''Return True if a testsbase/libtests.a is needed.''' - return(self.table['libtests']) - - def enableLibtests(self): - '''If libtests is enabled, then testsbase/libtests.a is needed.''' - self.table['libtests'] = True - - def disableLibtests(self): - '''If libtests is disabled, then testsbase/libtests.a is not needed.''' - self.table['libtests'] = False - - def resetLibtests(self): - '''Reset status of testsbase/libtests.a.''' - self.table['libtests'] = False - - - # Define single_configure methods. - def checkSingleConfigure(self): - '''Check whether single configure file should be generated.''' - return(self.table['single_configure']) - - def enableSingleConfigure(self): - '''Enable generation of the single configure file.''' - self.table['single_configure'] = True - - def disableSingleConfigure(self): - '''Disable generation of the single configure file.''' - self.table['single_configure'] = False - - def resetSingleConfigure(self): - '''Reset status of the single configure file generation.''' - self.table['single_configure'] = False - - - # Define dryrun methods. - def checkDryRun(self): - '''Check whether dryrun is enabled.''' - return(self.table['dryrun']) - - def enableDryRun(self): - '''Enable dryrun mode.''' - self.table['dryrun'] = True - - def disableDryRun(self): - '''Disable dryrun mode.''' - self.table['dryrun'] = False - - def resetDryRun(self): - '''Reset status of dryrun mode.''' - self.table['dryrun'] = False - - - # Define errors methods. - def checkErrors(self): - '''Check if GLError will be raised in non-critical situations.''' - return(self.table['errors']) - - def enableErrors(self): - '''Raise GLError in non-critical situations.''' - self.table['errors'] = True - - def disableErrors(self): - '''Do not raise GLError in non-critical situations.''' - self.table['errors'] = False - - def resetErrors(self): - '''Reset status of raising GLError in non-critical situations.''' - self.table['errors'] = False + def setAuxDir(self, auxdir): + '''Specify directory relative to --dir where auxiliary build tools are + placed. Default comes from configure.ac or configure.in.''' + if type(auxdir) is bytes or type(auxdir) is string: + if type(auxdir) is bytes: + auxdir = string(auxdir, ENCS['system']) + if auxdir: + self.table['auxdir'] = auxdir + else: # if type of auxdir is not bytes or string + raise(TypeError('auxdir must be a string, not %s' % + type(auxdir).__name__)) + + def resetAuxDir(self): + '''Reset directory relative to --dir where auxiliary build tools are + placed. Default comes from configure.ac or configure.in.''' + self.table['auxdir'] = string() + + # Define sourcebase methods. + def getSourceBase(self): + '''Return directory relative to destdir where source code is placed.''' + return(self.table['sourcebase']) + + def setSourceBase(self, sourcebase): + '''Specify directory relative to destdir where source code is placed.''' + if type(sourcebase) is bytes or type(sourcebase) is string: + if type(sourcebase) is bytes: + sourcebase = string(sourcebase, ENCS['system']) + if sourcebase: + self.table['sourcebase'] = sourcebase + else: # if type of sourcebase is not bytes or string + raise(TypeError('sourcebase must be a string, not %s' % + type(sourcebase).__name__)) + + def resetSourceBase(self): + '''Return directory relative to destdir where source code is placed.''' + self.table['sourcebase'] = string() + + # Define m4base methods. + def getM4Base(self): + '''Return directory relative to destdir where *.m4 macros are placed.''' + return(self.table['m4base']) + + def setM4Base(self, m4base): + '''Specify directory relative to destdir where *.m4 macros are placed.''' + if type(m4base) is bytes or type(m4base) is string: + if type(m4base) is bytes: + m4base = string(m4base, ENCS['system']) + if m4base: + self.table['m4base'] = m4base + else: # if type of m4base is not bytes or string + raise(TypeError('m4base must be a string, not %s' % + type(m4base).__name__)) + + def resetM4Base(self): + '''Reset directory relative to destdir where *.m4 macros are placed.''' + self.table['m4base'] = string() + + # Define pobase methods. + def getPoBase(self): + '''Return directory relative to destdir where *.po files are placed.''' + return(self.table['pobase']) + + def setPoBase(self, pobase): + '''Specify directory relative to destdir where *.po files are placed.''' + if type(pobase) is bytes or type(pobase) is string: + if type(pobase) is bytes: + pobase = string(pobase, ENCS['system']) + if pobase: + self.table['pobase'] = pobase + else: # if type of pobase is not bytes or string + raise(TypeError('pobase must be a string, not %s' % + type(pobase).__name__)) + + def resetPoBase(self): + '''Reset directory relative to destdir where *.po files are placed.''' + self.table['pobase'] = string() + + # Define docbase methods. + def getDocBase(self): + '''Return directory relative to destdir where doc files are placed. + Default value for this variable is 'doc').''' + return(self.table['docbase']) + + def setDocBase(self, docbase): + '''Specify directory relative to destdir where doc files are placed. + Default value for this variable is 'doc').''' + if type(docbase) is bytes or type(docbase) is string: + if type(docbase) is bytes: + docbase = string(docbase, ENCS['system']) + if docbase: + self.table['docbase'] = docbase + else: # if type of docbase is not bytes or string + raise(TypeError('docbase must be a string, not %s' % + type(docbase).__name__)) + + def resetDocBase(self): + '''Reset directory relative to destdir where doc files are placed. + Default value for this variable is 'doc').''' + self.table['docbase'] = string() + + # Define testsbase methods. + def getTestsBase(self): + '''Return directory relative to destdir where unit tests are placed. + Default value for this variable is 'tests').''' + return(self.table['testsbase']) + + def setTestsBase(self, testsbase): + '''Specify directory relative to destdir where unit tests are placed. + Default value for this variable is 'tests').''' + if type(testsbase) is bytes or type(testsbase) is string: + if type(testsbase) is bytes: + testsbase = string(testsbase, ENCS['system']) + if testsbase: + self.table['testsbase'] = testsbase + else: # if type of testsbase is not bytes or string + raise(TypeError('testsbase must be a string, not %s' % + type(testsbase).__name__)) + + def resetTestsBase(self): + '''Reset directory relative to destdir where unit tests are placed. + Default value for this variable is 'tests').''' + self.table['testsbase'] = string() + + # Define modules methods. + def addModule(self, module): + '''Add the module to the modules list.''' + if type(module) is bytes or type(module) is string: + if type(module) is bytes: + module = module.decode(ENCS['default']) + if module not in self.table['modules']: + self.table['modules'] += [module] + else: # if module has not bytes or string type + raise(TypeError('module must be a string, not %s' % + type(module).__name__)) + + def removeModule(self, module): + '''Remove the module from the modules list.''' + if type(module) is bytes or type(module) is string: + if type(module) is bytes: + module = module.decode(ENCS['default']) + if module in self.table['modules']: + self.table['modules'].remove(module) + else: # if module has not bytes or string type + raise(TypeError('module must be a string, not %s' % + type(module).__name__)) + + def getModules(self): + '''Return the modules list.''' + return(list(self.table['modules'])) + + def setModules(self, modules): + '''Set the modules list.''' + if type(modules) is list or type(modules) is tuple: + old_modules = self.table['modules'] + self.table['modules'] = list() + for module in modules: + try: # Try to add each module + self.addModule(module) + except TypeError as error: + self.table['modules'] = old_modules + raise(TypeError('each module must be a string')) + except GLError as error: + self.table['modules'] = old_modules + raise(GLError(error.errno, error.errinfo)) + else: # if type of modules is not list or tuple + raise(TypeError('modules must be a list or a tuple, not %s' % + type(modules).__name__)) + + def resetModules(self): + '''Reset the list of the modules.''' + self.table['modules'] = list() + + # Define avoids methods. + def addAvoid(self, module): + '''Avoid including the given module. Useful if you have code that provides + equivalent functionality.''' + if type(module) is bytes or type(module) is string: + if type(module) is bytes: + module = module.decode(ENCS['default']) + if module not in self.table['avoids']: + self.table['avoids'].append(module) + else: # if module has not bytes or string type + raise(TypeError('avoid must be a string, not %s' % + type(module).__name__)) + + def removeAvoid(self, module): + '''Remove the given module from the list of avoided modules.''' + if type(module) is bytes or type(module) is string: + if type(module) is bytes: + module = module.decode(ENCS['default']) + if module in self.table['avoids']: + self.table['avoids'].remove(module) + else: # if module has not bytes or string type + raise(TypeError('avoid must be a string, not %s' % + type(module).__name__)) + + def getAvoids(self): + '''Return the list of the avoided modules.''' + return(list(self.table['avoids'])) + + def setAvoids(self, modules): + '''Specify the modules which will be avoided.''' + if type(modules) is list or type(modules) is tuple: + old_avoids = self.table['avoids'] + self.table['avoids'] = list() + for module in modules: + try: # Try to add each module + self.addAvoid(module) + except TypeError as error: + self.table['avoids'] = old_avoids + raise(TypeError('each module must be a string')) + except GLError as error: + self.table['avoids'] = old_avoids + raise(GLError(error.errno, error.errinfo)) + else: # if type of modules is not list or tuple + raise(TypeError('modules must be a list or a tuple, not %s' % + type(modules).__name__)) + + def resetAvoids(self): + '''Reset the list of the avoided modules.''' + self.table['avoids'] = list() + + # Define files methods. + def addFile(self, file): + '''Add file to the list of files.''' + if type(file) is bytes or type(file) is string: + if type(file) is bytes: + file = file.decode(ENCS['default']) + if file not in self.table['files']: + self.table['files'].append(file) + else: # if file has not bytes or string type + raise(TypeError('file must be a string, not %s' % + type(file).__name__)) + + def removeFile(self, file): + '''Remove the given file from the list of files.''' + if type(file) is bytes or type(file) is string: + if type(file) is bytes: + file = file.decode(ENCS['default']) + if file in self.table['files']: + self.table['files'].remove(file) + else: # if file has not bytes or string type + raise(TypeError('file must be a string, not %s' % + type(file).__name__)) + + def getFiles(self): + '''Return the list of the fileed files.''' + return(list(self.table['files'])) + + def setFiles(self, files): + '''Specify the list of files.''' + if type(files) is list or type(files) is tuple: + old_files = self.table['files'] + self.table['files'] = list() + for file in files: + try: # Try to add each file + self.addFile(file) + except TypeError as error: + self.table['files'] = old_files + raise(TypeError('each file must be a string')) + except GLError as error: + self.table['files'] = old_files + raise(GLError(error.errno, error.errinfo)) + else: # if type of files is not list or tuple + raise(TypeError('files must be a list or a tuple, not %s' % + type(files).__name__)) + + def resetFiles(self): + '''Reset the list of files.''' + self.table['files'] = list() + + # Define tests/testflags methods + def checkTestFlag(self, flag): + '''Return the status of the test flag.''' + if flag in TESTS.values(): + return(flag in self.table['testflags']) + else: # if flag is not in TESTS + raise(TypeError('unknown flag: %s' % repr(flag))) + + def enableTestFlag(self, flag): + '''Enable test flag. You can get flags from TESTS variable.''' + if flag in TESTS.values(): + if flag not in self.table['testflags']: + self.table['testflags'].append(flag) + else: # if flag is not in TESTS + raise(TypeError('unknown flag: %s' % repr(flag))) + + def disableTestFlag(self, flag): + '''Disable test flag. You can get flags from TESTS variable.''' + if flag in TESTS.values(): + if flag in self.table['testflags']: + self.table['testflags'].remove(flag) + else: # if flag is not in TESTS + raise(TypeError('unknown flag: %s' % repr(flag))) + + def getTestFlags(self): + '''Return test flags. You can get flags from TESTS variable.''' + return(list(self.table['testflags'])) + + def setTestFlags(self, testflags): + '''Specify test flags. You can get flags from TESTS variable.''' + if type(testflags) is list or type(testflags) is tuple: + old_testflags = self.table['testflags'] + self.table['testflags'] = list() + for flag in testflags: + try: # Try to enable each flag + self.enableTestFlag(flag) + except TypeError as error: + raise(TypeError('each flag must be one of TESTS integers')) + self.table['testflags'] = testflags + else: # if type of testflags is not list or tuple + raise(TypeError('testflags must be a list or a tuple, not %s' % + type(testflags).__name__)) + + def resetTestFlags(self): + '''Reset test flags (only default flag will be enabled).''' + self.table['testflags'] = list() + self.table['tests'] = self.table['testflags'] + + # Define libname methods. + def getLibName(self): + '''Return the library name.''' + return(self.table['libname']) + + def setLibName(self, libname): + '''Specify the library name.''' + if type(libname) is bytes or type(libname) is string: + if type(libname) is bytes: + libname = string(libname, ENCS['system']) + if libname: + self.table['libname'] = libname + else: # if type of libname is not bytes or string + raise(TypeError('libname must be a string, not %s' % + type(module).__name__)) + + def resetLibName(self): + '''Reset the library name to 'libgnu'.''' + self.table['libname'] = string('libgnu') + + # Define libtool methods. + def checkLibtool(self): + '''Check if user enabled libtool rules.''' + return(self.table['libtool']) + + def enableLibtool(self): + '''Enable libtool rules.''' + self.table['libtool'] = True + + def disableLibtool(self): + '''Disable libtool rules.''' + self.table['libtool'] = False + + def resetLibtool(self): + '''Reset libtool rules.''' + self.table['libtool'] = False + + # Define conddeps methods. + def checkCondDeps(self): + '''Check if user enabled cond. dependencies.''' + return(self.table['conddeps']) + + def enableCondDeps(self): + '''Enable cond. dependencies (may save configure time and object code).''' + self.table['conddeps'] = True + + def disableCondDeps(self): + '''Disable cond. dependencies (may save configure time and object code).''' + self.table['conddeps'] = False + + def resetCondDeps(self): + '''Reset cond. dependencies (may save configure time and object code).''' + self.table['conddeps'] = False + + # Define lgpl methods. + def getLGPL(self): + '''Check for abort if modules aren't available under the LGPL. + Default value is False, which means that lgpl is disabled.''' + return(self.table['lgpl']) + + def setLGPL(self, lgpl): + '''Abort if modules aren't available under the LGPL. + Default value is False, which means that lgpl is disabled.''' + if (type(lgpl) is int and 2 <= lgpl <= 3) or type(lgpl) is bool: + self.table['lgpl'] = lgpl + else: # if lgpl is not False, 2 or 3 + raise(TypeError('invalid LGPL version: %s' % repr(lgpl))) + + def resetLGPL(self): + '''Disable abort if modules aren't available under the LGPL. + Default value is False, which means that lgpl is disabled.''' + self.table['lgpl'] = False + + # Define macro_prefix methods. + def getIncludeGuardPrefix(self): + '''Return include_guard_prefix to use inside GLEmiter class.''' + return(self.table['include_guard_prefix']) + + def getMacroPrefix(self): + '''Return the prefix of the macros 'gl_EARLY' and 'gl_INIT'. + Default macro_prefix is 'gl'.''' + return(self.table['macro_prefix']) + + def setMacroPrefix(self, macro_prefix): + '''Specify the prefix of the macros 'gl_EARLY' and 'gl_INIT'. + Default macro_prefix is 'gl'.''' + if type(macro_prefix) is bytes or type(macro_prefix) is string: + if type(macro_prefix) is bytes: + macro_prefix = string(macro_prefix, ENCS['system']) + if macro_prefix: + self.table['macro_prefix'] = macro_prefix + else: # if type of macro_prefix is not bytes or string + raise(TypeError('macro_prefix must be a string, not %s' % + type(macro_prefix).__name__)) + if macro_prefix == 'gl': + include_guard_prefix = 'GL' + else: # macro_prefix != 'gl' + include_guard_prefix = 'GL_%s' % macro_prefix.upper() + if type(include_guard_prefix) is bytes: + include_guard_prefix = include_guard_prefix.decode(ENCS['default']) + self.table['include_guard_prefix'] = include_guard_prefix + + def resetMacroPrefix(self): + '''Reset the prefix of the macros 'gl_EARLY' and 'gl_INIT'. + Default macro_prefix is 'gl'.''' + self.table['macro_prefix'] = string('gl') + include_guard_prefix = string('GL') + if type(include_guard_prefix) is bytes: + include_guard_prefix = include_guard_prefix.decode(ENCS['default']) + self.table['include_guard_prefix'] = include_guard_prefix + + # Define makefile methods. + def getMakefile(self): + '''Return the name of makefile in automake syntax in the source-base and + tests-base directories. Default is 'Makefile.am'.''' + return(self.table['makefile']) + + def setMakefile(self, makefile): + '''Specify the name of makefile in automake syntax in the source-base and + tests-base directories. Default is 'Makefile.am'.''' + if type(makefile) is bytes or type(makefile) is string: + if type(makefile) is bytes: + makefile = string(makefile, ENCS['system']) + if makefile: + self.table['makefile'] = makefile + else: # if type of makefile is not bytes or string + raise(TypeError('makefile must be a string, not %s' % + type(makefile).__name__)) + + def resetMakefile(self): + '''Reset the name of makefile in automake syntax in the source-base and + tests-base directories. Default is 'Makefile.am'.''' + self.table['makefile'] = string() + + # Define podomain methods. + def getPoDomain(self): + '''Return the prefix of the i18n domain. Usually use the package name. + A suffix '-gnulib' is appended.''' + return(self.table['podomain']) + + def setPoDomain(self, podomain): + '''Specify the prefix of the i18n domain. Usually use the package name. + A suffix '-gnulib' is appended.''' + if type(podomain) is bytes or type(podomain) is string: + if type(podomain) is bytes: + podomain = string(podomain, ENCS['system']) + if podomain: + self.table['podomain'] = podomain + else: # if type of podomain is not bytes or string + raise(TypeError('podomain must be a string, not %s' % + type(podomain).__name__)) + + def resetPoDomain(self): + '''Reset the prefix of the i18n domain. Usually use the package name. + A suffix '-gnulib' is appended.''' + self.table['podomain'] = string() + + # Define witness_c_macro methods. + def getWitnessCMacro(self): + '''Return the C macro that is defined when the sources in this directory + are compiled or used.''' + return(self.table['witness_c_macro']) + + def setWitnessCMacro(self, witness_c_macro): + '''Specify the C macro that is defined when the sources in this directory + are compiled or used.''' + if type(witness_c_macro) is bytes or type(witness_c_macro) is string: + if type(witness_c_macro) is bytes: + witness_c_macro = string(witness_c_macro, ENCS['system']) + if witness_c_macro: + self.table['witness_c_macro'] = witness_c_macro + else: # if type of witness_c_macro is not bytes or string + raise(TypeError('witness_c_macro must be a string, not %s' % + type(witness_c_macro).__name__)) + + def resetWitnessCMacro(self): + '''Return the C macro that is defined when the sources in this directory + are compiled or used.''' + self.table['witness_c_macro'] = string() + + # Define vc_files methods. + def checkVCFiles(self): + '''Check if update of the version control files is enabled or disabled.''' + return(self.table['vc_files']) + + def enableVCFiles(self): + '''Enable update of the version control files.''' + self.table['vc_files'] = True + + def disableVCFiles(self): + '''Disable update of the version control files.''' + self.table['vc_files'] = False + + def resetVCFiles(self): + '''Reset update of the version control files and set it to None.''' + self.table['vc_files'] = None + + # Define modcache methods. + def checkModuleCaching(self): + '''Get status of module caching optimization.''' + return(self.table['modcache']) + + def enableModuleCaching(self): + '''Enable module caching optimization.''' + self.table['modcache'] = True + + def disableModuleCaching(self): + '''Disable module caching optimization.''' + self.table['modcache'] = False + + def resetModuleCaching(self): + '''Reset module caching optimization.''' + self.table['modcache'] = False + + # Define configure_ac methods. + def getAutoconfFile(self): + '''Return path of autoconf file relative to destdir.''' + return(self.table['configure_ac']) + + def setAutoconfFile(self, configure_ac): + '''Specify path of autoconf file relative to destdir.''' + if type(configure_ac) is bytes or type(configure_ac) is string: + if type(configure_ac) is bytes: + configure_ac = string(configure_ac, ENCS['system']) + if configure_ac: + self.table['configure_ac'] = \ + relpath(self.table['destdir'], configure_ac) + else: # if type of configure_ac is not bytes or string + raise(TypeError('configure_ac must be a string, not %s' % + type(configure_ac).__name__)) + + def resetAutoconfFile(self): + '''Reset path of autoconf file relative to destdir.''' + configure_ac = string() + if isfile(joinpath(self.table['destdir'], 'configure.ac')): + configure_ac = joinpath(self.table['destdir'], 'configure.ac') + elif isfile(joinpath(self.table['destdir'], 'configure.in')): + configure_ac = joinpath(self.table['destdir'], 'configure.in') + self.table['configure_ac'] = configure_ac + + # Define ac_version methods. + def getAutoconfVersion(self): + '''Return preferred autoconf version. Default value is 2.59.''' + return(self.table['ac_version']) + + def setAutoconfVersion(self, ac_version): + '''Specify preferred autoconf version. Default value is 2.59.''' + if type(ac_version) is float or type(ac_version) is int: + self.table['ac_version'] = float(ac_version) + else: # if ac_version has not int or float type + raise(TypeError('ac_version must be an int or a float, not %s' % + type(ac_version).__name__)) + + def resetAutoconfVersion(self): + '''Specify preferred autoconf version. Default value is 2.59.''' + self.table['ac_version'] = 2.59 + + # Define symbolic methods. + def checkCopyrights(self): + '''Check if copyright notices in files should be replaced.''' + return(self.table['copyrights']) + + def checkSymbolic(self): + '''Check if pygnulib will make symbolic links instead of copying files.''' + return(self.table['symbolic']) + + def enableSymbolic(self): + '''Enable creation of the symbolic links instead of copying files.''' + self.table['symbolic'] = True + self.table['copyrights'] = False + + def disableSymbolic(self): + '''Enable creation of the symbolic links instead of copying files.''' + self.table['symbolic'] = False + self.table['copyrights'] = True + + def resetSymbolic(self): + '''Reset creation of the symbolic links instead of copying files.''' + self.table['symbolic'] = False + self.table['copyrights'] = True + + # Define lsymbolic methods. + def checkLSymbolic(self): + '''Check if pygnulib will make symbolic links instead of copying files, only + for files from the local override directory.''' + return(self.table['lsymbolic']) + + def enableLSymbolic(self): + '''Enable creation of symbolic links instead of copying files, only for + files from the local override directory.''' + self.table['lsymbolic'] = True + + def disableLSymbolic(self): + '''Disable creation of symbolic links instead of copying files, only for + files from the local override directory.''' + self.table['lsymbolic'] = False + + def resetLSymbolic(self): + '''Reset creation of symbolic links instead of copying files, only for + files from the local override directory.''' + self.table['lsymbolic'] = False + + # Define verbosity methods. + def getVerbosity(self): + '''Get verbosity level.''' + return(self.table['verbosity']) + + def decreaseVerbosity(self): + '''Decrease verbosity level.''' + if self.table['verbosity'] > MODES['verbose-min']: + self.table['verbosity'] -= 1 + + def increaseVerbosity(self): + '''Increase verbosity level.''' + if self.table['verbosity'] < MODES['verbose-max']: + self.table['verbosity'] += 1 + + def setVerbosity(self, verbose): + '''Set verbosity level to verbose, where -2 <= verbose <= 2. + If verbosity level is less than -2, verbosity level will be set to -2. + If verbosity level is greater than 2, verbosity level will be set to 2.''' + if type(verbose) is int: + if MODES['verbose-min'] <= verbose <= MODES['verbose-max']: + self.table['verbosity'] = verbose + elif verbose < MODES['verbose-min']: + self.table['verbosity'] = MODES['verbose-min'] + elif verbose > MODES['verbose-max']: + self.table['verbosity'] = MODES['verbose-max'] + else: # if type(verbose) is not int + raise(TypeError('verbosity must be an int, not %s' % + type(verbose).__name__)) + + def resetVerbosity(self): + '''Reset verbosity level.''' + self.table['verbosity'] = 0 + + # Define libtests methods. + def checkLibtests(self): + '''Return True if a testsbase/libtests.a is needed.''' + return(self.table['libtests']) + + def enableLibtests(self): + '''If libtests is enabled, then testsbase/libtests.a is needed.''' + self.table['libtests'] = True + + def disableLibtests(self): + '''If libtests is disabled, then testsbase/libtests.a is not needed.''' + self.table['libtests'] = False + + def resetLibtests(self): + '''Reset status of testsbase/libtests.a.''' + self.table['libtests'] = False + + # Define single_configure methods. + def checkSingleConfigure(self): + '''Check whether single configure file should be generated.''' + return(self.table['single_configure']) + + def enableSingleConfigure(self): + '''Enable generation of the single configure file.''' + self.table['single_configure'] = True + + def disableSingleConfigure(self): + '''Disable generation of the single configure file.''' + self.table['single_configure'] = False + + def resetSingleConfigure(self): + '''Reset status of the single configure file generation.''' + self.table['single_configure'] = False + + # Define dryrun methods. + def checkDryRun(self): + '''Check whether dryrun is enabled.''' + return(self.table['dryrun']) + + def enableDryRun(self): + '''Enable dryrun mode.''' + self.table['dryrun'] = True + + def disableDryRun(self): + '''Disable dryrun mode.''' + self.table['dryrun'] = False + + def resetDryRun(self): + '''Reset status of dryrun mode.''' + self.table['dryrun'] = False + + # Define errors methods. + def checkErrors(self): + '''Check if GLError will be raised in non-critical situations.''' + return(self.table['errors']) + + def enableErrors(self): + '''Raise GLError in non-critical situations.''' + self.table['errors'] = True + + def disableErrors(self): + '''Do not raise GLError in non-critical situations.''' + self.table['errors'] = False + + def resetErrors(self): + '''Reset status of raising GLError in non-critical situations.''' + self.table['errors'] = False diff --git a/pygnulib/GLEmiter.py b/pygnulib/GLEmiter.py index 3895f4d514..6df6eca7b6 100644 --- a/pygnulib/GLEmiter.py +++ b/pygnulib/GLEmiter.py @@ -56,30 +56,30 @@ relpath = os.path.relpath # Define GLEmiter class #=============================================================================== class GLEmiter(object): - '''This class is used to emit the contents of necessary files.''' - - def __init__(self, config): - '''GLEmiter.__init__(config) -> GLEmiter - - Create GLEmiter instance.''' - self.info = GLInfo() - if type(config) is not GLConfig: - raise(TypeError('config must be a GLConfig, not %s' % \ - type(config).__name__)) - self.config = config - - def __repr__(self): - '''x.__repr__() <==> repr(x)''' - result = '' % hex(id(self)) - return(result) - - def copyright_notice(self): - '''GLEmiter.copyright_notice() -> string - - Emit a header for a generated file.''' - emit = string() - emit += "# %s" % self.info.copyright() - emit += """ + '''This class is used to emit the contents of necessary files.''' + + def __init__(self, config): + '''GLEmiter.__init__(config) -> GLEmiter + + Create GLEmiter instance.''' + self.info = GLInfo() + if type(config) is not GLConfig: + raise(TypeError('config must be a GLConfig, not %s' % + type(config).__name__)) + self.config = config + + def __repr__(self): + '''x.__repr__() <==> repr(x)''' + result = '' % hex(id(self)) + return(result) + + def copyright_notice(self): + '''GLEmiter.copyright_notice() -> string + + Emit a header for a generated file.''' + emit = string() + emit += "# %s" % self.info.copyright() + emit += """ # # This file is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -100,284 +100,288 @@ class GLEmiter(object): # the same distribution terms as the rest of that program. # # Generated by gnulib-tool.\n""" - if type(emit) is bytes: - emit = emit.decode(ENCS['default']) - return(constants.nlconvert(emit)) - - def autoconfSnippet(self, module, fileassistant, toplevel, - disable_libtool, disable_gettext, replace_auxdir, indentation): - '''GLEmiter.autoconfSnippet(module, toplevel, - disable_libtool, disable_gettext, replace_auxdir, - indentation) -> string - - Emit the autoconf snippet of a module. - GLConfig: include_guard_prefix. - - module is a GLModule instance, which is processed. - fileassistant is a GLFileAssistant instance, which is used to get temporary - directories and sed transformer. - toplevel is a bool variable, False means a subordinate use of pygnulib. - disable_libtool is a bool variable; it tells whether to disable libtool - handling even if it has been specified through the GLConfig class. - disable_gettext is a bool variable; it tells whether to disable - AM_GNU_GETTEXT invocations. - replace_auxdir is a bool variable; it tells whether to replace - 'build-aux' directory in AC_CONFIG_FILES. - indentation is a string which contain spaces to prepend on each line.''' - emit = string() - if type(module) is not GLModule: - raise(TypeError('module must be a GLModule, not %s' % \ - type(module).__name__)) - if type(fileassistant) is not GLFileAssistant: - raise(TypeError('fileassistant must be a GLFileAssistant, not %s' % \ - type(fileassistant).__name__)) - if type(toplevel) is not bool: - raise(TypeError('toplevel must be a bool, not %s' % \ - type(toplevel).__name__)) - if type(disable_libtool) is not bool: - raise(TypeError('disable_libtool must be a bool, not %s' % \ - type(disable_libtool).__name__)) - if type(disable_gettext) is not bool: - raise(TypeError('disable_gettext must be a bool, not %s' % \ - type(disable_gettext).__name__)) - if type(indentation) is bytes or type(indentation) is string: - if type(indentation) is bytes: - indentation = indentation.decode(ENCS['default']) - else: # if indentation has not bytes or string type - raise(TypeError('indentation must be a string, not %s' % \ - type(indentation).__name__)) - if not indentation.isspace(): - raise(ValueError('indentation must contain only whitespaces')) - auxdir = self.config['auxdir'] - libtool = self.config['libtool'] - include_guard_prefix = self.config['include_guard_prefix'] - if str(module) in ['gnumakefile', 'maintainer-makefile']: - # These modules are meant to be used only in the top-level directory. - flag = toplevel - else: # if not str(module) in ['gnumakefile', 'maintainer-makefile'] - flag = True - if flag: - snippet = module.getAutoconfSnippet() - snippet = snippet.replace('${gl_include_guard_prefix}', - include_guard_prefix) - lines = [line for line in snippet.split('\n') if line.strip()] - snippet = '%s\n' % '\n'.join(lines) - transformer = fileassistant.transformers.get('aux', '') - pattern = compiler('(^.*?$)', re.S | re.M) - snippet = pattern.sub('%s\\1' % indentation, snippet) - if transformer: - args = ['sed', '-e', transformer] - path = fileassistant.tmpfilename('snippet') - with codecs.open(path, 'wb', 'UTF-8') as file: - file.write(snippet) - stdin = codecs.open(path, 'rb', 'UTF-8') - snippet = sp.check_output(args, stdin=stdin, shell=False) - snippet = snippet.decode("UTF-8") - os.remove(path) - if disable_libtool: - snippet = snippet.replace('$gl_cond_libtool', 'false') - snippet = snippet.replace('gl_libdeps', 'gltests_libdeps') - snippet = snippet.replace('gl_ltlibdeps', 'gltests_ltlibdeps') - if disable_gettext: - snippet = snippet.replace('AM_GNU_GETTEXT([external])', 'dnl you must \ + if type(emit) is bytes: + emit = emit.decode(ENCS['default']) + return(constants.nlconvert(emit)) + + def autoconfSnippet(self, module, fileassistant, toplevel, + disable_libtool, disable_gettext, replace_auxdir, indentation): + '''GLEmiter.autoconfSnippet(module, toplevel, + disable_libtool, disable_gettext, replace_auxdir, + indentation) -> string + + Emit the autoconf snippet of a module. + GLConfig: include_guard_prefix. + + module is a GLModule instance, which is processed. + fileassistant is a GLFileAssistant instance, which is used to get temporary + directories and sed transformer. + toplevel is a bool variable, False means a subordinate use of pygnulib. + disable_libtool is a bool variable; it tells whether to disable libtool + handling even if it has been specified through the GLConfig class. + disable_gettext is a bool variable; it tells whether to disable + AM_GNU_GETTEXT invocations. + replace_auxdir is a bool variable; it tells whether to replace + 'build-aux' directory in AC_CONFIG_FILES. + indentation is a string which contain spaces to prepend on each line.''' + emit = string() + if type(module) is not GLModule: + raise(TypeError('module must be a GLModule, not %s' % + type(module).__name__)) + if type(fileassistant) is not GLFileAssistant: + raise(TypeError('fileassistant must be a GLFileAssistant, not %s' % + type(fileassistant).__name__)) + if type(toplevel) is not bool: + raise(TypeError('toplevel must be a bool, not %s' % + type(toplevel).__name__)) + if type(disable_libtool) is not bool: + raise(TypeError('disable_libtool must be a bool, not %s' % + type(disable_libtool).__name__)) + if type(disable_gettext) is not bool: + raise(TypeError('disable_gettext must be a bool, not %s' % + type(disable_gettext).__name__)) + if type(indentation) is bytes or type(indentation) is string: + if type(indentation) is bytes: + indentation = indentation.decode(ENCS['default']) + else: # if indentation has not bytes or string type + raise(TypeError('indentation must be a string, not %s' % + type(indentation).__name__)) + if not indentation.isspace(): + raise(ValueError('indentation must contain only whitespaces')) + auxdir = self.config['auxdir'] + libtool = self.config['libtool'] + include_guard_prefix = self.config['include_guard_prefix'] + if str(module) in ['gnumakefile', 'maintainer-makefile']: + # These modules are meant to be used only in the top-level directory. + flag = toplevel + else: # if not str(module) in ['gnumakefile', 'maintainer-makefile'] + flag = True + if flag: + snippet = module.getAutoconfSnippet() + snippet = snippet.replace('${gl_include_guard_prefix}', + include_guard_prefix) + lines = [line for line in snippet.split('\n') if line.strip()] + snippet = '%s\n' % '\n'.join(lines) + transformer = fileassistant.transformers.get('aux', '') + pattern = compiler('(^.*?$)', re.S | re.M) + snippet = pattern.sub('%s\\1' % indentation, snippet) + if transformer: + args = ['sed', '-e', transformer] + path = fileassistant.tmpfilename('snippet') + with codecs.open(path, 'wb', 'UTF-8') as file: + file.write(snippet) + stdin = codecs.open(path, 'rb', 'UTF-8') + snippet = sp.check_output(args, stdin=stdin, shell=False) + snippet = snippet.decode("UTF-8") + os.remove(path) + if disable_libtool: + snippet = snippet.replace('$gl_cond_libtool', 'false') + snippet = snippet.replace('gl_libdeps', 'gltests_libdeps') + snippet = snippet.replace('gl_ltlibdeps', 'gltests_ltlibdeps') + if disable_gettext: + snippet = snippet.replace('AM_GNU_GETTEXT([external])', 'dnl you must \ add AM_GNU_GETTEXT([external]) or similar to configure.ac.') - emit += snippet - if str(module) == 'alloca' and libtool and not disable_libtool: - emit += 'changequote(,)dnl\n' - emit += "LTALLOCA=`echo \"$ALLOCA\" | sed -e 's/\\.[^.]* /.lo \ + emit += snippet + if str(module) == 'alloca' and libtool and not disable_libtool: + emit += 'changequote(,)dnl\n' + emit += "LTALLOCA=`echo \"$ALLOCA\" | sed -e 's/\\.[^.]* /.lo \ /g;s/\\.[^.]*$/.lo/'`\n" - emit += 'changequote([, ])dnl\n' - emit += 'AC_SUBST([LTALLOCA])' - if replace_auxdir: - regex = 'AC_CONFIG_FILES\\(\\[(.*?)\\:build-aux/(.*?)\\]\\)' - repl = 'AC_CONFIG_FILES([\\1:%s/\\2])' % auxdir - pattern = compiler(regex, re.S | re.M) - emit = pattern.sub(repl, emit) - lines = [line for line in emit.split('\n') if line.strip()] - emit = '%s\n' % '\n'.join(lines) - emit = constants.nlconvert(emit) - if type(emit) is bytes: - emit = emit.decode(ENCS['default']) - return(emit) - - def autoconfSnippets(self, modules, moduletable, fileassistant, - verifier, toplevel, disable_libtool, disable_gettext, replace_auxdir): - '''GLEmiter.autoconfSnippets(modules, fileassistant, - verifier, toplevel, disable_libtool, disable_gettext, - replace_auxdir) -> string - - Collect and emit the autoconf snippets of a set of modules. - GLConfig: conddeps. - - basemodules argument represents list of modules; every module in this list - must be a GLModule instance; this list of modules is used to sort all - modules after they were processed. - modules argument represents list of modules; every module in this list must - be a GLModule instance. - moduletable is a GLModuleTable instance, which contains necessary - information about dependencies of the modules. - fileassistant is a GLFileAssistant instance, which is used to get temporary - directories and sed transformers. - verifier is an integer, which can be 0, 1 or 2. - if verifier == 0, then process every module; - if verifier == 1, then process only non-tests modules; - if verifier == 2, then process only tests modules. - toplevel is a bool variable, False means a subordinate use of pygnulib. - disable_libtool is a bool variable; it tells whether to disable libtool - handling even if it has been specified through the GLConfig class. - disable_gettext is a bool variable; it tells whether to disable - AM_GNU_GETTEXT invocations. - replace_auxdir is a bool variable; it tells whether to replace - 'build-aux' directory in AC_CONFIG_FILES.''' - emit = string() - for module in modules: - if type(module) is not GLModule: - raise(TypeError('each module must be a GLModule instance')) - if type(moduletable) is not GLModuleTable: - raise(TypeError('moduletable must be a GLFileAssistant, not %s' % \ - type(moduletable).__name__)) - if type(fileassistant) is not GLFileAssistant: - raise(TypeError('fileassistant must be a GLFileAssistant, not %s' % \ - type(fileassistant).__name__)) - if type(verifier) is not int: - raise(TypeError('verifier must be an int, not %s' % \ - type(verifier).__name__)) - if not (0 <= verifier <= 2): - raise(ValueError('verifier must be 0, 1 or 2, not %d' % verifier)) - if type(toplevel) is not bool: - raise(TypeError('toplevel must be a bool, not %s' % \ - type(toplevel).__name__)) - if type(disable_libtool) is not bool: - raise(TypeError('disable_libtool must be a bool, not %s' % \ - type(disable_libtool).__name__)) - if type(disable_gettext) is not bool: - raise(TypeError('disable_gettext must be a bool, not %s' % \ - type(disable_gettext).__name__)) - if type(replace_auxdir) is not bool: - raise(TypeError('replace_auxdir must be a bool, not %s' % \ - type(replace_auxdir).__name__)) - auxdir = self.config['auxdir'] - conddeps = self.config['conddeps'] - macro_prefix = self.config['macro_prefix'] - if not conddeps: - # Ignore the conditions, and enable all modules unconditionally. - for module in modules: - if verifier == 0: - solution = True - elif verifier == 1: - solution = module.isNonTests() - elif verifier == 2: - solution = module.isTests() - if solution: - emit += self.autoconfSnippet(module, fileassistant, toplevel, - disable_libtool, disable_gettext, replace_auxdir, ' ') - else: # if conddeps - # Emit the autoconf code for the unconditional modules. - for module in modules: - if verifier == 0: - solution = True - elif verifier == 1: - solution = module.isNonTests() - elif verifier == 2: - solution = module.isTests() - if solution: - if not moduletable.isConditional(module): - emit += self.autoconfSnippet(module, fileassistant, toplevel, - disable_libtool, disable_gettext, replace_auxdir, ' ') - # Initialize the shell variables indicating that the modules are enabled. - for module in modules: - if verifier == 0: - solution = True - elif verifier == 1: - solution = module.isNonTests() - elif verifier == 2: - solution = module.isTests() - if solution: - if moduletable.isConditional(module): - shellvar = module.getShellVar() - emit += ' %s=false\n' % module.getShellVar() - # Emit the autoconf code for the conditional modules, each in a separate - # function. This makes it possible to support cycles among conditional - # modules. - for module in modules: - if verifier == 0: - solution = True - elif verifier == 1: - solution = module.isNonTests() - elif verifier == 2: - solution = module.isTests() - if solution: - if moduletable.isConditional(module): - shellfunc = module.getShellFunc() - shellvar = module.getShellVar() - emit += ' %s ()\n' % shellfunc - emit += ' {\n' - emit += ' if ! $%s; then\n' % shellvar - emit += self.autoconfSnippet(module, fileassistant, toplevel, - disable_libtool, disable_gettext, replace_auxdir, ' ') - emit += ' %s=true\n' % shellvar - dependencies = module.getDependencies() - depmodules = [pair[0] for pair in dependencies] - # Intersect dependencies with the modules list. - depmodules = [dep for dep in depmodules if dep in modules] - for depmodule in depmodules: - if moduletable.isConditional(depmodule): - shellfunc = depmodule.getShellFunc() - condition = moduletable.getCondition(module, depmodule) - if condition != None: - emit += ' if %s; then\n' % condition - emit += ' %s\n' % shellfunc - emit += ' fi\n' - else: # if condition == None - emit += ' %s\n' % shellfunc - else: # if not moduletable.isConditional(depmodule) - # The autoconf code for $dep has already been emitted above and - # therefore is already executed when this code is run. - pass - # Define the Automake conditionals. - emit += ' m4_pattern_allow([^%s_GNULIB_ENABLED_])\n' % macro_prefix - for module in modules: - if verifier == 0: - solution = True - elif verifier == 1: - solution = module.isNonTests() - elif verifier == 2: - solution = module.isTests() - if solution: - condname = module.getConditionalName() - shellvar = module.getShellVar() - emit += ' AM_CONDITIONAL([%s], [$%s])\n' % (condname, shellvar) - lines = [line for line in emit.split('\n') if line.strip()] - emit = '%s\n' % '\n'.join(lines) - emit = constants.nlconvert(emit) - if type(emit) is bytes: - emit = emit.decode(ENCS['default']) - return(emit) - - def po_Makevars(self): - '''GLEmiter.po_Makevars() -> string - - Emit the contents of po/ makefile parameterization. - GLConfig: pobase, podomain.''' - emit = string() - pobase = self.config['pobase'] - podomain = self.config['podomain'] - top_subdir = string() - source = '%s/' % os.path.normpath(pobase) - if os.path.sep in source: - for directory in source.split(os.path.sep): - if directory != '': - top_subdir += '../' - top_subdir = os.path.normpath(top_subdir) - emit += "## DO NOT EDIT! GENERATED AUTOMATICALLY!\n" - emit += "%s\n" % self.copyright_notice() - emit += "# Usually the message domain is the same as the package name.\n" - emit += "# But here it has a '-gnulib' suffix.\n" - emit += "DOMAIN = %s-gnulib\n\n" % podomain - emit += "# These two variables depend on the location of this directory.\n" - emit += "subdir = %s\n" % pobase - emit += "top_subdir = %s\n" % top_subdir - emit += """ + emit += 'changequote([, ])dnl\n' + emit += 'AC_SUBST([LTALLOCA])' + if replace_auxdir: + regex = 'AC_CONFIG_FILES\\(\\[(.*?)\\:build-aux/(.*?)\\]\\)' + repl = 'AC_CONFIG_FILES([\\1:%s/\\2])' % auxdir + pattern = compiler(regex, re.S | re.M) + emit = pattern.sub(repl, emit) + lines = [line for line in emit.split('\n') if line.strip()] + emit = '%s\n' % '\n'.join(lines) + emit = constants.nlconvert(emit) + if type(emit) is bytes: + emit = emit.decode(ENCS['default']) + return(emit) + + def autoconfSnippets(self, modules, moduletable, fileassistant, + verifier, toplevel, disable_libtool, disable_gettext, replace_auxdir): + '''GLEmiter.autoconfSnippets(modules, fileassistant, + verifier, toplevel, disable_libtool, disable_gettext, + replace_auxdir) -> string + + Collect and emit the autoconf snippets of a set of modules. + GLConfig: conddeps. + + basemodules argument represents list of modules; every module in this list + must be a GLModule instance; this list of modules is used to sort all + modules after they were processed. + modules argument represents list of modules; every module in this list must + be a GLModule instance. + moduletable is a GLModuleTable instance, which contains necessary + information about dependencies of the modules. + fileassistant is a GLFileAssistant instance, which is used to get temporary + directories and sed transformers. + verifier is an integer, which can be 0, 1 or 2. + if verifier == 0, then process every module; + if verifier == 1, then process only non-tests modules; + if verifier == 2, then process only tests modules. + toplevel is a bool variable, False means a subordinate use of pygnulib. + disable_libtool is a bool variable; it tells whether to disable libtool + handling even if it has been specified through the GLConfig class. + disable_gettext is a bool variable; it tells whether to disable + AM_GNU_GETTEXT invocations. + replace_auxdir is a bool variable; it tells whether to replace + 'build-aux' directory in AC_CONFIG_FILES.''' + emit = string() + for module in modules: + if type(module) is not GLModule: + raise(TypeError('each module must be a GLModule instance')) + if type(moduletable) is not GLModuleTable: + raise(TypeError('moduletable must be a GLFileAssistant, not %s' % + type(moduletable).__name__)) + if type(fileassistant) is not GLFileAssistant: + raise(TypeError('fileassistant must be a GLFileAssistant, not %s' % + type(fileassistant).__name__)) + if type(verifier) is not int: + raise(TypeError('verifier must be an int, not %s' % + type(verifier).__name__)) + if not (0 <= verifier <= 2): + raise(ValueError('verifier must be 0, 1 or 2, not %d' % verifier)) + if type(toplevel) is not bool: + raise(TypeError('toplevel must be a bool, not %s' % + type(toplevel).__name__)) + if type(disable_libtool) is not bool: + raise(TypeError('disable_libtool must be a bool, not %s' % + type(disable_libtool).__name__)) + if type(disable_gettext) is not bool: + raise(TypeError('disable_gettext must be a bool, not %s' % + type(disable_gettext).__name__)) + if type(replace_auxdir) is not bool: + raise(TypeError('replace_auxdir must be a bool, not %s' % + type(replace_auxdir).__name__)) + auxdir = self.config['auxdir'] + conddeps = self.config['conddeps'] + macro_prefix = self.config['macro_prefix'] + if not conddeps: + # Ignore the conditions, and enable all modules unconditionally. + for module in modules: + if verifier == 0: + solution = True + elif verifier == 1: + solution = module.isNonTests() + elif verifier == 2: + solution = module.isTests() + if solution: + emit += self.autoconfSnippet(module, fileassistant, toplevel, + disable_libtool, disable_gettext, replace_auxdir, ' ') + else: # if conddeps + # Emit the autoconf code for the unconditional modules. + for module in modules: + if verifier == 0: + solution = True + elif verifier == 1: + solution = module.isNonTests() + elif verifier == 2: + solution = module.isTests() + if solution: + if not moduletable.isConditional(module): + emit += self.autoconfSnippet(module, fileassistant, toplevel, + disable_libtool, disable_gettext, replace_auxdir, ' ') + # Initialize the shell variables indicating that the modules are enabled. + for module in modules: + if verifier == 0: + solution = True + elif verifier == 1: + solution = module.isNonTests() + elif verifier == 2: + solution = module.isTests() + if solution: + if moduletable.isConditional(module): + shellvar = module.getShellVar() + emit += ' %s=false\n' % module.getShellVar() + # Emit the autoconf code for the conditional modules, each in a separate + # function. This makes it possible to support cycles among conditional + # modules. + for module in modules: + if verifier == 0: + solution = True + elif verifier == 1: + solution = module.isNonTests() + elif verifier == 2: + solution = module.isTests() + if solution: + if moduletable.isConditional(module): + shellfunc = module.getShellFunc() + shellvar = module.getShellVar() + emit += ' %s ()\n' % shellfunc + emit += ' {\n' + emit += ' if ! $%s; then\n' % shellvar + emit += self.autoconfSnippet(module, fileassistant, toplevel, + disable_libtool, disable_gettext, replace_auxdir, ' ') + emit += ' %s=true\n' % shellvar + dependencies = module.getDependencies() + depmodules = [pair[0] for pair in dependencies] + # Intersect dependencies with the modules list. + depmodules = [ + dep for dep in depmodules if dep in modules] + for depmodule in depmodules: + if moduletable.isConditional(depmodule): + shellfunc = depmodule.getShellFunc() + condition = moduletable.getCondition( + module, depmodule) + if condition != None: + emit += ' if %s; then\n' % condition + emit += ' %s\n' % shellfunc + emit += ' fi\n' + else: # if condition == None + emit += ' %s\n' % shellfunc + # if not moduletable.isConditional(depmodule) + else: + # The autoconf code for $dep has already been emitted above and + # therefore is already executed when this code is run. + pass + # Define the Automake conditionals. + emit += ' m4_pattern_allow([^%s_GNULIB_ENABLED_])\n' % macro_prefix + for module in modules: + if verifier == 0: + solution = True + elif verifier == 1: + solution = module.isNonTests() + elif verifier == 2: + solution = module.isTests() + if solution: + condname = module.getConditionalName() + shellvar = module.getShellVar() + emit += ' AM_CONDITIONAL([%s], [$%s])\n' % ( + condname, shellvar) + lines = [line for line in emit.split('\n') if line.strip()] + emit = '%s\n' % '\n'.join(lines) + emit = constants.nlconvert(emit) + if type(emit) is bytes: + emit = emit.decode(ENCS['default']) + return(emit) + + def po_Makevars(self): + '''GLEmiter.po_Makevars() -> string + + Emit the contents of po/ makefile parameterization. + GLConfig: pobase, podomain.''' + emit = string() + pobase = self.config['pobase'] + podomain = self.config['podomain'] + top_subdir = string() + source = '%s/' % os.path.normpath(pobase) + if os.path.sep in source: + for directory in source.split(os.path.sep): + if directory != '': + top_subdir += '../' + top_subdir = os.path.normpath(top_subdir) + emit += "## DO NOT EDIT! GENERATED AUTOMATICALLY!\n" + emit += "%s\n" % self.copyright_notice() + emit += "# Usually the message domain is the same as the package name.\n" + emit += "# But here it has a '-gnulib' suffix.\n" + emit += "DOMAIN = %s-gnulib\n\n" % podomain + emit += "# These two variables depend on the location of this directory.\n" + emit += "subdir = %s\n" % pobase + emit += "top_subdir = %s\n" % top_subdir + emit += """ # These options get passed to xgettext. XGETTEXT_OPTIONS = \\ --keyword=_ --flag=_:1:pass-c-format \\ @@ -417,93 +421,93 @@ EXTRA_LOCALE_CATEGORIES = # package uses functions taking also a message context, like pgettext(), or # if in $(XGETTEXT_OPTIONS) you define keywords with a context argument. USE_MSGCTXT = no\n""" - if type(emit) is bytes: - emit = emit.decode(ENCS['default']) - return(constants.nlconvert(emit)) - - def po_POTFILES_in(self, files): - '''GLEmiter.po_POTFILES_in(files) -> string - - Emit the file list to be passed to xgettext. - GLConfig: sourcebase.''' - emit = string() - sourcebase = self.config['sourcebase'] - sourcebase = '%s%s' % (self.sourcebase, os.path.sep) - if type(sourcebase) is bytes: - sourcebase = sourcebase.decode(ENCS['default']) - files = [substart('lib/', sourcebase, file) for file in files] - files = [file for file in files if file.startswith(sourcebase)] - emit += "## DO NOT EDIT! GENERATED AUTOMATICALLY!\n" - emit += "%s\n" % self.copyright_notice() - emit += "# List of files which contain translatable strings.\n" - emit += '\n'.join(files) - emit += '\n' - if type(emit) is bytes: - emit = emit.decode(ENCS['default']) - return(constants.nlconvert(emit)) - - def initmacro_start(self, macro_prefix_arg): - '''GLEmiter.initmacro_start(macro_prefix_arg) -> string - - Emit the first few statements of the gl_INIT macro.''' - emit = string() - if type(macro_prefix_arg) is bytes or type(macro_prefix_arg) is string: - if type(macro_prefix_arg) is bytes: - macro_prefix_arg = macro_prefix_arg.decode(ENCS['default']) - else: # if macro_prefix_arg has not bytes or string type - raise(TypeError('macro_prefix_arg must be a string, not %s' % \ - type(macro_prefix_arg).__name__)) - # Overriding AC_LIBOBJ and AC_REPLACE_FUNCS has the effect of storing - # platform-dependent object files in ${macro_prefix_arg}_LIBOBJS instead - # of LIBOBJS. The purpose is to allow several gnulib instantiations under - # a single configure.ac file. (AC_CONFIG_LIBOBJ_DIR does not allow this - # flexibility). - # Furthermore it avoids an automake error like this when a Makefile.am - # that uses pieces of gnulib also uses $(LIBOBJ): - # automatically discovered file `error.c' should not be explicitly - # mentioned. - emit += " m4_pushdef([AC_LIBOBJ]," - emit += " m4_defn([%V1%_LIBOBJ]))\n" - emit += " m4_pushdef([AC_REPLACE_FUNCS]," - emit += " m4_defn([%V1%_REPLACE_FUNCS]))\n" - # Overriding AC_LIBSOURCES has the same purpose of avoiding the automake - # error when a Makefile.am that uses pieces of gnulib also uses $(LIBOBJ): - # automatically discovered file `error.c' should not be explicitly - # mentioned - # We let automake know about the files to be distributed through the - # EXTRA_lib_SOURCES variable. - emit += " m4_pushdef([AC_LIBSOURCES]," - emit += " m4_defn([%V1%_LIBSOURCES]))\n" - # Create data variables for checking the presence of files that are - # mentioned as AC_LIBSOURCES arguments. These are m4 variables, not shell - # variables, because we want the check to happen when the configure file is - # created, not when it is run. ${macro_prefix_arg}_LIBSOURCES_LIST is the - # list of files to check for. ${macro_prefix_arg}_LIBSOURCES_DIR is the - # subdirectory in which to expect them. - emit += " m4_pushdef([%V1%_LIBSOURCES_LIST], [])\n" - emit += " m4_pushdef([%V1%_LIBSOURCES_DIR], [])\n" - emit += " gl_COMMON\n" - emit = emit.replace('%V1%', macro_prefix_arg) - if type(emit) is bytes: - emit = emit.decode(ENCS['default']) - return(constants.nlconvert(emit)) - - def initmacro_end(self, macro_prefix_arg): - '''GLEmiter.initmacro_end(macro_prefix_arg) -> string - - Emit the last few statements of the gl_INIT macro.''' - emit = string() - if type(macro_prefix_arg) is bytes or type(macro_prefix_arg) is string: - if type(macro_prefix_arg) is bytes: - macro_prefix_arg = macro_prefix_arg.decode(ENCS['default']) - else: # if macro_prefix_arg has not bytes or string type - raise(TypeError('macro_prefix_arg must be a string, not %s' % \ - type(macro_prefix_arg).__name__)) - # Check the presence of files that are mentioned as AC_LIBSOURCES - # arguments. The check is performed only when autoconf is run from the - # directory where the configure.ac resides; if it is run from a different - # directory, the check is skipped. - emit += """\ + if type(emit) is bytes: + emit = emit.decode(ENCS['default']) + return(constants.nlconvert(emit)) + + def po_POTFILES_in(self, files): + '''GLEmiter.po_POTFILES_in(files) -> string + + Emit the file list to be passed to xgettext. + GLConfig: sourcebase.''' + emit = string() + sourcebase = self.config['sourcebase'] + sourcebase = '%s%s' % (self.sourcebase, os.path.sep) + if type(sourcebase) is bytes: + sourcebase = sourcebase.decode(ENCS['default']) + files = [substart('lib/', sourcebase, file) for file in files] + files = [file for file in files if file.startswith(sourcebase)] + emit += "## DO NOT EDIT! GENERATED AUTOMATICALLY!\n" + emit += "%s\n" % self.copyright_notice() + emit += "# List of files which contain translatable strings.\n" + emit += '\n'.join(files) + emit += '\n' + if type(emit) is bytes: + emit = emit.decode(ENCS['default']) + return(constants.nlconvert(emit)) + + def initmacro_start(self, macro_prefix_arg): + '''GLEmiter.initmacro_start(macro_prefix_arg) -> string + + Emit the first few statements of the gl_INIT macro.''' + emit = string() + if type(macro_prefix_arg) is bytes or type(macro_prefix_arg) is string: + if type(macro_prefix_arg) is bytes: + macro_prefix_arg = macro_prefix_arg.decode(ENCS['default']) + else: # if macro_prefix_arg has not bytes or string type + raise(TypeError('macro_prefix_arg must be a string, not %s' % + type(macro_prefix_arg).__name__)) + # Overriding AC_LIBOBJ and AC_REPLACE_FUNCS has the effect of storing + # platform-dependent object files in ${macro_prefix_arg}_LIBOBJS instead + # of LIBOBJS. The purpose is to allow several gnulib instantiations under + # a single configure.ac file. (AC_CONFIG_LIBOBJ_DIR does not allow this + # flexibility). + # Furthermore it avoids an automake error like this when a Makefile.am + # that uses pieces of gnulib also uses $(LIBOBJ): + # automatically discovered file `error.c' should not be explicitly + # mentioned. + emit += " m4_pushdef([AC_LIBOBJ]," + emit += " m4_defn([%V1%_LIBOBJ]))\n" + emit += " m4_pushdef([AC_REPLACE_FUNCS]," + emit += " m4_defn([%V1%_REPLACE_FUNCS]))\n" + # Overriding AC_LIBSOURCES has the same purpose of avoiding the automake + # error when a Makefile.am that uses pieces of gnulib also uses $(LIBOBJ): + # automatically discovered file `error.c' should not be explicitly + # mentioned + # We let automake know about the files to be distributed through the + # EXTRA_lib_SOURCES variable. + emit += " m4_pushdef([AC_LIBSOURCES]," + emit += " m4_defn([%V1%_LIBSOURCES]))\n" + # Create data variables for checking the presence of files that are + # mentioned as AC_LIBSOURCES arguments. These are m4 variables, not shell + # variables, because we want the check to happen when the configure file is + # created, not when it is run. ${macro_prefix_arg}_LIBSOURCES_LIST is the + # list of files to check for. ${macro_prefix_arg}_LIBSOURCES_DIR is the + # subdirectory in which to expect them. + emit += " m4_pushdef([%V1%_LIBSOURCES_LIST], [])\n" + emit += " m4_pushdef([%V1%_LIBSOURCES_DIR], [])\n" + emit += " gl_COMMON\n" + emit = emit.replace('%V1%', macro_prefix_arg) + if type(emit) is bytes: + emit = emit.decode(ENCS['default']) + return(constants.nlconvert(emit)) + + def initmacro_end(self, macro_prefix_arg): + '''GLEmiter.initmacro_end(macro_prefix_arg) -> string + + Emit the last few statements of the gl_INIT macro.''' + emit = string() + if type(macro_prefix_arg) is bytes or type(macro_prefix_arg) is string: + if type(macro_prefix_arg) is bytes: + macro_prefix_arg = macro_prefix_arg.decode(ENCS['default']) + else: # if macro_prefix_arg has not bytes or string type + raise(TypeError('macro_prefix_arg must be a string, not %s' % + type(macro_prefix_arg).__name__)) + # Check the presence of files that are mentioned as AC_LIBSOURCES + # arguments. The check is performed only when autoconf is run from the + # directory where the configure.ac resides; if it is run from a different + # directory, the check is skipped. + emit += """\ m4_ifval(%V1%_LIBSOURCES_LIST, [ m4_syscmd([test ! -d ]m4_defn([%V1%_LIBSOURCES_DIR])[ || for gl_file in ]%V1%_LIBSOURCES_LIST[ ; do @@ -536,30 +540,30 @@ found])]) AC_SUBST([%V1%_LIBOBJS], [$%V1%_libobjs]) AC_SUBST([%V1%_LTLIBOBJS], [$%V1%_ltlibobjs]) ])\n""" - emit = emit.replace('%V1%', macro_prefix_arg) - if type(emit) is bytes: - emit = emit.decode(ENCS['default']) - return(constants.nlconvert(emit)) - - def initmacro_done(self, macro_prefix_arg, sourcebase_arg): - '''GLEmiter.initmacro_done(macro_prefix_arg, sourcebase_arg) -> string - - Emit a few statements after the gl_INIT macro. - GLConfig: sourcebase.''' - emit = string() - if type(macro_prefix_arg) is bytes or type(macro_prefix_arg) is string: - if type(macro_prefix_arg) is bytes: - macro_prefix_arg = macro_prefix_arg.decode(ENCS['default']) - else: # if macro_prefix_arg has not bytes or string type - raise(TypeError('macro_prefix_arg must be a string, not %s' % \ - type(macro_prefix_arg).__name__)) - if type(sourcebase_arg) is bytes or type(sourcebase_arg) is string: - if type(sourcebase_arg) is bytes: - sourcebase_arg = sourcebase_arg.decode(ENCS['default']) - else: # if sourcebase_arg has not bytes or string type - raise(TypeError('sourcebase_arg must be a string, not %s' % \ - type(sourcebase_arg).__name__)) - emit += """\ + emit = emit.replace('%V1%', macro_prefix_arg) + if type(emit) is bytes: + emit = emit.decode(ENCS['default']) + return(constants.nlconvert(emit)) + + def initmacro_done(self, macro_prefix_arg, sourcebase_arg): + '''GLEmiter.initmacro_done(macro_prefix_arg, sourcebase_arg) -> string + + Emit a few statements after the gl_INIT macro. + GLConfig: sourcebase.''' + emit = string() + if type(macro_prefix_arg) is bytes or type(macro_prefix_arg) is string: + if type(macro_prefix_arg) is bytes: + macro_prefix_arg = macro_prefix_arg.decode(ENCS['default']) + else: # if macro_prefix_arg has not bytes or string type + raise(TypeError('macro_prefix_arg must be a string, not %s' % + type(macro_prefix_arg).__name__)) + if type(sourcebase_arg) is bytes or type(sourcebase_arg) is string: + if type(sourcebase_arg) is bytes: + sourcebase_arg = sourcebase_arg.decode(ENCS['default']) + else: # if sourcebase_arg has not bytes or string type + raise(TypeError('sourcebase_arg must be a string, not %s' % + type(sourcebase_arg).__name__)) + emit += """\ # Like AC_LIBOBJ, except that the module name goes # into %V1%_LIBOBJS instead of into LIBOBJS. @@ -587,552 +591,577 @@ AC_DEFUN([%V1%_LIBSOURCES], [ ]) ]) ])\n""" - emit = emit.replace('%V1%', macro_prefix_arg) - emit = emit.replace('%V2%', sourcebase_arg) - if type(emit) is bytes: - emit = emit.decode(ENCS['default']) - return(constants.nlconvert(emit)) - - def lib_Makefile_am(self, destfile, modules, - moduletable, makefiletable, actioncmd, for_test): - '''GLEmiter.lib_Makefile_am(destfile, modules, moduletable, makefiletable, - actioncmd, for_test) -> tuple of string and bool - - Emit the contents of the library Makefile. Returns string and a bool - variable which shows if subdirectories are used. - GLConfig: localdir, sourcebase, libname, pobase, auxdir, makefile, libtool, - macro_prefix, podomain, conddeps, witness_c_macro. - - destfile is a filename relative to destdir of Makefile being generated. - modules is a list of GLModule instances. - moduletable is a GLModuleTable instance. - makefiletable is a GLMakefileTable instance. - actioncmd is a string variable, which represents the actioncmd; it can be - an empty string e.g. when user wants to generate files for GLTestDir. - for_test is a bool variable; it must be set to True if creating a package - for testing, False otherwise.''' - if type(destfile) is bytes or type(destfile) is string: - if type(destfile) is bytes: - destfile = destfile.decode(ENCS['default']) - else: # if destfile has not bytes or string type - raise(TypeError('destfile must be a string, not %s' % \ - type(destfile).__name__)) - for module in modules: - if type(module) is not GLModule: - raise(TypeError('each module must be a GLModule instance')) - if type(moduletable) is not GLModuleTable: - raise(TypeError('moduletable must be a GLModuleTable, not %s' % \ - type(moduletable).__name__)) - if type(makefiletable) is not GLMakefileTable: - raise(TypeError('makefiletable must be a GLMakefileTable, not %s' % \ - type(makefiletable).__name__)) - if type(actioncmd) is bytes or type(actioncmd) is string: - if type(actioncmd) is bytes: - actioncmd = actioncmd.decode(ENCS['default']) - else: # if actioncmd has not bytes or string type - raise(TypeError('actioncmd must be a string, not %s' % \ - type(actioncmd).__name__)) - if type(for_test) is not bool: - raise(TypeError('for_test must be a bool, not %s' % \ - type(for_test).__name__)) - emit = string() - localdir = self.config['localdir'] - sourcebase = self.config['sourcebase'] - modcache = self.config['modcache'] - libname = self.config['libname'] - pobase = self.config['pobase'] - auxdir = self.config['auxdir'] - makefile = self.config['makefile'] - libtool = self.config['libtool'] - macro_prefix = self.config['macro_prefix'] - podomain = self.config['podomain'] - conddeps = self.config['conddeps'] - witness_c_macro = self.config['witness_c_macro'] - include_guard_prefix = self.config['include_guard_prefix'] - ac_version = self.config['ac_version'] - destfile = os.path.normpath(destfile) - - # When creating an includable Makefile.am snippet, augment variables with - # += instead of assigning them. - if makefile: - assign = '+=' - else: # if not makefile - assign = '=' - if libtool: - libext = 'la' - perhapsLT = 'LT' - LD_flags = False - else: # if not libtool - libext = 'a' - perhapsLT = '' - LD_flags = True - if for_test: - # When creating a package for testing: Attempt to provoke failures, - # especially link errors, already during "make" rather than during - # "make check", because "make check" is not possible in a cross-compiling - # situation. Turn check_PROGRAMS into noinst_PROGRAMS. - check_PROGRAMS = True - else: # if not for_test - check_PROGRAMS = False - emit += "## DO NOT EDIT! GENERATED AUTOMATICALLY!\n" - emit += "## Process this file with automake to produce Makefile.in.\n" - emit += self.copyright_notice() - if actioncmd: - if len(actioncmd) <= 3000: - emit += "# Reproduce by: %s\n" % actioncmd - emit += '\n' - uses_subdirs = False - - # Modify allsnippets variable. - allsnippets = string() - for module in modules: - if not module.isTests(): - # Get conditional snippet, edit it and save to amsnippet1. - amsnippet1 = module.getAutomakeSnippet_Conditional() - amsnippet1 = amsnippet1.replace('lib_LIBRARIES', 'lib%_LIBRARIES') - amsnippet1 = amsnippet1.replace('lib_LTLIBRARIES', 'lib%_LTLIBRARIES') - if LD_flags: - pattern = compiler('lib_LDFLAGS[\t ]*\\+=(.*?)$', re.S | re.M) - amsnippet1 = pattern.sub('', amsnippet1) - pattern = compiler('lib_([A-Z][A-Z](?:.*?))', re.S | re.M) - amsnippet1 = pattern.sub('%s_%s_\\1' % (libname, libext), amsnippet1) - amsnippet1 = amsnippet1.replace('lib%_LIBRARIES', 'lib_LIBRARIES') - amsnippet1 = amsnippet1.replace('lib%_LTLIBRARIES', 'lib_LTLIBRARIES') - amsnippet1 = amsnippet1.replace('${gl_include_guard_prefix}', - include_guard_prefix) - if str(module) == 'alloca': - amsnippet1 += '%s_%s_LIBADD += @%sALLOCA@\n' % \ - (libname, libext, perhapsLT) - amsnippet1 += '%s_%s_DEPENDENCIES += @%sALLOCA@\n' % \ - (libname, libext, perhapsLT) - if check_PROGRAMS: - amsnippet1 = amsnippet1.replace('check_PROGRAMS', 'noinst_PROGRAMS') - - # Get unconditional snippet, edit it and save to amsnippet1. - amsnippet2 = module.getAutomakeSnippet_Unconditional() - pattern = compiler('lib_([A-Z][A-Z](?:.*?))', re.S | re.M) - amsnippet2 = pattern.sub('%s_%s_\\1' % (libname, libext), amsnippet2) - if type(amsnippet1) is bytes: - amsnippet1 = amsnippet1.decode(ENCS['default']) - if type(amsnippet2) is bytes: - amsnippet2 = amsnippet1.decode(ENCS['default']) - if not (amsnippet1 +amsnippet2).isspace(): - allsnippets += '## begin gnulib module %s\n' % str(module) - if conddeps: - if moduletable.isConditional(module): - name = module.getConditionalName() - allsnippets += 'if %s\n' % name - allsnippets += amsnippet1 - if conddeps: - allsnippets += 'endif\n' - allsnippets += amsnippet2 - allsnippets += '## end gnulib module %s\n\n' % str(module) - - # Test whether there are some source files in subdirectories. - for file in module.getFiles(): - if file.startswith('lib/') and file.endswith('.c') and \ - file.count('/') > 1: - uses_subdirs = True - break - if not makefile: - subdir_options = string() - # If there are source files in subdirectories, prevent collision of the - # object files (example: hash.c and libxml/hash.c). - if uses_subdirs: - subdir_options = string(' subdir-objects') - emit += 'AUTOMAKE_OPTIONS = 1.5 gnits%s\n' % subdir_options - emit += '\n' - if not makefile: - emit += 'SUBDIRS =\n' - emit += 'noinst_HEADERS =\n' - emit += 'noinst_LIBRARIES =\n' - emit += 'noinst_LTLIBRARIES =\n' - # Automake versions < 1.11.4 create an empty pkgdatadir at - # installation time if you specify pkgdata_DATA to empty. - # See automake bugs #10997 and #11030: - # * http://debbugs.gnu.org/10997 - # * http://debbugs.gnu.org/11030 - # So we need this workaround. - pattern = compiler('^pkgdata_DATA *\\+=', re.S | re.M) - if pattern.findall(allsnippets): - emit += 'pkgdata_DATA =\n' - emit += 'EXTRA_DIST =\n' - emit += 'BUILT_SOURCES =\n' - emit += 'SUFFIXES =\n' - emit += 'MOSTLYCLEANFILES %s core *.stackdump\n' % assign - if not makefile: - emit += 'MOSTLYCLEANDIRS =\n' - emit += 'CLEANFILES =\n' - emit += 'DISTCLEANFILES =\n' - emit += 'MAINTAINERCLEANFILES =\n' - - # Execute edits that apply to the Makefile.am being generated. - current_edit = int() - makefile_am_edits = makefiletable.count() - while current_edit != makefile_am_edits: - dictionary = makefiletable[current_edit] - if dictionary['var']: - paths = list() - paths += [joinpath(dictionary['dir'], 'Makefile.am')] - paths += [os.path.normpath('./%s/Makefile.am' % dictionary['dir'])] - paths = sorted(set(paths)) - if destfile in paths: - emit += '%s += %s\n' % (dictionary['var'], dictionary['val']) - current_edit += 1 - - # Define two parts of cppflags variable. - emit += '\n' - cppflags_part1 = string() - cppflags_part2 = string() - if witness_c_macro: - cppflags_part1 = ' -D%s=1' % witness_c_macro - if for_test: - cppflags_part2 = ' -DGNULIB_STRICT_CHECKING=1' - cppflags = '%s%s' % (cppflags_part1, cppflags_part2) - if not makefile: - emit += 'AM_CPPFLAGS =%s\n' % cppflags - emit += 'AM_CFLAGS =\n' - else: # if makefile - if cppflags: - emit += 'AM_CPPFLAGS +=%s\n' % cppflags - emit += '\n' - - # One of the snippets or the user's Makefile.am already specifies an - # installation location for the library. Don't confuse automake by saying - # it should not be installed. - # First test if allsnippets already specify an installation location. - insnippets = False - inmakefile = False - regex = '^[a-zA-Z0-9_]*_%sLIBRARIES *\\+{0,1}= *%s.%s' % \ - (perhapsLT, libname, libext) - pattern = compiler(regex, re.S | re.M) - insnippets = bool(pattern.findall(allsnippets)) - # Then test if $sourcebase/Makefile.am (if it exists) specifies it. - path = joinpath(sourcebase, 'Makefile.am') - if makefile and isfile(path): - with codecs.open(path, 'rb', 'UTF-8') as file: - data = file.read() - inmakefile = bool(pattern.findall(data)) - if not any([insnippets, inmakefile]): - # By default, the generated library should not be installed. - emit += 'noinst_%sLIBRARIES += %s.%s\n' % (perhapsLT, libname, libext) - - emit += '\n' - emit += '%s_%s_SOURCES =\n' % (libname, libext) - # Here we use $(LIBOBJS), not @LIBOBJS@. The value is the same. However, - # automake during its analysis looks for $(LIBOBJS), not for @LIBOBJS@. - emit += '%s_%s_LIBADD = $(%s_%sLIBOBJS)\n' % \ - (libname, libext, macro_prefix, perhapsLT) - emit += '%s_%s_DEPENDENCIES = $(%s_%sLIBOBJS)\n' % \ - (libname, libext, macro_prefix, perhapsLT) - emit += 'EXTRA_%s_%s_SOURCES =\n' % (libname, libext) - if libtool: - emit += '%s_%s_LDFLAGS = $(AM_LDFLAGS)\n' % (libname, libext) - emit += '%s_%s_LDFLAGS += -no-undefined\n' % (libname, libext) - # Synthesize an ${libname}_${libext}_LDFLAGS augmentation by combining - # the link dependencies of all modules. - listing = list() - links = [module.getLink() for module in modules if not module.isTests()] - for link in links: - link = constants.nlremove(link) - position = link.find(' when linking with libtool') - if position != -1: - link = link[:position] - listing += [link] - listing = sorted(set([link for link in listing if link != ''])) - for link in listing: - emit += '%s_%s_LDFLAGS += %s\n' % (libname, libext, link) - emit += '\n' - if pobase: - emit += 'AM_CPPFLAGS += -DDEFAULT_TEXT_DOMAIN="%s-gnulib"\n' % podomain - emit += '\n' - allsnippets = allsnippets.replace('$(top_srcdir)/build-aux/', - '$(top_srcdir)/%s/' % auxdir) - emit += allsnippets - emit += '\n' - emit += 'mostlyclean-local: mostlyclean-generic\n' - emit += '\t@for dir in \'\' $(MOSTLYCLEANDIRS); do \\\n' - emit += '\t if test -n "$$dir" && test -d $$dir; then \\\n' - emit += '\t echo "rmdir $$dir"; rmdir $$dir; \\\n' - emit += '\t fi; \\\n' - emit += '\tdone; \\\n' - emit += '\t:\n' - emit = constants.nlconvert(emit) - if type(emit) is bytes: - emit = emit.decode(ENCS['default']) - result = tuple([emit, uses_subdirs]) - return(result) - - def tests_Makefile_am(self, destfile, modules, makefiletable, - witness_macro, for_test): - '''GLEmiter.tests_Makefile_am(destfile, modules, makefiletable, - witness_c_macro, for_test) -> tuple of string and bool - - Emit the contents of the tests Makefile. Returns string and a bool variable - which shows if subdirectories are used. - GLConfig: localdir, modules, libname, auxdir, makefile, libtool, - sourcebase, m4base, testsbase, macro_prefix, witness_c_macro, - single_configure, libtests. - - destfile is a filename relative to destdir of Makefile being generated. - witness_macro is a string which represents witness_c_macro with the suffix. - modules is a list of GLModule instances. - moduletable is a GLModuleTable instance. - makefiletable is a GLMakefileTable instance. - actioncmd is a string variable, which represents the actioncmd; it can be - an empty string e.g. when user wants to generate files for GLTestDir. - for_test is a bool variable; it must be set to True if creating a package - for testing, False otherwise.''' - if type(destfile) is bytes or type(destfile) is string: - if type(destfile) is bytes: - destfile = destfile.decode(ENCS['default']) - else: # if destfile has not bytes or string type - raise(TypeError('destfile must be a string, not %s' % \ - type(destfile).__name__)) - for module in modules: - if type(module) is not GLModule: - raise(TypeError('each module must be a GLModule instance')) - if type(makefiletable) is not GLMakefileTable: - raise(TypeError('makefiletable must be a GLMakefileTable, not %s' % \ - type(makefiletable).__name__)) - if type(witness_macro) is bytes or type(witness_macro) is string: - if type(witness_macro) is bytes: - witness_macro = witness_macro.decode(ENCS['default']) - else: # if witness_macro has not bytes or string type - raise(TypeError('witness_macro must be a string, not %s' % \ - type(witness_macro).__name__)) - if type(for_test) is not bool: - raise(TypeError('for_test must be a bool, not %s' % \ - type(for_test).__name__)) - emit = string() - localdir = self.config['localdir'] - auxdir = self.config['auxdir'] - sourcebase = self.config['sourcebase'] - modcache = self.config['modcache'] - libname = self.config['libname'] - m4base = self.config['m4base'] - pobase = self.config['pobase'] - testsbase = self.config['testsbase'] - makefile = self.config['makefile'] - libtool = self.config['libtool'] - macro_prefix = self.config['macro_prefix'] - podomain = self.config['podomain'] - conddeps = self.config['conddeps'] - witness_c_macro = self.config['witness_c_macro'] - include_guard_prefix = self.config['include_guard_prefix'] - ac_version = self.config['ac_version'] - libtests = self.config['libtests'] - single_configure = self.config['single_configure'] - - if libtool: - libext = 'la' - perhapsLT = 'LT' - LD_flags = False - else: # if not libtool - libext = 'a' - perhapsLT = '' - LD_flags = True - if for_test: - # When creating a package for testing: Attempt to provoke failures, - # especially link errors, already during "make" rather than during - # "make check", because "make check" is not possible in a cross-compiling - # situation. Turn check_PROGRAMS into noinst_PROGRAMS. - check_PROGRAMS = True - else: # if not for_test - check_PROGRAMS = False - - # Calculate testsbase_inverse - counter = int() - testsbase_inverse = string() - while counter < len(testsbase.split('/')): - testsbase_inverse += '../' - counter += 1 - testsbase_inverse = os.path.normpath(testsbase_inverse) - - # Begin the generation. - emit += "## DO NOT EDIT! GENERATED AUTOMATICALLY!\n" - emit += "## Process this file with automake to produce Makefile.in.\n" - emit += '%s\n' % self.copyright_notice() - - uses_subdirs = False - main_snippets = string() - longrun_snippets = string() - for module in modules: - if for_test and not single_configure: - flag = module.isTests() - else: # if for_test and not single_configure - flag = True - if flag: - snippet = module.getAutomakeSnippet() - snippet = snippet.replace('lib_LIBRARIES', 'lib%_LIBRARIES') - snippet = snippet.replace('lib_LTLIBRARIES', 'lib%_LTLIBRARIES') - if LD_flags: - pattern = compiler('lib_LDFLAGS[\t ]*\\+=(.*?)$', re.S | re.M) - snippet = pattern.sub('', snippet) - pattern = compiler('lib_([A-Z][A-Z](?:.*?))', re.S | re.M) - snippet = pattern.sub('libtests_a_\\1', snippet) - snippet = snippet.replace('lib%_LIBRARIES', 'lib_LIBRARIES') - snippet = snippet.replace('lib%_LTLIBRARIES', 'lib_LTLIBRARIES') - snippet = snippet.replace('${gl_include_guard_prefix}', - include_guard_prefix) - if check_PROGRAMS: - snippet = snippet.replace('check_PROGRAMS', 'noinst_PROGRAMS') - # Check if module is 'alloca'. - if libtests and str(module) == 'alloca': - snippet += 'libtests_a_LIBADD += @%sALLOCA@\n' % perhapsLT - snippet += 'libtests_a_DEPENDENCIES += @%sALLOCA@\n' % perhapsLT - - # Skip the contents if it's entirely empty. - if snippet.strip(): - # Check status of the module. - status = module.getStatus() - islongrun = False - for word in status: - if word == 'longrunning-test': - islongrun = True - break - if not islongrun: - snippet = snippet.replace('\n\nEXTRA_DIST', '\nEXTRA_DIST') - main_snippets += '## begin gnulib module %s\n' % str(module) - main_snippets += snippet - main_snippets += '## end gnulib module %s\n\n' % str(module) - else: # if islongrunning - snippet = snippet.replace('\n\nEXTRA_DIST', '\nEXTRA_DIST') - longrun_snippets += '## begin gnulib module %s\n' % str(module) - longrun_snippets += snippet - longrun_snippets += '## end gnulib module %s\n' % str(module) - - # Test whether there are some source files in subdirectories. - for file in module.getFiles(): - if file.startswith('lib/') and file.endswith('.c') and \ - file.count('/') > 1: - uses_subdirs = True - break - - # Generate dependencies here, since it eases the debugging of test failures. - # If there are source files in subdirectories, prevent collision of the - # object files (example: hash.c and libxml/hash.c). - subdir_options = string() - if uses_subdirs: - subdir_options = string(' subdir-objects') - emit += 'AUTOMAKE_OPTIONS = 1.5 foreign%s\n\n' % subdir_options - if for_test and not single_configure: - emit += 'ACLOCAL_AMFLAGS = -I %s/%s\n\n' % (testsbase_inverse, m4base) - - # Nothing is being added to SUBDIRS; nevertheless the existence of this - # variable is needed to avoid an error from automake: - # "AM_GNU_GETTEXT used but SUBDIRS not defined" - emit += 'SUBDIRS = .\n' - emit += 'TESTS =\n' - emit += 'XFAIL_TESTS =\n' - emit += 'TESTS_ENVIRONMENT =\n' - emit += 'noinst_PROGRAMS =\n' - if not for_test: - emit += 'check_PROGRAMS =\n' - emit += 'noinst_HEADERS =\n' - emit += 'noinst_LIBRARIES =\n' - if libtests: - if for_test: - emit += 'noinst_LIBRARIES += libtests.a\n' - else: # if not for_test - emit += 'check_LIBRARIES = libtests.a\n' - - # Automake versions < 1.11.4 create an empty pkgdatadir at - # installation time if you specify pkgdata_DATA to empty. - # See automake bugs #10997 and #11030: - # * http://debbugs.gnu.org/10997 - # * http://debbugs.gnu.org/11030 - # So we need this workaround. - pattern = compiler('^pkgdata_DATA *\\+=', re.S | re.M) - if bool(pattern.findall(main_snippets)) or \ - bool(pattern.findall(longrun_snippets)): - emit += 'pkgdata_DATA =\n' - - emit += 'EXTRA_DIST =\n' - emit += 'BUILT_SOURCES =\n' - emit += 'SUFFIXES =\n' - emit += 'MOSTLYCLEANFILES = core *.stackdump\n' - emit += 'MOSTLYCLEANDIRS =\n' - emit += 'CLEANFILES =\n' - emit += 'DISTCLEANFILES =\n' - emit += 'MAINTAINERCLEANFILES =\n' - - # Execute edits that apply to the Makefile.am being generated. - # Execute edits that apply to the Makefile.am being generated. - current_edit = int() - makefile_am_edits = makefiletable.count() - while current_edit != makefile_am_edits: - dictionary = makefiletable[current_edit] - if dictionary['var']: - paths = list() - paths += [joinpath(dictionary['dir'], 'Makefile.am')] - paths += [os.path.normpath('./%s/Makefile.am' % dictionary['dir'])] - paths = sorted(set(paths)) - if destfile in paths: - emit += '%s += %s\n' % (dictionary['var'], dictionary['val']) - current_edit += 1 - - emit += '\nAM_CPPFLAGS = \\\n' - if for_test: - emit += ' -DGNULIB_STRICT_CHECKING=1 \\\n' - if witness_c_macro: - emit += ' -D%s=1 \\\n' % witness_c_macro - if witness_macro: - emit += ' -D@%s@=1 \\\n' % witness_macro - emit += ' -I. -I$(srcdir) \\\n' - emit += ' -I%s -I$(srcdir)/%s \\\n' % \ - (testsbase_inverse, testsbase_inverse) - emit += ' -I%s/%s -I$(srcdir)/%s/%s\n' % \ - (testsbase_inverse, sourcebase, testsbase_inverse, sourcebase) - emit += '\n' - - local_ldadd_before = string() - local_ldadd_after = string() - if libtests: - # All test programs need to be linked with libtests.a. - # It needs to be passed to the linker before ${libname}.${libext}, since - # the tests-related modules depend on the main modules. - # It also needs to be passed to the linker after ${libname}.${libext} - # because the latter might contain incomplete modules (such as the - # 'error' module whose dependency to 'progname' is voluntarily omitted). - # The LIBTESTS_LIBDEPS can be passed to the linker once or twice, it does - # not matter. - local_ldadd_before = ' libtests.a' - local_ldadd_after = ' libtests.a $(LIBTESTS_LIBDEPS)' - emit += 'LDADD =%s %s/%s/%s.%s%s\n\n' % \ - (local_ldadd_before, testsbase_inverse, sourcebase, libname, libext, - local_ldadd_after) - if libtests: - emit += 'libtests_a_SOURCES =\n' - # Here we use $(LIBOBJS), not @LIBOBJS@. The value is the same. However, - # automake during its analysis looks for $(LIBOBJS), not for @LIBOBJS@. - emit += 'libtests_a_LIBADD = $(%stests_LIBOBJS)\n' % macro_prefix - emit += 'libtests_a_DEPENDENCIES = $(%stests_LIBOBJS)\n' % macro_prefix - emit += 'EXTRA_libtests_a_SOURCES =\n' - # The circular dependency in LDADD requires this. - emit += 'AM_LIBTOOLFLAGS = --preserve-dup-deps\n\n' - # Many test scripts use ${EXEEXT} or ${srcdir}. - # EXEEXT is defined by AC_PROG_CC through autoconf. - # srcdir is defined by autoconf and automake. - emit += "TESTS_ENVIRONMENT += EXEEXT='@EXEEXT@' srcdir='$(srcdir)'\n\n" - main_snippets = main_snippets.replace('$(top_srcdir)/build-aux/', - '$(top_srcdir)/%s/' % auxdir) - longrun_snippets = longrun_snippets.replace('$(top_srcdir)/build-aux/', - '$(top_srcdir)/%s/' % auxdir) - emit += main_snippets +longrun_snippets - emit += '# Clean up after Solaris cc.\n' - emit += 'clean-local:\n' - emit += '\trm -rf SunWS_cache\n\n' - emit += 'mostlyclean-local: mostlyclean-generic\n' - emit += '\t@for dir in \'\' $(MOSTLYCLEANDIRS); do \\\n' - emit += '\t if test -n "$$dir" && test -d $$dir; then \\\n' - emit += '\t echo "rmdir $$dir"; rmdir $$dir; \\\n' - emit += '\t fi; \\\n' - emit += '\tdone; \\\n' - emit += '\t:\n' - emit = constants.nlconvert(emit) - if type(emit) is bytes: - emit = emit.decode(ENCS['default']) - result = tuple([emit, uses_subdirs]) - return(result) + emit = emit.replace('%V1%', macro_prefix_arg) + emit = emit.replace('%V2%', sourcebase_arg) + if type(emit) is bytes: + emit = emit.decode(ENCS['default']) + return(constants.nlconvert(emit)) + + def lib_Makefile_am(self, destfile, modules, + moduletable, makefiletable, actioncmd, for_test): + '''GLEmiter.lib_Makefile_am(destfile, modules, moduletable, makefiletable, + actioncmd, for_test) -> tuple of string and bool + + Emit the contents of the library Makefile. Returns string and a bool + variable which shows if subdirectories are used. + GLConfig: localdir, sourcebase, libname, pobase, auxdir, makefile, libtool, + macro_prefix, podomain, conddeps, witness_c_macro. + + destfile is a filename relative to destdir of Makefile being generated. + modules is a list of GLModule instances. + moduletable is a GLModuleTable instance. + makefiletable is a GLMakefileTable instance. + actioncmd is a string variable, which represents the actioncmd; it can be + an empty string e.g. when user wants to generate files for GLTestDir. + for_test is a bool variable; it must be set to True if creating a package + for testing, False otherwise.''' + if type(destfile) is bytes or type(destfile) is string: + if type(destfile) is bytes: + destfile = destfile.decode(ENCS['default']) + else: # if destfile has not bytes or string type + raise(TypeError('destfile must be a string, not %s' % + type(destfile).__name__)) + for module in modules: + if type(module) is not GLModule: + raise(TypeError('each module must be a GLModule instance')) + if type(moduletable) is not GLModuleTable: + raise(TypeError('moduletable must be a GLModuleTable, not %s' % + type(moduletable).__name__)) + if type(makefiletable) is not GLMakefileTable: + raise(TypeError('makefiletable must be a GLMakefileTable, not %s' % + type(makefiletable).__name__)) + if type(actioncmd) is bytes or type(actioncmd) is string: + if type(actioncmd) is bytes: + actioncmd = actioncmd.decode(ENCS['default']) + else: # if actioncmd has not bytes or string type + raise(TypeError('actioncmd must be a string, not %s' % + type(actioncmd).__name__)) + if type(for_test) is not bool: + raise(TypeError('for_test must be a bool, not %s' % + type(for_test).__name__)) + emit = string() + localdir = self.config['localdir'] + sourcebase = self.config['sourcebase'] + modcache = self.config['modcache'] + libname = self.config['libname'] + pobase = self.config['pobase'] + auxdir = self.config['auxdir'] + makefile = self.config['makefile'] + libtool = self.config['libtool'] + macro_prefix = self.config['macro_prefix'] + podomain = self.config['podomain'] + conddeps = self.config['conddeps'] + witness_c_macro = self.config['witness_c_macro'] + include_guard_prefix = self.config['include_guard_prefix'] + ac_version = self.config['ac_version'] + destfile = os.path.normpath(destfile) + + # When creating an includable Makefile.am snippet, augment variables with + # += instead of assigning them. + if makefile: + assign = '+=' + else: # if not makefile + assign = '=' + if libtool: + libext = 'la' + perhapsLT = 'LT' + LD_flags = False + else: # if not libtool + libext = 'a' + perhapsLT = '' + LD_flags = True + if for_test: + # When creating a package for testing: Attempt to provoke failures, + # especially link errors, already during "make" rather than during + # "make check", because "make check" is not possible in a cross-compiling + # situation. Turn check_PROGRAMS into noinst_PROGRAMS. + check_PROGRAMS = True + else: # if not for_test + check_PROGRAMS = False + emit += "## DO NOT EDIT! GENERATED AUTOMATICALLY!\n" + emit += "## Process this file with automake to produce Makefile.in.\n" + emit += self.copyright_notice() + if actioncmd: + if len(actioncmd) <= 3000: + emit += "# Reproduce by: %s\n" % actioncmd + emit += '\n' + uses_subdirs = False + + # Modify allsnippets variable. + allsnippets = string() + for module in modules: + if not module.isTests(): + # Get conditional snippet, edit it and save to amsnippet1. + amsnippet1 = module.getAutomakeSnippet_Conditional() + amsnippet1 = amsnippet1.replace( + 'lib_LIBRARIES', 'lib%_LIBRARIES') + amsnippet1 = amsnippet1.replace( + 'lib_LTLIBRARIES', 'lib%_LTLIBRARIES') + if LD_flags: + pattern = compiler( + 'lib_LDFLAGS[\t ]*\\+=(.*?)$', re.S | re.M) + amsnippet1 = pattern.sub('', amsnippet1) + pattern = compiler('lib_([A-Z][A-Z](?:.*?))', re.S | re.M) + amsnippet1 = pattern.sub('%s_%s_\\1' % + (libname, libext), amsnippet1) + amsnippet1 = amsnippet1.replace( + 'lib%_LIBRARIES', 'lib_LIBRARIES') + amsnippet1 = amsnippet1.replace( + 'lib%_LTLIBRARIES', 'lib_LTLIBRARIES') + amsnippet1 = amsnippet1.replace('${gl_include_guard_prefix}', + include_guard_prefix) + if str(module) == 'alloca': + amsnippet1 += '%s_%s_LIBADD += @%sALLOCA@\n' % \ + (libname, libext, perhapsLT) + amsnippet1 += '%s_%s_DEPENDENCIES += @%sALLOCA@\n' % \ + (libname, libext, perhapsLT) + if check_PROGRAMS: + amsnippet1 = amsnippet1.replace( + 'check_PROGRAMS', 'noinst_PROGRAMS') + + # Get unconditional snippet, edit it and save to amsnippet1. + amsnippet2 = module.getAutomakeSnippet_Unconditional() + pattern = compiler('lib_([A-Z][A-Z](?:.*?))', re.S | re.M) + amsnippet2 = pattern.sub('%s_%s_\\1' % + (libname, libext), amsnippet2) + if type(amsnippet1) is bytes: + amsnippet1 = amsnippet1.decode(ENCS['default']) + if type(amsnippet2) is bytes: + amsnippet2 = amsnippet1.decode(ENCS['default']) + if not (amsnippet1 + amsnippet2).isspace(): + allsnippets += '## begin gnulib module %s\n' % str(module) + if conddeps: + if moduletable.isConditional(module): + name = module.getConditionalName() + allsnippets += 'if %s\n' % name + allsnippets += amsnippet1 + if conddeps: + allsnippets += 'endif\n' + allsnippets += amsnippet2 + allsnippets += '## end gnulib module %s\n\n' % str( + module) + + # Test whether there are some source files in subdirectories. + for file in module.getFiles(): + if file.startswith('lib/') and file.endswith('.c') and \ + file.count('/') > 1: + uses_subdirs = True + break + if not makefile: + subdir_options = string() + # If there are source files in subdirectories, prevent collision of the + # object files (example: hash.c and libxml/hash.c). + if uses_subdirs: + subdir_options = string(' subdir-objects') + emit += 'AUTOMAKE_OPTIONS = 1.5 gnits%s\n' % subdir_options + emit += '\n' + if not makefile: + emit += 'SUBDIRS =\n' + emit += 'noinst_HEADERS =\n' + emit += 'noinst_LIBRARIES =\n' + emit += 'noinst_LTLIBRARIES =\n' + # Automake versions < 1.11.4 create an empty pkgdatadir at + # installation time if you specify pkgdata_DATA to empty. + # See automake bugs #10997 and #11030: + # * http://debbugs.gnu.org/10997 + # * http://debbugs.gnu.org/11030 + # So we need this workaround. + pattern = compiler('^pkgdata_DATA *\\+=', re.S | re.M) + if pattern.findall(allsnippets): + emit += 'pkgdata_DATA =\n' + emit += 'EXTRA_DIST =\n' + emit += 'BUILT_SOURCES =\n' + emit += 'SUFFIXES =\n' + emit += 'MOSTLYCLEANFILES %s core *.stackdump\n' % assign + if not makefile: + emit += 'MOSTLYCLEANDIRS =\n' + emit += 'CLEANFILES =\n' + emit += 'DISTCLEANFILES =\n' + emit += 'MAINTAINERCLEANFILES =\n' + + # Execute edits that apply to the Makefile.am being generated. + current_edit = int() + makefile_am_edits = makefiletable.count() + while current_edit != makefile_am_edits: + dictionary = makefiletable[current_edit] + if dictionary['var']: + paths = list() + paths += [joinpath(dictionary['dir'], 'Makefile.am')] + paths += [os.path.normpath('./%s/Makefile.am' % + dictionary['dir'])] + paths = sorted(set(paths)) + if destfile in paths: + emit += '%s += %s\n' % (dictionary['var'], + dictionary['val']) + current_edit += 1 + + # Define two parts of cppflags variable. + emit += '\n' + cppflags_part1 = string() + cppflags_part2 = string() + if witness_c_macro: + cppflags_part1 = ' -D%s=1' % witness_c_macro + if for_test: + cppflags_part2 = ' -DGNULIB_STRICT_CHECKING=1' + cppflags = '%s%s' % (cppflags_part1, cppflags_part2) + if not makefile: + emit += 'AM_CPPFLAGS =%s\n' % cppflags + emit += 'AM_CFLAGS =\n' + else: # if makefile + if cppflags: + emit += 'AM_CPPFLAGS +=%s\n' % cppflags + emit += '\n' + + # One of the snippets or the user's Makefile.am already specifies an + # installation location for the library. Don't confuse automake by saying + # it should not be installed. + # First test if allsnippets already specify an installation location. + insnippets = False + inmakefile = False + regex = '^[a-zA-Z0-9_]*_%sLIBRARIES *\\+{0,1}= *%s.%s' % \ + (perhapsLT, libname, libext) + pattern = compiler(regex, re.S | re.M) + insnippets = bool(pattern.findall(allsnippets)) + # Then test if $sourcebase/Makefile.am (if it exists) specifies it. + path = joinpath(sourcebase, 'Makefile.am') + if makefile and isfile(path): + with codecs.open(path, 'rb', 'UTF-8') as file: + data = file.read() + inmakefile = bool(pattern.findall(data)) + if not any([insnippets, inmakefile]): + # By default, the generated library should not be installed. + emit += 'noinst_%sLIBRARIES += %s.%s\n' % ( + perhapsLT, libname, libext) + + emit += '\n' + emit += '%s_%s_SOURCES =\n' % (libname, libext) + # Here we use $(LIBOBJS), not @LIBOBJS@. The value is the same. However, + # automake during its analysis looks for $(LIBOBJS), not for @LIBOBJS@. + emit += '%s_%s_LIBADD = $(%s_%sLIBOBJS)\n' % \ + (libname, libext, macro_prefix, perhapsLT) + emit += '%s_%s_DEPENDENCIES = $(%s_%sLIBOBJS)\n' % \ + (libname, libext, macro_prefix, perhapsLT) + emit += 'EXTRA_%s_%s_SOURCES =\n' % (libname, libext) + if libtool: + emit += '%s_%s_LDFLAGS = $(AM_LDFLAGS)\n' % (libname, libext) + emit += '%s_%s_LDFLAGS += -no-undefined\n' % (libname, libext) + # Synthesize an ${libname}_${libext}_LDFLAGS augmentation by combining + # the link dependencies of all modules. + listing = list() + links = [module.getLink() + for module in modules if not module.isTests()] + for link in links: + link = constants.nlremove(link) + position = link.find(' when linking with libtool') + if position != -1: + link = link[:position] + listing += [link] + listing = sorted(set([link for link in listing if link != ''])) + for link in listing: + emit += '%s_%s_LDFLAGS += %s\n' % (libname, libext, link) + emit += '\n' + if pobase: + emit += 'AM_CPPFLAGS += -DDEFAULT_TEXT_DOMAIN="%s-gnulib"\n' % podomain + emit += '\n' + allsnippets = allsnippets.replace('$(top_srcdir)/build-aux/', + '$(top_srcdir)/%s/' % auxdir) + emit += allsnippets + emit += '\n' + emit += 'mostlyclean-local: mostlyclean-generic\n' + emit += '\t@for dir in \'\' $(MOSTLYCLEANDIRS); do \\\n' + emit += '\t if test -n "$$dir" && test -d $$dir; then \\\n' + emit += '\t echo "rmdir $$dir"; rmdir $$dir; \\\n' + emit += '\t fi; \\\n' + emit += '\tdone; \\\n' + emit += '\t:\n' + emit = constants.nlconvert(emit) + if type(emit) is bytes: + emit = emit.decode(ENCS['default']) + result = tuple([emit, uses_subdirs]) + return(result) + + def tests_Makefile_am(self, destfile, modules, makefiletable, + witness_macro, for_test): + '''GLEmiter.tests_Makefile_am(destfile, modules, makefiletable, + witness_c_macro, for_test) -> tuple of string and bool + + Emit the contents of the tests Makefile. Returns string and a bool variable + which shows if subdirectories are used. + GLConfig: localdir, modules, libname, auxdir, makefile, libtool, + sourcebase, m4base, testsbase, macro_prefix, witness_c_macro, + single_configure, libtests. + + destfile is a filename relative to destdir of Makefile being generated. + witness_macro is a string which represents witness_c_macro with the suffix. + modules is a list of GLModule instances. + moduletable is a GLModuleTable instance. + makefiletable is a GLMakefileTable instance. + actioncmd is a string variable, which represents the actioncmd; it can be + an empty string e.g. when user wants to generate files for GLTestDir. + for_test is a bool variable; it must be set to True if creating a package + for testing, False otherwise.''' + if type(destfile) is bytes or type(destfile) is string: + if type(destfile) is bytes: + destfile = destfile.decode(ENCS['default']) + else: # if destfile has not bytes or string type + raise(TypeError('destfile must be a string, not %s' % + type(destfile).__name__)) + for module in modules: + if type(module) is not GLModule: + raise(TypeError('each module must be a GLModule instance')) + if type(makefiletable) is not GLMakefileTable: + raise(TypeError('makefiletable must be a GLMakefileTable, not %s' % + type(makefiletable).__name__)) + if type(witness_macro) is bytes or type(witness_macro) is string: + if type(witness_macro) is bytes: + witness_macro = witness_macro.decode(ENCS['default']) + else: # if witness_macro has not bytes or string type + raise(TypeError('witness_macro must be a string, not %s' % + type(witness_macro).__name__)) + if type(for_test) is not bool: + raise(TypeError('for_test must be a bool, not %s' % + type(for_test).__name__)) + emit = string() + localdir = self.config['localdir'] + auxdir = self.config['auxdir'] + sourcebase = self.config['sourcebase'] + modcache = self.config['modcache'] + libname = self.config['libname'] + m4base = self.config['m4base'] + pobase = self.config['pobase'] + testsbase = self.config['testsbase'] + makefile = self.config['makefile'] + libtool = self.config['libtool'] + macro_prefix = self.config['macro_prefix'] + podomain = self.config['podomain'] + conddeps = self.config['conddeps'] + witness_c_macro = self.config['witness_c_macro'] + include_guard_prefix = self.config['include_guard_prefix'] + ac_version = self.config['ac_version'] + libtests = self.config['libtests'] + single_configure = self.config['single_configure'] + + if libtool: + libext = 'la' + perhapsLT = 'LT' + LD_flags = False + else: # if not libtool + libext = 'a' + perhapsLT = '' + LD_flags = True + if for_test: + # When creating a package for testing: Attempt to provoke failures, + # especially link errors, already during "make" rather than during + # "make check", because "make check" is not possible in a cross-compiling + # situation. Turn check_PROGRAMS into noinst_PROGRAMS. + check_PROGRAMS = True + else: # if not for_test + check_PROGRAMS = False + + # Calculate testsbase_inverse + counter = int() + testsbase_inverse = string() + while counter < len(testsbase.split('/')): + testsbase_inverse += '../' + counter += 1 + testsbase_inverse = os.path.normpath(testsbase_inverse) + + # Begin the generation. + emit += "## DO NOT EDIT! GENERATED AUTOMATICALLY!\n" + emit += "## Process this file with automake to produce Makefile.in.\n" + emit += '%s\n' % self.copyright_notice() + + uses_subdirs = False + main_snippets = string() + longrun_snippets = string() + for module in modules: + if for_test and not single_configure: + flag = module.isTests() + else: # if for_test and not single_configure + flag = True + if flag: + snippet = module.getAutomakeSnippet() + snippet = snippet.replace('lib_LIBRARIES', 'lib%_LIBRARIES') + snippet = snippet.replace( + 'lib_LTLIBRARIES', 'lib%_LTLIBRARIES') + if LD_flags: + pattern = compiler( + 'lib_LDFLAGS[\t ]*\\+=(.*?)$', re.S | re.M) + snippet = pattern.sub('', snippet) + pattern = compiler('lib_([A-Z][A-Z](?:.*?))', re.S | re.M) + snippet = pattern.sub('libtests_a_\\1', snippet) + snippet = snippet.replace('lib%_LIBRARIES', 'lib_LIBRARIES') + snippet = snippet.replace( + 'lib%_LTLIBRARIES', 'lib_LTLIBRARIES') + snippet = snippet.replace('${gl_include_guard_prefix}', + include_guard_prefix) + if check_PROGRAMS: + snippet = snippet.replace( + 'check_PROGRAMS', 'noinst_PROGRAMS') + # Check if module is 'alloca'. + if libtests and str(module) == 'alloca': + snippet += 'libtests_a_LIBADD += @%sALLOCA@\n' % perhapsLT + snippet += 'libtests_a_DEPENDENCIES += @%sALLOCA@\n' % perhapsLT + + # Skip the contents if it's entirely empty. + if snippet.strip(): + # Check status of the module. + status = module.getStatus() + islongrun = False + for word in status: + if word == 'longrunning-test': + islongrun = True + break + if not islongrun: + snippet = snippet.replace( + '\n\nEXTRA_DIST', '\nEXTRA_DIST') + main_snippets += '## begin gnulib module %s\n' % str( + module) + main_snippets += snippet + main_snippets += '## end gnulib module %s\n\n' % str( + module) + else: # if islongrunning + snippet = snippet.replace( + '\n\nEXTRA_DIST', '\nEXTRA_DIST') + longrun_snippets += '## begin gnulib module %s\n' % str( + module) + longrun_snippets += snippet + longrun_snippets += '## end gnulib module %s\n' % str( + module) + + # Test whether there are some source files in subdirectories. + for file in module.getFiles(): + if file.startswith('lib/') and file.endswith('.c') and \ + file.count('/') > 1: + uses_subdirs = True + break + + # Generate dependencies here, since it eases the debugging of test failures. + # If there are source files in subdirectories, prevent collision of the + # object files (example: hash.c and libxml/hash.c). + subdir_options = string() + if uses_subdirs: + subdir_options = string(' subdir-objects') + emit += 'AUTOMAKE_OPTIONS = 1.5 foreign%s\n\n' % subdir_options + if for_test and not single_configure: + emit += 'ACLOCAL_AMFLAGS = -I %s/%s\n\n' % ( + testsbase_inverse, m4base) + + # Nothing is being added to SUBDIRS; nevertheless the existence of this + # variable is needed to avoid an error from automake: + # "AM_GNU_GETTEXT used but SUBDIRS not defined" + emit += 'SUBDIRS = .\n' + emit += 'TESTS =\n' + emit += 'XFAIL_TESTS =\n' + emit += 'TESTS_ENVIRONMENT =\n' + emit += 'noinst_PROGRAMS =\n' + if not for_test: + emit += 'check_PROGRAMS =\n' + emit += 'noinst_HEADERS =\n' + emit += 'noinst_LIBRARIES =\n' + if libtests: + if for_test: + emit += 'noinst_LIBRARIES += libtests.a\n' + else: # if not for_test + emit += 'check_LIBRARIES = libtests.a\n' + + # Automake versions < 1.11.4 create an empty pkgdatadir at + # installation time if you specify pkgdata_DATA to empty. + # See automake bugs #10997 and #11030: + # * http://debbugs.gnu.org/10997 + # * http://debbugs.gnu.org/11030 + # So we need this workaround. + pattern = compiler('^pkgdata_DATA *\\+=', re.S | re.M) + if bool(pattern.findall(main_snippets)) or \ + bool(pattern.findall(longrun_snippets)): + emit += 'pkgdata_DATA =\n' + + emit += 'EXTRA_DIST =\n' + emit += 'BUILT_SOURCES =\n' + emit += 'SUFFIXES =\n' + emit += 'MOSTLYCLEANFILES = core *.stackdump\n' + emit += 'MOSTLYCLEANDIRS =\n' + emit += 'CLEANFILES =\n' + emit += 'DISTCLEANFILES =\n' + emit += 'MAINTAINERCLEANFILES =\n' + + # Execute edits that apply to the Makefile.am being generated. + # Execute edits that apply to the Makefile.am being generated. + current_edit = int() + makefile_am_edits = makefiletable.count() + while current_edit != makefile_am_edits: + dictionary = makefiletable[current_edit] + if dictionary['var']: + paths = list() + paths += [joinpath(dictionary['dir'], 'Makefile.am')] + paths += [os.path.normpath('./%s/Makefile.am' % + dictionary['dir'])] + paths = sorted(set(paths)) + if destfile in paths: + emit += '%s += %s\n' % (dictionary['var'], + dictionary['val']) + current_edit += 1 + + emit += '\nAM_CPPFLAGS = \\\n' + if for_test: + emit += ' -DGNULIB_STRICT_CHECKING=1 \\\n' + if witness_c_macro: + emit += ' -D%s=1 \\\n' % witness_c_macro + if witness_macro: + emit += ' -D@%s@=1 \\\n' % witness_macro + emit += ' -I. -I$(srcdir) \\\n' + emit += ' -I%s -I$(srcdir)/%s \\\n' % \ + (testsbase_inverse, testsbase_inverse) + emit += ' -I%s/%s -I$(srcdir)/%s/%s\n' % \ + (testsbase_inverse, sourcebase, testsbase_inverse, sourcebase) + emit += '\n' + local_ldadd_before = string() + local_ldadd_after = string() + if libtests: + # All test programs need to be linked with libtests.a. + # It needs to be passed to the linker before ${libname}.${libext}, since + # the tests-related modules depend on the main modules. + # It also needs to be passed to the linker after ${libname}.${libext} + # because the latter might contain incomplete modules (such as the + # 'error' module whose dependency to 'progname' is voluntarily omitted). + # The LIBTESTS_LIBDEPS can be passed to the linker once or twice, it does + # not matter. + local_ldadd_before = ' libtests.a' + local_ldadd_after = ' libtests.a $(LIBTESTS_LIBDEPS)' + emit += 'LDADD =%s %s/%s/%s.%s%s\n\n' % \ + (local_ldadd_before, testsbase_inverse, sourcebase, libname, libext, + local_ldadd_after) + if libtests: + emit += 'libtests_a_SOURCES =\n' + # Here we use $(LIBOBJS), not @LIBOBJS@. The value is the same. However, + # automake during its analysis looks for $(LIBOBJS), not for @LIBOBJS@. + emit += 'libtests_a_LIBADD = $(%stests_LIBOBJS)\n' % macro_prefix + emit += 'libtests_a_DEPENDENCIES = $(%stests_LIBOBJS)\n' % macro_prefix + emit += 'EXTRA_libtests_a_SOURCES =\n' + # The circular dependency in LDADD requires this. + emit += 'AM_LIBTOOLFLAGS = --preserve-dup-deps\n\n' + # Many test scripts use ${EXEEXT} or ${srcdir}. + # EXEEXT is defined by AC_PROG_CC through autoconf. + # srcdir is defined by autoconf and automake. + emit += "TESTS_ENVIRONMENT += EXEEXT='@EXEEXT@' srcdir='$(srcdir)'\n\n" + main_snippets = main_snippets.replace('$(top_srcdir)/build-aux/', + '$(top_srcdir)/%s/' % auxdir) + longrun_snippets = longrun_snippets.replace('$(top_srcdir)/build-aux/', + '$(top_srcdir)/%s/' % auxdir) + emit += main_snippets + longrun_snippets + emit += '# Clean up after Solaris cc.\n' + emit += 'clean-local:\n' + emit += '\trm -rf SunWS_cache\n\n' + emit += 'mostlyclean-local: mostlyclean-generic\n' + emit += '\t@for dir in \'\' $(MOSTLYCLEANDIRS); do \\\n' + emit += '\t if test -n "$$dir" && test -d $$dir; then \\\n' + emit += '\t echo "rmdir $$dir"; rmdir $$dir; \\\n' + emit += '\t fi; \\\n' + emit += '\tdone; \\\n' + emit += '\t:\n' + emit = constants.nlconvert(emit) + if type(emit) is bytes: + emit = emit.decode(ENCS['default']) + result = tuple([emit, uses_subdirs]) + return(result) diff --git a/pygnulib/GLError.py b/pygnulib/GLError.py index 2afe970b2b..04e2e731c1 100644 --- a/pygnulib/GLError.py +++ b/pygnulib/GLError.py @@ -47,69 +47,70 @@ relpath = os.path.relpath # Define GLError class #=============================================================================== class GLError(Exception): - '''Exception handler for pygnulib classes.''' + '''Exception handler for pygnulib classes.''' - def __init__(self, errno, errinfo=None): - '''Each error has following parameters: - errno: code of error; used to catch error type - 1: file does not exist in GLFileSystem: - 2: cannot patch file inside GLFileSystem: - 3: configure file does not exist: - 4: minimum supported autoconf version is 2.59, not - 5: is expected to contain gl_M4_BASE([]) - 6: missing sourcebase argument - 7: missing docbase argument - 8: missing testsbase argument - 9: missing libname argument - 10: conddeps are not supported with inctests - 11: incompatible licenses on modules: - 12: cannot process empy filelist - 13: cannot create the given directory: - 14: cannot delete the given file: - 15: cannot create the given file: - 16: cannot transform the given file: - 17: cannot update the given file: - 18: module lacks a license: - 19: could not create destination directory: - errinfo: additional information; - style: 0 or 1, wheter old-style''' - self.errno = errno; self.errinfo = errinfo - self.args = (self.errno, self.errinfo) - - def __repr__(self): - errinfo = self.errinfo - errors = \ - [ # Begin list of errors - "file does not exist in GLFileSystem: %s" % repr(errinfo), - "cannot patch file inside GLFileSystem: %s" % repr(errinfo), - "configure file does not exist: %s" % repr(errinfo), - "minimum supported autoconf version is 2.59, not %s" % repr(errinfo), - "%s is expected to contain gl_M4_BASE([%s])" % \ - (repr(os.path.join(errinfo, 'gnulib-comp.m4')), repr(errinfo)), - "missing sourcebase argument; cache file doesn't contain it," - +" so you might have to set this argument", - "missing docbase argument; you might have to create GLImport" \ - +" instance with mode 0 and docbase argument", - "missing testsbase argument; cache file doesn't contain it," - +" so you might have to set this argument" - "missing libname argument; cache file doesn't contain it," - +" so you might have to set this argument", - "conddeps are not supported with inctests", - "incompatible licenses on modules: %s" % repr(errinfo), - "cannot process empy filelist", - "cannot create the given directory: %s" % repr(errinfo), - "cannot remove the given file: %s" % repr(errinfo), - "cannot create the given file: %s" % repr(errinfo), - "cannot transform the given file: %s" % repr(errinfo), - "cannot update/replace the given file: %s" % repr(errinfo), - "module lacks a license: %s" % repr(errinfo), - "error when running subprocess: %s" % repr(errinfo), - ] # Complete list of errors - if not PYTHON3: - self.message = (b'[Errno %d] %s' % \ - (self.errno, errors[self.errno -1].encode(ENCS['default']))) - else: # if PYTHON3 - self.message = ('[Errno %d] %s' % \ - (self.errno, errors[self.errno -1])) - return(self.message) + def __init__(self, errno, errinfo=None): + '''Each error has following parameters: + errno: code of error; used to catch error type + 1: file does not exist in GLFileSystem: + 2: cannot patch file inside GLFileSystem: + 3: configure file does not exist: + 4: minimum supported autoconf version is 2.59, not + 5: is expected to contain gl_M4_BASE([]) + 6: missing sourcebase argument + 7: missing docbase argument + 8: missing testsbase argument + 9: missing libname argument + 10: conddeps are not supported with inctests + 11: incompatible licenses on modules: + 12: cannot process empy filelist + 13: cannot create the given directory: + 14: cannot delete the given file: + 15: cannot create the given file: + 16: cannot transform the given file: + 17: cannot update the given file: + 18: module lacks a license: + 19: could not create destination directory: + errinfo: additional information; + style: 0 or 1, wheter old-style''' + self.errno = errno + self.errinfo = errinfo + self.args = (self.errno, self.errinfo) + def __repr__(self): + errinfo = self.errinfo + errors = \ + [ # Begin list of errors + "file does not exist in GLFileSystem: %s" % repr(errinfo), + "cannot patch file inside GLFileSystem: %s" % repr(errinfo), + "configure file does not exist: %s" % repr(errinfo), + "minimum supported autoconf version is 2.59, not %s" % repr( + errinfo), + "%s is expected to contain gl_M4_BASE([%s])" % \ + (repr(os.path.join(errinfo, 'gnulib-comp.m4')), repr(errinfo)), + "missing sourcebase argument; cache file doesn't contain it," + + " so you might have to set this argument", + "missing docbase argument; you might have to create GLImport" \ + + " instance with mode 0 and docbase argument", + "missing testsbase argument; cache file doesn't contain it," + + " so you might have to set this argument" + "missing libname argument; cache file doesn't contain it," + + " so you might have to set this argument", + "conddeps are not supported with inctests", + "incompatible licenses on modules: %s" % repr(errinfo), + "cannot process empy filelist", + "cannot create the given directory: %s" % repr(errinfo), + "cannot remove the given file: %s" % repr(errinfo), + "cannot create the given file: %s" % repr(errinfo), + "cannot transform the given file: %s" % repr(errinfo), + "cannot update/replace the given file: %s" % repr(errinfo), + "module lacks a license: %s" % repr(errinfo), + "error when running subprocess: %s" % repr(errinfo), + ] # Complete list of errors + if not PYTHON3: + self.message = (b'[Errno %d] %s' % + (self.errno, errors[self.errno - 1].encode(ENCS['default']))) + else: # if PYTHON3 + self.message = ('[Errno %d] %s' % + (self.errno, errors[self.errno - 1])) + return(self.message) diff --git a/pygnulib/GLFileSystem.py b/pygnulib/GLFileSystem.py index 588df95cea..9821fd60c0 100644 --- a/pygnulib/GLFileSystem.py +++ b/pygnulib/GLFileSystem.py @@ -51,351 +51,355 @@ relpath = os.path.relpath # 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.''' - - def __init__(self, config): - '''Create new GLFileSystem instance. The only argument is localdir, - which can be an empty string too.''' - if type(config) is not GLConfig: - raise(TypeError('config must be a GLConfig, not %s' % \ - type(config).__name__)) - self.config = config - - def __repr__(self): - '''x.__repr__ <==> repr(x)''' - result = '' % hex(id(self)) - return(result) - - def lookup(self, name): - '''GLFileSystem.lookup(name) -> tuple - - Lookup a file in gnulib and localdir directories or combine it using Linux - '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.''' - if type(name) is bytes or type(name) is string: - if type(name) is bytes: - name = name.decode(ENCS['default']) - else: # if name has not bytes or string type - 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"' % (path_temp, path_diff) - 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)) - return(result) + '''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.''' + + def __init__(self, config): + '''Create new GLFileSystem instance. The only argument is localdir, + which can be an empty string too.''' + if type(config) is not GLConfig: + raise(TypeError('config must be a GLConfig, not %s' % + type(config).__name__)) + self.config = config + + def __repr__(self): + '''x.__repr__ <==> repr(x)''' + result = '' % hex(id(self)) + return(result) + + def lookup(self, name): + '''GLFileSystem.lookup(name) -> tuple + + Lookup a file in gnulib and localdir directories or combine it using Linux + '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.''' + if type(name) is bytes or type(name) is string: + if type(name) is bytes: + name = name.decode(ENCS['default']) + else: # if name has not bytes or string type + 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"' % (path_temp, path_diff) + 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)) + return(result) #=============================================================================== # Define GLFileAssistant class #=============================================================================== class GLFileAssistant(object): - '''GLFileAssistant is used to help with file processing.''' - - def __init__(self, config, transformers=dict()): - '''Create GLFileAssistant instance.''' - if type(config) is not GLConfig: - raise(TypeError('config must be a GLConfig, not %s' % \ - type(config).__name__)) - if type(transformers) is not dict: - raise(TypeError('transformers must be a dict, not %s' % \ - type(transformers).__name__)) - for key in ['lib', 'aux', 'main', 'tests']: - if key not in transformers: - transformers[key] = 's,x,x,' - else: # if key in transformers - value = transformers[key] - if type(value) is bytes or type(value) is string: - if type(value) is bytes: - transformers[key] = value.decode(ENCS['default']) - else: # if value has not bytes or string type - raise(TypeError('transformers[%s] must be a string, not %s' % \ - (key, type(value).__name__))) - self.original = None - self.rewritten = None - self.added = list() - self.makefile = list() - self.config = config - self.transformers = transformers - self.filesystem = GLFileSystem(self.config) - - def __repr__(self): - '''x.__repr__() <==> repr(x)''' - result = '' % hex(id(self)) - return(result) - - def tmpfilename(self, path): - '''GLFileAssistant.tmpfilename() -> string - - Return the name of a temporary file (file is relative to destdir).''' - if type(path) is bytes or type(path) is string: - if type(path) is bytes: - path = path.decode(ENCS['default']) - else: # if path has not bytes or string type - raise(TypeError( - 'path must be a string, not %s' % (type(path).__name__))) - if not self.config['dryrun']: - # Put the new contents of $file in a file in the same directory (needed - # to guarantee that an 'mv' to "$destdir/$file" works). - result = joinpath(self.config['destdir'], '%s.tmp' % path) - dirname = os.path.dirname(result) - if dirname and not isdir(dirname): - os.makedirs(dirname) - else: # if self.config['dryrun'] - # Put the new contents of $file in a file in a temporary directory - # (because the directory of "$file" might not exist). - tempdir = self.config['tempdir'] - result = joinpath(tempdir, '%s.tmp' % os.path.basename(path)) - dirname = os.path.dirname(result) - if not isdir(dirname): - os.makedirs(dirname) - if type(result) is bytes: - result = bytes.decode(ENCS['default']) - return(result) - - def setOriginal(self, original): - '''GLFileAssistant.setOriginal(original) - - Set the name of the original file which will be used.''' - if type(original) is bytes or type(original) is string: - if type(original) is bytes: - original = original.decode(ENCS['default']) - else: # if original has not bytes or string type - raise(TypeError( - 'original must be a string, not %s' % (type(original).__name__))) - self.original = original - - def setRewritten(self, rewritten): - '''GLFileAssistant.setRewritten(rewritten) - - Set the name of the rewritten file which will be used.''' - if type(rewritten) is bytes or type(rewritten) is string: - if type(rewritten) is bytes: - rewritten = rewritten.decode(ENCS['default']) - else: # if rewritten has not bytes or string type - raise(TypeError( - 'rewritten must be a string, not %s' % type(rewritten).__name__)) - self.rewritten = rewritten - - def addFile(self, file): - '''GLFileAssistant.addFile(file) - - Add file to the list of added files.''' - if file not in self.added: - self.added += [file] - - def removeFile(self, file): - '''GLFileAssistant.removeFile(file) - - Remove file from the list of added files.''' - if file in self.added: - self.added.pop(file) - - def getFiles(self): - '''Return list of the added files.''' - return(list(self.added)) - - def add(self, lookedup, tmpflag, tmpfile): - '''GLFileAssistant.add(lookedup, tmpflag, tmpfile) - - This method copies a file from gnulib into the destination directory. - The destination is known to exist. If tmpflag is True, then lookedup file - is a temporary one.''' - 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: - 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)) \ - and not tmpflag and filecmp.cmp(lookedup, tmpfile): - constants.link_if_changed(lookedup, joinpath(destdir, rewritten)) - else: # if any of these conditions is not met - try: # Try to move file - shutil.move(tmpfile, joinpath(destdir, rewritten)) - except Exception as error: - raise(GLError(17, original)) - else: # if self.config['dryrun'] - print('Copy file %s' % rewritten) - - def update(self, lookedup, tmpflag, tmpfile, already_present): - '''GLFileAssistant.update(lookedup, tmpflag, tmpfile, already_present) - - This method copies a file from gnulib into the destination directory. - The destination is known to exist. If tmpflag is True, then lookedup file - is a temporary one.''' - 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: - raise(TypeError('rewritten must be set before applying the method')) - if type(lookedup) is bytes or type(lookedup) is string: - if type(lookedup) is bytes: - lookedup = lookedup.decode(ENCS['default']) - else: # if lookedup has not bytes or string type - raise(TypeError('lookedup must be a string, not %s' % \ - type(lookedup).__name__)) - if type(already_present) is not bool: - raise(TypeError('already_present must be a bool, not %s' % \ - type(already_present).__name__)) - basename = rewritten - backupname = string('%s~' % basename) - basepath = joinpath(destdir, basename) - backuppath = joinpath(destdir, backupname) - if not filecmp.cmp(basepath, tmpfile): - if not self.config['dryrun']: - if already_present: - print('Updating file %s (backup in %s)' % (basename, backupname)) - else: # if not already_present - message = 'Replacing file ' - message += '%s (non-gnulib code backed up in ' % basename - message += '%s) !!' % backupname - print(message) - if isfile(backuppath): - os.remove(backuppath) - try: # Try to replace the given file - 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)) \ - and not tmpflag and filecmp.cmp(lookedup, tmpfile): - constants.link_if_changed(lookedup, basepath) - else: # if any of these conditions is not met - try: # Try to move file - if os.path.exists(basepath): - os.remove(basepath) - shutil.copy(tmpfile, rewritten) - except Exception as error: - raise(GLError(17, original)) - else: # if self.config['dryrun'] - if already_present: - print('Update file %s (backup in %s)' % (rewritten, backup)) - else: # if not already_present - print('Replace file %s (backup in %s)' % (rewritten, backup)) - - def add_or_update(self, already_present): - '''GLFileAssistant.add_or_update(already_present) - - This method handles a file that ought to be present afterwards.''' - original = self.original - rewritten = self.rewritten - if original == None: - raise(TypeError('original must be set before applying the method')) - elif rewritten == None: - raise(TypeError('rewritten must be set before applying the method')) - if type(already_present) is not bool: - raise(TypeError('already_present must be a bool, not %s' % \ - type(already_present).__name__)) - xoriginal = original - if original.startswith('tests=lib/'): - xoriginal = constants.substart('tests=lib/', 'lib/', original) - lookedup, tmpflag = self.filesystem.lookup(xoriginal) - tmpfile = self.tmpfilename(rewritten) - sed_transform_lib_file = self.transformers.get('lib', '') - sed_transform_build_aux_file = self.transformers.get('aux', '') - sed_transform_main_lib_file = self.transformers.get('main', '') - sed_transform_testsrelated_lib_file = self.transformers.get('tests', '') - try: # Try to copy lookedup file to tmpfile - shutil.copy(lookedup, tmpfile) - except Exception as error: - raise(GLError(15, lookedup)) - transformer = string() - if original.startswith('lib/'): - if sed_transform_main_lib_file: - transformer = sed_transform_main_lib_file - elif original.startswith('build-aux/'): - if sed_transform_build_aux_file: - transformer = sed_transform_build_aux_file - elif original.startswith('tests=lib/'): - if sed_transform_testsrelated_lib_file: - transformer = sed_transform_testsrelated_lib_file - if transformer: - args = ['sed', '-e', transformer] - stdin = codecs.open(lookedup, 'rb', 'UTF-8') - try: # Try to transform file - data = sp.check_output(args, stdin=stdin, shell=False) - data = data.decode("UTF-8") - except Exception as error: - raise(GLError(16, lookedup)) - with codecs.open(tmpfile, 'wb', 'UTF-8') as file: - file.write(data) - path = joinpath(self.config['destdir'], rewritten) - if isfile(path): - self.update(lookedup, tmpflag, tmpfile, already_present) - os.remove(tmpfile) - else: # if not isfile(path) - self.add(lookedup, tmpflag, tmpfile) - self.addFile(rewritten) - - def super_update(self, basename, tmpfile): - '''GLFileAssistant.super_update(basename, tmpfile) -> tuple - - Move tmpfile to destdir/basename path, making a backup of it. - Returns tuple, which contains basename, backupname and status. - 0: tmpfile is the same as destfile; - 1: tmpfile was used to update destfile; - 2: destfile was created, because it didn't exist.''' - backupname = '%s~' % basename - basepath = joinpath(self.config['destdir'], basename) - backuppath = joinpath(self.config['destdir'], backupname) - if isfile(basepath): - if filecmp.cmp(basepath, tmpfile): - result_flag = 0 - else: # if not filecmp.cmp(basepath, tmpfile) - result_flag = 1 + '''GLFileAssistant is used to help with file processing.''' + + def __init__(self, config, transformers=dict()): + '''Create GLFileAssistant instance.''' + if type(config) is not GLConfig: + raise(TypeError('config must be a GLConfig, not %s' % + type(config).__name__)) + if type(transformers) is not dict: + raise(TypeError('transformers must be a dict, not %s' % + type(transformers).__name__)) + for key in ['lib', 'aux', 'main', 'tests']: + if key not in transformers: + transformers[key] = 's,x,x,' + else: # if key in transformers + value = transformers[key] + if type(value) is bytes or type(value) is string: + if type(value) is bytes: + transformers[key] = value.decode(ENCS['default']) + else: # if value has not bytes or string type + raise(TypeError('transformers[%s] must be a string, not %s' % + (key, type(value).__name__))) + self.original = None + self.rewritten = None + self.added = list() + self.makefile = list() + self.config = config + self.transformers = transformers + self.filesystem = GLFileSystem(self.config) + + def __repr__(self): + '''x.__repr__() <==> repr(x)''' + result = '' % hex(id(self)) + return(result) + + def tmpfilename(self, path): + '''GLFileAssistant.tmpfilename() -> string + + Return the name of a temporary file (file is relative to destdir).''' + if type(path) is bytes or type(path) is string: + if type(path) is bytes: + path = path.decode(ENCS['default']) + else: # if path has not bytes or string type + raise(TypeError( + 'path must be a string, not %s' % (type(path).__name__))) if not self.config['dryrun']: - if isfile(backuppath): - os.remove(backuppath) - shutil.move(basepath, backuppath) - shutil.move(tmpfile, basepath) - else: # if self.config['dryrun'] - os.remove(tmpfile) - else: # if not isfile(basepath) - result_flag = 2 - if not self.config['dryrun']: - if isfile(basepath): - os.remove(basepath) - shutil.move(tmpfile, basepath) - else: # if self.config['dryrun'] - os.remove(tmpfile) - result = tuple([basename, backupname, result_flag]) - return(result) + # Put the new contents of $file in a file in the same directory (needed + # to guarantee that an 'mv' to "$destdir/$file" works). + result = joinpath(self.config['destdir'], '%s.tmp' % path) + dirname = os.path.dirname(result) + if dirname and not isdir(dirname): + os.makedirs(dirname) + else: # if self.config['dryrun'] + # Put the new contents of $file in a file in a temporary directory + # (because the directory of "$file" might not exist). + tempdir = self.config['tempdir'] + result = joinpath(tempdir, '%s.tmp' % os.path.basename(path)) + dirname = os.path.dirname(result) + if not isdir(dirname): + os.makedirs(dirname) + if type(result) is bytes: + result = bytes.decode(ENCS['default']) + return(result) + + def setOriginal(self, original): + '''GLFileAssistant.setOriginal(original) + + Set the name of the original file which will be used.''' + if type(original) is bytes or type(original) is string: + if type(original) is bytes: + original = original.decode(ENCS['default']) + else: # if original has not bytes or string type + raise(TypeError( + 'original must be a string, not %s' % (type(original).__name__))) + self.original = original + + def setRewritten(self, rewritten): + '''GLFileAssistant.setRewritten(rewritten) + + Set the name of the rewritten file which will be used.''' + if type(rewritten) is bytes or type(rewritten) is string: + if type(rewritten) is bytes: + rewritten = rewritten.decode(ENCS['default']) + else: # if rewritten has not bytes or string type + raise(TypeError( + 'rewritten must be a string, not %s' % type(rewritten).__name__)) + self.rewritten = rewritten + def addFile(self, file): + '''GLFileAssistant.addFile(file) + + Add file to the list of added files.''' + if file not in self.added: + self.added += [file] + + def removeFile(self, file): + '''GLFileAssistant.removeFile(file) + + Remove file from the list of added files.''' + if file in self.added: + self.added.pop(file) + + def getFiles(self): + '''Return list of the added files.''' + return(list(self.added)) + + def add(self, lookedup, tmpflag, tmpfile): + '''GLFileAssistant.add(lookedup, tmpflag, tmpfile) + + This method copies a file from gnulib into the destination directory. + The destination is known to exist. If tmpflag is True, then lookedup file + is a temporary one.''' + 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: + 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)) \ + and not tmpflag and filecmp.cmp(lookedup, tmpfile): + constants.link_if_changed( + lookedup, joinpath(destdir, rewritten)) + else: # if any of these conditions is not met + try: # Try to move file + shutil.move(tmpfile, joinpath(destdir, rewritten)) + except Exception as error: + raise(GLError(17, original)) + else: # if self.config['dryrun'] + print('Copy file %s' % rewritten) + + def update(self, lookedup, tmpflag, tmpfile, already_present): + '''GLFileAssistant.update(lookedup, tmpflag, tmpfile, already_present) + + This method copies a file from gnulib into the destination directory. + The destination is known to exist. If tmpflag is True, then lookedup file + is a temporary one.''' + 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: + raise(TypeError('rewritten must be set before applying the method')) + if type(lookedup) is bytes or type(lookedup) is string: + if type(lookedup) is bytes: + lookedup = lookedup.decode(ENCS['default']) + else: # if lookedup has not bytes or string type + raise(TypeError('lookedup must be a string, not %s' % + type(lookedup).__name__)) + if type(already_present) is not bool: + raise(TypeError('already_present must be a bool, not %s' % + type(already_present).__name__)) + basename = rewritten + backupname = string('%s~' % basename) + basepath = joinpath(destdir, basename) + backuppath = joinpath(destdir, backupname) + if not filecmp.cmp(basepath, tmpfile): + if not self.config['dryrun']: + if already_present: + print('Updating file %s (backup in %s)' % + (basename, backupname)) + else: # if not already_present + message = 'Replacing file ' + message += '%s (non-gnulib code backed up in ' % basename + message += '%s) !!' % backupname + print(message) + if isfile(backuppath): + os.remove(backuppath) + try: # Try to replace the given file + 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)) \ + and not tmpflag and filecmp.cmp(lookedup, tmpfile): + constants.link_if_changed(lookedup, basepath) + else: # if any of these conditions is not met + try: # Try to move file + if os.path.exists(basepath): + os.remove(basepath) + shutil.copy(tmpfile, rewritten) + except Exception as error: + raise(GLError(17, original)) + else: # if self.config['dryrun'] + if already_present: + print('Update file %s (backup in %s)' % + (rewritten, backup)) + else: # if not already_present + print('Replace file %s (backup in %s)' % + (rewritten, backup)) + + def add_or_update(self, already_present): + '''GLFileAssistant.add_or_update(already_present) + + This method handles a file that ought to be present afterwards.''' + original = self.original + rewritten = self.rewritten + if original == None: + raise(TypeError('original must be set before applying the method')) + elif rewritten == None: + raise(TypeError('rewritten must be set before applying the method')) + if type(already_present) is not bool: + raise(TypeError('already_present must be a bool, not %s' % + type(already_present).__name__)) + xoriginal = original + if original.startswith('tests=lib/'): + xoriginal = constants.substart('tests=lib/', 'lib/', original) + lookedup, tmpflag = self.filesystem.lookup(xoriginal) + tmpfile = self.tmpfilename(rewritten) + sed_transform_lib_file = self.transformers.get('lib', '') + sed_transform_build_aux_file = self.transformers.get('aux', '') + sed_transform_main_lib_file = self.transformers.get('main', '') + sed_transform_testsrelated_lib_file = self.transformers.get( + 'tests', '') + try: # Try to copy lookedup file to tmpfile + shutil.copy(lookedup, tmpfile) + except Exception as error: + raise(GLError(15, lookedup)) + transformer = string() + if original.startswith('lib/'): + if sed_transform_main_lib_file: + transformer = sed_transform_main_lib_file + elif original.startswith('build-aux/'): + if sed_transform_build_aux_file: + transformer = sed_transform_build_aux_file + elif original.startswith('tests=lib/'): + if sed_transform_testsrelated_lib_file: + transformer = sed_transform_testsrelated_lib_file + if transformer: + args = ['sed', '-e', transformer] + stdin = codecs.open(lookedup, 'rb', 'UTF-8') + try: # Try to transform file + data = sp.check_output(args, stdin=stdin, shell=False) + data = data.decode("UTF-8") + except Exception as error: + raise(GLError(16, lookedup)) + with codecs.open(tmpfile, 'wb', 'UTF-8') as file: + file.write(data) + path = joinpath(self.config['destdir'], rewritten) + if isfile(path): + self.update(lookedup, tmpflag, tmpfile, already_present) + os.remove(tmpfile) + else: # if not isfile(path) + self.add(lookedup, tmpflag, tmpfile) + self.addFile(rewritten) + + def super_update(self, basename, tmpfile): + '''GLFileAssistant.super_update(basename, tmpfile) -> tuple + + Move tmpfile to destdir/basename path, making a backup of it. + Returns tuple, which contains basename, backupname and status. + 0: tmpfile is the same as destfile; + 1: tmpfile was used to update destfile; + 2: destfile was created, because it didn't exist.''' + backupname = '%s~' % basename + basepath = joinpath(self.config['destdir'], basename) + backuppath = joinpath(self.config['destdir'], backupname) + if isfile(basepath): + if filecmp.cmp(basepath, tmpfile): + result_flag = 0 + else: # if not filecmp.cmp(basepath, tmpfile) + result_flag = 1 + if not self.config['dryrun']: + if isfile(backuppath): + os.remove(backuppath) + shutil.move(basepath, backuppath) + shutil.move(tmpfile, basepath) + else: # if self.config['dryrun'] + os.remove(tmpfile) + else: # if not isfile(basepath) + result_flag = 2 + if not self.config['dryrun']: + if isfile(basepath): + os.remove(basepath) + shutil.move(tmpfile, basepath) + else: # if self.config['dryrun'] + os.remove(tmpfile) + result = tuple([basename, backupname, result_flag]) + return(result) diff --git a/pygnulib/GLImport.py b/pygnulib/GLImport.py index 2859a22005..0e85a9a50d 100644 --- a/pygnulib/GLImport.py +++ b/pygnulib/GLImport.py @@ -59,423 +59,428 @@ normpath = os.path.normpath # Define GLImport class #=============================================================================== class GLImport(object): - '''GLImport class is used to provide methods for --import, --add-import, - --remove-import and --update actions. This is a high-level class, so - developers may have to use lower-level classes to create their own - scripts. However, if user needs just to use power of gnulib-tool, this class - is a very good choice.''' - - def __init__(self, config, mode): - '''Create GLImport instance. - The first variable, mode, must be one of the values of the MODES dict - object, which is accessible from constants module. The second one, config, - must be a GLConfig object.''' - if type(config) is not GLConfig: - raise(TypeError('config must have GLConfig type, not %s' % \ - repr(config))) - if type(mode) is int and \ - MODES['import'] <= mode <= MODES['update']: - self.mode = mode - else: # if mode is not int or is not 0-3 - raise(TypeError('mode must be 0 <= mode <= 3, not %s' % \ - repr(mode))) - - # Initialize some values. - self.cache = GLConfig() - self.config = config.copy() - os.rmdir(self.cache['tempdir']) - - # Get cached auxdir and libtool from configure.ac/in. - self.cache.setAuxDir('.') - path = joinpath(self.config['destdir'], 'configure.ac') - if not isfile(path): - path = joinpath(self.config['destdir'], 'configure.in') - if not isfile(path): - raise(GLError(3, path)) - self.config.setAutoconfFile(path) - with codecs.open(path, 'rb', 'UTF-8') as file: - data = file.read() - pattern = compiler(r'^AC_CONFIG_AUX_DIR\((.*?)\)$', re.S | re.M) - match = pattern.findall(data) - if match: - result = cleaner(match)[0] - self.cache.setAuxDir(joinpath(result, self.config['destdir'])) - pattern = compiler(r'A[CM]_PROG_LIBTOOL', re.S | re.M) - guessed_libtool = bool(pattern.findall(data)) - if self.config['auxdir'] == None: - self.config.setAuxDir(self.cache['auxdir']) - - # Guess autoconf version. - pattern = compiler('.*AC_PREREQ\((.*?)\)', re.S | re.M) - versions = cleaner(pattern.findall(data)) - if versions: - version = sorted(set([float(version) for version in versions]))[-1] - self.config.setAutoconfVersion(version) - if version < 2.59: - raise(GLError(4, version)) - - # Get other cached variables. - path = joinpath(self.config['m4base'], 'gnulib-cache.m4') - if isfile(joinpath(self.config['m4base'], 'gnulib-cache.m4')): - with codecs.open(path, 'rb', 'UTF-8') as file: - data = file.read() - - # Create regex object and keys. - pattern = compiler('^(gl_.*?)\\((.*?)\\)$', re.S | re.M) - keys = \ - [ - 'gl_LOCAL_DIR', 'gl_MODULES', 'gl_AVOID', 'gl_SOURCE_BASE', - 'gl_M4_BASE', 'gl_PO_BASE', 'gl_DOC_BASE', 'gl_TESTS_BASE', - 'gl_MAKEFILE_NAME', 'gl_MACRO_PREFIX', 'gl_PO_DOMAIN', - 'gl_WITNESS_C_MACRO', 'gl_VC_FILES', 'gl_LIB', - ] - - # Find bool values. - if 'gl_LGPL(' in data: - keys.append('gl_LGPL') - self.cache.setLGPL(True) - if 'gl_LIBTOOL' in data: - self.cache.enableLibtool() - data = data.replace('gl_LIBTOOL', '') - if 'gl_CONDITIONAL_DEPENDENCIES' in data: - self.cache.enableCondDeps() - data = data.replace('gl_CONDITIONAL_DEPENDENCIES', '') - if 'gl_VC_FILES' in data: - self.cache.enableVCFiles() - data = data.replace('gl_VC_FILES', '') - if 'gl_WITH_TESTS' in data: - self.cache.enableTestFlag(TESTS['tests']) - data = data.replace('gl_WITH_TESTS', '') - if 'gl_WITH_OBSOLETE' in data: - self.cache.enableTestFlag(TESTS['obsolete']) - data = data.replace('gl_WITH_OBSOLETE', '') - if 'gl_WITH_CXX_TESTS' in data: - self.cache.enableTestFlag(TESTS['c++-test']) - data = data.replace('gl_WITH_CXX_TESTS', '') - if 'gl_WITH_LONGRUNNING_TESTS' in data: - self.cache.enableTestFlag(TESTS['longrunning-test']) - data = data.replace('gl_WITH_LONGRUNNING_TESTS', '') - if 'gl_WITH_PRIVILEGED_TESTS' in data: - self.cache.enableTestFlag(TESTS['privileged-test']) - data = data.replace('gl_WITH_PRIVILEGED_TESTS', '') - if 'gl_WITH_UNPORTABLE_TESTS' in data: - self.cache.enableTestFlag(TESTS['unportable-test']) - data = data.replace('gl_WITH_UNPORTABLE_TESTS', '') - if 'gl_WITH_ALL_TESTS' in data: - self.cache.enableTestFlag(TESTS['all-test']) - data = data.replace('gl_WITH_ALL_TESTS', '') - # Find string values - result = dict(pattern.findall(data)) - values = cleaner([result.get(key, '') for key in keys]) - tempdict = dict(zip(keys, values)) - if 'gl_LGPL' in tempdict: - lgpl = cleaner(tempdict['gl_LGPL']) - if lgpl.isdecimal(): - self.cache.setLGPL(int(self.cache['lgpl'])) - else: # if 'gl_LGPL' not in tempdict - self.cache.setLGPL(False) - if tempdict['gl_LIB']: - self.cache.setLibName(cleaner(tempdict['gl_LIB'])) - if tempdict['gl_LOCAL_DIR']: - self.cache.setLocalDir(cleaner(tempdict['gl_LOCAL_DIR'])) - if tempdict['gl_MODULES']: - self.cache.setModules(cleaner(tempdict['gl_MODULES'].split())) - if tempdict['gl_AVOID']: - self.cache.setAvoids(cleaner(tempdict['gl_AVOID'].split())) - if tempdict['gl_SOURCE_BASE']: - self.cache.setSourceBase(cleaner(tempdict['gl_SOURCE_BASE'])) - if tempdict['gl_M4_BASE']: - self.cache.setM4Base(cleaner(tempdict['gl_M4_BASE'])) - if tempdict['gl_PO_BASE']: - self.cache.setPoBase(cleaner(tempdict['gl_PO_BASE'])) - if tempdict['gl_DOC_BASE']: - self.cache.setDocBase(cleaner(tempdict['gl_DOC_BASE'])) - if tempdict['gl_TESTS_BASE']: - self.cache.setTestsBase(cleaner(tempdict['gl_TESTS_BASE'])) - if tempdict['gl_MAKEFILE_NAME']: - self.cache.setMakefile(cleaner(tempdict['gl_MAKEFILE_NAME'])) - if tempdict['gl_MACRO_PREFIX']: - self.cache.setMacroPrefix(cleaner(tempdict['gl_MACRO_PREFIX'])) - if tempdict['gl_PO_DOMAIN']: - self.cache.setPoDomain(cleaner(tempdict['gl_PO_DOMAIN'])) - if tempdict['gl_WITNESS_C_MACRO']: - self.cache.setWitnessCMacro(cleaner(tempdict['gl_WITNESS_C_MACRO'])) - - # Get cached filelist from gnulib-comp.m4. - destdir, m4base = self.config.getDestDir(), self.config.getM4Base() - path = joinpath(destdir, m4base, 'gnulib-comp.m4') - if isfile(path): + '''GLImport class is used to provide methods for --import, --add-import, + --remove-import and --update actions. This is a high-level class, so + developers may have to use lower-level classes to create their own + scripts. However, if user needs just to use power of gnulib-tool, this class + is a very good choice.''' + + def __init__(self, config, mode): + '''Create GLImport instance. + The first variable, mode, must be one of the values of the MODES dict + object, which is accessible from constants module. The second one, config, + must be a GLConfig object.''' + if type(config) is not GLConfig: + raise(TypeError('config must have GLConfig type, not %s' % + repr(config))) + if type(mode) is int and \ + MODES['import'] <= mode <= MODES['update']: + self.mode = mode + else: # if mode is not int or is not 0-3 + raise(TypeError('mode must be 0 <= mode <= 3, not %s' % + repr(mode))) + + # Initialize some values. + self.cache = GLConfig() + self.config = config.copy() + os.rmdir(self.cache['tempdir']) + + # Get cached auxdir and libtool from configure.ac/in. + self.cache.setAuxDir('.') + path = joinpath(self.config['destdir'], 'configure.ac') + if not isfile(path): + path = joinpath(self.config['destdir'], 'configure.in') + if not isfile(path): + raise(GLError(3, path)) + self.config.setAutoconfFile(path) with codecs.open(path, 'rb', 'UTF-8') as file: - data = file.read() - regex = 'AC_DEFUN\\(\\[%s_FILE_LIST\\], \\[(.*?)\\]\\)' % \ - self.cache['macro_prefix'] - pattern = compiler(regex, re.S | re.M) - self.cache.setFiles(pattern.findall(data)[-1].strip().split()) - - # The self.config['localdir'] defaults to the cached one. Recall that the - # cached one is relative to $destdir, whereas the one we use is relative - # to . or absolute. - if not self.config['localdir']: - if self.cache['localdir']: - if isabs(self.config['destdir']): - localdir = joinpath(self.config['destdir'], self.cache['localdir']) - else: # if not isabs(self.config['destdir']) - if isabs(self.cache['localdir']): - localdir = joinpath(self.config['destdir'], self.cache['localdir']) - else: # if not isabs(self.cache['localdir']) - # NOTE: I NEED TO IMPLEMENT RELATIVE_CONCAT - localdir = os.path.relpath(joinpath(self.config['destdir'], - self.cache['localdir'])) - self.config.setLocalDir(localdir) - - if self.mode != MODES['import']: - if self.cache['m4base'] and \ - (self.config['m4base'] != self.cache['m4base']): - raise(GLError(5, m4base)) - - # Perform actions with modules. In --add-import, append each given module - # to the list of cached modules; in --remove-import, remove each given - # module from the list of cached modules; in --update, simply set - # self.config['modules'] to its cached version. - new, old = self.config.getModules(), self.cache.getModules() - if self.mode == MODES['add-import']: - modules = sorted(set(new +old)) - elif self.mode == MODES['remove-import']: - modules = [module for module in old if module in new] - elif self.mode == MODES['update']: - modules = self.cache.getModules() - - # If user tries to apply conddeps and testflag['tests'] together. - if self.config['tests'] and self.config['conddeps']: - raise(GLError(10, None)) - - # Update configuration dictionary. - self.config.update(self.cache) - for key in config.keys(): - value = config[key] - if not config.isdefault(key, value): - self.config.update_key(config, key) - self.config.setModules(modules) - - # Check if conddeps is enabled together with inctests. - inctests = self.config.checkTestFlag(TESTS['tests']) - if self.config['conddeps'] and inctests: - raise(GLError(10, None)) - - # Define GLImport attributes. - self.emiter = GLEmiter(self.config) - self.filesystem = GLFileSystem(self.config) - self.modulesystem = GLModuleSystem(self.config) - self.moduletable = GLModuleTable(self.config, list()) - self.makefiletable = GLMakefileTable(self.config) - - def __repr__(self): - '''x.__repr__ <==> repr(x)''' - result = '' % hex(id(self)) - return(result) - - def rewrite_old_files(self, files): - '''GLImport.rewrite_old_files(files) -> list - - Replace auxdir, docbase, sourcebase, m4base and testsbase from default - to their version from cached config.''' - if type(files) is not list: - raise(TypeError( - 'files argument must has list type, not %s' % type(files).__name__)) - files = \ - [ # Begin to convert bytes to string - file.decode(ENCS['default']) \ - if type(file) is bytes else file \ - for file in files - ] # Finish to convert bytes to string - for file in files: - if type(file) is not string: - raise(TypeError('each file must be a string instance')) - files = sorted(set(files)) - files = ['%s%s' % (file, os.path.sep) for file in files] - auxdir = self.cache['auxdir'] - docbase = self.cache['docbase'] - sourcebase = self.cache['sourcebase'] - m4base = self.cache['m4base'] - testsbase = self.cache['testsbase'] - result = list() - for file in files: - if file.startswith('build-aux/'): - path = constants.substart('build-aux/', '%s/' % auxdir, file) - elif file.startswith('doc/'): - path = constants.substart('doc/', '%s/' % docbase, file) - elif file.startswith('lib/'): - path = constants.substart('lib/', '%s/' % sourcebase, file) - elif file.startswith('m4/'): - path = constants.substart('m4/', '%s/' % m4base, file) - elif file.startswith('tests/'): - path = constants.substart('tests/', '%s/' % testsbase, file) - elif file.startswith('tests=lib/'): - path = constants.substart('tests=lib/', '%s/' % testsbase, file) - elif file.startswith('top/'): - path = constants.substart('top/', '', file) - else: # file is not a special file - path = file - result += [os.path.normpath(path)] - result = sorted(set(result)) - return(list(result)) - - def rewrite_new_files(self, files): - '''GLImport.rewrite_new_files(files) - - Replace auxdir, docbase, sourcebase, m4base and testsbase from default - to their version from config.''' - if type(files) is not list: - raise(TypeError( - 'files argument must has list type, not %s' % type(files).__name__)) - files = \ - [ # Begin to convert bytes to string - file.decode(ENCS['default']) \ - if type(file) is bytes else file \ - for file in files - ] # Finish to convert bytes to string - for file in files: - if type(file) is not string: - raise(TypeError('each file must be a string instance')) - files = sorted(set(files)) - auxdir = self.config['auxdir'] - docbase = self.config['docbase'] - sourcebase = self.config['sourcebase'] - m4base = self.config['m4base'] - testsbase = self.config['testsbase'] - result = list() - for file in files: - if file.startswith('build-aux/'): - path = constants.substart('build-aux/', '%s/' % auxdir, file) - elif file.startswith('doc/'): - path = constants.substart('doc/', '%s/' % docbase, file) - elif file.startswith('lib/'): - path = constants.substart('lib/', '%s/' % sourcebase, file) - elif file.startswith('m4/'): - path = constants.substart('m4/', '%s/' % m4base, file) - elif file.startswith('tests/'): - path = constants.substart('tests/', '%s/' % testsbase, file) - elif file.startswith('tests=lib/'): - path = constants.substart('tests=lib/', '%s/' % testsbase, file) - elif file.startswith('top/'): - path = constants.substart('top/', '', file) - else: # file is not a special file - path = file - result += [os.path.normpath(path)] - result = sorted(set(result)) - return(list(result)) - - def actioncmd(self): - '''Return command-line invocation comment.''' - modules = self.config.getModules() - avoids = self.config.getAvoids() - destdir = self.config.getDestDir() - localdir = self.config.getLocalDir() - auxdir = self.config.getAuxDir() - sourcebase = self.config.getSourceBase() - m4base = self.config.getM4Base() - docbase = self.config.getDocBase() - pobase = self.config.getPoBase() - testsbase = self.config.getTestsBase() - testflags = self.config.getTestFlags() - conddeps = self.config.checkCondDeps() - libname = self.config.getLibName() - lgpl = self.config.getLGPL() - makefile = self.config.getMakefile() - libtool = self.config.checkLibtool() - macro_prefix = self.config.getMacroPrefix() - witness_c_macro = self.config.getWitnessCMacro() - podomain = self.config.getPoDomain() - vc_files = self.config.checkVCFiles() - verbose = self.config.getVerbosity() - - # Create command-line invocation comment. - actioncmd = 'gnulib-tool --import' - actioncmd += ' --dir=%s' % destdir - if localdir: - actioncmd += ' --local-dir=%s' % localdir - actioncmd += ' --lib=%s' % libname - actioncmd += ' --source-base=%s' % sourcebase - actioncmd += ' --m4-base=%s' % m4base - if pobase: - actioncmd += ' --po-base=%s' % pobase - actioncmd += ' --doc-base=%s' % docbase - actioncmd += ' --tests-base=%s' % testsbase - actioncmd += ' --aux-dir=%s' % auxdir - if self.config.checkTestFlag(TESTS['tests']): - actioncmd += ' --with-tests' - if self.config.checkTestFlag(TESTS['obsolete']): - actioncmd += ' --with-obsolete' - if self.config.checkTestFlag(TESTS['c++-test']): - actioncmd += ' --with-c++-tests' - if self.config.checkTestFlag(TESTS['longrunning-test']): - actioncmd += ' --with-longrunning-tests' - if self.config.checkTestFlag(TESTS['privileged-test']): - actioncmd += ' --with-privileged-test' - if self.config.checkTestFlag(TESTS['unportable-test']): - actioncmd += ' --with-unportable-tests' - if self.config.checkTestFlag(TESTS['all-test']): - actioncmd += ' --with-all-tests' - for module in avoids: - actioncmd += ' --avoid=%s' % module - if lgpl: - if lgpl == True: - actioncmd += ' --lgpl' - else: # if lgpl != True - actioncmd += ' --lgpl=%s' % lgpl - if makefile: - actioncmd += ' --makefile-name=%s' % makefile - if conddeps: - actioncmd += ' --conditional-dependencies' - else: # if not conddeps - actioncmd += ' --no-conditional-dependencies' - if libtool: - actioncmd += ' --libtool' - else: # if not libtool - actioncmd += ' --no-libtool' - actioncmd += ' --macro-prefix=%s' % macro_prefix - if podomain: - actioncmd = ' --podomain=%s' % podomain - if witness_c_macro: - actioncmd += ' --witness_c_macro=%s' % witness_c_macro - if vc_files == True: - actioncmd += ' --vc-files' - elif vc_files == False: - actioncmd += ' --no-vc-files' - actioncmd += ' ' # Add a space - actioncmd += ' '.join(modules) - return(actioncmd) - - def gnulib_cache(self): - '''GLImport.gnulib_cache() -> string - - Emit the contents of generated $m4base/gnulib-cache.m4 file. - GLConfig: destdir, localdir, tests, sourcebase, m4base, pobase, docbase, - testsbase, conddeps, libtool, macro_prefix, podomain, vc_files.''' - emit = string() - moduletable = self.moduletable - actioncmd = self.actioncmd() - destdir = self.config['destdir'] - localdir = self.config['localdir'] - testflags = list(self.config['testflags']) - sourcebase = self.config['sourcebase'] - m4base = self.config['m4base'] - pobase = self.config['pobase'] - docbase = self.config['docbase'] - testsbase = self.config['testsbase'] - lgpl = self.config['lgpl'] - libname = self.config['libname'] - makefile = self.config['makefile'] - conddeps = self.config['conddeps'] - libtool = self.config['libtool'] - macro_prefix = self.config['macro_prefix'] - podomain = self.config['podomain'] - witness_c_macro = self.config['witness_c_macro'] - vc_files = self.config['vc_files'] - modules = [str(module) for module in moduletable['base']] - avoids = [str(avoid) for avoid in moduletable['avoids']] - emit += self.emiter.copyright_notice() - emit += '''# + data = file.read() + pattern = compiler(r'^AC_CONFIG_AUX_DIR\((.*?)\)$', re.S | re.M) + match = pattern.findall(data) + if match: + result = cleaner(match)[0] + self.cache.setAuxDir(joinpath(result, self.config['destdir'])) + pattern = compiler(r'A[CM]_PROG_LIBTOOL', re.S | re.M) + guessed_libtool = bool(pattern.findall(data)) + if self.config['auxdir'] == None: + self.config.setAuxDir(self.cache['auxdir']) + + # Guess autoconf version. + pattern = compiler('.*AC_PREREQ\((.*?)\)', re.S | re.M) + versions = cleaner(pattern.findall(data)) + if versions: + version = sorted(set([float(version) for version in versions]))[-1] + self.config.setAutoconfVersion(version) + if version < 2.59: + raise(GLError(4, version)) + + # Get other cached variables. + path = joinpath(self.config['m4base'], 'gnulib-cache.m4') + if isfile(joinpath(self.config['m4base'], 'gnulib-cache.m4')): + with codecs.open(path, 'rb', 'UTF-8') as file: + data = file.read() + + # Create regex object and keys. + pattern = compiler('^(gl_.*?)\\((.*?)\\)$', re.S | re.M) + keys = \ + [ + 'gl_LOCAL_DIR', 'gl_MODULES', 'gl_AVOID', 'gl_SOURCE_BASE', + 'gl_M4_BASE', 'gl_PO_BASE', 'gl_DOC_BASE', 'gl_TESTS_BASE', + 'gl_MAKEFILE_NAME', 'gl_MACRO_PREFIX', 'gl_PO_DOMAIN', + 'gl_WITNESS_C_MACRO', 'gl_VC_FILES', 'gl_LIB', + ] + + # Find bool values. + if 'gl_LGPL(' in data: + keys.append('gl_LGPL') + self.cache.setLGPL(True) + if 'gl_LIBTOOL' in data: + self.cache.enableLibtool() + data = data.replace('gl_LIBTOOL', '') + if 'gl_CONDITIONAL_DEPENDENCIES' in data: + self.cache.enableCondDeps() + data = data.replace('gl_CONDITIONAL_DEPENDENCIES', '') + if 'gl_VC_FILES' in data: + self.cache.enableVCFiles() + data = data.replace('gl_VC_FILES', '') + if 'gl_WITH_TESTS' in data: + self.cache.enableTestFlag(TESTS['tests']) + data = data.replace('gl_WITH_TESTS', '') + if 'gl_WITH_OBSOLETE' in data: + self.cache.enableTestFlag(TESTS['obsolete']) + data = data.replace('gl_WITH_OBSOLETE', '') + if 'gl_WITH_CXX_TESTS' in data: + self.cache.enableTestFlag(TESTS['c++-test']) + data = data.replace('gl_WITH_CXX_TESTS', '') + if 'gl_WITH_LONGRUNNING_TESTS' in data: + self.cache.enableTestFlag(TESTS['longrunning-test']) + data = data.replace('gl_WITH_LONGRUNNING_TESTS', '') + if 'gl_WITH_PRIVILEGED_TESTS' in data: + self.cache.enableTestFlag(TESTS['privileged-test']) + data = data.replace('gl_WITH_PRIVILEGED_TESTS', '') + if 'gl_WITH_UNPORTABLE_TESTS' in data: + self.cache.enableTestFlag(TESTS['unportable-test']) + data = data.replace('gl_WITH_UNPORTABLE_TESTS', '') + if 'gl_WITH_ALL_TESTS' in data: + self.cache.enableTestFlag(TESTS['all-test']) + data = data.replace('gl_WITH_ALL_TESTS', '') + # Find string values + result = dict(pattern.findall(data)) + values = cleaner([result.get(key, '') for key in keys]) + tempdict = dict(zip(keys, values)) + if 'gl_LGPL' in tempdict: + lgpl = cleaner(tempdict['gl_LGPL']) + if lgpl.isdecimal(): + self.cache.setLGPL(int(self.cache['lgpl'])) + else: # if 'gl_LGPL' not in tempdict + self.cache.setLGPL(False) + if tempdict['gl_LIB']: + self.cache.setLibName(cleaner(tempdict['gl_LIB'])) + if tempdict['gl_LOCAL_DIR']: + self.cache.setLocalDir(cleaner(tempdict['gl_LOCAL_DIR'])) + if tempdict['gl_MODULES']: + self.cache.setModules(cleaner(tempdict['gl_MODULES'].split())) + if tempdict['gl_AVOID']: + self.cache.setAvoids(cleaner(tempdict['gl_AVOID'].split())) + if tempdict['gl_SOURCE_BASE']: + self.cache.setSourceBase(cleaner(tempdict['gl_SOURCE_BASE'])) + if tempdict['gl_M4_BASE']: + self.cache.setM4Base(cleaner(tempdict['gl_M4_BASE'])) + if tempdict['gl_PO_BASE']: + self.cache.setPoBase(cleaner(tempdict['gl_PO_BASE'])) + if tempdict['gl_DOC_BASE']: + self.cache.setDocBase(cleaner(tempdict['gl_DOC_BASE'])) + if tempdict['gl_TESTS_BASE']: + self.cache.setTestsBase(cleaner(tempdict['gl_TESTS_BASE'])) + if tempdict['gl_MAKEFILE_NAME']: + self.cache.setMakefile(cleaner(tempdict['gl_MAKEFILE_NAME'])) + if tempdict['gl_MACRO_PREFIX']: + self.cache.setMacroPrefix(cleaner(tempdict['gl_MACRO_PREFIX'])) + if tempdict['gl_PO_DOMAIN']: + self.cache.setPoDomain(cleaner(tempdict['gl_PO_DOMAIN'])) + if tempdict['gl_WITNESS_C_MACRO']: + self.cache.setWitnessCMacro( + cleaner(tempdict['gl_WITNESS_C_MACRO'])) + + # Get cached filelist from gnulib-comp.m4. + destdir, m4base = self.config.getDestDir(), self.config.getM4Base() + path = joinpath(destdir, m4base, 'gnulib-comp.m4') + if isfile(path): + with codecs.open(path, 'rb', 'UTF-8') as file: + data = file.read() + regex = 'AC_DEFUN\\(\\[%s_FILE_LIST\\], \\[(.*?)\\]\\)' % \ + self.cache['macro_prefix'] + pattern = compiler(regex, re.S | re.M) + self.cache.setFiles(pattern.findall(data)[-1].strip().split()) + + # The self.config['localdir'] defaults to the cached one. Recall that the + # cached one is relative to $destdir, whereas the one we use is relative + # to . or absolute. + if not self.config['localdir']: + if self.cache['localdir']: + if isabs(self.config['destdir']): + localdir = joinpath( + self.config['destdir'], self.cache['localdir']) + else: # if not isabs(self.config['destdir']) + if isabs(self.cache['localdir']): + localdir = joinpath( + self.config['destdir'], self.cache['localdir']) + else: # if not isabs(self.cache['localdir']) + # NOTE: I NEED TO IMPLEMENT RELATIVE_CONCAT + localdir = os.path.relpath(joinpath(self.config['destdir'], + self.cache['localdir'])) + self.config.setLocalDir(localdir) + + if self.mode != MODES['import']: + if self.cache['m4base'] and \ + (self.config['m4base'] != self.cache['m4base']): + raise(GLError(5, m4base)) + + # Perform actions with modules. In --add-import, append each given module + # to the list of cached modules; in --remove-import, remove each given + # module from the list of cached modules; in --update, simply set + # self.config['modules'] to its cached version. + new, old = self.config.getModules(), self.cache.getModules() + if self.mode == MODES['add-import']: + modules = sorted(set(new + old)) + elif self.mode == MODES['remove-import']: + modules = [module for module in old if module in new] + elif self.mode == MODES['update']: + modules = self.cache.getModules() + + # If user tries to apply conddeps and testflag['tests'] together. + if self.config['tests'] and self.config['conddeps']: + raise(GLError(10, None)) + + # Update configuration dictionary. + self.config.update(self.cache) + for key in config.keys(): + value = config[key] + if not config.isdefault(key, value): + self.config.update_key(config, key) + self.config.setModules(modules) + + # Check if conddeps is enabled together with inctests. + inctests = self.config.checkTestFlag(TESTS['tests']) + if self.config['conddeps'] and inctests: + raise(GLError(10, None)) + + # Define GLImport attributes. + self.emiter = GLEmiter(self.config) + self.filesystem = GLFileSystem(self.config) + self.modulesystem = GLModuleSystem(self.config) + self.moduletable = GLModuleTable(self.config, list()) + self.makefiletable = GLMakefileTable(self.config) + + def __repr__(self): + '''x.__repr__ <==> repr(x)''' + result = '' % hex(id(self)) + return(result) + + def rewrite_old_files(self, files): + '''GLImport.rewrite_old_files(files) -> list + + Replace auxdir, docbase, sourcebase, m4base and testsbase from default + to their version from cached config.''' + if type(files) is not list: + raise(TypeError( + 'files argument must has list type, not %s' % type(files).__name__)) + files = \ + [ # Begin to convert bytes to string + file.decode(ENCS['default']) \ + if type(file) is bytes else file \ + for file in files + ] # Finish to convert bytes to string + for file in files: + if type(file) is not string: + raise(TypeError('each file must be a string instance')) + files = sorted(set(files)) + files = ['%s%s' % (file, os.path.sep) for file in files] + auxdir = self.cache['auxdir'] + docbase = self.cache['docbase'] + sourcebase = self.cache['sourcebase'] + m4base = self.cache['m4base'] + testsbase = self.cache['testsbase'] + result = list() + for file in files: + if file.startswith('build-aux/'): + path = constants.substart('build-aux/', '%s/' % auxdir, file) + elif file.startswith('doc/'): + path = constants.substart('doc/', '%s/' % docbase, file) + elif file.startswith('lib/'): + path = constants.substart('lib/', '%s/' % sourcebase, file) + elif file.startswith('m4/'): + path = constants.substart('m4/', '%s/' % m4base, file) + elif file.startswith('tests/'): + path = constants.substart('tests/', '%s/' % testsbase, file) + elif file.startswith('tests=lib/'): + path = constants.substart( + 'tests=lib/', '%s/' % testsbase, file) + elif file.startswith('top/'): + path = constants.substart('top/', '', file) + else: # file is not a special file + path = file + result += [os.path.normpath(path)] + result = sorted(set(result)) + return(list(result)) + + def rewrite_new_files(self, files): + '''GLImport.rewrite_new_files(files) + + Replace auxdir, docbase, sourcebase, m4base and testsbase from default + to their version from config.''' + if type(files) is not list: + raise(TypeError( + 'files argument must has list type, not %s' % type(files).__name__)) + files = \ + [ # Begin to convert bytes to string + file.decode(ENCS['default']) \ + if type(file) is bytes else file \ + for file in files + ] # Finish to convert bytes to string + for file in files: + if type(file) is not string: + raise(TypeError('each file must be a string instance')) + files = sorted(set(files)) + auxdir = self.config['auxdir'] + docbase = self.config['docbase'] + sourcebase = self.config['sourcebase'] + m4base = self.config['m4base'] + testsbase = self.config['testsbase'] + result = list() + for file in files: + if file.startswith('build-aux/'): + path = constants.substart('build-aux/', '%s/' % auxdir, file) + elif file.startswith('doc/'): + path = constants.substart('doc/', '%s/' % docbase, file) + elif file.startswith('lib/'): + path = constants.substart('lib/', '%s/' % sourcebase, file) + elif file.startswith('m4/'): + path = constants.substart('m4/', '%s/' % m4base, file) + elif file.startswith('tests/'): + path = constants.substart('tests/', '%s/' % testsbase, file) + elif file.startswith('tests=lib/'): + path = constants.substart( + 'tests=lib/', '%s/' % testsbase, file) + elif file.startswith('top/'): + path = constants.substart('top/', '', file) + else: # file is not a special file + path = file + result += [os.path.normpath(path)] + result = sorted(set(result)) + return(list(result)) + + def actioncmd(self): + '''Return command-line invocation comment.''' + modules = self.config.getModules() + avoids = self.config.getAvoids() + destdir = self.config.getDestDir() + localdir = self.config.getLocalDir() + auxdir = self.config.getAuxDir() + sourcebase = self.config.getSourceBase() + m4base = self.config.getM4Base() + docbase = self.config.getDocBase() + pobase = self.config.getPoBase() + testsbase = self.config.getTestsBase() + testflags = self.config.getTestFlags() + conddeps = self.config.checkCondDeps() + libname = self.config.getLibName() + lgpl = self.config.getLGPL() + makefile = self.config.getMakefile() + libtool = self.config.checkLibtool() + macro_prefix = self.config.getMacroPrefix() + witness_c_macro = self.config.getWitnessCMacro() + podomain = self.config.getPoDomain() + vc_files = self.config.checkVCFiles() + verbose = self.config.getVerbosity() + + # Create command-line invocation comment. + actioncmd = 'gnulib-tool --import' + actioncmd += ' --dir=%s' % destdir + if localdir: + actioncmd += ' --local-dir=%s' % localdir + actioncmd += ' --lib=%s' % libname + actioncmd += ' --source-base=%s' % sourcebase + actioncmd += ' --m4-base=%s' % m4base + if pobase: + actioncmd += ' --po-base=%s' % pobase + actioncmd += ' --doc-base=%s' % docbase + actioncmd += ' --tests-base=%s' % testsbase + actioncmd += ' --aux-dir=%s' % auxdir + if self.config.checkTestFlag(TESTS['tests']): + actioncmd += ' --with-tests' + if self.config.checkTestFlag(TESTS['obsolete']): + actioncmd += ' --with-obsolete' + if self.config.checkTestFlag(TESTS['c++-test']): + actioncmd += ' --with-c++-tests' + if self.config.checkTestFlag(TESTS['longrunning-test']): + actioncmd += ' --with-longrunning-tests' + if self.config.checkTestFlag(TESTS['privileged-test']): + actioncmd += ' --with-privileged-test' + if self.config.checkTestFlag(TESTS['unportable-test']): + actioncmd += ' --with-unportable-tests' + if self.config.checkTestFlag(TESTS['all-test']): + actioncmd += ' --with-all-tests' + for module in avoids: + actioncmd += ' --avoid=%s' % module + if lgpl: + if lgpl == True: + actioncmd += ' --lgpl' + else: # if lgpl != True + actioncmd += ' --lgpl=%s' % lgpl + if makefile: + actioncmd += ' --makefile-name=%s' % makefile + if conddeps: + actioncmd += ' --conditional-dependencies' + else: # if not conddeps + actioncmd += ' --no-conditional-dependencies' + if libtool: + actioncmd += ' --libtool' + else: # if not libtool + actioncmd += ' --no-libtool' + actioncmd += ' --macro-prefix=%s' % macro_prefix + if podomain: + actioncmd = ' --podomain=%s' % podomain + if witness_c_macro: + actioncmd += ' --witness_c_macro=%s' % witness_c_macro + if vc_files == True: + actioncmd += ' --vc-files' + elif vc_files == False: + actioncmd += ' --no-vc-files' + actioncmd += ' ' # Add a space + actioncmd += ' '.join(modules) + return(actioncmd) + + def gnulib_cache(self): + '''GLImport.gnulib_cache() -> string + + Emit the contents of generated $m4base/gnulib-cache.m4 file. + GLConfig: destdir, localdir, tests, sourcebase, m4base, pobase, docbase, + testsbase, conddeps, libtool, macro_prefix, podomain, vc_files.''' + emit = string() + moduletable = self.moduletable + actioncmd = self.actioncmd() + destdir = self.config['destdir'] + localdir = self.config['localdir'] + testflags = list(self.config['testflags']) + sourcebase = self.config['sourcebase'] + m4base = self.config['m4base'] + pobase = self.config['pobase'] + docbase = self.config['docbase'] + testsbase = self.config['testsbase'] + lgpl = self.config['lgpl'] + libname = self.config['libname'] + makefile = self.config['makefile'] + conddeps = self.config['conddeps'] + libtool = self.config['libtool'] + macro_prefix = self.config['macro_prefix'] + podomain = self.config['podomain'] + witness_c_macro = self.config['witness_c_macro'] + vc_files = self.config['vc_files'] + modules = [str(module) for module in moduletable['base']] + avoids = [str(avoid) for avoid in moduletable['avoids']] + emit += self.emiter.copyright_notice() + emit += '''# # This file represents the specification of how gnulib-tool is used. # It acts as a cache: It is written and read by gnulib-tool. # In projects that use version control, this file is meant to be put under @@ -487,86 +492,86 @@ class GLImport(object): # Specification in the form of a few \ gnulib-tool.m4 macro invocations:\n''' % actioncmd - if not localdir or localdir.startswith('/'): - relative_localdir = localdir - else: # if localdir or not localdir.startswith('/') - relative_localdir = constants.relativize(destdir, localdir) - emit += 'gl_LOCAL_DIR([%s])\n' % relative_localdir - emit += 'gl_MODULES([\n' - emit += ' %s\n' % '\n '.join(modules) - emit += '])\n' - if self.config.checkTestFlag(TESTS['obsolete']): - emit += 'gl_WITH_OBSOLETE\n' - if self.config.checkTestFlag(TESTS['cxx-tests']): - emit += 'gl_WITH_CXX_TESTS\n' - if self.config.checkTestFlag(TESTS['privileged-tests']): - emit += 'gl_WITH_PRIVILEGED_TESTS\n' - if self.config.checkTestFlag(TESTS['unportable-tests']): - emit += 'gl_WITH_UNPORTABLE_TESTS\n' - if self.config.checkTestFlag(TESTS['all-tests']): - emit += 'gl_WITH_ALL_TESTS\n' - emit += 'gl_AVOID([%s])\n' % ' '.join(avoids) - emit += 'gl_SOURCE_BASE([%s])\n' % sourcebase - emit += 'gl_M4_BASE([%s])\n' % m4base - emit += 'gl_PO_BASE([%s])\n' % pobase - emit += 'gl_DOC_BASE([%s])\n' % docbase - emit += 'gl_TESTS_BASE([%s])\n' % testsbase - if self.config.checkTestFlag(TESTS['tests']): - emit += 'gl_WITH_TESTS\n' - emit += 'gl_LIB([%s])\n' % libname - if lgpl != False: - if lgpl == True: - emit += 'gl_LGPL\n' - else: # if lgpl != True - emit += 'gl_LGPL([%d])\n' % lgpl - emit += 'gl_MAKEFILE_NAME([%s])\n' % makefile - if conddeps: - emit += 'gl_CONDITIONAL_DEPENDENCIES\n' - if libtool: - emit += 'gl_LIBTOOL\n' - emit += 'gl_MACRO_PREFIX([%s])\n' % macro_prefix - emit += 'gl_PO_DOMAIN([%s])\n' % podomain - emit += 'gl_WITNESS_C_DOMAIN([%s])\n' % witness_c_macro - if vc_files: - emit += 'gl_VC_FILES([%s])\n' % vc_files - if type(emit) is bytes: - emit = emit.decode(ENCS['default']) - return(constants.nlconvert(emit)) - - def gnulib_comp(self, files): - '''GLImport.gnulib_comp(files) -> string - - Emit the contents of generated $m4base/gnulib-comp.m4 file. - GLConfig: destdir, localdir, tests, sourcebase, m4base, pobase, docbase, - testsbase, conddeps, libtool, macro_prefix, podomain, vc_files.''' - emit = string() - assistant = self.assistant - moduletable = self.moduletable - destdir = self.config['destdir'] - localdir = self.config['localdir'] - auxdir = self.config['auxdir'] - testflags = list(self.config['testflags']) - sourcebase = self.config['sourcebase'] - m4base = self.config['m4base'] - pobase = self.config['pobase'] - docbase = self.config['docbase'] - testsbase = self.config['testsbase'] - lgpl = self.config['lgpl'] - libname = self.config['libname'] - makefile = self.config['makefile'] - conddeps = self.config['conddeps'] - libtool = self.config['libtool'] - macro_prefix = self.config['macro_prefix'] - podomain = self.config['podomain'] - witness_c_macro = self.config['witness_c_macro'] - configure_ac = self.config['configure_ac'] - vc_files = self.config['vc_files'] - libtests = self.config['libtests'] - modules = [str(module) for module in moduletable['base']] - avoids = [str(avoid) for avoid in moduletable['avoids']] - emit += '# DO NOT EDIT! GENERATED AUTOMATICALLY!\n' - emit += self.emiter.copyright_notice() - emit += '''# + if not localdir or localdir.startswith('/'): + relative_localdir = localdir + else: # if localdir or not localdir.startswith('/') + relative_localdir = constants.relativize(destdir, localdir) + emit += 'gl_LOCAL_DIR([%s])\n' % relative_localdir + emit += 'gl_MODULES([\n' + emit += ' %s\n' % '\n '.join(modules) + emit += '])\n' + if self.config.checkTestFlag(TESTS['obsolete']): + emit += 'gl_WITH_OBSOLETE\n' + if self.config.checkTestFlag(TESTS['cxx-tests']): + emit += 'gl_WITH_CXX_TESTS\n' + if self.config.checkTestFlag(TESTS['privileged-tests']): + emit += 'gl_WITH_PRIVILEGED_TESTS\n' + if self.config.checkTestFlag(TESTS['unportable-tests']): + emit += 'gl_WITH_UNPORTABLE_TESTS\n' + if self.config.checkTestFlag(TESTS['all-tests']): + emit += 'gl_WITH_ALL_TESTS\n' + emit += 'gl_AVOID([%s])\n' % ' '.join(avoids) + emit += 'gl_SOURCE_BASE([%s])\n' % sourcebase + emit += 'gl_M4_BASE([%s])\n' % m4base + emit += 'gl_PO_BASE([%s])\n' % pobase + emit += 'gl_DOC_BASE([%s])\n' % docbase + emit += 'gl_TESTS_BASE([%s])\n' % testsbase + if self.config.checkTestFlag(TESTS['tests']): + emit += 'gl_WITH_TESTS\n' + emit += 'gl_LIB([%s])\n' % libname + if lgpl != False: + if lgpl == True: + emit += 'gl_LGPL\n' + else: # if lgpl != True + emit += 'gl_LGPL([%d])\n' % lgpl + emit += 'gl_MAKEFILE_NAME([%s])\n' % makefile + if conddeps: + emit += 'gl_CONDITIONAL_DEPENDENCIES\n' + if libtool: + emit += 'gl_LIBTOOL\n' + emit += 'gl_MACRO_PREFIX([%s])\n' % macro_prefix + emit += 'gl_PO_DOMAIN([%s])\n' % podomain + emit += 'gl_WITNESS_C_DOMAIN([%s])\n' % witness_c_macro + if vc_files: + emit += 'gl_VC_FILES([%s])\n' % vc_files + if type(emit) is bytes: + emit = emit.decode(ENCS['default']) + return(constants.nlconvert(emit)) + + def gnulib_comp(self, files): + '''GLImport.gnulib_comp(files) -> string + + Emit the contents of generated $m4base/gnulib-comp.m4 file. + GLConfig: destdir, localdir, tests, sourcebase, m4base, pobase, docbase, + testsbase, conddeps, libtool, macro_prefix, podomain, vc_files.''' + emit = string() + assistant = self.assistant + moduletable = self.moduletable + destdir = self.config['destdir'] + localdir = self.config['localdir'] + auxdir = self.config['auxdir'] + testflags = list(self.config['testflags']) + sourcebase = self.config['sourcebase'] + m4base = self.config['m4base'] + pobase = self.config['pobase'] + docbase = self.config['docbase'] + testsbase = self.config['testsbase'] + lgpl = self.config['lgpl'] + libname = self.config['libname'] + makefile = self.config['makefile'] + conddeps = self.config['conddeps'] + libtool = self.config['libtool'] + macro_prefix = self.config['macro_prefix'] + podomain = self.config['podomain'] + witness_c_macro = self.config['witness_c_macro'] + configure_ac = self.config['configure_ac'] + vc_files = self.config['vc_files'] + libtests = self.config['libtests'] + modules = [str(module) for module in moduletable['base']] + avoids = [str(avoid) for avoid in moduletable['avoids']] + emit += '# DO NOT EDIT! GENERATED AUTOMATICALLY!\n' + emit += self.emiter.copyright_notice() + emit += '''# # This file represents the compiled summary of the specification in # gnulib-cache.m4. It lists the computed macro invocations that need # to be invoked from configure.ac. @@ -584,842 +589,854 @@ AC_DEFUN([%s_EARLY], m4_pattern_allow([^gl_LIBOBJS$])dnl a variable m4_pattern_allow([^gl_LTLIBOBJS$])dnl a variable AC_REQUIRE([gl_PROG_AR_RANLIB])\n''' % (configure_ac, macro_prefix) - uses_subdirs = False - for module in moduletable['main']: - # Test whether there are some source files in subdirectories. - for file in module.getFiles(): - if file.startswith('lib/') and file.endswith('.c') and \ - file.count('/') > 1: - uses_subdirs = True - break - if uses_subdirs: - emit += ' AC_REQUIRE([AM_PROG_CC_C_O])\n' - for module in moduletable['final']: - emit += ' # Code from module %s:\n' % str(module) - snippet = module.getAutoconfSnippet_Early() - lines = [line for line in snippet.split(constants.NL) if line != ''] - if lines: - emit += ' %s\n' % '\n '.join(lines) - emit += '])\n' - emit += ''' + uses_subdirs = False + for module in moduletable['main']: + # Test whether there are some source files in subdirectories. + for file in module.getFiles(): + if file.startswith('lib/') and file.endswith('.c') and \ + file.count('/') > 1: + uses_subdirs = True + break + if uses_subdirs: + emit += ' AC_REQUIRE([AM_PROG_CC_C_O])\n' + for module in moduletable['final']: + emit += ' # Code from module %s:\n' % str(module) + snippet = module.getAutoconfSnippet_Early() + lines = [line for line in snippet.split( + constants.NL) if line != ''] + if lines: + emit += ' %s\n' % '\n '.join(lines) + emit += '])\n' + emit += ''' # This macro should be invoked from %s, in the section # "Check for header files, types and library functions". AC_DEFUN([%s_INIT], [\n''' % (configure_ac, macro_prefix) - if libtool: - emit += ' AM_CONDITIONAL([GL_COND_LIBTOOL], [true])\n' - emit += ' gl_cond_libtool=true\n' - else: # if not libtool - emit += ' AM_CONDITIONAL([GL_COND_LIBTOOL], [false])\n' - emit += ' gl_cond_libtool=false\n' - emit += ' gl_libdeps=\n' - emit += ' gl_ltlibdeps=\n' - replace_auxdir = False - if auxdir != 'build-aux': - replace_auxdir = True - emit += ' gl_m4_base=\'%s\'\n' % m4base - emit += self.emiter.initmacro_start(macro_prefix) - emit += ' gl_source_base=\'%s\'\n' % sourcebase - if witness_c_macro: - emit += ' m4_pushdef([gl_MODULE_INDICATOR_CONDITION], [%s])\n' % \ - witness_c_macro - # Emit main autoconf snippets. - emit += self.emiter.autoconfSnippets(moduletable['main'], - moduletable, assistant, 0, True, False, True, replace_auxdir) - if witness_c_macro: - emit += ' m4_popdef([gl_MODULE_INDICATOR_CONDITION])\n' - emit += ' # End of code from modules\n' - emit += self.emiter.initmacro_end(macro_prefix) - emit += ' gltests_libdeps=\n' - emit += ' gltests_ltlibdeps=\n' - emit += self.emiter.initmacro_start('%stests' % macro_prefix) - emit += ' gl_source_base=\'%s\'\n' % testsbase - # Define a tests witness macro that depends on the package. - # PACKAGE is defined by AM_INIT_AUTOMAKE, PACKAGE_TARNAME is defined by - # AC_INIT. - # See . - emit += 'changequote(,)dnl\n' - emit += ' %stests_WITNESS=' % macro_prefix - emit += 'IN_`echo "${PACKAGE-$PACKAGE_TARNAME}" | LC_ALL=C tr \ + if libtool: + emit += ' AM_CONDITIONAL([GL_COND_LIBTOOL], [true])\n' + emit += ' gl_cond_libtool=true\n' + else: # if not libtool + emit += ' AM_CONDITIONAL([GL_COND_LIBTOOL], [false])\n' + emit += ' gl_cond_libtool=false\n' + emit += ' gl_libdeps=\n' + emit += ' gl_ltlibdeps=\n' + replace_auxdir = False + if auxdir != 'build-aux': + replace_auxdir = True + emit += ' gl_m4_base=\'%s\'\n' % m4base + emit += self.emiter.initmacro_start(macro_prefix) + emit += ' gl_source_base=\'%s\'\n' % sourcebase + if witness_c_macro: + emit += ' m4_pushdef([gl_MODULE_INDICATOR_CONDITION], [%s])\n' % \ + witness_c_macro + # Emit main autoconf snippets. + emit += self.emiter.autoconfSnippets(moduletable['main'], + moduletable, assistant, 0, True, False, True, replace_auxdir) + if witness_c_macro: + emit += ' m4_popdef([gl_MODULE_INDICATOR_CONDITION])\n' + emit += ' # End of code from modules\n' + emit += self.emiter.initmacro_end(macro_prefix) + emit += ' gltests_libdeps=\n' + emit += ' gltests_ltlibdeps=\n' + emit += self.emiter.initmacro_start('%stests' % macro_prefix) + emit += ' gl_source_base=\'%s\'\n' % testsbase + # Define a tests witness macro that depends on the package. + # PACKAGE is defined by AM_INIT_AUTOMAKE, PACKAGE_TARNAME is defined by + # AC_INIT. + # See . + emit += 'changequote(,)dnl\n' + emit += ' %stests_WITNESS=' % macro_prefix + emit += 'IN_`echo "${PACKAGE-$PACKAGE_TARNAME}" | LC_ALL=C tr \ abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ | LC_ALL=C sed -e \ \'s/[^A-Z0-9_]/_/g\'`_GNULIB_TESTS\n' - emit += 'changequote([, ])dnl\n' - emit += ' AC_SUBST([%stests_WITNESS])\n' % macro_prefix - emit += ' gl_module_indicator_condition=$%stests_WITNESS\n' % macro_prefix - emit += ' m4_pushdef([gl_MODULE_INDICATOR_CONDITION], ' - emit += '[$gl_module_indicator_condition])\n' - # Emit tests autoconf snippets. - emit += self.emiter.autoconfSnippets(moduletable['tests'], - moduletable, assistant, 0, True, True, True, replace_auxdir) - emit += ' m4_popdef([gl_MODULE_INDICATOR_CONDITION])\n' - emit += self.emiter.initmacro_end('%stests' % macro_prefix) - # _LIBDEPS and _LTLIBDEPS variables are not needed if this library is - # created using libtool, because libtool already handles the dependencies. - if not libtool: - libname_upper = libname.upper().replace('-', '_') - emit += ' %s_LIBDEPS="$gl_libdeps"\n' % libname_upper - emit += ' AC_SUBST([%s_LIBDEPS])\n' % libname_upper - emit += ' %s_LTLIBDEPS="$gl_ltlibdeps"\n' % libname_upper - emit += ' AC_SUBST([%s_LTLIBDEPS])\n' % libname_upper - if libtests: - emit += ' LIBTESTS_LIBDEPS="$gltests_libdeps"\n' - emit += ' AC_SUBST([LIBTESTS_LIBDEPS])\n' - emit += '])\n' - emit += self.emiter.initmacro_done(macro_prefix, sourcebase) - emit += self.emiter.initmacro_done('%stests' % macro_prefix, testsbase) - emit += ''' + emit += 'changequote([, ])dnl\n' + emit += ' AC_SUBST([%stests_WITNESS])\n' % macro_prefix + emit += ' gl_module_indicator_condition=$%stests_WITNESS\n' % macro_prefix + emit += ' m4_pushdef([gl_MODULE_INDICATOR_CONDITION], ' + emit += '[$gl_module_indicator_condition])\n' + # Emit tests autoconf snippets. + emit += self.emiter.autoconfSnippets(moduletable['tests'], + moduletable, assistant, 0, True, True, True, replace_auxdir) + emit += ' m4_popdef([gl_MODULE_INDICATOR_CONDITION])\n' + emit += self.emiter.initmacro_end('%stests' % macro_prefix) + # _LIBDEPS and _LTLIBDEPS variables are not needed if this library is + # created using libtool, because libtool already handles the dependencies. + if not libtool: + libname_upper = libname.upper().replace('-', '_') + emit += ' %s_LIBDEPS="$gl_libdeps"\n' % libname_upper + emit += ' AC_SUBST([%s_LIBDEPS])\n' % libname_upper + emit += ' %s_LTLIBDEPS="$gl_ltlibdeps"\n' % libname_upper + emit += ' AC_SUBST([%s_LTLIBDEPS])\n' % libname_upper + if libtests: + emit += ' LIBTESTS_LIBDEPS="$gltests_libdeps"\n' + emit += ' AC_SUBST([LIBTESTS_LIBDEPS])\n' + emit += '])\n' + emit += self.emiter.initmacro_done(macro_prefix, sourcebase) + emit += self.emiter.initmacro_done('%stests' % macro_prefix, testsbase) + emit += ''' # This macro records the list of files which have been installed by # gnulib-tool and may be removed by future gnulib-tool invocations. AC_DEFUN([%s_FILE_LIST], [\n''' % macro_prefix - emit += ' %s\n' % '\n '.join(files) - emit += '])\n' - if type(emit) is bytes: - emit = emit.decode(ENCS['default']) - return(emit) - - def _done_dir_(self, directory, dirs_added, dirs_removed): - '''GLImport._done_dir_(directory, dirs_added, dirs_removed) - - This method is used to determine ignore argument for _update_ignorelist_ - method and then call it.''' - destdir = self.config['destdir'] - if isdir(joinpath(destdir, 'CVS')) or \ - isdir(joinpath(destdir, directory, 'CVS')) or \ - isfile(joinpath(destdir, directory, '.cvsignore')): - self._update_ignorelist_(directory, '.cvsignore', - dirs_added, dirs_removed) - if isdir(joinpath(destdir, '.git')) or \ - isfile(joinpath(destdir, directory, '.gitignore')): - self._update_ignorelist_(directory, '.gitignore', - dirs_added, dirs_removed) - - - def _update_ignorelist_(self, directory, ignore, dirs_added, dirs_removed): - '''GLImport._update_ignorelist_(directory, ignore, dirs_added, dirs_removed) - - Update .gitignore or .cvsignore files.''' - result = string() - destdir = self.config['destdir'] - if ignore == '.gitignore': - anchor = '/' - else: - anchor = '' - srcpath = joinpath(destdir, directory, ignore) - backupname = '%s~' % srcpath - if isfile(srcpath): - if dirs_added or dirs_removed: - with codecs.open(srcpath, 'rb', 'UTF-8') as file: - srcdata = file.read() - dirs_ignore = sorted(set(srcdata.split('\n'))) - dirs_ignore = [line for line in dirs_ignore if line.strip()] - srcdata = '\n'.join(sorted(set(dirs_ignore))).strip() - dirs_ignore += [d for d in dirs_added if d not in dirs_ignore] - dirs_ignore = [d for d in dirs_ignore if d in dirs_removed] - dirs_ignore = ['%s%s' % (anchor, d) for d in dirs_ignore] - dirs_ignore = sorted(set(dirs_ignore)) - destdata = '\n'.join(sorted(set(dirs_ignore))).strip() - if srcdata != destdata: - if not self.config['dryrun']: - print('Updating %s (backup in %s)' % (srcpath, backupname)) - shutil.move(srcpath, backupname) - result = string() - with codecs.open(srcpath, 'wb', 'UTF-8') as file: - file.write(destdata) - else: # if self.config['dryrun'] - print('Updating %s (backup in %s)' % (srcpath, backupname)) - else: # if not isfile(srcpath) - if dirs_added: - if not self.config['dryrun']: - print('Creating %s' % srcpath) - dirs_added = sorted(set(dirs_added)) - dirs_added = ['%s%s' % (anchor, d) for d in dirs_added] - if ignore == '.cvsignore': - dirs_added = ['.deps', '.dirstamp'] +dirs_added - with codecs.open(srcpath, 'wb', 'UTF-8') as file: - file.write('\n'.join(dirs_added)) - file.write('\n') - else: # if self.config['dryrun'] - print('Create %s' % srcpath) - - def prepare(self): - '''Make all preparations before the execution of the code. - Returns filetable and sed transformers, which change the license.''' - destdir = self.config['destdir'] - localdir = self.config['localdir'] - auxdir = self.config['auxdir'] - modules = list(self.config['modules']) - avoids = list(self.config['avoids']) - testflags = list(self.config['testflags']) - sourcebase = self.config['sourcebase'] - m4base = self.config['m4base'] - pobase = self.config['pobase'] - docbase = self.config['docbase'] - testsbase = self.config['testsbase'] - lgpl = self.config['lgpl'] - copyrights = self.config['copyrights'] - libname = self.config['libname'] - makefile = self.config['makefile'] - conddeps = self.config['conddeps'] - libtool = self.config['libtool'] - macro_prefix = self.config['macro_prefix'] - podomain = self.config['podomain'] - witness_c_macro = self.config['witness_c_macro'] - vc_files = self.config['vc_files'] - configure_ac = self.config['configure_ac'] - ac_version = self.config['ac_version'] - verbose = self.config['verbosity'] - base_modules = sorted(set([self.modulesystem.find(m) for m in modules])) - avoids = sorted(set([self.modulesystem.find(a) for a in avoids])) - - # Perform transitive closure. - self.moduletable.setAvoids(avoids) - final_modules = self.moduletable.transitive_closure(base_modules) - - # Show final module list. - if verbose >= 0: - bold_on = '' - bold_off = '' - term = os.getenv('TERM') - if term == 'xterm': - bold_on = '\x1b[1m' - bold_off = '\x1b[0m' - print('Module list with included dependencies (indented):') - for module in final_modules: - if str(module) in self.config.getModules(): - print(' %s%s%s' % (bold_on, module, bold_off)) - else: # if str(module) not in self.config.getModules() - print(' %s' % module) - - # Separate modules into main_modules and tests_modules. - modules = self.moduletable.transitive_closure_separately( - base_modules, final_modules) - main_modules, tests_modules = modules - - # Transmit base_modules, final_modules, main_modules and tests_modules. - self.moduletable.setBaseModules(base_modules) - self.moduletable.setFinalModules(final_modules) - self.moduletable.setMainModules(main_modules) - self.moduletable.setTestsModules(tests_modules) - - # Print main_modules and tests_modules. - if verbose >= 1: - print('Main module list:') - for module in main_modules: - print(' %s' % str(module)) - print('Tests-related module list:') - for module in tests_modules: - print(' %s' % str(module)) - - # Determine whether a $testsbase/libtests.a is needed. - libtests = False - for module in tests_modules: - files = module.getFiles() - for file in files: - if file.startswith('lib/'): - libtests = True - break - if libtests: - self.config.enableLibtests() - - # Add dummy package if it is needed. - main_modules = self.moduletable.add_dummy(main_modules) - if libtests: # if we need to use libtests.a - tests_modules = self.moduletable.add_dummy(tests_modules) - - # Check license incompatibilities. - listing = list() - compatibilities = dict() - incompatibilities = string() - compatibilities['all'] = ['GPLed build tool', 'public domain', 'unlimited', - 'unmodifiable license text'] - compatibilities[3] = ['LGPL', 'LGPLv2+', 'LGPLv3+'] - compatibilities[2] = ['LGPLv2+'] - if lgpl: - for module in main_modules: - license = module.getLicense() - if license not in compatibilities['all']: - if lgpl == 3 or lgpl == True: - if license not in compatibilities[3]: - listing.append(tuple([str(module), license])) - elif lgpl == 2: - if license not in compatibilities[2]: - listing.append(tuple([str(module), license])) - if listing: - raise(GLError(11, listing)) - - # Print notices from modules. - for module in main_modules: - notice = module.getNotice() - notice = notice.strip() - if notice: - print('Notice from module %s:' % str(module)) - pattern = compiler('^(.*?)$', re.S | re.M) - notice = pattern.sub(' \\1', notice) - print(notice) - - # Determine script to apply to imported library files. - lgpl2gpl = ''' + emit += ' %s\n' % '\n '.join(files) + emit += '])\n' + if type(emit) is bytes: + emit = emit.decode(ENCS['default']) + return(emit) + + def _done_dir_(self, directory, dirs_added, dirs_removed): + '''GLImport._done_dir_(directory, dirs_added, dirs_removed) + + This method is used to determine ignore argument for _update_ignorelist_ + method and then call it.''' + destdir = self.config['destdir'] + if isdir(joinpath(destdir, 'CVS')) or \ + isdir(joinpath(destdir, directory, 'CVS')) or \ + isfile(joinpath(destdir, directory, '.cvsignore')): + self._update_ignorelist_(directory, '.cvsignore', + dirs_added, dirs_removed) + if isdir(joinpath(destdir, '.git')) or \ + isfile(joinpath(destdir, directory, '.gitignore')): + self._update_ignorelist_(directory, '.gitignore', + dirs_added, dirs_removed) + + def _update_ignorelist_(self, directory, ignore, dirs_added, dirs_removed): + '''GLImport._update_ignorelist_(directory, ignore, dirs_added, dirs_removed) + + Update .gitignore or .cvsignore files.''' + result = string() + destdir = self.config['destdir'] + if ignore == '.gitignore': + anchor = '/' + else: + anchor = '' + srcpath = joinpath(destdir, directory, ignore) + backupname = '%s~' % srcpath + if isfile(srcpath): + if dirs_added or dirs_removed: + with codecs.open(srcpath, 'rb', 'UTF-8') as file: + srcdata = file.read() + dirs_ignore = sorted(set(srcdata.split('\n'))) + dirs_ignore = [line for line in dirs_ignore if line.strip()] + srcdata = '\n'.join(sorted(set(dirs_ignore))).strip() + dirs_ignore += [d for d in dirs_added if d not in dirs_ignore] + dirs_ignore = [d for d in dirs_ignore if d in dirs_removed] + dirs_ignore = ['%s%s' % (anchor, d) for d in dirs_ignore] + dirs_ignore = sorted(set(dirs_ignore)) + destdata = '\n'.join(sorted(set(dirs_ignore))).strip() + if srcdata != destdata: + if not self.config['dryrun']: + print('Updating %s (backup in %s)' % + (srcpath, backupname)) + shutil.move(srcpath, backupname) + result = string() + with codecs.open(srcpath, 'wb', 'UTF-8') as file: + file.write(destdata) + else: # if self.config['dryrun'] + print('Updating %s (backup in %s)' % + (srcpath, backupname)) + else: # if not isfile(srcpath) + if dirs_added: + if not self.config['dryrun']: + print('Creating %s' % srcpath) + dirs_added = sorted(set(dirs_added)) + dirs_added = ['%s%s' % (anchor, d) for d in dirs_added] + if ignore == '.cvsignore': + dirs_added = ['.deps', '.dirstamp'] + dirs_added + with codecs.open(srcpath, 'wb', 'UTF-8') as file: + file.write('\n'.join(dirs_added)) + file.write('\n') + else: # if self.config['dryrun'] + print('Create %s' % srcpath) + + def prepare(self): + '''Make all preparations before the execution of the code. + Returns filetable and sed transformers, which change the license.''' + destdir = self.config['destdir'] + localdir = self.config['localdir'] + auxdir = self.config['auxdir'] + modules = list(self.config['modules']) + avoids = list(self.config['avoids']) + testflags = list(self.config['testflags']) + sourcebase = self.config['sourcebase'] + m4base = self.config['m4base'] + pobase = self.config['pobase'] + docbase = self.config['docbase'] + testsbase = self.config['testsbase'] + lgpl = self.config['lgpl'] + copyrights = self.config['copyrights'] + libname = self.config['libname'] + makefile = self.config['makefile'] + conddeps = self.config['conddeps'] + libtool = self.config['libtool'] + macro_prefix = self.config['macro_prefix'] + podomain = self.config['podomain'] + witness_c_macro = self.config['witness_c_macro'] + vc_files = self.config['vc_files'] + configure_ac = self.config['configure_ac'] + ac_version = self.config['ac_version'] + verbose = self.config['verbosity'] + base_modules = sorted( + set([self.modulesystem.find(m) for m in modules])) + avoids = sorted(set([self.modulesystem.find(a) for a in avoids])) + + # Perform transitive closure. + self.moduletable.setAvoids(avoids) + final_modules = self.moduletable.transitive_closure(base_modules) + + # Show final module list. + if verbose >= 0: + bold_on = '' + bold_off = '' + term = os.getenv('TERM') + if term == 'xterm': + bold_on = '\x1b[1m' + bold_off = '\x1b[0m' + print('Module list with included dependencies (indented):') + for module in final_modules: + if str(module) in self.config.getModules(): + print(' %s%s%s' % (bold_on, module, bold_off)) + else: # if str(module) not in self.config.getModules() + print(' %s' % module) + + # Separate modules into main_modules and tests_modules. + modules = self.moduletable.transitive_closure_separately( + base_modules, final_modules) + main_modules, tests_modules = modules + + # Transmit base_modules, final_modules, main_modules and tests_modules. + self.moduletable.setBaseModules(base_modules) + self.moduletable.setFinalModules(final_modules) + self.moduletable.setMainModules(main_modules) + self.moduletable.setTestsModules(tests_modules) + + # Print main_modules and tests_modules. + if verbose >= 1: + print('Main module list:') + for module in main_modules: + print(' %s' % str(module)) + print('Tests-related module list:') + for module in tests_modules: + print(' %s' % str(module)) + + # Determine whether a $testsbase/libtests.a is needed. + libtests = False + for module in tests_modules: + files = module.getFiles() + for file in files: + if file.startswith('lib/'): + libtests = True + break + if libtests: + self.config.enableLibtests() + + # Add dummy package if it is needed. + main_modules = self.moduletable.add_dummy(main_modules) + if libtests: # if we need to use libtests.a + tests_modules = self.moduletable.add_dummy(tests_modules) + + # Check license incompatibilities. + listing = list() + compatibilities = dict() + incompatibilities = string() + compatibilities['all'] = ['GPLed build tool', 'public domain', 'unlimited', + 'unmodifiable license text'] + compatibilities[3] = ['LGPL', 'LGPLv2+', 'LGPLv3+'] + compatibilities[2] = ['LGPLv2+'] + if lgpl: + for module in main_modules: + license = module.getLicense() + if license not in compatibilities['all']: + if lgpl == 3 or lgpl == True: + if license not in compatibilities[3]: + listing.append(tuple([str(module), license])) + elif lgpl == 2: + if license not in compatibilities[2]: + listing.append(tuple([str(module), license])) + if listing: + raise(GLError(11, listing)) + + # Print notices from modules. + for module in main_modules: + notice = module.getNotice() + notice = notice.strip() + if notice: + print('Notice from module %s:' % str(module)) + pattern = compiler('^(.*?)$', re.S | re.M) + notice = pattern.sub(' \\1', notice) + print(notice) + + # Determine script to apply to imported library files. + lgpl2gpl = ''' s/GNU Lesser General/GNU General/g s/Lesser General Public License/General Public License/g s/GNU Library General/GNU General/g s/Library General Public License/General Public License/g s/version 2\\(.1\\)\\{0,1\\}\\([ ,]\\)/version 3\\2/g''' - sed_transform_lib_file = string() - if 'config-h' in [str(module) for module in main_modules]: - sed_transform_lib_file += ''' + sed_transform_lib_file = string() + if 'config-h' in [str(module) for module in main_modules]: + sed_transform_lib_file += ''' s/^#ifdef[\t ]*HAVE_CONFIG_H[\t ]*$/#if 1/ ''' - sed_transform_main_lib_file = sed_transform_lib_file - if copyrights: - if lgpl: # if lgpl is enabled - if lgpl == 3: - sed_transform_main_lib_file += ''' + sed_transform_main_lib_file = sed_transform_lib_file + if copyrights: + if lgpl: # if lgpl is enabled + if lgpl == 3: + sed_transform_main_lib_file += ''' s/GNU General/GNU Lesser General/g s/General Public License/Lesser General Public License/g s/Lesser Lesser General Public License/Lesser General Public''' \ - +' License/g' - elif lgpl == 2: - sed_transform_main_lib_file += ''' + + ' License/g' + elif lgpl == 2: + sed_transform_main_lib_file += ''' s/GNU General/GNU Lesser General/g s/General Public License/Lesser General Public License/g s/Lesser Lesser General Public License/Lesser General Public''' \ - +'''License/g + + '''License/g s/version [23]\\([ ,]\\)/version 2.1\\1/g''' - else: # if lgpl is disabled - sed_transform_main_lib_file += lgpl2gpl - - # Determine script to apply to auxiliary files that go into $auxdir/. - sed_transform_build_aux_file = string() - if copyrights: - sed_transform_build_aux_file += lgpl2gpl - - # Determine script to apply to library files that go into $testsbase/. - sed_transform_testsrelated_lib_file = sed_transform_lib_file - if copyrights: - sed_transform_testsrelated_lib_file += lgpl2gpl - - # Determine the final file lists. - main_filelist, tests_filelist = \ - self.moduletable.filelist_separately(main_modules, tests_modules) - filelist = sorted(set(main_filelist +tests_filelist), key=string.lower) - if not filelist: - raise(GLError(12, None)) - - # Print list of files. - if verbose >= 0: - print('File list:') - for file in filelist: - if file.startswith('tests=lib/'): - rest = file[10:] - print(' lib/%s -> tests/%s' % (rest, rest)) - else: - print(' %s' % file) - - # Prepare basic filelist and basic old_files/new_files variables. - filelist = sorted(set(filelist)) - new_files = filelist +['m4/gnulib-tool.m4'] - old_files = list(self.cache['files']) - path = joinpath(destdir, m4base, 'gnulib-tool.m4') - if isfile(path): - old_files += [joinpath('m4', 'gnulib-tool.m4')] - - # Construct tables and transformers. - transformers = dict() - transformers['lib'] = string(sed_transform_lib_file) - transformers['aux'] = string(sed_transform_build_aux_file) - transformers['main'] = string(sed_transform_main_lib_file) - transformers['tests'] = string(sed_transform_testsrelated_lib_file) - old_table = list() - new_table = list() - for src in old_files: - dest = self.rewrite_old_files([src])[-1] - old_table += [tuple([dest, src])] - for src in new_files: - dest = self.rewrite_new_files([src])[-1] - new_table += [tuple([dest, src])] - old_table = sorted(set(old_table)) - new_table = sorted(set(new_table)) - - # Prepare the filetable. - filetable = dict() - filetable['all'] = sorted(set(filelist)) - filetable['old'] = \ - sorted(set(old_table), key=lambda t: tuple(t[0].lower())) - filetable['new'] = \ - sorted(set(new_table), key=lambda t: tuple(t[0].lower())) - filetable['added'] = list() - filetable['removed'] = list() - - # Return the result. - result = tuple([filetable, transformers]) - return(result) - - def execute(self, filetable, transformers): - '''Perform operations on the lists of files, which are given in a special - format except filelist argument. Such lists of files can be created using - GLImport.prepare() function.''' - if type(filetable) is not dict: - raise(TypeError('filetable must be a dict, not %s' % \ - type(filetable).__name__)) - for key in ['all', 'old', 'new', 'added', 'removed']: - if key not in filetable: - raise(KeyError('filetable must contain key %s' % repr(key))) - destdir = self.config['destdir'] - localdir = self.config['localdir'] - auxdir = self.config['auxdir'] - modules = list(self.config['modules']) - avoids = list(self.config['avoids']) - testflags = list(self.config['testflags']) - sourcebase = self.config['sourcebase'] - m4base = self.config['m4base'] - pobase = self.config['pobase'] - docbase = self.config['docbase'] - testsbase = self.config['testsbase'] - lgpl = self.config['lgpl'] - copyrights = self.config['copyrights'] - libname = self.config['libname'] - makefile = self.config['makefile'] - conddeps = self.config['conddeps'] - libtool = self.config['libtool'] - macro_prefix = self.config['macro_prefix'] - podomain = self.config['podomain'] - witness_c_macro = self.config['witness_c_macro'] - vc_files = self.config['vc_files'] - configure_ac = self.config['configure_ac'] - ac_version = self.config['ac_version'] - verbose = self.config['verbosity'] - actioncmd = self.actioncmd() - - # Create all necessary directories. - dirs = list() - if pobase: - dirs += [pobase] - if [file for file in filetable['all'] if file.startswith('doc/')]: - dirs += [docbase] - dirs += [sourcebase, m4base, auxdir] - dirs += [os.path.dirname(pair[0]) for pair in filetable['new']] - dirs = sorted(set([joinpath(destdir, d) for d in dirs])) - for directory in dirs: - if not isdir(directory): - print('Creating directory %s' % directory) - if not self.config['dryrun']: - try: # Try to create directory - os.makedirs(directory) - except Exception as error: - raise(GLError(13, directory)) - else: # if self.config['dryrun'] - print('Create directory %s' % directory) - - # Create GLFileAssistant instance to process files. - self.assistant = GLFileAssistant(self.config, transformers) - - # Files which are in filetable['old'] and not in filetable['new']. - # They will be removed and added to filetable['removed'] list. - pairs = [f for f in filetable['old'] if f not in filetable['old']] - pairs = sorted(set(pairs), key=lambda t: tuple(t[0].lower())) - files = sorted(set(pair[0] for pair in pairs)) - for file in files: - path = joinpath(destdir, file) - if isfile(path) or os.path.islink(path): - if not self.config['dryrun']: - backup = string('%s~' % path) - print('Removing file %s (backup in )' % (path, backup)) - try: # Try to move file - if os.path.exists(backup): - os.remove(backup) - shutil.move(path, '%s~' % path) - except Exception as error: - raise(GLError(14, file)) - else: # if self.config['dryrun'] - print('Remove file %s (backup in %s~)' % (path, path)) - filetable['removed'] += [file] - - # Files which are in filetable['new'] and not in filetable['old']. - # They will be added/updated and added to filetable['added'] list. - already_present = False - pairs = [f for f in filetable['new'] if f not in filetable['old']] - pairs = sorted(set(pairs)) - for pair in pairs: - original = pair[1] - rewritten = pair[0] - self.assistant.setOriginal(original) - self.assistant.setRewritten(rewritten) - self.assistant.add_or_update(already_present) - - # Files which are in filetable['new'] and in filetable['old']. - # They will be added/updated and added to filetable['added'] list. - already_present = True - pairs = [f for f in filetable['new'] if f in filetable['old']] - pairs = sorted(set(pairs)) - for pair in pairs: - original = pair[1] - rewritten = pair[0] - self.assistant.setOriginal(original) - self.assistant.setRewritten(rewritten) - self.assistant.add_or_update(already_present) - - # Add files which were added to the list of filetable['added']. - filetable['added'] += self.assistant.getFiles() - filetable['added'] = sorted(set(filetable['added'])) - - # Determine include_guard_prefix. - include_guard_prefix = self.config['include_guard_prefix'] - - # Determine makefile name. - if not makefile: - makefile_am = string('Makefile.am') - else: # if makefile - makefile_am = makefile - - # Create normal Makefile.ams. - for_test = False - - # Setup list of Makefile.am edits that are to be performed afterwards. - # Some of these edits apply to files that we will generate; others are - # under the responsibility of the developer. - makefile_am_edits = dict() - if makefile_am == 'Makefile.am': - sourcebase_dir = os.path.dirname(sourcebase) - sourcebase_base = os.path.basename(sourcebase) - self.makefiletable.editor(sourcebase_dir, 'SUBDIRS', sourcebase_base) - if pobase: - pobase_dir = os.path.dirname(pobase) - pobase_base = os.path.basename(pobase) - self.makefiletable.editor(pobase_dir, 'SUBDIRS', pobase_base) - if self.config.checkTestFlag(TESTS['tests']): - if makefile_am == 'Makefile.am': - testsbase_dir = os.path.dirname(testsbase) - testsbase_base = os.path.basename(testsbase) - self.makefiletable.editor(testsbase_dir, 'SUBDIRS', testsbase_base) - self.makefiletable.editor('', 'ACLOCAL_AMFLAGS', '-I %s' % m4base) - self.makefiletable.parent() - - # Create library makefile. - basename = joinpath(sourcebase, makefile_am) - tmpfile = self.assistant.tmpfilename(basename) - emit, uses_subdirs = self.emiter.lib_Makefile_am(basename, - self.moduletable['main'], self.moduletable, self.makefiletable, - actioncmd, for_test) - with codecs.open(tmpfile, 'wb', 'UTF-8') as file: - file.write(emit) - filename, backup, flag = self.assistant.super_update(basename, tmpfile) - if flag == 1: - if not self.config['dryrun']: - print('Updating %s (backup in %s)' % (filename, backup)) - else: # if self.config['dryrun'] - print('Update %s (backup in %s)' % (filename, backup)) - elif flag == 2: - if not self.config['dryrun']: - print('Creating %s' % filename) - else: # if self.config['dryrun']: - print('Create %s' % filename) - filetable['added'] += [filename] - if isfile(tmpfile): - os.remove(tmpfile) - - # Create po/ directory. - filesystem = GLFileSystem(self.config) - if pobase: - # Create po makefile and auxiliary files. - for file in ['Makefile.in.in', 'remove-potcdate.sin']: - tmpfile = self.assistant.tmpfilename(joinpath(pobase, file)) - path = joinpath('build-aux', 'po', file) - lookedup, flag = filesystem.lookup(path) - shutil.move(lookedup, tmpfile) - basename = joinpath(pobase, file) + else: # if lgpl is disabled + sed_transform_main_lib_file += lgpl2gpl + + # Determine script to apply to auxiliary files that go into $auxdir/. + sed_transform_build_aux_file = string() + if copyrights: + sed_transform_build_aux_file += lgpl2gpl + + # Determine script to apply to library files that go into $testsbase/. + sed_transform_testsrelated_lib_file = sed_transform_lib_file + if copyrights: + sed_transform_testsrelated_lib_file += lgpl2gpl + + # Determine the final file lists. + main_filelist, tests_filelist = \ + self.moduletable.filelist_separately(main_modules, tests_modules) + filelist = sorted( + set(main_filelist + tests_filelist), key=string.lower) + if not filelist: + raise(GLError(12, None)) + + # Print list of files. + if verbose >= 0: + print('File list:') + for file in filelist: + if file.startswith('tests=lib/'): + rest = file[10:] + print(' lib/%s -> tests/%s' % (rest, rest)) + else: + print(' %s' % file) + + # Prepare basic filelist and basic old_files/new_files variables. + filelist = sorted(set(filelist)) + new_files = filelist + ['m4/gnulib-tool.m4'] + old_files = list(self.cache['files']) + path = joinpath(destdir, m4base, 'gnulib-tool.m4') + if isfile(path): + old_files += [joinpath('m4', 'gnulib-tool.m4')] + + # Construct tables and transformers. + transformers = dict() + transformers['lib'] = string(sed_transform_lib_file) + transformers['aux'] = string(sed_transform_build_aux_file) + transformers['main'] = string(sed_transform_main_lib_file) + transformers['tests'] = string(sed_transform_testsrelated_lib_file) + old_table = list() + new_table = list() + for src in old_files: + dest = self.rewrite_old_files([src])[-1] + old_table += [tuple([dest, src])] + for src in new_files: + dest = self.rewrite_new_files([src])[-1] + new_table += [tuple([dest, src])] + old_table = sorted(set(old_table)) + new_table = sorted(set(new_table)) + + # Prepare the filetable. + filetable = dict() + filetable['all'] = sorted(set(filelist)) + filetable['old'] = \ + sorted(set(old_table), key=lambda t: tuple(t[0].lower())) + filetable['new'] = \ + sorted(set(new_table), key=lambda t: tuple(t[0].lower())) + filetable['added'] = list() + filetable['removed'] = list() + + # Return the result. + result = tuple([filetable, transformers]) + return(result) + + def execute(self, filetable, transformers): + '''Perform operations on the lists of files, which are given in a special + format except filelist argument. Such lists of files can be created using + GLImport.prepare() function.''' + if type(filetable) is not dict: + raise(TypeError('filetable must be a dict, not %s' % + type(filetable).__name__)) + for key in ['all', 'old', 'new', 'added', 'removed']: + if key not in filetable: + raise(KeyError('filetable must contain key %s' % repr(key))) + destdir = self.config['destdir'] + localdir = self.config['localdir'] + auxdir = self.config['auxdir'] + modules = list(self.config['modules']) + avoids = list(self.config['avoids']) + testflags = list(self.config['testflags']) + sourcebase = self.config['sourcebase'] + m4base = self.config['m4base'] + pobase = self.config['pobase'] + docbase = self.config['docbase'] + testsbase = self.config['testsbase'] + lgpl = self.config['lgpl'] + copyrights = self.config['copyrights'] + libname = self.config['libname'] + makefile = self.config['makefile'] + conddeps = self.config['conddeps'] + libtool = self.config['libtool'] + macro_prefix = self.config['macro_prefix'] + podomain = self.config['podomain'] + witness_c_macro = self.config['witness_c_macro'] + vc_files = self.config['vc_files'] + configure_ac = self.config['configure_ac'] + ac_version = self.config['ac_version'] + verbose = self.config['verbosity'] + actioncmd = self.actioncmd() + + # Create all necessary directories. + dirs = list() + if pobase: + dirs += [pobase] + if [file for file in filetable['all'] if file.startswith('doc/')]: + dirs += [docbase] + dirs += [sourcebase, m4base, auxdir] + dirs += [os.path.dirname(pair[0]) for pair in filetable['new']] + dirs = sorted(set([joinpath(destdir, d) for d in dirs])) + for directory in dirs: + if not isdir(directory): + print('Creating directory %s' % directory) + if not self.config['dryrun']: + try: # Try to create directory + os.makedirs(directory) + except Exception as error: + raise(GLError(13, directory)) + else: # if self.config['dryrun'] + print('Create directory %s' % directory) + + # Create GLFileAssistant instance to process files. + self.assistant = GLFileAssistant(self.config, transformers) + + # Files which are in filetable['old'] and not in filetable['new']. + # They will be removed and added to filetable['removed'] list. + pairs = [f for f in filetable['old'] if f not in filetable['old']] + pairs = sorted(set(pairs), key=lambda t: tuple(t[0].lower())) + files = sorted(set(pair[0] for pair in pairs)) + for file in files: + path = joinpath(destdir, file) + if isfile(path) or os.path.islink(path): + if not self.config['dryrun']: + backup = string('%s~' % path) + print('Removing file %s (backup in )' % (path, backup)) + try: # Try to move file + if os.path.exists(backup): + os.remove(backup) + shutil.move(path, '%s~' % path) + except Exception as error: + raise(GLError(14, file)) + else: # if self.config['dryrun'] + print('Remove file %s (backup in %s~)' % (path, path)) + filetable['removed'] += [file] + + # Files which are in filetable['new'] and not in filetable['old']. + # They will be added/updated and added to filetable['added'] list. + already_present = False + pairs = [f for f in filetable['new'] if f not in filetable['old']] + pairs = sorted(set(pairs)) + for pair in pairs: + original = pair[1] + rewritten = pair[0] + self.assistant.setOriginal(original) + self.assistant.setRewritten(rewritten) + self.assistant.add_or_update(already_present) + + # Files which are in filetable['new'] and in filetable['old']. + # They will be added/updated and added to filetable['added'] list. + already_present = True + pairs = [f for f in filetable['new'] if f in filetable['old']] + pairs = sorted(set(pairs)) + for pair in pairs: + original = pair[1] + rewritten = pair[0] + self.assistant.setOriginal(original) + self.assistant.setRewritten(rewritten) + self.assistant.add_or_update(already_present) + + # Add files which were added to the list of filetable['added']. + filetable['added'] += self.assistant.getFiles() + filetable['added'] = sorted(set(filetable['added'])) + + # Determine include_guard_prefix. + include_guard_prefix = self.config['include_guard_prefix'] + + # Determine makefile name. + if not makefile: + makefile_am = string('Makefile.am') + else: # if makefile + makefile_am = makefile + + # Create normal Makefile.ams. + for_test = False + + # Setup list of Makefile.am edits that are to be performed afterwards. + # Some of these edits apply to files that we will generate; others are + # under the responsibility of the developer. + makefile_am_edits = dict() + if makefile_am == 'Makefile.am': + sourcebase_dir = os.path.dirname(sourcebase) + sourcebase_base = os.path.basename(sourcebase) + self.makefiletable.editor( + sourcebase_dir, 'SUBDIRS', sourcebase_base) + if pobase: + pobase_dir = os.path.dirname(pobase) + pobase_base = os.path.basename(pobase) + self.makefiletable.editor(pobase_dir, 'SUBDIRS', pobase_base) + if self.config.checkTestFlag(TESTS['tests']): + if makefile_am == 'Makefile.am': + testsbase_dir = os.path.dirname(testsbase) + testsbase_base = os.path.basename(testsbase) + self.makefiletable.editor( + testsbase_dir, 'SUBDIRS', testsbase_base) + self.makefiletable.editor('', 'ACLOCAL_AMFLAGS', '-I %s' % m4base) + self.makefiletable.parent() + + # Create library makefile. + basename = joinpath(sourcebase, makefile_am) + tmpfile = self.assistant.tmpfilename(basename) + emit, uses_subdirs = self.emiter.lib_Makefile_am(basename, + self.moduletable['main'], self.moduletable, self.makefiletable, + actioncmd, for_test) + with codecs.open(tmpfile, 'wb', 'UTF-8') as file: + file.write(emit) filename, backup, flag = self.assistant.super_update(basename, tmpfile) if flag == 1: - if not self.config['dryrun']: - print('Updating %s (backup in %s)' % (filename, backup)) - else: # if self.config['dryrun'] - print('Update %s (backup in %s)' % (filename, backup)) + if not self.config['dryrun']: + print('Updating %s (backup in %s)' % (filename, backup)) + else: # if self.config['dryrun'] + print('Update %s (backup in %s)' % (filename, backup)) elif flag == 2: - if not self.config['dryrun']: - print('Creating %s' % filename) - else: # if self.config['dryrun']: - print('Create %s' % filename) - filetable['added'] += [filename] - if isfile(tmpfile): - os.remove(tmpfile) - - # Create po makefile parameterization, part 1. - basename = joinpath(pobase, 'Makevars') - tmpfile = self.assistant.tmpfilename(basename) - emit = self.emiter.po_Makevars() - with codecs.open(tmpfile, 'wb', 'UTF-8') as file: - file.write(emit) - filename, backup, flag = self.assistant.super_update(basename, tmpfile) - if flag == 1: - if not self.config['dryrun']: - print('Updating %s (backup in %s)' % (filename, backup)) - else: # if self.config['dryrun'] - print('Update %s (backup in %s)' % (filename, backup)) - elif flag == 2: - if not self.config['dryrun']: - print('Creating %s' % filename) - else: # if self.config['dryrun']: - print('Create %s' % filename) - filetable['added'] += [filename] - if isfile(tmpfile): - os.remove(tmpfile) - - # Create po makefile parameterization, part 2. - basename = joinpath(pobase, 'POTFILES.in') - tmpfile = self.assistant.tmpfilename(basename) - with codecs.open(tmpfile, 'wb', 'UTF-8') as file: - file.write(self.emiter.po_POTFILES_in(filetable['all'])) - basename = joinpath(pobase, 'POTFILES.in') - filename, backup, flag = self.assistant.super_update(basename, tmpfile) - if flag == 1: - if not self.config['dryrun']: - print('Updating %s (backup in %s)' % (filename, backup)) - else: # if self.config['dryrun'] - print('Update %s (backup in %s)' % (filename, backup)) - elif flag == 2: - if not self.config['dryrun']: - print('Creating %s' % filename) - else: # if self.config['dryrun']: - print('Create %s' % filename) - filetable['added'] += [filename] - if isfile(tmpfile): - os.remove(tmpfile) - - # Fetch PO files. - TP_URL = 'http://translationproject.org/latest/' - TP_RSYNC_URI = 'translationproject.org::tp/latest/' - if not self.config['dryrun']: - print('Fetching gnulib PO files from %s' % TP_URL) - os.chdir(joinpath(destdir, pobase)) - cmd = 'if type rsync 2>/dev/null | grep / > /dev/null; ' - cmd += 'then echo 1; else echo 0; fi' - result = sp.check_output(cmd, shell=True) - result = bool(int(result)) - if result: # use rsync - args = ['rsync', '-Lrtz', '%sgulib/' % TP_RSYNC_URI, '.'] - else: # use wget - args = ['wget', '--quiet', '-r', '-l1', '-nd', '-np', 'A.po', - '%sgnulib' % TP_URL] - sp.call(args, shell=True) - else: # if self.config['dryrun'] - print('Fetch gnulib PO files from %s' % TP_URL) - - # Create po/LINGUAS. - basename = joinpath(pobase, 'LINGUAS') - if not self.config['dryrun']: + if not self.config['dryrun']: + print('Creating %s' % filename) + else: # if self.config['dryrun']: + print('Create %s' % filename) + filetable['added'] += [filename] + if isfile(tmpfile): + os.remove(tmpfile) + + # Create po/ directory. + filesystem = GLFileSystem(self.config) + if pobase: + # Create po makefile and auxiliary files. + for file in ['Makefile.in.in', 'remove-potcdate.sin']: + tmpfile = self.assistant.tmpfilename(joinpath(pobase, file)) + path = joinpath('build-aux', 'po', file) + lookedup, flag = filesystem.lookup(path) + shutil.move(lookedup, tmpfile) + basename = joinpath(pobase, file) + filename, backup, flag = self.assistant.super_update( + basename, tmpfile) + if flag == 1: + if not self.config['dryrun']: + print('Updating %s (backup in %s)' % + (filename, backup)) + else: # if self.config['dryrun'] + print('Update %s (backup in %s)' % (filename, backup)) + elif flag == 2: + if not self.config['dryrun']: + print('Creating %s' % filename) + else: # if self.config['dryrun']: + print('Create %s' % filename) + filetable['added'] += [filename] + if isfile(tmpfile): + os.remove(tmpfile) + + # Create po makefile parameterization, part 1. + basename = joinpath(pobase, 'Makevars') + tmpfile = self.assistant.tmpfilename(basename) + emit = self.emiter.po_Makevars() + with codecs.open(tmpfile, 'wb', 'UTF-8') as file: + file.write(emit) + filename, backup, flag = self.assistant.super_update( + basename, tmpfile) + if flag == 1: + if not self.config['dryrun']: + print('Updating %s (backup in %s)' % (filename, backup)) + else: # if self.config['dryrun'] + print('Update %s (backup in %s)' % (filename, backup)) + elif flag == 2: + if not self.config['dryrun']: + print('Creating %s' % filename) + else: # if self.config['dryrun']: + print('Create %s' % filename) + filetable['added'] += [filename] + if isfile(tmpfile): + os.remove(tmpfile) + + # Create po makefile parameterization, part 2. + basename = joinpath(pobase, 'POTFILES.in') + tmpfile = self.assistant.tmpfilename(basename) + with codecs.open(tmpfile, 'wb', 'UTF-8') as file: + file.write(self.emiter.po_POTFILES_in(filetable['all'])) + basename = joinpath(pobase, 'POTFILES.in') + filename, backup, flag = self.assistant.super_update( + basename, tmpfile) + if flag == 1: + if not self.config['dryrun']: + print('Updating %s (backup in %s)' % (filename, backup)) + else: # if self.config['dryrun'] + print('Update %s (backup in %s)' % (filename, backup)) + elif flag == 2: + if not self.config['dryrun']: + print('Creating %s' % filename) + else: # if self.config['dryrun']: + print('Create %s' % filename) + filetable['added'] += [filename] + if isfile(tmpfile): + os.remove(tmpfile) + + # Fetch PO files. + TP_URL = 'http://translationproject.org/latest/' + TP_RSYNC_URI = 'translationproject.org::tp/latest/' + if not self.config['dryrun']: + print('Fetching gnulib PO files from %s' % TP_URL) + os.chdir(joinpath(destdir, pobase)) + cmd = 'if type rsync 2>/dev/null | grep / > /dev/null; ' + cmd += 'then echo 1; else echo 0; fi' + result = sp.check_output(cmd, shell=True) + result = bool(int(result)) + if result: # use rsync + args = ['rsync', '-Lrtz', '%sgulib/' % TP_RSYNC_URI, '.'] + else: # use wget + args = ['wget', '--quiet', '-r', '-l1', '-nd', '-np', 'A.po', + '%sgnulib' % TP_URL] + sp.call(args, shell=True) + else: # if self.config['dryrun'] + print('Fetch gnulib PO files from %s' % TP_URL) + + # Create po/LINGUAS. + basename = joinpath(pobase, 'LINGUAS') + if not self.config['dryrun']: + tmpfile = self.assistant.tmpfilename(basename) + data = string('# Set of available languages.\n') + files = [constants.subend('.po', '', file) + for file in os.listdir(joinpath(destdir, pobase))] + files = [file.decode(ENCS['default']) if type(file) is bytes + else file for file in files] + data += '\n'.join(files) + with codecs.open(tmpfile, 'wb', 'UTF-8') as file: + file.write(data) + filename, backup, flag = self.assistant.super_update( + basename, tmpfile) + if flag == 1: + print('Updating %s (backup in %s)' % (filename, backup)) + elif flag == 2: + print('Creating %s' % filename) + filetable['added'] += [filename] + if isfile(tmpfile): + os.remove(tmpfile) + else: # if not self.config['dryrun'] + backupname = '%s~' % basename + if isfile(destdir, basename): + print('Update %s (backup in %s)' % (basename, backupname)) + else: # if not isfile(destdir, basename) + print('Create %s' % basename) + + # Create m4/gnulib-cache.m4. + basename = joinpath(m4base, 'gnulib-cache.m4') tmpfile = self.assistant.tmpfilename(basename) - data = string('# Set of available languages.\n') - files = [constants.subend('.po', '', file) \ - for file in os.listdir(joinpath(destdir, pobase))] - files = [file.decode(ENCS['default']) if type(file) is bytes \ - else file for file in files] - data += '\n'.join(files) + emit = self.gnulib_cache() with codecs.open(tmpfile, 'wb', 'UTF-8') as file: - file.write(data) + file.write(emit) filename, backup, flag = self.assistant.super_update(basename, tmpfile) if flag == 1: - print('Updating %s (backup in %s)' % (filename, backup)) + if not self.config['dryrun']: + print('Updating %s (backup in %s)' % (filename, backup)) + else: # if self.config['dryrun'] + print('Update %s (backup in %s)' % (filename, backup)) elif flag == 2: - print('Creating %s' % filename) - filetable['added'] += [filename] + if not self.config['dryrun']: + print('Creating %s' % filename) + else: # if self.config['dryrun']: + print('Create %s' % filename) + if emit[-2:] == '\r\n': + emit = emit[:-2] + elif emit[-1:] == '\n': + emit = emit[:-1] + print(emit) if isfile(tmpfile): - os.remove(tmpfile) - else: # if not self.config['dryrun'] - backupname = '%s~' % basename - if isfile(destdir, basename): - print('Update %s (backup in %s)' % (basename, backupname)) - else: # if not isfile(destdir, basename) - print('Create %s' % basename) - - # Create m4/gnulib-cache.m4. - basename = joinpath(m4base, 'gnulib-cache.m4') - tmpfile = self.assistant.tmpfilename(basename) - emit = self.gnulib_cache() - with codecs.open(tmpfile, 'wb', 'UTF-8') as file: - file.write(emit) - filename, backup, flag = self.assistant.super_update(basename, tmpfile) - if flag == 1: - if not self.config['dryrun']: - print('Updating %s (backup in %s)' % (filename, backup)) - else: # if self.config['dryrun'] - print('Update %s (backup in %s)' % (filename, backup)) - elif flag == 2: - if not self.config['dryrun']: - print('Creating %s' % filename) - else: # if self.config['dryrun']: - print('Create %s' % filename) - if emit[-2:] == '\r\n': - emit = emit[:-2] - elif emit[-1:] == '\n': - emit = emit[:-1] - print(emit) - if isfile(tmpfile): - os.remove(tmpfile) - - # Create m4/gnulib-comp.m4. - basename = joinpath(m4base, 'gnulib-comp.m4') - tmpfile = self.assistant.tmpfilename(basename) - emit = self.gnulib_comp(filetable['all']) - with codecs.open(tmpfile, 'wb', 'UTF-8') as file: - file.write(emit) - filename, backup, flag = self.assistant.super_update(basename, tmpfile) - if flag == 1: - if not self.config['dryrun']: - print('Updating %s (backup in %s)' % (filename, backup)) - else: # if self.config['dryrun'] - print('Update %s (backup in %s)' % (filename, backup)) - elif flag == 2: - if not self.config['dryrun']: - print('Creating %s' % filename) - else: # if self.config['dryrun']: - print('Create %s' % filename) - if emit[-2:] == '\r\n': - emit = emit[:-2] - elif emit[-1:] == '\n': - emit = emit[:-1] - print(emit) - if isfile(tmpfile): - os.remove(tmpfile) - - # Create tests Makefile. - inctests = self.config.checkTestFlag(TESTS['tests']) - if inctests: - basename = joinpath(testsbase, makefile_am) - tmpfile = self.assistant.tmpfilename(basename) - emit, uses_subdirs = self.emiter.lib_Makefile_am(basename, - self.moduletable['tests'], self.moduletable, self.makefiletable, - actioncmd, for_test) - with codecs.open(tmpfile, 'wb', 'UTF-8') as file: - file.write(emit) - filename, backup, flag = self.assistant.super_update(basename, tmpfile) - if flag == 1: - if not self.config['dryrun']: - print('Updating %s (backup in %s)' % (filename, backup)) - else: # if self.config['dryrun'] - print('Update %s (backup in %s)' % (filename, backup)) - elif flag == 2: - if not self.config['dryrun']: - print('Creating %s' % filename) - else: # if self.config['dryrun']: - print('Create %s' % filename) - filetable['added'] += [filename] - if isfile(tmpfile): - os.remove(tmpfile) - - # Update the .cvsignore and .gitignore files. - ignorelist = list() - filetable['added'] = sorted(set(filetable['added'])) - filetable['removed'] = sorted(set(filetable['added'])) - for file in filetable['added']: - directory, basename = os.path.split(file) - ignorelist += [tuple([directory, '|A|', basename])] - for file in filetable['removed']: - directory, basename = os.path.split(file) - ignorelist += [tuple([directory, '|R|', basename])] - last_dir = string() - last_dirs_added = list() - last_dirs_removed = list() - for row in ignorelist: - next_dir = row[0] - operand = row[1] - filename = row[2] - if next_dir != last_dir: - self._done_dir_(last_dir, last_dirs_added, last_dirs_removed) - last_dir = next_dir + os.remove(tmpfile) + + # Create m4/gnulib-comp.m4. + basename = joinpath(m4base, 'gnulib-comp.m4') + tmpfile = self.assistant.tmpfilename(basename) + emit = self.gnulib_comp(filetable['all']) + with codecs.open(tmpfile, 'wb', 'UTF-8') as file: + file.write(emit) + filename, backup, flag = self.assistant.super_update(basename, tmpfile) + if flag == 1: + if not self.config['dryrun']: + print('Updating %s (backup in %s)' % (filename, backup)) + else: # if self.config['dryrun'] + print('Update %s (backup in %s)' % (filename, backup)) + elif flag == 2: + if not self.config['dryrun']: + print('Creating %s' % filename) + else: # if self.config['dryrun']: + print('Create %s' % filename) + if emit[-2:] == '\r\n': + emit = emit[:-2] + elif emit[-1:] == '\n': + emit = emit[:-1] + print(emit) + if isfile(tmpfile): + os.remove(tmpfile) + + # Create tests Makefile. + inctests = self.config.checkTestFlag(TESTS['tests']) + if inctests: + basename = joinpath(testsbase, makefile_am) + tmpfile = self.assistant.tmpfilename(basename) + emit, uses_subdirs = self.emiter.lib_Makefile_am(basename, + self.moduletable['tests'], self.moduletable, self.makefiletable, + actioncmd, for_test) + with codecs.open(tmpfile, 'wb', 'UTF-8') as file: + file.write(emit) + filename, backup, flag = self.assistant.super_update( + basename, tmpfile) + if flag == 1: + if not self.config['dryrun']: + print('Updating %s (backup in %s)' % (filename, backup)) + else: # if self.config['dryrun'] + print('Update %s (backup in %s)' % (filename, backup)) + elif flag == 2: + if not self.config['dryrun']: + print('Creating %s' % filename) + else: # if self.config['dryrun']: + print('Create %s' % filename) + filetable['added'] += [filename] + if isfile(tmpfile): + os.remove(tmpfile) + + # Update the .cvsignore and .gitignore files. + ignorelist = list() + filetable['added'] = sorted(set(filetable['added'])) + filetable['removed'] = sorted(set(filetable['added'])) + for file in filetable['added']: + directory, basename = os.path.split(file) + ignorelist += [tuple([directory, '|A|', basename])] + for file in filetable['removed']: + directory, basename = os.path.split(file) + ignorelist += [tuple([directory, '|R|', basename])] + last_dir = string() last_dirs_added = list() last_dirs_removed = list() - if operand == '|A|': - last_dirs_added += [filename] - elif operand == '|R|': - last_dirs_removed += [filename] - self._done_dir_(last_dir, last_dirs_added, last_dirs_removed) - exit() - - # Finish the work. - print('Finished.\n') - print('You may need to add #include directives \ + for row in ignorelist: + next_dir = row[0] + operand = row[1] + filename = row[2] + if next_dir != last_dir: + self._done_dir_(last_dir, last_dirs_added, last_dirs_removed) + last_dir = next_dir + last_dirs_added = list() + last_dirs_removed = list() + if operand == '|A|': + last_dirs_added += [filename] + elif operand == '|R|': + last_dirs_removed += [filename] + self._done_dir_(last_dir, last_dirs_added, last_dirs_removed) + exit() + + # Finish the work. + print('Finished.\n') + print('You may need to add #include directives \ for the following .h files.') - modules = sorted(set([module for module in self.moduletable['base'] \ - if module in self.moduletable['main']])) - # First the #include <...> directives without #ifs, sorted for convenience, - # then the #include "..." directives without #ifs, sorted for convenience, - # then the #include directives that are surrounded by #ifs. Not sorted. - includes_angles = list() - includes_quotes = list() - includes_if = list() - for module in modules: - include = module.getInclude() - for include in include.split('\n'): - if '%s#if' % constants.NL in '%s%s' % (constants.NL, include): - includes_if += [include] - else: # if '%s#if' % constants.NL in '%s%s' % (constants.NL, include) - if 'include "' in include: - includes_quotes += [include] - else: # if 'include "' not in include - includes_angles += [include] - includes_angles = sorted(set(includes_angles)) - includes_quotes = sorted(set(includes_quotes)) - includes = includes_angles +includes_quotes +includes_if - includes = [include for include in includes if include.split()] - for include in includes: - print(' %s' % include) - - # Get link directives. - links = [module.getLink() for module in self.moduletable['main']] - links = sorted(set([link for link in links if link.strip()])) - if links: - print(''' + modules = sorted(set([module for module in self.moduletable['base'] + if module in self.moduletable['main']])) + # First the #include <...> directives without #ifs, sorted for convenience, + # then the #include "..." directives without #ifs, sorted for convenience, + # then the #include directives that are surrounded by #ifs. Not sorted. + includes_angles = list() + includes_quotes = list() + includes_if = list() + for module in modules: + include = module.getInclude() + for include in include.split('\n'): + if '%s#if' % constants.NL in '%s%s' % (constants.NL, include): + includes_if += [include] + # if '%s#if' % constants.NL in '%s%s' % (constants.NL, include) + else: + if 'include "' in include: + includes_quotes += [include] + else: # if 'include "' not in include + includes_angles += [include] + includes_angles = sorted(set(includes_angles)) + includes_quotes = sorted(set(includes_quotes)) + includes = includes_angles + includes_quotes + includes_if + includes = [include for include in includes if include.split()] + for include in includes: + print(' %s' % include) + + # Get link directives. + links = [module.getLink() for module in self.moduletable['main']] + links = sorted(set([link for link in links if link.strip()])) + if links: + print(''' You may need to use the following Makefile variables when linking. Use them in _LDADD when linking a program, or in _a_LDFLAGS or _la_LDFLAGS when linking a library.''') - for link in links: - print(' %s' % link) - - # Print reminders. - print('') - print('Don\'t forget to') - if makefile_am == 'Makefile.am': - print(' - add "%s/Makefile" to AC_CONFIG_FILES in %s,' % \ - (sourcebase, configure_ac)) - else: # if makefile_am != 'Makefile.am' - print(' - "include %s" from within "%s/Makefile.am",' % \ - (makefile, sourcebase)) - if pobase: - print(' - add "%s/Makefile.in to AC_CONFIG_FILES in %s,' % \ - (pobase, configure_ac)) - if inctests: - if makefile_am == 'Makefile.am': - print(' - add "%s/Makefile" to AC_CONFIG_FILES in %s,' % \ - (testsbase, configure_ac)) - else: # if makefile_am != 'Makefile.am' - print(' - "include %s" from within "%s/Makefile.am",' % \ - (makefile, testsbase)) - # Print makefile edits. - current_edit = int() - makefile_am_edits = self.makefiletable.count() - while current_edit != makefile_am_edits: - dictionary = self.makefiletable[current_edit] - if dictionary['var']: - print(' - mention "%s" in %s in %s,' % \ - (dictionary['val'], dictionary['var'], - joinpath(dictionary['dir'], 'Makefile.am'))) - current_edit += 1 - - # Detect position_early_after. - with codecs.open(configure_ac, 'rb', 'UTF-8') as file: - data = file.read() - match_result1 = \ - bool(compiler('^ *AC_PROG_CC_STDC', re.S | re.M).findall(data)) - match_result2 = \ - bool(compiler('^ *AC_PROG_CC_C99', re.S | re.M).findall(data)) - if match_result1: - position_early_after = 'AC_PROG_CC_STDC' - elif match_result2: - position_early_after = 'AC_PROG_CC_C99' - else: # if not any([match_result1, match_result2]) - position_early_after = 'AC_PROG_CC' - print(' - invoke %s_EARLY in %s, right after %s,' % \ - (macro_prefix, configure_ac, position_early_after)) - print(' - invoke %s_INIT in %s.' % \ - (macro_prefix, configure_ac)) - sp.call(['rm', '-rf', self.config['tempdir']], shell=False) + for link in links: + print(' %s' % link) + + # Print reminders. + print('') + print('Don\'t forget to') + if makefile_am == 'Makefile.am': + print(' - add "%s/Makefile" to AC_CONFIG_FILES in %s,' % + (sourcebase, configure_ac)) + else: # if makefile_am != 'Makefile.am' + print(' - "include %s" from within "%s/Makefile.am",' % + (makefile, sourcebase)) + if pobase: + print(' - add "%s/Makefile.in to AC_CONFIG_FILES in %s,' % + (pobase, configure_ac)) + if inctests: + if makefile_am == 'Makefile.am': + print(' - add "%s/Makefile" to AC_CONFIG_FILES in %s,' % + (testsbase, configure_ac)) + else: # if makefile_am != 'Makefile.am' + print(' - "include %s" from within "%s/Makefile.am",' % + (makefile, testsbase)) + # Print makefile edits. + current_edit = int() + makefile_am_edits = self.makefiletable.count() + while current_edit != makefile_am_edits: + dictionary = self.makefiletable[current_edit] + if dictionary['var']: + print(' - mention "%s" in %s in %s,' % + (dictionary['val'], dictionary['var'], + joinpath(dictionary['dir'], 'Makefile.am'))) + current_edit += 1 + # Detect position_early_after. + with codecs.open(configure_ac, 'rb', 'UTF-8') as file: + data = file.read() + match_result1 = \ + bool(compiler('^ *AC_PROG_CC_STDC', re.S | re.M).findall(data)) + match_result2 = \ + bool(compiler('^ *AC_PROG_CC_C99', re.S | re.M).findall(data)) + if match_result1: + position_early_after = 'AC_PROG_CC_STDC' + elif match_result2: + position_early_after = 'AC_PROG_CC_C99' + else: # if not any([match_result1, match_result2]) + position_early_after = 'AC_PROG_CC' + print(' - invoke %s_EARLY in %s, right after %s,' % + (macro_prefix, configure_ac, position_early_after)) + print(' - invoke %s_INIT in %s.' % + (macro_prefix, configure_ac)) + sp.call(['rm', '-rf', self.config['tempdir']], shell=False) diff --git a/pygnulib/GLInfo.py b/pygnulib/GLInfo.py index 646b20cf65..71f19ca2c9 100644 --- a/pygnulib/GLInfo.py +++ b/pygnulib/GLInfo.py @@ -48,72 +48,72 @@ relpath = os.path.relpath # Define GLInfo class #=============================================================================== class GLInfo(object): - '''This class is used to get fromatted information about gnulib-tool. - This information is mainly used in stdout messages, but can be used - anywhere else. The return values are not the same as for the module, - but still depends on them.''' - - def __repr__(self): - '''x.__repr__ <==> repr(x)''' - result = '' % hex(id(self)) - return(result) - - def package(self): - '''Return formatted string which contains name of the package.''' - result = 'GNU gnulib' - return(result) - - def authors(self): - '''Return formatted string which contains authors. - The special __author__ variable is used (type is list).''' - result = string() - for item in __author__: - if item == __author__[-2]: - result += '%s ' % item - elif item == __author__[-1]: - result += 'and %s' % item - else: - result += '%s, ' % item - return(result) - - def license(self): - '''Return formatted string which contains license and its description.''' - result = 'License GPLv3+: GNU GPL version 3 or later' - result += ' \n' - result += 'This is free software: you are free' - result += ' to change and redistribute it.\n' - result += 'There is NO WARRANTY, to the extent permitted by law.' - return(result) - - def copyright(self): - '''Return formatted string which contains copyright. - The special __copyright__ variable is used (type is str).''' - result = 'Copyright (C) %s' % __copyright__ - return(result) - - def date(self): - '''Return formatted string which contains date and time in GMT format.''' - if isdir(DIRS['git']): - counter = int() # Create counter - result = string() # Create string - args = ['git', 'log'] - result = sp.check_output(args).decode("UTF-8") - # Get date as "Fri Mar 21 07:16:51 2008 -0600" from string - pattern = re.compile('Date:[\t ]*(.*?)$', re.S | re.M) - result = pattern.findall(result)[0] - # Turn "Fri Mar 21 07:16:51 2008 -0600" into "Mar 21 2008 07:16:51 -0600" - pattern = re.compile('^[^ ]* ([^ ]*) ([0-9]*) ([0-9:]*) ([0-9]*) ') - result = pattern.sub('\\1 \\2 \\4 \\3 ', result) - # Use GNU date to compute the time in GMT - args = ['date', '-d', result, '-u', '+%Y-%m-%d %H:%M:%S'] - proc = sp.check_output(args) - result = string(proc, "UTF-8") - result = result.rstrip(os.linesep) - return(result) - - def usage(self): - '''Show help message.''' - result = '''\ + '''This class is used to get fromatted information about gnulib-tool. + This information is mainly used in stdout messages, but can be used + anywhere else. The return values are not the same as for the module, + but still depends on them.''' + + def __repr__(self): + '''x.__repr__ <==> repr(x)''' + result = '' % hex(id(self)) + return(result) + + def package(self): + '''Return formatted string which contains name of the package.''' + result = 'GNU gnulib' + return(result) + + def authors(self): + '''Return formatted string which contains authors. + The special __author__ variable is used (type is list).''' + result = string() + for item in __author__: + if item == __author__[-2]: + result += '%s ' % item + elif item == __author__[-1]: + result += 'and %s' % item + else: + result += '%s, ' % item + return(result) + + def license(self): + '''Return formatted string which contains license and its description.''' + result = 'License GPLv3+: GNU GPL version 3 or later' + result += ' \n' + result += 'This is free software: you are free' + result += ' to change and redistribute it.\n' + result += 'There is NO WARRANTY, to the extent permitted by law.' + return(result) + + def copyright(self): + '''Return formatted string which contains copyright. + The special __copyright__ variable is used (type is str).''' + result = 'Copyright (C) %s' % __copyright__ + return(result) + + def date(self): + '''Return formatted string which contains date and time in GMT format.''' + if isdir(DIRS['git']): + counter = int() # Create counter + result = string() # Create string + args = ['git', 'log'] + result = sp.check_output(args).decode("UTF-8") + # Get date as "Fri Mar 21 07:16:51 2008 -0600" from string + pattern = re.compile('Date:[\t ]*(.*?)$', re.S | re.M) + result = pattern.findall(result)[0] + # Turn "Fri Mar 21 07:16:51 2008 -0600" into "Mar 21 2008 07:16:51 -0600" + pattern = re.compile('^[^ ]* ([^ ]*) ([0-9]*) ([0-9:]*) ([0-9]*) ') + result = pattern.sub('\\1 \\2 \\4 \\3 ', result) + # Use GNU date to compute the time in GMT + args = ['date', '-d', result, '-u', '+%Y-%m-%d %H:%M:%S'] + proc = sp.check_output(args) + result = string(proc, "UTF-8") + result = result.rstrip(os.linesep) + return(result) + + def usage(self): + '''Show help message.''' + result = '''\ Usage: gnulib-tool --list gnulib-tool --find filename gnulib-tool --import [module1 ... moduleN] @@ -287,16 +287,15 @@ Options for --import, --add/remove-import, --update: don't replace copyright notices. Report bugs to .''' - return(result) - - def version(self): - '''Return formatted string which contains git or CVS version.''' - if isdir(DIRS['git']): - version_gen = joinpath(DIRS['build-aux'], 'git-version-gen') - args = [version_gen, DIRS['root']] - result = sp.check_output(args).decode("UTF-8") - result = result.strip() - if result == 'UNKNOWN': - result = string() - return(result) + return(result) + def version(self): + '''Return formatted string which contains git or CVS version.''' + if isdir(DIRS['git']): + version_gen = joinpath(DIRS['build-aux'], 'git-version-gen') + args = [version_gen, DIRS['root']] + result = sp.check_output(args).decode("UTF-8") + result = result.strip() + if result == 'UNKNOWN': + result = string() + return(result) diff --git a/pygnulib/GLMakefileTable.py b/pygnulib/GLMakefileTable.py index 3c0e1d4e86..2ecc2686bb 100644 --- a/pygnulib/GLMakefileTable.py +++ b/pygnulib/GLMakefileTable.py @@ -52,82 +52,81 @@ filter_filelist = constants.filter_filelist # Define GLMakefileTable class #=============================================================================== class GLMakefileTable(object): - '''This class is used to edit Makefile and store edits as table. - When user creates Makefile, he may need to use this class.''' - - def __init__(self, config): - '''GLMakefileTable.__init__(config) -> GLMakefileTable - - Create GLMakefileTable instance.''' - if type(config) is not GLConfig: - raise(TypeError('config must be a GLConfig, not %s' % \ - type(config).__name__)) - self.config = config - self.table = list() - - def __getitem__(self, y): - '''x.__getitem__(y) = x[y]''' - if type(y) is not int: - raise(TypeError('indices must be integers, not %s' % \ - type(y).__name__)) - result = self.table[y] - return(dict(result)) - - def editor(self, dir, var, val): - '''GLMakefileTable.editor(dir, var, val) - - This method is used to remember that ${dir}Makefile.am needs to be edited - to that ${var} mentions ${val}.''' - if type(dir) is bytes or type(dir) is string: - if type(dir) is bytes: - dir = dir.decode(ENCS['default']) - else: # if dir has not bytes or string type - raise(TypeError( - 'dir must be a string, not %s' % (type(dir).__name__))) - if type(var) is bytes or type(var) is string: - if type(var) is bytes: - var = var.decode(ENCS['default']) - else: # if var has not bytes or string type - raise(TypeError( - 'var must be a string, not %s' % (type(var).__name__))) - if type(val) is bytes or type(val) is string: - if type(val) is bytes: - val = val.decode(ENCS['default']) - else: # if val has not bytes or string type - raise(TypeError( - 'val must be a string, not %s' % (type(val).__name__))) - dictionary = {'dir': dir, 'var': var, 'val': val} - self.table += [dictionary] - - def parent(self): - '''GLMakefileTable.parent() - - Add a special row to Makefile.am table with the first parent directory - which contains or will contain Makefile.am file. - GLConfig: sourcebase, m4base, testsbase, testflags, makefile.''' - m4base = self.config['m4base'] - sourcebase = self.config['sourcebase'] - testsbase = self.config['testsbase'] - makefile = self.config['makefile'] - inctests = self.config.checkTestFlag(TESTS['tests']) - dir1 = string('%s%s' % (m4base, os.path.sep)) - mfd = string('Makefile.am') - if not makefile: - mfx = string('Makefile.am') - else: # if makefile - mfx = makefile - dir2 = string() - while dir1 and \ - (joinpath(self.config['destdir'], dir1, mfd) or \ - joinpath(dir1, mfd) == joinpath(sourcebase, mfx) or \ - (inctests and joinpath(dir1, mfd) == joinpath(testsbase, mfx))): - dir2 = joinpath(os.path.basename(dir1), dir2) - dir1 = os.path.dirname(dir1) - self.editor(dir1, 'EXTRA_DIST', joinpath(dir2, 'gnulib-cache.m4')) - - def count(self): - '''GLMakefileTable.count() -> int - - Count number of edits which were applied.''' - return(len(self.table)) + '''This class is used to edit Makefile and store edits as table. + When user creates Makefile, he may need to use this class.''' + def __init__(self, config): + '''GLMakefileTable.__init__(config) -> GLMakefileTable + + Create GLMakefileTable instance.''' + if type(config) is not GLConfig: + raise(TypeError('config must be a GLConfig, not %s' % + type(config).__name__)) + self.config = config + self.table = list() + + def __getitem__(self, y): + '''x.__getitem__(y) = x[y]''' + if type(y) is not int: + raise(TypeError('indices must be integers, not %s' % + type(y).__name__)) + result = self.table[y] + return(dict(result)) + + def editor(self, dir, var, val): + '''GLMakefileTable.editor(dir, var, val) + + This method is used to remember that ${dir}Makefile.am needs to be edited + to that ${var} mentions ${val}.''' + if type(dir) is bytes or type(dir) is string: + if type(dir) is bytes: + dir = dir.decode(ENCS['default']) + else: # if dir has not bytes or string type + raise(TypeError( + 'dir must be a string, not %s' % (type(dir).__name__))) + if type(var) is bytes or type(var) is string: + if type(var) is bytes: + var = var.decode(ENCS['default']) + else: # if var has not bytes or string type + raise(TypeError( + 'var must be a string, not %s' % (type(var).__name__))) + if type(val) is bytes or type(val) is string: + if type(val) is bytes: + val = val.decode(ENCS['default']) + else: # if val has not bytes or string type + raise(TypeError( + 'val must be a string, not %s' % (type(val).__name__))) + dictionary = {'dir': dir, 'var': var, 'val': val} + self.table += [dictionary] + + def parent(self): + '''GLMakefileTable.parent() + + Add a special row to Makefile.am table with the first parent directory + which contains or will contain Makefile.am file. + GLConfig: sourcebase, m4base, testsbase, testflags, makefile.''' + m4base = self.config['m4base'] + sourcebase = self.config['sourcebase'] + testsbase = self.config['testsbase'] + makefile = self.config['makefile'] + inctests = self.config.checkTestFlag(TESTS['tests']) + dir1 = string('%s%s' % (m4base, os.path.sep)) + mfd = string('Makefile.am') + if not makefile: + mfx = string('Makefile.am') + else: # if makefile + mfx = makefile + dir2 = string() + while dir1 and \ + (joinpath(self.config['destdir'], dir1, mfd) or + joinpath(dir1, mfd) == joinpath(sourcebase, mfx) or + (inctests and joinpath(dir1, mfd) == joinpath(testsbase, mfx))): + dir2 = joinpath(os.path.basename(dir1), dir2) + dir1 = os.path.dirname(dir1) + self.editor(dir1, 'EXTRA_DIST', joinpath(dir2, 'gnulib-cache.m4')) + + def count(self): + '''GLMakefileTable.count() -> int + + Count number of edits which were applied.''' + return(len(self.table)) diff --git a/pygnulib/GLModuleSystem.py b/pygnulib/GLModuleSystem.py index 34501e20e2..09ce5f6bf4 100644 --- a/pygnulib/GLModuleSystem.py +++ b/pygnulib/GLModuleSystem.py @@ -52,1216 +52,1229 @@ filter_filelist = constants.filter_filelist # Define GLModuleSystem class #=============================================================================== class GLModuleSystem(object): - '''GLModuleSystem is used to operate with module system using dynamic - searching and patching.''' - - def __init__(self, config): - '''GLModuleSystem.__init__(config) -> GLModuleSystem - - Create new GLModuleSystem instance. Some functions use GLFileSystem class - to look up a file in localdir or gnulib directories, or combine it through - 'patch' utility.''' - self.args = dict() - if type(config) is not GLConfig: - raise(TypeError('config must be a GLConfig, not %s' % \ - type(config).__name__)) - self.config = config - self.filesystem = GLFileSystem(self.config) - - def __repr__(self): - '''x.__repr__ <==> repr(x)''' - result = '' % hex(id(self)) - return(result) - - def exists(self, module): - '''GLModuleSystem.exists(module) -> bool - - Check whether the given module exists. - GLConfig: localdir.''' - if type(module) is bytes or string: - if type(module) is bytes: - module = module.decode(ENCS['default']) - else: # if module has not bytes or string type - raise(TypeError( - 'module must be a string, not %s' % type(module).__name__)) - result = bool() - badnames = ['CVS', 'ChangeLog', 'COPYING', 'README', 'TEMPLATE', - 'TEMPLATE-EXTENDED', 'TEMPLATE-TESTS'] - if isfile(joinpath(DIRS['modules'], module)) or \ - all([ # Begin all(iterable) function - self.config['localdir'], - isdir(joinpath(self.config['localdir'], 'modules')), - isfile(joinpath(self.config['localdir'], 'modules', module)) - ]): # Close all(iterable) function - if module not in badnames: - result = True - return(result) - - def find(self, module): - '''GLModuleSystem.find(module) -> GLModule - - Find the given module.''' - if type(module) is bytes or string: - if type(module) is bytes: - module = module.decode(ENCS['default']) - else: # if module has not bytes or string type - raise(TypeError( - 'module must be a string, not %s' % type(module).__name__)) - if self.exists(module): - path, istemp = self.filesystem.lookup(joinpath('modules', module)) - result = GLModule(self.config, path, istemp) - return(result) - else: # if not self.exists(module) - if self.config['errors']: - raise(GLError(3, module)) - else: # if not self.config['errors'] - sys.stderr.write('gnulib-tool: warning: ') - sys.stderr.write('file %s does not exist\n' % str(module)) - - def list(self): - '''GLModuleSystem.list() -> list - - Return the available module names as tuple. We could use a combination - of os.walk() function and re module. However, it takes too much time to - complete, so this version uses subprocess to run shell commands.''' - result = string() - listing = list() - localdir = self.config['localdir'] - find_args = ['find', 'modules', '-type', 'f', '-print'] - sed_args = \ - [ - 'sed', - '-e', r's,^modules/,,', - '-e', r'/^CVS\//d', - '-e', r'/\/CVS\//d', - '-e', r'/^ChangeLog$/d', - '-e', r'/\/ChangeLog$/d', - '-e', r'/^COPYING$/d', - '-e', r'/\/COPYING$/d', - '-e', r'/^README$/d', - '-e', r'/\/README$/d', - '-e', r'/^TEMPLATE$/d', - '-e', r'/^TEMPLATE-EXTENDED$/d', - '-e', r'/^TEMPLATE-TESTS$/d', - '-e', r'/^\..*/d', - '-e', r'/~$/d', - '-e', r'/-tests$/d', - ] - - # Read modules from gnulib root directory. - os.chdir(constants.DIRS['root']) - find = sp.Popen(find_args, stdout=sp.PIPE) - result += find.stdout.read().decode("UTF-8") - - # Read modules from local directory. - if localdir and isdir(joinpath(localdir, 'modules')): - os.chdir(localdir) - find = sp.Popen(find_args, stdout=sp.PIPE) - result += find.stdout.read().decode("UTF-8") - sed_args += ['-e', r's,\.diff$,,'] - - # Save the list of the modules to file. - os.chdir(DIRS['cwd']) - path = joinpath(self.config['tempdir'], 'list') - with codecs.open(path, 'wb', 'UTF-8') as file: - file.write(result) - - # Filter the list of the modules. - stdin = codecs.open(path, 'rb', 'UTF-8') - sed = sp.Popen(sed_args, stdin=stdin, stdout=sp.PIPE) - result = sed.stdout.read().decode("UTF-8") - stdin.close(); os.remove(path) - listing = [line for line in result.split('\n') if line.strip()] - listing = sorted(set(listing)) - return(listing) + '''GLModuleSystem is used to operate with module system using dynamic + searching and patching.''' + + def __init__(self, config): + '''GLModuleSystem.__init__(config) -> GLModuleSystem + + Create new GLModuleSystem instance. Some functions use GLFileSystem class + to look up a file in localdir or gnulib directories, or combine it through + 'patch' utility.''' + self.args = dict() + if type(config) is not GLConfig: + raise(TypeError('config must be a GLConfig, not %s' % + type(config).__name__)) + self.config = config + self.filesystem = GLFileSystem(self.config) + + def __repr__(self): + '''x.__repr__ <==> repr(x)''' + result = '' % hex(id(self)) + return(result) + + def exists(self, module): + '''GLModuleSystem.exists(module) -> bool + + Check whether the given module exists. + GLConfig: localdir.''' + if type(module) is bytes or string: + if type(module) is bytes: + module = module.decode(ENCS['default']) + else: # if module has not bytes or string type + raise(TypeError( + 'module must be a string, not %s' % type(module).__name__)) + result = bool() + badnames = ['CVS', 'ChangeLog', 'COPYING', 'README', 'TEMPLATE', + 'TEMPLATE-EXTENDED', 'TEMPLATE-TESTS'] + if isfile(joinpath(DIRS['modules'], module)) or \ + all([ # Begin all(iterable) function + self.config['localdir'], + isdir(joinpath(self.config['localdir'], 'modules')), + isfile( + joinpath(self.config['localdir'], 'modules', module)) + ]): # Close all(iterable) function + if module not in badnames: + result = True + return(result) + + def find(self, module): + '''GLModuleSystem.find(module) -> GLModule + + Find the given module.''' + if type(module) is bytes or string: + if type(module) is bytes: + module = module.decode(ENCS['default']) + else: # if module has not bytes or string type + raise(TypeError( + 'module must be a string, not %s' % type(module).__name__)) + if self.exists(module): + path, istemp = self.filesystem.lookup(joinpath('modules', module)) + result = GLModule(self.config, path, istemp) + return(result) + else: # if not self.exists(module) + if self.config['errors']: + raise(GLError(3, module)) + else: # if not self.config['errors'] + sys.stderr.write('gnulib-tool: warning: ') + sys.stderr.write('file %s does not exist\n' % str(module)) + + def list(self): + '''GLModuleSystem.list() -> list + + Return the available module names as tuple. We could use a combination + of os.walk() function and re module. However, it takes too much time to + complete, so this version uses subprocess to run shell commands.''' + result = string() + listing = list() + localdir = self.config['localdir'] + find_args = ['find', 'modules', '-type', 'f', '-print'] + sed_args = \ + [ + 'sed', + '-e', r's,^modules/,,', + '-e', r'/^CVS\//d', + '-e', r'/\/CVS\//d', + '-e', r'/^ChangeLog$/d', + '-e', r'/\/ChangeLog$/d', + '-e', r'/^COPYING$/d', + '-e', r'/\/COPYING$/d', + '-e', r'/^README$/d', + '-e', r'/\/README$/d', + '-e', r'/^TEMPLATE$/d', + '-e', r'/^TEMPLATE-EXTENDED$/d', + '-e', r'/^TEMPLATE-TESTS$/d', + '-e', r'/^\..*/d', + '-e', r'/~$/d', + '-e', r'/-tests$/d', + ] + + # Read modules from gnulib root directory. + os.chdir(constants.DIRS['root']) + find = sp.Popen(find_args, stdout=sp.PIPE) + result += find.stdout.read().decode("UTF-8") + + # Read modules from local directory. + if localdir and isdir(joinpath(localdir, 'modules')): + os.chdir(localdir) + find = sp.Popen(find_args, stdout=sp.PIPE) + result += find.stdout.read().decode("UTF-8") + sed_args += ['-e', r's,\.diff$,,'] + + # Save the list of the modules to file. + os.chdir(DIRS['cwd']) + path = joinpath(self.config['tempdir'], 'list') + with codecs.open(path, 'wb', 'UTF-8') as file: + file.write(result) + + # Filter the list of the modules. + stdin = codecs.open(path, 'rb', 'UTF-8') + sed = sp.Popen(sed_args, stdin=stdin, stdout=sp.PIPE) + result = sed.stdout.read().decode("UTF-8") + stdin.close() + os.remove(path) + listing = [line for line in result.split('\n') if line.strip()] + listing = sorted(set(listing)) + return(listing) #=============================================================================== # Define GLModule class #=============================================================================== class GLModule(object): - '''GLModule is used to create a module object from the file with the given - path. GLModule can get all information about module, get its dependencies, - files, etc.''' - - def __init__(self, config, module, patched=False): - '''GLModule.__init__(config, module[, patched]) -> GLModule - - Create new GLModule instance. Arguments are module and patched, where - module is a string representing the path to the module and patched is a - bool indicating that module was created after applying patch.''' - self.args = dict() - self.cache = dict() - self.content = string() - if type(config) is not GLConfig: - raise(TypeError('config must be a GLConfig, not %s' % \ - type(config).__name__)) - if type(module) is bytes or type(module) is string: - if type(module) is bytes: - module = module.decode(ENCS['default']) - else: # if module has not bytes or string type - raise(TypeError('module must be a string, not %s' % \ - type(module).__name__)) - if type(patched) is not bool: - raise(TypeError('patched must be a bool, not %s' % \ - type(module).__name__)) - self.module = module - self.patched = patched - self.config = config - self.filesystem = GLFileSystem(self.config) - self.modulesystem = GLModuleSystem(self.config) - with codecs.open(module, 'rb', 'UTF-8') as file: - self.content = file.read() - self.regex ='(?:Description:|Comment:|Status:|Notice:|Applicability:|\ + '''GLModule is used to create a module object from the file with the given + path. GLModule can get all information about module, get its dependencies, + files, etc.''' + + def __init__(self, config, module, patched=False): + '''GLModule.__init__(config, module[, patched]) -> GLModule + + Create new GLModule instance. Arguments are module and patched, where + module is a string representing the path to the module and patched is a + bool indicating that module was created after applying patch.''' + self.args = dict() + self.cache = dict() + self.content = string() + if type(config) is not GLConfig: + raise(TypeError('config must be a GLConfig, not %s' % + type(config).__name__)) + if type(module) is bytes or type(module) is string: + if type(module) is bytes: + module = module.decode(ENCS['default']) + else: # if module has not bytes or string type + raise(TypeError('module must be a string, not %s' % + type(module).__name__)) + if type(patched) is not bool: + raise(TypeError('patched must be a bool, not %s' % + type(module).__name__)) + self.module = module + self.patched = patched + self.config = config + self.filesystem = GLFileSystem(self.config) + self.modulesystem = GLModuleSystem(self.config) + with codecs.open(module, 'rb', 'UTF-8') as file: + self.content = file.read() + self.regex = '(?:Description:|Comment:|Status:|Notice:|Applicability:|\ Files:|Depends-on:|configure\\.ac-early:|configure\\.ac:|Makefile\\.am:|\ Include:|Link:|License:|Maintainer:)' - - def __eq__(self, module): - '''x.__eq__(y) <==> x==y''' - result = bool() - if type(module) is GLModule: - if self.module == module.module: - result = True - return(result) - - def __ne__(self, module): - '''x.__ne__(y) <==> x!=y''' - result = bool() - if type(module) is GLModule: - if self.module != module.module: - result = True - return(result) - - def __ge__(self, module): - '''x.__ge__(y) <==> x>=y''' - result = bool() - if type(module) is GLModule: - if self.module >= module.module: - result = True - return(result) - - def __gt__(self, module): - '''x.__gt__(y) <==> x>y''' - result = bool() - if type(module) is GLModule: - if self.module > module.module: - result = True - return(result) - - def __hash__(self): - '''x.__hash__() <==> hash(x)''' - module = hash(self.module) - patched = hash(self.patched) - result = module^patched - return(result) - - def __le__(self, module): - '''x.__le__(y) <==> x<=y''' - result = bool() - if type(module) is GLModule: - if self.module <= module.module: - result = True - return(result) - - def __lt__(self, module): - '''x.__lt__(y) <==> x str(x)''' - result = self.getName() - return(result) - - def __repr__(self): - '''x.__repr__ <==> repr(x)''' - result = '' % \ - (repr(self.getName()), hex(id(self))) - return(result) - - def getName(self): - '''GLModule.getName() -> string - - Return the name of the module.''' - pattern = compiler(joinpath('modules', '(.*?)$')) - result = pattern.findall(self.module)[0] - return(result) - - def isPatched(self): - '''GLModule.isPatched() -> bool - - Check whether module was created after applying patch.''' - return(self.patched) - - def isTests(self): - '''GLModule.isTests() -> bool - - Check whether module is a -tests version of module.''' - result = self.getName().endswith('-tests') - return(result) - - def isNonTests(self): - '''GLModule.isTests() -> bool - - Check whether module is not a -tests version of module.''' - result = not(self.isTests()) - return(result) - - def getTestsName(self): - '''Return -tests version of the module name.''' - result = self.getName() - if not result.endswith('-tests'): - result += '-tests' - return(result) - - def getTestsModule(self): - '''Return -tests version of the module as GLModule.''' - result = self.modulesystem.find(self.getTestsName()) - return(result) - - def getShellFunc(self): - '''GLModule.getShellFunc() -> string - - Computes the shell function name that will contain the m4 macros for the - module.''' - isalnum = True - macro_prefix = self.config['macro_prefix'] - for char in str(module): - if char not in constants.ALPHANUMERIC: - isalnum = False - break - if isalnum: - module = str(self) - else: # if not isalnum - module = '%s\n' % str(self) - if type(module) is string: - module = module.encode(ENCS['default']) - module = hashlib.md5(module).hexdigest() - result = 'func_%s_gnulib_m4code_%s' % (macro_prefix, module) - if type(result) is bytes: - result = result.decode(ENCS['default']) - return(result) - - def getShellVar(self): - '''GLModule.getShellVar() -> string - - Compute the shell variable name the will be set to true once the m4 macros - for the module have been executed.''' - isalnum = True - macro_prefix = self.config['macro_prefix'] - for char in str(module): - if char not in constants.ALPHANUMERIC: - isalnum = False - break - if isalnum: - module = str(self) - else: # if not isalnum - module = '%s\n' % str(self) - if type(module) is string: - module = module.encode(ENCS['default']) - module = hashlib.md5(module).hexdigest() - result = '%s_gnulib_enabled_%s' % (macro_prefix, module) - if type(result) is bytes: - result = result.decode(ENCS['default']) - return(result) - - def getConditionalName(self): - '''GLModule.getConditionalName() -> string - - Return the automake conditional name. - GLConfig: macro_prefix.''' - macro_prefix = self.config['macro_prefix'] - nonascii = \ - [ # Begin to filter non-ascii chars - char for char in self.getName() if char not in \ - 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_' - ] # Finish to filter non-ascii chars - if nonascii: - name = self.getName().encode(ENCS['default']) - name = hashlib.md5(name).hexdigest() - conditional = '%s_GNULIB_ENABLED_%s' % (macro_prefix, name) - else: # if not nonascii - result = '%s_GNULIB_ENABLED_%s' (macro_prefix, name) - if type(result) is bytes: - result = result.decode(ENCS['default']) - return(result) - - def getDescription(self): - '''GLModule.getDescription() -> string - - Return description of the module.''' - section = 'Description:' - if 'description' not in self.cache: - if section not in self.content: - result = string() - else: # if section in self.content - pattern = '^%s[\t ]*(.*?)%s' % (section, self.regex) - pattern = compiler(pattern, re.S | re.M) - result = pattern.findall(self.content) - if type(result) is list: - if not result: - result = string() - else: # if result - result = result[-1] - result = result.strip() - self.cache['description'] = result - return(self.cache['description']) - - def getComment(self): - '''GLModule.getComment() -> string - - Return comment to module.''' - section = 'Comment:' - if 'comment' not in self.cache: - if section not in self.content: - result = string() - else: # if section in self.content - pattern = '^%s[\t ]*(.*?)%s' % (section, self.regex) - pattern = compiler(pattern, re.S | re.M) - result = pattern.findall(self.content) - if type(result) is list: - if not result: - result = string() - else: # if result - result = result[-1] - result = result.strip() - self.cache['comment'] = result - return(self.cache['comment']) - - def getStatus(self): - '''GLModule.getStatus() -> string - - Return module status.''' - section = 'Status:' - if 'status' not in self.cache: - if section not in self.content: - result = string() - else: # if section in self.content - snippet = self.content.split(section)[-1] - snippet = snippet.replace('\r\n', '\n') - lines = ['%s\n' % line for line in snippet.split('\n')] - parts = list() - for line in lines: - regex = '^(Description|Comment|Status|Notice|Applicability|' - regex += 'Files|Depends-on|configure\\.ac-early|configure\\.ac|' - regex += 'Makefile\\.am|Include|Link|License|Maintainer):$' - pattern = compiler(regex) - findflag = pattern.findall(line) - if findflag: - break - parts += [line] - result = [part.strip() for part in parts if part.strip()] - self.cache['status'] = list(result) - return(list(self.cache['status'])) - - def getNotice(self): - '''GLModule.getNotice() -> string - - Return notice to module.''' - section = 'Notice:' - if 'notice' not in self.cache: - if section not in self.content: - result = string() - else: # if section in self.content - snippet = self.content.split(section)[-1] - snippet = snippet.replace('\r\n', '\n') - lines = ['%s\n' % line for line in snippet.split('\n')] - parts = list() - for line in lines: - regex = '^(Description|Comment|Status|Notice|Applicability|' - regex += 'Files|Depends-on|configure\\.ac-early|configure\\.ac|' - regex += 'Makefile\\.am|Include|Link|License|Maintainer):$' - pattern = compiler(regex) - findflag = pattern.findall(line) - if findflag: - break - parts += [line] - result = ''.join(parts) - self.cache['notice'] = result - return(self.cache['notice']) - - def getApplicability(self): - '''GLModule.getApplicability() -> string - - Return applicability of module.''' - section = 'Applicability:' - if 'applicability' not in self.cache: - if section not in self.content: - result = string() - else: # if section in self.content - snippet = self.content.split(section)[-1] - snippet = snippet.replace('\r\n', '\n') - lines = ['%s\n' % line for line in snippet.split('\n')] - parts = list() - for line in lines: - regex = '^(Description|Comment|Status|Notice|Applicability|' - regex += 'Files|Depends-on|configure\\.ac-early|configure\\.ac|' - regex += 'Makefile\\.am|Include|Link|License|Maintainer):$' - pattern = compiler(regex) - findflag = pattern.findall(line) - if findflag: - break - parts += [line] - parts = [part.strip() for part in parts] - result = ''.join(parts) - if not result.strip(): - if self.getName().endswith('-tests'): - result = 'tests' - else: # if not self.getName().endswith('-tests') - result = 'main' - if type(result) is bytes: - result = result.decode(ENCS['default']) - result = result.strip() - self.cache['applicability'] = result - return(self.cache['applicability']) - - def getFiles(self): - '''GLModule.getFiles() -> list - - Return list of files. - GLConfig: ac_version.''' - ac_version = self.config['ac_version'] - section = 'Files:' - result = list() - if 'files' not in self.cache: - if section not in self.content: + + def __eq__(self, module): + '''x.__eq__(y) <==> x==y''' + result = bool() + if type(module) is GLModule: + if self.module == module.module: + result = True + return(result) + + def __ne__(self, module): + '''x.__ne__(y) <==> x!=y''' + result = bool() + if type(module) is GLModule: + if self.module != module.module: + result = True + return(result) + + def __ge__(self, module): + '''x.__ge__(y) <==> x>=y''' + result = bool() + if type(module) is GLModule: + if self.module >= module.module: + result = True + return(result) + + def __gt__(self, module): + '''x.__gt__(y) <==> x>y''' + result = bool() + if type(module) is GLModule: + if self.module > module.module: + result = True + return(result) + + def __hash__(self): + '''x.__hash__() <==> hash(x)''' + module = hash(self.module) + patched = hash(self.patched) + result = module ^ patched + return(result) + + def __le__(self, module): + '''x.__le__(y) <==> x<=y''' + result = bool() + if type(module) is GLModule: + if self.module <= module.module: + result = True + return(result) + + def __lt__(self, module): + '''x.__lt__(y) <==> x str(x)''' + result = self.getName() + return(result) + + def __repr__(self): + '''x.__repr__ <==> repr(x)''' + result = '' % \ + (repr(self.getName()), hex(id(self))) + return(result) + + def getName(self): + '''GLModule.getName() -> string + + Return the name of the module.''' + pattern = compiler(joinpath('modules', '(.*?)$')) + result = pattern.findall(self.module)[0] + return(result) + + def isPatched(self): + '''GLModule.isPatched() -> bool + + Check whether module was created after applying patch.''' + return(self.patched) + + def isTests(self): + '''GLModule.isTests() -> bool + + Check whether module is a -tests version of module.''' + result = self.getName().endswith('-tests') + return(result) + + def isNonTests(self): + '''GLModule.isTests() -> bool + + Check whether module is not a -tests version of module.''' + result = not(self.isTests()) + return(result) + + def getTestsName(self): + '''Return -tests version of the module name.''' + result = self.getName() + if not result.endswith('-tests'): + result += '-tests' + return(result) + + def getTestsModule(self): + '''Return -tests version of the module as GLModule.''' + result = self.modulesystem.find(self.getTestsName()) + return(result) + + def getShellFunc(self): + '''GLModule.getShellFunc() -> string + + Computes the shell function name that will contain the m4 macros for the + module.''' + isalnum = True + macro_prefix = self.config['macro_prefix'] + for char in str(module): + if char not in constants.ALPHANUMERIC: + isalnum = False + break + if isalnum: + module = str(self) + else: # if not isalnum + module = '%s\n' % str(self) + if type(module) is string: + module = module.encode(ENCS['default']) + module = hashlib.md5(module).hexdigest() + result = 'func_%s_gnulib_m4code_%s' % (macro_prefix, module) + if type(result) is bytes: + result = result.decode(ENCS['default']) + return(result) + + def getShellVar(self): + '''GLModule.getShellVar() -> string + + Compute the shell variable name the will be set to true once the m4 macros + for the module have been executed.''' + isalnum = True + macro_prefix = self.config['macro_prefix'] + for char in str(module): + if char not in constants.ALPHANUMERIC: + isalnum = False + break + if isalnum: + module = str(self) + else: # if not isalnum + module = '%s\n' % str(self) + if type(module) is string: + module = module.encode(ENCS['default']) + module = hashlib.md5(module).hexdigest() + result = '%s_gnulib_enabled_%s' % (macro_prefix, module) + if type(result) is bytes: + result = result.decode(ENCS['default']) + return(result) + + def getConditionalName(self): + '''GLModule.getConditionalName() -> string + + Return the automake conditional name. + GLConfig: macro_prefix.''' + macro_prefix = self.config['macro_prefix'] + nonascii = \ + [ # Begin to filter non-ascii chars + char for char in self.getName() if char not in \ + 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_' + ] # Finish to filter non-ascii chars + if nonascii: + name = self.getName().encode(ENCS['default']) + name = hashlib.md5(name).hexdigest() + conditional = '%s_GNULIB_ENABLED_%s' % (macro_prefix, name) + else: # if not nonascii + result = '%s_GNULIB_ENABLED_%s' (macro_prefix, name) + if type(result) is bytes: + result = result.decode(ENCS['default']) + return(result) + + def getDescription(self): + '''GLModule.getDescription() -> string + + Return description of the module.''' + section = 'Description:' + if 'description' not in self.cache: + if section not in self.content: + result = string() + else: # if section in self.content + pattern = '^%s[\t ]*(.*?)%s' % (section, self.regex) + pattern = compiler(pattern, re.S | re.M) + result = pattern.findall(self.content) + if type(result) is list: + if not result: + result = string() + else: # if result + result = result[-1] + result = result.strip() + self.cache['description'] = result + return(self.cache['description']) + + def getComment(self): + '''GLModule.getComment() -> string + + Return comment to module.''' + section = 'Comment:' + if 'comment' not in self.cache: + if section not in self.content: + result = string() + else: # if section in self.content + pattern = '^%s[\t ]*(.*?)%s' % (section, self.regex) + pattern = compiler(pattern, re.S | re.M) + result = pattern.findall(self.content) + if type(result) is list: + if not result: + result = string() + else: # if result + result = result[-1] + result = result.strip() + self.cache['comment'] = result + return(self.cache['comment']) + + def getStatus(self): + '''GLModule.getStatus() -> string + + Return module status.''' + section = 'Status:' + if 'status' not in self.cache: + if section not in self.content: + result = string() + else: # if section in self.content + snippet = self.content.split(section)[-1] + snippet = snippet.replace('\r\n', '\n') + lines = ['%s\n' % line for line in snippet.split('\n')] + parts = list() + for line in lines: + regex = '^(Description|Comment|Status|Notice|Applicability|' + regex += 'Files|Depends-on|configure\\.ac-early|configure\\.ac|' + regex += 'Makefile\\.am|Include|Link|License|Maintainer):$' + pattern = compiler(regex) + findflag = pattern.findall(line) + if findflag: + break + parts += [line] + result = [part.strip() for part in parts if part.strip()] + self.cache['status'] = list(result) + return(list(self.cache['status'])) + + def getNotice(self): + '''GLModule.getNotice() -> string + + Return notice to module.''' + section = 'Notice:' + if 'notice' not in self.cache: + if section not in self.content: + result = string() + else: # if section in self.content + snippet = self.content.split(section)[-1] + snippet = snippet.replace('\r\n', '\n') + lines = ['%s\n' % line for line in snippet.split('\n')] + parts = list() + for line in lines: + regex = '^(Description|Comment|Status|Notice|Applicability|' + regex += 'Files|Depends-on|configure\\.ac-early|configure\\.ac|' + regex += 'Makefile\\.am|Include|Link|License|Maintainer):$' + pattern = compiler(regex) + findflag = pattern.findall(line) + if findflag: + break + parts += [line] + result = ''.join(parts) + self.cache['notice'] = result + return(self.cache['notice']) + + def getApplicability(self): + '''GLModule.getApplicability() -> string + + Return applicability of module.''' + section = 'Applicability:' + if 'applicability' not in self.cache: + if section not in self.content: + result = string() + else: # if section in self.content + snippet = self.content.split(section)[-1] + snippet = snippet.replace('\r\n', '\n') + lines = ['%s\n' % line for line in snippet.split('\n')] + parts = list() + for line in lines: + regex = '^(Description|Comment|Status|Notice|Applicability|' + regex += 'Files|Depends-on|configure\\.ac-early|configure\\.ac|' + regex += 'Makefile\\.am|Include|Link|License|Maintainer):$' + pattern = compiler(regex) + findflag = pattern.findall(line) + if findflag: + break + parts += [line] + parts = [part.strip() for part in parts] + result = ''.join(parts) + if not result.strip(): + if self.getName().endswith('-tests'): + result = 'tests' + else: # if not self.getName().endswith('-tests') + result = 'main' + if type(result) is bytes: + result = result.decode(ENCS['default']) + result = result.strip() + self.cache['applicability'] = result + return(self.cache['applicability']) + + def getFiles(self): + '''GLModule.getFiles() -> list + + Return list of files. + GLConfig: ac_version.''' + ac_version = self.config['ac_version'] + section = 'Files:' result = list() - else: # if section in self.content - snippet = self.content.split(section)[-1] - snippet = snippet.replace('\r\n', '\n') - lines = ['%s\n' % line for line in snippet.split('\n')] - parts = list() - for line in lines: - regex = '^(Description|Comment|Status|Notice|Applicability|' - regex += 'Files|Depends-on|configure\\.ac-early|configure\\.ac|' - regex += 'Makefile\\.am|Include|Link|License|Maintainer):$' - pattern = compiler(regex) - findflag = pattern.findall(line) - if findflag: - break - parts += [line] - result = [part.strip() for part in parts if part.strip()] - result += [joinpath('m4', '00gnulib.m4')] - result += [joinpath('m4', 'gnulib-common.m4')] - if ac_version == 2.59: - result += [joinpath('m4', 'onceonly.m4')] - self.cache['files'] = list(result) - return(list(self.cache['files'])) - - def getDependencies(self): - '''GLModule.getDependencies() -> list - - Return list of dependencies. - GLConfig: localdir.''' - localdir = self.config['localdir'] - result = list() - section = 'Depends-on:' - if 'dependencies' not in self.cache: - if section not in self.content: - depmodules = list() - else: # if section in self.content - snippet = self.content.split(section)[-1] - snippet = snippet.replace('\r\n', '\n') - lines = ['%s\n' % line for line in snippet.split('\n')] - parts = list() - for line in lines: - regex = '^(Description|Comment|Status|Notice|Applicability|' - regex += 'Files|Depends-on|configure\\.ac-early|configure\\.ac|' - regex += 'Makefile\\.am|Include|Link|License|Maintainer):$' - pattern = compiler(regex) - findflag = pattern.findall(line) - if findflag: - break - parts += [line] - modules = ''.join(parts) - modules = [line for line in modules.split('\n') if line.strip()] - modules = [module for module in modules if not module.startswith('#')] - for line in modules: - split = [part for part in line.split(' ') if part.strip()] - if len(split) == 1: - module = line.strip() - condition = None - else: # if len(split) != 1 - module = split[0] - condition = split[1] - if type(condition) is bytes: - condition = condition.decode(ENCS['default']) - result += [tuple([self.modulesystem.find(module), condition])] - self.cache['dependencies'] = result - return(list(self.cache['dependencies'])) - - def getAutoconfSnippet_Early(self): - '''GLModule.getAutoconfSnippet_Early() -> string - - Return autoconf-early snippet.''' - section = 'configure.ac-early:' - if 'autoconf-early' not in self.cache: - if section not in self.content: - result = string() - else: # if section in self.content - snippet = self.content.split(section)[-1] - snippet = snippet.replace('\r\n', '\n') - lines = ['%s\n' % line for line in snippet.split('\n')] - parts = list() - for line in lines: - regex = '^(Description|Comment|Status|Notice|Applicability|' - regex += 'Files|Depends-on|configure\\.ac-early|configure\\.ac|' - regex += 'Makefile\\.am|Include|Link|License|Maintainer):$' - pattern = compiler(regex) - findflag = pattern.findall(line) - if findflag: - break - parts += [line] - result = ''.join(parts) - self.cache['autoconf-early'] = result - return(self.cache['autoconf-early']) - - def getAutoconfSnippet(self): - '''GLModule.getAutoconfSnippet() -> string - - Return autoconf snippet.''' - section = 'configure.ac:' - if 'autoconf' not in self.cache: - if section not in self.content: - result = string() - else: # if section in self.content - snippet = self.content.split(section)[-1] - snippet = snippet.replace('\r\n', '\n') - lines = ['%s\n' % line for line in snippet.split('\n')] - parts = list() - for line in lines: - regex = '^(Description|Comment|Status|Notice|Applicability|' - regex += 'Files|Depends-on|configure\\.ac-early|configure\\.ac|' - regex += 'Makefile\\.am|Include|Link|License|Maintainer):$' - pattern = compiler(regex) - findflag = pattern.findall(line) - if findflag: - break - parts += [line] - result = ''.join(parts) - self.cache['autoconf'] = result - return(self.cache['autoconf']) - - def getAutomakeSnippet(self): - '''getAutomakeSnippet() -> string - - Get automake snippet. - GLConfig: auxdir, ac_version.''' - result = string() # Define stack variable - conditional = self.getAutomakeSnippet_Conditional() - if conditional.strip(): - result += self.getAutomakeSnippet_Conditional() - else: # if not conditional.strip() - result += '\n' - result += self.getAutomakeSnippet_Unconditional() - return(result) - - def getAutomakeSnippet_Conditional(self): - '''GLModule.getAutomakeSnippet_Conditional() -> string - - Return conditional automake snippet.''' - section = 'Makefile.am:' - if 'makefile-conditional' not in self.cache: - if section not in self.content: - result = string() - else: # if section in self.content - snippet = self.content.split(section)[-1] - snippet = snippet.replace('\r\n', '\n') - lines = ['%s\n' % line for line in snippet.split('\n')] - parts = list() - for line in lines: - regex = '^(Description|Comment|Status|Notice|Applicability|' - regex += 'Files|Depends-on|configure\\.ac-early|configure\\.ac|' - regex += 'Makefile\\.am|Include|Link|License|Maintainer):$' - pattern = compiler(regex) - findflag = pattern.findall(line) - if findflag: - break - parts += [line] - result = ''.join(parts) - self.cache['makefile-conditional'] = result - return(self.cache['makefile-conditional']) - - def getAutomakeSnippet_Unconditional(self): - '''GLModule.getAutomakeSnippet_Unconditional() -> string - - Return unconditional automake snippet. - GLConfig: auxdir, ac_version.''' - auxdir = self.config['auxdir'] - ac_version = self.config['ac_version'] - result = string() - if 'makefile-unconditional' not in self.cache: - if self.isTests(): - files = self.getFiles() - extra_files = filter_filelist(constants.NL, files, - 'tests/', '', 'tests/', '').split(constants.NL) - extra_files = sorted(set(extra_files)) - if extra_files: - result += string('EXTRA_DIST += %s' % ' '.join(extra_files)) - result += constants.NL *2 - else: # if not tests module - # TODO: unconditional automake snippet for nontests modules - snippet = self.getAutomakeSnippet_Conditional() - snippet = snippet.replace('\\\n', ' ') - pattern = compiler('^lib_SOURCES[\t ]*\\+=[\t ]*(.*?)$', re.S | re.M) - mentioned_files = pattern.findall(snippet) - if mentioned_files != list(): - mentioned_files = mentioned_files[-1].split(' ') - mentioned_files = [f.strip() for f in mentioned_files] - mentioned_files = [f for f in mentioned_files if f != ''] - mentioned_files = sorted(set(mentioned_files)) - all_files = self.getFiles() - lib_files = filter_filelist(constants.NL, all_files, - 'lib/', '', 'lib/', '').split(constants.NL) - extra_files = [f for f in lib_files if f not in mentioned_files] - extra_files = sorted(set(extra_files)) - if extra_files != [''] and extra_files: - result += string('EXTRA_DIST += %s' % ' '.join(extra_files)) - result += '\n\n' - # Synthesize also an EXTRA_lib_SOURCES augmentation - if str(self) != 'relocatable-prog-wrapper' and str(self) != 'pt_chown': - extra_files = filter_filelist(constants.NL, extra_files, - '', '.c', '', '').split(constants.NL) - extra_files = sorted(set(extra_files)) - if extra_files != ['']: - result += string('EXTRA_lib_SOURCES += %s' % ' '.join(extra_files)) - result += '\n\n' - # Synthesize an EXTRA_DIST augmentation also for the files in build-aux - buildaux_files = filter_filelist(constants.NL, all_files, - 'build-aux/', '', 'build-aux/', '').split(constants.NL) - buildaux_files = sorted(set(buildaux_files)) - if buildaux_files != ['']: - buildaux_files = ''.join(buildaux_files) - buildaux_files = joinpath('$(top_srcdir)', auxdir, buildaux_files) - result += string('EXTRA_DIST += %s' % buildaux_files) - result += '\n\n' - # Synthesize an EXTRA_DIST augmentation also for the files from top/. - top_files = filter_filelist(constants.NL, all_files, - 'top/', '', 'top/', '').split(constants.NL) - top_files = sorted(set(top_files)) - if top_files != ['']: - top_files = ''.join(top_files) - top_files = joinpath('$(top_srcdir)', top_files) - result += string('EXTRA_DIST += %s' % top_files) - result += '\n\n' - result = constants.nlconvert(result) - self.cache['makefile-unconditional'] = result - return(self.cache['makefile-unconditional']) - - def getInclude(self): - '''GLModule.getInclude() -> string - - Return include directive.''' - section = 'Include:' - if 'include' not in self.cache: - if section not in self.content: - result = string() - else: # if section in self.content - snippet = self.content.split(section)[-1] - snippet = snippet.replace('\r\n', '\n') - lines = ['%s\n' % line for line in snippet.split('\n')] - parts = list() - for line in lines: - regex = '^(Description|Comment|Status|Notice|Applicability|' - regex += 'Files|Depends-on|configure\\.ac-early|configure\\.ac|' - regex += 'Makefile\\.am|Include|Link|License|Maintainer):$' - pattern = compiler(regex) - findflag = pattern.findall(line) - if findflag: - break - parts += [line] - result = ''.join(parts) - result = result.strip() - pattern = compiler('^(["<].*?[>"])', re.S | re.M) - result = pattern.sub('#include \\1', result) - self.cache['include'] = result - return(self.cache['include']) - - def getLink(self): - '''GLModule.getLink() -> string - - Return link directive.''' - section = 'Link:' - if 'link' not in self.cache: - if section not in self.content: - result = string() - else: # if section in self.content - snippet = self.content.split(section)[-1] - snippet = snippet.replace('\r\n', '\n') - lines = ['%s\n' % line for line in snippet.split('\n')] - parts = list() - for line in lines: - regex = '^(Description|Comment|Status|Notice|Applicability|' - regex += 'Files|Depends-on|configure\\.ac-early|configure\\.ac|' - regex += 'Makefile\\.am|Include|Link|License|Maintainer):$' - pattern = compiler(regex) - findflag = pattern.findall(line) - if findflag: - break - parts += [line] - parts = [part.strip() for part in parts if part.strip()] - result = ''.join(parts) - self.cache['link'] = result - return(self.cache['link']) - - def getLicense(self): - '''GLModule.getLicense(self) -> string - - Get license and warn user if module lacks a license.''' - license = self.getLicense_Raw() - if not self.isTests(): - if not license: - if self.config['errors']: - raise(GLError(18, string(self))) - else: # if not self.config['errors'] - sys.stderr.write('gnulib-tool: warning: ') - sys.stderr.write('module %s lacks a license\n' % str(self)) - if not license: - license = 'GPL' - return(license) - - def getLicense_Raw(self): - '''GLModule.getLicense_Raw() -> string - - Return module license.''' - section = 'License:' - if 'license' not in self.cache: - if section not in self.content: - result = string() - else: # if section in self.content - pattern = '^%s[\t ]*(.*?)%s' % (section, self.regex) - pattern = compiler(pattern, re.S | re.M) - result = pattern.findall(self.content) - if type(result) is list: - if not result: - result = string() - else: # if result - result = result[-1] - result = result.strip() - self.cache['license'] = result - return(self.cache['license']) - - def getMaintainer(self): - '''GLModule.getMaintainer() -> string - - Return maintainer directive.''' - section = 'Maintainer:' - if 'maintainer' not in self.cache: - if section not in self.content: + if 'files' not in self.cache: + if section not in self.content: + result = list() + else: # if section in self.content + snippet = self.content.split(section)[-1] + snippet = snippet.replace('\r\n', '\n') + lines = ['%s\n' % line for line in snippet.split('\n')] + parts = list() + for line in lines: + regex = '^(Description|Comment|Status|Notice|Applicability|' + regex += 'Files|Depends-on|configure\\.ac-early|configure\\.ac|' + regex += 'Makefile\\.am|Include|Link|License|Maintainer):$' + pattern = compiler(regex) + findflag = pattern.findall(line) + if findflag: + break + parts += [line] + result = [part.strip() for part in parts if part.strip()] + result += [joinpath('m4', '00gnulib.m4')] + result += [joinpath('m4', 'gnulib-common.m4')] + if ac_version == 2.59: + result += [joinpath('m4', 'onceonly.m4')] + self.cache['files'] = list(result) + return(list(self.cache['files'])) + + def getDependencies(self): + '''GLModule.getDependencies() -> list + + Return list of dependencies. + GLConfig: localdir.''' + localdir = self.config['localdir'] + result = list() + section = 'Depends-on:' + if 'dependencies' not in self.cache: + if section not in self.content: + depmodules = list() + else: # if section in self.content + snippet = self.content.split(section)[-1] + snippet = snippet.replace('\r\n', '\n') + lines = ['%s\n' % line for line in snippet.split('\n')] + parts = list() + for line in lines: + regex = '^(Description|Comment|Status|Notice|Applicability|' + regex += 'Files|Depends-on|configure\\.ac-early|configure\\.ac|' + regex += 'Makefile\\.am|Include|Link|License|Maintainer):$' + pattern = compiler(regex) + findflag = pattern.findall(line) + if findflag: + break + parts += [line] + modules = ''.join(parts) + modules = [line for line in modules.split( + '\n') if line.strip()] + modules = [ + module for module in modules if not module.startswith('#')] + for line in modules: + split = [part for part in line.split(' ') if part.strip()] + if len(split) == 1: + module = line.strip() + condition = None + else: # if len(split) != 1 + module = split[0] + condition = split[1] + if type(condition) is bytes: + condition = condition.decode(ENCS['default']) + result += [tuple([self.modulesystem.find(module), condition])] + self.cache['dependencies'] = result + return(list(self.cache['dependencies'])) + + def getAutoconfSnippet_Early(self): + '''GLModule.getAutoconfSnippet_Early() -> string + + Return autoconf-early snippet.''' + section = 'configure.ac-early:' + if 'autoconf-early' not in self.cache: + if section not in self.content: + result = string() + else: # if section in self.content + snippet = self.content.split(section)[-1] + snippet = snippet.replace('\r\n', '\n') + lines = ['%s\n' % line for line in snippet.split('\n')] + parts = list() + for line in lines: + regex = '^(Description|Comment|Status|Notice|Applicability|' + regex += 'Files|Depends-on|configure\\.ac-early|configure\\.ac|' + regex += 'Makefile\\.am|Include|Link|License|Maintainer):$' + pattern = compiler(regex) + findflag = pattern.findall(line) + if findflag: + break + parts += [line] + result = ''.join(parts) + self.cache['autoconf-early'] = result + return(self.cache['autoconf-early']) + + def getAutoconfSnippet(self): + '''GLModule.getAutoconfSnippet() -> string + + Return autoconf snippet.''' + section = 'configure.ac:' + if 'autoconf' not in self.cache: + if section not in self.content: + result = string() + else: # if section in self.content + snippet = self.content.split(section)[-1] + snippet = snippet.replace('\r\n', '\n') + lines = ['%s\n' % line for line in snippet.split('\n')] + parts = list() + for line in lines: + regex = '^(Description|Comment|Status|Notice|Applicability|' + regex += 'Files|Depends-on|configure\\.ac-early|configure\\.ac|' + regex += 'Makefile\\.am|Include|Link|License|Maintainer):$' + pattern = compiler(regex) + findflag = pattern.findall(line) + if findflag: + break + parts += [line] + result = ''.join(parts) + self.cache['autoconf'] = result + return(self.cache['autoconf']) + + def getAutomakeSnippet(self): + '''getAutomakeSnippet() -> string + + Get automake snippet. + GLConfig: auxdir, ac_version.''' + result = string() # Define stack variable + conditional = self.getAutomakeSnippet_Conditional() + if conditional.strip(): + result += self.getAutomakeSnippet_Conditional() + else: # if not conditional.strip() + result += '\n' + result += self.getAutomakeSnippet_Unconditional() + return(result) + + def getAutomakeSnippet_Conditional(self): + '''GLModule.getAutomakeSnippet_Conditional() -> string + + Return conditional automake snippet.''' + section = 'Makefile.am:' + if 'makefile-conditional' not in self.cache: + if section not in self.content: + result = string() + else: # if section in self.content + snippet = self.content.split(section)[-1] + snippet = snippet.replace('\r\n', '\n') + lines = ['%s\n' % line for line in snippet.split('\n')] + parts = list() + for line in lines: + regex = '^(Description|Comment|Status|Notice|Applicability|' + regex += 'Files|Depends-on|configure\\.ac-early|configure\\.ac|' + regex += 'Makefile\\.am|Include|Link|License|Maintainer):$' + pattern = compiler(regex) + findflag = pattern.findall(line) + if findflag: + break + parts += [line] + result = ''.join(parts) + self.cache['makefile-conditional'] = result + return(self.cache['makefile-conditional']) + + def getAutomakeSnippet_Unconditional(self): + '''GLModule.getAutomakeSnippet_Unconditional() -> string + + Return unconditional automake snippet. + GLConfig: auxdir, ac_version.''' + auxdir = self.config['auxdir'] + ac_version = self.config['ac_version'] result = string() - else: # if section in self.content - snippet = self.content.split(section)[-1] - snippet = snippet.replace('\r\n', '\n') - lines = ['%s\n' % line for line in snippet.split('\n')] - parts = list() - for line in lines: - regex = '^(Description|Comment|Status|Notice|Applicability|' - regex += 'Files|Depends-on|configure\\.ac-early|configure\\.ac|' - regex += 'Makefile\\.am|Include|Link|License|Maintainer):$' - pattern = compiler(regex) - findflag = pattern.findall(line) - if findflag: - break - parts += [line] - result = ''.join(parts) - result = result.strip() - self.cache['maintainer'] = result - return(self.cache['maintainer']) + if 'makefile-unconditional' not in self.cache: + if self.isTests(): + files = self.getFiles() + extra_files = filter_filelist(constants.NL, files, + 'tests/', '', 'tests/', '').split(constants.NL) + extra_files = sorted(set(extra_files)) + if extra_files: + result += string('EXTRA_DIST += %s' % + ' '.join(extra_files)) + result += constants.NL * 2 + else: # if not tests module + # TODO: unconditional automake snippet for nontests modules + snippet = self.getAutomakeSnippet_Conditional() + snippet = snippet.replace('\\\n', ' ') + pattern = compiler( + '^lib_SOURCES[\t ]*\\+=[\t ]*(.*?)$', re.S | re.M) + mentioned_files = pattern.findall(snippet) + if mentioned_files != list(): + mentioned_files = mentioned_files[-1].split(' ') + mentioned_files = [f.strip() for f in mentioned_files] + mentioned_files = [f for f in mentioned_files if f != ''] + mentioned_files = sorted(set(mentioned_files)) + all_files = self.getFiles() + lib_files = filter_filelist(constants.NL, all_files, + 'lib/', '', 'lib/', '').split(constants.NL) + extra_files = [ + f for f in lib_files if f not in mentioned_files] + extra_files = sorted(set(extra_files)) + if extra_files != [''] and extra_files: + result += string('EXTRA_DIST += %s' % + ' '.join(extra_files)) + result += '\n\n' + # Synthesize also an EXTRA_lib_SOURCES augmentation + if str(self) != 'relocatable-prog-wrapper' and str(self) != 'pt_chown': + extra_files = filter_filelist(constants.NL, extra_files, + '', '.c', '', '').split(constants.NL) + extra_files = sorted(set(extra_files)) + if extra_files != ['']: + result += string('EXTRA_lib_SOURCES += %s' % + ' '.join(extra_files)) + result += '\n\n' + # Synthesize an EXTRA_DIST augmentation also for the files in build-aux + buildaux_files = filter_filelist(constants.NL, all_files, + 'build-aux/', '', 'build-aux/', '').split(constants.NL) + buildaux_files = sorted(set(buildaux_files)) + if buildaux_files != ['']: + buildaux_files = ''.join(buildaux_files) + buildaux_files = joinpath( + '$(top_srcdir)', auxdir, buildaux_files) + result += string('EXTRA_DIST += %s' % buildaux_files) + result += '\n\n' + # Synthesize an EXTRA_DIST augmentation also for the files from top/. + top_files = filter_filelist(constants.NL, all_files, + 'top/', '', 'top/', '').split(constants.NL) + top_files = sorted(set(top_files)) + if top_files != ['']: + top_files = ''.join(top_files) + top_files = joinpath('$(top_srcdir)', top_files) + result += string('EXTRA_DIST += %s' % top_files) + result += '\n\n' + result = constants.nlconvert(result) + self.cache['makefile-unconditional'] = result + return(self.cache['makefile-unconditional']) + + def getInclude(self): + '''GLModule.getInclude() -> string + + Return include directive.''' + section = 'Include:' + if 'include' not in self.cache: + if section not in self.content: + result = string() + else: # if section in self.content + snippet = self.content.split(section)[-1] + snippet = snippet.replace('\r\n', '\n') + lines = ['%s\n' % line for line in snippet.split('\n')] + parts = list() + for line in lines: + regex = '^(Description|Comment|Status|Notice|Applicability|' + regex += 'Files|Depends-on|configure\\.ac-early|configure\\.ac|' + regex += 'Makefile\\.am|Include|Link|License|Maintainer):$' + pattern = compiler(regex) + findflag = pattern.findall(line) + if findflag: + break + parts += [line] + result = ''.join(parts) + result = result.strip() + pattern = compiler('^(["<].*?[>"])', re.S | re.M) + result = pattern.sub('#include \\1', result) + self.cache['include'] = result + return(self.cache['include']) + + def getLink(self): + '''GLModule.getLink() -> string + + Return link directive.''' + section = 'Link:' + if 'link' not in self.cache: + if section not in self.content: + result = string() + else: # if section in self.content + snippet = self.content.split(section)[-1] + snippet = snippet.replace('\r\n', '\n') + lines = ['%s\n' % line for line in snippet.split('\n')] + parts = list() + for line in lines: + regex = '^(Description|Comment|Status|Notice|Applicability|' + regex += 'Files|Depends-on|configure\\.ac-early|configure\\.ac|' + regex += 'Makefile\\.am|Include|Link|License|Maintainer):$' + pattern = compiler(regex) + findflag = pattern.findall(line) + if findflag: + break + parts += [line] + parts = [part.strip() for part in parts if part.strip()] + result = ''.join(parts) + self.cache['link'] = result + return(self.cache['link']) + + def getLicense(self): + '''GLModule.getLicense(self) -> string + + Get license and warn user if module lacks a license.''' + license = self.getLicense_Raw() + if not self.isTests(): + if not license: + if self.config['errors']: + raise(GLError(18, string(self))) + else: # if not self.config['errors'] + sys.stderr.write('gnulib-tool: warning: ') + sys.stderr.write('module %s lacks a license\n' % str(self)) + if not license: + license = 'GPL' + return(license) + + def getLicense_Raw(self): + '''GLModule.getLicense_Raw() -> string + + Return module license.''' + section = 'License:' + if 'license' not in self.cache: + if section not in self.content: + result = string() + else: # if section in self.content + pattern = '^%s[\t ]*(.*?)%s' % (section, self.regex) + pattern = compiler(pattern, re.S | re.M) + result = pattern.findall(self.content) + if type(result) is list: + if not result: + result = string() + else: # if result + result = result[-1] + result = result.strip() + self.cache['license'] = result + return(self.cache['license']) + + def getMaintainer(self): + '''GLModule.getMaintainer() -> string + + Return maintainer directive.''' + section = 'Maintainer:' + if 'maintainer' not in self.cache: + if section not in self.content: + result = string() + else: # if section in self.content + snippet = self.content.split(section)[-1] + snippet = snippet.replace('\r\n', '\n') + lines = ['%s\n' % line for line in snippet.split('\n')] + parts = list() + for line in lines: + regex = '^(Description|Comment|Status|Notice|Applicability|' + regex += 'Files|Depends-on|configure\\.ac-early|configure\\.ac|' + regex += 'Makefile\\.am|Include|Link|License|Maintainer):$' + pattern = compiler(regex) + findflag = pattern.findall(line) + if findflag: + break + parts += [line] + result = ''.join(parts) + result = result.strip() + self.cache['maintainer'] = result + return(self.cache['maintainer']) #=============================================================================== # Define GLModuleTable class #=============================================================================== class GLModuleTable(object): - '''GLModuleTable is used to work with the list of the modules.''' - - def __init__(self, config, avoids=list()): - '''GLModuleTable.__init__(config, avoids) -> GLModuleTable - - Create new GLModuleTable instance. If modules are specified, then add - every module from iterable as unconditional module. If avoids is specified, - then in transitive_closure every dependency which is in avoids won't be - included in the final modules list. If testflags iterable is enabled, then - don't add module which status is in the testflags. If conddeps are enabled, - then store condition for each dependency if it has a condition. - The only necessary argument is localdir, which is needed just to create - modulesystem instance to look for dependencies.''' - self.avoids = list() # Avoids - self.dependers = dict() # Dependencies - self.conditionals = dict() # Conditional modules - self.unconditionals = dict() # Unconditional modules - self.base_modules = list() # Base modules - self.main_modules = list() # Main modules - self.tests_modules = list() # Tests modules - self.final_modules = list() # Final modules - if type(config) is not GLConfig: - raise(TypeError('config must be a GLConfig, not %s' % \ - type(config).__name__)) - for avoid in avoids: - if type(avoid) is not GLModule: - raise(TypeError('each avoid must be a GLModule instance')) - self.avoids += [avoids] - self.config = config - self.filesystem = GLFileSystem(self.config) - self.modulesystem = GLModuleSystem(self.config) - - def __repr__(self): - '''x.__repr__() <==> repr(x)''' - result = '' % hex(id(self)) - return(result) - - def __getitem__(self, y): - '''x.__getitem__(y) <==> x[y]''' - if y in ['base', 'final', 'main', 'tests', 'avoids']: - if y == 'base': - return(self.getBaseModules()) - elif y == 'final': - return(self.getFinalModules()) - elif y == 'main': - return(self.getMainModules()) - elif y == 'tests': - return(self.getTestsModules()) - else: # if y == 'avoids' - return(self.getAvoids()) - else: # if y is not in list - raise(KeyError('GLModuleTable does not contain key: %s' % repr(y))) - - def addConditional(self, parent, module, condition): - '''GLModuleTable.addConditional(module, condition) - - Add new conditional dependency from parent to module with condition.''' - if type(parent) is not GLModule: - raise(TypeError('parent must be a GLModule, not %s' % \ - type(parent).__name__)) - if type(module) is not GLModule: - raise(TypeError('module must be a GLModule, not %s' % \ - type(module).__name__)) - if type(condition) is bytes or type(condition) is string \ - or condition == True: - if type(condition) is bytes: - condition = condition.decode(ENCS['default']) - else: # if condition has not bytes or string type or is not True - raise(TypeError('condition must be a string or True, not %s' % \ - type(condition).__name__)) - if not str(module) in self.unconditionals: - if str(module) not in self.dependers: - self.dependers[module] = list() - self.dependers[module] += [module] - key = '%s---%s' % (str(parent), str(module)) - self.conditionals[key] = condition - - def addUnconditional(self, module): - '''GLModuleTable.addUnconditional(module) - - Add module as unconditional dependency.''' - if type(module) is not GLModule: - raise(TypeError('module must be a GLModule, not %s' % \ - type(module).__name__)) - if str(module) in self.dependers: - self.dependers.pop(str(module)) - self.unconditionals[str(module)] = True - - def isConditional(self, module): - '''GLModuleTable.isConditional(module) -> bool - - Check whether module is unconditional.''' - if type(module) is not GLModule: - raise(TypeError('module must be a GLModule, not %s' % \ - type(module).__name__)) - result = str(module) in self.dependers - return(result) - - def getCondition(self, parent, module): - '''GLModuleTable.getCondition(module) -> string or True - - Return condition from parent to module. Condition can be string or True. - If module is not in the list of conddeps, method returns None.''' - if type(parent) is not GLModule: - raise(TypeError('parent must be a GLModule, not %s' % \ - type(parent).__name__)) - if type(module) is not GLModule: - raise(TypeError('module must be a GLModule, not %s' % \ - type(module).__name__)) - key = '%s---%s' % (str(parent), str(module)) - result = None - if key in self.conditionals: - result = self.conditionals[key] - return(result) - - def transitive_closure(self, modules): - '''GLModuleTable.transitive_closure(modules) -> list - - Use transitive closure to add module and its dependencies. Add every - module and its dependencies from modules list, but do not add dependencies - which contain in avoids list. If any testflag is enabled, then do not add - dependencies which have the status as this flag. If conddeps are enabled, - then store condition for each dependency if it has a condition. This method - is used to update final list of modules. Method returns list of modules. - GLConfig: testflags.''' - for module in modules: - if type(module) is not GLModule: - raise(TypeError('each module must be a GLModule instance')) - handledmodules = list() - inmodules = modules - outmodules = list() - if self.config['conddeps']: - for module in modules: - self.addUnconditional(module) - while inmodules: - inmodules_this_round = inmodules - inmodules = list() - for module in inmodules_this_round: - outmodules += [module] + '''GLModuleTable is used to work with the list of the modules.''' + + def __init__(self, config, avoids=list()): + '''GLModuleTable.__init__(config, avoids) -> GLModuleTable + + Create new GLModuleTable instance. If modules are specified, then add + every module from iterable as unconditional module. If avoids is specified, + then in transitive_closure every dependency which is in avoids won't be + included in the final modules list. If testflags iterable is enabled, then + don't add module which status is in the testflags. If conddeps are enabled, + then store condition for each dependency if it has a condition. + The only necessary argument is localdir, which is needed just to create + modulesystem instance to look for dependencies.''' + self.avoids = list() # Avoids + self.dependers = dict() # Dependencies + self.conditionals = dict() # Conditional modules + self.unconditionals = dict() # Unconditional modules + self.base_modules = list() # Base modules + self.main_modules = list() # Main modules + self.tests_modules = list() # Tests modules + self.final_modules = list() # Final modules + if type(config) is not GLConfig: + raise(TypeError('config must be a GLConfig, not %s' % + type(config).__name__)) + for avoid in avoids: + if type(avoid) is not GLModule: + raise(TypeError('each avoid must be a GLModule instance')) + self.avoids += [avoids] + self.config = config + self.filesystem = GLFileSystem(self.config) + self.modulesystem = GLModuleSystem(self.config) + + def __repr__(self): + '''x.__repr__() <==> repr(x)''' + result = '' % hex(id(self)) + return(result) + + def __getitem__(self, y): + '''x.__getitem__(y) <==> x[y]''' + if y in ['base', 'final', 'main', 'tests', 'avoids']: + if y == 'base': + return(self.getBaseModules()) + elif y == 'final': + return(self.getFinalModules()) + elif y == 'main': + return(self.getMainModules()) + elif y == 'tests': + return(self.getTestsModules()) + else: # if y == 'avoids' + return(self.getAvoids()) + else: # if y is not in list + raise(KeyError('GLModuleTable does not contain key: %s' % repr(y))) + + def addConditional(self, parent, module, condition): + '''GLModuleTable.addConditional(module, condition) + + Add new conditional dependency from parent to module with condition.''' + if type(parent) is not GLModule: + raise(TypeError('parent must be a GLModule, not %s' % + type(parent).__name__)) + if type(module) is not GLModule: + raise(TypeError('module must be a GLModule, not %s' % + type(module).__name__)) + if type(condition) is bytes or type(condition) is string \ + or condition == True: + if type(condition) is bytes: + condition = condition.decode(ENCS['default']) + else: # if condition has not bytes or string type or is not True + raise(TypeError('condition must be a string or True, not %s' % + type(condition).__name__)) + if not str(module) in self.unconditionals: + if str(module) not in self.dependers: + self.dependers[module] = list() + self.dependers[module] += [module] + key = '%s---%s' % (str(parent), str(module)) + self.conditionals[key] = condition + + def addUnconditional(self, module): + '''GLModuleTable.addUnconditional(module) + + Add module as unconditional dependency.''' + if type(module) is not GLModule: + raise(TypeError('module must be a GLModule, not %s' % + type(module).__name__)) + if str(module) in self.dependers: + self.dependers.pop(str(module)) + self.unconditionals[str(module)] = True + + def isConditional(self, module): + '''GLModuleTable.isConditional(module) -> bool + + Check whether module is unconditional.''' + if type(module) is not GLModule: + raise(TypeError('module must be a GLModule, not %s' % + type(module).__name__)) + result = str(module) in self.dependers + return(result) + + def getCondition(self, parent, module): + '''GLModuleTable.getCondition(module) -> string or True + + Return condition from parent to module. Condition can be string or True. + If module is not in the list of conddeps, method returns None.''' + if type(parent) is not GLModule: + raise(TypeError('parent must be a GLModule, not %s' % + type(parent).__name__)) + if type(module) is not GLModule: + raise(TypeError('module must be a GLModule, not %s' % + type(module).__name__)) + key = '%s---%s' % (str(parent), str(module)) + result = None + if key in self.conditionals: + result = self.conditionals[key] + return(result) + + def transitive_closure(self, modules): + '''GLModuleTable.transitive_closure(modules) -> list + + Use transitive closure to add module and its dependencies. Add every + module and its dependencies from modules list, but do not add dependencies + which contain in avoids list. If any testflag is enabled, then do not add + dependencies which have the status as this flag. If conddeps are enabled, + then store condition for each dependency if it has a condition. This method + is used to update final list of modules. Method returns list of modules. + GLConfig: testflags.''' + for module in modules: + if type(module) is not GLModule: + raise(TypeError('each module must be a GLModule instance')) + handledmodules = list() + inmodules = modules + outmodules = list() if self.config['conddeps']: - automake_snippet = \ - module.getAutomakeSnippet_Conditional() - pattern = compiler('^if') - if not pattern.findall(automake_snippet): - self.addUnconditional(module) - conditional = self.isConditional(module) - dependencies = module.getDependencies() - depmodules = [pair[0] for pair in dependencies] - conditions = [pair[1] for pair in dependencies] + for module in modules: + self.addUnconditional(module) + while inmodules: + inmodules_this_round = inmodules + inmodules = list() + for module in inmodules_this_round: + outmodules += [module] + if self.config['conddeps']: + automake_snippet = \ + module.getAutomakeSnippet_Conditional() + pattern = compiler('^if') + if not pattern.findall(automake_snippet): + self.addUnconditional(module) + conditional = self.isConditional(module) + dependencies = module.getDependencies() + depmodules = [pair[0] for pair in dependencies] + conditions = [pair[1] for pair in dependencies] + if TESTS['tests'] in self.config['testflags']: + testsname = module.getTestsName() + if self.modulesystem.exists(testsname): + testsmodule = self.modulesystem.find(testsname) + depmodules += [testsmodule] + conditions += [None] + for depmodule in depmodules: + include = True + includes = list() + status = depmodule.getStatus() + for word in status: + if word == 'obsolete': + if TESTS['obsolete'] in self.config['testflags'] or \ + TESTS['all-test'] in self.config['testflags']: + includes += [False] + elif word == 'c++-test': + if TESTS['c++-test'] in self.config['testflags'] or \ + TESTS['all-test'] in self.config['testflags']: + includes += [False] + elif word == 'longrunning-test': + if TESTS['longrunning-test'] in self.config['testflags'] or \ + TESTS['all-test'] in self.config['testflags']: + includes += [False] + elif word == 'privileged-test': + if TESTS['privileged-test'] in self.config['testflags'] or \ + TESTS['all-test'] in self.config['testflags']: + includes += [False] + elif word == 'all-test': + if TESTS['all-test'] in self.config['testflags'] or \ + TESTS['all-test'] in self.config['testflags']: + includes += [False] + else: # if any other word + if word.endswith('-tests'): + if TESTS['all-test'] in self.config['testflags']: + includes += [False] + include = any(includes) + if include and depmodule not in self.avoids: + inmodules += [depmodule] + if self.config['conddeps']: + index = depmodules.index(depmodule) + condition = conditions[index] + if condition: + self.addConditional( + module, depmodule, condition) + else: # if condition + if conditional: + self.addConditional( + module, depmodule, True) + else: # if not conditional + self.addUnconditional(module) + listing = list() # Create empty list + inmodules = sorted(set(inmodules)) + handledmodules = sorted(set(handledmodules + inmodules_this_round)) + inmodules = \ + [ # Begin to filter inmodules + module for module in inmodules if module not in handledmodules + ] # Finish to filter inmodules + inmodules = sorted(set(inmodules)) + modules = sorted(set(outmodules)) + self.modules = modules + return(list(modules)) + + def transitive_closure_separately(self, basemodules, finalmodules): + '''GLModuleTable.transitive_closure_separately(*args, **kwargs) -> tuple + + Determine main module list and tests-related module list separately. + The main module list is the transitive closure of the specified modules, + ignoring tests modules. Its lib/* sources go into $sourcebase/. If lgpl is + specified, it will consist only of LGPLed source. + The tests-related module list is the transitive closure of the specified + modules, including tests modules, minus the main module list excluding + modules of applicability 'all'. Its lib/* sources (brought in through + dependencies of *-tests modules) go into $testsbase/. It may contain GPLed + source, even if lgpl is specified. + Arguments are basemodules and finalmodules, where basemodules argument + represents modules specified by user and finalmodules represents modules + list after previous transitive_closure. + Method returns tuple which contains two lists: the list of main modules and + the list of tests-related modules. Both lists contain dependencies. + GLConfig: testflags.''' + inctests = False + main_modules = list() + tests_modules = list() if TESTS['tests'] in self.config['testflags']: - testsname = module.getTestsName() - if self.modulesystem.exists(testsname): - testsmodule = self.modulesystem.find(testsname) - depmodules += [testsmodule] - conditions += [None] - for depmodule in depmodules: - include = True - includes = list() - status = depmodule.getStatus() - for word in status: - if word == 'obsolete': - if TESTS['obsolete'] in self.config['testflags'] or \ - TESTS['all-test'] in self.config['testflags']: - includes += [False] - elif word == 'c++-test': - if TESTS['c++-test'] in self.config['testflags'] or \ - TESTS['all-test'] in self.config['testflags']: - includes += [False] - elif word == 'longrunning-test': - if TESTS['longrunning-test'] in self.config['testflags'] or \ - TESTS['all-test'] in self.config['testflags']: - includes += [False] - elif word == 'privileged-test': - if TESTS['privileged-test'] in self.config['testflags'] or \ - TESTS['all-test'] in self.config['testflags']: - includes += [False] - elif word == 'all-test': - if TESTS['all-test'] in self.config['testflags'] or \ - TESTS['all-test'] in self.config['testflags']: - includes += [False] - else: # if any other word - if word.endswith('-tests'): - if TESTS['all-test'] in self.config['testflags']: - includes += [False] - include = any(includes) - if include and depmodule not in self.avoids: - inmodules += [depmodule] - if self.config['conddeps']: - index = depmodules.index(depmodule) - condition = conditions[index] - if condition: - self.addConditional(module, depmodule, condition) - else: # if condition - if conditional: - self.addConditional(module, depmodule, True) - else: # if not conditional - self.addUnconditional(module) - listing = list() # Create empty list - inmodules = sorted(set(inmodules)) - handledmodules = sorted(set(handledmodules +inmodules_this_round)) - inmodules = \ - [ # Begin to filter inmodules - module for module in inmodules if module not in handledmodules - ] # Finish to filter inmodules - inmodules = sorted(set(inmodules)) - modules = sorted(set(outmodules)) - self.modules = modules - return(list(modules)) - - def transitive_closure_separately(self, basemodules, finalmodules): - '''GLModuleTable.transitive_closure_separately(*args, **kwargs) -> tuple - - Determine main module list and tests-related module list separately. - The main module list is the transitive closure of the specified modules, - ignoring tests modules. Its lib/* sources go into $sourcebase/. If lgpl is - specified, it will consist only of LGPLed source. - The tests-related module list is the transitive closure of the specified - modules, including tests modules, minus the main module list excluding - modules of applicability 'all'. Its lib/* sources (brought in through - dependencies of *-tests modules) go into $testsbase/. It may contain GPLed - source, even if lgpl is specified. - Arguments are basemodules and finalmodules, where basemodules argument - represents modules specified by user and finalmodules represents modules - list after previous transitive_closure. - Method returns tuple which contains two lists: the list of main modules and - the list of tests-related modules. Both lists contain dependencies. - GLConfig: testflags.''' - inctests = False - main_modules = list() - tests_modules = list() - if TESTS['tests'] in self.config['testflags']: - self.config['testflags'].pop(TESTS['tests']) - inctests = True - for module in basemodules: - if type(module) is not GLModule: - raise(TypeError('each module must be a GLModule instance')) - for module in finalmodules: - if type(module) is not GLModule: - raise(TypeError('each module must be a GLModule instance')) - main_modules = self.transitive_closure(basemodules) - tests_modules = \ - [m for m in finalmodules if m not in main_modules] + \ - [m for m in main_modules if m.getApplicability() != 'main'] - tests_modules = sorted(set(tests_modules)) - if inctests: - testflags = sorted(set(self.config['testflags'] +[TESTS['tests']])) - self.config.setTestFlags(testflags) - result = tuple([main_modules, tests_modules]) - return(result) - - def add_dummy(self, modules): - '''GLModuleTable.add_dummy(modules) -> list - - Add dummy package to list of modules if dummy package is needed. If not, - return original list of modules. - GLConfig: auxdir, ac_version.''' - auxdir = self.config['auxdir'] - ac_version = self.config['ac_version'] - have_lib_sources = False - for module in modules: - if type(module) is not GLModule: - raise(TypeError('each module must be a GLModule instance')) - snippet = module.getAutomakeSnippet() - snippet = snippet.replace('\\\n', '') - pattern = compiler('^lib_SOURCES[\t ]*\\+=[\t ]*(.*?)$', re.S | re.M) - files = pattern.findall(snippet) - if files: # if source files were found - files = files[-1].split(' ') - for file in files: - if not file.endswith('.h'): - have_lib_sources = True - break - if not have_lib_sources: - dummy = self.modulesystem.find('dummy') - modules = sorted(set(modules +[dummy])) - return(list(modules)) - - def filelist(self, modules): - '''GLModuleTable.filelist(modules) -> list - - Determine the final file list for the given list of modules. The list of - modules must already include dependencies. - GLConfig: ac_version.''' - ac_version = self.config['ac_version'] - filelist = list() - for module in modules: - if type(module) is not GLModule: - raise(TypeError('each module must be a GLModule instance')) - listings = [module.getFiles() for module in modules] - for listing in listings: - for file in listing: - if file not in filelist: - filelist += [file] - return(filelist) - - def filelist_separately(self, main_modules, tests_modules): - '''GLModuleTable.filelist_separately(**kwargs) -> list - - Determine the final file lists. They must be computed separately, because - files in lib/* go into $sourcebase/ if they are in the main file list but - into $testsbase/ if they are in the tests-related file list. Furthermore - lib/dummy.c can be in both.''' - ac_version = self.config['ac_version'] - main_filelist = self.filelist(main_modules) - tests_filelist = self.filelist(tests_modules) - tests_filelist = \ - [ # Begin to sort filelist - file.replace('lib/', 'tests=lib/', 1) \ - if file.startswith('lib/') else file - for file in tests_filelist - ] # Finish to sort filelist - result = tuple([main_filelist, tests_filelist]) - return(result) - - def getAvoids(self): - '''GLModuleTable.getAvoids() -> list - - Return list of avoids.''' - return(list(self.avoids)) - - def setAvoids(self, modules): - '''GLModuleTable.setAvoids(modules) - - Specify list of avoids.''' - for module in modules: - if type(module) is not GLModule: - raise(TypeError('each module must be a GLModule instance')) - self.avoids = sorted(set(modules)) - - def getBaseModules(self): - '''GLModuleTable.getBaseModules() -> list - - Return list of base modules.''' - return(list(self.base_modules)) - - def setBaseModules(self, modules): - '''GLModuleTable.setBaseModules(modules) - - Specify list of base modules.''' - for module in modules: - if type(module) is not GLModule: - raise(TypeError('each module must be a GLModule instance')) - self.base_modules = sorted(set(modules)) - - def getFinalModules(self): - '''GLModuleTable.getFinalModules() -> list - - Return list of final modules.''' - return(list(self.final_modules)) - - def setFinalModules(self, modules): - '''GLModuleTable.setFinalModules(modules) - - Specify list of final modules.''' - for module in modules: - if type(module) is not GLModule: - raise(TypeError('each module must be a GLModule instance')) - self.final_modules = sorted(set(modules)) - - def getMainModules(self): - '''GLModuleTable.getMainModules() -> list - - Return list of main modules.''' - return(list(self.main_modules)) - - def setMainModules(self, modules): - '''GLModuleTable.setMainModules(modules) - - Specify list of main modules.''' - for module in modules: - if type(module) is not GLModule: - raise(TypeError('each module must be a GLModule instance')) - self.main_modules = sorted(set(modules)) - - def getTestsModules(self): - '''GLModuleTable.getTestsModules() -> list - - Return list of tests modules.''' - return(list(self.tests_modules)) - - def setTestsModules(self, modules): - '''GLModuleTable.setTestsModules(modules) - - Specify list of tests modules.''' - for module in modules: - if type(module) is not GLModule: - raise(TypeError('each module must be a GLModule instance')) - self.tests_modules = sorted(set(modules)) + self.config['testflags'].pop(TESTS['tests']) + inctests = True + for module in basemodules: + if type(module) is not GLModule: + raise(TypeError('each module must be a GLModule instance')) + for module in finalmodules: + if type(module) is not GLModule: + raise(TypeError('each module must be a GLModule instance')) + main_modules = self.transitive_closure(basemodules) + tests_modules = \ + [m for m in finalmodules if m not in main_modules] + \ + [m for m in main_modules if m.getApplicability() != 'main'] + tests_modules = sorted(set(tests_modules)) + if inctests: + testflags = sorted( + set(self.config['testflags'] + [TESTS['tests']])) + self.config.setTestFlags(testflags) + result = tuple([main_modules, tests_modules]) + return(result) + + def add_dummy(self, modules): + '''GLModuleTable.add_dummy(modules) -> list + + Add dummy package to list of modules if dummy package is needed. If not, + return original list of modules. + GLConfig: auxdir, ac_version.''' + auxdir = self.config['auxdir'] + ac_version = self.config['ac_version'] + have_lib_sources = False + for module in modules: + if type(module) is not GLModule: + raise(TypeError('each module must be a GLModule instance')) + snippet = module.getAutomakeSnippet() + snippet = snippet.replace('\\\n', '') + pattern = compiler( + '^lib_SOURCES[\t ]*\\+=[\t ]*(.*?)$', re.S | re.M) + files = pattern.findall(snippet) + if files: # if source files were found + files = files[-1].split(' ') + for file in files: + if not file.endswith('.h'): + have_lib_sources = True + break + if not have_lib_sources: + dummy = self.modulesystem.find('dummy') + modules = sorted(set(modules + [dummy])) + return(list(modules)) + + def filelist(self, modules): + '''GLModuleTable.filelist(modules) -> list + + Determine the final file list for the given list of modules. The list of + modules must already include dependencies. + GLConfig: ac_version.''' + ac_version = self.config['ac_version'] + filelist = list() + for module in modules: + if type(module) is not GLModule: + raise(TypeError('each module must be a GLModule instance')) + listings = [module.getFiles() for module in modules] + for listing in listings: + for file in listing: + if file not in filelist: + filelist += [file] + return(filelist) + + def filelist_separately(self, main_modules, tests_modules): + '''GLModuleTable.filelist_separately(**kwargs) -> list + + Determine the final file lists. They must be computed separately, because + files in lib/* go into $sourcebase/ if they are in the main file list but + into $testsbase/ if they are in the tests-related file list. Furthermore + lib/dummy.c can be in both.''' + ac_version = self.config['ac_version'] + main_filelist = self.filelist(main_modules) + tests_filelist = self.filelist(tests_modules) + tests_filelist = \ + [ # Begin to sort filelist + file.replace('lib/', 'tests=lib/', 1) \ + if file.startswith('lib/') else file + for file in tests_filelist + ] # Finish to sort filelist + result = tuple([main_filelist, tests_filelist]) + return(result) + + def getAvoids(self): + '''GLModuleTable.getAvoids() -> list + + Return list of avoids.''' + return(list(self.avoids)) + + def setAvoids(self, modules): + '''GLModuleTable.setAvoids(modules) + + Specify list of avoids.''' + for module in modules: + if type(module) is not GLModule: + raise(TypeError('each module must be a GLModule instance')) + self.avoids = sorted(set(modules)) + + def getBaseModules(self): + '''GLModuleTable.getBaseModules() -> list + + Return list of base modules.''' + return(list(self.base_modules)) + + def setBaseModules(self, modules): + '''GLModuleTable.setBaseModules(modules) + + Specify list of base modules.''' + for module in modules: + if type(module) is not GLModule: + raise(TypeError('each module must be a GLModule instance')) + self.base_modules = sorted(set(modules)) + + def getFinalModules(self): + '''GLModuleTable.getFinalModules() -> list + + Return list of final modules.''' + return(list(self.final_modules)) + + def setFinalModules(self, modules): + '''GLModuleTable.setFinalModules(modules) + + Specify list of final modules.''' + for module in modules: + if type(module) is not GLModule: + raise(TypeError('each module must be a GLModule instance')) + self.final_modules = sorted(set(modules)) + + def getMainModules(self): + '''GLModuleTable.getMainModules() -> list + + Return list of main modules.''' + return(list(self.main_modules)) + + def setMainModules(self, modules): + '''GLModuleTable.setMainModules(modules) + + Specify list of main modules.''' + for module in modules: + if type(module) is not GLModule: + raise(TypeError('each module must be a GLModule instance')) + self.main_modules = sorted(set(modules)) + + def getTestsModules(self): + '''GLModuleTable.getTestsModules() -> list + + Return list of tests modules.''' + return(list(self.tests_modules)) + + def setTestsModules(self, modules): + '''GLModuleTable.setTestsModules(modules) + Specify list of tests modules.''' + for module in modules: + if type(module) is not GLModule: + raise(TypeError('each module must be a GLModule instance')) + self.tests_modules = sorted(set(modules)) diff --git a/pygnulib/GLTestDir.py b/pygnulib/GLTestDir.py index 58663eab00..562e170678 100644 --- a/pygnulib/GLTestDir.py +++ b/pygnulib/GLTestDir.py @@ -59,929 +59,940 @@ normpath = os.path.normpath # Define GLTestDir class #=============================================================================== class GLTestDir(object): - '''GLTestDir class is used to create a scratch package with the given - list of the modules.''' - - def __init__(self, config, testdir): - '''GLTestDir.__init__(config, testdir) -> GLTestDir - - Create new GLTestDir instance.''' - if type(config) is not GLConfig: - raise(TypeError('config must be a GLConfig, not %s' % \ - type(config).__name__)) - if type(testdir) is bytes or type(testdir) is string: - if type(testdir) is bytes: - testdir = testdir.decode(ENCS['default']) - self.config = config - self.testdir = os.path.normpath(testdir) - if not os.path.exists(self.testdir): - try: # Try to create directory - os.mkdir(self.testdir) - except Exception as error: - raise(GLError(19, self.testdir)) - self.emiter = GLEmiter(self.config) - self.filesystem = GLFileSystem(self.config) - self.modulesystem = GLModuleSystem(self.config) - self.moduletable = GLModuleTable(self.config) - self.assistant = GLFileAssistant(self.config) - self.makefiletable = GLMakefileTable(self.config) - - # Subdirectory names. - self.config.setSourceBase('gllib') - self.config.setM4Base('glm4') - self.config.setDocBase('gldoc') - self.config.setTestsBase('gltests') - self.config.setMacroPrefix('gl') - self.config.resetPoBase() - self.config.resetPoDomain() - self.config.resetWitnessCMacro() - self.config.resetVCFiles() - - def rewrite_files(self, files): - '''GLTestDir.rewrite_files(files) - - Replace auxdir, docbase, sourcebase, m4base and testsbase from default - to their version from config.''' - if type(files) is not list: - raise(TypeError( - 'files argument must has list type, not %s' % type(files).__name__)) - files = \ - [ # Begin to convert bytes to string - file.decode(ENCS['default']) \ - if type(file) is bytes else file \ - for file in files - ] # Finish to convert bytes to string - for file in files: - if type(file) is not string: - raise(TypeError('each file must be a string instance')) - files = sorted(set(files)) - auxdir = self.config['auxdir'] - docbase = self.config['docbase'] - sourcebase = self.config['sourcebase'] - m4base = self.config['m4base'] - testsbase = self.config['testsbase'] - result = list() - for file in files: - if file.startswith('build-aux/'): - path = constants.substart('build-aux/', '%s/' % auxdir, file) - elif file.startswith('doc/'): - path = constants.substart('doc/', '%s/' % docbase, file) - elif file.startswith('lib/'): - path = constants.substart('lib/', '%s/' % sourcebase, file) - elif file.startswith('m4/'): - path = constants.substart('m4/', '%s/' % m4base, file) - elif file.startswith('tests/'): - path = constants.substart('tests/', '%s/' % testsbase, file) - elif file.startswith('tests=lib/'): - path = constants.substart('tests=lib/', '%s/' % testsbase, file) - elif file.startswith('top/'): - path = constants.substart('top/', '', file) - else: # file is not a special file - path = file - result += [os.path.normpath(path)] - result = sorted(set(result)) - return(list(result)) - - def execute(self): - '''GLTestDir.execute() - - Create a scratch package with the given modules.''' - localdir = self.config['localdir'] - auxdir = self.config['auxdir'] - testflags = list(self.config['testflags']) - sourcebase = self.config['sourcebase'] - m4base = self.config['m4base'] - pobase = self.config['pobase'] - docbase = self.config['docbase'] - testsbase = self.config['testsbase'] - libname = self.config['libname'] - libtool = self.config['libtool'] - witness_c_macro = self.config['witness_c_macro'] - symbolic = self.config['symbolic'] - lsymbolic = self.config['lsymbolic'] - single_configure = self.config['single_configure'] - include_guard_prefix = self.config['include_guard_prefix'] - macro_prefix = self.config['macro_prefix'] - verbose = self.config['verbosity'] - - base_modules = [self.modulesystem.find(m) for m in self.config['modules']] - if not base_modules: - base_modules = self.modulesystem.list() - base_modules = [self.modulesystem.find(m) for m in base_modules] - # All modules together. - # Except config-h, which breaks all modules which use HAVE_CONFIG_H. - # Except ftruncate, mountlist, which abort the configuration on mingw. - # Except lib-ignore, which leads to link errors when Sun C++ is used. - base_modules = sorted(set(base_modules)) - base_modules = [module for module in base_modules if str(module) not in \ - ['config-h', 'ftruncate', 'mountlist', 'lib-ignore']] - - # When computing transitive closures, don't consider $module to depend on - # $module-tests. Need this because tests are implicitly GPL and may depend - # on GPL modules - therefore we don't want a warning in this case. - saved_testflags = list(self.config['testflags']) - self.config.disableTestFlag(TESTS['tests']) - for requested_module in base_modules: - requested_licence = requested_module.getLicense() - # Here we use self.moduletable.transitive_closure([module]), not just - # module.getDependencies, so that we also detect weird situations like - # an LGPL module which depends on a GPLed build tool module which depends - # on a GPL module. - if requested_licence != 'GPL': - modules = self.moduletable.transitive_closure([requested_module]) - for module in modules: - license = module.getLicense() - errormsg = 'module %s depends on a module ' % requested_module - errormsg += 'with an incompatible license: %s\n' % module - if requested_licence == 'GPLv2+': - if license not in ['GPLv2+', 'LGPLv2+']: - sys.stderr.write(errormsg) - elif requested_licence in ['LGPL']: - if license not in ['LGPL', 'LGPLv2+']: - sys.stderr.write(errormsg) - elif requested_licence in ['LGPLv2+']: - if license not in ['LGPLv2+']: - sys.stderr.write(errormsg) - self.config.setTestFlags(saved_testflags) - - # Determine final module list. - modules = self.moduletable.transitive_closure(base_modules) - final_modules = list(modules) - - # Show final module list. - if verbose >= 0: - bold_on = '' - bold_off = '' - term = os.getenv('TERM') - if term == 'xterm': - bold_on = '\x1b[1m' - bold_off = '\x1b[0m' - print('Module list with included dependencies (indented):') - for module in final_modules: - if str(module) in self.config.getModules(): - print(' %s%s%s' % (bold_on, module, bold_off)) - else: # if str(module) not in self.config.getModules() - print(' %s' % module) - - # Generate lists of the modules. - if single_configure: - # Determine main module list and tests-related module list separately. - main_modules, tests_modules = \ - self.moduletable.transitive_closure_separately( - base_modules, final_modules) - # Print main_modules and tests_modules. - if verbose >= 1: - print('Main module list:') - for module in main_modules: - print(' %s' % str(module)) - print('Tests-related module list:') - for module in tests_modules: - print(' %s' % str(module)) - # Determine whether a $testsbase/libtests.a is needed. - libtests = False - for module in tests_modules: - files = module.getFiles() + '''GLTestDir class is used to create a scratch package with the given + list of the modules.''' + + def __init__(self, config, testdir): + '''GLTestDir.__init__(config, testdir) -> GLTestDir + + Create new GLTestDir instance.''' + if type(config) is not GLConfig: + raise(TypeError('config must be a GLConfig, not %s' % + type(config).__name__)) + if type(testdir) is bytes or type(testdir) is string: + if type(testdir) is bytes: + testdir = testdir.decode(ENCS['default']) + self.config = config + self.testdir = os.path.normpath(testdir) + if not os.path.exists(self.testdir): + try: # Try to create directory + os.mkdir(self.testdir) + except Exception as error: + raise(GLError(19, self.testdir)) + self.emiter = GLEmiter(self.config) + self.filesystem = GLFileSystem(self.config) + self.modulesystem = GLModuleSystem(self.config) + self.moduletable = GLModuleTable(self.config) + self.assistant = GLFileAssistant(self.config) + self.makefiletable = GLMakefileTable(self.config) + + # Subdirectory names. + self.config.setSourceBase('gllib') + self.config.setM4Base('glm4') + self.config.setDocBase('gldoc') + self.config.setTestsBase('gltests') + self.config.setMacroPrefix('gl') + self.config.resetPoBase() + self.config.resetPoDomain() + self.config.resetWitnessCMacro() + self.config.resetVCFiles() + + def rewrite_files(self, files): + '''GLTestDir.rewrite_files(files) + + Replace auxdir, docbase, sourcebase, m4base and testsbase from default + to their version from config.''' + if type(files) is not list: + raise(TypeError( + 'files argument must has list type, not %s' % type(files).__name__)) + files = \ + [ # Begin to convert bytes to string + file.decode(ENCS['default']) \ + if type(file) is bytes else file \ + for file in files + ] # Finish to convert bytes to string for file in files: - if file.startswith('lib/'): - libtests = True - break - if libtests: - self.config.enableLibtests() - - if single_configure: - # Add dummy package if it is needed. - main_modules = self.moduletable.add_dummy(main_modules) - if 'dummy' in [str(module) for module in main_modules]: - main_modules = [m for m in main_modules if str(m) != 'dummy'] - dummy = self.modulesystem.find('dummy') - main_modules = sorted(set(main_modules)) +[dummy] - if libtests: # if we need to use libtests.a - tests_modules = self.moduletable.add_dummy(tests_modules) - if 'dummy' in [str(module) for module in tests_modules]: - tests_modules = [m for m in tests_modules if str(m) != 'dummy'] - dummy = self.modulesystem.find('dummy') - tests_modules = sorted(set(tests_modules)) +[dummy] - else: # if not single_configure - modules = self.moduletable.add_dummy(modules) - if 'dummy' in [str(module) for module in modules]: - modules = [m for m in modules if str(m) != 'dummy'] - dummy = self.modulesystem.find('dummy') - modules = sorted(set(modules)) +[dummy] - - # Show banner notice of every module. - if single_configure: - for module in main_modules: - notice = module.getNotice() - if notice: - print('Notice from module %s:' % str(module)) - pattern = compiler('^(.*?)$', re.S | re.M) - notice = pattern.sub(' \\1', notice) - print(notice) - else: # if not single_configure - for module in modules: - notice = module.getNotice() - if notice: - print('Notice from module %s:' % str(module)) - pattern = compiler('^(.*?)$', re.S | re.M) - notice = pattern.sub(' \\1', notice) - print(notice) - - # Determine final file list. - if single_configure: - main_filelist, tests_filelist = \ - self.moduletable.filelist_separately(main_modules, tests_modules) - filelist = sorted(set(main_filelist +tests_filelist)) - else: # if not single_configure - filelist = self.moduletable.filelist(modules) - - filelist = sorted(set(filelist)) - - # Print list of files. - if verbose >= 0: - print('File list:') - for file in filelist: - if file.startswith('tests=lib/'): - rest = file[10:] - print(' lib/%s -> tests/%s' % (rest, rest)) - else: - print(' %s' % file) - - # Add files for which the copy in gnulib is newer than the one that - # "automake --add-missing --copy" would provide. - filelist += ['build-aux/config.guess', 'build-aux/config.sub'] - filelist = sorted(set(filelist)) - - # Create directories. - directories = [os.path.dirname(file) \ - for file in self.rewrite_files(filelist)] - directories = sorted(set(directories)) - - # Copy files or make symbolic links. - filetable = list() - for src in filelist: - dest = self.rewrite_files([src])[-1] - filetable += [tuple([dest, src])] - for row in filetable: - src = row[1] - dest = row[0] - destpath = joinpath(self.testdir, dest) - dirname = os.path.dirname(destpath) - if not isdir(dirname): - os.makedirs(dirname) - if src.startswith('tests=lib/'): - src = constants.substart('tests=lib/', 'lib/', src) - lookedup, flag = self.filesystem.lookup(src) - if isfile(destpath): - os.remove(destpath) - if flag: - shutil.copy(lookedup, destpath) - else: # if not flag - if symbolic or (lsymbolic and lookedup == joinpath(localdir, src)): - constants.link_relative(lookedup, destpath) - else: - shutil.copy(lookedup, destpath) - - # Create $sourcebase/Makefile.am. - for_test = True - directory = joinpath(self.testdir, sourcebase) - if not isdir(directory): - os.mkdir(directory) - destfile = joinpath(directory, 'Makefile.am') - if single_configure: - emit, uses_subdirs = self.emiter.lib_Makefile_am(destfile, main_modules, - self.moduletable, self.makefiletable, '', for_test) - else: # if not single_configure - emit, uses_subdirs = self.emiter.lib_Makefile_am(destfile, modules, - self.moduletable, self.makefiletable, '', for_test) - with codecs.open(destfile, 'wb', 'UTF-8') as file: - file.write(emit) - any_uses_subdirs = uses_subdirs - - # Create $m4base/Makefile.am. - directory = joinpath(self.testdir, m4base) - if not isdir(directory): - os.mkdir(directory) - destfile = joinpath(directory, 'Makefile.am') - emit = string() - emit += '## Process this file with automake to produce Makefile.in.\n\n' - emit += 'EXTRA_DIST =\n' - for file in filelist: - if file.startswith('m4/'): - file = constants.substart('m4/', '', file) - emit += 'EXTRA_DIST += %s\n' % file - emit = constants.nlconvert(emit) - if type(emit) is bytes: - emit = emit.decode(ENCS['default']) - with codecs.open(destfile, 'wb', 'UTF-8') as file: - file.write(emit) - - subdirs = [sourcebase, m4base] - subdirs_with_configure_ac = list() - - testsbase_appened = False - inctests = self.config.checkTestFlag(TESTS['tests']) - if inctests: - directory = joinpath(self.testdir, testsbase) - if not isdir(directory): - os.mkdir(directory) - if single_configure: - # Create $testsbase/Makefile.am. + if type(file) is not string: + raise(TypeError('each file must be a string instance')) + files = sorted(set(files)) + auxdir = self.config['auxdir'] + docbase = self.config['docbase'] + sourcebase = self.config['sourcebase'] + m4base = self.config['m4base'] + testsbase = self.config['testsbase'] + result = list() + for file in files: + if file.startswith('build-aux/'): + path = constants.substart('build-aux/', '%s/' % auxdir, file) + elif file.startswith('doc/'): + path = constants.substart('doc/', '%s/' % docbase, file) + elif file.startswith('lib/'): + path = constants.substart('lib/', '%s/' % sourcebase, file) + elif file.startswith('m4/'): + path = constants.substart('m4/', '%s/' % m4base, file) + elif file.startswith('tests/'): + path = constants.substart('tests/', '%s/' % testsbase, file) + elif file.startswith('tests=lib/'): + path = constants.substart( + 'tests=lib/', '%s/' % testsbase, file) + elif file.startswith('top/'): + path = constants.substart('top/', '', file) + else: # file is not a special file + path = file + result += [os.path.normpath(path)] + result = sorted(set(result)) + return(list(result)) + + def execute(self): + '''GLTestDir.execute() + + Create a scratch package with the given modules.''' + localdir = self.config['localdir'] + auxdir = self.config['auxdir'] + testflags = list(self.config['testflags']) + sourcebase = self.config['sourcebase'] + m4base = self.config['m4base'] + pobase = self.config['pobase'] + docbase = self.config['docbase'] + testsbase = self.config['testsbase'] + libname = self.config['libname'] + libtool = self.config['libtool'] + witness_c_macro = self.config['witness_c_macro'] + symbolic = self.config['symbolic'] + lsymbolic = self.config['lsymbolic'] + single_configure = self.config['single_configure'] + include_guard_prefix = self.config['include_guard_prefix'] + macro_prefix = self.config['macro_prefix'] + verbose = self.config['verbosity'] + + base_modules = [self.modulesystem.find( + m) for m in self.config['modules']] + if not base_modules: + base_modules = self.modulesystem.list() + base_modules = [self.modulesystem.find(m) for m in base_modules] + # All modules together. + # Except config-h, which breaks all modules which use HAVE_CONFIG_H. + # Except ftruncate, mountlist, which abort the configuration on mingw. + # Except lib-ignore, which leads to link errors when Sun C++ is used. + base_modules = sorted(set(base_modules)) + base_modules = [module for module in base_modules if str(module) not in + ['config-h', 'ftruncate', 'mountlist', 'lib-ignore']] + + # When computing transitive closures, don't consider $module to depend on + # $module-tests. Need this because tests are implicitly GPL and may depend + # on GPL modules - therefore we don't want a warning in this case. + saved_testflags = list(self.config['testflags']) + self.config.disableTestFlag(TESTS['tests']) + for requested_module in base_modules: + requested_licence = requested_module.getLicense() + # Here we use self.moduletable.transitive_closure([module]), not just + # module.getDependencies, so that we also detect weird situations like + # an LGPL module which depends on a GPLed build tool module which depends + # on a GPL module. + if requested_licence != 'GPL': + modules = self.moduletable.transitive_closure( + [requested_module]) + for module in modules: + license = module.getLicense() + errormsg = 'module %s depends on a module ' % requested_module + errormsg += 'with an incompatible license: %s\n' % module + if requested_licence == 'GPLv2+': + if license not in ['GPLv2+', 'LGPLv2+']: + sys.stderr.write(errormsg) + elif requested_licence in ['LGPL']: + if license not in ['LGPL', 'LGPLv2+']: + sys.stderr.write(errormsg) + elif requested_licence in ['LGPLv2+']: + if license not in ['LGPLv2+']: + sys.stderr.write(errormsg) + self.config.setTestFlags(saved_testflags) + + # Determine final module list. + modules = self.moduletable.transitive_closure(base_modules) + final_modules = list(modules) + + # Show final module list. + if verbose >= 0: + bold_on = '' + bold_off = '' + term = os.getenv('TERM') + if term == 'xterm': + bold_on = '\x1b[1m' + bold_off = '\x1b[0m' + print('Module list with included dependencies (indented):') + for module in final_modules: + if str(module) in self.config.getModules(): + print(' %s%s%s' % (bold_on, module, bold_off)) + else: # if str(module) not in self.config.getModules() + print(' %s' % module) + + # Generate lists of the modules. + if single_configure: + # Determine main module list and tests-related module list separately. + main_modules, tests_modules = \ + self.moduletable.transitive_closure_separately( + base_modules, final_modules) + # Print main_modules and tests_modules. + if verbose >= 1: + print('Main module list:') + for module in main_modules: + print(' %s' % str(module)) + print('Tests-related module list:') + for module in tests_modules: + print(' %s' % str(module)) + # Determine whether a $testsbase/libtests.a is needed. + libtests = False + for module in tests_modules: + files = module.getFiles() + for file in files: + if file.startswith('lib/'): + libtests = True + break + if libtests: + self.config.enableLibtests() + + if single_configure: + # Add dummy package if it is needed. + main_modules = self.moduletable.add_dummy(main_modules) + if 'dummy' in [str(module) for module in main_modules]: + main_modules = [m for m in main_modules if str(m) != 'dummy'] + dummy = self.modulesystem.find('dummy') + main_modules = sorted(set(main_modules)) + [dummy] + if libtests: # if we need to use libtests.a + tests_modules = self.moduletable.add_dummy(tests_modules) + if 'dummy' in [str(module) for module in tests_modules]: + tests_modules = [ + m for m in tests_modules if str(m) != 'dummy'] + dummy = self.modulesystem.find('dummy') + tests_modules = sorted(set(tests_modules)) + [dummy] + else: # if not single_configure + modules = self.moduletable.add_dummy(modules) + if 'dummy' in [str(module) for module in modules]: + modules = [m for m in modules if str(m) != 'dummy'] + dummy = self.modulesystem.find('dummy') + modules = sorted(set(modules)) + [dummy] + + # Show banner notice of every module. + if single_configure: + for module in main_modules: + notice = module.getNotice() + if notice: + print('Notice from module %s:' % str(module)) + pattern = compiler('^(.*?)$', re.S | re.M) + notice = pattern.sub(' \\1', notice) + print(notice) + else: # if not single_configure + for module in modules: + notice = module.getNotice() + if notice: + print('Notice from module %s:' % str(module)) + pattern = compiler('^(.*?)$', re.S | re.M) + notice = pattern.sub(' \\1', notice) + print(notice) + + # Determine final file list. + if single_configure: + main_filelist, tests_filelist = \ + self.moduletable.filelist_separately( + main_modules, tests_modules) + filelist = sorted(set(main_filelist + tests_filelist)) + else: # if not single_configure + filelist = self.moduletable.filelist(modules) + + filelist = sorted(set(filelist)) + + # Print list of files. + if verbose >= 0: + print('File list:') + for file in filelist: + if file.startswith('tests=lib/'): + rest = file[10:] + print(' lib/%s -> tests/%s' % (rest, rest)) + else: + print(' %s' % file) + + # Add files for which the copy in gnulib is newer than the one that + # "automake --add-missing --copy" would provide. + filelist += ['build-aux/config.guess', 'build-aux/config.sub'] + filelist = sorted(set(filelist)) + + # Create directories. + directories = [os.path.dirname(file) + for file in self.rewrite_files(filelist)] + directories = sorted(set(directories)) + + # Copy files or make symbolic links. + filetable = list() + for src in filelist: + dest = self.rewrite_files([src])[-1] + filetable += [tuple([dest, src])] + for row in filetable: + src = row[1] + dest = row[0] + destpath = joinpath(self.testdir, dest) + dirname = os.path.dirname(destpath) + if not isdir(dirname): + os.makedirs(dirname) + if src.startswith('tests=lib/'): + src = constants.substart('tests=lib/', 'lib/', src) + lookedup, flag = self.filesystem.lookup(src) + if isfile(destpath): + os.remove(destpath) + if flag: + shutil.copy(lookedup, destpath) + else: # if not flag + if symbolic or (lsymbolic and lookedup == joinpath(localdir, src)): + constants.link_relative(lookedup, destpath) + else: + shutil.copy(lookedup, destpath) + + # Create $sourcebase/Makefile.am. + for_test = True + directory = joinpath(self.testdir, sourcebase) + if not isdir(directory): + os.mkdir(directory) destfile = joinpath(directory, 'Makefile.am') - print(repr(destfile)) - witness_macro = '%stests_WITNESS' % macro_prefix - emit, uses_subdirs = self.emiter.tests_Makefile_am(destfile, - tests_modules, self.makefiletable, witness_macro, for_test) + if single_configure: + emit, uses_subdirs = self.emiter.lib_Makefile_am(destfile, main_modules, + self.moduletable, self.makefiletable, '', for_test) + else: # if not single_configure + emit, uses_subdirs = self.emiter.lib_Makefile_am(destfile, modules, + self.moduletable, self.makefiletable, '', for_test) with codecs.open(destfile, 'wb', 'UTF-8') as file: - file.write(emit) - else: # if not single_configure - # Create $testsbase/Makefile.am. + file.write(emit) + any_uses_subdirs = uses_subdirs + + # Create $m4base/Makefile.am. + directory = joinpath(self.testdir, m4base) + if not isdir(directory): + os.mkdir(directory) destfile = joinpath(directory, 'Makefile.am') - libtests = False - self.config.disableLibtests() - emit, uses_subdirs = self.emiter.tests_Makefile_am(destfile, - modules, self.makefiletable, '', for_test) + emit = string() + emit += '## Process this file with automake to produce Makefile.in.\n\n' + emit += 'EXTRA_DIST =\n' + for file in filelist: + if file.startswith('m4/'): + file = constants.substart('m4/', '', file) + emit += 'EXTRA_DIST += %s\n' % file + emit = constants.nlconvert(emit) + if type(emit) is bytes: + emit = emit.decode(ENCS['default']) with codecs.open(destfile, 'wb', 'UTF-8') as file: - file.write(emit) - # Viewed from the $testsbase subdirectory, $auxdir is different. + file.write(emit) + + subdirs = [sourcebase, m4base] + subdirs_with_configure_ac = list() + + testsbase_appened = False + inctests = self.config.checkTestFlag(TESTS['tests']) + if inctests: + directory = joinpath(self.testdir, testsbase) + if not isdir(directory): + os.mkdir(directory) + if single_configure: + # Create $testsbase/Makefile.am. + destfile = joinpath(directory, 'Makefile.am') + print(repr(destfile)) + witness_macro = '%stests_WITNESS' % macro_prefix + emit, uses_subdirs = self.emiter.tests_Makefile_am(destfile, + tests_modules, self.makefiletable, witness_macro, for_test) + with codecs.open(destfile, 'wb', 'UTF-8') as file: + file.write(emit) + else: # if not single_configure + # Create $testsbase/Makefile.am. + destfile = joinpath(directory, 'Makefile.am') + libtests = False + self.config.disableLibtests() + emit, uses_subdirs = self.emiter.tests_Makefile_am(destfile, + modules, self.makefiletable, '', for_test) + with codecs.open(destfile, 'wb', 'UTF-8') as file: + file.write(emit) + # Viewed from the $testsbase subdirectory, $auxdir is different. + emit = string() + saved_auxdir = self.config['auxdir'] + testsbase = '%s/' % os.path.normpath(testsbase) + counter = int() + auxdir = string() + finish = (len(testsbase.split('/')) - 1) + while counter < finish: + auxdir += '../' + counter += 1 + auxdir = os.path.normpath(joinpath(auxdir, saved_auxdir)) + testsbase = os.path.normpath(testsbase) + self.config.setAuxDir(auxdir) + # Create $testsbase/configure.ac. + emit += '# Process this file with autoconf ' + emit += 'to produce a configure script.\n' + emit += 'AC_INIT([dummy], [0])\n' + emit += 'AC_CONFIG_AUX_DIR([%s])\n' % auxdir + emit += 'AM_INIT_AUTOMAKE\n\n' + emit += 'AC_CONFIG_HEADERS([config.h])\n\n' + emit += 'AC_PROG_CC\n' + emit += 'AC_PROG_INSTALL\n' + emit += 'AC_PROG_MAKE_SET\n' + emit += 'gl_PROG_AR_RANLIB\n\n' + if uses_subdirs: + emit += 'AM_PROG_CC_C_O\n\n' + snippets = list() + for module in modules: + if str(module) in ['gnumakefile', 'maintainer-makefile']: + # These are meant to be used only in the top-level directory. + pass + # if str(module) not in ['gnumakefile', 'maintainer-makefile'] + else: + snippet = module.getAutoconfSnippet_Early() + lines = [line for line in snippet.split( + '\n') if line.strip()] + snippet = '\n'.join(lines) + pattern = compiler( + 'AC_REQUIRE\\(\\[([^()].*?)\\]\\)', re.S | re.M) + snippet = pattern.sub('\\1', snippet) + snippet = snippet.strip() + snippets += [snippet] + snippets = [snippet for snippet in snippets if snippet.strip()] + emit += '%s\n' % '\n'.join(snippets) + if libtool: + emit += 'LT_INIT([win32-dll])\n' + emit += 'LT_LANG([C++])\n' + emit += 'AM_CONDITIONAL([GL_COND_LIBTOOL], [true])\n' + emit += 'gl_cond_libtool=true\n' + else: # if not libtool + emit += 'AM_CONDITIONAL([GL_COND_LIBTOOL], [false])\n' + emit += 'gl_cond_libtool=false\n' + emit += 'gl_libdeps=\n' + emit += 'gl_ltlibdeps=\n' + # Wrap the set of autoconf snippets into an autoconf macro that is then + # invoked. This is needed because autoconf does not support AC_REQUIRE + # at the top level: + # error: AC_REQUIRE(gt_CSHARPCOMP): cannot be used outside of an + # AC_DEFUN'd macro + # but we want the AC_REQUIRE to have its normal meaning (provide one + # expansion of the required macro before the current point, and only + # one expansion total). + emit += 'AC_DEFUN([gl_INIT], [\n' + replace_auxdir = True + emit += "gl_m4_base='../%s'\n" % m4base + emit += self.emiter.initmacro_start(macro_prefix) + # We don't have explicit ordering constraints between the various + # autoconf snippets. It's cleanest to put those of the library before + # those of the tests. + emit += "gl_source_base='../%s'\n" % sourcebase + emit += self.emiter.autoconfSnippets(modules, + self.moduletable, self.assistant, 1, False, False, False, + replace_auxdir) + emit += "gl_source_base='.'" + emit += self.emiter.autoconfSnippets(modules, + self.moduletable, self.assistant, 2, False, False, False, + replace_auxdir) + emit += self.emiter.initmacro_end(macro_prefix) + # _LIBDEPS and _LTLIBDEPS variables are not needed if this library is + # created using libtool, because libtool already handles the + # dependencies. + if not libtool: + libname_upper = libname.upper().replace('-', '_') + emit += ' %s_LIBDEPS="$gl_libdeps"\n' % libname_upper + emit += ' AC_SUBST([%s_LIBDEPS])\n' % libname_upper + emit += ' %s_LTLIBDEPS="$gl_ltlibdeps"\n' % libname_upper + emit += ' AC_SUBST([%s_LTLIBDEPS])\n' % libname_upper + emit += '])\n' + # FIXME use $sourcebase or $testsbase? + emit += self.emiter.initmacro_done(macro_prefix, sourcebase) + emit += '\ngl_INIT\n\n' + # Usually $testsbase/config.h will be a superset of config.h. Verify + # this by "merging" config.h into $testsbase/config.h; look out for gcc + # warnings. + emit += 'AH_TOP([#include \"../config.h\"])\n\n' + emit += 'AC_CONFIG_FILES([Makefile])\n' + emit += 'AC_OUTPUT\n' + emit = constants.nlconvert(emit) + if type(emit) is bytes: + emit = emit.decode(ENCS['default']) + path = joinpath(self.testdir, testsbase, 'configure.ac') + with codecs.open(path, 'wb', 'UTF-8') as file: + file.write(emit) + + # Restore changed variables. + self.config.setAuxDir(saved_auxdir) + auxdir = self.config['auxdir'] + subdirs_with_configure_ac += [testsbase] + + subdirs += [testsbase] + testsbase_appened = True + + # Create Makefile.am. + emit = string() + emit += '## Process this file with automake to produce Makefile.in.\n\n' + emit += 'AUTOMAKE_OPTIONS = 1.5 foreign\n\n' + emit += 'SUBDIRS = %s\n\n' % ' '.join(subdirs) + emit += 'ACLOCAL_AMFLAGS = -I %s\n' % m4base + emit = constants.nlconvert(emit) + if type(emit) is bytes: + emit = emit.decode(ENCS['default']) + path = joinpath(self.testdir, 'Makefile.am') + with codecs.open(path, 'wb', 'UTF-8') as file: + file.write(emit) + + # Create configure.ac emit = string() - saved_auxdir = self.config['auxdir'] - testsbase = '%s/' % os.path.normpath(testsbase) - counter = int() - auxdir = string() - finish = (len(testsbase.split('/')) -1) - while counter < finish: - auxdir += '../' - counter += 1 - auxdir = os.path.normpath(joinpath(auxdir, saved_auxdir)) - testsbase = os.path.normpath(testsbase) - self.config.setAuxDir(auxdir) - # Create $testsbase/configure.ac. emit += '# Process this file with autoconf ' emit += 'to produce a configure script.\n' emit += 'AC_INIT([dummy], [0])\n' - emit += 'AC_CONFIG_AUX_DIR([%s])\n' % auxdir + if auxdir != '.': + emit += 'AC_CONFIG_AUX_DIR([%s])\n' % auxdir emit += 'AM_INIT_AUTOMAKE\n\n' emit += 'AC_CONFIG_HEADERS([config.h])\n\n' emit += 'AC_PROG_CC\n' emit += 'AC_PROG_INSTALL\n' - emit += 'AC_PROG_MAKE_SET\n' + emit += 'AC_PROG_MAKE_SET\n\n' + emit += '# For autobuild.\n' + emit += 'AC_CANONICAL_BUILD\n' + emit += 'AC_CANONICAL_HOST\n\n' + emit += 'm4_pattern_forbid([^gl_[A-Z]])dnl the gnulib macro namespace\n' + emit += 'm4_pattern_allow([^gl_ES$])dnl a valid locale name\n' + emit += 'm4_pattern_allow([^gl_LIBOBJS$])dnl a variable\n' + emit += 'm4_pattern_allow([^gl_LTLIBOBJS$])dnl a variable\n\n' emit += 'gl_PROG_AR_RANLIB\n\n' - if uses_subdirs: - emit += 'AM_PROG_CC_C_O\n\n' + if any_uses_subdirs: + emit += 'AM_PROG_CC_C_O\n' snippets = list() - for module in modules: - if str(module) in ['gnumakefile', 'maintainer-makefile']: - # These are meant to be used only in the top-level directory. - pass - else: # if str(module) not in ['gnumakefile', 'maintainer-makefile'] - snippet = module.getAutoconfSnippet_Early() - lines = [line for line in snippet.split('\n') if line.strip()] - snippet = '\n'.join(lines) - pattern = compiler('AC_REQUIRE\\(\\[([^()].*?)\\]\\)', re.S | re.M) - snippet = pattern.sub('\\1', snippet) - snippet = snippet.strip() - snippets += [snippet] + for module in final_modules: + if single_configure: + solution = True + else: # if not single_configure + solution = module.isNonTests() + if solution: + snippet = module.getAutoconfSnippet_Early() + lines = [line for line in snippet.split('\n') if line.strip()] + snippet = '\n'.join(lines) + pattern = compiler( + 'AC_REQUIRE\\(\\[([^()].*?)\\]\\)', re.S | re.M) + snippet = pattern.sub('\\1', snippet) + snippet = snippet.strip() + snippets += [snippet] snippets = [snippet for snippet in snippets if snippet.strip()] emit += '%s\n' % '\n'.join(snippets) if libtool: - emit += 'LT_INIT([win32-dll])\n' - emit += 'LT_LANG([C++])\n' - emit += 'AM_CONDITIONAL([GL_COND_LIBTOOL], [true])\n' - emit += 'gl_cond_libtool=true\n' - else: # if not libtool - emit += 'AM_CONDITIONAL([GL_COND_LIBTOOL], [false])\n' - emit += 'gl_cond_libtool=false\n' - emit += 'gl_libdeps=\n' - emit += 'gl_ltlibdeps=\n' + emit += 'LT_INIT([win32-dll])\n' + emit += 'LT_LANG([C++])\n' + emit += 'AM_CONDITIONAL([GL_COND_LIBTOOL], [true])\n' + emit += 'gl_cond_libtool=true\n' + else: # if not libtool + emit += 'AM_CONDITIONAL([GL_COND_LIBTOOL], [false])\n' + emit += 'gl_cond_libtool=false\n' + emit += 'gl_libdeps=\n' + emit += 'gl_ltlibdeps=\n' # Wrap the set of autoconf snippets into an autoconf macro that is then # invoked. This is needed because autoconf does not support AC_REQUIRE # at the top level: # error: AC_REQUIRE(gt_CSHARPCOMP): cannot be used outside of an # AC_DEFUN'd macro # but we want the AC_REQUIRE to have its normal meaning (provide one - # expansion of the required macro before the current point, and only - # one expansion total). + # expansion of the required macro before the current point, and only one + # expansion total). emit += 'AC_DEFUN([gl_INIT], [\n' - replace_auxdir = True - emit += "gl_m4_base='../%s'\n" % m4base + if auxdir != 'build-aux': + replace_auxdir = True + else: # auxdir == 'build-aux' + replace_auxdir = False + emit += 'gl_m4_base=\'%s\'\n' % m4base emit += self.emiter.initmacro_start(macro_prefix) - # We don't have explicit ordering constraints between the various - # autoconf snippets. It's cleanest to put those of the library before - # those of the tests. - emit += "gl_source_base='../%s'\n" % sourcebase - emit += self.emiter.autoconfSnippets(modules, - self.moduletable, self.assistant, 1, False, False, False, - replace_auxdir) - emit += "gl_source_base='.'" - emit += self.emiter.autoconfSnippets(modules, - self.moduletable, self.assistant, 2, False, False, False, - replace_auxdir) + emit += 'gl_source_base=\'%s\'\n' % sourcebase + if single_configure: + emit += self.emiter.autoconfSnippets(main_modules, self.moduletable, + self.assistant, 0, False, False, False, replace_auxdir) + else: # if not single_configure + emit += self.emiter.autoconfSnippets(modules, self.moduletable, + self.assistant, 1, False, False, False, replace_auxdir) emit += self.emiter.initmacro_end(macro_prefix) + if single_configure: + emit += ' gltests_libdeps=\n' + emit += ' gltests_ltlibdeps=\n' + emit += self.emiter.initmacro_start('%stests' % macro_prefix) + emit += ' gl_source_base=\'%s\'\n' % testsbase + # Define a tests witness macro. + emit += ' %stests_WITNESS=IN_GNULIB_TESTS\n' % macro_prefix + emit += ' AC_SUBST([%stests_WITNESS])\n' % macro_prefix + emit += ' gl_module_indicator_condition=$%stests_WITNESS\n' % \ + macro_prefix + emit += ' m4_pushdef([gl_MODULE_INDICATOR_CONDITION], ' + emit += '[$gl_module_indicator_condition])\n' + snippets = self.emiter.autoconfSnippets(tests_modules, self.moduletable, + self.assistant, 1, True, False, False, replace_auxdir) + emit += snippets.strip() + emit += ' m4_popdef([gl_MODULE_INDICATOR_CONDITION])\n' + emit += self.emiter.initmacro_end('%stests' % macro_prefix) # _LIBDEPS and _LTLIBDEPS variables are not needed if this library is - # created using libtool, because libtool already handles the - # dependencies. + # created using libtool, because libtool already handles the dependencies. if not libtool: - libname_upper = libname.upper().replace('-', '_') - emit += ' %s_LIBDEPS="$gl_libdeps"\n' % libname_upper - emit += ' AC_SUBST([%s_LIBDEPS])\n' % libname_upper - emit += ' %s_LTLIBDEPS="$gl_ltlibdeps"\n' % libname_upper - emit += ' AC_SUBST([%s_LTLIBDEPS])\n' % libname_upper + libname_upper = libname.upper().replace('-', '_') + emit += ' %s_LIBDEPS="$gl_libdeps"\n' % libname_upper + emit += ' AC_SUBST([%s_LIBDEPS])\n' % libname_upper + emit += ' %s_LTLIBDEPS="$gl_ltlibdeps"\n' % libname_upper + emit += ' AC_SUBST([%s_LTLIBDEPS])\n' % libname_upper + if single_configure and libtests: + emit += ' LIBTESTS_LIBDEPS="$gltests_libdeps"\n' + emit += ' AC_SUBST([LIBTESTS_LIBDEPS])\n' emit += '])\n' - # FIXME use $sourcebase or $testsbase? emit += self.emiter.initmacro_done(macro_prefix, sourcebase) + if single_configure: + emit += self.emiter.initmacro_done('%stests' % + macro_prefix, testsbase) emit += '\ngl_INIT\n\n' - # Usually $testsbase/config.h will be a superset of config.h. Verify - # this by "merging" config.h into $testsbase/config.h; look out for gcc - # warnings. - emit += 'AH_TOP([#include \"../config.h\"])\n\n' - emit += 'AC_CONFIG_FILES([Makefile])\n' + if subdirs_with_configure_ac: + if single_configure: + emit += 'AC_CONFIG_SUBDIRS([%s])\n' % \ + ' '.join(subdirs_with_configure_ac[:-1]) + else: # if not single_configure + emit += 'AC_CONFIG_SUBDIRS([%s])\n' % \ + ' '.join(subdirs_with_configure_ac) + makefiles = ['Makefile'] + for directory in subdirs: + # For subdirs that have a configure.ac by their own, it's the subdir's + # configure.ac which creates the subdir's Makefile.am, not this one. + makefiles += [joinpath(directory, 'Makefile')] + if not single_configure: + makefiles = makefiles[:-1] + emit += 'AC_CONFIG_FILES([%s])\n' % ' '.join(makefiles) emit += 'AC_OUTPUT\n' - emit = constants.nlconvert(emit) - if type(emit) is bytes: - emit = emit.decode(ENCS['default']) - path = joinpath(self.testdir, testsbase, 'configure.ac') + path = joinpath(self.testdir, 'configure.ac') with codecs.open(path, 'wb', 'UTF-8') as file: - file.write(emit) - - # Restore changed variables. - self.config.setAuxDir(saved_auxdir) - auxdir = self.config['auxdir'] - subdirs_with_configure_ac += [testsbase] - - subdirs += [testsbase] - testsbase_appened = True - - # Create Makefile.am. - emit = string() - emit += '## Process this file with automake to produce Makefile.in.\n\n' - emit += 'AUTOMAKE_OPTIONS = 1.5 foreign\n\n' - emit += 'SUBDIRS = %s\n\n' % ' '.join(subdirs) - emit += 'ACLOCAL_AMFLAGS = -I %s\n' % m4base - emit = constants.nlconvert(emit) - if type(emit) is bytes: - emit = emit.decode(ENCS['default']) - path = joinpath(self.testdir, 'Makefile.am') - with codecs.open(path, 'wb', 'UTF-8') as file: - file.write(emit) - - # Create configure.ac - emit = string() - emit += '# Process this file with autoconf ' - emit += 'to produce a configure script.\n' - emit += 'AC_INIT([dummy], [0])\n' - if auxdir != '.': - emit += 'AC_CONFIG_AUX_DIR([%s])\n' % auxdir - emit += 'AM_INIT_AUTOMAKE\n\n' - emit += 'AC_CONFIG_HEADERS([config.h])\n\n' - emit += 'AC_PROG_CC\n' - emit += 'AC_PROG_INSTALL\n' - emit += 'AC_PROG_MAKE_SET\n\n' - emit += '# For autobuild.\n' - emit += 'AC_CANONICAL_BUILD\n' - emit += 'AC_CANONICAL_HOST\n\n' - emit += 'm4_pattern_forbid([^gl_[A-Z]])dnl the gnulib macro namespace\n' - emit += 'm4_pattern_allow([^gl_ES$])dnl a valid locale name\n' - emit += 'm4_pattern_allow([^gl_LIBOBJS$])dnl a variable\n' - emit += 'm4_pattern_allow([^gl_LTLIBOBJS$])dnl a variable\n\n' - emit += 'gl_PROG_AR_RANLIB\n\n' - if any_uses_subdirs: - emit += 'AM_PROG_CC_C_O\n' - snippets = list() - for module in final_modules: - if single_configure: - solution = True - else: # if not single_configure - solution = module.isNonTests() - if solution: - snippet = module.getAutoconfSnippet_Early() - lines = [line for line in snippet.split('\n') if line.strip()] - snippet = '\n'.join(lines) - pattern = compiler('AC_REQUIRE\\(\\[([^()].*?)\\]\\)', re.S | re.M) - snippet = pattern.sub('\\1', snippet) - snippet = snippet.strip() - snippets += [snippet] - snippets = [snippet for snippet in snippets if snippet.strip()] - emit += '%s\n' % '\n'.join(snippets) - if libtool: - emit += 'LT_INIT([win32-dll])\n' - emit += 'LT_LANG([C++])\n' - emit += 'AM_CONDITIONAL([GL_COND_LIBTOOL], [true])\n' - emit += 'gl_cond_libtool=true\n' - else: # if not libtool - emit += 'AM_CONDITIONAL([GL_COND_LIBTOOL], [false])\n' - emit += 'gl_cond_libtool=false\n' - emit += 'gl_libdeps=\n' - emit += 'gl_ltlibdeps=\n' - # Wrap the set of autoconf snippets into an autoconf macro that is then - # invoked. This is needed because autoconf does not support AC_REQUIRE - # at the top level: - # error: AC_REQUIRE(gt_CSHARPCOMP): cannot be used outside of an - # AC_DEFUN'd macro - # but we want the AC_REQUIRE to have its normal meaning (provide one - # expansion of the required macro before the current point, and only one - # expansion total). - emit += 'AC_DEFUN([gl_INIT], [\n' - if auxdir != 'build-aux': - replace_auxdir = True - else: # auxdir == 'build-aux' - replace_auxdir = False - emit += 'gl_m4_base=\'%s\'\n' % m4base - emit += self.emiter.initmacro_start(macro_prefix) - emit += 'gl_source_base=\'%s\'\n' % sourcebase - if single_configure: - emit += self.emiter.autoconfSnippets(main_modules, self.moduletable, - self.assistant, 0, False, False, False, replace_auxdir) - else: # if not single_configure - emit += self.emiter.autoconfSnippets(modules, self.moduletable, - self.assistant, 1, False, False, False, replace_auxdir) - emit += self.emiter.initmacro_end(macro_prefix) - if single_configure: - emit += ' gltests_libdeps=\n' - emit += ' gltests_ltlibdeps=\n' - emit += self.emiter.initmacro_start('%stests' % macro_prefix) - emit += ' gl_source_base=\'%s\'\n' % testsbase - # Define a tests witness macro. - emit += ' %stests_WITNESS=IN_GNULIB_TESTS\n' % macro_prefix - emit += ' AC_SUBST([%stests_WITNESS])\n' % macro_prefix - emit += ' gl_module_indicator_condition=$%stests_WITNESS\n' % \ - macro_prefix - emit += ' m4_pushdef([gl_MODULE_INDICATOR_CONDITION], ' - emit += '[$gl_module_indicator_condition])\n' - snippets = self.emiter.autoconfSnippets(tests_modules, self.moduletable, - self.assistant, 1, True, False, False, replace_auxdir) - emit += snippets.strip() - emit += ' m4_popdef([gl_MODULE_INDICATOR_CONDITION])\n' - emit += self.emiter.initmacro_end('%stests' % macro_prefix) - # _LIBDEPS and _LTLIBDEPS variables are not needed if this library is - # created using libtool, because libtool already handles the dependencies. - if not libtool: - libname_upper = libname.upper().replace('-', '_') - emit += ' %s_LIBDEPS="$gl_libdeps"\n' % libname_upper - emit += ' AC_SUBST([%s_LIBDEPS])\n' % libname_upper - emit += ' %s_LTLIBDEPS="$gl_ltlibdeps"\n' % libname_upper - emit += ' AC_SUBST([%s_LTLIBDEPS])\n' % libname_upper - if single_configure and libtests: - emit += ' LIBTESTS_LIBDEPS="$gltests_libdeps"\n' - emit += ' AC_SUBST([LIBTESTS_LIBDEPS])\n' - emit += '])\n' - emit += self.emiter.initmacro_done(macro_prefix, sourcebase) - if single_configure: - emit += self.emiter.initmacro_done('%stests' % macro_prefix, testsbase) - emit += '\ngl_INIT\n\n' - if subdirs_with_configure_ac: - if single_configure: - emit += 'AC_CONFIG_SUBDIRS([%s])\n' % \ - ' '.join(subdirs_with_configure_ac[:-1]) - else: # if not single_configure - emit += 'AC_CONFIG_SUBDIRS([%s])\n' % \ - ' '.join(subdirs_with_configure_ac) - makefiles = ['Makefile'] - for directory in subdirs: - # For subdirs that have a configure.ac by their own, it's the subdir's - # configure.ac which creates the subdir's Makefile.am, not this one. - makefiles += [joinpath(directory, 'Makefile')] - if not single_configure: - makefiles = makefiles[:-1] - emit += 'AC_CONFIG_FILES([%s])\n' % ' '.join(makefiles) - emit += 'AC_OUTPUT\n' - path = joinpath(self.testdir, 'configure.ac') - with codecs.open(path, 'wb', 'UTF-8') as file: - file.write(emit) - - # Create autogenerated files. - # Do not use "${AUTORECONF} --force --install", because it may invoke - # autopoint, which brings in older versions of some of our .m4 files. - os.chdir(self.testdir) - # gettext - if isfile(joinpath(m4base, 'gettext.m4')): - args = [UTILS['autopoint'], '--force'] - constants.execute(args, verbose) - for src in os.listdir(m4base): - src = joinpath(m4base, src) - if src.endswith('.m4~'): - dest = src[:-1] - if isfile(dest): - os.remove(dest) - shutil.move(src, dest) - # libtoolize - if libtool: - args = [UTILS['libtoolize'], '--copy'] - constants.execute(args, verbose) - # aclocal - args = [UTILS['aclocal'], '-I', m4base] - constants.execute(args, verbose) - if not isdir('build-aux'): - os.mkdir('build-aux') - # autoconf - args = [UTILS['autoconf']] - constants.execute(args, verbose) - # autoheader - args = [UTILS['autoheader']] - constants.execute(args, verbose) - # automake - args = [UTILS['automake'], '--add-missing', '--copy'] - constants.execute(args, verbose) - os.chdir(DIRS['cwd']) - if inctests and not single_configure: - # Do not use "${AUTORECONF} --force --install", because it may invoke - # autopoint, which brings in older versions of some of our .m4 files. - os.chdir(joinpath(self.testdir, testsbase)) - # gettext - if isfile(joinpath(m4base, 'gettext.m4')): - args = [UTILS['autopoint'], '--force'] + file.write(emit) + + # Create autogenerated files. + # Do not use "${AUTORECONF} --force --install", because it may invoke + # autopoint, which brings in older versions of some of our .m4 files. + os.chdir(self.testdir) + # gettext + if isfile(joinpath(m4base, 'gettext.m4')): + args = [UTILS['autopoint'], '--force'] + constants.execute(args, verbose) + for src in os.listdir(m4base): + src = joinpath(m4base, src) + if src.endswith('.m4~'): + dest = src[:-1] + if isfile(dest): + os.remove(dest) + shutil.move(src, dest) + # libtoolize + if libtool: + args = [UTILS['libtoolize'], '--copy'] + constants.execute(args, verbose) + # aclocal + args = [UTILS['aclocal'], '-I', m4base] + constants.execute(args, verbose) + if not isdir('build-aux'): + os.mkdir('build-aux') + # autoconf + args = [UTILS['autoconf']] + constants.execute(args, verbose) + # autoheader + args = [UTILS['autoheader']] + constants.execute(args, verbose) + # automake + args = [UTILS['automake'], '--add-missing', '--copy'] constants.execute(args, verbose) - for src in os.listdir(m4base): - src = joinpath(m4base, src) - if src.endswith('.m4~'): - dest = src[:-1] - if isfile(dest): - os.remove(dest) - shutil.move(src, dest) - # aclocal - args = [UTILS['aclocal'], '-I', joinpath('..', m4base)] - constants.execute(args, verbose) - if not isdir(joinpath('../build-aux')): - os.mkdir('../build-aux') - # autoconf - args = [UTILS['autoconf']] - constants.execute(args, verbose) - # autoheader - args = [UTILS['autoheader']] - constants.execute(args, verbose) - # automake - args = [UTILS['automake'], '--add-missing', '--copy'] - constants.execute(args, verbose) - os.chdir(DIRS['cwd']) - - # Need to run configure and make once, to create built files that are to be - # distributed (such as parse-datetime.c). - path = joinpath(self.testdir, sourcebase, 'Makefile.am') - with codecs.open(path, 'rb', 'UTF-8') as file: - snippet = file.read() - cleaned_files = list() - tests_cleaned_files = list() - built_sources = list() - tests_built_sources = list() - distributed_built_sources = list() - tests_distributed_built_sources = list() - - # Extract the value of "CLEANFILES += ..." and "MOSTLYCLEANFILES += ...". - regex_find = list() - snippet = snippet.replace('\\\n', '') - pattern = compiler('^CLEANFILES[\t ]*\\+=(.*?)$', re.S | re.M) - regex_find += pattern.findall(snippet) - pattern = compiler('^MOSTLYCLEANFILES[\t ]*\\+=(.*?)$', re.S | re.M) - regex_find += pattern.findall(snippet) - regex_find = [line.strip() for line in regex_find if line.strip()] - for part in regex_find: - cleaned_files += \ - [line.strip() for line in part.split(' ') if line.strip()] - - # Extract the value of "BUILT_SOURCES += ...". Remove variable references - # such $(FOO_H) because they don't refer to distributed files. - regex_find = list() - pattern = compiler('^BUILT_SOURCES[\t ]*\\+=(.*?)$', re.S | re.M) - regex_find += pattern.findall(snippet) - regex_find = [line.strip() for line in regex_find if line.strip()] - for part in regex_find: - built_sources += \ - [line.strip() for line in part.split(' ') if line.strip()] - built_sources = [line for line in built_sources \ - if not bool(compiler('[$]\\([A-Za-z0-9_]*\\)$').findall(line))] - distributed_built_sources = [file for file in built_sources \ - if file not in cleaned_files] - - if inctests: - # Likewise for built files in the $testsbase directory. - path = joinpath(self.testdir, testsbase, 'Makefile.am') - with codecs.open(path, 'rb', 'UTF-8') as file: - snippet = file.read() - - # Extract the value of "CLEANFILES += ..." and "MOSTLYCLEANFILES += ...". - regex_find = list() - snippet = snippet.replace('\\\n', '') - pattern = compiler('^CLEANFILES[\t ]*\\+=(.*?)$', re.S | re.M) - regex_find += pattern.findall(snippet) - pattern = compiler('^MOSTLYCLEANFILES[\t ]*\\+=(.*?)$', re.S | re.M) - regex_find += pattern.findall(snippet) - regex_find = [line.strip() for line in regex_find if line.strip()] - for part in regex_find: - tests_cleaned_files += \ - [line.strip() for line in part.split(' ') if line.strip()] - - # Extract the value of "BUILT_SOURCES += ...". Remove variable references - # such $(FOO_H) because they don't refer to distributed files. - regex_find = list() - tests_built_sources = list() - pattern = compiler('^BUILT_SOURCES[\t ]*\\+=(.*?)$', re.S | re.M) - regex_find += pattern.findall(snippet) - regex_find = [line.strip() for line in regex_find if line.strip()] - for part in regex_find: - tests_built_sources += \ - [line.strip() for line in part.split(' ') if line.strip()] - tests_built_sources = [line for line in tests_built_sources \ - if not bool(compiler('[$]\\([A-Za-z0-9_]*\\)$').findall(line))] - tests_distributed_built_sources = [file for file in tests_built_sources \ - if file not in cleaned_files] - - if distributed_built_sources or tests_distributed_built_sources: - os.chdir(self.testdir) - sp.call('./configure') - if distributed_built_sources: - os.chdir(sourcebase) - with codecs.open('Makefile', 'ab', 'UTF-8') as file: - file.write('built_sources: $(BUILT_SOURCES)\n') - args = [UTILS['make'], - 'AUTOCONF=%s' % UTILS['autoconf'], - 'AUTOHEADER=%s' % UTILS['autoheader'], - 'ACLOCAL=%s' % UTILS['aclocal'], - 'AUTOMAKE=%s' % UTILS['automake'], - 'AUTORECONF=%s' % UTILS['autoreconf'], - 'built_sources'] - sp.call(args) - os.chdir('..') - if tests_distributed_built_sources: - os.chdir(testsbase) - with codecs.open('Makefile', 'ab', 'UTF-8') as file: - file.write('built_sources: $(BUILT_SOURCES)\n') - args = [UTILS['make'], - 'AUTOCONF=%s' % UTILS['autoconf'], - 'AUTOHEADER=%s' % UTILS['autoheader'], - 'ACLOCAL=%s' % UTILS['aclocal'], - 'AUTOMAKE=%s' % UTILS['automake'], - 'AUTORECONF=%s' % UTILS['autoreconf'], - 'built_sources'] - sp.call(args) - os.chdir('..') - args = [UTILS['make'], - 'AUTOCONF=%s' % UTILS['autoconf'], - 'AUTOHEADER=%s' % UTILS['autoheader'], - 'ACLOCAL=%s' % UTILS['aclocal'], - 'AUTOMAKE=%s' % UTILS['automake'], - 'AUTORECONF=%s' % UTILS['autoreconf'], - 'AUTOPOINT=%s' % UTILS['autopoint'], - 'LIBTOOLIZE=%s' % UTILS['libtoolize'], - 'distclean'] - sp.call(args) - sp.call(['rm', '-rf', self.config['tempdir']], shell=False) + os.chdir(DIRS['cwd']) + if inctests and not single_configure: + # Do not use "${AUTORECONF} --force --install", because it may invoke + # autopoint, which brings in older versions of some of our .m4 files. + os.chdir(joinpath(self.testdir, testsbase)) + # gettext + if isfile(joinpath(m4base, 'gettext.m4')): + args = [UTILS['autopoint'], '--force'] + constants.execute(args, verbose) + for src in os.listdir(m4base): + src = joinpath(m4base, src) + if src.endswith('.m4~'): + dest = src[:-1] + if isfile(dest): + os.remove(dest) + shutil.move(src, dest) + # aclocal + args = [UTILS['aclocal'], '-I', joinpath('..', m4base)] + constants.execute(args, verbose) + if not isdir(joinpath('../build-aux')): + os.mkdir('../build-aux') + # autoconf + args = [UTILS['autoconf']] + constants.execute(args, verbose) + # autoheader + args = [UTILS['autoheader']] + constants.execute(args, verbose) + # automake + args = [UTILS['automake'], '--add-missing', '--copy'] + constants.execute(args, verbose) + os.chdir(DIRS['cwd']) + + # Need to run configure and make once, to create built files that are to be + # distributed (such as parse-datetime.c). + path = joinpath(self.testdir, sourcebase, 'Makefile.am') + with codecs.open(path, 'rb', 'UTF-8') as file: + snippet = file.read() + cleaned_files = list() + tests_cleaned_files = list() + built_sources = list() + tests_built_sources = list() + distributed_built_sources = list() + tests_distributed_built_sources = list() + + # Extract the value of "CLEANFILES += ..." and "MOSTLYCLEANFILES += ...". + regex_find = list() + snippet = snippet.replace('\\\n', '') + pattern = compiler('^CLEANFILES[\t ]*\\+=(.*?)$', re.S | re.M) + regex_find += pattern.findall(snippet) + pattern = compiler('^MOSTLYCLEANFILES[\t ]*\\+=(.*?)$', re.S | re.M) + regex_find += pattern.findall(snippet) + regex_find = [line.strip() for line in regex_find if line.strip()] + for part in regex_find: + cleaned_files += \ + [line.strip() for line in part.split(' ') if line.strip()] + + # Extract the value of "BUILT_SOURCES += ...". Remove variable references + # such $(FOO_H) because they don't refer to distributed files. + regex_find = list() + pattern = compiler('^BUILT_SOURCES[\t ]*\\+=(.*?)$', re.S | re.M) + regex_find += pattern.findall(snippet) + regex_find = [line.strip() for line in regex_find if line.strip()] + for part in regex_find: + built_sources += \ + [line.strip() for line in part.split(' ') if line.strip()] + built_sources = [line for line in built_sources + if not bool(compiler('[$]\\([A-Za-z0-9_]*\\)$').findall(line))] + distributed_built_sources = [file for file in built_sources + if file not in cleaned_files] + + if inctests: + # Likewise for built files in the $testsbase directory. + path = joinpath(self.testdir, testsbase, 'Makefile.am') + with codecs.open(path, 'rb', 'UTF-8') as file: + snippet = file.read() + + # Extract the value of "CLEANFILES += ..." and "MOSTLYCLEANFILES += ...". + regex_find = list() + snippet = snippet.replace('\\\n', '') + pattern = compiler('^CLEANFILES[\t ]*\\+=(.*?)$', re.S | re.M) + regex_find += pattern.findall(snippet) + pattern = compiler( + '^MOSTLYCLEANFILES[\t ]*\\+=(.*?)$', re.S | re.M) + regex_find += pattern.findall(snippet) + regex_find = [line.strip() for line in regex_find if line.strip()] + for part in regex_find: + tests_cleaned_files += \ + [line.strip() for line in part.split(' ') if line.strip()] + + # Extract the value of "BUILT_SOURCES += ...". Remove variable references + # such $(FOO_H) because they don't refer to distributed files. + regex_find = list() + tests_built_sources = list() + pattern = compiler('^BUILT_SOURCES[\t ]*\\+=(.*?)$', re.S | re.M) + regex_find += pattern.findall(snippet) + regex_find = [line.strip() for line in regex_find if line.strip()] + for part in regex_find: + tests_built_sources += \ + [line.strip() for line in part.split(' ') if line.strip()] + tests_built_sources = [line for line in tests_built_sources + if not bool(compiler('[$]\\([A-Za-z0-9_]*\\)$').findall(line))] + tests_distributed_built_sources = [file for file in tests_built_sources + if file not in cleaned_files] + + if distributed_built_sources or tests_distributed_built_sources: + os.chdir(self.testdir) + sp.call('./configure') + if distributed_built_sources: + os.chdir(sourcebase) + with codecs.open('Makefile', 'ab', 'UTF-8') as file: + file.write('built_sources: $(BUILT_SOURCES)\n') + args = [UTILS['make'], + 'AUTOCONF=%s' % UTILS['autoconf'], + 'AUTOHEADER=%s' % UTILS['autoheader'], + 'ACLOCAL=%s' % UTILS['aclocal'], + 'AUTOMAKE=%s' % UTILS['automake'], + 'AUTORECONF=%s' % UTILS['autoreconf'], + 'built_sources'] + sp.call(args) + os.chdir('..') + if tests_distributed_built_sources: + os.chdir(testsbase) + with codecs.open('Makefile', 'ab', 'UTF-8') as file: + file.write('built_sources: $(BUILT_SOURCES)\n') + args = [UTILS['make'], + 'AUTOCONF=%s' % UTILS['autoconf'], + 'AUTOHEADER=%s' % UTILS['autoheader'], + 'ACLOCAL=%s' % UTILS['aclocal'], + 'AUTOMAKE=%s' % UTILS['automake'], + 'AUTORECONF=%s' % UTILS['autoreconf'], + 'built_sources'] + sp.call(args) + os.chdir('..') + args = [UTILS['make'], + 'AUTOCONF=%s' % UTILS['autoconf'], + 'AUTOHEADER=%s' % UTILS['autoheader'], + 'ACLOCAL=%s' % UTILS['aclocal'], + 'AUTOMAKE=%s' % UTILS['automake'], + 'AUTORECONF=%s' % UTILS['autoreconf'], + 'AUTOPOINT=%s' % UTILS['autopoint'], + 'LIBTOOLIZE=%s' % UTILS['libtoolize'], + 'distclean'] + sp.call(args) + sp.call(['rm', '-rf', self.config['tempdir']], shell=False) #=============================================================================== # Define GLMegaTestDir class #=============================================================================== class GLMegaTestDir(object): - '''GLMegaTestDir class is used to create a mega scratch package with the - given modules one by one and all together.''' - - def __init__(self, config, megatestdir): - '''GLMegaTestDir.__init__(config, megatestdir) -> GLMegaTestDir - - Create new GLTestDir instance.''' - if type(config) is not GLConfig: - raise(TypeError('config must be a GLConfig, not %s' % \ - type(config).__name__)) - if type(megatestdir) is bytes or type(megatestdir) is string: - if type(megatestdir) is bytes: - megatestdir = megatestdir.decode(ENCS['default']) - self.config = config - self.megatestdir = os.path.normpath(megatestdir) - if not os.path.exists(self.megatestdir): - try: # Try to create directory - os.mkdir(self.megatestdir) - except Exception as error: - raise(GLError(19, self.megatestdir)) - self.emiter = GLEmiter(self.config) - self.filesystem = GLFileSystem(self.config) - self.modulesystem = GLModuleSystem(self.config) - self.moduletable = GLModuleTable(self.config) - self.assistant = GLFileAssistant(self.config) - self.makefiletable = GLMakefileTable(self.config) - - def execute(self): - '''GLMegaTestDir.execute() - - Create a mega scratch package with the given modules one by one and all - together.''' - megasubdirs = list() - modules = [self.modulesystem.find(m) for m in self.config['modules']] - if not modules: - modules = self.modulesystem.list() - modules = [self.modulesystem.find(m) for m in modules] - modules = sorted(set(modules)) - - # First, all modules one by one. - for module in modules: - self.config.setModules([str(module)]) - #GLTestDir(self.config, self.megatestdir).execute() - megasubdirs += [str(module)] - - # Then, all modules all together. - # Except config-h, which breaks all modules which use HAVE_CONFIG_H. - modules = [module for module in modules if str(module) != 'config-h'] - self.config.setModules([str(module) for module in modules]) - #GLTestDir(self.config, self.megatestdir).execute() - megasubdirs += ['ALL'] - - # Create autobuild. - emit = string() - repdict = dict() - repdict['Jan'] = repdict['January'] = '01' - repdict['Feb'] = repdict['February'] = '02' - repdict['Mar'] = repdict['March'] = '03' - repdict['Apr'] = repdict['April'] = '04' - repdict['May'] = repdict['May'] = '05' - repdict['Jun'] = repdict['June'] = '06' - repdict['Jul'] = repdict['July'] = '07' - repdict['Aug'] = repdict['August'] = '08' - repdict['Sep'] = repdict['September'] = '09' - repdict['Oct'] = repdict['October'] = '10' - repdict['Nov'] = repdict['November'] = '11' - repdict['Dec'] = repdict['December'] = '12' - if isfile(joinpath(DIRS['root'], 'CVS', 'Entries')): - vc_witness = joinpath(DIRS['root'], 'CVS', 'Entries') - else: # if not isfile(joinpath(DIRS['root'], 'CVS', 'Entries')) - vc_witness = joinpath(DIRS['root'], '.git', 'refs', 'heads', 'master') - mdate_sh = joinpath(DIRS['root'], 'build-aux', 'mdate-sh') - args = ['sh', mdate_sh, vc_witness] - cvsdate = sp.check_output(args).decode("UTF-8").strip() - for key in repdict: - if len(key) > 3: - cvsdate = cvsdate.replace(key, repdict[key]) - for key in repdict: - cvsdate = cvsdate.replace(key, repdict[key]) - cvsdate = ''.join([date for date in cvsdate.split(' ') if date.strip()]) - cvsdate = '%s%s%s' % (cvsdate[4:], cvsdate[2:4], cvsdate[:2]) - emit += '#!/bin/sh\n' - emit += 'CVSDATE=%s\n' % cvsdate - emit += ': ${MAKE=make}\n' - emit += 'test -d logs || mkdir logs\n' - emit += 'for module in %s; do\n' % ' '.join(megasubdirs) - emit += ' echo "Working on module $module..."\n' - emit += ' safemodule=`echo $module | sed -e \'s|/|-|g\'`\n' - emit += ' (echo "To: gnulib@autobuild.josefsson.org"\\\n' - emit += ' echo\n' - emit += ' set -x\n' - emit += ' : autobuild project... $module\n' - emit += ' : autobuild revision... cvs-$CVSDATE-000000\n' - emit += ' : autobuild timestamp... `date "+%Y%m%d-%H%M%S"`\n' - emit += ' : autobuild hostname... `hostname`\n' - emit += ' cd $module && ./configure $CONFIGURE_OPTIONS && $MAKE' - emit += ' && $MAKE check && $MAKE distclean\n' - emit += ' echo rc=$?\n' - emit += ' ) 2>&1 | { if test -n "$AUTOBUILD_SUBST"; then ' - emit += 'sed -e "$AUTOBUILD_SUBST"; else cat; fi; } > logs/$safemodule\n' - emit += 'done\n' - emit = constants.nlconvert(emit) - if type(emit) is bytes: - emit = emit.decode(ENCS['default']) - path = joinpath(self.megatestdir, 'do-autobuild') - with codecs.open(path, 'wb', 'UTF-8') as file: - file.write(emit) - - # Create Makefile.am. - emit = string() - emit += '## Process this file with automake to produce Makefile.in.\n\n' - emit += 'AUTOMAKE_OPTIONS = 1.5 foreign\n\n' - emit += 'SUBDIRS = %s\n\n' % ' '.join(megasubdirs) - emit += 'EXTRA_DIST = do-autobuild\n' - emit = constants.nlconvert(emit) - if type(emit) is bytes: - emit = emit.decode(ENCS['default']) - path = joinpath(self.megatestdir, 'Makefile.am') - with codecs.open(path, 'wb', 'UTF-8') as file: - file.write(emit) - - - emit = string() - emit += '# Process this file with autoconf ' - emit += 'to produce a configure script.\n' - emit += 'AC_INIT([dummy], [0])\n\n' - if auxdir != '.': - emit += 'AC_CONFIG_AUX_DIR([%s])\n' % auxdir - emit += 'AM_INIT_AUTOMAKE\n\n' - emit += 'AC_PROG_MAKE_SET\n\n' - emit += 'AC_CONFIG_SUBDIRS([%s])\n' % ' '.megasubdirs - emit += 'AC_CONFIG_FILES([Makefile])\n' - emit += 'AC_OUTPUT\n' - emit = constants.nlconvert(emit) - if type(emit) is bytes: - emit = emit.decode(ENCS['default']) - path = joinpath(self.megatestdir, 'Makefile.am') - with codecs.open(path, 'wb', 'UTF-8') as file: - file.write(emit) - - # Create autogenerated files. - os.chdir(DIRS['cwd']) - args = [UTILS['aclocal']] - constants.execute(args, verbose) - try: # Try to make a directory - if not isdir('build-aux'): - os,mkdir('build-aux') - except Exception as error: - pass - args = [UTILS['autoconf']] - constants.execute(args, verbose) - args = [UTILS['automake'], '--add-missing', '--copy'] - constants.execute(args, verbose) - sp.call(['rm', '-rf', self.config['tempdir']], shell=False) + '''GLMegaTestDir class is used to create a mega scratch package with the + given modules one by one and all together.''' + + def __init__(self, config, megatestdir): + '''GLMegaTestDir.__init__(config, megatestdir) -> GLMegaTestDir + + Create new GLTestDir instance.''' + if type(config) is not GLConfig: + raise(TypeError('config must be a GLConfig, not %s' % + type(config).__name__)) + if type(megatestdir) is bytes or type(megatestdir) is string: + if type(megatestdir) is bytes: + megatestdir = megatestdir.decode(ENCS['default']) + self.config = config + self.megatestdir = os.path.normpath(megatestdir) + if not os.path.exists(self.megatestdir): + try: # Try to create directory + os.mkdir(self.megatestdir) + except Exception as error: + raise(GLError(19, self.megatestdir)) + self.emiter = GLEmiter(self.config) + self.filesystem = GLFileSystem(self.config) + self.modulesystem = GLModuleSystem(self.config) + self.moduletable = GLModuleTable(self.config) + self.assistant = GLFileAssistant(self.config) + self.makefiletable = GLMakefileTable(self.config) + + def execute(self): + '''GLMegaTestDir.execute() + + Create a mega scratch package with the given modules one by one and all + together.''' + megasubdirs = list() + modules = [self.modulesystem.find(m) for m in self.config['modules']] + if not modules: + modules = self.modulesystem.list() + modules = [self.modulesystem.find(m) for m in modules] + modules = sorted(set(modules)) + + # First, all modules one by one. + for module in modules: + self.config.setModules([str(module)]) + #GLTestDir(self.config, self.megatestdir).execute() + megasubdirs += [str(module)] + + # Then, all modules all together. + # Except config-h, which breaks all modules which use HAVE_CONFIG_H. + modules = [module for module in modules if str(module) != 'config-h'] + self.config.setModules([str(module) for module in modules]) + #GLTestDir(self.config, self.megatestdir).execute() + megasubdirs += ['ALL'] + + # Create autobuild. + emit = string() + repdict = dict() + repdict['Jan'] = repdict['January'] = '01' + repdict['Feb'] = repdict['February'] = '02' + repdict['Mar'] = repdict['March'] = '03' + repdict['Apr'] = repdict['April'] = '04' + repdict['May'] = repdict['May'] = '05' + repdict['Jun'] = repdict['June'] = '06' + repdict['Jul'] = repdict['July'] = '07' + repdict['Aug'] = repdict['August'] = '08' + repdict['Sep'] = repdict['September'] = '09' + repdict['Oct'] = repdict['October'] = '10' + repdict['Nov'] = repdict['November'] = '11' + repdict['Dec'] = repdict['December'] = '12' + if isfile(joinpath(DIRS['root'], 'CVS', 'Entries')): + vc_witness = joinpath(DIRS['root'], 'CVS', 'Entries') + else: # if not isfile(joinpath(DIRS['root'], 'CVS', 'Entries')) + vc_witness = joinpath( + DIRS['root'], '.git', 'refs', 'heads', 'master') + mdate_sh = joinpath(DIRS['root'], 'build-aux', 'mdate-sh') + args = ['sh', mdate_sh, vc_witness] + cvsdate = sp.check_output(args).decode("UTF-8").strip() + for key in repdict: + if len(key) > 3: + cvsdate = cvsdate.replace(key, repdict[key]) + for key in repdict: + cvsdate = cvsdate.replace(key, repdict[key]) + cvsdate = ''.join( + [date for date in cvsdate.split(' ') if date.strip()]) + cvsdate = '%s%s%s' % (cvsdate[4:], cvsdate[2:4], cvsdate[:2]) + emit += '#!/bin/sh\n' + emit += 'CVSDATE=%s\n' % cvsdate + emit += ': ${MAKE=make}\n' + emit += 'test -d logs || mkdir logs\n' + emit += 'for module in %s; do\n' % ' '.join(megasubdirs) + emit += ' echo "Working on module $module..."\n' + emit += ' safemodule=`echo $module | sed -e \'s|/|-|g\'`\n' + emit += ' (echo "To: gnulib@autobuild.josefsson.org"\\\n' + emit += ' echo\n' + emit += ' set -x\n' + emit += ' : autobuild project... $module\n' + emit += ' : autobuild revision... cvs-$CVSDATE-000000\n' + emit += ' : autobuild timestamp... `date "+%Y%m%d-%H%M%S"`\n' + emit += ' : autobuild hostname... `hostname`\n' + emit += ' cd $module && ./configure $CONFIGURE_OPTIONS && $MAKE' + emit += ' && $MAKE check && $MAKE distclean\n' + emit += ' echo rc=$?\n' + emit += ' ) 2>&1 | { if test -n "$AUTOBUILD_SUBST"; then ' + emit += 'sed -e "$AUTOBUILD_SUBST"; else cat; fi; } > logs/$safemodule\n' + emit += 'done\n' + emit = constants.nlconvert(emit) + if type(emit) is bytes: + emit = emit.decode(ENCS['default']) + path = joinpath(self.megatestdir, 'do-autobuild') + with codecs.open(path, 'wb', 'UTF-8') as file: + file.write(emit) + + # Create Makefile.am. + emit = string() + emit += '## Process this file with automake to produce Makefile.in.\n\n' + emit += 'AUTOMAKE_OPTIONS = 1.5 foreign\n\n' + emit += 'SUBDIRS = %s\n\n' % ' '.join(megasubdirs) + emit += 'EXTRA_DIST = do-autobuild\n' + emit = constants.nlconvert(emit) + if type(emit) is bytes: + emit = emit.decode(ENCS['default']) + path = joinpath(self.megatestdir, 'Makefile.am') + with codecs.open(path, 'wb', 'UTF-8') as file: + file.write(emit) + + emit = string() + emit += '# Process this file with autoconf ' + emit += 'to produce a configure script.\n' + emit += 'AC_INIT([dummy], [0])\n\n' + if auxdir != '.': + emit += 'AC_CONFIG_AUX_DIR([%s])\n' % auxdir + emit += 'AM_INIT_AUTOMAKE\n\n' + emit += 'AC_PROG_MAKE_SET\n\n' + emit += 'AC_CONFIG_SUBDIRS([%s])\n' % ' '.megasubdirs + emit += 'AC_CONFIG_FILES([Makefile])\n' + emit += 'AC_OUTPUT\n' + emit = constants.nlconvert(emit) + if type(emit) is bytes: + emit = emit.decode(ENCS['default']) + path = joinpath(self.megatestdir, 'Makefile.am') + with codecs.open(path, 'wb', 'UTF-8') as file: + file.write(emit) + # Create autogenerated files. + os.chdir(DIRS['cwd']) + args = [UTILS['aclocal']] + constants.execute(args, verbose) + try: # Try to make a directory + if not isdir('build-aux'): + os, mkdir('build-aux') + except Exception as error: + pass + args = [UTILS['autoconf']] + constants.execute(args, verbose) + args = [UTILS['automake'], '--add-missing', '--copy'] + constants.execute(args, verbose) + sp.call(['rm', '-rf', self.config['tempdir']], shell=False) diff --git a/pygnulib/__init__.py b/pygnulib/__init__.py index 5fbb4220a7..fc205c2654 100644 --- a/pygnulib/__init__.py +++ b/pygnulib/__init__.py @@ -18,4 +18,3 @@ the common infrastructure needed by GNU packages.''' __copyright__ = '2012 Free Software Foundation, Inc.' __author__ = 'Dmitriy Selyutin' __license__ = 'GNU GPLv3+' - diff --git a/pygnulib/classes.py b/pygnulib/classes.py index 3756db3c6e..9e8a65851a 100644 --- a/pygnulib/classes.py +++ b/pygnulib/classes.py @@ -9,57 +9,57 @@ __all__ = list() try: - # Constants - from . import constants - - # Main classes - from .GLConfig import GLConfig - from .GLError import GLError - from .GLInfo import GLInfo - - # File system - from .GLFileSystem import GLFileSystem - from .GLFileSystem import GLFileAssistant - - # Module system - from .GLModuleSystem import GLModule - from .GLModuleSystem import GLModuleSystem - from .GLModuleSystem import GLModuleTable - - # Different modes - from .GLImport import GLImport - from .GLEmiter import GLEmiter - from .GLTestDir import GLTestDir - from .GLTestDir import GLMegaTestDir - - # Other modules - from .GLMakefileTable import GLMakefileTable + # Constants + from . import constants + + # Main classes + from .GLConfig import GLConfig + from .GLError import GLError + from .GLInfo import GLInfo + + # File system + from .GLFileSystem import GLFileSystem + from .GLFileSystem import GLFileAssistant + + # Module system + from .GLModuleSystem import GLModule + from .GLModuleSystem import GLModuleSystem + from .GLModuleSystem import GLModuleTable + + # Different modes + from .GLImport import GLImport + from .GLEmiter import GLEmiter + from .GLTestDir import GLTestDir + from .GLTestDir import GLMegaTestDir + + # Other modules + from .GLMakefileTable import GLMakefileTable except ValueError as error: - # Constants - import constants - - # Main classes - from GLConfig import GLConfig - from GLError import GLError - from GLInfo import GLInfo - - # File system - from GLFileSystem import GLFileSystem - from GLFileSystem import GLFileAssistant - - # Module system - from GLModuleSystem import GLModule - from GLModuleSystem import GLModuleSystem - from GLModuleSystem import GLModuleTable - - # Different modes - from GLImport import GLImport - from GLEmiter import GLEmiter - from GLTestDir import GLTestDir - from GLTestDir import GLMegaTestDir - - # Other modules - from GLMakefileTable import GLMakefileTable + # Constants + import constants + + # Main classes + from GLConfig import GLConfig + from GLError import GLError + from GLInfo import GLInfo + + # File system + from GLFileSystem import GLFileSystem + from GLFileSystem import GLFileAssistant + + # Module system + from GLModuleSystem import GLModule + from GLModuleSystem import GLModuleSystem + from GLModuleSystem import GLModuleTable + + # Different modes + from GLImport import GLImport + from GLEmiter import GLEmiter + from GLTestDir import GLTestDir + from GLTestDir import GLMegaTestDir + + # Other modules + from GLMakefileTable import GLMakefileTable # Append modules to namespace. __all__ += ['GLConfig', 'GLError', 'GLInfo'] @@ -74,4 +74,3 @@ __all__ += ['GLMakefileTable'] __author__ = constants.__author__ __license__ = constants.__license__ __copyright__ = constants.__copyright__ - diff --git a/pygnulib/constants.py b/pygnulib/constants.py index defca17e87..3255635989 100644 --- a/pygnulib/constants.py +++ b/pygnulib/constants.py @@ -20,12 +20,12 @@ import subprocess as sp #=============================================================================== __all__ = list() __author__ = \ -[ - 'Bruno Haible', - 'Paul Eggert', - 'Simon Josefsson', - 'Dmitriy Selyutin', -] + [ + 'Bruno Haible', + 'Paul Eggert', + 'Simon Josefsson', + 'Dmitriy Selyutin', + ] __license__ = 'GNU GPLv3+' __copyright__ = '2012 Free Software Foundation, Inc.' @@ -35,62 +35,62 @@ __copyright__ = '2012 Free Software Foundation, Inc.' #=============================================================================== # Check for Python version if sys.version_info.major == 2: - PYTHON3 = False + PYTHON3 = False else: - PYTHON3 = True + PYTHON3 = True # Create string compatibility if not PYTHON3: - string = unicode -else: # if PYTHON3 - string = str + string = unicode +else: # if PYTHON3 + string = str # Current working directory if not PYTHON3: - os.getcwdb = os.getcwd - os.getcwd = os.getcwdu + os.getcwdb = os.getcwd + os.getcwd = os.getcwdu #=============================================================================== # Define global constants #=============================================================================== # Declare neccessary variables -APP = dict() # Application -DIRS = dict() # Directories -UTILS = dict() # Utilities -ENCS = dict() # Encodings -FILES = dict() # Files -MODES = dict() # Modes -TESTS = dict() # Tests +APP = dict() # Application +DIRS = dict() # Directories +UTILS = dict() # Utilities +ENCS = dict() # Encodings +FILES = dict() # Files +MODES = dict() # Modes +TESTS = dict() # Tests NL = ''' -''' # Newline character +''' # Newline character ALPHANUMERIC = 'abcdefghijklmnopqrstuvwxyz\ ABCDEFGHIJKLMNOPQRSTUVWXYZ\ -0123456789' # Alphanumeric characters +0123456789' # Alphanumeric characters # Set ENCS dictionary import __main__ as interpreter if not hasattr(interpreter, '__file__'): - if sys.stdout.encoding != None: - ENCS['default'] = sys.stdout.encoding - else: # sys.stdout.encoding == None + if sys.stdout.encoding != None: + ENCS['default'] = sys.stdout.encoding + else: # sys.stdout.encoding == None + ENCS['default'] = 'UTF-8' +else: # if hasattr(interpreter, '__file__'): ENCS['default'] = 'UTF-8' -else: # if hasattr(interpreter, '__file__'): - ENCS['default'] = 'UTF-8' ENCS['system'] = sys.getfilesystemencoding() ENCS['shell'] = sys.stdout.encoding if ENCS['shell'] == None: - ENCS['shell'] = 'UTF-8' + ENCS['shell'] = 'UTF-8' # Set APP dictionary APP['name'] = sys.argv[0] if not APP['name']: - APP['name'] = 'gnulib-tool.py' + APP['name'] = 'gnulib-tool.py' APP['path'] = os.path.realpath(sys.argv[0]) if type(APP['name']) is bytes: - APP['name'] = string(APP['name'], ENCS['system']) + APP['name'] = string(APP['name'], ENCS['system']) if type(APP['path']) is bytes: - APP['path'] = string(APP['path'], ENCS['system']) + APP['path'] = string(APP['path'], ENCS['system']) # Set DIRS dictionary DIRS['root'] = os.path.dirname(APP['path']) @@ -110,34 +110,34 @@ FILES['changelog'] = os.path.join(DIRS['root'], 'ChangeLog') # Set MODES dictionary MODES = \ -{ - 'import': 0, - 'add-import': 1, - 'remove-import': 2, - 'update': 3, -} + { + 'import': 0, + 'add-import': 1, + 'remove-import': 2, + 'update': 3, + } MODES['verbose-min'] = -2 MODES['verbose-default'] = 0 MODES['verbose-max'] = 2 # Set TESTS dictionary TESTS = \ -{ - 'tests': 0, - 'obsolete': 1, - 'c++-test': 2, - 'cxx-test': 2, - 'c++-tests': 2, - 'cxx-tests': 2, - 'longrunning-test': 3, - 'longrunning-tests': 3, - 'privileged-test': 4, - 'privileged-tests': 4, - 'unportable-test': 5, - 'unportable-tests': 5, - 'all-test': 6, - 'all-tests': 6, -} + { + 'tests': 0, + 'obsolete': 1, + 'c++-test': 2, + 'cxx-test': 2, + 'c++-tests': 2, + 'cxx-tests': 2, + 'longrunning-test': 3, + 'longrunning-tests': 3, + 'privileged-test': 4, + 'privileged-tests': 4, + 'unportable-test': 5, + 'unportable-tests': 5, + 'all-test': 6, + 'all-tests': 6, + } # Define AUTOCONF minimum version DEFAULT_AUTOCONF_MINVERSION = 2.59 @@ -152,285 +152,301 @@ LIBTOOLPATH = '' # You can also set the variable AUTOCONF individually if AUTOCONFPATH: - UTILS['autoconf'] = AUTOCONFPATH + 'autoconf' + UTILS['autoconf'] = AUTOCONFPATH + 'autoconf' else: - if os.getenv('AUTOCONF'): - UTILS['autoconf'] = os.getenv('AUTOCONF') - else: - UTILS['autoconf'] = 'autoconf' + if os.getenv('AUTOCONF'): + UTILS['autoconf'] = os.getenv('AUTOCONF') + else: + UTILS['autoconf'] = 'autoconf' # You can also set the variable AUTORECONF individually if AUTOCONFPATH: - UTILS['autoreconf'] = AUTOCONFPATH + 'autoreconf' + UTILS['autoreconf'] = AUTOCONFPATH + 'autoreconf' else: - if os.getenv('AUTORECONF'): - UTILS['autoreconf'] = os.getenv('AUTORECONF') - else: - UTILS['autoreconf'] = 'autoreconf' + if os.getenv('AUTORECONF'): + UTILS['autoreconf'] = os.getenv('AUTORECONF') + else: + UTILS['autoreconf'] = 'autoreconf' # You can also set the variable AUTOHEADER individually if AUTOCONFPATH: - UTILS['autoheader'] = AUTOCONFPATH + 'autoheader' + UTILS['autoheader'] = AUTOCONFPATH + 'autoheader' else: - if os.getenv('AUTOHEADER'): - UTILS['autoheader'] = os.getenv('AUTOHEADER') - else: - UTILS['autoheader'] = 'autoheader' + if os.getenv('AUTOHEADER'): + UTILS['autoheader'] = os.getenv('AUTOHEADER') + else: + UTILS['autoheader'] = 'autoheader' # You can also set the variable AUTOMAKE individually if AUTOMAKEPATH: - UTILS['automake'] = AUTOMAKEPATH + 'automake' + UTILS['automake'] = AUTOMAKEPATH + 'automake' else: - if os.getenv('AUTOMAKE'): - UTILS['automake'] = os.getenv('AUTOMAKE') - else: - UTILS['automake'] = 'automake' + if os.getenv('AUTOMAKE'): + UTILS['automake'] = os.getenv('AUTOMAKE') + else: + UTILS['automake'] = 'automake' # You can also set the variable ACLOCAL individually if AUTOMAKEPATH: - UTILS['aclocal'] = AUTOMAKEPATH + 'aclocal' + UTILS['aclocal'] = AUTOMAKEPATH + 'aclocal' else: - if os.getenv('ACLOCAL'): - UTILS['aclocal'] = os.getenv('ACLOCAL') - else: - UTILS['aclocal'] = 'aclocal' + if os.getenv('ACLOCAL'): + UTILS['aclocal'] = os.getenv('ACLOCAL') + else: + UTILS['aclocal'] = 'aclocal' # You can also set the variable AUTOPOINT individually if GETTEXTPATH: - UTILS['autopoint'] = GETTEXTPATH + 'autopoint' + UTILS['autopoint'] = GETTEXTPATH + 'autopoint' else: - if os.getenv('AUTOPOINT'): - UTILS['autopoint'] = os.getenv('AUTOPOINT') - else: - UTILS['autopoint'] = 'autopoint' + if os.getenv('AUTOPOINT'): + UTILS['autopoint'] = os.getenv('AUTOPOINT') + else: + UTILS['autopoint'] = 'autopoint' # You can also set the variable LIBTOOLIZE individually if LIBTOOLPATH: - UTILS['libtoolize'] = LIBTOOLPATH + 'libtoolize' + UTILS['libtoolize'] = LIBTOOLPATH + 'libtoolize' else: - if os.getenv('LIBTOOLIZE'): - UTILS['libtoolize'] = os.getenv('LIBTOOLIZE') - else: - UTILS['libtoolize'] = 'libtoolize' + if os.getenv('LIBTOOLIZE'): + UTILS['libtoolize'] = os.getenv('LIBTOOLIZE') + else: + UTILS['libtoolize'] = 'libtoolize' # You can also set the variable MAKE if os.getenv('MAKE'): - UTILS['make'] = os.getenv('MAKE') + UTILS['make'] = os.getenv('MAKE') else: - UTILS['make'] = 'make' + UTILS['make'] = 'make' #=============================================================================== # Define global functions #=============================================================================== def execute(args, verbose): - '''Execute the given shell command.''' - if verbose >= 0: - print("executing %s" % ' '.join(args)) - try: # Try to run - retcode = sp.call(args) - except Exception as error: - print(error) - sys.exit(1) - else: - # Commands like automake produce output to stderr even when they succeed. - # Turn this output off if the command succeeds. - temp = tempfile.mktemp() - if type(temp) is bytes: - temp = temp.decode(ENCS['system']) - xargs = '%s > %s 2>&1' % (' '.join(args), temp) - try: # Try to run - retcode = sp.call(xargs, shell=True) - except Exception as error: - print(error) - sys.exit(1) - if retcode == 0: - os.remove(temp) + '''Execute the given shell command.''' + if verbose >= 0: + print("executing %s" % ' '.join(args)) + try: # Try to run + retcode = sp.call(args) + except Exception as error: + print(error) + sys.exit(1) else: - print("executing %s" % ' '.join(args)) - with codecs.open(temp, 'rb') as file: - cmdout = file.read() - print(cmdout) - os.remove(temp) - sys.exit(retcode) + # Commands like automake produce output to stderr even when they succeed. + # Turn this output off if the command succeeds. + temp = tempfile.mktemp() + if type(temp) is bytes: + temp = temp.decode(ENCS['system']) + xargs = '%s > %s 2>&1' % (' '.join(args), temp) + try: # Try to run + retcode = sp.call(xargs, shell=True) + except Exception as error: + print(error) + sys.exit(1) + if retcode == 0: + os.remove(temp) + else: + print("executing %s" % ' '.join(args)) + with codecs.open(temp, 'rb') as file: + cmdout = file.read() + print(cmdout) + os.remove(temp) + sys.exit(retcode) + def compiler(pattern, flags=0): - '''Compile regex pattern depending on version of Python.''' - if not PYTHON3: - pattern = re.compile(pattern, re.UNICODE | flags) - else: # if PYTHON3 - pattern = re.compile(pattern, flags) - return(pattern) + '''Compile regex pattern depending on version of Python.''' + if not PYTHON3: + pattern = re.compile(pattern, re.UNICODE | flags) + else: # if PYTHON3 + pattern = re.compile(pattern, flags) + return(pattern) + def cleaner(sequence): - '''Clean string or list of strings after using regex.''' - if type(sequence) is string: - sequence = sequence.replace('[', '') - sequence = sequence.replace(']', '') - elif type(sequence) is list: - sequence = [value.replace('[', '').replace(']', '') for value in sequence] - sequence = [value.replace('(', '').replace(')', '') for value in sequence] - sequence = [False if value == 'false' else value for value in sequence] - sequence = [True if value == 'true' else value for value in sequence] - sequence = [value.strip() for value in sequence] - return(sequence) + '''Clean string or list of strings after using regex.''' + if type(sequence) is string: + sequence = sequence.replace('[', '') + sequence = sequence.replace(']', '') + elif type(sequence) is list: + sequence = [value.replace('[', '').replace(']', '') + for value in sequence] + sequence = [value.replace('(', '').replace(')', '') + for value in sequence] + sequence = [False if value == 'false' else value for value in sequence] + sequence = [True if value == 'true' else value for value in sequence] + sequence = [value.strip() for value in sequence] + return(sequence) + def joinpath(head, *tail): - '''joinpath(head, *tail) -> string - - Join two or more pathname components, inserting '/' as needed. If any - component is an absolute path, all previous path components will be - discarded. The second argument may be string or list of strings.''' - newtail = list() - if type(head) is bytes: - head = head.decode(ENCS['default']) - for item in tail: - if type(item) is bytes: - item = item.decode(ENCS['default']) - newtail += [item] - result = os.path.normpath(os.path.join(head, *tail)) - if type(result) is bytes: - result = result.decode(ENCS['default']) - return(result) + '''joinpath(head, *tail) -> string + + Join two or more pathname components, inserting '/' as needed. If any + component is an absolute path, all previous path components will be + discarded. The second argument may be string or list of strings.''' + newtail = list() + if type(head) is bytes: + head = head.decode(ENCS['default']) + for item in tail: + if type(item) is bytes: + item = item.decode(ENCS['default']) + newtail += [item] + result = os.path.normpath(os.path.join(head, *tail)) + if type(result) is bytes: + result = result.decode(ENCS['default']) + return(result) + def relativize(dir1, dir2): - '''Compute a relative pathname reldir such that dir1/reldir = dir2.''' - dir0 = os.getcwd() - if type(dir1) is bytes: - dir1 = dir1.decode(ENCS['default']) - if type(dir2) is bytes: - dir2 = dir2.decode(ENCS['default']) - while dir1: - dir1 = '%s%s' % (os.path.normpath(dir1), os.path.sep) - dir2 = '%s%s' % (os.path.normpath(dir2), os.path.sep) - if dir1.startswith(os.path.sep): - first = dir1[:dir1.find(os.path.sep, 1)] - else: # if not dir1.startswith('/') - first = dir1[:dir1.find(os.path.sep)] - if first != '.': - if first == '..': - dir2 = os.path.basename(joinpath(dir0, dir2)) - dir0 = os.path.dirname(dir0) - else: # if first != '..' - # Get first component of dir2 - if dir2.startswith(os.path.sep): - first2 = dir2[:dir2.find(os.path.sep, 1)] - else: # if not dir1.startswith('/') - first2 = dir2[:dir2.find(os.path.sep)] - if first == first2: - dir2 = dir2[dir2.find(os.path.sep)+1:] - else: # if first != first2 - dir2 = joinpath('..', dir2) - dir0 = joinpath(dir0, first) - dir1 = dir1[dir1.find(os.path.sep)+1:] - result = os.path.normpath(dir2) - return(result) + '''Compute a relative pathname reldir such that dir1/reldir = dir2.''' + dir0 = os.getcwd() + if type(dir1) is bytes: + dir1 = dir1.decode(ENCS['default']) + if type(dir2) is bytes: + dir2 = dir2.decode(ENCS['default']) + while dir1: + dir1 = '%s%s' % (os.path.normpath(dir1), os.path.sep) + dir2 = '%s%s' % (os.path.normpath(dir2), os.path.sep) + if dir1.startswith(os.path.sep): + first = dir1[:dir1.find(os.path.sep, 1)] + else: # if not dir1.startswith('/') + first = dir1[:dir1.find(os.path.sep)] + if first != '.': + if first == '..': + dir2 = os.path.basename(joinpath(dir0, dir2)) + dir0 = os.path.dirname(dir0) + else: # if first != '..' + # Get first component of dir2 + if dir2.startswith(os.path.sep): + first2 = dir2[:dir2.find(os.path.sep, 1)] + else: # if not dir1.startswith('/') + first2 = dir2[:dir2.find(os.path.sep)] + if first == first2: + dir2 = dir2[dir2.find(os.path.sep) + 1:] + else: # if first != first2 + dir2 = joinpath('..', dir2) + dir0 = joinpath(dir0, first) + dir1 = dir1[dir1.find(os.path.sep) + 1:] + result = os.path.normpath(dir2) + return(result) + def link_relative(src, dest): '''Like ln -s, except that src is given relative to the current directory (or absolute), not given relative to the directory of dest.''' if type(src) is bytes or type(src) is string: - if type(src) is bytes: - src = src.decode(ENCS['default']) - else: # if src has not bytes or string type - raise(TypeError( - 'src must be a string, not %s' % (type(src).__name__))) + if type(src) is bytes: + src = src.decode(ENCS['default']) + else: # if src has not bytes or string type + raise(TypeError( + 'src must be a string, not %s' % (type(src).__name__))) if type(dest) is bytes or type(dest) is string: - if type(dest) is bytes: - dest = dest.decode(ENCS['default']) - else: # if dest has not bytes or string type - raise(TypeError( - 'dest must be a string, not %s' % (type(dest).__name__))) + if type(dest) is bytes: + dest = dest.decode(ENCS['default']) + else: # if dest has not bytes or string type + raise(TypeError( + 'dest must be a string, not %s' % (type(dest).__name__))) if src.startswith('/'): - os.symlink(src, dest) - else: # if not src.startswith('/') - if dest.startswith('/'): - if not constants.PYTHON3: - cwd = os.getcwdu() - else: # if constants.PYTHON3 - cwd = os.getcwd() - os.symlink(joinpath(cwd, src), dest) - else: # if not dest.startswith('/') - destdir = os.path.dirname(dest) - if not destdir: - destdir = '.' - if type(destdir) is bytes: - destdir = destdir.decode(ENCS['default']) - src = relativize(destdir, src) os.symlink(src, dest) + else: # if not src.startswith('/') + if dest.startswith('/'): + if not constants.PYTHON3: + cwd = os.getcwdu() + else: # if constants.PYTHON3 + cwd = os.getcwd() + os.symlink(joinpath(cwd, src), dest) + else: # if not dest.startswith('/') + destdir = os.path.dirname(dest) + if not destdir: + destdir = '.' + if type(destdir) is bytes: + destdir = destdir.decode(ENCS['default']) + src = relativize(destdir, src) + os.symlink(src, dest) + def link_if_changed(src, dest): - '''Create a symlink, but avoids munging timestamps if the link is correct.''' - if type(src) is bytes: - src = src.decode(ENCS['default']) - if type(dest) is bytes: - dest = dest.decode(ENCS['default']) - ln_target = os.path.realpath(src) - if not (os.path.islink(dest) and src == ln_target): - os.remove(dest) - link_relative(src, dest) + '''Create a symlink, but avoids munging timestamps if the link is correct.''' + if type(src) is bytes: + src = src.decode(ENCS['default']) + if type(dest) is bytes: + dest = dest.decode(ENCS['default']) + ln_target = os.path.realpath(src) + if not (os.path.islink(dest) and src == ln_target): + os.remove(dest) + link_relative(src, dest) + def filter_filelist(separator, filelist, - prefix, suffix, removed_prefix, removed_suffix, - added_prefix=string(), added_suffix=string()): - '''filter_filelist(*args) -> list - - Filter the given list of files. Filtering: Only the elements starting with - prefix and ending with suffix are considered. Processing: removed_prefix - and removed_suffix are removed from each element, added_prefix and - added_suffix are added to each element.''' - listing = list() - for filename in filelist: - if filename.startswith(prefix) and filename.endswith(suffix): - pattern = compiler('^%s(.*?)%s$' % (removed_prefix, removed_suffix)) - result = pattern.sub('%s\\1%s' % (added_prefix, added_suffix), filename) - listing += [result] - result = separator.join(listing) - return(result) + prefix, suffix, removed_prefix, removed_suffix, + added_prefix=string(), added_suffix=string()): + '''filter_filelist(*args) -> list + + Filter the given list of files. Filtering: Only the elements starting with + prefix and ending with suffix are considered. Processing: removed_prefix + and removed_suffix are removed from each element, added_prefix and + added_suffix are added to each element.''' + listing = list() + for filename in filelist: + if filename.startswith(prefix) and filename.endswith(suffix): + pattern = compiler('^%s(.*?)%s$' % + (removed_prefix, removed_suffix)) + result = pattern.sub('%s\\1%s' % + (added_prefix, added_suffix), filename) + listing += [result] + result = separator.join(listing) + return(result) + def substart(orig, repl, data): - result = data - if data.startswith(orig): - result = repl + data[len(orig):] - return(result) + result = data + if data.startswith(orig): + result = repl + data[len(orig):] + return(result) + def subend(orig, repl, data): - result = data - if data.endswith(orig): - result = repl + data[:len(repl)] - return(result) + result = data + if data.endswith(orig): + result = repl + data[:len(repl)] + return(result) + def nlconvert(text): - '''Convert line-endings to specific for this platform.''' - system = platform.system().lower() - text = text.replace('\r\n', '\n') - if system == 'windows': - text = text.replace('\n', '\r\n') - return(text) + '''Convert line-endings to specific for this platform.''' + system = platform.system().lower() + text = text.replace('\r\n', '\n') + if system == 'windows': + text = text.replace('\n', '\r\n') + return(text) + def nlremove(text): - '''Remove empty lines from the source text.''' - text = nlconvert(text) - text = text.replace('\r\n', '\n') - lines = [line for line in text.split('\n') if line != ''] - text = '\n'.join(lines) - text = nlconvert(text) - return(text) + '''Remove empty lines from the source text.''' + text = nlconvert(text) + text = text.replace('\r\n', '\n') + lines = [line for line in text.split('\n') if line != ''] + text = '\n'.join(lines) + text = nlconvert(text) + return(text) + def nlcount(text): - '''Return count of newlines before and after text.''' - counter = int() - before = int() - after = int() - text = text.replace('\r\n', '\n') - while text[counter] == '\n': - before += 1 - counter += 1 - counter = len(text) -1 - while text[counter] == '\n': - after += 1 - counter -= 1 - print(before, after) + '''Return count of newlines before and after text.''' + counter = int() + before = int() + after = int() + text = text.replace('\r\n', '\n') + while text[counter] == '\n': + before += 1 + counter += 1 + counter = len(text) - 1 + while text[counter] == '\n': + after += 1 + counter -= 1 + print(before, after) -__all__ += ['APP', 'DIRS', 'FILES', 'MODES', 'UTILS'] +__all__ += ['APP', 'DIRS', 'FILES', 'MODES', 'UTILS'] -- 2.39.5