mercurial/hg.py
changeset 26219 ae33fff17c1e
parent 26103 30be3aeb5344
child 26240 2b1434e5eaa0
equal deleted inserted replaced
26218:7d45ec47c0af 26219:ae33fff17c1e
   821         dst.setconfig('web', 'cacerts', v, 'copied')
   821         dst.setconfig('web', 'cacerts', v, 'copied')
   822     elif v:
   822     elif v:
   823         dst.setconfig('web', 'cacerts', util.expandpath(v), 'copied')
   823         dst.setconfig('web', 'cacerts', util.expandpath(v), 'copied')
   824 
   824 
   825     return dst
   825     return dst
       
   826 
       
   827 # Files of interest
       
   828 # Used to check if the repository has changed looking at mtime and size of
       
   829 # theses files.
       
   830 foi = [('spath', '00changelog.i'),
       
   831        ('spath', 'phaseroots'), # ! phase can change content at the same size
       
   832        ('spath', 'obsstore'),
       
   833        ('path', 'bookmarks'), # ! bookmark can change content at the same size
       
   834       ]
       
   835 
       
   836 class cachedlocalrepo(object):
       
   837     """Holds a localrepository that can be cached and reused."""
       
   838 
       
   839     def __init__(self, repo):
       
   840         """Create a new cached repo from an existing repo.
       
   841 
       
   842         We assume the passed in repo was recently created. If the
       
   843         repo has changed between when it was created and when it was
       
   844         turned into a cache, it may not refresh properly.
       
   845         """
       
   846         assert isinstance(repo, localrepo.localrepository)
       
   847         self._repo = repo
       
   848         self._state, self.mtime = self._repostate()
       
   849 
       
   850     def fetch(self):
       
   851         """Refresh (if necessary) and return a repository.
       
   852 
       
   853         If the cached instance is out of date, it will be recreated
       
   854         automatically and returned.
       
   855 
       
   856         Returns a tuple of the repo and a boolean indicating whether a new
       
   857         repo instance was created.
       
   858         """
       
   859         # We compare the mtimes and sizes of some well-known files to
       
   860         # determine if the repo changed. This is not precise, as mtimes
       
   861         # are susceptible to clock skew and imprecise filesystems and
       
   862         # file content can change while maintaining the same size.
       
   863 
       
   864         state, mtime = self._repostate()
       
   865         if state == self._state:
       
   866             return self._repo, False
       
   867 
       
   868         self._repo = repository(self._repo.baseui, self._repo.url())
       
   869         self._state = state
       
   870         self.mtime = mtime
       
   871 
       
   872         return self._repo, True
       
   873 
       
   874     def _repostate(self):
       
   875         state = []
       
   876         maxmtime = -1
       
   877         for attr, fname in foi:
       
   878             prefix = getattr(self._repo, attr)
       
   879             p = os.path.join(prefix, fname)
       
   880             try:
       
   881                 st = os.stat(p)
       
   882             except OSError:
       
   883                 st = os.stat(prefix)
       
   884             state.append((st.st_mtime, st.st_size))
       
   885             maxmtime = max(maxmtime, st.st_mtime)
       
   886 
       
   887         return tuple(state), maxmtime
       
   888 
       
   889     def copy(self):
       
   890         """Obtain a copy of this class instance."""
       
   891         c = cachedlocalrepo(self._repo)
       
   892         c._state = self._state
       
   893         c.mtime = self.mtime
       
   894         return c