#!/usr/bin/env python
# Copyright (c) 2012 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""
lastchange.py -- Chromium revision fetching utility.
"""
from __future__ import print_function

import argparse
import collections
import logging
import os
import subprocess
import sys

VersionInfo = collections.namedtuple("VersionInfo",
                                     ("revision_id", "revision", "timestamp"))

class GitError(Exception):
  pass

# This function exists for compatibility with logic outside this
# repository that uses this file as a library.
# TODO(eliribble) remove this function after it has been ported into
# the repositories that depend on it
def RunGitCommand(directory, command):
  """
  Launches git subcommand.

  Errors are swallowed.

  Returns:
    A process object or None.
  """
  command = ['git'] + command
  # Force shell usage under cygwin. This is a workaround for
  # mysterious loss of cwd while invoking cygwin's git.
  # We can't just pass shell=True to Popen, as under win32 this will
  # cause CMD to be used, while we explicitly want a cygwin shell.
  if sys.platform == 'cygwin':
    command = ['sh', '-c', ' '.join(command)]
  try:
    proc = subprocess.Popen(command,
                            stdout=subprocess.PIPE,
                            stderr=subprocess.PIPE,
                            cwd=directory,
                            shell=(sys.platform=='win32'))
    return proc
  except OSError as e:
    logging.error('Command %r failed: %s' % (' '.join(command), e))
    return None


def _RunGitCommand(directory, command):
  """Launches git subcommand.

  Returns:
    The stripped stdout of the git command.
  Raises:
    GitError on failure, including a nonzero return code.
  """
  command = ['git'] + command
  # Force shell usage under cygwin. This is a workaround for
  # mysterious loss of cwd while invoking cygwin's git.
  # We can't just pass shell=True to Popen, as under win32 this will
  # cause CMD to be used, while we explicitly want a cygwin shell.
  if sys.platform == 'cygwin':
    command = ['sh', '-c', ' '.join(command)]
  try:
    logging.info("Executing '%s' in %s", ' '.join(command), directory)
    proc = subprocess.Popen(command,
                            stdout=subprocess.PIPE,
                            stderr=subprocess.PIPE,
                            cwd=directory,
                            shell=(sys.platform=='win32'))
    stdout, stderr = proc.communicate()
    stdout = stdout.strip()
    logging.debug("returncode: %d", proc.returncode)
    logging.debug("stdout: %s", stdout)
    logging.debug("stderr: %s", stderr)
    if proc.returncode != 0 or not stdout:
      raise GitError((
          "Git command '{}' in {} failed: "
          "rc={}, stdout='{}' stderr='{}'").format(
          " ".join(command), directory, proc.returncode, stdout, stderr))
    return stdout
  except OSError as e:
    raise GitError("Git command 'git {}' in {} failed: {}".format(
        " ".join(command), directory, e))


def GetMergeBase(directory, ref):
  """
  Return the merge-base of HEAD and ref.

  Args:
    directory: The directory containing the .git directory.
    ref: The ref to use to find the merge base.
  Returns:
    The git commit SHA of the merge-base as a string.
  """
  logging.debug("Calculating merge base between HEAD and %s in %s",
                ref, directory)
  command = ['merge-base', 'HEAD', ref]
  return _RunGitCommand(directory, command)


def FetchGitRevision(directory, commit_filter, start_commit="HEAD"):
  """
  Fetch the Git hash (and Cr-Commit-Position if any) for a given directory.

  Args:
    directory: The directory containing the .git directory.
    commit_filter: A filter to supply to grep to filter commits
    start_commit: A commit identifier. The result of this function
      will be limited to only consider commits before the provided
      commit.
  Returns:
    A VersionInfo object. On error all values will be 0.
  """
  hash_ = ''

  git_args = ['log', '-1', '--format=%H %ct']
  if commit_filter is not None:
    git_args.append('--grep=' + commit_filter)

  git_args.append(start_commit)

  output = _RunGitCommand(directory, git_args)
  hash_, commit_timestamp = output.split()
  if not hash_:
    return VersionInfo('0', '0', 0)

  revision = hash_
  output = _RunGitCommand(directory, ['cat-file', 'commit', hash_])
  for line in reversed(output.splitlines()):
    if line.startswith('Cr-Commit-Position:'):
      pos = line.rsplit()[-1].strip()
      logging.debug("Found Cr-Commit-Position '%s'", pos)
      revision = "{}-{}".format(hash_, pos)
      break
  return VersionInfo(hash_, revision, int(commit_timestamp))


def GetHeaderGuard(path):
  """
  Returns the header #define guard for the given file path.
  This treats everything after the last instance of "src/" as being a
  relevant part of the guard. If there is no "src/", then the entire path
  is used.
  """
  src_index = path.rfind('src/')
  if src_index != -1:
    guard = path[src_index + 4:]
  else:
    guard = path
  guard = guard.upper()
  return guard.replace('/', '_').replace('.', '_').replace('\\', '_') + '_'


def GetHeaderContents(path, define, version):
  """
  Returns what the contents of the header file should be that indicate the given
  revision.
  """
  header_guard = GetHeaderGuard(path)

  header_contents = """/* Generated by lastchange.py, do not edit.*/

