mirror of https://github.com/acidanthera/audk.git
405 lines
15 KiB
Python
Executable File
405 lines
15 KiB
Python
Executable File
## @file
|
|
# Update build revisions of the tools when performing a developer build
|
|
#
|
|
# This script will modife the C/Include/Common/BuildVersion.h file and the two
|
|
# Python scripts, Python/Common/BuildVersion.py and Python/UPT/BuildVersion.py.
|
|
# If SVN is available, the tool will obtain the current checked out version of
|
|
# the source tree for including the the --version commands.
|
|
|
|
# Copyright (c) 2014 - 2015, Intel Corporation. All rights reserved.<BR>
|
|
#
|
|
# This program and the accompanying materials
|
|
# are licensed and made available under the terms and conditions of the BSD License
|
|
# which accompanies this distribution. The full text of the license may be found at
|
|
# http://opensource.org/licenses/bsd-license.php
|
|
#
|
|
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|
##
|
|
""" This program will update the BuildVersion.py and BuildVersion.h files used to set a tool's version value """
|
|
from __future__ import absolute_import
|
|
|
|
import os
|
|
import shlex
|
|
import subprocess
|
|
import sys
|
|
|
|
from argparse import ArgumentParser, SUPPRESS
|
|
from tempfile import NamedTemporaryFile
|
|
from types import IntType, ListType
|
|
|
|
|
|
SYS_ENV_ERR = "ERROR : %s system environment variable must be set prior to running this tool.\n"
|
|
|
|
__execname__ = "UpdateBuildVersions.py"
|
|
SVN_REVISION = "$LastChangedRevision: 3 $"
|
|
SVN_REVISION = SVN_REVISION.replace("$LastChangedRevision:", "").replace("$", "").strip()
|
|
__copyright__ = "Copyright (c) 2014, Intel Corporation. All rights reserved."
|
|
VERSION_NUMBER = "0.7.0"
|
|
__version__ = "Version %s.%s" % (VERSION_NUMBER, SVN_REVISION)
|
|
|
|
|
|
def ParseOptions():
|
|
"""
|
|
Parse the command-line options.
|
|
The options for this tool will be passed along to the MkBinPkg tool.
|
|
"""
|
|
parser = ArgumentParser(
|
|
usage=("%s [options]" % __execname__),
|
|
description=__copyright__,
|
|
conflict_handler='resolve')
|
|
|
|
# Standard Tool Options
|
|
parser.add_argument("--version", action="version",
|
|
version=__execname__ + " " + __version__)
|
|
parser.add_argument("-s", "--silent", action="store_true",
|
|
dest="silent",
|
|
help="All output will be disabled, pass/fail determined by the exit code")
|
|
parser.add_argument("-v", "--verbose", action="store_true",
|
|
dest="verbose",
|
|
help="Enable verbose output")
|
|
# Tool specific options
|
|
parser.add_argument("--revert", action="store_true",
|
|
dest="REVERT", default=False,
|
|
help="Revert the BuildVersion files only")
|
|
parser.add_argument("--svn-test", action="store_true",
|
|
dest="TEST_SVN", default=False,
|
|
help="Test if the svn command is available")
|
|
parser.add_argument("--svnFlag", action="store_true",
|
|
dest="HAVE_SVN", default=False,
|
|
help=SUPPRESS)
|
|
|
|
return(parser.parse_args())
|
|
|
|
|
|
def ShellCommandResults(CmdLine, Opt):
|
|
""" Execute the comand, returning the output content """
|
|
file_list = NamedTemporaryFile(delete=False)
|
|
filename = file_list.name
|
|
Results = []
|
|
|
|
returnValue = 0
|
|
try:
|
|
subprocess.check_call(args=shlex.split(CmdLine), stderr=subprocess.STDOUT, stdout=file_list)
|
|
except subprocess.CalledProcessError as err_val:
|
|
file_list.close()
|
|
if not Opt.silent:
|
|
sys.stderr.write("ERROR : %d : %s\n" % (err_val.returncode, err_val.__str__()))
|
|
if os.path.exists(filename):
|
|
sys.stderr.write(" : Partial results may be in this file: %s\n" % filename)
|
|
sys.stderr.flush()
|
|
returnValue = err_val.returncode
|
|
|
|
except IOError as err_val:
|
|
(errno, strerror) = err_val.args
|
|
file_list.close()
|
|
if not Opt.silent:
|
|
sys.stderr.write("I/O ERROR : %s : %s\n" % (str(errno), strerror))
|
|
sys.stderr.write("ERROR : this command failed : %s\n" % CmdLine)
|
|
if os.path.exists(filename):
|
|
sys.stderr.write(" : Partial results may be in this file: %s\n" % filename)
|
|
sys.stderr.flush()
|
|
returnValue = errno
|
|
|
|
except OSError as err_val:
|
|
(errno, strerror) = err_val.args
|
|
file_list.close()
|
|
if not Opt.silent:
|
|
sys.stderr.write("OS ERROR : %s : %s\n" % (str(errno), strerror))
|
|
sys.stderr.write("ERROR : this command failed : %s\n" % CmdLine)
|
|
if os.path.exists(filename):
|
|
sys.stderr.write(" : Partial results may be in this file: %s\n" % filename)
|
|
sys.stderr.flush()
|
|
returnValue = errno
|
|
|
|
except KeyboardInterrupt:
|
|
file_list.close()
|
|
if not Opt.silent:
|
|
sys.stderr.write("ERROR : Command terminated by user : %s\n" % CmdLine)
|
|
if os.path.exists(filename):
|
|
sys.stderr.write(" : Partial results may be in this file: %s\n" % filename)
|
|
sys.stderr.flush()
|
|
returnValue = 1
|
|
|
|
finally:
|
|
if not file_list.closed:
|
|
file_list.flush()
|
|
os.fsync(file_list.fileno())
|
|
file_list.close()
|
|
|
|
if os.path.exists(filename):
|
|
fd_ = open(filename, 'r')
|
|
Results = fd_.readlines()
|
|
fd_.close()
|
|
os.unlink(filename)
|
|
|
|
if returnValue > 0:
|
|
return returnValue
|
|
|
|
return Results
|
|
|
|
|
|
def UpdateBuildVersionPython(Rev, UserModified, opts):
|
|
""" This routine will update the BuildVersion.h files in the C source tree """
|
|
for SubDir in ["Common", "UPT"]:
|
|
PyPath = os.path.join(os.environ['BASE_TOOLS_PATH'], "Source", "Python", SubDir)
|
|
BuildVersionPy = os.path.join(PyPath, "BuildVersion.py")
|
|
fd_ = open(os.path.normpath(BuildVersionPy), 'r')
|
|
contents = fd_.readlines()
|
|
fd_.close()
|
|
if opts.HAVE_SVN is False:
|
|
BuildVersionOrig = os.path.join(PyPath, "orig_BuildVersion.py")
|
|
fd_ = open (BuildVersionOrig, 'w')
|
|
for line in contents:
|
|
fd_.write(line)
|
|
fd_.flush()
|
|
fd_.close()
|
|
new_content = []
|
|
for line in contents:
|
|
if line.strip().startswith("gBUILD_VERSION"):
|
|
new_line = "gBUILD_VERSION = \"Developer Build based on Revision: %s\"" % Rev
|
|
if UserModified:
|
|
new_line = "gBUILD_VERSION = \"Developer Build based on Revision: %s with Modified Sources\"" % Rev
|
|
new_content.append(new_line)
|
|
continue
|
|
new_content.append(line)
|
|
|
|
fd_ = open(os.path.normpath(BuildVersionPy), 'w')
|
|
for line in new_content:
|
|
fd_.write(line)
|
|
fd_.close()
|
|
|
|
|
|
def UpdateBuildVersionH(Rev, UserModified, opts):
|
|
""" This routine will update the BuildVersion.h files in the C source tree """
|
|
CPath = os.path.join(os.environ['BASE_TOOLS_PATH'], "Source", "C", "Include", "Common")
|
|
BuildVersionH = os.path.join(CPath, "BuildVersion.h")
|
|
fd_ = open(os.path.normpath(BuildVersionH), 'r')
|
|
contents = fd_.readlines()
|
|
fd_.close()
|
|
if opts.HAVE_SVN is False:
|
|
BuildVersionOrig = os.path.join(CPath, "orig_BuildVersion.h")
|
|
fd_ = open(BuildVersionOrig, 'w')
|
|
for line in contents:
|
|
fd_.write(line)
|
|
fd_.flush()
|
|
fd_.close()
|
|
|
|
new_content = []
|
|
for line in contents:
|
|
if line.strip().startswith("#define"):
|
|
new_line = "#define __BUILD_VERSION \"Developer Build based on Revision: %s\"" % Rev
|
|
if UserModified:
|
|
new_line = "#define __BUILD_VERSION \"Developer Build based on Revision: %s with Modified Sources\"" % \
|
|
Rev
|
|
new_content.append(new_line)
|
|
continue
|
|
new_content.append(line)
|
|
|
|
fd_ = open(os.path.normpath(BuildVersionH), 'w')
|
|
for line in new_content:
|
|
fd_.write(line)
|
|
fd_.close()
|
|
|
|
|
|
def RevertCmd(Filename, Opt):
|
|
""" This is the shell command that does the SVN revert """
|
|
CmdLine = "svn revert %s" % Filename.replace("\\", "/").strip()
|
|
try:
|
|
subprocess.check_output(args=shlex.split(CmdLine))
|
|
except subprocess.CalledProcessError as err_val:
|
|
if not Opt.silent:
|
|
sys.stderr.write("Subprocess ERROR : %s\n" % err_val)
|
|
sys.stderr.flush()
|
|
|
|
except IOError as err_val:
|
|
(errno, strerror) = err_val.args
|
|
if not Opt.silent:
|
|
sys.stderr.write("I/O ERROR : %d : %s\n" % (str(errno), strerror))
|
|
sys.stderr.write("ERROR : this command failed : %s\n" % CmdLine)
|
|
sys.stderr.flush()
|
|
|
|
except OSError as err_val:
|
|
(errno, strerror) = err_val.args
|
|
if not Opt.silent:
|
|
sys.stderr.write("OS ERROR : %d : %s\n" % (str(errno), strerror))
|
|
sys.stderr.write("ERROR : this command failed : %s\n" % CmdLine)
|
|
sys.stderr.flush()
|
|
|
|
except KeyboardInterrupt:
|
|
if not Opt.silent:
|
|
sys.stderr.write("ERROR : Command terminated by user : %s\n" % CmdLine)
|
|
sys.stderr.flush()
|
|
|
|
if Opt.verbose:
|
|
sys.stdout.write("Reverted this file: %s\n" % Filename)
|
|
sys.stdout.flush()
|
|
|
|
|
|
def GetSvnRevision(opts):
|
|
""" Get the current revision of the BaseTools/Source tree, and check if any of the files have been modified """
|
|
Revision = "Unknown"
|
|
Modified = False
|
|
|
|
if opts.HAVE_SVN is False:
|
|
sys.stderr.write("WARNING: the svn command-line tool is not available.\n")
|
|
return (Revision, Modified)
|
|
|
|
SrcPath = os.path.join(os.environ['BASE_TOOLS_PATH'], "Source")
|
|
# Check if there are modified files.
|
|
Cwd = os.getcwd()
|
|
os.chdir(SrcPath)
|
|
|
|
StatusCmd = "svn st -v --depth infinity --non-interactive"
|
|
contents = ShellCommandResults(StatusCmd, opts)
|
|
os.chdir(Cwd)
|
|
if isinstance(contents, ListType):
|
|
for line in contents:
|
|
if line.startswith("M "):
|
|
Modified = True
|
|
break
|
|
|
|
# Get the repository revision of BaseTools/Source
|
|
InfoCmd = "svn info %s" % SrcPath.replace("\\", "/").strip()
|
|
Revision = 0
|
|
contents = ShellCommandResults(InfoCmd, opts)
|
|
if isinstance(contents, IntType):
|
|
return 0, Modified
|
|
for line in contents:
|
|
line = line.strip()
|
|
if line.startswith("Revision:"):
|
|
Revision = line.replace("Revision:", "").strip()
|
|
break
|
|
|
|
return (Revision, Modified)
|
|
|
|
|
|
def CheckSvn(opts):
|
|
"""
|
|
This routine will return True if an svn --version command succeeds, or False if it fails.
|
|
If it failed, SVN is not available.
|
|
"""
|
|
OriginalSilent = opts.silent
|
|
opts.silent = True
|
|
VerCmd = "svn --version"
|
|
contents = ShellCommandResults(VerCmd, opts)
|
|
opts.silent = OriginalSilent
|
|
if isinstance(contents, IntType):
|
|
if opts.verbose:
|
|
sys.stdout.write("SVN does not appear to be available.\n")
|
|
sys.stdout.flush()
|
|
return False
|
|
|
|
if opts.verbose:
|
|
sys.stdout.write("Found %s" % contents[0])
|
|
sys.stdout.flush()
|
|
return True
|
|
|
|
|
|
def CopyOrig(Src, Dest, Opt):
|
|
""" Overwrite the Dest File with the Src File content """
|
|
try:
|
|
fd_ = open(Src, 'r')
|
|
contents = fd_.readlines()
|
|
fd_.close()
|
|
fd_ = open(Dest, 'w')
|
|
for line in contents:
|
|
fd_.write(line)
|
|
fd_.flush()
|
|
fd_.close()
|
|
except IOError:
|
|
if not Opt.silent:
|
|
sys.stderr.write("Unable to restore this file: %s\n" % Dest)
|
|
sys.stderr.flush()
|
|
return 1
|
|
|
|
os.remove(Src)
|
|
if Opt.verbose:
|
|
sys.stdout.write("Restored this file: %s\n" % Src)
|
|
sys.stdout.flush()
|
|
|
|
return 0
|
|
|
|
|
|
def CheckOriginals(Opts):
|
|
"""
|
|
If SVN was not available, then the tools may have made copies of the original BuildVersion.* files using
|
|
orig_BuildVersion.* for the name. If they exist, replace the existing BuildVersion.* file with the corresponding
|
|
orig_BuildVersion.* file.
|
|
Returns 0 if this succeeds, or 1 if the copy function fails. It will also return 0 if the orig_BuildVersion.* file
|
|
does not exist.
|
|
"""
|
|
CPath = os.path.join(os.environ['BASE_TOOLS_PATH'], "Source", "C", "Include", "Common")
|
|
BuildVersionH = os.path.join(CPath, "BuildVersion.h")
|
|
OrigBuildVersionH = os.path.join(CPath, "orig_BuildVersion.h")
|
|
if not os.path.exists(OrigBuildVersionH):
|
|
return 0
|
|
if CopyOrig(OrigBuildVersionH, BuildVersionH, Opts):
|
|
return 1
|
|
for SubDir in ["Common", "UPT"]:
|
|
PyPath = os.path.join(os.environ['BASE_TOOLS_PATH'], "Source", "Python", SubDir)
|
|
BuildVersionPy = os.path.join(PyPath, "BuildVersion.h")
|
|
OrigBuildVersionPy = os.path.join(PyPath, "orig_BuildVersion.h")
|
|
if not os.path.exists(OrigBuildVersionPy):
|
|
return 0
|
|
if CopyOrig(OrigBuildVersionPy, BuildVersionPy, Opts):
|
|
return 1
|
|
|
|
return 0
|
|
|
|
|
|
def RevertBuildVersionFiles(opts):
|
|
"""
|
|
This routine will attempt to perform an SVN --revert on each of the BuildVersion.* files
|
|
"""
|
|
if not opts.HAVE_SVN:
|
|
if CheckOriginals(opts):
|
|
return 1
|
|
return 0
|
|
# SVN is available
|
|
BuildVersionH = os.path.join(os.environ['BASE_TOOLS_PATH'], "Source", "C", "Include", "Common", "BuildVersion.h")
|
|
RevertCmd(BuildVersionH, opts)
|
|
for SubDir in ["Common", "UPT"]:
|
|
BuildVersionPy = os.path.join(os.environ['BASE_TOOLS_PATH'], "Source", "Python", SubDir, "BuildVersion.py")
|
|
RevertCmd(BuildVersionPy, opts)
|
|
|
|
def UpdateRevisionFiles():
|
|
""" Main routine that will update the BuildVersion.py and BuildVersion.h files."""
|
|
options = ParseOptions()
|
|
# Check the working environment
|
|
if "WORKSPACE" not in os.environ.keys():
|
|
sys.stderr.write(SYS_ENV_ERR % 'WORKSPACE')
|
|
return 1
|
|
if 'BASE_TOOLS_PATH' not in os.environ.keys():
|
|
sys.stderr.write(SYS_ENV_ERR % 'BASE_TOOLS_PATH')
|
|
return 1
|
|
if not os.path.exists(os.environ['BASE_TOOLS_PATH']):
|
|
sys.stderr.write("Unable to locate the %s directory." % os.environ['BASE_TOOLS_PATH'])
|
|
return 1
|
|
|
|
|
|
options.HAVE_SVN = CheckSvn(options)
|
|
if options.TEST_SVN:
|
|
return (not options.HAVE_SVN)
|
|
# done processing the option, now use the option.HAVE_SVN as a flag. True = Have it, False = Don't have it.
|
|
if options.REVERT:
|
|
# Just revert the tools an exit
|
|
RevertBuildVersionFiles(options)
|
|
else:
|
|
# Revert any changes in the BuildVersion.* files before setting them again.
|
|
RevertBuildVersionFiles(options)
|
|
Revision, Modified = GetSvnRevision(options)
|
|
if options.verbose:
|
|
sys.stdout.write("Revision: %s is Modified: %s\n" % (Revision, Modified))
|
|
sys.stdout.flush()
|
|
UpdateBuildVersionH(Revision, Modified, options)
|
|
UpdateBuildVersionPython(Revision, Modified, options)
|
|
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(UpdateRevisionFiles())
|
|
|
|
|