#!/usr/bin/env python

# Copyright (c) 2016 Google Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# Updates an output file with version info unless the new content is the same
# as the existing content.
#
# Args: <changes-file> <output-file>
#
# The output file will contain a line of text consisting of two C source syntax
# string literals separated by a comma:
#  - The software version deduced from the given CHANGES file.
#  - A longer string with the project name, the software version number, and
#    git commit information for the CHANGES file's directory.  The commit
#    information is the output of "git describe" if that succeeds, or "git
#    rev-parse HEAD" if that succeeds, or otherwise a message containing the
#    phrase "unknown hash".
# The string contents are escaped as necessary.

import datetime
import errno
import os
import os.path
import re
import subprocess
import logging
import sys
import time

# Format of the output generated by this script. Example:
# "v2023.1", "SPIRV-Tools v2023.1 0fc5526f2b01a0cc89192c10cf8bef77f1007a62, 2023-01-18T14:51:49"
OUTPUT_FORMAT = '"{version_tag}", "SPIRV-Tools {version_tag} {description}"\n'

def mkdir_p(directory):
    """Make the directory, and all its ancestors as required.  Any of the
    directories are allowed to already exist."""

    if directory == "":
        # We're being asked to make the current directory.
        return

    try:
        os.makedirs(directory)
    except OSError as e:
        if e.errno == errno.EEXIST and os.path.isdir(directory):
            pass
        else:
            raise

def command_output(cmd, directory, may_fail=False):
    """Runs a command in a directory and returns its standard output stream.

    Captures the standard error stream.

    Raises a RuntimeError if the command fails to launch or otherwise fails. If
    `may_fail` is true, suppresses the log message when running the command
    succeeds but returns a non-zero error code.
    """
    try:
      # Set shell=True on Windows so that Chromium's git.bat can be found when
      # 'git' is invoked.
      p = subprocess.Popen(cmd,
                           cwd=directory,
                           stdout=subprocess.PIPE,
                           stderr=subprocess.PIPE,
                           shell=os.name == 'nt')
      (stdout, stderr) = p.communicate()
      if p.returncode != 0 and not may_fail:
        logging.error('Failed to run "{}" in "{}": {}'.format(cmd, directory, stderr.decode()))
    except Exception as e:
        logging.error('Failed to run "{}" in "{}": {}'.format(cmd, directory, str(e)))
        return False, None
    return p.returncode == 0, stdout

def deduce_software_version(changes_file):
    """Returns a tuple (success, software version number) parsed from the
    given CHANGES file.

    Success is set to True if the software version could be deduced.
    Software version is undefined if success if False.
    Function expects the CHANGES file to describes most recent versions first.
    """

    # Match the first well-formed version-and-date line
    # Allow trailing whitespace in the checked-out source code has
    # unexpected carriage returns on a linefeed-only system such as
    # Linux.
    pattern = re.compile(r'^(v\d+\.\d+(-dev)?) \d\d\d\d-\d\d-\d\d\s*$')
    with open(changes_file, mode='r') as f:
        for line in f.readlines():
            match = pattern.match(line)
            if match:
                return True, match.group(1)
    return False, None


def describe(repo_path):
    """Returns a string describing the current Git HEAD version as descriptively
    as possible.

    Runs 'git describe', or alternately 'git rev-parse HEAD', in directory.  If
    successful, returns the output; otherwise returns 'unknown hash, <date>'."""

    success, output = command_output(['git', 'describe'], repo_path, may_fail=True)
    if not success:
      output = command_output(['git', 'rev-parse', 'HEAD'], repo_path)

    if success:
      # decode() is needed here for Python3 compatibility. In Python2,
      # str and bytes are the same type, but not in Python3.
      # Popen.communicate() returns a bytes instance, which needs to be
      # decoded into text data first in Python3. And this decode() won't
      # hurt Python2.
      return output.rstrip().decode()

    # This is the fallback case where git gives us no information,
    # e.g. because the source tree might not be in a git tree.
    # In this case, usually use a timestamp.  However, to ensure
    # reproducible builds, allow the builder to override the wall
    # clock time with environment variable SOURCE_DATE_EPOCH
    # containing a (presumably) fixed timestamp.
    timestamp = int(os.environ.get('SOURCE_DATE_EPOCH', time.time()))
    iso_date = datetime.datetime.utcfromtimestamp(timestamp).isoformat()
    return "unknown hash, {}".format(iso_date)

def main():
    FORMAT = '%(asctime)s %(message)s'
    logging.basicConfig(format="[%(asctime)s][%(levelname)-8s] %(message)s", datefmt="%H:%M:%S")
    if len(sys.argv) != 3:
        logging.error("usage: {} <repo-path> <output-file>".format(sys.argv[0]))
        sys.exit(1)

    changes_file_path = os.path.realpath(sys.argv[1])
    output_file_path = sys.argv[2]

    success, version = deduce_software_version(changes_file_path)
    if not success:
      logging.error("Could not deduce latest release version from {}.".format(changes_file_path))
      sys.exit(1)

    repo_path = os.path.dirname(changes_file_path)
    description = describe(repo_path)
    content = OUTPUT_FORMAT.format(version_tag=version, description=description)

    # Escape file content.
    content.replace('"', '\\"')

    if os.path.isfile(output_file_path):
      with open(output_file_path, 'r') as f:
        if content == f.read():
          return

    mkdir_p(os.path.dirname(output_file_path))
    with open(output_file_path, 'w') as f:
        f.write(content)

if __name__ == '__main__':
    main()
