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

Side by Side Diff: tools/auto_bisect/source_control.py

Issue 418113003: Extract SourceControl to module; extract common methods to bisect_utils. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 4 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 | « tools/auto_bisect/bisect_utils.py ('k') | tools/bisect-perf-regression.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 # Copyright 2014 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 """This module contains the SourceControl class and related functions."""
6
7 import os
8
9 from . import bisect_utils
10
11 CROS_VERSION_PATTERN = 'new version number from %s'
12
13
14 def DetermineAndCreateSourceControl(opts):
15 """Attempts to determine the underlying source control workflow and returns
16 a SourceControl object.
17
18 Returns:
19 An instance of a SourceControl object, or None if the current workflow
20 is unsupported.
21 """
22 (output, _) = bisect_utils.RunGit(['rev-parse', '--is-inside-work-tree'])
23
24 if output.strip() == 'true':
25 return GitSourceControl(opts)
26
27 return None
28
29
30 class SourceControl(object):
shatch 2014/07/25 16:28:50 Not for this CL, but probably ok to kill the abstr
31 """SourceControl is an abstraction over the source control system."""
32
33 def __init__(self):
34 super(SourceControl, self).__init__()
35
36 def SyncToRevisionWithGClient(self, revision):
37 """Uses gclient to sync to the specified revision.
38
39 ie. gclient sync --revision <revision>
40
41 Args:
42 revision: The git SHA1 or svn CL (depending on workflow).
43
44 Returns:
45 The return code of the call.
46 """
47 return bisect_utils.RunGClient(['sync', '--verbose', '--reset', '--force',
48 '--delete_unversioned_trees', '--nohooks', '--revision', revision])
49
50 def SyncToRevisionWithRepo(self, timestamp):
51 """Uses repo to sync all the underlying git depots to the specified
52 time.
53
54 Args:
55 timestamp: The unix timestamp to sync to.
56
57 Returns:
58 The return code of the call.
59 """
60 return bisect_utils.RunRepoSyncAtTimestamp(timestamp)
61
62
63 class GitSourceControl(SourceControl):
64 """GitSourceControl is used to query the underlying source control."""
65
66 def __init__(self, opts):
67 super(GitSourceControl, self).__init__()
68 self.opts = opts
69
70 def IsGit(self):
71 return True
72
73 def GetRevisionList(self, revision_range_end, revision_range_start, cwd=None):
74 """Retrieves a list of revisions between |revision_range_start| and
75 |revision_range_end|.
76
77 Args:
78 revision_range_end: The SHA1 for the end of the range.
79 revision_range_start: The SHA1 for the beginning of the range.
80
81 Returns:
82 A list of the revisions between |revision_range_start| and
83 |revision_range_end| (inclusive).
84 """
85 revision_range = '%s..%s' % (revision_range_start, revision_range_end)
86 cmd = ['log', '--format=%H', '-10000', '--first-parent', revision_range]
87 log_output = bisect_utils.CheckRunGit(cmd, cwd=cwd)
88
89 revision_hash_list = log_output.split()
90 revision_hash_list.append(revision_range_start)
91
92 return revision_hash_list
93
94 def SyncToRevision(self, revision, sync_client=None):
95 """Syncs to the specified revision.
96
97 Args:
98 revision: The revision to sync to.
99 use_gclient: Specifies whether or not we should sync using gclient or
100 just use source control directly.
101
102 Returns:
103 True if successful.
104 """
105
106 if not sync_client:
107 results = bisect_utils.RunGit(['checkout', revision])[1]
108 elif sync_client == 'gclient':
109 results = self.SyncToRevisionWithGClient(revision)
110 elif sync_client == 'repo':
111 results = self.SyncToRevisionWithRepo(revision)
112
113 return not results
114
115 def ResolveToRevision(self, revision_to_check, depot, depot_deps_dict,
116 search, cwd=None):
117 """If an SVN revision is supplied, try to resolve it to a git SHA1.
118
119 Args:
120 revision_to_check: The user supplied revision string that may need to be
121 resolved to a git SHA1.
122 depot: The depot the revision_to_check is from.
123 depot_deps_dict: A dictionary with information about different depots.
124 search: The number of changelists to try if the first fails to resolve
125 to a git hash. If the value is negative, the function will search
126 backwards chronologically, otherwise it will search forward.
127
128 Returns:
129 A string containing a git SHA1 hash, otherwise None.
130 """
131 # Android-chrome is git only, so no need to resolve this to anything else.
132 if depot == 'android-chrome':
133 return revision_to_check
134
135 if depot != 'cros':
136 if not bisect_utils.IsStringInt(revision_to_check):
137 return revision_to_check
138
139 depot_svn = 'svn://svn.chromium.org/chrome/trunk/src'
140
141 if depot != 'chromium':
142 depot_svn = depot_deps_dict[depot]['svn']
143
144 svn_revision = int(revision_to_check)
145 git_revision = None
146
147 if search > 0:
148 search_range = xrange(svn_revision, svn_revision + search, 1)
149 else:
150 search_range = xrange(svn_revision, svn_revision + search, -1)
151
152 for i in search_range:
153 svn_pattern = 'git-svn-id: %s@%d' % (depot_svn, i)
154 cmd = ['log', '--format=%H', '-1', '--grep', svn_pattern,
155 'origin/master']
156
157 (log_output, return_code) = bisect_utils.RunGit(cmd, cwd=cwd)
158
159 assert not return_code, 'An error occurred while running'\
160 ' "git %s"' % ' '.join(cmd)
161
162 if not return_code:
163 log_output = log_output.strip()
164
165 if log_output:
166 git_revision = log_output
167
168 break
169
170 return git_revision
171 else:
172 if bisect_utils.IsStringInt(revision_to_check):
173 return int(revision_to_check)
174 else:
175 cwd = os.getcwd()
176 os.chdir(os.path.join(os.getcwd(), 'src', 'third_party',
177 'chromiumos-overlay'))
178 pattern = CROS_VERSION_PATTERN % revision_to_check
179 cmd = ['log', '--format=%ct', '-1', '--grep', pattern]
180
181 git_revision = None
182
183 log_output = bisect_utils.CheckRunGit(cmd, cwd=cwd)
184 if log_output:
185 git_revision = log_output
186 git_revision = int(log_output.strip())
187 os.chdir(cwd)
188
189 return git_revision
190
191 def IsInProperBranch(self):
192 """Confirms they're in the master branch for performing the bisection.
193 This is needed or gclient will fail to sync properly.
194
195 Returns:
196 True if the current branch on src is 'master'
197 """
198 cmd = ['rev-parse', '--abbrev-ref', 'HEAD']
199 log_output = bisect_utils.CheckRunGit(cmd)
200 log_output = log_output.strip()
201
202 return log_output == "master"
203
204 def SVNFindRev(self, revision, cwd=None):
205 """Maps directly to the 'git svn find-rev' command.
206
207 Args:
208 revision: The git SHA1 to use.
209
210 Returns:
211 An integer changelist #, otherwise None.
212 """
213
214 cmd = ['svn', 'find-rev', revision]
215
216 output = bisect_utils.CheckRunGit(cmd, cwd)
217 svn_revision = output.strip()
218
219 if bisect_utils.IsStringInt(svn_revision):
220 return int(svn_revision)
221
222 return None
223
224 def QueryRevisionInfo(self, revision, cwd=None):
225 """Gathers information on a particular revision, such as author's name,
226 email, subject, and date.
227
228 Args:
229 revision: Revision you want to gather information on.
230 Returns:
231 A dict in the following format:
232 {
233 'author': %s,
234 'email': %s,
235 'date': %s,
236 'subject': %s,
237 'body': %s,
238 }
239 """
240 commit_info = {}
241
242 formats = ['%cN', '%cE', '%s', '%cD', '%b']
243 targets = ['author', 'email', 'subject', 'date', 'body']
244
245 for i in xrange(len(formats)):
246 cmd = ['log', '--format=%s' % formats[i], '-1', revision]
247 output = bisect_utils.CheckRunGit(cmd, cwd=cwd)
248 commit_info[targets[i]] = output.rstrip()
249
250 return commit_info
251
252 def CheckoutFileAtRevision(self, file_name, revision, cwd=None):
253 """Performs a checkout on a file at the given revision.
254
255 Returns:
256 True if successful.
257 """
258 return not bisect_utils.RunGit(
259 ['checkout', revision, file_name], cwd=cwd)[1]
260
261 def RevertFileToHead(self, file_name):
262 """Unstages a file and returns it to HEAD.
263
264 Returns:
265 True if successful.
266 """
267 # Reset doesn't seem to return 0 on success.
268 bisect_utils.RunGit(['reset', 'HEAD', file_name])
269
270 return not bisect_utils.RunGit(['checkout', bisect_utils.FILE_DEPS_GIT])[1]
271
272 def QueryFileRevisionHistory(self, filename, revision_start, revision_end):
273 """Returns a list of commits that modified this file.
274
275 Args:
276 filename: Name of file.
277 revision_start: Start of revision range.
278 revision_end: End of revision range.
279
280 Returns:
281 Returns a list of commits that touched this file.
282 """
283 cmd = ['log', '--format=%H', '%s~1..%s' % (revision_start, revision_end),
284 filename]
285 output = bisect_utils.CheckRunGit(cmd)
286
287 return [o for o in output.split('\n') if o]
OLDNEW
« no previous file with comments | « tools/auto_bisect/bisect_utils.py ('k') | tools/bisect-perf-regression.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698