1# Copyright (c) 2012 The Chromium Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5"""Small utility library of python functions used during SDK building.
6"""
7
8import os
9import re
10import sys
11
12# pylint: disable=E0602
13
14# Reuse last change utility code.
15SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
16SRC_DIR = os.path.dirname(os.path.dirname(os.path.dirname(SCRIPT_DIR)))
17sys.path.append(os.path.join(SRC_DIR, 'build/util'))
18import lastchange
19
20
21# Location of chrome's version file.
22VERSION_PATH = os.path.join(SRC_DIR, 'chrome', 'VERSION')
23
24
25def ChromeVersion():
26  '''Extract chrome version from src/chrome/VERSION + svn.
27
28  Returns:
29    Chrome version string or trunk + svn rev.
30  '''
31  info = FetchGitCommitPosition()
32  if info.url == 'git':
33    _, ref, revision = ParseCommitPosition(info.revision)
34    if ref == 'refs/heads/master':
35      return 'trunk.%s' % revision
36  return ChromeVersionNoTrunk()
37
38
39def ChromeVersionNoTrunk():
40  '''Extract the chrome version from src/chrome/VERSION.
41  Ignore whether this is a trunk build.
42
43  Returns:
44    Chrome version string.
45  '''
46  exec(open(VERSION_PATH).read())
47  return '%s.%s.%s.%s' % (MAJOR, MINOR, BUILD, PATCH)
48
49
50def ChromeMajorVersion():
51  '''Extract chrome major version from src/chrome/VERSION.
52
53  Returns:
54    Chrome major version.
55  '''
56  exec(open(VERSION_PATH, 'r').read())
57  return str(MAJOR)
58
59
60def ChromeRevision():
61  '''Extract chrome revision from svn.
62
63     Now that the Chrome source-of-truth is git, this will return the
64     Cr-Commit-Position instead. Fortunately, this value is equal to the SVN
65     revision if one exists.
66
67  Returns:
68    The Chrome revision as a string. e.g. "12345"
69  '''
70  version = FetchGitCommitPosition()
71  return ParseCommitPosition(version.revision)[2]
72
73
74def ChromeCommitPosition():
75  '''Return the full git sha and commit position.
76
77  Returns:
78    A value like:
79    0178d4831bd36b5fb9ff477f03dc43b11626a6dc-refs/heads/master@{#292238}
80  '''
81  return FetchGitCommitPosition().revision
82
83
84def NaClRevision():
85  '''Extract NaCl revision from svn.
86
87  Returns:
88    The NaCl revision as a string. e.g. "12345"
89  '''
90  nacl_dir = os.path.join(SRC_DIR, 'native_client')
91  return lastchange.FetchVersionInfo(None, nacl_dir, 'native_client').revision
92
93
94def FetchGitCommitPosition(directory=None):
95  '''Return the "commit-position" of the Chromium git repo. This should be
96  equivalent to the SVN revision if one exists.
97  '''
98  SEARCH_LIMIT = 100
99  for i in xrange(SEARCH_LIMIT):
100    cmd = ['show', '-s', '--format=%H%n%B', 'HEAD~%d' % i]
101    proc = lastchange.RunGitCommand(directory, cmd)
102    if not proc:
103      break
104
105    output = proc.communicate()[0]
106    if not (proc.returncode == 0 and output):
107      break
108
109    lines = output.splitlines()
110
111    # First line is the hash.
112    hsh = lines[0]
113    if not re.match(r'[0-9a-fA-F]+', hsh):
114      break
115
116    for line in reversed(lines):
117      if line.startswith('Cr-Commit-Position:'):
118        pos = line.rsplit()[-1].strip()
119        return lastchange.VersionInfo('git', '%s-%s' % (hsh, pos))
120
121  raise Exception('Unable to fetch a Git Commit Position.')
122
123
124
125def ParseCommitPosition(commit_position):
126  '''Parse a Chrome commit position into its components.
127
128  Given a commit position like:
129    0178d4831bd36b5fb9ff477f03dc43b11626a6dc-refs/heads/master@{#292238}
130  Returns:
131    ("0178d4831bd36b5fb9ff477f03dc43b11626a6dc", "refs/heads/master", "292238")
132  '''
133  m = re.match(r'([0-9a-fA-F]+)(?:-([^@]+)@{#(\d+)})?', commit_position)
134  if m:
135    return m.groups()
136  return None
137