]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Scripts/UpdateBuildVersions.py
BaseTools/BinToPcd: Follow PEP-8 indent of 4 spaces
[mirror_edk2.git] / BaseTools / Scripts / UpdateBuildVersions.py
1 ## @file
2 # Update build revisions of the tools when performing a developer build
3 #
4 # This script will modife the C/Include/Common/BuildVersion.h file and the two
5 # Python scripts, Python/Common/BuildVersion.py and Python/UPT/BuildVersion.py.
6 # If SVN is available, the tool will obtain the current checked out version of
7 # the source tree for including the the --version commands.
8
9 # Copyright (c) 2014 - 2015, Intel Corporation. All rights reserved.<BR>
10 #
11 # This program and the accompanying materials
12 # are licensed and made available under the terms and conditions of the BSD License
13 # which accompanies this distribution. The full text of the license may be found at
14 # http://opensource.org/licenses/bsd-license.php
15 #
16 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
17 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 ##
19 """ This program will update the BuildVersion.py and BuildVersion.h files used to set a tool's version value """
20 from __future__ import absolute_import
21
22 import os
23 import shlex
24 import subprocess
25 import sys
26
27 from argparse import ArgumentParser, SUPPRESS
28 from tempfile import NamedTemporaryFile
29 from types import IntType, ListType
30
31
32 SYS_ENV_ERR = "ERROR : %s system environment variable must be set prior to running this tool.\n"
33
34 __execname__ = "UpdateBuildVersions.py"
35 SVN_REVISION = "$LastChangedRevision: 3 $"
36 SVN_REVISION = SVN_REVISION.replace("$LastChangedRevision:", "").replace("$", "").strip()
37 __copyright__ = "Copyright (c) 2014, Intel Corporation. All rights reserved."
38 VERSION_NUMBER = "0.7.0"
39 __version__ = "Version %s.%s" % (VERSION_NUMBER, SVN_REVISION)
40
41
42 def ParseOptions():
43 """
44 Parse the command-line options.
45 The options for this tool will be passed along to the MkBinPkg tool.
46 """
47 parser = ArgumentParser(
48 usage=("%s [options]" % __execname__),
49 description=__copyright__,
50 conflict_handler='resolve')
51
52 # Standard Tool Options
53 parser.add_argument("--version", action="version",
54 version=__execname__ + " " + __version__)
55 parser.add_argument("-s", "--silent", action="store_true",
56 dest="silent",
57 help="All output will be disabled, pass/fail determined by the exit code")
58 parser.add_argument("-v", "--verbose", action="store_true",
59 dest="verbose",
60 help="Enable verbose output")
61 # Tool specific options
62 parser.add_argument("--revert", action="store_true",
63 dest="REVERT", default=False,
64 help="Revert the BuildVersion files only")
65 parser.add_argument("--svn-test", action="store_true",
66 dest="TEST_SVN", default=False,
67 help="Test if the svn command is available")
68 parser.add_argument("--svnFlag", action="store_true",
69 dest="HAVE_SVN", default=False,
70 help=SUPPRESS)
71
72 return(parser.parse_args())
73
74
75 def ShellCommandResults(CmdLine, Opt):
76 """ Execute the comand, returning the output content """
77 file_list = NamedTemporaryFile(delete=False)
78 filename = file_list.name
79 Results = []
80
81 returnValue = 0
82 try:
83 subprocess.check_call(args=shlex.split(CmdLine), stderr=subprocess.STDOUT, stdout=file_list)
84 except subprocess.CalledProcessError as err_val:
85 file_list.close()
86 if not Opt.silent:
87 sys.stderr.write("ERROR : %d : %s\n" % (err_val.returncode, err_val.__str__()))
88 if os.path.exists(filename):
89 sys.stderr.write(" : Partial results may be in this file: %s\n" % filename)
90 sys.stderr.flush()
91 returnValue = err_val.returncode
92
93 except IOError as (errno, strerror):
94 file_list.close()
95 if not Opt.silent:
96 sys.stderr.write("I/O ERROR : %s : %s\n" % (str(errno), strerror))
97 sys.stderr.write("ERROR : this command failed : %s\n" % CmdLine)
98 if os.path.exists(filename):
99 sys.stderr.write(" : Partial results may be in this file: %s\n" % filename)
100 sys.stderr.flush()
101 returnValue = errno
102
103 except OSError as (errno, strerror):
104 file_list.close()
105 if not Opt.silent:
106 sys.stderr.write("OS ERROR : %s : %s\n" % (str(errno), strerror))
107 sys.stderr.write("ERROR : this command failed : %s\n" % CmdLine)
108 if os.path.exists(filename):
109 sys.stderr.write(" : Partial results may be in this file: %s\n" % filename)
110 sys.stderr.flush()
111 returnValue = errno
112
113 except KeyboardInterrupt:
114 file_list.close()
115 if not Opt.silent:
116 sys.stderr.write("ERROR : Command terminated by user : %s\n" % CmdLine)
117 if os.path.exists(filename):
118 sys.stderr.write(" : Partial results may be in this file: %s\n" % filename)
119 sys.stderr.flush()
120 returnValue = 1
121
122 finally:
123 if not file_list.closed:
124 file_list.flush()
125 os.fsync(file_list.fileno())
126 file_list.close()
127
128 if os.path.exists(filename):
129 fd_ = open(filename, 'r')
130 Results = fd_.readlines()
131 fd_.close()
132 os.unlink(filename)
133
134 if returnValue > 0:
135 return returnValue
136
137 return Results
138
139
140 def UpdateBuildVersionPython(Rev, UserModified, opts):
141 """ This routine will update the BuildVersion.h files in the C source tree """
142 for SubDir in ["Common", "UPT"]:
143 PyPath = os.path.join(os.environ['BASE_TOOLS_PATH'], "Source", "Python", SubDir)
144 BuildVersionPy = os.path.join(PyPath, "BuildVersion.py")
145 fd_ = open(os.path.normpath(BuildVersionPy), 'r')
146 contents = fd_.readlines()
147 fd_.close()
148 if opts.HAVE_SVN is False:
149 BuildVersionOrig = os.path.join(PyPath, "orig_BuildVersion.py")
150 fd_ = open (BuildVersionOrig, 'w')
151 for line in contents:
152 fd_.write(line)
153 fd_.flush()
154 fd_.close()
155 new_content = []
156 for line in contents:
157 if line.strip().startswith("gBUILD_VERSION"):
158 new_line = "gBUILD_VERSION = \"Developer Build based on Revision: %s\"" % Rev
159 if UserModified:
160 new_line = "gBUILD_VERSION = \"Developer Build based on Revision: %s with Modified Sources\"" % Rev
161 new_content.append(new_line)
162 continue
163 new_content.append(line)
164
165 fd_ = open(os.path.normpath(BuildVersionPy), 'w')
166 for line in new_content:
167 fd_.write(line)
168 fd_.close()
169
170
171 def UpdateBuildVersionH(Rev, UserModified, opts):
172 """ This routine will update the BuildVersion.h files in the C source tree """
173 CPath = os.path.join(os.environ['BASE_TOOLS_PATH'], "Source", "C", "Include", "Common")
174 BuildVersionH = os.path.join(CPath, "BuildVersion.h")
175 fd_ = open(os.path.normpath(BuildVersionH), 'r')
176 contents = fd_.readlines()
177 fd_.close()
178 if opts.HAVE_SVN is False:
179 BuildVersionOrig = os.path.join(CPath, "orig_BuildVersion.h")
180 fd_ = open(BuildVersionOrig, 'w')
181 for line in contents:
182 fd_.write(line)
183 fd_.flush()
184 fd_.close()
185
186 new_content = []
187 for line in contents:
188 if line.strip().startswith("#define"):
189 new_line = "#define __BUILD_VERSION \"Developer Build based on Revision: %s\"" % Rev
190 if UserModified:
191 new_line = "#define __BUILD_VERSION \"Developer Build based on Revision: %s with Modified Sources\"" % \
192 Rev
193 new_content.append(new_line)
194 continue
195 new_content.append(line)
196
197 fd_ = open(os.path.normpath(BuildVersionH), 'w')
198 for line in new_content:
199 fd_.write(line)
200 fd_.close()
201
202
203 def RevertCmd(Filename, Opt):
204 """ This is the shell command that does the SVN revert """
205 CmdLine = "svn revert %s" % Filename.replace("\\", "/").strip()
206 try:
207 subprocess.check_output(args=shlex.split(CmdLine))
208 except subprocess.CalledProcessError as err_val:
209 if not Opt.silent:
210 sys.stderr.write("Subprocess ERROR : %s\n" % err_val)
211 sys.stderr.flush()
212
213 except IOError as (errno, strerror):
214 if not Opt.silent:
215 sys.stderr.write("I/O ERROR : %d : %s\n" % (str(errno), strerror))
216 sys.stderr.write("ERROR : this command failed : %s\n" % CmdLine)
217 sys.stderr.flush()
218
219 except OSError as (errno, strerror):
220 if not Opt.silent:
221 sys.stderr.write("OS ERROR : %d : %s\n" % (str(errno), strerror))
222 sys.stderr.write("ERROR : this command failed : %s\n" % CmdLine)
223 sys.stderr.flush()
224
225 except KeyboardInterrupt:
226 if not Opt.silent:
227 sys.stderr.write("ERROR : Command terminated by user : %s\n" % CmdLine)
228 sys.stderr.flush()
229
230 if Opt.verbose:
231 sys.stdout.write("Reverted this file: %s\n" % Filename)
232 sys.stdout.flush()
233
234
235 def GetSvnRevision(opts):
236 """ Get the current revision of the BaseTools/Source tree, and check if any of the files have been modified """
237 Revision = "Unknown"
238 Modified = False
239
240 if opts.HAVE_SVN is False:
241 sys.stderr.write("WARNING: the svn command-line tool is not available.\n")
242 return (Revision, Modified)
243
244 SrcPath = os.path.join(os.environ['BASE_TOOLS_PATH'], "Source")
245 # Check if there are modified files.
246 Cwd = os.getcwd()
247 os.chdir(SrcPath)
248
249 StatusCmd = "svn st -v --depth infinity --non-interactive"
250 contents = ShellCommandResults(StatusCmd, opts)
251 os.chdir(Cwd)
252 if type(contents) is ListType:
253 for line in contents:
254 if line.startswith("M "):
255 Modified = True
256 break
257
258 # Get the repository revision of BaseTools/Source
259 InfoCmd = "svn info %s" % SrcPath.replace("\\", "/").strip()
260 Revision = 0
261 contents = ShellCommandResults(InfoCmd, opts)
262 if type(contents) is IntType:
263 return 0, Modified
264 for line in contents:
265 line = line.strip()
266 if line.startswith("Revision:"):
267 Revision = line.replace("Revision:", "").strip()
268 break
269
270 return (Revision, Modified)
271
272
273 def CheckSvn(opts):
274 """
275 This routine will return True if an svn --version command succeeds, or False if it fails.
276 If it failed, SVN is not available.
277 """
278 OriginalSilent = opts.silent
279 opts.silent = True
280 VerCmd = "svn --version"
281 contents = ShellCommandResults(VerCmd, opts)
282 opts.silent = OriginalSilent
283 if type(contents) is IntType:
284 if opts.verbose:
285 sys.stdout.write("SVN does not appear to be available.\n")
286 sys.stdout.flush()
287 return False
288
289 if opts.verbose:
290 sys.stdout.write("Found %s" % contents[0])
291 sys.stdout.flush()
292 return True
293
294
295 def CopyOrig(Src, Dest, Opt):
296 """ Overwrite the Dest File with the Src File content """
297 try:
298 fd_ = open(Src, 'r')
299 contents = fd_.readlines()
300 fd_.close()
301 fd_ = open(Dest, 'w')
302 for line in contents:
303 fd_.write(line)
304 fd_.flush()
305 fd_.close()
306 except IOError:
307 if not Opt.silent:
308 sys.stderr.write("Unable to restore this file: %s\n" % Dest)
309 sys.stderr.flush()
310 return 1
311
312 os.remove(Src)
313 if Opt.verbose:
314 sys.stdout.write("Restored this file: %s\n" % Src)
315 sys.stdout.flush()
316
317 return 0
318
319
320 def CheckOriginals(Opts):
321 """
322 If SVN was not available, then the tools may have made copies of the original BuildVersion.* files using
323 orig_BuildVersion.* for the name. If they exist, replace the existing BuildVersion.* file with the corresponding
324 orig_BuildVersion.* file.
325 Returns 0 if this succeeds, or 1 if the copy function fails. It will also return 0 if the orig_BuildVersion.* file
326 does not exist.
327 """
328 CPath = os.path.join(os.environ['BASE_TOOLS_PATH'], "Source", "C", "Include", "Common")
329 BuildVersionH = os.path.join(CPath, "BuildVersion.h")
330 OrigBuildVersionH = os.path.join(CPath, "orig_BuildVersion.h")
331 if not os.path.exists(OrigBuildVersionH):
332 return 0
333 if CopyOrig(OrigBuildVersionH, BuildVersionH, Opts):
334 return 1
335 for SubDir in ["Common", "UPT"]:
336 PyPath = os.path.join(os.environ['BASE_TOOLS_PATH'], "Source", "Python", SubDir)
337 BuildVersionPy = os.path.join(PyPath, "BuildVersion.h")
338 OrigBuildVersionPy = os.path.join(PyPath, "orig_BuildVersion.h")
339 if not os.path.exists(OrigBuildVersionPy):
340 return 0
341 if CopyOrig(OrigBuildVersionPy, BuildVersionPy, Opts):
342 return 1
343
344 return 0
345
346
347 def RevertBuildVersionFiles(opts):
348 """
349 This routine will attempt to perform an SVN --revert on each of the BuildVersion.* files
350 """
351 if not opts.HAVE_SVN:
352 if CheckOriginals(opts):
353 return 1
354 return 0
355 # SVN is available
356 BuildVersionH = os.path.join(os.environ['BASE_TOOLS_PATH'], "Source", "C", "Include", "Common", "BuildVersion.h")
357 RevertCmd(BuildVersionH, opts)
358 for SubDir in ["Common", "UPT"]:
359 BuildVersionPy = os.path.join(os.environ['BASE_TOOLS_PATH'], "Source", "Python", SubDir, "BuildVersion.py")
360 RevertCmd(BuildVersionPy, opts)
361
362 def UpdateRevisionFiles():
363 """ Main routine that will update the BuildVersion.py and BuildVersion.h files."""
364 options = ParseOptions()
365 # Check the working environment
366 if "WORKSPACE" not in os.environ.keys():
367 sys.stderr.write(SYS_ENV_ERR % 'WORKSPACE')
368 return 1
369 if 'BASE_TOOLS_PATH' not in os.environ.keys():
370 sys.stderr.write(SYS_ENV_ERR % 'BASE_TOOLS_PATH')
371 return 1
372 if not os.path.exists(os.environ['BASE_TOOLS_PATH']):
373 sys.stderr.write("Unable to locate the %s directory." % os.environ['BASE_TOOLS_PATH'])
374 return 1
375
376
377 options.HAVE_SVN = CheckSvn(options)
378 if options.TEST_SVN:
379 return (not options.HAVE_SVN)
380 # done processing the option, now use the option.HAVE_SVN as a flag. True = Have it, False = Don't have it.
381 if options.REVERT:
382 # Just revert the tools an exit
383 RevertBuildVersionFiles(options)
384 else:
385 # Revert any changes in the BuildVersion.* files before setting them again.
386 RevertBuildVersionFiles(options)
387 Revision, Modified = GetSvnRevision(options)
388 if options.verbose:
389 sys.stdout.write("Revision: %s is Modified: %s\n" % (Revision, Modified))
390 sys.stdout.flush()
391 UpdateBuildVersionH(Revision, Modified, options)
392 UpdateBuildVersionPython(Revision, Modified, options)
393
394 return 0
395
396
397 if __name__ == "__main__":
398 sys.exit(UpdateRevisionFiles())
399
400