#!/usr/bin/env python
# Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
# for details. All rights reserved. Use of this source code is governed by a
# BSD-style license that can be found in the LICENSE file.
#
# This python script creates a version string in a C++ file.

import hashlib
import os
import sys
import time
from optparse import OptionParser
import utils

def debugLog(message):
  print >> sys.stderr, message
  sys.stderr.flush()

# When these files change, snapshots created by the VM are potentially no longer
# backwards-compatible.
VM_SNAPSHOT_FILES=[
  # Header files.
  'clustered_snapshot.h',
  'datastream.h',
  'image_snapshot.h',
  'object.h',
  'raw_object.h',
  'snapshot.h',
  'snapshot_ids.h',
  'symbols.h',
  # Source files.
  'clustered_snapshot.cc',
  'dart.cc',
  'dart_api_impl.cc',
  'image_snapshot.cc',
  'object.cc',
  'raw_object.cc',
  'raw_object_snapshot.cc',
  'snapshot.cc',
  'symbols.cc',
]

def MakeVersionString(quiet, no_git_hash, custom_for_pub=None):
  if custom_for_pub:
    latest = utils.GetLatestDevTag()
    if not latest:
      # If grabbing the dev tag fails, then fall back on the VERSION file.
      latest = utils.GetSemanticSDKVersion(no_git_hash=True)
    if no_git_hash:
      version_string = ("%s.%s" % (latest, custom_for_pub))
    else:
      git_hash = utils.GetShortGitHash()
      version_string = ("%s.%s-%s" % (latest, custom_for_pub, git_hash))
  else:
    version_string = utils.GetSemanticSDKVersion(no_git_hash=no_git_hash)
  if not quiet:
    debugLog("Returning version string: %s " % version_string)
  return version_string


def MakeSnapshotHashString():
  vmhash = hashlib.md5()
  for vmfilename in VM_SNAPSHOT_FILES:
    vmfilepath = os.path.join(utils.DART_DIR, 'runtime', 'vm', vmfilename)
    with open(vmfilepath) as vmfile:
      vmhash.update(vmfile.read())
  return vmhash.hexdigest()


def MakeFile(quiet, output_file, input_file, no_git_hash, custom_for_pub, version_file=None):
  if version_file:
    version_string = utils.GetVersion(version_file)
  else:
    version_string = MakeVersionString(quiet, no_git_hash, custom_for_pub)

  version_cc_text = open(input_file).read()
  version_cc_text = version_cc_text.replace("{{VERSION_STR}}",
                                            version_string)
  version_time = utils.GetGitTimestamp()
  if no_git_hash or version_time == None:
    version_time = "Unknown timestamp"
  version_cc_text = version_cc_text.replace("{{COMMIT_TIME}}",
                                            version_time)
  abi_version = utils.GetAbiVersion(version_file)
  version_cc_text = version_cc_text.replace("{{ABI_VERSION}}", abi_version)
  oldest_supported_abi_version = utils.GetOldestSupportedAbiVersion(version_file)
  version_cc_text = version_cc_text.replace("{{OLDEST_SUPPORTED_ABI_VERSION}}",
                                            oldest_supported_abi_version)
  snapshot_hash = MakeSnapshotHashString()
  version_cc_text = version_cc_text.replace("{{SNAPSHOT_HASH}}",
                                            snapshot_hash)
  open(output_file, 'w').write(version_cc_text)
  return True


def main(args):
  try:
    # Parse input.
    parser = OptionParser()
    parser.add_option("--custom_for_pub",
        action="store",
        type="string",
        help=("Generates a version string that works with pub that includes"
              "the given string"))
    parser.add_option("--input",
        action="store",
        type="string",
        help="input template file.")
    parser.add_option("--no_git_hash",
        action="store_true",
        default=False,
        help="Don't try to determine svn revision")
    parser.add_option("--output",
        action="store",
        type="string",
        help="output file name")
    parser.add_option("-q", "--quiet",
        action="store_true",
        default=False,
        help="disable console output")
    parser.add_option("--version-file",
        action="store",
        type="string",
        default=None,
        help="Version file")

    (options, args) = parser.parse_args()

    # If there is no input template, then write the bare version string to
    # options.output. If there is no options.output, then write the version
    # string to stdout.
    if not options.input:
      version_string = MakeVersionString(
          options.quiet, options.no_git_hash, options.custom_for_pub)
      if options.output:
        open(options.output, 'w').write(version_string)
      else:
        print (version_string)
      return 0

    if not options.output:
      sys.stderr.write('--output not specified\n')
      return -1
    if not options.input:
      sys.stderr.write('--input not specified\n')
      return -1

    files = []
    for arg in args:
      files.append(arg)

    if not MakeFile(options.quiet, options.output, options.input,
                    options.no_git_hash, options.custom_for_pub, options.version_file):
      return -1

    return 0
  except Exception as inst:
    sys.stderr.write('make_version.py exception\n')
    sys.stderr.write(str(inst))
    sys.stderr.write('\n')
    return -1

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