OLD | NEW |
1 # Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 # Copyright (c) 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 """Gclient-specific SCM-specific operations.""" | 5 """Gclient-specific SCM-specific operations.""" |
6 | 6 |
7 import logging | 7 import logging |
8 import os | 8 import os |
9 import posixpath | 9 import posixpath |
10 import re | 10 import re |
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
172 if options.revision: | 172 if options.revision: |
173 # Override the revision number. | 173 # Override the revision number. |
174 revision = str(options.revision) | 174 revision = str(options.revision) |
175 if revision: | 175 if revision: |
176 rev_str = ' at %s' % revision | 176 rev_str = ' at %s' % revision |
177 | 177 |
178 if options.verbose: | 178 if options.verbose: |
179 print("\n_____ %s%s" % (self.relpath, rev_str)) | 179 print("\n_____ %s%s" % (self.relpath, rev_str)) |
180 | 180 |
181 if not os.path.exists(self.checkout_path): | 181 if not os.path.exists(self.checkout_path): |
182 self._Run(['clone', url, self.checkout_path], | 182 # Cloning |
183 cwd=self._root_dir, redirect_stdout=False) | 183 for i in range(3): |
| 184 try: |
| 185 self._Run(['clone', url, self.checkout_path], |
| 186 cwd=self._root_dir, redirect_stdout=False) |
| 187 break |
| 188 except gclient_utils.Error, e: |
| 189 # TODO(maruel): Hackish, should be fixed by moving _Run() to |
| 190 # CheckCall(). |
| 191 # Too bad we don't have access to the actual output. |
| 192 # We should check for "transfer closed with NNN bytes remaining to |
| 193 # read". In the meantime, just make sure .git exists. |
| 194 if (e.args[0] == 'git command clone returned 128' and |
| 195 os.path.exists(os.path.join(self.checkout_path, '.git'))): |
| 196 print str(e) |
| 197 print "Retrying..." |
| 198 continue |
| 199 raise e |
| 200 |
184 if revision: | 201 if revision: |
185 self._Run(['reset', '--hard', revision], redirect_stdout=False) | 202 self._Run(['reset', '--hard', revision], redirect_stdout=False) |
186 files = self._Run(['ls-files']).split() | 203 files = self._Run(['ls-files']).split() |
187 file_list.extend([os.path.join(self.checkout_path, f) for f in files]) | 204 file_list.extend([os.path.join(self.checkout_path, f) for f in files]) |
188 return | 205 return |
189 | 206 |
190 if not os.path.exists(os.path.join(self.checkout_path, '.git')): | 207 if not os.path.exists(os.path.join(self.checkout_path, '.git')): |
191 raise gclient_utils.Error('\n____ %s%s\n' | 208 raise gclient_utils.Error('\n____ %s%s\n' |
192 '\tPath is not a git repo. No .git dir.\n' | 209 '\tPath is not a git repo. No .git dir.\n' |
193 '\tTo resolve:\n' | 210 '\tTo resolve:\n' |
194 '\t\trm -rf %s\n' | 211 '\t\trm -rf %s\n' |
195 '\tAnd run gclient sync again\n' | 212 '\tAnd run gclient sync again\n' |
196 % (self.relpath, rev_str, self.relpath)) | 213 % (self.relpath, rev_str, self.relpath)) |
197 | 214 |
198 new_base = 'origin' | 215 new_base = 'origin' |
199 if revision: | 216 if revision: |
200 new_base = revision | 217 new_base = revision |
201 cur_branch = self._GetCurrentBranch() | 218 cur_branch = self._GetCurrentBranch() |
202 | 219 |
203 # Check if we are in a rebase conflict | 220 # Check if we are in a rebase conflict |
204 if cur_branch is None: | 221 if cur_branch is None: |
205 raise gclient_utils.Error('\n____ %s%s\n' | 222 raise gclient_utils.Error('\n____ %s%s\n' |
206 '\tAlready in a conflict, i.e. (no branch).\n' | 223 '\tAlready in a conflict, i.e. (no branch).\n' |
207 '\tFix the conflict and run gclient again.\n' | 224 '\tFix the conflict and run gclient again.\n' |
208 '\tOr to abort run:\n\t\tgit-rebase --abort\n' | 225 '\tOr to abort run:\n\t\tgit-rebase --abort\n' |
209 '\tSee man git-rebase for details.\n' | 226 '\tSee man git-rebase for details.\n' |
210 % (self.relpath, rev_str)) | 227 % (self.relpath, rev_str)) |
211 | 228 |
| 229 # TODO(maruel): Do we need to do an automatic retry here? Probably overkill |
212 merge_base = self._Run(['merge-base', 'HEAD', new_base]) | 230 merge_base = self._Run(['merge-base', 'HEAD', new_base]) |
213 self._Run(['remote', 'update'], redirect_stdout=False) | 231 self._Run(['remote', 'update'], redirect_stdout=False) |
214 files = self._Run(['diff', new_base, '--name-only']).split() | 232 files = self._Run(['diff', new_base, '--name-only']).split() |
215 file_list.extend([os.path.join(self.checkout_path, f) for f in files]) | 233 file_list.extend([os.path.join(self.checkout_path, f) for f in files]) |
216 if options.force: | 234 if options.force: |
217 self._Run(['reset', '--hard', merge_base], redirect_stdout=False) | 235 self._Run(['reset', '--hard', merge_base], redirect_stdout=False) |
218 self._Run(['rebase', '-v', '--onto', new_base, merge_base, cur_branch], | 236 try: |
219 redirect_stdout=False, checkrc=False) | 237 self._Run(['rebase', '-v', '--onto', new_base, merge_base, cur_branch], |
| 238 redirect_stdout=False) |
| 239 except gclient_utils.Error: |
| 240 pass |
220 | 241 |
221 # If the rebase generated a conflict, abort and ask user to fix | 242 # If the rebase generated a conflict, abort and ask user to fix |
222 if self._GetCurrentBranch() is None: | 243 if self._GetCurrentBranch() is None: |
223 raise gclient_utils.Error('\n____ %s%s\n' | 244 raise gclient_utils.Error('\n____ %s%s\n' |
224 '\nConflict while rebasing this branch.\n' | 245 '\nConflict while rebasing this branch.\n' |
225 'Fix the conflict and run gclient again.\n' | 246 'Fix the conflict and run gclient again.\n' |
226 'See man git-rebase for details.\n' | 247 'See man git-rebase for details.\n' |
227 % (self.relpath, rev_str)) | 248 % (self.relpath, rev_str)) |
228 | 249 |
229 print "Checked out revision %s." % self.revinfo(options, (), None) | 250 print "Checked out revision %s." % self.revinfo(options, (), None) |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
291 | 312 |
292 def _GetCurrentBranch(self): | 313 def _GetCurrentBranch(self): |
293 # Returns name of current branch | 314 # Returns name of current branch |
294 # Returns None if inside a (no branch) | 315 # Returns None if inside a (no branch) |
295 tokens = self._Run(['branch']).split() | 316 tokens = self._Run(['branch']).split() |
296 branch = tokens[tokens.index('*') + 1] | 317 branch = tokens[tokens.index('*') + 1] |
297 if branch == '(no': | 318 if branch == '(no': |
298 return None | 319 return None |
299 return branch | 320 return branch |
300 | 321 |
301 def _Run(self, args, cwd=None, checkrc=True, redirect_stdout=True): | 322 def _Run(self, args, cwd=None, redirect_stdout=True): |
302 # TODO(maruel): Merge with Capture? | 323 # TODO(maruel): Merge with Capture or better gclient_utils.CheckCall(). |
303 if cwd is None: | 324 if cwd is None: |
304 cwd = self.checkout_path | 325 cwd = self.checkout_path |
305 stdout=None | 326 stdout = None |
306 if redirect_stdout: | 327 if redirect_stdout: |
307 stdout=subprocess.PIPE | 328 stdout = subprocess.PIPE |
308 if cwd == None: | 329 if cwd == None: |
309 cwd = self.checkout_path | 330 cwd = self.checkout_path |
310 cmd = [self.COMMAND] | 331 cmd = [self.COMMAND] |
311 cmd.extend(args) | 332 cmd.extend(args) |
312 logging.debug(cmd) | 333 logging.debug(cmd) |
313 try: | 334 try: |
314 sp = subprocess.Popen(cmd, cwd=cwd, stdout=stdout) | 335 sp = subprocess.Popen(cmd, cwd=cwd, stdout=stdout) |
315 output = sp.communicate()[0] | 336 output = sp.communicate()[0] |
316 except OSError: | 337 except OSError: |
317 raise gclient_utils.Error("git command '%s' failed to run." % | 338 raise gclient_utils.Error("git command '%s' failed to run." % |
318 ' '.join(cmd) + "\nCheck that you have git installed.") | 339 ' '.join(cmd) + "\nCheck that you have git installed.") |
319 if checkrc and sp.returncode: | 340 if sp.returncode: |
320 raise gclient_utils.Error('git command %s returned %d' % | 341 raise gclient_utils.Error('git command %s returned %d' % |
321 (args[0], sp.returncode)) | 342 (args[0], sp.returncode)) |
322 if output is not None: | 343 if output is not None: |
323 return output.strip() | 344 return output.strip() |
324 | 345 |
325 | 346 |
326 class SVNWrapper(SCMWrapper, scm.SVN): | 347 class SVNWrapper(SCMWrapper, scm.SVN): |
327 """ Wrapper for SVN """ | 348 """ Wrapper for SVN """ |
328 | 349 |
329 def cleanup(self, options, args, file_list): | 350 def cleanup(self, options, args, file_list): |
(...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
549 print("\n________ couldn't run \'%s\' in \'%s\':\nThe directory " | 570 print("\n________ couldn't run \'%s\' in \'%s\':\nThe directory " |
550 "does not exist." | 571 "does not exist." |
551 % (' '.join(command), path)) | 572 % (' '.join(command), path)) |
552 # There's no file list to retrieve. | 573 # There's no file list to retrieve. |
553 else: | 574 else: |
554 self.RunAndGetFileList(options, command, path, file_list) | 575 self.RunAndGetFileList(options, command, path, file_list) |
555 | 576 |
556 def FullUrlForRelativeUrl(self, url): | 577 def FullUrlForRelativeUrl(self, url): |
557 # Find the forth '/' and strip from there. A bit hackish. | 578 # Find the forth '/' and strip from there. A bit hackish. |
558 return '/'.join(self.url.split('/')[:4]) + url | 579 return '/'.join(self.url.split('/')[:4]) + url |
OLD | NEW |