2 # Copyright 2014 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
7 version.py -- Chromium version string substitution utility.
15 def fetch_values_from_file(values_dict
, file_name
):
17 Fetches KEYWORD=VALUE settings from the specified file.
19 Everything to the left of the first '=' is the keyword,
20 everything to the right is the value. No stripping of
21 white space, so beware.
23 The file must exist, otherwise you get the Python exception from open().
25 for line
in open(file_name
, 'r').readlines():
26 key
, val
= line
.rstrip('\r\n').split('=', 1)
27 values_dict
[key
] = val
30 def fetch_values(file_list
):
32 Returns a dictionary of values to be used for substitution, populating
33 the dictionary with KEYWORD=VALUE settings from the files in 'file_list'.
35 Explicitly adds the following value from internal calculations:
39 CHROME_BUILD_TYPE
= os
.environ
.get('CHROME_BUILD_TYPE')
40 if CHROME_BUILD_TYPE
== '_official':
46 OFFICIAL_BUILD
= official_build
,
49 for file_name
in file_list
:
50 fetch_values_from_file(values
, file_name
)
55 def subst_template(contents
, values
):
57 Returns the template with substituted values from the specified dictionary.
59 Keywords to be substituted are surrounded by '@': @KEYWORD@.
61 No attempt is made to avoid recursive substitution. The order
62 of evaluation is random based on the order of the keywords returned
63 by the Python dictionary. So do NOT substitute a value that
64 contains any @KEYWORD@ strings expecting them to be recursively
67 for key
, val
in values
.iteritems():
69 contents
= contents
.replace('@' + key
+ '@', val
)
71 print repr(key
), repr(val
)
75 def subst_file(file_name
, values
):
77 Returns the contents of the specified file_name with substituted
78 values from the specified dictionary.
80 This is like subst_template, except it operates on a file.
82 template
= open(file_name
, 'r').read()
83 return subst_template(template
, values
);
86 def write_if_changed(file_name
, contents
):
88 Writes the specified contents to the specified file_name
89 iff the contents are different than the current contents.
92 old_contents
= open(file_name
, 'r').read()
93 except EnvironmentError:
96 if contents
== old_contents
:
99 open(file_name
, 'w').write(contents
)
103 parser
= argparse
.ArgumentParser()
104 parser
.add_argument('-f', '--file', action
='append', default
=[],
105 help='Read variables from FILE.')
106 parser
.add_argument('-i', '--input', default
=None,
107 help='Read strings to substitute from FILE.')
108 parser
.add_argument('-o', '--output', default
=None,
109 help='Write substituted strings to FILE.')
110 parser
.add_argument('-t', '--template', default
=None,
111 help='Use TEMPLATE as the strings to substitute.')
112 parser
.add_argument('-e', '--eval', action
='append', default
=[],
113 help='Evaluate VAL after reading variables. Can be used '
114 'to synthesize variables. e.g. -e \'PATCH_HI=int('
116 parser
.add_argument('args', nargs
=argparse
.REMAINDER
,
117 help='For compatibility: INPUT and OUTPUT can be '
118 'passed as positional arguments.')
119 options
= parser
.parse_args()
122 for expression
in options
.eval:
124 evals
.update(dict([expression
.split('=', 1)]))
126 parser
.error('-e requires VAR=VAL')
128 # Compatibility with old versions that considered the first two positional
129 # arguments shorthands for --input and --output.
130 while len(options
.args
) and (options
.input is None or \
131 options
.output
is None):
132 if options
.input is None:
133 options
.input = options
.args
.pop(0)
134 elif options
.output
is None:
135 options
.output
= options
.args
.pop(0)
137 parser
.error('Unexpected arguments: %r' % options
.args
)
139 values
= fetch_values(options
.file)
140 for key
, val
in evals
.iteritems():
141 values
[key
] = str(eval(val
, globals(), values
))
143 if options
.template
is not None:
144 contents
= subst_template(options
.template
, values
)
146 contents
= subst_file(options
.input, values
)
148 # Generate a default set of version information.
149 contents
= """MAJOR=%(MAJOR)s
153 LASTCHANGE=%(LASTCHANGE)s
154 OFFICIAL_BUILD=%(OFFICIAL_BUILD)s
157 if options
.output
is not None:
158 write_if_changed(options
.output
, contents
)
165 if __name__
== '__main__':