Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(218)

Side by Side Diff: build/util/lastchange.py

Issue 7104106: Unify the version string to be displayed on "About Chromium" dialog. (Closed) Base URL: http://git.chromium.org/git/chromium.git@trunk
Patch Set: Skip CreateVersionString() for NACL_WIN64 Created 9 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | chrome/app/nibs/About.xib » ('j') | chrome/app/nibs/About.xib » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 # Copyright (c) 2011 The Chromium Authors. All rights reserved. 2 # Copyright (c) 2011 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be 3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file. 4 # found in the LICENSE file.
5 5
6 """ 6 """
7 lastchange.py -- Chromium revision fetching utility. 7 lastchange.py -- Chromium revision fetching utility.
8 """ 8 """
9 9
10 import re 10 import re
11 import optparse 11 import optparse
12 import os 12 import os
13 import subprocess 13 import subprocess
14 import sys 14 import sys
15 15
16 _GIT_SVN_ID_REGEX = re.compile(r'.*git-svn-id:\s*([^@]*)@([0-9]+)', re.DOTALL)
17
16 class VersionInfo(object): 18 class VersionInfo(object):
17 def __init__(self, url, root, revision): 19 def __init__(self, url, root, revision):
18 self.url = url 20 self.url = url
19 self.root = root 21 self.root = root
20 self.revision = revision 22 self.revision = revision
21 23
22 24
23 def FetchSVNRevision(directory): 25 def FetchSVNRevision(directory):
24 """ 26 """
25 Fetch the Subversion branch and revision for a given directory. 27 Fetch the Subversion branch and revision for a given directory.
26 28
27 Errors are swallowed. 29 Errors are swallowed.
28 30
29 Returns: 31 Returns:
30 a VersionInfo object or None on error. 32 A VersionInfo object or None on error.
31 """ 33 """
32 try: 34 try:
33 proc = subprocess.Popen(['svn', 'info'], 35 proc = subprocess.Popen(['svn', 'info'],
34 stdout=subprocess.PIPE, 36 stdout=subprocess.PIPE,
35 stderr=subprocess.PIPE, 37 stderr=subprocess.PIPE,
36 cwd=directory, 38 cwd=directory,
37 shell=(sys.platform=='win32')) 39 shell=(sys.platform=='win32'))
38 except OSError: 40 except OSError:
39 # command is apparently either not installed or not executable. 41 # command is apparently either not installed or not executable.
40 return None 42 return None
(...skipping 18 matching lines...) Expand all
59 return VersionInfo(url, root, revision) 61 return VersionInfo(url, root, revision)
60 62
61 63
62 def RunGitCommand(directory, command): 64 def RunGitCommand(directory, command):
63 """ 65 """
64 Launches git subcommand. 66 Launches git subcommand.
65 67
66 Errors are swallowed. 68 Errors are swallowed.
67 69
68 Returns: 70 Returns:
69 process object or None. 71 A process object or None.
70 """ 72 """
71 command = ['git'] + command 73 command = ['git'] + command
72 # Force shell usage under cygwin & win32. This is a workaround for 74 # Force shell usage under cygwin & win32. This is a workaround for
73 # mysterious loss of cwd while invoking cygwin's git. 75 # mysterious loss of cwd while invoking cygwin's git.
74 # We can't just pass shell=True to Popen, as under win32 this will 76 # We can't just pass shell=True to Popen, as under win32 this will
75 # cause CMD to be used, while we explicitly want a cygwin shell. 77 # cause CMD to be used, while we explicitly want a cygwin shell.
76 if sys.platform in ('cygwin', 'win32'): 78 if sys.platform in ('cygwin', 'win32'):
77 command = ['sh', '-c', ' '.join(command)] 79 command = ['sh', '-c', ' '.join(command)]
78 try: 80 try:
79 proc = subprocess.Popen(command, 81 proc = subprocess.Popen(command,
80 stdout=subprocess.PIPE, 82 stdout=subprocess.PIPE,
81 stderr=subprocess.PIPE, 83 stderr=subprocess.PIPE,
82 cwd=directory) 84 cwd=directory)
83 return proc 85 return proc
84 except OSError: 86 except OSError:
85 return None 87 return None
86 88
87 89
88 def FetchGitRevision(directory): 90 def FetchGitRevision(directory):
89 """ 91 """
90 Fetch the Git hash for a given directory. 92 Fetch the Git hash for a given directory.
91 93
92 Errors are swallowed. 94 Errors are swallowed.
93 95
94 Returns: 96 Returns:
95 a VersionInfo object or None on error. 97 A VersionInfo object or None on error.
96 """ 98 """
97 proc = RunGitCommand(directory, ['rev-parse', 'HEAD']) 99 proc = RunGitCommand(directory, ['rev-parse', 'HEAD'])
98 if proc: 100 if proc:
99 output = proc.communicate()[0].strip() 101 output = proc.communicate()[0].strip()
100 if proc.returncode == 0 and output: 102 if proc.returncode == 0 and output:
101 return VersionInfo('git', 'git', output[:7]) 103 return VersionInfo('git', 'git', output[:7])
102 return None 104 return None
103 105
104 106
105 def IsGitSVN(directory): 107 def FetchGitSVNRoot(directory):
106 """ 108 """
107 Checks whether git-svn has been set up. 109 Fetch the SVN root repository through Git.
108 110
109 Errors are swallowed. 111 Errors are swallowed.
110 112
111 Returns: 113 Returns:
112 whether git-svn has been set up. 114 The SVN root repository or 'git-svn' on error.
113 """ 115 """
114 # To test whether git-svn has been set up, query the config for any 116 proc = RunGitCommand(directory,
115 # svn-related configuration. This command exits with an error code 117 ['config', '--get-regexp', '^svn-remote.svn.url$'])
116 # if there aren't any matches, so ignore its output.
117 proc = RunGitCommand(directory, ['config', '--get-regexp', '^svn'])
118 if proc: 118 if proc:
119 return (proc.wait() == 0) 119 output = proc.communicate()[0].strip()
120 return False 120 if proc.returncode == 0 and output:
121 # Zero return code implies presence of requested configuration variable.
122 # Its value is second (last) field of output.
123 match = re.search(r'\S+$', output)
124 if match:
125 return match.group(0)
126 return 'git-svn'
121 127
122 128
123 def FetchGitSVNURL(directory): 129 def FetchGitSVNURLAndRevision(directory):
124 """ 130 """
125 Fetch URL of SVN repository bound to git. 131 Fetch the Subversion URL and revision through Git.
126 132
127 Errors are swallowed. 133 Errors are swallowed.
128 134
129 Returns: 135 Returns:
130 SVN URL. 136 A tuple containing the Subversion URL and revision.
131 """ 137 """
132 if IsGitSVN(directory): 138 proc = RunGitCommand(directory, ['log', '-1',
133 proc = RunGitCommand(directory, ['svn', 'info', '--url']) 139 '--grep=git-svn-id', '--format=%b'])
134 if proc:
135 output = proc.communicate()[0].strip()
136 if proc.returncode == 0:
137 match = re.search(r'^\w+://.*$', output, re.M)
138 if match:
139 return match.group(0)
140 return ''
141
142
143 def FetchGitSVNRoot(directory):
144 """
145 Fetch root of SVN repository bound to git.
146
147 Errors are swallowed.
148
149 Returns:
150 SVN root repository.
151 """
152 if IsGitSVN(directory):
153 git_command = ['config', '--get-regexp', '^svn-remote.svn.url$']
154 proc = RunGitCommand(directory, git_command)
155 if proc:
156 output = proc.communicate()[0].strip()
157 if proc.returncode == 0:
158 # Zero return code implies presence of requested configuration variable.
159 # Its value is second (last) field of output.
160 match = re.search(r'\S+$', output)
161 if match:
162 return match.group(0)
163 return ''
164
165
166 def LookupGitSVNRevision(directory, depth):
167 """
168 Fetch the Git-SVN identifier for the local tree.
169 Parses first |depth| commit messages.
170
171 Errors are swallowed.
172 """
173 if not IsGitSVN(directory):
174 return None
175 git_re = re.compile(r'^\s*git-svn-id:\s+(\S+)@(\d+)')
176 proc = RunGitCommand(directory, ['log', '-' + str(depth)])
177 if proc: 140 if proc:
178 for line in proc.stdout: 141 output = proc.communicate()[0].strip()
179 match = git_re.match(line) 142 if proc.returncode == 0 and output:
143 # Extract the latest SVN revision and the SVN URL.
144 # The target line is the last "git-svn-id: ..." line like this:
145 # git-svn-id: svn://svn.chromium.org/chrome/trunk/src@85528 0039d316....
146 match = _GIT_SVN_ID_REGEX.search(output)
180 if match: 147 if match:
181 id = match.group(2) 148 return match.group(1), match.group(2)
182 if id: 149 return None, None
183 proc.stdout.close() # Cut pipe for fast exit.
184 return id
185 return None
186 150
187 151
188 def IsGitSVNDirty(directory): 152 def IsGitSVNDirty(directory):
189 """ 153 """
190 Checks whether our git-svn tree contains clean trunk or some branch. 154 Checks whether our git-svn tree contains clean trunk or any local changes.
191 155
192 Errors are swallowed. 156 Errors are swallowed.
193 """ 157 """
194 # For git branches the last commit message is either 158 proc = RunGitCommand(directory, ['log', '-1'])
195 # some local commit or a merge. 159 if proc:
196 return LookupGitSVNRevision(directory, 1) is None 160 output = proc.communicate()[0].strip()
161 if proc.returncode == 0 and output:
162 # Extract the latest SVN revision and the SVN URL.
163 # The target line is the last "git-svn-id: ..." line like this:
164 # git-svn-id: svn://svn.chromium.org/chrome/trunk/src@85528 0039d316....
165 match = _GIT_SVN_ID_REGEX.search(output)
166 if match:
167 # Check if there are any local uncommitted changes.
168 proc = RunGitCommand(directory, ['checkout'])
169 if proc:
170 output = proc.communicate()[0].strip()
171 if proc.returncode == 0 and not output:
172 return False
173 return True
197 174
198 175
199 def FetchGitSVNRevision(directory): 176 def FetchGitSVNRevision(directory):
200 """ 177 """
201 Fetch the Git-SVN identifier for the local tree. 178 Fetch the Git-SVN identifier for the local tree.
202 179
203 Errors are swallowed. 180 Errors are swallowed.
204 """ 181 """
205 # We assume that at least first 999 commit messages contain svn evidence. 182 url, revision = FetchGitSVNURLAndRevision(directory)
206 revision = LookupGitSVNRevision(directory, 999) 183 if url and revision:
207 if not revision: 184 root = FetchGitSVNRoot(directory)
208 return None 185 if IsGitSVNDirty(directory):
209 if IsGitSVNDirty(directory): 186 revision = revision + '-dirty'
210 revision = revision + '-dirty' 187 return VersionInfo(url, root, revision)
211 url = FetchGitSVNURL(directory) 188 return None
212 root = FetchGitSVNRoot(directory)
213 return VersionInfo(url, root, revision)
214 189
215 190
216 def FetchVersionInfo(default_lastchange, directory=None): 191 def FetchVersionInfo(default_lastchange, directory=None):
217 """ 192 """
218 Returns the last change (in the form of a branch, revision tuple), 193 Returns the last change (in the form of a branch, revision tuple),
219 from some appropriate revision control system. 194 from some appropriate revision control system.
220 """ 195 """
221 version_info = (FetchSVNRevision(directory) or 196 version_info = (FetchSVNRevision(directory) or
222 FetchGitSVNRevision(directory) or FetchGitRevision(directory)) 197 FetchGitSVNRevision(directory) or FetchGitRevision(directory))
223 if not version_info: 198 if not version_info:
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
277 if out_file: 252 if out_file:
278 WriteIfChanged(out_file, contents) 253 WriteIfChanged(out_file, contents)
279 else: 254 else:
280 sys.stdout.write(contents) 255 sys.stdout.write(contents)
281 256
282 return 0 257 return 0
283 258
284 259
285 if __name__ == '__main__': 260 if __name__ == '__main__':
286 sys.exit(main()) 261 sys.exit(main())
OLDNEW
« no previous file with comments | « no previous file | chrome/app/nibs/About.xib » ('j') | chrome/app/nibs/About.xib » ('J')

Powered by Google App Engine
This is Rietveld 408576698