mercurial/manifest.py
branchstable
changeset 26813 b66e3ca0b90c
parent 26402 05871262acd5
child 26871 1cbf144fd8a1
equal deleted inserted replaced
26535:d3712209921d 26813:b66e3ca0b90c
     7 
     7 
     8 from i18n import _
     8 from i18n import _
     9 import mdiff, parsers, error, revlog, util
     9 import mdiff, parsers, error, revlog, util
    10 import array, struct
    10 import array, struct
    11 import os
    11 import os
       
    12 import heapq
    12 
    13 
    13 propertycache = util.propertycache
    14 propertycache = util.propertycache
    14 
    15 
    15 def _parsev1(data):
    16 def _parsev1(data):
    16     # This method does a little bit of excessive-looking
    17     # This method does a little bit of excessive-looking
   439         dir, subpath = f.split('/', 1)
   440         dir, subpath = f.split('/', 1)
   440         return dir + '/', subpath
   441         return dir + '/', subpath
   441     else:
   442     else:
   442         return '', f
   443         return '', f
   443 
   444 
   444 _noop = lambda: None
   445 _noop = lambda s: None
   445 
   446 
   446 class treemanifest(object):
   447 class treemanifest(object):
   447     def __init__(self, dir='', text=''):
   448     def __init__(self, dir='', text=''):
   448         self._dir = dir
   449         self._dir = dir
   449         self._node = revlog.nullid
   450         self._node = revlog.nullid
   450         self._load = _noop
   451         self._loadfunc = _noop
       
   452         self._copyfunc = _noop
   451         self._dirty = False
   453         self._dirty = False
   452         self._dirs = {}
   454         self._dirs = {}
   453         # Using _lazymanifest here is a little slower than plain old dicts
   455         # Using _lazymanifest here is a little slower than plain old dicts
   454         self._files = {}
   456         self._files = {}
   455         self._flags = {}
   457         self._flags = {}
   473     def _isempty(self):
   475     def _isempty(self):
   474         self._load() # for consistency; already loaded by all callers
   476         self._load() # for consistency; already loaded by all callers
   475         return (not self._files and (not self._dirs or
   477         return (not self._files and (not self._dirs or
   476                 all(m._isempty() for m in self._dirs.values())))
   478                 all(m._isempty() for m in self._dirs.values())))
   477 
   479 
   478     def __str__(self):
   480     def __repr__(self):
   479         return ('<treemanifest dir=%s, node=%s, loaded=%s, dirty=%s>' %
   481         return ('<treemanifest dir=%s, node=%s, loaded=%s, dirty=%s at 0x%x>' %
   480                 (self._dir, revlog.hex(self._node),
   482                 (self._dir, revlog.hex(self._node),
   481                  bool(self._load is _noop),
   483                  bool(self._loadfunc is _noop),
   482                  self._dirty))
   484                  self._dirty, id(self)))
   483 
   485 
   484     def dir(self):
   486     def dir(self):
   485         '''The directory that this tree manifest represents, including a
   487         '''The directory that this tree manifest represents, including a
   486         trailing '/'. Empty string for the repo root directory.'''
   488         trailing '/'. Empty string for the repo root directory.'''
   487         return self._dir
   489         return self._dir
   595             self._dirs[dir].__setitem__(subpath, n)
   597             self._dirs[dir].__setitem__(subpath, n)
   596         else:
   598         else:
   597             self._files[f] = n[:21] # to match manifestdict's behavior
   599             self._files[f] = n[:21] # to match manifestdict's behavior
   598         self._dirty = True
   600         self._dirty = True
   599 
   601 
       
   602     def _load(self):
       
   603         if self._loadfunc is not _noop:
       
   604             lf, self._loadfunc = self._loadfunc, _noop
       
   605             lf(self)
       
   606         elif self._copyfunc is not _noop:
       
   607             cf, self._copyfunc = self._copyfunc, _noop
       
   608             cf(self)
       
   609 
   600     def setflag(self, f, flags):
   610     def setflag(self, f, flags):
   601         """Set the flags (symlink, executable) for path f."""
   611         """Set the flags (symlink, executable) for path f."""
   602         assert 'd' not in flags
   612         assert 'd' not in flags
   603         self._load()
   613         self._load()
   604         dir, subpath = _splittopdir(f)
   614         dir, subpath = _splittopdir(f)
   612 
   622 
   613     def copy(self):
   623     def copy(self):
   614         copy = treemanifest(self._dir)
   624         copy = treemanifest(self._dir)
   615         copy._node = self._node
   625         copy._node = self._node
   616         copy._dirty = self._dirty
   626         copy._dirty = self._dirty
   617         def _load():
   627         if self._copyfunc is _noop:
   618             self._load()
   628             def _copyfunc(s):
   619             for d in self._dirs:
   629                 self._load()
   620                 copy._dirs[d] = self._dirs[d].copy()
   630                 for d in self._dirs:
   621             copy._files = dict.copy(self._files)
   631                     s._dirs[d] = self._dirs[d].copy()
   622             copy._flags = dict.copy(self._flags)
   632                 s._files = dict.copy(self._files)
   623             copy._load = _noop
   633                 s._flags = dict.copy(self._flags)
   624         copy._load = _load
   634             if self._loadfunc is _noop:
   625         if self._load == _noop:
   635                 _copyfunc(copy)
   626             # Chaining _load if it's _noop is functionally correct, but the
   636             else:
   627             # chain may end up excessively long (stack overflow), and
   637                 copy._copyfunc = _copyfunc
   628             # will prevent garbage collection of 'self'.
   638         else:
   629             copy._load()
   639             copy._copyfunc = self._copyfunc
   630         return copy
   640         return copy
   631 
   641 
   632     def filesnotin(self, m2):
   642     def filesnotin(self, m2):
   633         '''Set of files in this manifest that are not in the other'''
   643         '''Set of files in this manifest that are not in the other'''
   634         files = set()
   644         files = set()
   831         dirs = [(d[:-1], self._dirs[d]._node, 'd') for d in self._dirs]
   841         dirs = [(d[:-1], self._dirs[d]._node, 'd') for d in self._dirs]
   832         files = [(f, self._files[f], flags(f)) for f in self._files]
   842         files = [(f, self._files[f], flags(f)) for f in self._files]
   833         return _text(sorted(dirs + files), usemanifestv2)
   843         return _text(sorted(dirs + files), usemanifestv2)
   834 
   844 
   835     def read(self, gettext, readsubtree):
   845     def read(self, gettext, readsubtree):
   836         def _load():
   846         def _load_for_read(s):
   837             # Mark as loaded already here, so __setitem__ and setflag() don't
   847             s.parse(gettext(), readsubtree)
   838             # cause infinite loops when they try to load.
   848             s._dirty = False
   839             self._load = _noop
   849         self._loadfunc = _load_for_read
   840             self.parse(gettext(), readsubtree)
       
   841             self._dirty = False
       
   842         self._load = _load
       
   843 
   850 
   844     def writesubtrees(self, m1, m2, writesubtree):
   851     def writesubtrees(self, m1, m2, writesubtree):
   845         self._load() # for consistency; should never have any effect here
   852         self._load() # for consistency; should never have any effect here
   846         emptytree = treemanifest()
   853         emptytree = treemanifest()
   847         for d, subm in self._dirs.iteritems():
   854         for d, subm in self._dirs.iteritems():
   968             # compute a delta here using properties we know about the
   975             # compute a delta here using properties we know about the
   969             # manifest up-front, which may save time later for the
   976             # manifest up-front, which may save time later for the
   970             # revlog layer.
   977             # revlog layer.
   971 
   978 
   972             _checkforbidden(added)
   979             _checkforbidden(added)
   973             # combine the changed lists into one list for sorting
   980             # combine the changed lists into one sorted iterator
   974             work = [(x, False) for x in added]
   981             work = heapq.merge([(x, False) for x in added],
   975             work.extend((x, True) for x in removed)
   982                                [(x, True) for x in removed])
   976             # this could use heapq.merge() (from Python 2.6+) or equivalent
       
   977             # since the lists are already sorted
       
   978             work.sort()
       
   979 
   983 
   980             arraytext, deltatext = m.fastdelta(self._mancache[p1][1], work)
   984             arraytext, deltatext = m.fastdelta(self._mancache[p1][1], work)
   981             cachedelta = self.rev(p1), deltatext
   985             cachedelta = self.rev(p1), deltatext
   982             text = util.buffer(arraytext)
   986             text = util.buffer(arraytext)
   983             n = self.addrevision(text, transaction, link, p1, p2, cachedelta)
   987             n = self.addrevision(text, transaction, link, p1, p2, cachedelta)