Add TabModel#closeAllTabs(boolean allowDelegation, boolean uponExit) and TabModelSele...
[chromium-blink-merge.git] / tools / auto_bisect / source_control.py
blobe1d7dad7014026cf087566e0393641b328cde51d
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.
5 """This module contains functions for performing source control operations."""
7 import bisect_utils
10 def IsInGitRepository():
11 output, _ = bisect_utils.RunGit(['rev-parse', '--is-inside-work-tree'])
12 return output.strip() == 'true'
15 def SyncToRevisionWithGClient(revision):
16 """Uses gclient to sync to the specified revision.
18 This is like running gclient sync --revision <revision>.
20 Args:
21 revision: A git SHA1 hash or SVN revision number (depending on workflow).
23 Returns:
24 The return code of the call.
25 """
26 return bisect_utils.RunGClient(
27 ['sync', '--verbose', '--reset', '--force',
28 '--delete_unversioned_trees', '--nohooks', '--revision', revision])
31 def GetRevisionList(end_revision_hash, start_revision_hash, cwd=None):
32 """Retrieves a list of git commit hashes in a range.
34 Args:
35 end_revision_hash: The SHA1 for the end of the range, inclusive.
36 start_revision_hash: The SHA1 for the beginning of the range, inclusive.
38 Returns:
39 A list of the git commit hashes in the range, in reverse time order --
40 that is, starting with |end_revision_hash|.
41 """
42 revision_range = '%s..%s' % (start_revision_hash, end_revision_hash)
43 cmd = ['log', '--format=%H', '-10000', '--first-parent', revision_range]
44 log_output = bisect_utils.CheckRunGit(cmd, cwd=cwd)
46 revision_hash_list = log_output.split()
47 revision_hash_list.append(start_revision_hash)
49 return revision_hash_list
52 def SyncToRevision(revision, sync_client=None):
53 if not sync_client:
54 _, return_code = bisect_utils.RunGit(['checkout', revision])
55 elif sync_client == 'gclient':
56 return_code = SyncToRevisionWithGClient(revision)
57 else:
58 raise NotImplementedError('Unsupported sync_client: "%s"' % sync_client)
60 return not return_code
63 def ResolveToRevision(revision_to_check, depot, depot_deps_dict,
64 search, cwd=None):
65 """Tries to resolve an SVN revision or commit position to a git SHA1.
67 Args:
68 revision_to_check: The user supplied revision string that may need to be
69 resolved to a git commit hash. This may be an SVN revision, git commit
70 position, or a git commit hash.
71 depot: The depot (dependency repository) that |revision_to_check| is from.
72 depot_deps_dict: A dictionary with information about different depots.
73 search: How many revisions forward or backward to search. If the value is
74 negative, the function will search backwards chronologically, otherwise
75 it will search forward.
77 Returns:
78 A string containing a git SHA1 hash, otherwise None.
79 """
80 # Android-chrome is git only, so no need to resolve this to anything else.
81 if depot == 'android-chrome':
82 return revision_to_check
84 # If the given revision can't be parsed as an integer, then it may already
85 # be a git commit hash.
86 if not bisect_utils.IsStringInt(revision_to_check):
87 return revision_to_check
89 depot_svn = 'svn://svn.chromium.org/chrome/trunk/src'
91 if depot != 'chromium':
92 depot_svn = depot_deps_dict[depot]['svn']
93 svn_revision = int(revision_to_check)
94 git_revision = None
96 if search > 0:
97 search_range = xrange(svn_revision, svn_revision + search, 1)
98 else:
99 search_range = xrange(svn_revision, svn_revision + search, -1)
101 for i in search_range:
102 # NOTE: Checking for the git-svn-id footer is for backwards compatibility.
103 # When we can assume that all the revisions we care about are from after
104 # git commit positions started getting added, we don't need to check this.
105 svn_pattern = 'git-svn-id: %s@%d' % (depot_svn, i)
106 commit_position_pattern = '^Cr-Commit-Position: .*@{#%d}' % i
107 cmd = ['log', '--format=%H', '-1', '--grep', svn_pattern,
108 '--grep', commit_position_pattern, 'origin/master']
109 log_output = bisect_utils.CheckRunGit(cmd, cwd=cwd)
110 log_output = log_output.strip()
112 if log_output:
113 git_revision = log_output
114 break
116 return git_revision
119 def IsInProperBranch():
120 """Checks whether the current branch is "master"."""
121 cmd = ['rev-parse', '--abbrev-ref', 'HEAD']
122 log_output = bisect_utils.CheckRunGit(cmd)
123 log_output = log_output.strip()
124 return log_output == 'master'
127 def GetCommitPosition(git_revision, cwd=None):
128 """Finds git commit postion for the given git hash.
130 This function executes "git footer --position-num <git hash>" command to get
131 commit position the given revision.
133 Args:
134 git_revision: The git SHA1 to use.
135 cwd: Working directory to run the command from.
137 Returns:
138 Git commit position as integer or None.
140 cmd = ['footers', '--position-num', git_revision]
141 output = bisect_utils.CheckRunGit(cmd, cwd)
142 commit_position = output.strip()
144 if bisect_utils.IsStringInt(commit_position):
145 return int(commit_position)
147 return None
150 def QueryRevisionInfo(revision, cwd=None):
151 """Gathers information on a particular revision, such as author's name,
152 email, subject, and date.
154 Args:
155 revision: Revision you want to gather information on; a git commit hash.
157 Returns:
158 A dict in the following format:
160 'author': %s,
161 'email': %s,
162 'date': %s,
163 'subject': %s,
164 'body': %s,
167 commit_info = {}
169 formats = ['%aN', '%aE', '%s', '%cD', '%b']
170 targets = ['author', 'email', 'subject', 'date', 'body']
172 for i in xrange(len(formats)):
173 cmd = ['log', '--format=%s' % formats[i], '-1', revision]
174 output = bisect_utils.CheckRunGit(cmd, cwd=cwd)
175 commit_info[targets[i]] = output.rstrip()
177 return commit_info
180 def CheckoutFileAtRevision(file_name, revision, cwd=None):
181 """Performs a checkout on a file at the given revision.
183 Returns:
184 True if successful.
186 command = ['checkout', revision, file_name]
187 _, return_code = bisect_utils.RunGit(command, cwd=cwd)
188 return not return_code
191 def RevertFileToHead(file_name):
192 """Un-stages a file and resets the file's state to HEAD.
194 Returns:
195 True if successful.
197 # Reset doesn't seem to return 0 on success.
198 bisect_utils.RunGit(['reset', 'HEAD', file_name])
199 _, return_code = bisect_utils.RunGit(
200 ['checkout', bisect_utils.FILE_DEPS_GIT])
201 return not return_code
204 def QueryFileRevisionHistory(filename, revision_start, revision_end):
205 """Returns a list of commits that modified this file.
207 Args:
208 filename: Name of file.
209 revision_start: Start of revision range (inclusive).
210 revision_end: End of revision range.
212 Returns:
213 Returns a list of commits that touched this file.
215 cmd = [
216 'log',
217 '--format=%H',
218 '%s~1..%s' % (revision_start, revision_end),
219 '--',
220 filename,
222 output = bisect_utils.CheckRunGit(cmd)
223 lines = output.split('\n')
224 return [o for o in lines if o]