OLD | NEW |
1 # Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. | 1 # Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. |
2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
4 | 4 |
5 """SCM-specific utility classes.""" | 5 """SCM-specific utility classes.""" |
6 | 6 |
7 import glob | 7 import glob |
8 import os | 8 import os |
9 import re | 9 import re |
10 import shutil | 10 import shutil |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
71 | 71 |
72 Returns an array of (status, file) tuples.""" | 72 Returns an array of (status, file) tuples.""" |
73 command = ["diff", "--name-status", "-r", "%s.." % upstream_branch] | 73 command = ["diff", "--name-status", "-r", "%s.." % upstream_branch] |
74 if not files: | 74 if not files: |
75 pass | 75 pass |
76 elif isinstance(files, basestring): | 76 elif isinstance(files, basestring): |
77 command.append(files) | 77 command.append(files) |
78 else: | 78 else: |
79 command.extend(files) | 79 command.extend(files) |
80 | 80 |
81 status = GIT.Capture(command).rstrip() | 81 status = GIT.Capture(command)[0].rstrip() |
82 results = [] | 82 results = [] |
83 if status: | 83 if status: |
84 for statusline in status.split('\n'): | 84 for statusline in status.split('\n'): |
85 m = re.match('^(\w)\t(.+)$', statusline) | 85 m = re.match('^(\w)\t(.+)$', statusline) |
86 if not m: | 86 if not m: |
87 raise Exception("status currently unsupported: %s" % statusline) | 87 raise Exception("status currently unsupported: %s" % statusline) |
88 results.append(('%s ' % m.group(1), m.group(2))) | 88 results.append(('%s ' % m.group(1), m.group(2))) |
89 return results | 89 return results |
90 | 90 |
91 @staticmethod | 91 @staticmethod |
(...skipping 27 matching lines...) Expand all Loading... |
119 print_messages, | 119 print_messages, |
120 print_stdout, | 120 print_stdout, |
121 filter=filter) | 121 filter=filter) |
122 | 122 |
123 @staticmethod | 123 @staticmethod |
124 def GetEmail(repo_root): | 124 def GetEmail(repo_root): |
125 """Retrieves the user email address if known.""" | 125 """Retrieves the user email address if known.""" |
126 # We could want to look at the svn cred when it has a svn remote but it | 126 # We could want to look at the svn cred when it has a svn remote but it |
127 # should be fine for now, users should simply configure their git settings. | 127 # should be fine for now, users should simply configure their git settings. |
128 return GIT.Capture(['config', 'user.email'], | 128 return GIT.Capture(['config', 'user.email'], |
129 repo_root, error_ok=True).strip() | 129 repo_root, error_ok=True)[0].strip() |
130 | 130 |
131 @staticmethod | 131 @staticmethod |
132 def ShortBranchName(branch): | 132 def ShortBranchName(branch): |
133 """Converts a name like 'refs/heads/foo' to just 'foo'.""" | 133 """Converts a name like 'refs/heads/foo' to just 'foo'.""" |
134 return branch.replace('refs/heads/', '') | 134 return branch.replace('refs/heads/', '') |
135 | 135 |
136 @staticmethod | 136 @staticmethod |
137 def GetBranchRef(cwd): | 137 def GetBranchRef(cwd): |
138 """Returns the full branch reference, e.g. 'refs/heads/master'.""" | 138 """Returns the full branch reference, e.g. 'refs/heads/master'.""" |
139 return GIT.Capture(['symbolic-ref', 'HEAD'], cwd).strip() | 139 return GIT.Capture(['symbolic-ref', 'HEAD'], cwd)[0].strip() |
140 | 140 |
141 @staticmethod | 141 @staticmethod |
142 def GetBranch(cwd): | 142 def GetBranch(cwd): |
143 """Returns the short branch name, e.g. 'master'.""" | 143 """Returns the short branch name, e.g. 'master'.""" |
144 return GIT.ShortBranchName(GIT.GetBranchRef(cwd)) | 144 return GIT.ShortBranchName(GIT.GetBranchRef(cwd)) |
145 | 145 |
146 @staticmethod | 146 @staticmethod |
147 def IsGitSvn(cwd): | 147 def IsGitSvn(cwd): |
148 """Returns true if this repo looks like it's using git-svn.""" | 148 """Returns true if this repo looks like it's using git-svn.""" |
149 # If you have any "svn-remote.*" config keys, we think you're using svn. | 149 # If you have any "svn-remote.*" config keys, we think you're using svn. |
(...skipping 10 matching lines...) Expand all Loading... |
160 # Strategy: | 160 # Strategy: |
161 # 1) find all git-svn branches and note their svn URLs. | 161 # 1) find all git-svn branches and note their svn URLs. |
162 # 2) iterate through our branch history and match up the URLs. | 162 # 2) iterate through our branch history and match up the URLs. |
163 | 163 |
164 # regexp matching the git-svn line that contains the URL. | 164 # regexp matching the git-svn line that contains the URL. |
165 git_svn_re = re.compile(r'^\s*git-svn-id: (\S+)@', re.MULTILINE) | 165 git_svn_re = re.compile(r'^\s*git-svn-id: (\S+)@', re.MULTILINE) |
166 | 166 |
167 # Get the refname and svn url for all refs/remotes/*. | 167 # Get the refname and svn url for all refs/remotes/*. |
168 remotes = GIT.Capture( | 168 remotes = GIT.Capture( |
169 ['for-each-ref', '--format=%(refname)', 'refs/remotes'], | 169 ['for-each-ref', '--format=%(refname)', 'refs/remotes'], |
170 cwd).splitlines() | 170 cwd)[0].splitlines() |
171 svn_refs = {} | 171 svn_refs = {} |
172 for ref in remotes: | 172 for ref in remotes: |
173 match = git_svn_re.search( | 173 match = git_svn_re.search( |
174 GIT.Capture(['cat-file', '-p', ref], cwd)) | 174 GIT.Capture(['cat-file', '-p', ref], cwd)[0]) |
175 if match: | 175 if match: |
176 svn_refs[match.group(1)] = ref | 176 svn_refs[match.group(1)] = ref |
177 | 177 |
178 svn_branch = '' | 178 svn_branch = '' |
179 if len(svn_refs) == 1: | 179 if len(svn_refs) == 1: |
180 # Only one svn branch exists -- seems like a good candidate. | 180 # Only one svn branch exists -- seems like a good candidate. |
181 svn_branch = svn_refs.values()[0] | 181 svn_branch = svn_refs.values()[0] |
182 elif len(svn_refs) > 1: | 182 elif len(svn_refs) > 1: |
183 # We have more than one remote branch available. We don't | 183 # We have more than one remote branch available. We don't |
184 # want to go through all of history, so read a line from the | 184 # want to go through all of history, so read a line from the |
(...skipping 14 matching lines...) Expand all Loading... |
199 @staticmethod | 199 @staticmethod |
200 def FetchUpstreamTuple(cwd): | 200 def FetchUpstreamTuple(cwd): |
201 """Returns a tuple containg remote and remote ref, | 201 """Returns a tuple containg remote and remote ref, |
202 e.g. 'origin', 'refs/heads/master' | 202 e.g. 'origin', 'refs/heads/master' |
203 """ | 203 """ |
204 remote = '.' | 204 remote = '.' |
205 branch = GIT.GetBranch(cwd) | 205 branch = GIT.GetBranch(cwd) |
206 upstream_branch = None | 206 upstream_branch = None |
207 upstream_branch = GIT.Capture( | 207 upstream_branch = GIT.Capture( |
208 ['config', 'branch.%s.merge' % branch], in_directory=cwd, | 208 ['config', 'branch.%s.merge' % branch], in_directory=cwd, |
209 error_ok=True).strip() | 209 error_ok=True)[0].strip() |
210 if upstream_branch: | 210 if upstream_branch: |
211 remote = GIT.Capture( | 211 remote = GIT.Capture( |
212 ['config', 'branch.%s.remote' % branch], | 212 ['config', 'branch.%s.remote' % branch], |
213 in_directory=cwd, error_ok=True).strip() | 213 in_directory=cwd, error_ok=True)[0].strip() |
214 else: | 214 else: |
215 # Fall back on trying a git-svn upstream branch. | 215 # Fall back on trying a git-svn upstream branch. |
216 if GIT.IsGitSvn(cwd): | 216 if GIT.IsGitSvn(cwd): |
217 upstream_branch = GIT.GetSVNBranch(cwd) | 217 upstream_branch = GIT.GetSVNBranch(cwd) |
218 return remote, upstream_branch | 218 return remote, upstream_branch |
219 | 219 |
220 @staticmethod | 220 @staticmethod |
221 def GetUpstream(cwd): | 221 def GetUpstream(cwd): |
222 """Gets the current branch's upstream branch.""" | 222 """Gets the current branch's upstream branch.""" |
223 remote, upstream_branch = GIT.FetchUpstreamTuple(cwd) | 223 remote, upstream_branch = GIT.FetchUpstreamTuple(cwd) |
(...skipping 10 matching lines...) Expand all Loading... |
234 files, usually in the prospect to apply the patch for a try job.""" | 234 files, usually in the prospect to apply the patch for a try job.""" |
235 if not branch: | 235 if not branch: |
236 branch = GIT.GetUpstream(cwd) | 236 branch = GIT.GetUpstream(cwd) |
237 command = ['diff-tree', '-p', '--no-prefix', branch, branch_head] | 237 command = ['diff-tree', '-p', '--no-prefix', branch, branch_head] |
238 if not full_move: | 238 if not full_move: |
239 command.append('-C') | 239 command.append('-C') |
240 # TODO(maruel): --binary support. | 240 # TODO(maruel): --binary support. |
241 if files: | 241 if files: |
242 command.append('--') | 242 command.append('--') |
243 command.extend(files) | 243 command.extend(files) |
244 diff = GIT.Capture(command, cwd).splitlines(True) | 244 diff = GIT.Capture(command, cwd)[0].splitlines(True) |
245 for i in range(len(diff)): | 245 for i in range(len(diff)): |
246 # In the case of added files, replace /dev/null with the path to the | 246 # In the case of added files, replace /dev/null with the path to the |
247 # file being added. | 247 # file being added. |
248 if diff[i].startswith('--- /dev/null'): | 248 if diff[i].startswith('--- /dev/null'): |
249 diff[i] = '--- %s' % diff[i+1][4:] | 249 diff[i] = '--- %s' % diff[i+1][4:] |
250 return ''.join(diff) | 250 return ''.join(diff) |
251 | 251 |
252 @staticmethod | 252 @staticmethod |
253 def GetDifferentFiles(cwd, branch=None, branch_head='HEAD'): | 253 def GetDifferentFiles(cwd, branch=None, branch_head='HEAD'): |
254 """Returns the list of modified files between two branches.""" | 254 """Returns the list of modified files between two branches.""" |
255 if not branch: | 255 if not branch: |
256 branch = GIT.GetUpstream(cwd) | 256 branch = GIT.GetUpstream(cwd) |
257 command = ['diff', '--name-only', branch, branch_head] | 257 command = ['diff', '--name-only', branch, branch_head] |
258 return GIT.Capture(command, cwd).splitlines(False) | 258 return GIT.Capture(command, cwd)[0].splitlines(False) |
259 | 259 |
260 @staticmethod | 260 @staticmethod |
261 def GetPatchName(cwd): | 261 def GetPatchName(cwd): |
262 """Constructs a name for this patch.""" | 262 """Constructs a name for this patch.""" |
263 short_sha = GIT.Capture(['rev-parse', '--short=4', 'HEAD'], cwd).strip() | 263 short_sha = GIT.Capture(['rev-parse', '--short=4', 'HEAD'], cwd)[0].strip() |
264 return "%s-%s" % (GIT.GetBranch(cwd), short_sha) | 264 return "%s-%s" % (GIT.GetBranch(cwd), short_sha) |
265 | 265 |
266 @staticmethod | 266 @staticmethod |
267 def GetCheckoutRoot(path): | 267 def GetCheckoutRoot(path): |
268 """Returns the top level directory of a git checkout as an absolute path. | 268 """Returns the top level directory of a git checkout as an absolute path. |
269 """ | 269 """ |
270 root = GIT.Capture(['rev-parse', '--show-cdup'], path).strip() | 270 root = GIT.Capture(['rev-parse', '--show-cdup'], path)[0].strip() |
271 return os.path.abspath(os.path.join(path, root)) | 271 return os.path.abspath(os.path.join(path, root)) |
272 | 272 |
273 | 273 |
274 class SVN(object): | 274 class SVN(object): |
275 COMMAND = "svn" | 275 COMMAND = "svn" |
276 | 276 |
277 @staticmethod | 277 @staticmethod |
278 def Run(args, in_directory): | 278 def Run(args, in_directory): |
279 """Runs svn, sending output to stdout. | 279 """Runs svn, sending output to stdout. |
280 | 280 |
(...skipping 448 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
729 if not cur_dir_repo_root: | 729 if not cur_dir_repo_root: |
730 return None | 730 return None |
731 | 731 |
732 while True: | 732 while True: |
733 parent = os.path.dirname(directory) | 733 parent = os.path.dirname(directory) |
734 if (SVN.CaptureInfo(parent, print_error=False).get( | 734 if (SVN.CaptureInfo(parent, print_error=False).get( |
735 "Repository Root") != cur_dir_repo_root): | 735 "Repository Root") != cur_dir_repo_root): |
736 break | 736 break |
737 directory = parent | 737 directory = parent |
738 return GetCasedPath(directory) | 738 return GetCasedPath(directory) |
OLD | NEW |