3 # Copyright (C) 2002-2024 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.
22 # CODING STYLE for this file and its companions:
23 # Like PEP 8 <https://peps.python.org/pep-0008/>, except
24 # - Line length is not limited to 79 characters.
25 # - Line breaking before or after binary operators? Better before, like in GNU.
26 # - Place line breaks to help reading the code:
27 # Avoid line breaks inside expressions, if they can be avoided.
28 # Do use line breaks to separate the parts of [ ... for ... ] iterations.
29 # You can use this command to check the style:
30 # $ pycodestyle --max-line-length=136 --ignore=E265,W503,E241,E711,E712,E201,E202,E221 gnulib-tool.py pygnulib/*.py
32 # You can use this command to check for mistakes:
33 # $ pylint --disable=C0103,C0114,C0121,C0209,C0301,C0302,R0902,R0912,R0913,R0914,R0915,R1705,R1702,R1720 gnulib-tool.py pygnulib/*.py
36 #===============================================================================
37 # Define global imports
38 #===============================================================================
45 import subprocess
as sp
47 from tempfile
import mktemp
48 from pygnulib
import constants
49 from pygnulib
import classes
52 #===============================================================================
53 # Define global constants
54 #===============================================================================
58 UTILS
= constants
.UTILS
59 MODES
= constants
.MODES
60 TESTS
= constants
.TESTS
61 joinpath
= constants
.joinpath
62 copyfile
= constants
.copyfile
65 isfile
= os
.path
.isfile
68 #===============================================================================
70 #===============================================================================
72 info
= classes
.GLInfo()
73 parser
= argparse
.ArgumentParser(
74 prog
=constants
.APP
['name'],
75 usage
='gnulib-tool.py --help',
78 # Here we list the options in the order they are listed in the --help output.
81 parser
.add_argument('--list',
86 parser
.add_argument('--find',
91 parser
.add_argument('--import',
96 parser
.add_argument('--add-import',
97 dest
='mode_add_import',
101 parser
.add_argument('--remove-import',
102 dest
='mode_remove_import',
106 parser
.add_argument('--update',
111 parser
.add_argument('--create-testdir',
112 dest
='mode_create_testdir',
116 parser
.add_argument('--create-megatestdir',
117 dest
='mode_create_megatestdir',
121 parser
.add_argument('--test',
126 parser
.add_argument('--megatest',
127 dest
='mode_megatest',
131 parser
.add_argument('--extract-description',
132 dest
='mode_xdescription',
135 parser
.add_argument('--extract-comment',
136 dest
='mode_xcomment',
139 parser
.add_argument('--extract-status',
143 parser
.add_argument('--extract-notice',
147 parser
.add_argument('--extract-applicability',
148 dest
='mode_xapplicability',
151 parser
.add_argument('--extract-filelist',
152 dest
='mode_xfilelist',
155 parser
.add_argument('--extract-dependencies',
156 dest
='mode_xdependencies',
159 parser
.add_argument('--extract-autoconf-snippet',
160 dest
='mode_xautoconf',
163 parser
.add_argument('--extract-automake-snippet',
164 dest
='mode_xautomake',
167 parser
.add_argument('--extract-include-directive',
168 dest
='mode_xinclude',
171 parser
.add_argument('--extract-link-directive',
175 parser
.add_argument('--extract-license',
176 dest
='mode_xlicense',
179 parser
.add_argument('--extract-maintainer',
180 dest
='mode_xmaintainer',
183 parser
.add_argument('--extract-tests-module',
188 parser
.add_argument('--copy-file',
189 dest
='mode_copy_file',
193 parser
.add_argument('--help', '--hel', '--he', '--h',
198 parser
.add_argument('--version', '--versio', '--versi', '--vers',
202 # no-changelog: a no-op for backward compatibility
203 parser
.add_argument('--no-changelog',
206 action
='store_false')
208 parser
.add_argument('--dir',
213 parser
.add_argument('--local-dir',
218 # cache-modules: a no-op for backward compatibility
219 parser
.add_argument('--cache-modules',
220 dest
='cache_modules',
223 parser
.add_argument('--no-cache-modules',
224 dest
='cache_modules',
226 action
='store_false')
228 parser
.add_argument('--verbose',
232 parser
.add_argument('--quiet',
236 parser
.add_argument('--dry-run',
241 parser
.add_argument('--with-tests',
245 parser
.add_argument('--without-tests',
248 action
='store_false')
250 parser
.add_argument('--with-obsolete',
255 parser
.add_argument('--with-c++-tests',
256 dest
='inc_cxx_tests',
259 parser
.add_argument('--without-c++-tests',
260 dest
='excl_cxx_tests',
264 parser
.add_argument('--with-longrunning-tests',
265 dest
='inc_longrunning_tests',
268 parser
.add_argument('--without-longrunning-tests',
269 dest
='excl_longrunning_tests',
273 parser
.add_argument('--with-privileged-tests',
274 dest
='inc_privileged_tests',
277 parser
.add_argument('--without-privileged-tests',
278 dest
='excl_privileged_tests',
282 parser
.add_argument('--with-unportable-tests',
283 dest
='inc_unportable_tests',
286 parser
.add_argument('--without-unportable-tests',
287 dest
='excl_unportable_tests',
291 parser
.add_argument('--with-all-tests',
296 parser
.add_argument('--avoid',
301 # conditional-dependencies
302 parser
.add_argument('--conditional-dependencies',
303 dest
='cond_dependencies',
306 parser
.add_argument('--no-conditional-dependencies',
307 dest
='cond_dependencies',
309 action
="store_false")
311 parser
.add_argument('--libtool',
315 parser
.add_argument('--no-libtool',
318 action
="store_false")
320 parser
.add_argument('--lib',
325 parser
.add_argument('--source-base',
330 parser
.add_argument('--m4-base',
335 parser
.add_argument('--po-base',
340 parser
.add_argument('--doc-base',
345 parser
.add_argument('--tests-base',
350 parser
.add_argument('--aux-dir',
355 parser
.add_argument('--lgpl',
359 choices
=['2', '3orGPLv2', '3'],
362 parser
.add_argument('--makefile-name',
363 dest
='makefile_name',
367 parser
.add_argument('--macro-prefix',
372 parser
.add_argument('--po-domain',
377 parser
.add_argument('--witness-c-macro',
378 dest
='witness_c_macro',
382 parser
.add_argument('--vc-files',
386 parser
.add_argument('--no-vc-files',
389 action
='store_false')
391 parser
.add_argument('--single-configure',
392 dest
='single_configure',
396 parser
.add_argument('-s', '--symbolic', '--symlink',
401 parser
.add_argument('--local-symlink',
405 # All other arguments are collected.
406 parser
.add_argument("non_option_arguments",
409 # Parse the given arguments. Don't signal an error if non-option arguments
410 # occur between or after options.
411 cmdargs
, unhandled
= parser
.parse_known_args()
413 # Handle --help and --version, ignoring all other options.
414 if cmdargs
.help != None:
417 if cmdargs
.version
!= None:
418 version
= info
.version()
420 version
= ' ' + version
421 message
= '''gnulib-tool (%s %s)%s\n%s\n%s\n\nWritten by %s.''' \
422 % (info
.package(), info
.date(), version
, info
.copyright(),
423 info
.license(), info
.authors())
427 # Report unhandled arguments.
428 for arg
in unhandled
:
429 if arg
.startswith('-'):
430 message
= '%s: Unrecognized option \'%s\'.\n' % (constants
.APP
['name'], arg
)
431 message
+= 'Try \'gnulib-tool --help\' for more information.\n'
432 sys
.stderr
.write(message
)
434 # By now, all unhandled arguments were non-options.
435 cmdargs
.non_option_arguments
+= unhandled
437 # Determine when user tries to combine modes.
442 cmdargs
.mode_add_import
,
443 cmdargs
.mode_remove_import
,
445 cmdargs
.mode_create_testdir
,
446 cmdargs
.mode_create_megatestdir
,
448 cmdargs
.mode_megatest
,
449 cmdargs
.mode_xdescription
,
450 cmdargs
.mode_xcomment
,
451 cmdargs
.mode_xstatus
,
452 cmdargs
.mode_xnotice
,
453 cmdargs
.mode_xapplicability
,
454 cmdargs
.mode_xfilelist
,
455 cmdargs
.mode_xdependencies
,
456 cmdargs
.mode_xautoconf
,
457 cmdargs
.mode_xautomake
,
458 cmdargs
.mode_xinclude
,
460 cmdargs
.mode_xlicense
,
461 cmdargs
.mode_xmaintainer
,
463 cmdargs
.mode_copy_file
,
468 if len(overflow
) > 1:
469 message
= '%s: Unable to combine different modes of work.\n' % constants
.APP
['name']
470 message
+= 'Try \'gnulib-tool --help\' for more information.\n'
471 sys
.stderr
.write(message
)
474 # Determine selected mode.
478 if cmdargs
.mode_list
!= None:
480 if cmdargs
.mode_find
!= None:
482 files
= list(cmdargs
.non_option_arguments
)
483 if cmdargs
.mode_import
!= None:
485 modules
= list(cmdargs
.non_option_arguments
)
486 if cmdargs
.mode_add_import
!= None:
488 modules
= list(cmdargs
.non_option_arguments
)
489 if cmdargs
.mode_remove_import
!= None:
490 mode
= 'remove-import'
491 modules
= list(cmdargs
.non_option_arguments
)
492 if cmdargs
.mode_update
!= None:
494 if len(cmdargs
.non_option_arguments
) > 0:
495 message
= '%s: too many arguments in \'update\' mode\n'
496 message
+= 'Try \'gnulib-tool --help\' for more information.\n'
497 message
+= 'If you really want to modify the gnulib configuration of your project,\n'
498 message
+= 'you need to use \'gnulib-tool --import\' - at your own risk!\n'
499 sys
.stderr
.write(message
)
501 if cmdargs
.mode_create_testdir
!= None:
502 mode
= 'create-testdir'
503 modules
= list(cmdargs
.non_option_arguments
)
504 if cmdargs
.mode_create_megatestdir
!= None:
505 mode
= 'create-megatestdir'
506 modules
= list(cmdargs
.non_option_arguments
)
507 if cmdargs
.mode_test
!= None:
509 modules
= list(cmdargs
.non_option_arguments
)
510 if cmdargs
.mode_megatest
!= None:
512 modules
= list(cmdargs
.non_option_arguments
)
513 if cmdargs
.mode_xdescription
!= None:
514 mode
= 'extract-description'
515 modules
= list(cmdargs
.non_option_arguments
)
516 if cmdargs
.mode_xcomment
!= None:
517 mode
= 'extract-comment'
518 modules
= list(cmdargs
.non_option_arguments
)
519 if cmdargs
.mode_xstatus
!= None:
520 mode
= 'extract-status'
521 modules
= list(cmdargs
.non_option_arguments
)
522 if cmdargs
.mode_xnotice
!= None:
523 mode
= 'extract-notice'
524 modules
= list(cmdargs
.non_option_arguments
)
525 if cmdargs
.mode_xapplicability
!= None:
526 mode
= 'extract-applicability'
527 modules
= list(cmdargs
.non_option_arguments
)
528 if cmdargs
.mode_xfilelist
!= None:
529 mode
= 'extract-filelist'
530 modules
= list(cmdargs
.non_option_arguments
)
531 if cmdargs
.mode_xautoconf
!= None:
532 mode
= 'extract-autoconf-snippet'
533 modules
= list(cmdargs
.non_option_arguments
)
534 if cmdargs
.mode_xautomake
!= None:
535 mode
= 'extract-automake-snippet'
536 modules
= list(cmdargs
.non_option_arguments
)
537 if cmdargs
.mode_xdependencies
!= None:
538 mode
= 'extract-dependencies'
539 modules
= list(cmdargs
.non_option_arguments
)
540 if cmdargs
.mode_xinclude
!= None:
541 mode
= 'extract-include-directive'
542 modules
= list(cmdargs
.non_option_arguments
)
543 if cmdargs
.mode_xlink
!= None:
544 mode
= 'extract-link-directive'
545 modules
= list(cmdargs
.non_option_arguments
)
546 if cmdargs
.mode_xlicense
!= None:
547 mode
= 'extract-license'
548 modules
= list(cmdargs
.non_option_arguments
)
549 if cmdargs
.mode_xmaintainer
!= None:
550 mode
= 'extract-maintainer'
551 modules
= list(cmdargs
.non_option_arguments
)
552 if cmdargs
.mode_xtests
!= None:
553 mode
= 'extract-tests-module'
554 modules
= list(cmdargs
.non_option_arguments
)
555 if cmdargs
.mode_copy_file
!= None:
557 if len(cmdargs
.non_option_arguments
) < 1 or len(cmdargs
.non_option_arguments
) > 2:
558 message
= '%s: *** ' % constants
.APP
['name']
559 message
+= 'invalid number of arguments for --%s\n' % mode
560 message
+= 'Try \'gnulib-tool --help\' for more information.\n'
561 message
+= '%s: *** Stop.\n' % constants
.APP
['name']
562 sys
.stderr
.write(message
)
564 files
= list(cmdargs
.non_option_arguments
)
566 if ((mode
in ['import', 'add-import', 'remove-import']
567 and (cmdargs
.excl_cxx_tests
or cmdargs
.excl_longrunning_tests
568 or cmdargs
.excl_privileged_tests
or cmdargs
.excl_unportable_tests
569 or cmdargs
.single_configure
))
571 and (cmdargs
.localpath
!= None or cmdargs
.libname
!= None
572 or cmdargs
.sourcebase
!= None or cmdargs
.m4base
!= None
573 or cmdargs
.pobase
!= None or cmdargs
.docbase
!= None
574 or cmdargs
.testsbase
!= None or cmdargs
.auxdir
!= None
575 or cmdargs
.inctests
!= None or cmdargs
.obsolete
!= None
576 or cmdargs
.inc_cxx_tests
!= None
577 or cmdargs
.inc_longrunning_tests
!= None
578 or cmdargs
.inc_privileged_tests
!= None
579 or cmdargs
.inc_unportable_tests
!= None
580 or cmdargs
.alltests
!= None
581 or cmdargs
.excl_cxx_tests
!= None
582 or cmdargs
.excl_longrunning_tests
!= None
583 or cmdargs
.excl_privileged_tests
!= None
584 or cmdargs
.excl_unportable_tests
!= None
585 or cmdargs
.avoids
!= None or cmdargs
.lgpl
!= None
586 or cmdargs
.makefile_name
!= None
587 or cmdargs
.macro_prefix
!= None or cmdargs
.podomain
!= None
588 or cmdargs
.witness_c_macro
!= None or cmdargs
.vc_files
!= None))):
589 message
= '%s: *** ' % constants
.APP
['name']
590 message
+= 'invalid options for --%s mode\n' % mode
591 message
+= 'Try \'gnulib-tool --help\' for more information.\n'
592 message
+= '%s: *** Stop.\n' % constants
.APP
['name']
593 sys
.stderr
.write(message
)
595 if cmdargs
.pobase
!= None and cmdargs
.podomain
== None:
596 message
= '%s: *** ' % constants
.APP
['name']
597 message
+= 'together with --po-base, you need to specify --po-domain\n'
598 message
+= 'Try \'gnulib-tool --help\' for more information.\n'
599 message
+= '%s: *** Stop.\n' % constants
.APP
['name']
600 sys
.stderr
.write(message
)
602 if cmdargs
.pobase
== None and cmdargs
.podomain
!= None:
603 message
= '%s: warning: --po-domain has no effect without a --po-base option\n' % constants
.APP
['name']
604 sys
.stderr
.write(message
)
606 # Determine specific settings.
607 destdir
= cmdargs
.destdir
609 destdir
= cmdargs
.destdir
[0]
610 localpath
= cmdargs
.localpath
611 if localpath
!= None:
613 for list1
in localpath
615 libname
= cmdargs
.libname
617 libname
= cmdargs
.libname
[0]
618 auxdir
= cmdargs
.auxdir
620 auxdir
= cmdargs
.auxdir
[0]
621 sourcebase
= cmdargs
.sourcebase
622 if sourcebase
!= None:
623 sourcebase
= cmdargs
.sourcebase
[0]
624 m4base
= cmdargs
.m4base
626 m4base
= cmdargs
.m4base
[0]
627 pobase
= cmdargs
.pobase
629 pobase
= cmdargs
.pobase
[0]
630 testsbase
= cmdargs
.testsbase
631 if testsbase
!= None:
632 testsbase
= cmdargs
.testsbase
[0]
633 dryrun
= cmdargs
.dryrun
634 verbose
= -cmdargs
.quiet
+ cmdargs
.verbose
635 inctests
= cmdargs
.inctests
636 # Canonicalize the inctests variable.
638 if mode
in ['import', 'add-import', 'remove-import', 'update']:
640 elif mode
in ['create-testdir', 'create-megatestdir', 'test', 'megatest']:
642 incl_test_categories
= []
644 incl_test_categories
+= [constants
.TESTS
['tests']]
646 incl_test_categories
+= [constants
.TESTS
['obsolete']]
647 if cmdargs
.inc_cxx_tests
:
648 incl_test_categories
+= [constants
.TESTS
['cxx-tests']]
649 if cmdargs
.inc_longrunning_tests
:
650 incl_test_categories
+= [constants
.TESTS
['longrunning-tests']]
651 if cmdargs
.inc_privileged_tests
:
652 incl_test_categories
+= [constants
.TESTS
['privileged-tests']]
653 if cmdargs
.inc_unportable_tests
:
654 incl_test_categories
+= [constants
.TESTS
['unportable-tests']]
656 incl_test_categories
+= [constants
.TESTS
['all-tests']]
657 excl_test_categories
= []
658 if cmdargs
.excl_cxx_tests
:
659 excl_test_categories
+= [constants
.TESTS
['cxx-tests']]
660 if cmdargs
.excl_longrunning_tests
:
661 excl_test_categories
+= [constants
.TESTS
['longrunning-tests']]
662 if cmdargs
.excl_privileged_tests
:
663 excl_test_categories
+= [constants
.TESTS
['privileged-tests']]
664 if cmdargs
.excl_unportable_tests
:
665 excl_test_categories
+= [constants
.TESTS
['unportable-tests']]
671 cond_dependencies
= cmdargs
.cond_dependencies
672 libtool
= cmdargs
.libtool
673 makefile_name
= cmdargs
.makefile_name
674 if makefile_name
!= None:
675 makefile_name
= makefile_name
[0]
676 macro_prefix
= cmdargs
.macro_prefix
677 if macro_prefix
!= None:
678 macro_prefix
= macro_prefix
[0]
679 podomain
= cmdargs
.podomain
681 podomain
= podomain
[0]
682 witness_c_macro
= cmdargs
.witness_c_macro
683 if witness_c_macro
!= None:
684 witness_c_macro
= witness_c_macro
[0]
685 vc_files
= cmdargs
.vc_files
686 avoids
= cmdargs
.avoids
690 for module
in list1
]
691 symlink
= cmdargs
.symlink
== True
692 lsymlink
= cmdargs
.lsymlink
== True
693 single_configure
= cmdargs
.single_configure
696 # Create pygnulib configuration.
697 config
= classes
.GLConfig(
704 sourcebase
=sourcebase
,
708 incl_test_categories
=incl_test_categories
,
709 excl_test_categories
=excl_test_categories
,
712 makefile_name
=makefile_name
,
714 conddeps
=cond_dependencies
,
715 macro_prefix
=macro_prefix
,
717 witness_c_macro
=witness_c_macro
,
721 single_configure
=single_configure
,
726 # Work in the given mode.
728 modulesystem
= classes
.GLModuleSystem(config
)
729 listing
= modulesystem
.list()
730 result
= '\n'.join(listing
)
731 os
.rmdir(config
['tempdir'])
735 modulesystem
= classes
.GLModuleSystem(config
)
736 for filename
in files
:
737 if (isfile(joinpath(DIRS
['root'], filename
))
738 or (localpath
!= None
739 and any([ isfile(joinpath(localdir
, filename
))
740 for localdir
in localpath
]))):
741 # Convert the file name to a POSIX basic regex.
742 # Needs to handle . [ \ * ^ $.
743 filename_regex
= filename
.replace('\\', '\\\\').replace('[', '\\[').replace('^', '\\^')
744 filename_regex
= re
.compile('([.*$])').sub('[\\1]', filename_regex
)
745 filename_line_regex
= '^' + filename_regex
+ '$'
746 # Read module candidates from gnulib root directory.
747 command
= "find modules -type f -print | xargs -n 100 grep -l %s /dev/null | sed -e 's,^modules/,,'" % shlex
.quote(filename_line_regex
)
748 os
.chdir(constants
.DIRS
['root'])
749 with sp
.Popen(command
, shell
=True, stdout
=sp
.PIPE
) as proc
:
750 result
= proc
.stdout
.read().decode("UTF-8")
751 os
.chdir(DIRS
['cwd'])
752 # Read module candidates from local directories.
753 if localpath
!= None and len(localpath
) > 0:
754 command
= "find modules -type f -print | xargs -n 100 grep -l %s /dev/null | sed -e 's,^modules/,,' -e 's,\\.diff$,,'" % shlex
.quote(filename_line_regex
)
755 for localdir
in localpath
:
757 with sp
.Popen(command
, shell
=True, stdout
=sp
.PIPE
) as proc
:
758 result
+= proc
.stdout
.read().decode("UTF-8")
759 os
.chdir(DIRS
['cwd'])
761 for line
in result
.split('\n')
763 # Remove modules/ prefix from each file name.
764 pattern
= re
.compile('^modules/')
765 listing
= [ pattern
.sub('', line
)
766 for line
in listing
]
767 # Filter out undesired file names.
770 if modulesystem
.file_is_module(line
) ]
771 candidates
= sorted(set(listing
))
772 for name
in candidates
:
773 module
= modulesystem
.find(name
)
774 if module
: # Ignore module candidates that don't actually exist.
775 if module
.getFiles():
778 message
= '%s: warning: file %s does not exist\n' % (constants
.APP
['name'], filename
)
779 sys
.stderr
.write(message
)
781 elif mode
in ['import', 'add-import', 'remove-import', 'update']:
785 config
.setDestDir(destdir
)
787 if mode
== MODES
['import']:
788 # Set variables to default values.
799 config
.setSourceBase(sourcebase
)
800 config
.setM4Base(m4base
)
801 config
.setDocBase(docbase
)
802 config
.setTestsBase(testsbase
)
803 config
.setMacroPrefix(macro_prefix
)
805 # Perform GLImport actions.
806 importer
= classes
.GLImport(config
, mode
)
807 filetable
, transformers
= importer
.prepare()
808 importer
.execute(filetable
, transformers
)
810 else: # if mode != MODE['--import']
812 if not isfile(joinpath(destdir
, m4base
, 'gnulib-cache.m4')):
821 config
.setSourceBase(sourcebase
)
822 config
.setM4Base(m4base
)
823 config
.setDocBase(docbase
)
824 config
.setTestsBase(testsbase
)
825 config
.setMacroPrefix(macro_prefix
)
826 # Perform GLImport actions.
827 importer
= classes
.GLImport(config
, mode
)
828 filetable
, transformers
= importer
.prepare()
829 importer
.execute(filetable
, transformers
)
830 else: # if not m4base
833 filepath
= joinpath(destdir
, 'Makefile.am')
835 with codecs
.open(filepath
, 'rb', 'UTF-8') as file:
837 data
= data
.split('ACLOCAL_AMFLAGS')[1]
838 data
= data
[data
.find('=') + 1:data
.find('\n')]
839 aclocal_amflags
= data
.split()
840 for aclocal_amflag
in aclocal_amflags
:
842 if not isabs(aclocal_amflag
):
843 m4dirs
+= [aclocal_amflag
]
844 else: # if not dirisnext
845 if aclocal_amflag
== '-I':
847 else: # if aclocal_amflag != '-I'
849 else: # if not isfile(filepath)
850 filepath
= joinpath(destdir
, 'aclocal.m4')
852 pattern
= re
.compile(r
'm4_include\(\[(.*?)\]\)')
853 with codecs
.open(filepath
, 'rb', 'UTF-8') as file:
854 m4dirs
= pattern
.findall(file.read())
855 m4dirs
= [ os
.path
.dirname(m4dir
)
856 for m4dir
in m4dirs
]
859 if isfile(joinpath(destdir
, m4dir
, 'gnulib-cache.m4')) ]
860 m4dirs
= sorted(set(m4dirs
))
862 # First use of gnulib in a package.
863 # Any number of additional modules can be given.
873 config
.setSourceBase(sourcebase
)
874 config
.setM4Base(m4base
)
875 config
.setDocBase(docbase
)
876 config
.setTestsBase(testsbase
)
877 config
.setMacroPrefix(macro_prefix
)
878 # Perform GLImport actions.
879 importer
= classes
.GLImport(config
, mode
)
880 filetable
, transformers
= importer
.prepare()
881 importer
.execute(filetable
, transformers
)
882 elif len(m4dirs
) == 1:
884 config
.setM4Base(m4base
)
885 # Perform GLImport actions.
886 importer
= classes
.GLImport(config
, mode
)
887 filetable
, transformers
= importer
.prepare()
888 importer
.execute(filetable
, transformers
)
889 else: # if len(m4dirs) > 1
890 for m4base
in m4dirs
:
891 config
.setM4Base(m4base
)
892 # Perform GLImport actions.
893 importer
= classes
.GLImport(config
, mode
)
894 filetable
, transformers
= importer
.prepare()
895 importer
.execute(filetable
, transformers
)
897 elif mode
== 'create-testdir':
899 message
= '%s: *** ' % constants
.APP
['name']
900 message
+= 'please specify --dir option\n'
901 message
+= '%s: *** Stop.\n' % constants
.APP
['name']
902 sys
.stderr
.write(message
)
906 config
.setAuxDir(auxdir
)
907 testdir
= classes
.GLTestDir(config
, destdir
)
910 elif mode
== 'create-megatestdir':
912 message
= '%s: *** ' % constants
.APP
['name']
913 message
+= 'please specify --dir option\n'
914 message
+= '%s: *** Stop.\n' % constants
.APP
['name']
915 sys
.stderr
.write(message
)
919 config
.setAuxDir(auxdir
)
920 testdir
= classes
.GLMegaTestDir(config
, destdir
)
925 destdir
= 'testdir%04d' % random
.randrange(0, 9999)
928 config
.setAuxDir(auxdir
)
929 testdir
= classes
.GLTestDir(config
, destdir
)
934 try: # Try to execute commands
935 sp
.call(['../configure'])
936 sp
.call([UTILS
['make']])
937 sp
.call([UTILS
['make'], 'check'])
938 sp
.call([UTILS
['make'], 'distclean'])
939 except Exception as error
:
941 args
= ['find', '.', '-type', 'f', '-print']
942 remaining
= sp
.check_output(args
).decode(ENCS
['shell'])
943 lines
= [ line
.strip()
944 for line
in remaining
.split('\n')
946 remaining
= ' '.join(lines
)
948 message
= 'Remaining files: %s\n' % remaining
949 message
+= 'gnulib-tool: *** Stop.\n'
950 sys
.stderr
.write(message
)
953 sp
.call(['rm', '-rf', destdir
], shell
=False)
955 elif mode
== 'megatest':
957 destdir
= 'testdir %04d' % random
.randrange(0, 9999)
960 config
.setAuxDir(auxdir
)
961 testdir
= classes
.GLMegaTestDir(config
, destdir
)
966 sp
.call(['../configure'])
967 sp
.call([UTILS
['make']])
968 sp
.call([UTILS
['make'], 'check'])
969 sp
.call([UTILS
['make'], 'distclean'])
970 args
= ['find', '.', '-type', 'f', '-print']
971 remaining
= sp
.check_output(args
).decode(ENCS
['shell'])
972 lines
= [ line
.strip()
973 for line
in remaining
.split('\n')
975 remaining
= ' '.join(lines
)
977 message
= 'Remaining files: %s\n' % remaining
978 message
+= 'gnulib-tool: *** Stop.\n'
979 sys
.stderr
.write(message
)
982 sp
.call(['rm', '-rf', destdir
], shell
=False)
984 elif mode
== 'extract-description':
985 modulesystem
= classes
.GLModuleSystem(config
)
987 module
= modulesystem
.find(name
)
989 sys
.stdout
.write(module
.getDescription())
991 elif mode
== 'extract-comment':
992 modulesystem
= classes
.GLModuleSystem(config
)
994 module
= modulesystem
.find(name
)
996 sys
.stdout
.write(module
.getComment())
998 elif mode
== 'extract-status':
999 modulesystem
= classes
.GLModuleSystem(config
)
1000 for name
in modules
:
1001 module
= modulesystem
.find(name
)
1003 sys
.stdout
.write(module
.getStatus())
1005 elif mode
== 'extract-notice':
1006 modulesystem
= classes
.GLModuleSystem(config
)
1007 for name
in modules
:
1008 module
= modulesystem
.find(name
)
1010 sys
.stdout
.write(module
.getNotice())
1012 elif mode
== 'extract-applicability':
1013 modulesystem
= classes
.GLModuleSystem(config
)
1014 for name
in modules
:
1015 module
= modulesystem
.find(name
)
1017 print(module
.getApplicability())
1019 elif mode
== 'extract-filelist':
1020 modulesystem
= classes
.GLModuleSystem(config
)
1021 for name
in modules
:
1022 module
= modulesystem
.find(name
)
1024 files
= module
.getFiles()
1025 print('\n'.join(files
))
1027 elif mode
== 'extract-dependencies':
1029 message
= '%s: *** ' % constants
.APP
['name']
1030 message
+= 'cannot combine --avoid and --extract-dependencies\n'
1031 message
+= '%s: *** Stop.\n' % constants
.APP
['name']
1032 sys
.stderr
.write(message
)
1034 modulesystem
= classes
.GLModuleSystem(config
)
1035 for name
in modules
:
1036 module
= modulesystem
.find(name
)
1038 sys
.stdout
.write(module
.getDependencies())
1040 elif mode
== 'extract-autoconf-snippet':
1041 modulesystem
= classes
.GLModuleSystem(config
)
1042 for name
in modules
:
1043 module
= modulesystem
.find(name
)
1045 sys
.stdout
.write(module
.getAutoconfSnippet())
1047 elif mode
== 'extract-automake-snippet':
1048 modulesystem
= classes
.GLModuleSystem(config
)
1049 for name
in modules
:
1050 module
= modulesystem
.find(name
)
1052 sys
.stdout
.write(module
.getAutomakeSnippet())
1054 elif mode
== 'extract-include-directive':
1055 modulesystem
= classes
.GLModuleSystem(config
)
1056 for name
in modules
:
1057 module
= modulesystem
.find(name
)
1059 sys
.stdout
.write(module
.getInclude())
1061 elif mode
== 'extract-link-directive':
1062 modulesystem
= classes
.GLModuleSystem(config
)
1063 for name
in modules
:
1064 module
= modulesystem
.find(name
)
1066 sys
.stdout
.write(module
.getLink())
1068 elif mode
== 'extract-license':
1069 modulesystem
= classes
.GLModuleSystem(config
)
1070 for name
in modules
:
1071 module
= modulesystem
.find(name
)
1073 print(module
.getLicense())
1075 elif mode
== 'extract-maintainer':
1076 modulesystem
= classes
.GLModuleSystem(config
)
1077 for name
in modules
:
1078 module
= modulesystem
.find(name
)
1080 sys
.stdout
.write(module
.getMaintainer())
1082 elif mode
== 'extract-tests-module':
1083 modulesystem
= classes
.GLModuleSystem(config
)
1084 for name
in modules
:
1085 module
= modulesystem
.find(name
)
1087 if module
.getTestsModule():
1088 print(module
.getTestsName())
1090 elif mode
== 'copy-file':
1092 # The second argument is the destination; either a directory ot a file.
1093 # It defaults to the current directory.
1096 else: # if len(files) < 2
1099 auxdir
= 'build-aux'
1108 config
.setAuxDir(auxdir
)
1109 config
.setSourceBase(sourcebase
)
1110 config
.setM4Base(m4base
)
1111 config
.setDocBase(docbase
)
1112 config
.setTestsBase(testsbase
)
1113 filesystem
= classes
.GLFileSystem(config
)
1114 lookedup
, flag
= filesystem
.lookup(srcpath
)
1117 if srcpath
.startswith('build-aux/'):
1118 destpath
= constants
.substart('build-aux/', '%s/' % auxdir
, srcpath
)
1119 elif srcpath
.startswith('doc/'):
1120 destpath
= constants
.substart('doc/', '%s/' % docbase
, srcpath
)
1121 elif srcpath
.startswith('lib/'):
1122 destpath
= constants
.substart('lib/', '%s/' % sourcebase
, srcpath
)
1123 elif srcpath
.startswith('m4/'):
1124 destpath
= constants
.substart('m4/', '%s/' % m4base
, srcpath
)
1125 elif srcpath
.startswith('tests/'):
1126 destpath
= constants
.substart('tests/', '%s/' % testsbase
, srcpath
)
1127 elif srcpath
.startswith('top/'):
1128 destpath
= constants
.substart('top/', '', srcpath
)
1131 else: # if not isdir(dest)
1132 destdir
= os
.path
.dirname(dest
)
1133 destpath
= os
.path
.basename(dest
)
1134 # Create the directory for destfile.
1135 dirname
= os
.path
.dirname(joinpath(destdir
, destpath
))
1136 if not config
['dryrun']:
1137 if dirname
and not isdir(dirname
):
1138 try: # Try to create directories
1139 os
.makedirs(dirname
)
1140 except FileExistsError
:
1143 assistant
= classes
.GLFileAssistant(config
)
1144 tmpfile
= assistant
.tmpfilename(destpath
)
1145 copyfile(lookedup
, tmpfile
)
1146 assistant
.setOriginal(srcpath
)
1147 assistant
.config
.setDestDir(destdir
)
1148 assistant
.setRewritten(destpath
)
1149 if isfile(joinpath(destdir
, destpath
)):
1150 # The file already exists.
1151 assistant
.update(lookedup
, flag
, tmpfile
, True)
1152 else: # if not isfile(joinpath(destdir, destpath))
1154 # Don't protest if the file should be there but isn't: it happens
1155 # frequently that developers don't put autogenerated files under
1157 assistant
.add(lookedup
, flag
, tmpfile
)
1162 message
= '%s: *** ' % constants
.APP
['name']
1163 message
+= 'no mode specified\n'
1164 message
+= '%s: *** Stop.\n' % constants
.APP
['name']
1165 sys
.stderr
.write(message
)
1169 if __name__
== '__main__':
1170 try: # Try to execute
1172 except classes
.GLError
as error
:
1173 errmode
= 0 # gnulib-style errors
1175 errinfo
= error
.errinfo
1177 message
= '%s: *** ' % constants
.APP
['name']
1181 message
+= 'file %s not found' % errinfo
1183 message
+= 'patch file %s didn\'t apply cleanly' % errinfo
1185 message
+= 'cannot find %s - make sure you run gnulib-tool from within your package\'s directory' % errinfo
1187 message
+= 'minimum supported autoconf version is 2.59. Try adding'
1188 message
+= 'AC_PREREQ([%s])' % constants
.DEFAULT_AUTOCONF_MINVERSION
1189 message
+= ' to your configure.ac.'
1191 message
+= '%s is expected to contain gl_M4_BASE([%s])' % (repr(os
.path
.join(errinfo
, 'gnulib-comp.m4')), repr(errinfo
))
1193 message
+= 'missing --source-base option'
1195 message
+= 'missing --doc-base option. --doc-base has been introduced '
1196 message
+= 'on 2006-07-11; if your last invocation of \'gnulib-tool '
1197 message
+= '--import\' is before that date, you need to run'
1198 message
+= '\'gnulib-tool --import\' once, with a --doc-base option.'
1200 message
+= 'missing --tests-base option'
1202 message
+= 'missing --lib option'
1204 message
= 'gnulib-tool: option --conditional-dependencies is not supported with --with-tests'
1206 incompatibilities
= ''
1207 message
+= 'incompatible license on modules:%s' % constants
.NL
1208 for pair
in errinfo
:
1209 incompatibilities
+= pair
[0]
1210 incompatibilities
+= ' %s' % pair
[1]
1211 incompatibilities
+= constants
.NL
1213 with codecs
.open(tempname
, 'wb', 'UTF-8') as file:
1214 file.write(incompatibilities
)
1215 sed_table
= 's,^\\([^ ]*\\) ,\\1' + ' ' * 51 + ',\n'
1216 sed_table
+= 's,^\\(' + '.' * 49 + '[^ ]*\\) *,' + ' ' * 17 + '\\1 ,'
1217 args
= ['sed', '-e', sed_table
, tempname
]
1218 incompatibilities
= sp
.check_output(args
).decode(ENCS
['default'])
1219 message
+= incompatibilities
1222 message
+= 'refusing to do nothing'
1224 message
+= 'could not create directory %s' % errinfo
1226 message
+= 'could not delete file %s' % errinfo
1228 message
+= 'could not create file %s' % errinfo
1230 message
+= 'could not transform file %s' % errinfo
1232 message
+= 'could not update file %s' % errinfo
1234 message
+= 'module %s lacks a license' % errinfo
1236 message
+= 'could not create destination directory: %s' % errinfo
1237 message
+= '\n%s: *** Stop.\n' % constants
.APP
['name']
1238 sys
.stderr
.write(message
)