#ifndef %(header_guard)s
#define %(header_guard)s

#define %(define)s "%(version)s"

#endif  // %(header_guard)s
"""
  header_contents = header_contents % { 'header_guard': header_guard,
                                        'define': define,
                                        'version': version }
  return header_contents


def GetGitTopDirectory(source_dir):
  """Get the top git directory - the directory that contains the .git directory.

  Args:
    source_dir: The directory to search.
  Returns:
    The output of "git rev-parse --show-toplevel" as a string
  """
  return _RunGitCommand(source_dir, ['rev-parse', '--show-toplevel'])


def WriteIfChanged(file_name, contents):
  """
  Writes the specified contents to the specified file_name
  iff the contents are different than the current contents.
  Returns if new data was written.
  """
  try:
    old_contents = open(file_name, 'r').read()
  except EnvironmentError:
    pass
  else:
    if contents == old_contents:
      return False
    os.unlink(file_name)
  open(file_name, 'w').write(contents)
  return True


def main(argv=None):
  if argv is None:
    argv = sys.argv

  parser = argparse.ArgumentParser(usage="lastchange.py [options]")
  parser.add_argument("-m", "--version-macro",
                    help=("Name of C #define when using --header. Defaults to "
                          "LAST_CHANGE."))
  parser.add_argument("-o", "--output", metavar="FILE",
                    help=("Write last change to FILE. "
                          "Can be combined with --header to write both files."))
  parser.add_argument("--header", metavar="FILE",
                    help=("Write last change to FILE as a C/C++ header. "
                          "Can be combined with --output to write both files."))
  parser.add_argument("--merge-base-ref",
                    default=None,
                    help=("Only consider changes since the merge "
                          "base between HEAD and the provided ref"))
  parser.add_argument("--revision-id-only", action='store_true',
                    help=("Output the revision as a VCS revision ID only (in "
                          "Git, a 40-character commit hash, excluding the "
                          "Cr-Commit-Position)."))
  parser.add_argument("--print-only", action="store_true",
                    help=("Just print the revision string. Overrides any "
                          "file-output-related options."))
  parser.add_argument("-s", "--source-dir", metavar="DIR",
                    help="Use repository in the given directory.")
  parser.add_argument("--filter", metavar="REGEX",
                    help=("Only use log entries where the commit message "
                          "matches the supplied filter regex. Defaults to "
                          "'^Change-Id:' to suppress local commits."),
                    default='^Change-Id:')

  args, extras = parser.parse_known_args(argv[1:])

  logging.basicConfig(level=logging.WARNING)

  out_file = args.output
  header = args.header
  commit_filter=args.filter

  while len(extras) and out_file is None:
    if out_file is None:
      out_file = extras.pop(0)
  if extras:
    sys.stderr.write('Unexpected arguments: %r\n\n' % extras)
    parser.print_help()
    sys.exit(2)

  source_dir = args.source_dir or os.path.dirname(os.path.abspath(__file__))
  try:
    git_top_dir = GetGitTopDirectory(source_dir)
  except GitError as e:
    logging.error("Failed to get git top directory from '%s': %s",
                  source_dir, e)
    return 2

  if args.merge_base_ref:
    try:
      merge_base_sha = GetMergeBase(git_top_dir, args.merge_base_ref)
    except GitError as e:
      logging.error("You requested a --merge-base-ref value of '%s' but no "
                    "merge base could be found between it and HEAD. Git "
                    "reports: %s", args.merge_base_ref, e)
      return 3
  else:
    merge_base_sha = 'HEAD'

  try:
    version_info = FetchGitRevision(git_top_dir, commit_filter, merge_base_sha)
  except GitError as e:
    logging.error("Failed to get version info: %s", e)
    logging.info(("Falling back to a version of 0.0.0 to allow script to "
        "finish. This is normal if you are bootstrapping a new environment "
        "or do not have a git repository for any other reason. If not, this "
        "could represent a serious error."))
    version_info = VersionInfo('0', '0', 0)

  revision_string = version_info.revision
  if args.revision_id_only:
    revision_string = version_info.revision_id

  if args.print_only:
    print(revision_string)
  else:
    contents = "LASTCHANGE=%s\n" % revision_string
    if not out_file and not args.header:
      sys.stdout.write(contents)
    else:
      if out_file:
        committime_file = out_file + '.committime'
        out_changed = WriteIfChanged(out_file, contents)
        if out_changed or not os.path.exists(committime_file):
          with open(committime_file, 'w') as timefile:
            timefile.write(str(version_info.timestamp))
      if header:
        WriteIfChanged(header,
                       GetHeaderContents(header, args.version_macro,
                                         revision_string))

  return 0


if __name__ == '__main__':
  sys.exit(main())
