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): |
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] |
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 |