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

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: x Created 9 years, 10 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, agent):
evanm 2011/02/25 19:06:59 Can you add docs for this like the other functions
Denis Lagno 2011/03/01 12:33:53 Done.
63 command.insert(0, 'git');
evanm 2011/02/25 19:06:59 Rather than modifying the caller's array, it might
Denis Lagno 2011/03/01 12:33:53 Done.
64 # Force shell usage under cygwin & win32. This is a workaround for
65 # mysterious loss of cwd while invoking cygwin's git.
66 # We can't just pass shell=True to Popen, as under win32 this will
67 # cause CMD to be used, while we explicitly want a cygwin shell.
68 if sys.platform in ('cygwin', 'win32'):
69 command = ['sh', '-c', ' '.join(command)]
70 try:
71 proc = subprocess.Popen(command,
72 stdout=subprocess.PIPE,
73 stderr=subprocess.PIPE,
74 cwd=directory)
75 return agent(proc)
evanm 2011/02/25 19:06:59 Why do this continuation-passing style rather than
Denis Lagno 2011/03/01 12:33:53 Done.
76 except OSError:
77 return None
78
79
80 def FetchGitRevision(directory):
81 """
82 Fetch the Git hash for a given directory.
83
84 Errors are swallowed.
85
86 Returns:
87 a VersionInfo object or None on error.
88 """
89 git_command = ['rev-parse', 'HEAD']
90 def agent(proc):
91 output = proc.communicate()[0].strip()
92 if proc.returncode == 0 and output:
93 return VersionInfo('git', 'git', output[:7])
94 return None
95 return RunGitCommand(directory, git_command, agent)
96
97
98 def IsGitSVN(directory):
99 """
100 Checks whether git-svn has been set up.
101
102 Errors are swallowed.
103
104 Returns:
105 whether git-svn has been set up.
106 """
107 # To test whether git-svn has been set up, query the config for any
108 # svn-related configuration. This command exits with an error code
109 # if there aren't any matches, so ignore its output.
110 git_command = ['config', '--get-regexp', '^svn']
111 return RunGitCommand(directory, git_command, lambda proc: (proc.wait() == 0))
112
113
114 def FetchGitSVNURL(directory):
115 """
116 Fetch URL of SVN repository bound to git.
117
118 Errors are swallowed.
119
120 Returns:
121 SVN URL.
122 """
123 git_command = ['svn', 'info', '--url']
evanm 2011/02/25 19:06:59 This will hang the build if the user has a git clo
Denis Lagno 2011/03/01 12:33:53 this function is never called if IsGitSvn() return
124 def agent(proc):
125 output = proc.communicate()[0].strip()
126 if proc.returncode == 0:
127 return output
128 return None
129 return RunGitCommand(directory, git_command, agent)
130
131
132 def LookupGitSVNRevision(directory, depth):
133 """
134 Fetch the Git-SVN identifier for the local tree.
135 Parses first |depth| commit messages.
136
137 Errors are swallowed.
138 """
139 if not IsGitSVN(directory):
140 return None
141 git_re = re.compile('^\s*git-svn-id:\s+(\S+)@(\d+)', re.M)
142 git_command = ['log', '-' + str(depth)]
143 def agent(proc):
144 for line in proc.stdout:
145 match = git_re.search(line)
146 if match:
147 id = match.group(2)
148 if id:
149 proc.stdout.close() # Cut pipe for fast exit.
150 return id
151 return None
152 return RunGitCommand(directory, git_command, agent)
153
154
155 def IsGitSVNDirty(directory):
156 """
157 Checks whether our git-svn tree contains clean trunk or some branch.
158
159 Errors are swallowed.
160 """
161 # For git branches the last commit message is either
162 # some local commit or a merge.
163 return LookupGitSVNRevision(directory, 1) is None
164
165
166 def FetchGitSVNRevision(directory):
167 """
168 Fetch the Git-SVN identifier for the local tree.
169
170 Errors are swallowed.
171 """
172 # We assume that at least first 999 commit messages contain svn evidence.
173 revision = LookupGitSVNRevision(directory, 999)
174 if not revision:
175 return None
176 if IsGitSVNDirty(directory):
177 revision = revision + '-dirty'
178 return VersionInfo(FetchGitSVNURL(directory), 'git-svn', revision)
179
180
89 def FetchVersionInfo(default_lastchange, directory=None): 181 def FetchVersionInfo(default_lastchange, directory=None):
90 """ 182 """
91 Returns the last change (in the form of a branch, revision tuple), 183 Returns the last change (in the form of a branch, revision tuple),
92 from some appropriate revision control system. 184 from some appropriate revision control system.
93 """ 185 """
94 version_info = FetchSVNRevision(directory) or FetchGitRevision(directory) 186 version_info = (FetchSVNRevision(directory) or
187 FetchGitSVNRevision(directory) or FetchGitRevision(directory))
95 if not version_info: 188 if not version_info:
96 if default_lastchange and os.path.exists(default_lastchange): 189 if default_lastchange and os.path.exists(default_lastchange):
97 revision = open(default_lastchange, 'r').read().strip() 190 revision = open(default_lastchange, 'r').read().strip()
98 version_info = VersionInfo(None, None, revision) 191 version_info = VersionInfo(None, None, revision)
99 else: 192 else:
100 version_info = VersionInfo('unknown', '', '0') 193 version_info = VersionInfo('unknown', '', '0')
101 return version_info 194 return version_info
102 195
103 196
104 def WriteIfChanged(file_name, contents): 197 def WriteIfChanged(file_name, contents):
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
149 if out_file: 242 if out_file:
150 WriteIfChanged(out_file, contents) 243 WriteIfChanged(out_file, contents)
151 else: 244 else:
152 sys.stdout.write(contents) 245 sys.stdout.write(contents)
153 246
154 return 0 247 return 0
155 248
156 249
157 if __name__ == '__main__': 250 if __name__ == '__main__':
158 sys.exit(main()) 251 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