## @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())


