summaryrefslogtreecommitdiffstats
path: root/subcmds/sync.py
diff options
context:
space:
mode:
Diffstat (limited to 'subcmds/sync.py')
-rw-r--r--subcmds/sync.py61
1 files changed, 60 insertions, 1 deletions
diff --git a/subcmds/sync.py b/subcmds/sync.py
index 64ed38e7..27dd877d 100644
--- a/subcmds/sync.py
+++ b/subcmds/sync.py
@@ -16,6 +16,7 @@
16import netrc 16import netrc
17from optparse import SUPPRESS_HELP 17from optparse import SUPPRESS_HELP
18import os 18import os
19import pickle
19import re 20import re
20import shutil 21import shutil
21import socket 22import socket
@@ -47,6 +48,8 @@ from error import RepoChangedException, GitError
47from project import SyncBuffer 48from project import SyncBuffer
48from progress import Progress 49from progress import Progress
49 50
51_ONE_DAY_S = 24 * 60 * 60
52
50class _FetchError(Exception): 53class _FetchError(Exception):
51 """Internal error thrown in _FetchHelper() when we don't want stack trace.""" 54 """Internal error thrown in _FetchHelper() when we don't want stack trace."""
52 pass 55 pass
@@ -212,10 +215,12 @@ later is required to fix a server side protocol bug.
212 # - We always make sure we unlock the lock if we locked it. 215 # - We always make sure we unlock the lock if we locked it.
213 try: 216 try:
214 try: 217 try:
218 start = time.time()
215 success = project.Sync_NetworkHalf( 219 success = project.Sync_NetworkHalf(
216 quiet=opt.quiet, 220 quiet=opt.quiet,
217 current_branch_only=opt.current_branch_only, 221 current_branch_only=opt.current_branch_only,
218 clone_bundle=not opt.no_clone_bundle) 222 clone_bundle=not opt.no_clone_bundle)
223 self._fetch_times.Set(project, time.time() - start)
219 224
220 # Lock around all the rest of the code, since printing, updating a set 225 # Lock around all the rest of the code, since printing, updating a set
221 # and Progress.update() are not thread safe. 226 # and Progress.update() are not thread safe.
@@ -293,6 +298,7 @@ later is required to fix a server side protocol bug.
293 sys.exit(1) 298 sys.exit(1)
294 299
295 pm.end() 300 pm.end()
301 self._fetch_times.Save()
296 for project in projects: 302 for project in projects:
297 project.bare_git.gc('--auto') 303 project.bare_git.gc('--auto')
298 return fetched 304 return fetched
@@ -496,12 +502,15 @@ uncommitted changes are present' % project.relpath
496 self.jobs = self.manifest.default.sync_j 502 self.jobs = self.manifest.default.sync_j
497 all_projects = self.GetProjects(args, missing_ok=True) 503 all_projects = self.GetProjects(args, missing_ok=True)
498 504
505 self._fetch_times = _FetchTimes(self.manifest)
499 if not opt.local_only: 506 if not opt.local_only:
500 to_fetch = [] 507 to_fetch = []
501 now = time.time() 508 now = time.time()
502 if (24 * 60 * 60) <= (now - rp.LastFetch): 509 if _ONE_DAY_S <= (now - rp.LastFetch):
503 to_fetch.append(rp) 510 to_fetch.append(rp)
504 to_fetch.extend(all_projects) 511 to_fetch.extend(all_projects)
512 to_fetch.sort(key=self._fetch_times.Get, reverse=True)
513 self._fetch_times.Clear()
505 514
506 fetched = self._Fetch(to_fetch, opt) 515 fetched = self._Fetch(to_fetch, opt)
507 _PostRepoFetch(rp, opt.no_repo_verify) 516 _PostRepoFetch(rp, opt.no_repo_verify)
@@ -621,3 +630,53 @@ warning: Cannot automatically authenticate repo."""
621 print >>sys.stderr 630 print >>sys.stderr
622 return False 631 return False
623 return True 632 return True
633
634class _FetchTimes(object):
635 def __init__(self, manifest):
636 self._path = os.path.join(manifest.repodir, '.repopickle_fetchtimes')
637 self._times = None
638
639 def Clear(self):
640 self._times = {}
641
642 def Get(self, project):
643 self._Load()
644 return self._times.get(project.name, _ONE_DAY_S)
645
646 def Set(self, project, t):
647 self._times[project.name] = t
648
649 def _Load(self):
650 if self._times is None:
651 try:
652 f = open(self._path)
653 except IOError:
654 self._times = {}
655 return self._times
656 try:
657 try:
658 self._times = pickle.load(f)
659 except:
660 try:
661 os.remove(self._path)
662 except OSError:
663 pass
664 self._times = {}
665 finally:
666 f.close()
667 return self._times
668
669 def Save(self):
670 if self._times is None:
671 return
672 try:
673 f = open(self._path, 'wb')
674 try:
675 pickle.dump(self._times, f)
676 except (IOError, OSError, pickle.PickleError):
677 try:
678 os.remove(self._path)
679 except OSError:
680 pass
681 finally:
682 f.close()