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."""
10 def IsInGitRepository():
11 output
, _
= bisect_utils
.RunGit(['rev-parse', '--is-inside-work-tree'])
12 return output
.strip() == 'true'
15 def GetRevisionList(end_revision_hash
, start_revision_hash
, cwd
=None):
16 """Retrieves a list of git commit hashes in a range.
19 end_revision_hash: The SHA1 for the end of the range, inclusive.
20 start_revision_hash: The SHA1 for the beginning of the range, inclusive.
23 A list of the git commit hashes in the range, in reverse time order --
24 that is, starting with |end_revision_hash|.
26 revision_range
= '%s..%s' % (start_revision_hash
, end_revision_hash
)
27 cmd
= ['log', '--format=%H', '-10000', '--first-parent', revision_range
]
28 log_output
= bisect_utils
.CheckRunGit(cmd
, cwd
=cwd
)
30 revision_hash_list
= log_output
.split()
31 revision_hash_list
.append(start_revision_hash
)
33 return revision_hash_list
36 def SyncToRevision(revision
, sync_client
=None):
37 """Syncs or checks out a revision based on sync_client argument.
40 revision: Git hash for the solutions with the format <repo>@rev.
41 E.g., "src@2ae43f...", "src/third_party/webkit@asr1234" etc.
42 sync_client: Syncs to revision when this is True otherwise checks out
46 True if sync or checkout is successful, False otherwise.
49 _
, return_code
= bisect_utils
.RunGit(['checkout', revision
])
50 elif sync_client
== 'gclient':
51 return_code
= bisect_utils
.RunGClientAndSync([revision
])
53 raise NotImplementedError('Unsupported sync_client: "%s"' % sync_client
)
55 return not return_code
58 def GetCurrentRevision(cwd
=None):
59 """Gets current revision of the given repository."""
60 return bisect_utils
.CheckRunGit(['rev-parse', 'HEAD'], cwd
=cwd
).strip()
63 def ResolveToRevision(revision_to_check
, depot
, depot_deps_dict
,
65 """Tries to resolve an SVN revision or commit position to a git SHA1.
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.
78 A string containing a git SHA1 hash, otherwise None.
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
)
97 search_range
= xrange(svn_revision
, svn_revision
+ search
, 1)
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()
113 git_revision
= log_output
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 position for the given git hash.
130 This function executes "git footer --position-num <git hash>" command to get
131 commit position the given revision.
134 git_revision: The git SHA1 to use.
135 cwd: Working directory to run the command from.
138 Git commit position as integer or None.
140 # Some of the respositories are pure git based, unlike other repositories
141 # they doesn't have commit position. e.g., skia, angle.
142 cmd
= ['footers', '--position-num', git_revision
]
143 output
, return_code
= bisect_utils
.RunGit(cmd
, cwd
)
145 commit_position
= output
.strip()
146 if bisect_utils
.IsStringInt(commit_position
):
147 return int(commit_position
)
151 def GetCommitTime(git_revision
, cwd
=None):
152 """Returns commit time for the given revision in UNIX timestamp."""
153 cmd
= ['log', '--format=%ct', '-1', git_revision
]
154 output
= bisect_utils
.CheckRunGit(cmd
, cwd
=cwd
)
158 def QueryRevisionInfo(revision
, cwd
=None):
159 """Gathers information on a particular revision, such as author's name,
160 email, subject, and date.
163 revision: Revision you want to gather information on; a git commit hash.
166 A dict in the following format:
177 formats
= ['%aN', '%aE', '%s', '%cD', '%b']
178 targets
= ['author', 'email', 'subject', 'date', 'body']
180 for i
in xrange(len(formats
)):
181 cmd
= ['log', '--format=%s' % formats
[i
], '-1', revision
]
182 output
= bisect_utils
.CheckRunGit(cmd
, cwd
=cwd
)
183 commit_info
[targets
[i
]] = output
.rstrip()
188 def CheckoutFileAtRevision(file_name
, revision
, cwd
=None):
189 """Performs a checkout on a file at the given revision.
194 command
= ['checkout', revision
, file_name
]
195 _
, return_code
= bisect_utils
.RunGit(command
, cwd
=cwd
)
196 return not return_code
199 def RevertFileToHead(file_name
):
200 """Un-stages a file and resets the file's state to HEAD.
205 # Reset doesn't seem to return 0 on success.
206 bisect_utils
.RunGit(['reset', 'HEAD', file_name
])
207 _
, return_code
= bisect_utils
.RunGit(
208 ['checkout', bisect_utils
.FILE_DEPS_GIT
])
209 return not return_code
212 def QueryFileRevisionHistory(filename
, revision_start
, revision_end
):
213 """Returns a list of commits that modified this file.
216 filename: Name of file.
217 revision_start: Start of revision range (inclusive).
218 revision_end: End of revision range.
221 Returns a list of commits that touched this file.
226 '%s~1..%s' % (revision_start
, revision_end
),
230 output
= bisect_utils
.CheckRunGit(cmd
)
231 lines
= output
.split('\n')
232 return [o
for o
in lines
if o
]