OLD | NEW |
---|---|
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # Copyright 2014 The Chromium Authors. All rights reserved. | 2 # Copyright 2014 The Chromium Authors. All rights reserved. |
3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
5 | 5 |
6 """A git command for managing a local cache of git repositories.""" | 6 """A git command for managing a local cache of git repositories.""" |
7 | 7 |
8 from __future__ import print_function | 8 from __future__ import print_function |
9 import errno | 9 import errno |
10 import logging | 10 import logging |
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
174 self.url = url | 174 self.url = url |
175 self.fetch_specs = set([self.parse_fetch_spec(ref) for ref in (refs or [])]) | 175 self.fetch_specs = set([self.parse_fetch_spec(ref) for ref in (refs or [])]) |
176 self.basedir = self.UrlToCacheDir(url) | 176 self.basedir = self.UrlToCacheDir(url) |
177 self.mirror_path = os.path.join(self.GetCachePath(), self.basedir) | 177 self.mirror_path = os.path.join(self.GetCachePath(), self.basedir) |
178 if print_func: | 178 if print_func: |
179 self.print = self.print_without_file | 179 self.print = self.print_without_file |
180 self.print_func = print_func | 180 self.print_func = print_func |
181 else: | 181 else: |
182 self.print = print | 182 self.print = print |
183 | 183 |
184 def print_without_file(self, message, **kwargs): | 184 def print_without_file(self, message, **_kwargs): |
185 self.print_func(message) | 185 self.print_func(message) |
186 | 186 |
187 @property | 187 @property |
188 def bootstrap_bucket(self): | 188 def bootstrap_bucket(self): |
189 if 'chrome-internal' in self.url: | 189 if 'chrome-internal' in self.url: |
190 return 'chrome-git-cache' | 190 return 'chrome-git-cache' |
191 else: | 191 else: |
192 return 'chromium-git-cache' | 192 return 'chromium-git-cache' |
193 | 193 |
194 @classmethod | 194 @classmethod |
(...skipping 28 matching lines...) Expand all Loading... | |
223 cachepath = subprocess.check_output( | 223 cachepath = subprocess.check_output( |
224 [cls.git_exe, 'config', '--global', 'cache.cachepath']).strip() | 224 [cls.git_exe, 'config', '--global', 'cache.cachepath']).strip() |
225 except subprocess.CalledProcessError: | 225 except subprocess.CalledProcessError: |
226 cachepath = None | 226 cachepath = None |
227 if not cachepath: | 227 if not cachepath: |
228 raise RuntimeError( | 228 raise RuntimeError( |
229 'No global cache.cachepath git configuration found.') | 229 'No global cache.cachepath git configuration found.') |
230 setattr(cls, 'cachepath', cachepath) | 230 setattr(cls, 'cachepath', cachepath) |
231 return getattr(cls, 'cachepath') | 231 return getattr(cls, 'cachepath') |
232 | 232 |
233 def Rename(self, src, dst, count=3): | |
234 i = 0 | |
235 while True: | |
236 i += 1 | |
237 | |
238 try: | |
239 os.rename(src, dst) | |
240 return | |
241 except OSError as e: | |
242 # This is somehow racy on Windows. | |
243 # Catching OSError because WindowsError isn't portable and | |
244 # pylint complains. | |
245 if i >= count: | |
246 raise | |
247 self.print('Error moving [%s] to [%s] (%d / %d): %s' % ( | |
nodir
2016/11/11 01:34:30
attempt %d / %d
so make it obviously clear
| |
248 src, dst, i+1, count, str(e))) | |
nodir
2016/11/11 01:34:30
sleep?
nodir
2016/11/11 01:34:30
str unnecessary?
| |
249 | |
233 def RunGit(self, cmd, **kwargs): | 250 def RunGit(self, cmd, **kwargs): |
234 """Run git in a subprocess.""" | 251 """Run git in a subprocess.""" |
235 cwd = kwargs.setdefault('cwd', self.mirror_path) | 252 cwd = kwargs.setdefault('cwd', self.mirror_path) |
236 kwargs.setdefault('print_stdout', False) | 253 kwargs.setdefault('print_stdout', False) |
237 kwargs.setdefault('filter_fn', self.print) | 254 kwargs.setdefault('filter_fn', self.print) |
238 env = kwargs.get('env') or kwargs.setdefault('env', os.environ.copy()) | 255 env = kwargs.get('env') or kwargs.setdefault('env', os.environ.copy()) |
239 env.setdefault('GIT_ASKPASS', 'true') | 256 env.setdefault('GIT_ASKPASS', 'true') |
240 env.setdefault('SSH_ASKPASS', 'true') | 257 env.setdefault('SSH_ASKPASS', 'true') |
241 self.print('running "git %s" in "%s"' % (' '.join(cmd), cwd)) | 258 self.print('running "git %s" in "%s"' % (' '.join(cmd), cwd)) |
242 gclient_utils.CheckCallAndFilter([self.git_exe] + cmd, **kwargs) | 259 gclient_utils.CheckCallAndFilter([self.git_exe] + cmd, **kwargs) |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
317 with zipfile.ZipFile(filename, 'r') as f: | 334 with zipfile.ZipFile(filename, 'r') as f: |
318 f.printdir() | 335 f.printdir() |
319 f.extractall(directory) | 336 f.extractall(directory) |
320 except Exception as e: | 337 except Exception as e: |
321 self.print('Encountered error: %s' % str(e), file=sys.stderr) | 338 self.print('Encountered error: %s' % str(e), file=sys.stderr) |
322 retcode = 1 | 339 retcode = 1 |
323 else: | 340 else: |
324 retcode = 0 | 341 retcode = 0 |
325 finally: | 342 finally: |
326 # Clean up the downloaded zipfile. | 343 # Clean up the downloaded zipfile. |
327 gclient_utils.rm_file_or_tree(tempdir) | 344 gclient_utils.rm_file_or_tree(tempdir) |
nodir
2016/11/11 01:34:30
can you please add a retry here too?
| |
328 | 345 |
329 if retcode: | 346 if retcode: |
330 self.print( | 347 self.print( |
331 'Extracting bootstrap zipfile %s failed.\n' | 348 'Extracting bootstrap zipfile %s failed.\n' |
332 'Resuming normal operations.' % filename) | 349 'Resuming normal operations.' % filename) |
333 return False | 350 return False |
334 return True | 351 return True |
335 | 352 |
336 def exists(self): | 353 def exists(self): |
337 return os.path.isfile(os.path.join(self.mirror_path, 'config')) | 354 return os.path.isfile(os.path.join(self.mirror_path, 'config')) |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
434 # This is a major failure, we need to clean and force a bootstrap. | 451 # This is a major failure, we need to clean and force a bootstrap. |
435 gclient_utils.rmtree(rundir) | 452 gclient_utils.rmtree(rundir) |
436 self.print(GIT_CACHE_CORRUPT_MESSAGE) | 453 self.print(GIT_CACHE_CORRUPT_MESSAGE) |
437 tempdir = self._ensure_bootstrapped(depth, bootstrap, force=True) | 454 tempdir = self._ensure_bootstrapped(depth, bootstrap, force=True) |
438 assert tempdir | 455 assert tempdir |
439 self._fetch(tempdir or self.mirror_path, verbose, depth) | 456 self._fetch(tempdir or self.mirror_path, verbose, depth) |
440 finally: | 457 finally: |
441 if tempdir: | 458 if tempdir: |
442 if os.path.exists(self.mirror_path): | 459 if os.path.exists(self.mirror_path): |
443 gclient_utils.rmtree(self.mirror_path) | 460 gclient_utils.rmtree(self.mirror_path) |
444 os.rename(tempdir, self.mirror_path) | 461 self.Rename(tempdir, self.mirror_path) |
445 if not ignore_lock: | 462 if not ignore_lock: |
446 lockfile.unlock() | 463 lockfile.unlock() |
447 | 464 |
448 def update_bootstrap(self, prune=False): | 465 def update_bootstrap(self, prune=False): |
449 # The files are named <git number>.zip | 466 # The files are named <git number>.zip |
450 gen_number = subprocess.check_output( | 467 gen_number = subprocess.check_output( |
451 [self.git_exe, 'number', 'master'], cwd=self.mirror_path).strip() | 468 [self.git_exe, 'number', 'master'], cwd=self.mirror_path).strip() |
452 # Run Garbage Collect to compress packfile. | 469 # Run Garbage Collect to compress packfile. |
453 self.RunGit(['gc', '--prune=all']) | 470 self.RunGit(['gc', '--prune=all']) |
454 # Creating a temp file and then deleting it ensures we can use this name. | 471 # Creating a temp file and then deleting it ensures we can use this name. |
(...skipping 267 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
722 dispatcher = subcommand.CommandDispatcher(__name__) | 739 dispatcher = subcommand.CommandDispatcher(__name__) |
723 return dispatcher.execute(OptionParser(), argv) | 740 return dispatcher.execute(OptionParser(), argv) |
724 | 741 |
725 | 742 |
726 if __name__ == '__main__': | 743 if __name__ == '__main__': |
727 try: | 744 try: |
728 sys.exit(main(sys.argv[1:])) | 745 sys.exit(main(sys.argv[1:])) |
729 except KeyboardInterrupt: | 746 except KeyboardInterrupt: |
730 sys.stderr.write('interrupted\n') | 747 sys.stderr.write('interrupted\n') |
731 sys.exit(1) | 748 sys.exit(1) |
OLD | NEW |