1c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)# Copyright (c) 2012 The Chromium Authors. All rights reserved.
2c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)# Use of this source code is governed by a BSD-style license that can be
3c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)# found in the LICENSE file.
4c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)"""Small utility library of python functions used during SDK building.
6c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)"""
7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import os
91320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport re
10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import sys
11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)# pylint: disable=E0602
13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)# Reuse last change utility code.
15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)SRC_DIR = os.path.dirname(os.path.dirname(os.path.dirname(SCRIPT_DIR)))
17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)sys.path.append(os.path.join(SRC_DIR, 'build/util'))
18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import lastchange
19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)# Location of chrome's version file.
22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)VERSION_PATH = os.path.join(SRC_DIR, 'chrome', 'VERSION')
23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)def ChromeVersion():
26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  '''Extract chrome version from src/chrome/VERSION + svn.
27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  Returns:
29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    Chrome version string or trunk + svn rev.
30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  '''
311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  info = FetchGitCommitPosition()
321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if info.url == 'git':
331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    _, ref, revision = ParseCommitPosition(info.revision)
341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if ref == 'refs/heads/master':
351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      return 'trunk.%s' % revision
361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return ChromeVersionNoTrunk()
37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)def ChromeVersionNoTrunk():
40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  '''Extract the chrome version from src/chrome/VERSION.
41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  Ignore whether this is a trunk build.
42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  Returns:
44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    Chrome version string.
45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  '''
46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  exec(open(VERSION_PATH).read())
47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return '%s.%s.%s.%s' % (MAJOR, MINOR, BUILD, PATCH)
48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)def ChromeMajorVersion():
51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  '''Extract chrome major version from src/chrome/VERSION.
52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
53c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  Returns:
54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    Chrome major version.
55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  '''
56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  exec(open(VERSION_PATH, 'r').read())
57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return str(MAJOR)
58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)def ChromeRevision():
61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  '''Extract chrome revision from svn.
62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci     Now that the Chrome source-of-truth is git, this will return the
641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci     Cr-Commit-Position instead. Fortunately, this value is equal to the SVN
651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci     revision if one exists.
661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
67c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  Returns:
68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    The Chrome revision as a string. e.g. "12345"
69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  '''
701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  version = FetchGitCommitPosition()
711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return ParseCommitPosition(version.revision)[2]
721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccidef ChromeCommitPosition():
751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  '''Return the full git sha and commit position.
761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  Returns:
781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    A value like:
791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    0178d4831bd36b5fb9ff477f03dc43b11626a6dc-refs/heads/master@{#292238}
801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  '''
811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return FetchGitCommitPosition().revision
821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
83eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
84eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochdef NaClRevision():
85eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  '''Extract NaCl revision from svn.
86eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
87eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  Returns:
88eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    The NaCl revision as a string. e.g. "12345"
89eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  '''
90eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  nacl_dir = os.path.join(SRC_DIR, 'native_client')
911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return lastchange.FetchVersionInfo(None, nacl_dir, 'native_client').revision
921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccidef FetchGitCommitPosition(directory=None):
951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  '''Return the "commit-position" of the Chromium git repo. This should be
961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  equivalent to the SVN revision if one exists.
971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  '''
981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  SEARCH_LIMIT = 100
991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  for i in xrange(SEARCH_LIMIT):
1001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    cmd = ['show', '-s', '--format=%H%n%B', 'HEAD~%d' % i]
1011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    proc = lastchange.RunGitCommand(directory, cmd)
1021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if not proc:
1031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      break
1041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    output = proc.communicate()[0]
1061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if not (proc.returncode == 0 and output):
1071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      break
1081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    lines = output.splitlines()
1101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    # First line is the hash.
1121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    hsh = lines[0]
1131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if not re.match(r'[0-9a-fA-F]+', hsh):
1141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      break
1151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    for line in reversed(lines):
1171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      if line.startswith('Cr-Commit-Position:'):
1181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        pos = line.rsplit()[-1].strip()
1191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        return lastchange.VersionInfo('git', '%s-%s' % (hsh, pos))
1201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  raise Exception('Unable to fetch a Git Commit Position.')
1221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccidef ParseCommitPosition(commit_position):
1261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  '''Parse a Chrome commit position into its components.
1271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  Given a commit position like:
1291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    0178d4831bd36b5fb9ff477f03dc43b11626a6dc-refs/heads/master@{#292238}
1301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  Returns:
1311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    ("0178d4831bd36b5fb9ff477f03dc43b11626a6dc", "refs/heads/master", "292238")
1321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  '''
1331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  m = re.match(r'([0-9a-fA-F]+)(?:-([^@]+)@{#(\d+)})?', commit_position)
1341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if m:
1351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return m.groups()
1361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return None
137