1 # Copyright Deniz Bahadir 2015
3 # Distributed under the Boost Software License, Version 1.0.
4 # (See accompanying file LICENSE_1_0.txt or copy at
5 # http://www.boost.org/LICENSE_1_0.txt)
7 # See http://www.boost.org/libs/mpl for documentation.
8 # See http://stackoverflow.com/a/29627158/3115457 for further information.
19 def check_header_comment(filename
):
20 """Checks if the header-comment of the given file needs fixing."""
22 name
= os
.path
.basename( filename
)
23 # Read content of input file.
24 sourcefile
= open( filename
, "rU" )
25 content
= sourcefile
.read()
27 # Search content for '$Id$'.
28 match
= re
.search(r
'\$Id\$', content
)
30 # Make sure that the correct value for '$Id$' was already set.
31 match
= re
.search(r
'\$Id: ' + name
+ r
'\s+[^$]+\$', content
)
33 # The given file needs no fixing.
35 # The given file needs fixing.
39 def check_input_files_for_variadic_seq(headerDir
, sourceDir
):
40 """Checks if files, used as input when pre-processing MPL-containers in their variadic form, need fixing."""
41 # Check input files in include/source-directories.
42 files
= glob
.glob( os
.path
.join( headerDir
, "*.hpp" ) )
43 files
+= glob
.glob( os
.path
.join( headerDir
, "aux_", "*.hpp" ) )
44 files
+= glob
.glob( os
.path
.join( sourceDir
, "src", "*" ) )
45 for currentFile
in sorted( files
):
46 if check_header_comment( currentFile
):
51 def check_input_files_for_numbered_seq(sourceDir
, suffix
, containers
):
52 """Check if files, used as input when pre-processing MPL-containers in their numbered form, need fixing."""
53 # Check input files for each MPL-container type.
54 for container
in containers
:
55 files
= glob
.glob( os
.path
.join( sourceDir
, container
, container
+ '*' + suffix
) )
56 for currentFile
in sorted( files
):
57 if check_header_comment( currentFile
):
62 def check_input_files(headerDir
, sourceDir
, containers
=['vector', 'list', 'set', 'map'],
63 seqType
='both', verbose
=False):
64 """Checks if source- and header-files, used as input when pre-processing MPL-containers, need fixing."""
65 # Check the input files for containers in their variadic form.
67 if seqType
== "both" or seqType
== "variadic":
69 print "Check if input files for pre-processing Boost.MPL variadic containers need fixing."
70 result1
= check_input_files_for_variadic_seq(headerDir
, sourceDir
)
73 print " At least one input file needs fixing!"
75 print " No input file needs fixing!"
76 # Check the input files for containers in their numbered form.
79 if seqType
== "both" or seqType
== "numbered":
81 print "Check input files for pre-processing Boost.MPL numbered containers."
82 result2
= check_input_files_for_numbered_seq(headerDir
, ".hpp", containers
)
83 result3
= check_input_files_for_numbered_seq(sourceDir
, ".cpp", containers
)
85 if result2
or result3
:
86 print " At least one input file needs fixing!"
88 print " No input file needs fixing!"
90 return result1
or result2
or result3
92 def fix_header_comment(filename
, timestamp
):
93 """Fixes the header-comment of the given file."""
95 name
= os
.path
.basename( filename
)
96 for line
in fileinput
.input( filename
, inplace
=1, mode
="rU" ):
97 # If header-comment already contains anything for '$Id$', remove it.
98 line
= re
.sub(r
'\$Id:[^$]+\$', r
'$Id$', line
.rstrip())
99 # Replace '$Id$' by a string containing the file's name (and a timestamp)!
100 line
= re
.sub(re
.escape(r
'$Id$'), r
'$Id: ' + name
+ r
' ' + timestamp
.isoformat() + r
' $', line
.rstrip())
104 def fix_input_files_for_variadic_seq(headerDir
, sourceDir
, timestamp
):
105 """Fixes files used as input when pre-processing MPL-containers in their variadic form."""
106 # Fix files in include/source-directories.
107 files
= glob
.glob( os
.path
.join( headerDir
, "*.hpp" ) )
108 files
+= glob
.glob( os
.path
.join( headerDir
, "aux_", "*.hpp" ) )
109 files
+= glob
.glob( os
.path
.join( sourceDir
, "src", "*" ) )
110 for currentFile
in sorted( files
):
111 fix_header_comment( currentFile
, timestamp
)
114 def fix_input_files_for_numbered_seq(sourceDir
, suffix
, timestamp
, containers
):
115 """Fixes files used as input when pre-processing MPL-containers in their numbered form."""
116 # Fix input files for each MPL-container type.
117 for container
in containers
:
118 files
= glob
.glob( os
.path
.join( sourceDir
, container
, container
+ '*' + suffix
) )
119 for currentFile
in sorted( files
):
120 fix_header_comment( currentFile
, timestamp
)
123 def fix_input_files(headerDir
, sourceDir
, containers
=['vector', 'list', 'set', 'map'],
124 seqType
='both', verbose
=False):
125 """Fixes source- and header-files used as input when pre-processing MPL-containers."""
126 # The new modification time.
127 timestamp
= datetime
.datetime
.now();
128 # Fix the input files for containers in their variadic form.
129 if seqType
== "both" or seqType
== "variadic":
131 print "Fix input files for pre-processing Boost.MPL variadic containers."
132 fix_input_files_for_variadic_seq(headerDir
, sourceDir
, timestamp
)
133 # Fix the input files for containers in their numbered form.
134 if seqType
== "both" or seqType
== "numbered":
136 print "Fix input files for pre-processing Boost.MPL numbered containers."
137 fix_input_files_for_numbered_seq(headerDir
, ".hpp", timestamp
, containers
)
138 fix_input_files_for_numbered_seq(sourceDir
, ".cpp", timestamp
, containers
)
141 def to_existing_absolute_path(string
):
142 """Converts a path into its absolute path and verifies that it exists or throws an exception."""
143 value
= os
.path
.abspath(string
)
144 if not os
.path
.exists( value
) or not os
.path
.isdir( value
):
145 msg
= '"%r" is not a valid path to a directory.' % string
146 raise argparse
.ArgumentTypeError(msg
)
151 """The main function."""
153 # Prepare and run cmdline-parser.
154 cmdlineParser
= argparse
.ArgumentParser(
155 description
="Fixes the input files used for pre-processing of Boost.MPL headers.")
156 cmdlineParser
.add_argument("-v", "--verbose", dest
='verbose', action
='store_true',
157 help="Be a little bit more verbose.")
158 cmdlineParser
.add_argument("--check-only", dest
='checkonly', action
='store_true',
159 help="Only checks if fixing is required.")
160 cmdlineParser
.add_argument(dest
='sourceDir', metavar
="<source-dir>",
161 type=to_existing_absolute_path
,
162 help="The source-directory of Boost.")
163 args
= cmdlineParser
.parse_args()
165 # Some verbose debug output.
167 print "Arguments extracted from command-line:"
168 print " verbose = ", args
.verbose
169 print " check-only = ", args
.checkonly
170 print " source directory = ", args
.sourceDir
172 # The directories for header- and source files of Boost.MPL.
173 # NOTE: Assuming 'args.sourceDir' is the source-directory of the entire boost project.
174 headerDir
= os
.path
.join( args
.sourceDir
, "boost", "mpl" )
175 sourceDir
= os
.path
.join( args
.sourceDir
, "libs", "mpl", "preprocessed" )
176 # Check that the header/source-directories exist.
177 if not os
.path
.exists( headerDir
) or not os
.path
.exists( sourceDir
):
178 # Maybe 'args.sourceDir' is not the source-directory of the entire boost project
179 # but instead of the Boost.MPL git-directory, only?
180 headerDir
= os
.path
.join( args
.sourceDir
, "include", "boost", "mpl" )
181 sourceDir
= os
.path
.join( args
.sourceDir
, "preprocessed" )
182 if not os
.path
.exists( headerDir
) or not os
.path
.exists( sourceDir
):
183 cmdlineParser
.print_usage()
184 print "error: Cannot find Boost.MPL header/source files in given Boost source-directory!"
187 # Some verbose debug output.
189 print "Chosen header-directory: ", headerDir
190 print "Chosen source-directory: ", sourceDir
193 # Check input files for generating pre-processed headers.
194 result
= check_input_files(headerDir
, sourceDir
, verbose
= args
.verbose
)
196 print "Fixing the input-files used for pre-processing of Boost.MPL headers IS required."
198 print "Fixing the input-files used for pre-processing of Boost.MPL headers is NOT required."
200 # Fix input files for generating pre-processed headers.
201 fix_input_files(headerDir
, sourceDir
, verbose
= args
.verbose
)
204 if __name__
== '__main__':