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

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: Rebased with the patch of issue 7249003 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/tools/build/win/version.bat » ('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 class VersionInfo(object): 16 class VersionInfo(object):
17 def __init__(self, url, root, revision): 17 def __init__(self, url, root, revision):
18 self.url = url 18 self.url = url
19 self.root = root 19 self.root = root
20 self.revision = revision 20 self.revision = revision
21 21
22 22
23 def FetchSVNRevision(directory): 23 def FetchSVNRevision(directory):
24 """ 24 """
25 Fetch the Subversion branch and revision for a given directory. 25 Fetch the Subversion branch and revision for a given directory.
26 26
27 Errors are swallowed. 27 Errors are swallowed.
28 28
29 Returns: 29 Returns:
30 a VersionInfo object or None on error. 30 A VersionInfo object or None on error.
31 """ 31 """
32 try: 32 try:
33 proc = subprocess.Popen(['svn', 'info'], 33 proc = subprocess.Popen(['svn', 'info'],
34 stdout=subprocess.PIPE, 34 stdout=subprocess.PIPE,
35 stderr=subprocess.PIPE, 35 stderr=subprocess.PIPE,
36 cwd=directory, 36 cwd=directory,
37 shell=(sys.platform=='win32')) 37 shell=(sys.platform=='win32'))
38 except OSError: 38 except OSError:
39 # command is apparently either not installed or not executable. 39 # command is apparently either not installed or not executable.
40 return None 40 return None
(...skipping 18 matching lines...) Expand all
59 return VersionInfo(url, root, revision) 59 return VersionInfo(url, root, revision)
60 60
61 61
62 def RunGitCommand(directory, command): 62 def RunGitCommand(directory, command):
63 """ 63 """
64 Launches git subcommand. 64 Launches git subcommand.
65 65
66 Errors are swallowed. 66 Errors are swallowed.
67 67
68 Returns: 68 Returns:
69 process object or None. 69 A process object or None.
70 """ 70 """
71 command = ['git'] + command 71 command = ['git'] + command
72 # Force shell usage under cygwin & win32. This is a workaround for 72 # Force shell usage under cygwin & win32. This is a workaround for
73 # mysterious loss of cwd while invoking cygwin's git. 73 # mysterious loss of cwd while invoking cygwin's git.
74 # We can't just pass shell=True to Popen, as under win32 this will 74 # 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. 75 # cause CMD to be used, while we explicitly want a cygwin shell.
76 if sys.platform in ('cygwin', 'win32'): 76 if sys.platform in ('cygwin', 'win32'):
77 command = ['sh', '-c', ' '.join(command)] 77 command = ['sh', '-c', ' '.join(command)]
78 try: 78 try:
79 proc = subprocess.Popen(command, 79 proc = subprocess.Popen(command,
80 stdout=subprocess.PIPE, 80 stdout=subprocess.PIPE,
81 stderr=subprocess.PIPE, 81 stderr=subprocess.PIPE,
82 cwd=directory) 82 cwd=directory)
83 return proc 83 return proc
84 except OSError: 84 except OSError:
85 return None 85 return None
86 86
87 87
88 def FetchGitRevision(directory): 88 def FetchGitRevision(directory):
89 """ 89 """
90 Fetch the Git hash for a given directory. 90 Fetch the Git hash for a given directory.
91 91
92 Errors are swallowed. 92 Errors are swallowed.
93 93
94 Returns: 94 Returns:
95 a VersionInfo object or None on error. 95 A VersionInfo object or None on error.
96 """ 96 """
97 proc = RunGitCommand(directory, ['rev-parse', 'HEAD']) 97 proc = RunGitCommand(directory, ['rev-parse', 'HEAD'])
98 if proc: 98 if proc:
99 output = proc.communicate()[0].strip() 99 output = proc.communicate()[0].strip()
100 if proc.returncode == 0 and output: 100 if proc.returncode == 0 and output:
101 return VersionInfo('git', 'git', output[:7]) 101 return VersionInfo('git', 'git', output[:7])
102 return None 102 return None
103 103
104 104
105 def IsGitSVN(directory): 105 def FetchGitSVNRoot(directory):
106 """ 106 """
107 Checks whether git-svn has been set up. 107 Fetch the SVN root repository through Git.
108 108
109 Errors are swallowed. 109 Errors are swallowed.
110 110
111 Returns: 111 Returns:
112 whether git-svn has been set up. 112 The SVN root repository or 'git-svn' on error.
113 """ 113 """
114 # To test whether git-svn has been set up, query the config for any 114 proc = RunGitCommand(directory,
115 # svn-related configuration. This command exits with an error code 115 ['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: 116 if proc:
119 return (proc.wait() == 0) 117 output = proc.communicate()[0].strip()
120 return False 118 if proc.returncode == 0 and output:
119 # Zero return code implies presence of requested configuration variable.
120 # Its value is second (last) field of output.
121 match = re.search(r'\S+$', output)
122 if match:
123 return match.group(0)
124 return 'git-svn'
121 125
122 126
123 def FetchGitSVNURL(directory): 127 def FetchGitSVNURLAndRevision(directory):
124 """ 128 """
125 Fetch URL of SVN repository bound to git. 129 Fetch the Subversion URL and revision through Git.
126 130
127 Errors are swallowed. 131 Errors are swallowed.
128 132
129 Returns: 133 Returns:
130 SVN URL. 134 A tuple containing the Subversion URL and revision.
131 """ 135 """
132 if IsGitSVN(directory): 136 proc = RunGitCommand(directory, ['log', '-1',
133 proc = RunGitCommand(directory, ['svn', 'info', '--url']) 137 '--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: 138 if proc:
178 for line in proc.stdout: 139 output = proc.communicate()[0].strip()
179 match = git_re.match(line) 140 if proc.returncode == 0 and output:
141 # Extract the latest SVN revision and the SVN URL.
142 # The target line is the last "git-svn-id: ..." line like this:
143 # git-svn-id: svn://svn.chromium.org/chrome/trunk/src@85528 0039d316....
144 match = re.search(r'.*git-svn-id:\s*([^@]*)@([0-9]+)', output, re.DOTALL)
180 if match: 145 if match:
181 id = match.group(2) 146 return match.group(1), match.group(2)
182 if id: 147 return None, None
183 proc.stdout.close() # Cut pipe for fast exit.
184 return id
185 return None
186 148
187 149
188 def IsGitSVNDirty(directory): 150 def IsGitSVNDirty(directory):
189 """ 151 """
190 Checks whether our git-svn tree contains clean trunk or some branch. 152 Checks whether our git-svn tree contains clean trunk or any local changes.
191 153
192 Errors are swallowed. 154 Errors are swallowed.
193 """ 155 """
194 # For git branches the last commit message is either 156 proc = RunGitCommand(directory, ['log', '-1'])
195 # some local commit or a merge. 157 if proc:
196 return LookupGitSVNRevision(directory, 1) is None 158 output = proc.communicate()[0].strip()
159 if proc.returncode == 0 and output:
160 # Extract the latest SVN revision and the SVN URL.
161 # The target line is the last "git-svn-id: ..." line like this:
162 # git-svn-id: svn://svn.chromium.org/chrome/trunk/src@85528 0039d316....
163 match = re.search(r'.*git-svn-id:\s*([^@]*)@([0-9]+)', output, re.DOTALL)
tony 2011/06/27 18:26:07 Nit: Please move this regular expression out into
haraken1 2011/06/28 00:11:09 Done.
164 if match:
165 # Check if there are any local uncommitted changes.
166 proc = RunGitCommand(directory, ['checkout'])
167 if proc:
168 output = proc.communicate()[0].strip()
169 if proc.returncode == 0 and not output:
170 return False
171 return True
197 172
198 173
199 def FetchGitSVNRevision(directory): 174 def FetchGitSVNRevision(directory):
200 """ 175 """
201 Fetch the Git-SVN identifier for the local tree. 176 Fetch the Git-SVN identifier for the local tree.
202 177
203 Errors are swallowed. 178 Errors are swallowed.
204 """ 179 """
205 # We assume that at least first 999 commit messages contain svn evidence. 180 url, revision = FetchGitSVNURLAndRevision(directory)
206 revision = LookupGitSVNRevision(directory, 999) 181 if url and revision:
207 if not revision: 182 root = FetchGitSVNRoot(directory)
208 return None 183 if IsGitSVNDirty(directory):
209 if IsGitSVNDirty(directory): 184 revision = revision + '-dirty'
210 revision = revision + '-dirty' 185 return VersionInfo(url, root, revision)
211 url = FetchGitSVNURL(directory) 186 return None
212 root = FetchGitSVNRoot(directory)
213 return VersionInfo(url, root, revision)
214 187
215 188
216 def FetchVersionInfo(default_lastchange, directory=None): 189 def FetchVersionInfo(default_lastchange, directory=None):
217 """ 190 """
218 Returns the last change (in the form of a branch, revision tuple), 191 Returns the last change (in the form of a branch, revision tuple),
219 from some appropriate revision control system. 192 from some appropriate revision control system.
220 """ 193 """
221 version_info = (FetchSVNRevision(directory) or 194 version_info = (FetchSVNRevision(directory) or
222 FetchGitSVNRevision(directory) or FetchGitRevision(directory)) 195 FetchGitSVNRevision(directory) or FetchGitRevision(directory))
223 if not version_info: 196 if not version_info:
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
277 if out_file: 250 if out_file:
278 WriteIfChanged(out_file, contents) 251 WriteIfChanged(out_file, contents)
279 else: 252 else:
280 sys.stdout.write(contents) 253 sys.stdout.write(contents)
281 254
282 return 0 255 return 0
283 256
284 257
285 if __name__ == '__main__': 258 if __name__ == '__main__':
286 sys.exit(main()) 259 sys.exit(main())
OLDNEW
« no previous file with comments | « no previous file | chrome/app/nibs/About.xib » ('j') | chrome/tools/build/win/version.bat » ('J')

Powered by Google App Engine
This is Rietveld 408576698