Allow setting CVS username for gnu-web-doc-update.
[gnulib.git] / gnulib-tool.py
blob27cec96017769bc550ef665338b6ff262fd7b566
1 #!/usr/bin/python
3 # Copyright (C) 2002-2021 Free Software Foundation, Inc.
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; either version 3 of the License, or
8 # (at your option) any later version.
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
15 # You should have received a copy of the GNU General Public License
16 # along with this program. If not, see <https://www.gnu.org/licenses/>.
19 # This program is meant for authors or maintainers which want to import
20 # modules from gnulib into their packages.
23 #===============================================================================
24 # Define global imports
25 #===============================================================================
26 import os
27 import re
28 import sys
29 import codecs
30 import random
31 import shutil
32 import argparse
33 import subprocess as sp
34 from tempfile import mktemp
35 from pprint import pprint
36 from pygnulib import constants
37 from pygnulib import classes
40 #===============================================================================
41 # Define global constants
42 #===============================================================================
43 PYTHON3 = constants.PYTHON3
44 APP = constants.APP
45 DIRS = constants.DIRS
46 ENCS = constants.ENCS
47 UTILS = constants.UTILS
48 MODES = constants.MODES
49 TESTS = constants.TESTS
50 compiler = constants.compiler
51 joinpath = constants.joinpath
52 cleaner = constants.cleaner
53 string = constants.string
54 isabs = os.path.isabs
55 isdir = os.path.isdir
56 isfile = os.path.isfile
57 normpath = os.path.normpath
58 relpath = os.path.relpath
61 #===============================================================================
62 # Define main part
63 #===============================================================================
64 def main():
65 # Reset arguments
66 mode = None
67 destdir = None
68 localdir = None
69 modcache = None
70 verbose = None
71 auxdir = None
72 modules = None
73 avoids = None
74 sourcebase = None
75 m4base = None
76 pobase = None
77 docbase = None
78 testsbase = None
79 tests = None
80 libname = None
81 lgpl = None
82 makefile = None
83 libtool = None
84 conddeps = None
85 macro_prefix = None
86 podomain = None
87 witness_c_macro = None
88 vc_files = None
89 dryrun = None
90 errors = None
92 info = classes.GLInfo()
93 parser = argparse.ArgumentParser(
94 prog=constants.APP['name'],
95 usage='gnulib-tool.py --help',
96 add_help=False)
97 # help
98 parser.add_argument('-h', '--help', '--hel', '--he', '--h',
99 dest='help',
100 default=None,
101 action='store_true')
102 # version
103 parser.add_argument('--version', '--versio', '--versi', '--vers',
104 dest='version',
105 default=None,
106 action='store_true')
107 # list
108 parser.add_argument('-l', '--list', '--lis',
109 dest='mode_list',
110 default=None,
111 action='store_true')
112 # find
113 parser.add_argument('-f', '--find', '--fin', '--fi', '--f',
114 dest='mode_find',
115 default=None,
116 nargs='*')
117 # import
118 parser.add_argument('-i', '--import',
119 dest='mode_import',
120 default=None,
121 nargs='*')
122 # add-import
123 parser.add_argument('-a', '--add-import',
124 dest='mode_add_import',
125 default=None,
126 nargs='+')
127 # remove-import
128 parser.add_argument('-r', '--remove-import',
129 dest='mode_remove_import',
130 default=None,
131 nargs='+')
132 # update
133 parser.add_argument('-u', '--update',
134 dest='mode_update',
135 default=None,
136 action='store_true')
137 # create-testdir
138 parser.add_argument('-td', '--create-testdir',
139 dest='mode_create_testdir',
140 default=None,
141 nargs='*')
142 # create-megatestdir
143 parser.add_argument('-mtd', '--create-megatestdir',
144 dest='mode_create_megatestdir',
145 default=None,
146 nargs='*')
147 # test
148 parser.add_argument('-t', '--test',
149 dest='mode_test',
150 default=None,
151 nargs='*')
152 # megatest
153 parser.add_argument('-mt', '--megatest', '--megates', '--megate', '--megat',
154 '--mega', '--meg', '--me', '--m',
155 dest='mode_megatest',
156 default=None,
157 nargs='*')
158 # copy-file
159 parser.add_argument('-c', '--copy-file',
160 dest='mode_copy_file',
161 default=None,
162 nargs='+')
163 # extract-*
164 parser.add_argument('-xD', '--extract-description',
165 dest='mode_xdescription',
166 default=None,
167 nargs='*')
168 parser.add_argument('-xc', '--extract-comment',
169 dest='mode_xcomment',
170 default=None,
171 nargs='*')
172 parser.add_argument('-xs', '--extract-status',
173 dest='mode_xstatus',
174 default=None,
175 nargs='*')
176 parser.add_argument('-xn', '--extract-notice',
177 dest='mode_xnotice',
178 default=None,
179 nargs='*')
180 parser.add_argument('-xa', '--extract-applicability',
181 dest='mode_xapplicability',
182 default=None,
183 nargs='*')
184 parser.add_argument('-xf', '--extract-filelist',
185 dest='mode_xfilelist',
186 default=None,
187 nargs='*')
188 parser.add_argument('-xd', '--extract-dependencies',
189 dest='mode_xdependencies',
190 default=None,
191 nargs='*')
192 parser.add_argument('-xac', '--extract-autoconf-snippet',
193 dest='mode_xautoconf',
194 default=None,
195 nargs='*')
196 parser.add_argument('-xam', '--extract-automake-snippet',
197 dest='mode_xautomake',
198 default=None,
199 nargs='*')
200 parser.add_argument('-xi', '--extract-include-directive',
201 dest='mode_xinclude',
202 default=None,
203 nargs='*')
204 parser.add_argument('-xl', '--extract-link-directive',
205 dest='mode_xlink',
206 default=None,
207 nargs='*')
208 parser.add_argument('-xL', '--extract-license',
209 dest='mode_xlicense',
210 default=None,
211 nargs='*')
212 parser.add_argument('-xm', '--extract-maintainer',
213 dest='mode_xmaintainer',
214 default=None,
215 nargs='*')
216 # no-changelog: a no-op for backward compatibility
217 parser.add_argument('--no-changelog',
218 dest='changelog',
219 default=None,
220 action='store_false')
221 # destdir
222 parser.add_argument('-d', '--dir',
223 dest='destdir',
224 default=None,
225 nargs=1)
226 # localdir
227 parser.add_argument('-ld', '--local-dir',
228 dest='localdir',
229 default=None,
230 nargs=1)
231 # verbose
232 parser.add_argument('-v', '--verbose',
233 default=0,
234 action='count')
235 # quiet
236 parser.add_argument('-q', '--quiet',
237 default=0,
238 action='count')
239 # dryrun
240 parser.add_argument('--dry-run',
241 dest='dryrun',
242 default=None,
243 action='store_true')
244 # inctests
245 parser.add_argument('--with-tests',
246 dest='inctests',
247 default=None,
248 action='store_true')
249 # makefile
250 parser.add_argument("--makefile-name",
251 dest="makefile",
252 default=None,
253 type=str)
254 # obsolete
255 parser.add_argument('--with-obsolete',
256 dest='obsolete',
257 default=None,
258 action='store_true')
259 # c++-tests
260 parser.add_argument('--with-c++-tests',
261 dest='cxx',
262 default=None,
263 action='store_true')
264 # longrunning-tests
265 parser.add_argument('--with-longrunning-tests',
266 dest='longrunning',
267 default=None,
268 action='store_true')
269 # privileged-tests
270 parser.add_argument('--with-privileged-tests',
271 dest='privileged',
272 default=None,
273 action='store_true')
274 # unportable-tests
275 parser.add_argument('--with-unportable-tests',
276 dest='unportable',
277 default=None,
278 action='store_true')
279 # all-tests
280 parser.add_argument('--with-all-tests',
281 dest='alltests',
282 default=None,
283 action='store_true')
284 # auxdir
285 parser.add_argument('--aux-dir',
286 dest='auxdir',
287 default=None,
288 nargs=1)
289 # libname
290 parser.add_argument('--lib',
291 dest='libname',
292 default=None,
293 nargs=1)
294 # libtool
295 parser.add_argument("--libtool",
296 dest=libtool,
297 default=False,
298 action="store_true")
299 # sourcebase
300 parser.add_argument('-sb', '--source-base',
301 dest='sourcebase',
302 default=None,
303 nargs=1)
304 # m4base
305 parser.add_argument('-mb', '--m4-base',
306 dest='m4base',
307 default=None,
308 nargs=1)
309 # pobase
310 parser.add_argument('-pb', '--po-base',
311 dest='pobase',
312 default=None,
313 nargs=1)
314 # docbase
315 parser.add_argument('-db', '--doc-base',
316 dest='docbase',
317 default=None,
318 nargs=1)
319 # testsbase
320 parser.add_argument('-tb', '--tests-base',
321 dest='testsbase',
322 default=None,
323 nargs=1)
324 # lgpl
325 parser.add_argument('--lgpl',
326 dest='lgpl',
327 default=False,
328 type=int,
329 nargs='?')
330 # avoids
331 parser.add_argument('--avoid',
332 dest='avoids',
333 default=None,
334 nargs='+')
336 # Parse the given arguments.
337 cmdargs = parser.parse_args()
339 # Determine when user tries to combine modes.
340 args = [
341 cmdargs.mode_list,
342 cmdargs.mode_import,
343 cmdargs.mode_add_import,
344 cmdargs.mode_remove_import,
345 cmdargs.mode_update,
346 cmdargs.mode_create_testdir,
347 cmdargs.mode_create_megatestdir,
348 cmdargs.mode_test,
349 cmdargs.mode_megatest,
350 cmdargs.mode_copy_file,
351 cmdargs.mode_xdescription,
352 cmdargs.mode_xcomment,
353 cmdargs.mode_xstatus,
354 cmdargs.mode_xnotice,
355 cmdargs.mode_xapplicability,
356 cmdargs.mode_xfilelist,
357 cmdargs.mode_xdependencies,
358 cmdargs.mode_xautoconf,
359 cmdargs.mode_xautomake,
360 cmdargs.mode_xinclude,
361 cmdargs.mode_xlink,
362 cmdargs.mode_xlicense,
363 cmdargs.mode_xmaintainer,
365 overflow = [arg for arg in args if arg]
366 if len(overflow) > 1:
367 message = 'gnulib-tool: Unable to combine different modes of work.\n'
368 message += 'Try \'gnulib-tool --help\' for more information.\n'
369 sys.stderr.write(message)
370 sys.exit(1)
372 # Determine selected mode.
373 if cmdargs.help != None:
374 print(info.usage())
375 sys.exit(0)
376 if cmdargs.version != None:
377 message = '''gnulib-tool (%s %s)%s\n%s\n%s\n\nWritten by %s.''' % \
378 (info.package(), info.date(), info.version(), info.copyright(),
379 info.license(), info.authors())
380 print(message)
381 sys.exit(0)
382 if cmdargs.mode_list != None:
383 mode = 'list'
384 if cmdargs.mode_import != None:
385 mode = 'import'
386 modules = list(cmdargs.mode_import)
387 if cmdargs.mode_add_import != None:
388 mode = 'add-import'
389 modules = list(cmdargs.mode_add_import)
390 if cmdargs.mode_remove_import != None:
391 mode = 'remove-import'
392 modules = list(cmdargs.mode_remove_import)
393 if cmdargs.mode_update != None:
394 mode = 'update'
395 if cmdargs.mode_create_testdir != None:
396 mode = 'create-testdir'
397 modules = list(cmdargs.mode_create_testdir)
398 if cmdargs.mode_create_megatestdir != None:
399 mode = 'create-megatestdir'
400 modules = list(cmdargs.mode_create_megatestdir)
401 if cmdargs.mode_test != None:
402 mode = 'test'
403 modules = list(cmdargs.mode_test)
404 if cmdargs.mode_megatest != None:
405 mode = 'megatest'
406 modules = list(cmdargs.mode_megatest)
407 if cmdargs.mode_xdescription != None:
408 mode = 'extract-description'
409 modules = list(cmdargs.mode_xdescription)
410 if cmdargs.mode_xcomment != None:
411 mode = 'extract-comment'
412 modules = list(cmdargs.mode_xcomment)
413 if cmdargs.mode_xstatus != None:
414 mode = 'extract-status'
415 modules = list(cmdargs.mode_xstatus)
416 if cmdargs.mode_xnotice != None:
417 mode = 'extract-notice'
418 modules = list(cmdargs.mode_xnotice)
419 if cmdargs.mode_xapplicability != None:
420 mode = 'extract-applicability'
421 modules = list(cmdargs.mode_xapplicability)
422 if cmdargs.mode_xfilelist != None:
423 mode = 'extract-filelist'
424 modules = list(cmdargs.mode_xfilelist)
425 if cmdargs.mode_xautoconf != None:
426 mode = 'extract-autoconf-snippet'
427 modules = list(cmdargs.mode_xautoconf)
428 if cmdargs.mode_xautomake != None:
429 mode = 'extract-automake-snippet'
430 modules = list(cmdargs.mode_xautomake)
431 if cmdargs.mode_xdependencies != None:
432 mode = 'extract-dependencies'
433 modules = list(cmdargs.mode_xdependencies)
434 if cmdargs.mode_xinclude != None:
435 mode = 'extract-include-directive'
436 modules = list(cmdargs.mode_xinclude)
437 if cmdargs.mode_xlink != None:
438 mode = 'extract-link-directive'
439 modules = list(cmdargs.mode_xlink)
440 if cmdargs.mode_xlicense != None:
441 mode = 'extract-license'
442 modules = list(cmdargs.mode_xlicense)
443 if cmdargs.mode_xmaintainer != None:
444 mode = 'extract-maintainer'
445 modules = list(cmdargs.mode_xmaintainer)
446 if cmdargs.mode_copy_file != None:
447 mode = 'copy-file'
448 if len(cmdargs.mode_copy_file) > 2:
449 message = '%s: *** ' % constants.APP['name']
450 message += 'invalid number of arguments for --%s' % mode
451 message += '\n%s: *** Exit.\n' % constants.APP['name']
452 sys.stderr.write(message)
453 sys.exit(1)
454 files = list(cmdargs.mode_copy_file)
456 # Determine specific settings.
457 destdir = cmdargs.destdir
458 if destdir != None:
459 destdir = cmdargs.destdir[0]
460 localdir = cmdargs.localdir
461 if localdir != None:
462 localdir = cmdargs.localdir[0]
463 libname = cmdargs.libname
464 if libname != None:
465 libname = cmdargs.libname[0]
466 auxdir = cmdargs.auxdir
467 if auxdir != None:
468 auxdir = cmdargs.auxdir[0]
469 sourcebase = cmdargs.sourcebase
470 if sourcebase != None:
471 sourcebase = cmdargs.sourcebase[0]
472 m4base = cmdargs.m4base
473 if m4base != None:
474 m4base = cmdargs.m4base[0]
475 pobase = cmdargs.pobase
476 if pobase != None:
477 pobase = cmdargs.pobase[0]
478 testsbase = cmdargs.testsbase
479 if testsbase != None:
480 testsbase = cmdargs.testsbase[0]
481 dryrun = cmdargs.dryrun
482 verbose = -cmdargs.quiet + cmdargs.verbose
483 inctests = cmdargs.inctests
484 flags = [cmdargs.inctests, cmdargs.obsolete, cmdargs.cxx,
485 cmdargs.longrunning, cmdargs.privileged, cmdargs.unportable,
486 cmdargs.alltests]
487 testflags = list()
488 for flag in flags:
489 index = flags.index(flag)
490 if flag != None:
491 if flag:
492 if index == 0:
493 testflags += [constants.TESTS['tests']]
494 elif index == 1:
495 testflags += [constants.TESTS['obsolete']]
496 elif index == 2:
497 testflags += [constants.TESTS['cxx-tests']]
498 elif index == 3:
499 testflags += [constants.TESTS['longrunning-tests']]
500 elif index == 4:
501 testflags += [constants.TESTS['privileged-tests']]
502 elif index == 5:
503 testflags += [constants.TESTS['unportable-tests']]
504 elif index == 6:
505 testflags += [constants.TESTS['all-tests']]
506 lgpl = cmdargs.lgpl
507 libtool = cmdargs.libtool
508 makefile = cmdargs.makefile
509 if lgpl == None:
510 lgpl = True
511 avoids = cmdargs.avoids
513 # Create pygnulib configuration.
514 config = classes.GLConfig(
515 destdir=destdir,
516 localdir=localdir,
517 m4base=m4base,
518 auxdir=auxdir,
519 modules=modules,
520 avoids=avoids,
521 sourcebase=sourcebase,
522 pobase=pobase,
523 docbase=docbase,
524 testsbase=testsbase,
525 testflags=testflags,
526 libname=libname,
527 lgpl=lgpl,
528 makefile=makefile,
529 libtool=libtool,
530 conddeps=conddeps,
531 macro_prefix=macro_prefix,
532 podomain=podomain,
533 witness_c_macro=witness_c_macro,
534 vc_files=vc_files,
535 modcache=modcache,
536 verbose=verbose,
537 dryrun=dryrun,
540 # Canonicalize the inctests variable.
541 if inctests == None:
542 if mode in ['import', 'add-import', 'remove-import', 'update']:
543 config.disableTestFlag(TESTS['tests'])
544 elif mode in ['create-testdir', 'create-megatestdir', 'test', 'megatest']:
545 config.enableTestFlag(TESTS['tests'])
547 # Work in the given mode.
548 if mode in ['list']:
549 modulesystem = classes.GLModuleSystem(config)
550 listing = modulesystem.list()
551 result = '\n'.join(listing)
552 os.rmdir(config['tempdir'])
553 print(result)
555 elif mode in ['import', 'add-import', 'remove-import', 'update']:
556 mode = MODES[mode]
557 if not destdir:
558 destdir = '.'
559 config.setDestDir(destdir)
561 if mode == MODES['import']:
562 # Set variables to default values.
563 if not sourcebase:
564 sourcebase = 'lib'
565 if not m4base:
566 m4base = 'm4'
567 if not docbase:
568 docbase = 'doc'
569 if not testsbase:
570 testsbase = 'tests'
571 if not macro_prefix:
572 macro_prefix = 'gl'
573 config.setSourceBase(sourcebase)
574 config.setM4Base(m4base)
575 config.setDocBase(docbase)
576 config.setTestsBase(testsbase)
577 config.setMacroPrefix(macro_prefix)
579 # Perform GLImport actions.
580 importer = classes.GLImport(config, mode)
581 filetable, transformers = importer.prepare()
582 importer.execute(filetable, transformers)
584 else: # if mode != MODE['--import']
585 if m4base:
586 if not isfile(joinpath(destdir, m4base, 'gnulib-cache.m4')):
587 if not sourcebase:
588 sourcebase = 'lib'
589 if not docbase:
590 docbase = 'doc'
591 if not testsbase:
592 testsbase = 'tests'
593 if not macro_prefix:
594 macro_prefix = 'gl'
595 config.setSourceBase(sourcebase)
596 config.setM4Base(m4base)
597 config.setDocBase(docbase)
598 config.setTestsBase(testsbase)
599 config.setMacroPrefix(macro_prefix)
600 # Perform GLImport actions.
601 importer = classes.GLImport(config, mode)
602 filetable, transformers = importer.prepare()
603 importer.execute(filetable, transformers)
604 else: # if not m4base
605 m4dirs = list()
606 dirisnext = bool()
607 filepath = joinpath(destdir, 'Makefile.am')
608 if isfile(filepath):
609 with codecs.open(filepath, 'rb', 'UTF-8') as file:
610 data = file.read()
611 data = data.split('ACLOCAL_AMFLAGS')[1]
612 data = data[data.find('=') + 1:data.find('\n')]
613 aclocal_amflags = data.split()
614 for aclocal_amflag in aclocal_amflags:
615 if dirisnext:
616 if not isabs(aclocal_amflag):
617 m4dirs += [aclocal_amflag]
618 else: # if not dirisnext
619 if aclocal_amflag == '-I':
620 dirisnext = True
621 else: # if aclocal_amflag != '-I'
622 dirisnext = False
623 else: # if not isfile(filepath)
624 filepath = joinpath(destdir, 'aclocal.m4')
625 if isfile(filepath):
626 pattern = constants.compiler(
627 r'm4_include\(\[(.*?)\]\)')
628 with codecs.open(filepath, 'rb', 'UTF-8') as file:
629 m4dirs = pattern.findall(file.read())
630 m4dirs = [os.path.dirname(m4dir) for m4dir in m4dirs]
631 m4dirs = \
632 [ # Begin filtering
633 m4dir for m4dir in m4dirs \
634 if isfile(joinpath(destdir, m4dir, 'gnulib-cache.m4'))
635 ] # Finish filtering
636 m4dirs = sorted(set(m4dirs))
637 if len(m4dirs) == 0:
638 # First use of gnulib in a package.
639 # Any number of additional modules can be given.
640 if not sourcebase:
641 sourcebase = 'lib'
642 m4base = 'm4'
643 if not docbase:
644 docbase = 'doc'
645 if not testsbase:
646 testsbase = 'tests'
647 if not macro_prefix:
648 macro_prefix = 'gl'
649 config.setSourceBase(sourcebase)
650 config.setM4Base(m4base)
651 config.setDocBase(docbase)
652 config.setTestsBase(testsbase)
653 config.setMacroPrefix(macro_prefix)
654 # Perform GLImport actions.
655 importer = classes.GLImport(config, mode)
656 filetable, transformers = importer.prepare()
657 importer.execute(filetable, transformers)
658 elif len(m4dirs) == 1:
659 m4base = m4dirs[-1]
660 config.setM4Base(m4base)
661 # Perform GLImport actions.
662 importer = classes.GLImport(config, mode)
663 filetable, transformers = importer.prepare()
664 importer.execute(filetable, transformers)
665 else: # if len(m4dirs) > 1
666 for m4base in m4dirs:
667 config.setM4Base(m4base)
668 # Perform GLImport actions.
669 importer = classes.GLImport(config, mode)
670 filetable, transformers = importer.prepare()
671 importer.execute(filetable, transformers)
673 elif mode == 'create-testdir':
674 if not destdir:
675 message = '%s: *** ' % constants.APP['name']
676 message += 'please specify --dir option'
677 message += '\n%s: *** Exit.\n' % constants.APP['name']
678 sys.stderr.write(message)
679 sys.exit(1)
680 if not auxdir:
681 auxdir = 'build-aux'
682 config.setAuxDir(auxdir)
683 testdir = classes.GLTestDir(config, destdir)
684 testdir.execute()
686 elif mode == 'create-megatestdir':
687 if not destdir:
688 message = '%s: *** ' % constants.APP['name']
689 message += 'please specify --dir option'
690 message += '\n%s: *** Exit.\n' % constants.APP['name']
691 sys.stderr.write(message)
692 sys.exit(1)
693 if not auxdir:
694 auxdir = 'build-aux'
695 config.setAuxDir(auxdir)
696 testdir = classes.GLMegaTestDir(config, destdir)
697 testdir.execute()
699 elif mode == 'test':
700 if not destdir:
701 destdir = 'testdir %04d' % random.randrange(0, 9999)
702 if not auxdir:
703 auxdir = 'build-aux'
704 config.setAuxDir(auxdir)
705 testdir = classes.GLTestDir(config, destdir)
706 testdir.execute()
707 os.chdir(destdir)
708 os.mkdir('build')
709 os.chdir('build')
710 try: # Try to execute commands
711 sp.call(['../configure'])
712 sp.call([UTILS['make']])
713 sp.call([UTILS['make'], 'check'])
714 sp.call([UTILS['make'], 'distclean'])
715 except Exception as error:
716 sys.exit(1)
717 args = ['find', '.', '-type', 'f', '-print']
718 remaining = sp.check_output(args).decode(ENCS['shell'])
719 lines = [line.strip()
720 for line in remaining.split('\n') if line.strip()]
721 remaining = ' '.join(lines)
722 if remaining:
723 message = 'Remaining files: %s\n' % remaining
724 message += 'gnulib-tool: *** Stop.\n'
725 sys.stderr.write(message)
726 sys.exit(1)
727 os.chdir('../..')
728 sp.call(['rm', '-rf', destdir], shell=False)
730 elif mode == 'megatest':
731 if not destdir:
732 destdir = 'testdir %04d' % random.randrange(0, 9999)
733 if not auxdir:
734 auxdir = 'build-aux'
735 config.setAuxDir(auxdir)
736 testdir = classes.GLMegaTestDir(config, destdir)
737 testdir.execute()
738 os.chdir(destdir)
739 os.mkdir('build')
740 os.chdir('build')
741 sp.call(['../configure'])
742 sp.call([UTILS['make']])
743 sp.call([UTILS['make'], 'check'])
744 sp.call([UTILS['make'], 'distclean'])
745 args = ['find', '.', '-type', 'f', '-print']
746 remaining = sp.check_output(args).decode(ENCS['shell'])
747 lines = [line.strip()
748 for line in remaining.split('\n') if line.strip()]
749 remaining = ' '.join(lines)
750 if remaining:
751 message = 'Remaining files: %s\n' % remaining
752 message += 'gnulib-tool: *** Stop.\n'
753 sys.stderr.write(message)
754 sys.exit(1)
755 os.chdir('../..')
756 sp.call(['rm', '-rf', destdir], shell=False)
758 elif mode == 'extract-description':
759 modulesystem = classes.GLModuleSystem(config)
760 modules = [modulesystem.find(module) for module in modules]
761 for module in modules:
762 print(module.getDescription())
764 elif mode == 'extract-comment':
765 modulesystem = classes.GLModuleSystem(config)
766 modules = [modulesystem.find(module) for module in modules]
767 for module in modules:
768 print(module.getComment())
770 elif mode == 'extract-status':
771 modulesystem = classes.GLModuleSystem(config)
772 modules = [modulesystem.find(module) for module in modules]
773 for module in modules:
774 status = module.getStatus()
775 print('\n'.join(status))
777 elif mode == 'extract-notice':
778 modulesystem = classes.GLModuleSystem(config)
779 modules = [modulesystem.find(module) for module in modules]
780 for module in modules:
781 print(module.getNotice())
783 elif mode == 'extract-applicability':
784 modulesystem = classes.GLModuleSystem(config)
785 modules = [modulesystem.find(module) for module in modules]
786 for module in modules:
787 print(module.getApplicability())
789 elif mode == 'extract-filelist':
790 modulesystem = classes.GLModuleSystem(config)
791 modules = [modulesystem.find(module) for module in modules]
792 for module in modules:
793 files = module.getFiles()
794 print('\n'.join(files))
796 elif mode == 'extract-dependencies':
797 result = string()
798 if avoids:
799 message = '%s: *** ' % constants.APP['name']
800 message += 'cannot combine --avoid and --extract-dependencies\n'
801 message += '%s: *** Exit.\n' % constants.APP['name']
802 sys.stderr.write(message)
803 sys.exit(1)
804 modulesystem = classes.GLModuleSystem(config)
805 modules = [modulesystem.find(module) for module in modules]
806 for module in modules:
807 dependencies = module.getDependencies()
808 if dependencies:
809 for depmodule, condition in dependencies:
810 if condition == None:
811 result += '%s\n' % str(depmodule)
812 else: # if condition != None
813 result += '%s\t%s' % (str(depmodule), condition)
814 print(result)
816 elif mode == 'extract-autoconf-snippet':
817 modulesystem = classes.GLModuleSystem(config)
818 modules = [modulesystem.find(module) for module in modules]
819 for module in modules:
820 print(module.getAutoconfSnippet())
822 elif mode == 'extract-automake-snippet':
823 modulesystem = classes.GLModuleSystem(config)
824 modules = [modulesystem.find(module) for module in modules]
825 for module in modules:
826 print(module.getAutomakeSnippet())
828 elif mode == 'extract-include-directive':
829 modulesystem = classes.GLModuleSystem(config)
830 modules = [modulesystem.find(module) for module in modules]
831 for module in modules:
832 print(module.getInclude())
834 elif mode == 'extract-link-directive':
835 modulesystem = classes.GLModuleSystem(config)
836 modules = [modulesystem.find(module) for module in modules]
837 for module in modules:
838 print(module.getLink())
840 elif mode == 'extract-license':
841 modulesystem = classes.GLModuleSystem(config)
842 modules = [modulesystem.find(module) for module in modules]
843 for module in modules:
844 print(module.getLicense())
846 elif mode == 'extract-maintainer':
847 modulesystem = classes.GLModuleSystem(config)
848 modules = [modulesystem.find(module) for module in modules]
849 for module in modules:
850 print(module.getMaintainer())
852 elif mode == 'extract-tests-module':
853 modulesystem = classes.GLModuleSystem(config)
854 modules = [modulesystem.find(module) for module in modules]
855 for module in modules:
856 if module.getTestsModule():
857 print(module.getTestsName())
859 elif mode == 'copy-file':
860 srcpath = files[0]
861 if len(files) == 2:
862 dest = files[1]
863 else: # if len(files) != 2
864 dest = '.'
865 if type(srcpath) is bytes:
866 srcpath = srcpath.decode(ENCS['default'])
867 if type(dest) is bytes:
868 dest = dest.decode(ENCS['default'])
869 if not auxdir:
870 auxdir = 'build-aux'
871 if not sourcebase:
872 sourcebase = 'lib'
873 if not m4base:
874 m4base = 'm4'
875 if not docbase:
876 docbase = 'doc'
877 if not testsbase:
878 testsbase = 'tests'
879 config.setAuxDir(auxdir)
880 config.setSourceBase(sourcebase)
881 config.setM4Base(m4base)
882 config.setDocBase(docbase)
883 config.setTestsBase(testsbase)
884 filesystem = classes.GLFileSystem(config)
885 lookedup, flag = filesystem.lookup(srcpath)
886 if isdir(dest):
887 destdir = string(dest)
888 if srcpath.startswith('build-aux/'):
889 destpath = constants.substart(
890 'build-aux/', '%s/' % auxdir, srcpath)
891 elif srcpath.startswith('doc/'):
892 destpath = constants.substart('doc/', '%s/' % docbase, srcpath)
893 elif srcpath.startswith('lib/'):
894 destpath = constants.substart(
895 'lib/', '%s/' % sourcebase, srcpath)
896 elif srcpath.startswith('m4/'):
897 destpath = constants.substart('m4/', '%s/' % m4base, srcpath)
898 elif srcpath.startswith('tests/'):
899 destpath = constants.substart(
900 'tests/', '%s/' % testsbase, srcpath)
901 elif srcpath.startswith('tests=lib/'):
902 destpath = constants.substart(
903 'tests=lib/', '%s/' % testsbase, srcpath)
904 elif srcpath.startswith('top/'):
905 destpath = constants.substart('top/', '', srcpath)
906 else: # either case
907 destpath = srcpath
908 else: # if not isdir(destpath)
909 destdir = os.path.dirname(destpath)
910 destpath = os.path.basename(destpath)
911 # Create the directory for destfile.
912 dirname = os.path.dirname(joinpath(destdir, destpath))
913 if not config['dryrun']:
914 if dirname and not isdir(dirname):
915 try: # Try to create directories
916 os.makedirs(dirname)
917 except Exception as error:
918 pass
919 # Copy the file.
920 assistant = classes.GLFileAssistant(config)
921 tmpfile = assistant.tmpfilename(destpath)
922 shutil.copy(lookedup, tmpfile)
923 already_present = True
924 assistant.setOriginal(srcpath)
925 assistant.setRewritten(destpath)
926 if isfile(joinpath(destdir, destpath)):
927 # The file already exists.
928 assistant.update(lookedup, flag, tmpfile, already_present)
929 else: # if not isfile(joinpath(destdir, destpath))
930 # Install the file.
931 # Don't protest if the file should be there but isn't: it happens
932 # frequently that developers don't put autogenerated files under version
933 # control.
934 assistant.add(lookedup, flag, tmpfile)
935 if isfile(tmpfile):
936 os.remove(tmpfile)
938 else:
939 message = '%s: *** ' % constants.APP['name']
940 message += 'no mode specified'
941 message += '\n%s: *** Exit.\n' % constants.APP['name']
942 sys.stderr.write(message)
943 sys.exit(1)
946 if __name__ == '__main__':
947 try: # Try to execute
948 main()
949 except classes.GLError as error:
950 errmode = 0 # gnulib-style errors
951 errno = error.errno
952 errinfo = error.errinfo
953 if errmode == 0:
954 message = '%s: *** ' % constants.APP['name']
955 if errinfo == None:
956 errinfo = string()
957 if errno == 1:
958 message += 'file %s not found' % errinfo
959 elif errno == 2:
960 message += 'patch file %s didn\'t apply cleanly' % errinfo
961 elif errno == 3:
962 message += 'cannot find %s - make sure ' % errinfo
963 message += 'you run gnulib-tool from within your package\'s directory'
964 elif errno == 4:
965 message += 'minimum supported autoconf version is 2.59. Try adding'
966 message += 'AC_PREREQ([%s])' % constants.DEFAULT_AUTOCONF_MINVERSION
967 message += ' to your configure.ac.'
968 elif errno == 5:
969 "%s is expected to contain gl_M4_BASE([%s])" % \
970 (repr(os.path.join(errinfo, 'gnulib-comp.m4')), repr(errinfo))
971 elif errno == 6:
972 message += 'missing --source-base option'
973 elif errno == 7:
974 message += 'missing --doc-base option. --doc-base has been introduced '
975 message += 'on 2006-07-11; if your last invocation of \'gnulib-tool '
976 message += '--import\' is before that date, you need to run'
977 message += '\'gnulib-tool --import\' once, with a --doc-base option.'
978 elif errno == 8:
979 message += 'missing --tests-base option'
980 elif errno == 9:
981 message += 'missing --lib option'
982 elif errno == 10:
983 message = 'gnulib-tool: option --conditional-dependencies is not '
984 message += 'supported with --with-tests\n'
985 elif errno == 11:
986 incompatibilities = string()
987 message += 'incompatible license on modules:%s' % constants.NL
988 for pair in errinfo:
989 incompatibilities += pair[0]
990 incompatibilities += ' %s' % pair[1]
991 incompatibilities += constants.NL
992 tempname = mktemp()
993 with codecs.open(tempname, 'wb', 'UTF-8') as file:
994 file.write(incompatibilities)
995 sed_table = 's,^\\([^ ]*\\) ,\\1' + ' ' * 51 + ',\n'
996 sed_table += 's,^\\(' + '.' * 49 + \
997 '[^ ]*\) *,' + ' ' * 17 + '\\1 ,'
998 args = ['sed', '-e', sed_table, tempname]
999 incompatibilities = sp.check_output(
1000 args).decode(ENCS['default'])
1001 message += incompatibilities
1002 os.remove(tempname)
1003 elif errno == 12:
1004 message += 'refusing to do nothing'
1005 elif errno in [13, 14, 15, 16, 17]:
1006 message += 'failed'
1007 elif errno == 19:
1008 message += 'could not create destination directory: %s' % errinfo
1009 if errno != 10:
1010 message += '\n%s: *** Exit.\n' % constants.APP['name']
1011 sys.stderr.write(message)
1012 sys.exit(1)