]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Scripts/UpdateBuildVersions.py
BaseTools/BinToPcd: Fix Python 2.7.x compatibility issue
[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 err_val:
94 (errno, strerror) = err_val.args
95 file_list.close()
96 if not Opt.silent:
97 sys.stderr.write("I/O ERROR : %s : %s\n" % (str(errno), strerror))
98 sys.stderr.write("ERROR : this command failed : %s\n" % CmdLine)
99 if os.path.exists(filename):
100 sys.stderr.write(" : Partial results may be in this file: %s\n" % filename)
101 sys.stderr.flush()
102 returnValue = errno
103
104 except OSError as err_val:
105 (errno, strerror) = err_val.args
106 file_list.close()
107 if not Opt.silent:
108 sys.stderr.write("OS ERROR : %s : %s\n" % (str(errno), strerror))
109 sys.stderr.write("ERROR : this command failed : %s\n" % CmdLine)
110 if os.path.exists(filename):
111 sys.stderr.write(" : Partial results may be in this file: %s\n" % filename)
112 sys.stderr.flush()
113 returnValue = errno
114
115 except KeyboardInterrupt:
116 file_list.close()
117 if not Opt.silent:
118 sys.stderr.write("ERROR : Command terminated by user : %s\n" % CmdLine)
119 if os.path.exists(filename):
120 sys.stderr.write(" : Partial results may be in this file: %s\n" % filename)
121 sys.stderr.flush()
122 returnValue = 1
123
124 finally:
125 if not file_list.closed:
126 file_list.flush()
127 os.fsync(file_list.fileno())
128 file_list.close()
129
130 if os.path.exists(filename):
131 fd_ = open(filename, 'r')
132 Results = fd_.readlines()
133 fd_.close()
134 os.unlink(filename)
135
136 if returnValue > 0:
137 return returnValue
138
139 return Results
140
141
142 def UpdateBuildVersionPython(Rev, UserModified, opts):
143 """ This routine will update the BuildVersion.h files in the C source tree """
144 for SubDir in ["Common", "UPT"]:
145 PyPath = os.path.join(os.environ['BASE_TOOLS_PATH'], "Source", "Python", SubDir)
146 BuildVersionPy = os.path.join(PyPath, "BuildVersion.py")
147 fd_ = open(os.path.normpath(BuildVersionPy), 'r')
148 contents = fd_.readlines()
149 fd_.close()
150 if opts.HAVE_SVN is False:
151 BuildVersionOrig = os.path.join(PyPath, "orig_BuildVersion.py")
152 fd_ = open (BuildVersionOrig, 'w')
153 for line in contents:
154 fd_.write(line)
155 fd_.flush()
156 fd_.close()
157 new_content = []
158 for line in contents:
159 if line.strip().startswith("gBUILD_VERSION"):
160 new_line = "gBUILD_VERSION = \"Developer Build based on Revision: %s\"" % Rev
161 if UserModified:
162 new_line = "gBUILD_VERSION = \"Developer Build based on Revision: %s with Modified Sources\"" % Rev
163 new_content.append(new_line)
164 continue
165 new_content.append(line)
166
167 fd_ = open(os.path.normpath(BuildVersionPy), 'w')
168 for line in new_content:
169 fd_.write(line)
170 fd_.close()
171
172
173 def UpdateBuildVersionH(Rev, UserModified, opts):
174 """ This routine will update the BuildVersion.h files in the C source tree """
175 CPath = os.path.join(os.environ['BASE_TOOLS_PATH'], "Source", "C", "Include", "Common")
176 BuildVersionH = os.path.join(CPath, "BuildVersion.h")
177 fd_ = open(os.path.normpath(BuildVersionH), 'r')
178 contents = fd_.readlines()
179 fd_.close()
180 if opts.HAVE_SVN is False:
181 BuildVersionOrig = os.path.join(CPath, "orig_BuildVersion.h")
182 fd_ = open(BuildVersionOrig, 'w')
183 for line in contents:
184 fd_.write(line)
185 fd_.flush()
186 fd_.close()
187
188 new_content = []
189 for line in contents:
190 if line.strip().startswith("#define"):
191 new_line = "#define __BUILD_VERSION \"Developer Build based on Revision: %s\"" % Rev
192 if UserModified:
193 new_line = "#define __BUILD_VERSION \"Developer Build based on Revision: %s with Modified Sources\"" % \
194 Rev
195 new_content.append(new_line)
196 continue
197 new_content.append(line)
198
199 fd_ = open(os.path.normpath(BuildVersionH), 'w')
200 for line in new_content:
201 fd_.write(line)
202 fd_.close()
203
204
205 def RevertCmd(Filename, Opt):
206 """ This is the shell command that does the SVN revert """
207 CmdLine = "svn revert %s" % Filename.replace("\\", "/").strip()
208 try:
209 subprocess.check_output(args=shlex.split(CmdLine))
210 except subprocess.CalledProcessError as err_val:
211 if not Opt.silent:
212 sys.stderr.write("Subprocess ERROR : %s\n" % err_val)
213 sys.stderr.flush()
214
215 except IOError as err_val:
216 (errno, strerror) = err_val.args
217 if not Opt.silent:
218 sys.stderr.write("I/O ERROR : %d : %s\n" % (str(errno), strerror))
219 sys.stderr.write("ERROR : this command failed : %s\n" % CmdLine)
220 sys.stderr.flush()
221
222 except OSError as err_val:
223 (errno, strerror) = err_val.args
224 if not Opt.silent:
225 sys.stderr.write("OS ERROR : %d : %s\n" % (str(errno), strerror))
226 sys.stderr.write("ERROR : this command failed : %s\n" % CmdLine)
227 sys.stderr.flush()
228
229 except KeyboardInterrupt:
230 if not Opt.silent:
231 sys.stderr.write("ERROR : Command terminated by user : %s\n" % CmdLine)
232 sys.stderr.flush()
233
234 if Opt.verbose:
235 sys.stdout.write("Reverted this file: %s\n" % Filename)
236 sys.stdout.flush()
237
238
239 def GetSvnRevision(opts):
240 """ Get the current revision of the BaseTools/Source tree, and check if any of the files have been modified """
241 Revision = "Unknown"
242 Modified = False
243
244 if opts.HAVE_SVN is False:
245 sys.stderr.write("WARNING: the svn command-line tool is not available.\n")
246 return (Revision, Modified)
247
248 SrcPath = os.path.join(os.environ['BASE_TOOLS_PATH'], "Source")
249 # Check if there are modified files.
250 Cwd = os.getcwd()
251 os.chdir(SrcPath)
252
253 StatusCmd = "svn st -v --depth infinity --non-interactive"
254 contents = ShellCommandResults(StatusCmd, opts)
255 os.chdir(Cwd)
256 if isinstance(contents, ListType):
257 for line in contents:
258 if line.startswith("M "):
259 Modified = True
260 break
261
262 # Get the repository revision of BaseTools/Source
263 InfoCmd = "svn info %s" % SrcPath.replace("\\", "/").strip()
264 Revision = 0
265 contents = ShellCommandResults(InfoCmd, opts)
266 if isinstance(contents, IntType):
267 return 0, Modified
268 for line in contents:
269 line = line.strip()
270 if line.startswith("Revision:"):
271 Revision = line.replace("Revision:", "").strip()
272 break
273
274 return (Revision, Modified)
275
276
277 def CheckSvn(opts):
278 """
279 This routine will return True if an svn --version command succeeds, or False if it fails.
280 If it failed, SVN is not available.
281 """
282 OriginalSilent = opts.silent
283 opts.silent = True
284 VerCmd = "svn --version"
285 contents = ShellCommandResults(VerCmd, opts)
286 opts.silent = OriginalSilent
287 if isinstance(contents, IntType):
288 if opts.verbose:
289 sys.stdout.write("SVN does not appear to be available.\n")
290 sys.stdout.flush()
291 return False
292
293 if opts.verbose:
294 sys.stdout.write("Found %s" % contents[0])
295 sys.stdout.flush()
296 return True
297
298
299 def CopyOrig(Src, Dest, Opt):
300 """ Overwrite the Dest File with the Src File content """
301 try:
302 fd_ = open(Src, 'r')
303 contents = fd_.readlines()
304 fd_.close()
305 fd_ = open(Dest, 'w')
306 for line in contents:
307 fd_.write(line)
308 fd_.flush()
309 fd_.close()
310 except IOError:
311 if not Opt.silent:
312 sys.stderr.write("Unable to restore this file: %s\n" % Dest)
313 sys.stderr.flush()
314 return 1
315
316 os.remove(Src)
317 if Opt.verbose:
318 sys.stdout.write("Restored this file: %s\n" % Src)
319 sys.stdout.flush()
320
321 return 0
322
323
324 def CheckOriginals(Opts):
325 """
326 If SVN was not available, then the tools may have made copies of the original BuildVersion.* files using
327 orig_BuildVersion.* for the name. If they exist, replace the existing BuildVersion.* file with the corresponding
328 orig_BuildVersion.* file.
329 Returns 0 if this succeeds, or 1 if the copy function fails. It will also return 0 if the orig_BuildVersion.* file
330 does not exist.
331 """
332 CPath = os.path.join(os.environ['BASE_TOOLS_PATH'], "Source", "C", "Include", "Common")
333 BuildVersionH = os.path.join(CPath, "BuildVersion.h")
334 OrigBuildVersionH = os.path.join(CPath, "orig_BuildVersion.h")
335 if not os.path.exists(OrigBuildVersionH):
336 return 0
337 if CopyOrig(OrigBuildVersionH, BuildVersionH, Opts):
338 return 1
339 for SubDir in ["Common", "UPT"]:
340 PyPath = os.path.join(os.environ['BASE_TOOLS_PATH'], "Source", "Python", SubDir)
341 BuildVersionPy = os.path.join(PyPath, "BuildVersion.h")
342 OrigBuildVersionPy = os.path.join(PyPath, "orig_BuildVersion.h")
343 if not os.path.exists(OrigBuildVersionPy):
344 return 0
345 if CopyOrig(OrigBuildVersionPy, BuildVersionPy, Opts):
346 return 1
347
348 return 0
349
350
351 def RevertBuildVersionFiles(opts):
352 """
353 This routine will attempt to perform an SVN --revert on each of the BuildVersion.* files
354 """
355 if not opts.HAVE_SVN:
356 if CheckOriginals(opts):
357 return 1
358 return 0
359 # SVN is available
360 BuildVersionH = os.path.join(os.environ['BASE_TOOLS_PATH'], "Source", "C", "Include", "Common", "BuildVersion.h")
361 RevertCmd(BuildVersionH, opts)
362 for SubDir in ["Common", "UPT"]:
363 BuildVersionPy = os.path.join(os.environ['BASE_TOOLS_PATH'], "Source", "Python", SubDir, "BuildVersion.py")
364 RevertCmd(BuildVersionPy, opts)
365
366 def UpdateRevisionFiles():
367 """ Main routine that will update the BuildVersion.py and BuildVersion.h files."""
368 options = ParseOptions()
369 # Check the working environment
370 if "WORKSPACE" not in os.environ.keys():
371 sys.stderr.write(SYS_ENV_ERR % 'WORKSPACE')
372 return 1
373 if 'BASE_TOOLS_PATH' not in os.environ.keys():
374 sys.stderr.write(SYS_ENV_ERR % 'BASE_TOOLS_PATH')
375 return 1
376 if not os.path.exists(os.environ['BASE_TOOLS_PATH']):
377 sys.stderr.write("Unable to locate the %s directory." % os.environ['BASE_TOOLS_PATH'])
378 return 1
379
380
381 options.HAVE_SVN = CheckSvn(options)
382 if options.TEST_SVN:
383 return (not options.HAVE_SVN)
384 # done processing the option, now use the option.HAVE_SVN as a flag. True = Have it, False = Don't have it.
385 if options.REVERT:
386 # Just revert the tools an exit
387 RevertBuildVersionFiles(options)
388 else:
389 # Revert any changes in the BuildVersion.* files before setting them again.
390 RevertBuildVersionFiles(options)
391 Revision, Modified = GetSvnRevision(options)
392 if options.verbose:
393 sys.stdout.write("Revision: %s is Modified: %s\n" % (Revision, Modified))
394 sys.stdout.flush()
395 UpdateBuildVersionH(Revision, Modified, options)
396 UpdateBuildVersionPython(Revision, Modified, options)
397
398 return 0
399
400
401 if __name__ == "__main__":
402 sys.exit(UpdateRevisionFiles())
403
404