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

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

Issue 6474044: Try harder to dig git-svn revision. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: tweak Created 9 years, 9 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 | no next file » | no next file with comments »
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) 2010 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 optparse 11 import optparse
11 import os 12 import os
12 import subprocess 13 import subprocess
13 import sys 14 import sys
14 15
15 class VersionInfo(object): 16 class VersionInfo(object):
16 def __init__(self, url, root, revision): 17 def __init__(self, url, root, revision):
17 self.url = url 18 self.url = url
18 self.root = root 19 self.root = root
19 self.revision = revision 20 self.revision = revision
20 21
21 def FetchGitRevision(directory):
22 """
23 Fetch the Git hash for the a given directory.
24
25 Errors are swallowed.
26
27 Returns:
28 a VersionInfo object or None on error.
29 """
30 # Force shell usage under cygwin & win32. This is a workaround for
31 # mysterious loss of cwd while invoking cygwin's git.
32 # We can't just pass shell=True to Popen, as under win32 this will
33 # cause CMD to be used, while we explicitly want a cygwin shell.
34 command = ['git', 'rev-parse', 'HEAD']
35 if sys.platform in ('cygwin', 'win32'):
36 command = ['sh', '-c', ' '.join(command)]
37 try:
38 proc = subprocess.Popen(command,
39 stdout=subprocess.PIPE,
40 stderr=subprocess.PIPE,
41 cwd=directory)
42 except OSError:
43 return None
44 output = proc.communicate()[0].strip()
45 if proc.returncode == 0 and output:
46 return VersionInfo('git', 'git', output[:7])
47 return None
48
49 22
50 def FetchSVNRevision(directory): 23 def FetchSVNRevision(directory):
51 """ 24 """
52 Fetch the Subversion branch and revision for the a given directory. 25 Fetch the Subversion branch and revision for a given directory.
53 26
54 Errors are swallowed. 27 Errors are swallowed.
55 28
56 Returns: 29 Returns:
57 a VersionInfo object or None on error. 30 a VersionInfo object or None on error.
58 """ 31 """
59 try: 32 try:
60 proc = subprocess.Popen(['svn', 'info'], 33 proc = subprocess.Popen(['svn', 'info'],
61 stdout=subprocess.PIPE, 34 stdout=subprocess.PIPE,
62 stderr=subprocess.PIPE, 35 stderr=subprocess.PIPE,
(...skipping 16 matching lines...) Expand all
79 try: 52 try:
80 url = attrs['URL'] 53 url = attrs['URL']
81 root = attrs['Repository Root'] 54 root = attrs['Repository Root']
82 revision = attrs['Revision'] 55 revision = attrs['Revision']
83 except KeyError: 56 except KeyError:
84 return None 57 return None
85 58
86 return VersionInfo(url, root, revision) 59 return VersionInfo(url, root, revision)
87 60
88 61
62 def RunGitCommand(directory, command):
63 """
64 Launches git subcommand.
65
66 Errors are swallowed.
67
68 Returns:
69 process object or None.
70 """
71 command = ['git'] + command
72 # Force shell usage under cygwin & win32. This is a workaround for
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
75 # cause CMD to be used, while we explicitly want a cygwin shell.
76 if sys.platform in ('cygwin', 'win32'):
77 command = ['sh', '-c', ' '.join(command)]
78 try:
79 proc = subprocess.Popen(command,
80 stdout=subprocess.PIPE,
81 stderr=subprocess.PIPE,
82 cwd=directory)
83 return proc
84 except OSError:
85 return None
86
87
88 def FetchGitRevision(directory):
89 """
90 Fetch the Git hash for a given directory.
91
92 Errors are swallowed.
93
94 Returns:
95 a VersionInfo object or None on error.
96 """
97 proc = RunGitCommand(directory, ['rev-parse', 'HEAD'])
98 if proc:
99 output = proc.communicate()[0].strip()
100 if proc.returncode == 0 and output:
101 return VersionInfo('git', 'git', output[:7])
102 return None
103
104
105 def IsGitSVN(directory):
106 """
107 Checks whether git-svn has been set up.
108
109 Errors are swallowed.
110
111 Returns:
112 whether git-svn has been set up.
113 """
114 # To test whether git-svn has been set up, query the config for any
115 # svn-related configuration. This command exits with an error code
116 # if there aren't any matches, so ignore its output.
117 proc = RunGitCommand(directory, ['config', '--get-regexp', '^svn'])
118 return (proc.wait() == 0)
119
120
121 def FetchGitSVNURL(directory):
122 """
123 Fetch URL of SVN repository bound to git.
124
125 Errors are swallowed.
126
127 Returns:
128 SVN URL.
129 """
130 if not IsGitSVN(directory):
131 return None
132 proc = RunGitCommand(directory, ['svn', 'info', '--url'])
133 if proc:
134 output = proc.communicate()[0].strip()
135 if proc.returncode == 0:
136 return output
137 return None
138
139
140 def LookupGitSVNRevision(directory, depth):
141 """
142 Fetch the Git-SVN identifier for the local tree.
143 Parses first |depth| commit messages.
144
145 Errors are swallowed.
146 """
147 if not IsGitSVN(directory):
148 return None
149 git_re = re.compile('^\s*git-svn-id:\s+(\S+)@(\d+)', re.M)
150 proc = RunGitCommand(directory, ['log', '-' + str(depth)])
151 if proc:
152 for line in proc.stdout:
153 match = git_re.search(line)
154 if match:
155 id = match.group(2)
156 if id:
157 proc.stdout.close() # Cut pipe for fast exit.
158 return id
159 return None
160
161
162 def IsGitSVNDirty(directory):
163 """
164 Checks whether our git-svn tree contains clean trunk or some branch.
165
166 Errors are swallowed.
167 """
168 # For git branches the last commit message is either
169 # some local commit or a merge.
170 return LookupGitSVNRevision(directory, 1) is None
Evan Martin 2011/03/02 00:03:59 I guess elsewhere people call local changes "dirty
Denis Lagno 2011/03/02 13:16:19 Current code should mark any local changes as "dir
171
172
173 def FetchGitSVNRevision(directory):
174 """
175 Fetch the Git-SVN identifier for the local tree.
176
177 Errors are swallowed.
178 """
179 # We assume that at least first 999 commit messages contain svn evidence.
180 revision = LookupGitSVNRevision(directory, 999)
181 if not revision:
182 return None
183 if IsGitSVNDirty(directory):
184 revision = revision + '-dirty'
185 return VersionInfo(FetchGitSVNURL(directory), 'git-svn', revision)
186
187
89 def FetchVersionInfo(default_lastchange, directory=None): 188 def FetchVersionInfo(default_lastchange, directory=None):
90 """ 189 """
91 Returns the last change (in the form of a branch, revision tuple), 190 Returns the last change (in the form of a branch, revision tuple),
92 from some appropriate revision control system. 191 from some appropriate revision control system.
93 """ 192 """
94 version_info = FetchSVNRevision(directory) or FetchGitRevision(directory) 193 version_info = (FetchSVNRevision(directory) or
194 FetchGitSVNRevision(directory) or FetchGitRevision(directory))
95 if not version_info: 195 if not version_info:
96 if default_lastchange and os.path.exists(default_lastchange): 196 if default_lastchange and os.path.exists(default_lastchange):
97 revision = open(default_lastchange, 'r').read().strip() 197 revision = open(default_lastchange, 'r').read().strip()
98 version_info = VersionInfo(None, None, revision) 198 version_info = VersionInfo(None, None, revision)
99 else: 199 else:
100 version_info = VersionInfo('unknown', '', '0') 200 version_info = VersionInfo('unknown', '', '0')
101 return version_info 201 return version_info
102 202
103 203
104 def WriteIfChanged(file_name, contents): 204 def WriteIfChanged(file_name, contents):
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
149 if out_file: 249 if out_file:
150 WriteIfChanged(out_file, contents) 250 WriteIfChanged(out_file, contents)
151 else: 251 else:
152 sys.stdout.write(contents) 252 sys.stdout.write(contents)
153 253
154 return 0 254 return 0
155 255
156 256
157 if __name__ == '__main__': 257 if __name__ == '__main__':
158 sys.exit(main()) 258 sys.exit(main())
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698