media/webrtc/trunk/build/util/lastchange.py

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/media/webrtc/trunk/build/util/lastchange.py	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,230 @@
     1.4 +#!/usr/bin/env python
     1.5 +# Copyright (c) 2012 The Chromium Authors. All rights reserved.
     1.6 +# Use of this source code is governed by a BSD-style license that can be
     1.7 +# found in the LICENSE file.
     1.8 +
     1.9 +"""
    1.10 +lastchange.py -- Chromium revision fetching utility.
    1.11 +"""
    1.12 +
    1.13 +import re
    1.14 +import optparse
    1.15 +import os
    1.16 +import subprocess
    1.17 +import sys
    1.18 +
    1.19 +_GIT_SVN_ID_REGEX = re.compile(r'.*git-svn-id:\s*([^@]*)@([0-9]+)', re.DOTALL)
    1.20 +
    1.21 +class VersionInfo(object):
    1.22 +  def __init__(self, url, revision):
    1.23 +    self.url = url
    1.24 +    self.revision = revision
    1.25 +
    1.26 +
    1.27 +def FetchSVNRevision(directory, svn_url_regex):
    1.28 +  """
    1.29 +  Fetch the Subversion branch and revision for a given directory.
    1.30 +
    1.31 +  Errors are swallowed.
    1.32 +
    1.33 +  Returns:
    1.34 +    A VersionInfo object or None on error.
    1.35 +  """
    1.36 +  try:
    1.37 +    proc = subprocess.Popen(['svn', 'info'],
    1.38 +                            stdout=subprocess.PIPE,
    1.39 +                            stderr=subprocess.PIPE,
    1.40 +                            cwd=directory,
    1.41 +                            shell=(sys.platform=='win32'))
    1.42 +  except OSError:
    1.43 +    # command is apparently either not installed or not executable.
    1.44 +    return None
    1.45 +  if not proc:
    1.46 +    return None
    1.47 +
    1.48 +  attrs = {}
    1.49 +  for line in proc.stdout:
    1.50 +    line = line.strip()
    1.51 +    if not line:
    1.52 +      continue
    1.53 +    key, val = line.split(': ', 1)
    1.54 +    attrs[key] = val
    1.55 +
    1.56 +  try:
    1.57 +    match = svn_url_regex.search(attrs['URL'])
    1.58 +    if match:
    1.59 +      url = match.group(2)
    1.60 +    else:
    1.61 +      url = ''
    1.62 +    revision = attrs['Revision']
    1.63 +  except KeyError:
    1.64 +    return None
    1.65 +
    1.66 +  return VersionInfo(url, revision)
    1.67 +
    1.68 +
    1.69 +def RunGitCommand(directory, command):
    1.70 +  """
    1.71 +  Launches git subcommand.
    1.72 +
    1.73 +  Errors are swallowed.
    1.74 +
    1.75 +  Returns:
    1.76 +    A process object or None.
    1.77 +  """
    1.78 +  command = ['git'] + command
    1.79 +  # Force shell usage under cygwin. This is a workaround for
    1.80 +  # mysterious loss of cwd while invoking cygwin's git.
    1.81 +  # We can't just pass shell=True to Popen, as under win32 this will
    1.82 +  # cause CMD to be used, while we explicitly want a cygwin shell.
    1.83 +  if sys.platform == 'cygwin':
    1.84 +    command = ['sh', '-c', ' '.join(command)]
    1.85 +  try:
    1.86 +    proc = subprocess.Popen(command,
    1.87 +                            stdout=subprocess.PIPE,
    1.88 +                            stderr=subprocess.PIPE,
    1.89 +                            cwd=directory,
    1.90 +                            shell=(sys.platform=='win32'))
    1.91 +    return proc
    1.92 +  except OSError:
    1.93 +    return None
    1.94 +
    1.95 +
    1.96 +def FetchGitRevision(directory):
    1.97 +  """
    1.98 +  Fetch the Git hash for a given directory.
    1.99 +
   1.100 +  Errors are swallowed.
   1.101 +
   1.102 +  Returns:
   1.103 +    A VersionInfo object or None on error.
   1.104 +  """
   1.105 +  proc = RunGitCommand(directory, ['rev-parse', 'HEAD'])
   1.106 +  if proc:
   1.107 +    output = proc.communicate()[0].strip()
   1.108 +    if proc.returncode == 0 and output:
   1.109 +      return VersionInfo('git', output[:7])
   1.110 +  return None
   1.111 +
   1.112 +
   1.113 +def FetchGitSVNURLAndRevision(directory, svn_url_regex):
   1.114 +  """
   1.115 +  Fetch the Subversion URL and revision through Git.
   1.116 +
   1.117 +  Errors are swallowed.
   1.118 +
   1.119 +  Returns:
   1.120 +    A tuple containing the Subversion URL and revision.
   1.121 +  """
   1.122 +  proc = RunGitCommand(directory, ['log', '-1',
   1.123 +                                   '--grep=git-svn-id', '--format=%b'])
   1.124 +  if proc:
   1.125 +    output = proc.communicate()[0].strip()
   1.126 +    if proc.returncode == 0 and output:
   1.127 +      # Extract the latest SVN revision and the SVN URL.
   1.128 +      # The target line is the last "git-svn-id: ..." line like this:
   1.129 +      # git-svn-id: svn://svn.chromium.org/chrome/trunk/src@85528 0039d316....
   1.130 +      match = _GIT_SVN_ID_REGEX.search(output)
   1.131 +      if match:
   1.132 +        revision = match.group(2)
   1.133 +        url_match = svn_url_regex.search(match.group(1))
   1.134 +        if url_match:
   1.135 +          url = url_match.group(2)
   1.136 +        else:
   1.137 +          url = ''
   1.138 +        return url, revision
   1.139 +  return None, None
   1.140 +
   1.141 +
   1.142 +def FetchGitSVNRevision(directory, svn_url_regex):
   1.143 +  """
   1.144 +  Fetch the Git-SVN identifier for the local tree.
   1.145 +
   1.146 +  Errors are swallowed.
   1.147 +  """
   1.148 +  url, revision = FetchGitSVNURLAndRevision(directory, svn_url_regex)
   1.149 +  if url and revision:
   1.150 +    return VersionInfo(url, revision)
   1.151 +  return None
   1.152 +
   1.153 +
   1.154 +def FetchVersionInfo(default_lastchange, directory=None,
   1.155 +                     directory_regex_prior_to_src_url='chrome|svn'):
   1.156 +  """
   1.157 +  Returns the last change (in the form of a branch, revision tuple),
   1.158 +  from some appropriate revision control system.
   1.159 +  """
   1.160 +  svn_url_regex = re.compile(
   1.161 +      r'.*/(' + directory_regex_prior_to_src_url + r')(/.*)')
   1.162 +
   1.163 +  version_info = (FetchSVNRevision(directory, svn_url_regex) or
   1.164 +                  FetchGitSVNRevision(directory, svn_url_regex) or
   1.165 +                  FetchGitRevision(directory))
   1.166 +  if not version_info:
   1.167 +    if default_lastchange and os.path.exists(default_lastchange):
   1.168 +      revision = open(default_lastchange, 'r').read().strip()
   1.169 +      version_info = VersionInfo(None, revision)
   1.170 +    else:
   1.171 +      version_info = VersionInfo(None, None)
   1.172 +  return version_info
   1.173 +
   1.174 +
   1.175 +def WriteIfChanged(file_name, contents):
   1.176 +  """
   1.177 +  Writes the specified contents to the specified file_name
   1.178 +  iff the contents are different than the current contents.
   1.179 +  """
   1.180 +  try:
   1.181 +    old_contents = open(file_name, 'r').read()
   1.182 +  except EnvironmentError:
   1.183 +    pass
   1.184 +  else:
   1.185 +    if contents == old_contents:
   1.186 +      return
   1.187 +    os.unlink(file_name)
   1.188 +  open(file_name, 'w').write(contents)
   1.189 +
   1.190 +
   1.191 +def main(argv=None):
   1.192 +  if argv is None:
   1.193 +    argv = sys.argv
   1.194 +
   1.195 +  parser = optparse.OptionParser(usage="lastchange.py [options]")
   1.196 +  parser.add_option("-d", "--default-lastchange", metavar="FILE",
   1.197 +                    help="default last change input FILE")
   1.198 +  parser.add_option("-o", "--output", metavar="FILE",
   1.199 +                    help="write last change to FILE")
   1.200 +  parser.add_option("--revision-only", action='store_true',
   1.201 +                    help="just print the SVN revision number")
   1.202 +  opts, args = parser.parse_args(argv[1:])
   1.203 +
   1.204 +  out_file = opts.output
   1.205 +
   1.206 +  while len(args) and out_file is None:
   1.207 +    if out_file is None:
   1.208 +      out_file = args.pop(0)
   1.209 +  if args:
   1.210 +    sys.stderr.write('Unexpected arguments: %r\n\n' % args)
   1.211 +    parser.print_help()
   1.212 +    sys.exit(2)
   1.213 +
   1.214 +  version_info = FetchVersionInfo(opts.default_lastchange,
   1.215 +      os.path.dirname(sys.argv[0]))
   1.216 +
   1.217 +  if version_info.revision == None:
   1.218 +    version_info.revision = '0'
   1.219 +
   1.220 +  if opts.revision_only:
   1.221 +    print version_info.revision
   1.222 +  else:
   1.223 +    contents = "LASTCHANGE=%s\n" % version_info.revision
   1.224 +    if out_file:
   1.225 +      WriteIfChanged(out_file, contents)
   1.226 +    else:
   1.227 +      sys.stdout.write(contents)
   1.228 +
   1.229 +  return 0
   1.230 +
   1.231 +
   1.232 +if __name__ == '__main__':
   1.233 +  sys.exit(main())

mercurial