mercurial/manifest.py
changeset 46780 6266d19556ad
parent 46715 45f0d5297698
child 46819 d4ba4d51f85f
equal deleted inserted replaced
46779:49fd21f32695 46780:6266d19556ad
   790 _noop = lambda s: None
   790 _noop = lambda s: None
   791 
   791 
   792 
   792 
   793 @interfaceutil.implementer(repository.imanifestdict)
   793 @interfaceutil.implementer(repository.imanifestdict)
   794 class treemanifest(object):
   794 class treemanifest(object):
   795     def __init__(self, dir=b'', text=b''):
   795     def __init__(self, nodeconstants, dir=b'', text=b''):
   796         self._dir = dir
   796         self._dir = dir
       
   797         self.nodeconstants = nodeconstants
   797         self._node = nullid
   798         self._node = nullid
   798         self._loadfunc = _noop
   799         self._loadfunc = _noop
   799         self._copyfunc = _noop
   800         self._copyfunc = _noop
   800         self._dirty = False
   801         self._dirty = False
   801         self._dirs = {}
   802         self._dirs = {}
  1049         self._load()
  1050         self._load()
  1050         dir, subpath = _splittopdir(f)
  1051         dir, subpath = _splittopdir(f)
  1051         if dir:
  1052         if dir:
  1052             self._loadlazy(dir)
  1053             self._loadlazy(dir)
  1053             if dir not in self._dirs:
  1054             if dir not in self._dirs:
  1054                 self._dirs[dir] = treemanifest(self._subpath(dir))
  1055                 self._dirs[dir] = treemanifest(
       
  1056                     self.nodeconstants, self._subpath(dir)
       
  1057                 )
  1055             self._dirs[dir].__setitem__(subpath, n)
  1058             self._dirs[dir].__setitem__(subpath, n)
  1056         else:
  1059         else:
  1057             # manifest nodes are either 20 bytes or 32 bytes,
  1060             # manifest nodes are either 20 bytes or 32 bytes,
  1058             # depending on the hash in use. Assert this as historically
  1061             # depending on the hash in use. Assert this as historically
  1059             # sometimes extra bytes were added.
  1062             # sometimes extra bytes were added.
  1076         self._load()
  1079         self._load()
  1077         dir, subpath = _splittopdir(f)
  1080         dir, subpath = _splittopdir(f)
  1078         if dir:
  1081         if dir:
  1079             self._loadlazy(dir)
  1082             self._loadlazy(dir)
  1080             if dir not in self._dirs:
  1083             if dir not in self._dirs:
  1081                 self._dirs[dir] = treemanifest(self._subpath(dir))
  1084                 self._dirs[dir] = treemanifest(
       
  1085                     self.nodeconstants, self._subpath(dir)
       
  1086                 )
  1082             self._dirs[dir].setflag(subpath, flags)
  1087             self._dirs[dir].setflag(subpath, flags)
  1083         else:
  1088         else:
  1084             self._flags[f] = flags
  1089             self._flags[f] = flags
  1085         self._dirty = True
  1090         self._dirty = True
  1086 
  1091 
  1087     def copy(self):
  1092     def copy(self):
  1088         copy = treemanifest(self._dir)
  1093         copy = treemanifest(self.nodeconstants, self._dir)
  1089         copy._node = self._node
  1094         copy._node = self._node
  1090         copy._dirty = self._dirty
  1095         copy._dirty = self._dirty
  1091         if self._copyfunc is _noop:
  1096         if self._copyfunc is _noop:
  1092 
  1097 
  1093             def _copyfunc(s):
  1098             def _copyfunc(s):
  1213             return self.copy()
  1218             return self.copy()
  1214 
  1219 
  1215         visit = match.visitchildrenset(self._dir[:-1])
  1220         visit = match.visitchildrenset(self._dir[:-1])
  1216         if visit == b'all':
  1221         if visit == b'all':
  1217             return self.copy()
  1222             return self.copy()
  1218         ret = treemanifest(self._dir)
  1223         ret = treemanifest(self.nodeconstants, self._dir)
  1219         if not visit:
  1224         if not visit:
  1220             return ret
  1225             return ret
  1221 
  1226 
  1222         self._load()
  1227         self._load()
  1223         for fn in self._files:
  1228         for fn in self._files:
  1270         if match and not match.always():
  1275         if match and not match.always():
  1271             m1 = self._matches(match)
  1276             m1 = self._matches(match)
  1272             m2 = m2._matches(match)
  1277             m2 = m2._matches(match)
  1273             return m1.diff(m2, clean=clean)
  1278             return m1.diff(m2, clean=clean)
  1274         result = {}
  1279         result = {}
  1275         emptytree = treemanifest()
  1280         emptytree = treemanifest(self.nodeconstants)
  1276 
  1281 
  1277         def _iterativediff(t1, t2, stack):
  1282         def _iterativediff(t1, t2, stack):
  1278             """compares two tree manifests and append new tree-manifests which
  1283             """compares two tree manifests and append new tree-manifests which
  1279             needs to be compared to stack"""
  1284             needs to be compared to stack"""
  1280             if t1._node == t2._node and not t1._dirty and not t2._dirty:
  1285             if t1._node == t2._node and not t1._dirty and not t2._dirty:
  1366 
  1371 
  1367     def writesubtrees(self, m1, m2, writesubtree, match):
  1372     def writesubtrees(self, m1, m2, writesubtree, match):
  1368         self._load()  # for consistency; should never have any effect here
  1373         self._load()  # for consistency; should never have any effect here
  1369         m1._load()
  1374         m1._load()
  1370         m2._load()
  1375         m2._load()
  1371         emptytree = treemanifest()
  1376         emptytree = treemanifest(self.nodeconstants)
  1372 
  1377 
  1373         def getnode(m, d):
  1378         def getnode(m, d):
  1374             ld = m._lazydirs.get(d)
  1379             ld = m._lazydirs.get(d)
  1375             if ld:
  1380             if ld:
  1376                 return ld[0]
  1381                 return ld[0]
  1549     full-text manifest contents.
  1554     full-text manifest contents.
  1550     """
  1555     """
  1551 
  1556 
  1552     def __init__(
  1557     def __init__(
  1553         self,
  1558         self,
       
  1559         nodeconstants,
  1554         opener,
  1560         opener,
  1555         tree=b'',
  1561         tree=b'',
  1556         dirlogcache=None,
  1562         dirlogcache=None,
  1557         indexfile=None,
  1563         indexfile=None,
  1558         treemanifest=False,
  1564         treemanifest=False,
  1565         `treemanifest` - used to indicate this is a tree manifest revlog. Opener
  1571         `treemanifest` - used to indicate this is a tree manifest revlog. Opener
  1566         options can also be used to make this a tree manifest revlog. The opener
  1572         options can also be used to make this a tree manifest revlog. The opener
  1567         option takes precedence, so if it is set to True, we ignore whatever
  1573         option takes precedence, so if it is set to True, we ignore whatever
  1568         value is passed in to the constructor.
  1574         value is passed in to the constructor.
  1569         """
  1575         """
       
  1576         self.nodeconstants = nodeconstants
  1570         # During normal operations, we expect to deal with not more than four
  1577         # During normal operations, we expect to deal with not more than four
  1571         # revs at a time (such as during commit --amend). When rebasing large
  1578         # revs at a time (such as during commit --amend). When rebasing large
  1572         # stacks of commits, the number can go up, hence the config knob below.
  1579         # stacks of commits, the number can go up, hence the config knob below.
  1573         cachesize = 4
  1580         cachesize = 4
  1574         optiontreemanifest = False
  1581         optiontreemanifest = False
  1652     def dirlog(self, d):
  1659     def dirlog(self, d):
  1653         if d:
  1660         if d:
  1654             assert self._treeondisk
  1661             assert self._treeondisk
  1655         if d not in self._dirlogcache:
  1662         if d not in self._dirlogcache:
  1656             mfrevlog = manifestrevlog(
  1663             mfrevlog = manifestrevlog(
  1657                 self.opener, d, self._dirlogcache, treemanifest=self._treeondisk
  1664                 self.nodeconstants,
       
  1665                 self.opener,
       
  1666                 d,
       
  1667                 self._dirlogcache,
       
  1668                 treemanifest=self._treeondisk,
  1658             )
  1669             )
  1659             self._dirlogcache[d] = mfrevlog
  1670             self._dirlogcache[d] = mfrevlog
  1660         return self._dirlogcache[d]
  1671         return self._dirlogcache[d]
  1661 
  1672 
  1662     def add(
  1673     def add(
  1915     of the list of files in the given commit. Consumers of the output of this
  1926     of the list of files in the given commit. Consumers of the output of this
  1916     class do not care about the implementation details of the actual manifests
  1927     class do not care about the implementation details of the actual manifests
  1917     they receive (i.e. tree or flat or lazily loaded, etc)."""
  1928     they receive (i.e. tree or flat or lazily loaded, etc)."""
  1918 
  1929 
  1919     def __init__(self, opener, repo, rootstore, narrowmatch):
  1930     def __init__(self, opener, repo, rootstore, narrowmatch):
       
  1931         self.nodeconstants = repo.nodeconstants
  1920         usetreemanifest = False
  1932         usetreemanifest = False
  1921         cachesize = 4
  1933         cachesize = 4
  1922 
  1934 
  1923         opts = getattr(opener, 'options', None)
  1935         opts = getattr(opener, 'options', None)
  1924         if opts is not None:
  1936         if opts is not None:
  1953         if node in self._dirmancache.get(tree, ()):
  1965         if node in self._dirmancache.get(tree, ()):
  1954             return self._dirmancache[tree][node]
  1966             return self._dirmancache[tree][node]
  1955 
  1967 
  1956         if not self._narrowmatch.always():
  1968         if not self._narrowmatch.always():
  1957             if not self._narrowmatch.visitdir(tree[:-1]):
  1969             if not self._narrowmatch.visitdir(tree[:-1]):
  1958                 return excludeddirmanifestctx(tree, node)
  1970                 return excludeddirmanifestctx(self.nodeconstants, tree, node)
  1959         if tree:
  1971         if tree:
  1960             if self._rootstore._treeondisk:
  1972             if self._rootstore._treeondisk:
  1961                 if verify:
  1973                 if verify:
  1962                     # Side-effect is LookupError is raised if node doesn't
  1974                     # Side-effect is LookupError is raised if node doesn't
  1963                     # exist.
  1975                     # exist.
  2116 @interfaceutil.implementer(repository.imanifestrevisionwritable)
  2128 @interfaceutil.implementer(repository.imanifestrevisionwritable)
  2117 class memtreemanifestctx(object):
  2129 class memtreemanifestctx(object):
  2118     def __init__(self, manifestlog, dir=b''):
  2130     def __init__(self, manifestlog, dir=b''):
  2119         self._manifestlog = manifestlog
  2131         self._manifestlog = manifestlog
  2120         self._dir = dir
  2132         self._dir = dir
  2121         self._treemanifest = treemanifest()
  2133         self._treemanifest = treemanifest(manifestlog.nodeconstants)
  2122 
  2134 
  2123     def _storage(self):
  2135     def _storage(self):
  2124         return self._manifestlog.getstorage(b'')
  2136         return self._manifestlog.getstorage(b'')
  2125 
  2137 
  2126     def copy(self):
  2138     def copy(self):
  2166 
  2178 
  2167     def _storage(self):
  2179     def _storage(self):
  2168         narrowmatch = self._manifestlog._narrowmatch
  2180         narrowmatch = self._manifestlog._narrowmatch
  2169         if not narrowmatch.always():
  2181         if not narrowmatch.always():
  2170             if not narrowmatch.visitdir(self._dir[:-1]):
  2182             if not narrowmatch.visitdir(self._dir[:-1]):
  2171                 return excludedmanifestrevlog(self._dir)
  2183                 return excludedmanifestrevlog(
       
  2184                     self._manifestlog.nodeconstants, self._dir
       
  2185                 )
  2172         return self._manifestlog.getstorage(self._dir)
  2186         return self._manifestlog.getstorage(self._dir)
  2173 
  2187 
  2174     def read(self):
  2188     def read(self):
  2175         if self._data is None:
  2189         if self._data is None:
  2176             store = self._storage()
  2190             store = self._storage()
  2177             if self._node == nullid:
  2191             if self._node == nullid:
  2178                 self._data = treemanifest()
  2192                 self._data = treemanifest(self._manifestlog.nodeconstants)
  2179             # TODO accessing non-public API
  2193             # TODO accessing non-public API
  2180             elif store._treeondisk:
  2194             elif store._treeondisk:
  2181                 m = treemanifest(dir=self._dir)
  2195                 m = treemanifest(self._manifestlog.nodeconstants, dir=self._dir)
  2182 
  2196 
  2183                 def gettext():
  2197                 def gettext():
  2184                     return store.revision(self._node)
  2198                     return store.revision(self._node)
  2185 
  2199 
  2186                 def readsubtree(dir, subm):
  2200                 def readsubtree(dir, subm):
  2196                     text = pycompat.bytestr(store.fulltextcache[self._node])
  2210                     text = pycompat.bytestr(store.fulltextcache[self._node])
  2197                 else:
  2211                 else:
  2198                     text = store.revision(self._node)
  2212                     text = store.revision(self._node)
  2199                     arraytext = bytearray(text)
  2213                     arraytext = bytearray(text)
  2200                     store.fulltextcache[self._node] = arraytext
  2214                     store.fulltextcache[self._node] = arraytext
  2201                 self._data = treemanifest(dir=self._dir, text=text)
  2215                 self._data = treemanifest(
       
  2216                     self._manifestlog.nodeconstants, dir=self._dir, text=text
       
  2217                 )
  2202 
  2218 
  2203         return self._data
  2219         return self._data
  2204 
  2220 
  2205     def node(self):
  2221     def node(self):
  2206         return self._node
  2222         return self._node
  2233         else:
  2249         else:
  2234             # Need to perform a slow delta
  2250             # Need to perform a slow delta
  2235             r0 = store.deltaparent(store.rev(self._node))
  2251             r0 = store.deltaparent(store.rev(self._node))
  2236             m0 = self._manifestlog.get(self._dir, store.node(r0)).read()
  2252             m0 = self._manifestlog.get(self._dir, store.node(r0)).read()
  2237             m1 = self.read()
  2253             m1 = self.read()
  2238             md = treemanifest(dir=self._dir)
  2254             md = treemanifest(self._manifestlog.nodeconstants, dir=self._dir)
  2239             for f, ((n0, fl0), (n1, fl1)) in pycompat.iteritems(m0.diff(m1)):
  2255             for f, ((n0, fl0), (n1, fl1)) in pycompat.iteritems(m0.diff(m1)):
  2240                 if n1:
  2256                 if n1:
  2241                     md[f] = n1
  2257                     md[f] = n1
  2242                     if fl1:
  2258                     if fl1:
  2243                         md.setflag(f, fl1)
  2259                         md.setflag(f, fl1)
  2276     detect a merge conflict outside the narrowspec. That's what this
  2292     detect a merge conflict outside the narrowspec. That's what this
  2277     class is: it stands in for a directory whose node is known, but
  2293     class is: it stands in for a directory whose node is known, but
  2278     whose contents are unknown.
  2294     whose contents are unknown.
  2279     """
  2295     """
  2280 
  2296 
  2281     def __init__(self, dir, node):
  2297     def __init__(self, nodeconstants, dir, node):
  2282         super(excludeddir, self).__init__(dir)
  2298         super(excludeddir, self).__init__(nodeconstants, dir)
  2283         self._node = node
  2299         self._node = node
  2284         # Add an empty file, which will be included by iterators and such,
  2300         # Add an empty file, which will be included by iterators and such,
  2285         # appearing as the directory itself (i.e. something like "dir/")
  2301         # appearing as the directory itself (i.e. something like "dir/")
  2286         self._files[b''] = node
  2302         self._files[b''] = node
  2287         self._flags[b''] = b't'
  2303         self._flags[b''] = b't'
  2296 
  2312 
  2297 
  2313 
  2298 class excludeddirmanifestctx(treemanifestctx):
  2314 class excludeddirmanifestctx(treemanifestctx):
  2299     """context wrapper for excludeddir - see that docstring for rationale"""
  2315     """context wrapper for excludeddir - see that docstring for rationale"""
  2300 
  2316 
  2301     def __init__(self, dir, node):
  2317     def __init__(self, nodeconstants, dir, node):
       
  2318         self.nodeconstants = nodeconstants
  2302         self._dir = dir
  2319         self._dir = dir
  2303         self._node = node
  2320         self._node = node
  2304 
  2321 
  2305     def read(self):
  2322     def read(self):
  2306         return excludeddir(self._dir, self._node)
  2323         return excludeddir(self.nodeconstants, self._dir, self._node)
  2307 
  2324 
  2308     def readfast(self, shallow=False):
  2325     def readfast(self, shallow=False):
  2309         # special version of readfast since we don't have underlying storage
  2326         # special version of readfast since we don't have underlying storage
  2310         return self.read()
  2327         return self.read()
  2311 
  2328 
  2323     skipped. This class exists to conform to the manifestrevlog
  2340     skipped. This class exists to conform to the manifestrevlog
  2324     interface for those directories and proactively prevent writes to
  2341     interface for those directories and proactively prevent writes to
  2325     outside the narrowspec.
  2342     outside the narrowspec.
  2326     """
  2343     """
  2327 
  2344 
  2328     def __init__(self, dir):
  2345     def __init__(self, nodeconstants, dir):
       
  2346         self.nodeconstants = nodeconstants
  2329         self._dir = dir
  2347         self._dir = dir
  2330 
  2348 
  2331     def __len__(self):
  2349     def __len__(self):
  2332         raise error.ProgrammingError(
  2350         raise error.ProgrammingError(
  2333             b'attempt to get length of excluded dir %s' % self._dir
  2351             b'attempt to get length of excluded dir %s' % self._dir