summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--subcmds/sync.py61
1 files changed, 60 insertions, 1 deletions
diff --git a/subcmds/sync.py b/subcmds/sync.py
index e68a025e..a8022d9d 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 self._Fetch(to_fetch, opt) 515 self._Fetch(to_fetch, opt)
507 _PostRepoFetch(rp, opt.no_repo_verify) 516 _PostRepoFetch(rp, opt.no_repo_verify)
@@ -602,3 +611,53 @@ warning: Cannot automatically authenticate repo."""
602 print >>sys.stderr 611 print >>sys.stderr
603 return False 612 return False
604 return True 613 return True
614
615class _FetchTimes(object):
616 def __init__(self, manifest):
617 self._path = os.path.join(manifest.repodir, '.repopickle_fetchtimes')
618 self._times = None
619
620 def Clear(self):
621 self._times = {}
622
623 def Get(self, project):
624 self._Load()
625 return self._times.get(project.name, _ONE_DAY_S)
626
627 def Set(self, project, t):
628 self._times[project.name] = t
629
630 def _Load(self):
631 if self._times is None:
632 try:
633 f = open(self._path)
634 except IOError:
635 self._times = {}
636 return self._times
637 try:
638 try:
639 self._times = pickle.load(f)
640 except:
641 try:
642 os.remove(self._path)
643 except OSError:
644 pass
645 self._times = {}
646 finally:
647 f.close()
648 return self._times
649
650 def Save(self):
651 if self._times is None:
652 return
653 try:
654 f = open(self._path, 'wb')
655 try:
656 pickle.dump(self._times, f)
657 except (IOError, OSError, pickle.PickleError):
658 try:
659 os.remove(self._path)
660 except OSError:
661 pass
662 finally:
663 f.close()