944 if dir not in self._dirlogcache: |
944 if dir not in self._dirlogcache: |
945 self._dirlogcache[dir] = manifestrevlog(self.opener, dir, |
945 self._dirlogcache[dir] = manifestrevlog(self.opener, dir, |
946 self._dirlogcache) |
946 self._dirlogcache) |
947 return self._dirlogcache[dir] |
947 return self._dirlogcache[dir] |
948 |
948 |
|
949 def add(self, m, transaction, link, p1, p2, added, removed): |
|
950 if (p1 in self.fulltextcache and util.safehasattr(m, 'fastdelta') |
|
951 and not self._usemanifestv2): |
|
952 # If our first parent is in the manifest cache, we can |
|
953 # compute a delta here using properties we know about the |
|
954 # manifest up-front, which may save time later for the |
|
955 # revlog layer. |
|
956 |
|
957 _checkforbidden(added) |
|
958 # combine the changed lists into one sorted iterator |
|
959 work = heapq.merge([(x, False) for x in added], |
|
960 [(x, True) for x in removed]) |
|
961 |
|
962 arraytext, deltatext = m.fastdelta(self.fulltextcache[p1], work) |
|
963 cachedelta = self.rev(p1), deltatext |
|
964 text = util.buffer(arraytext) |
|
965 n = self.addrevision(text, transaction, link, p1, p2, cachedelta) |
|
966 else: |
|
967 # The first parent manifest isn't already loaded, so we'll |
|
968 # just encode a fulltext of the manifest and pass that |
|
969 # through to the revlog layer, and let it handle the delta |
|
970 # process. |
|
971 if self._treeondisk: |
|
972 m1 = self.read(p1) |
|
973 m2 = self.read(p2) |
|
974 n = self._addtree(m, transaction, link, m1, m2) |
|
975 arraytext = None |
|
976 else: |
|
977 text = m.text(self._usemanifestv2) |
|
978 n = self.addrevision(text, transaction, link, p1, p2) |
|
979 arraytext = array.array('c', text) |
|
980 |
|
981 self.fulltextcache[n] = arraytext |
|
982 |
|
983 return n |
|
984 |
|
985 def _addtree(self, m, transaction, link, m1, m2): |
|
986 # If the manifest is unchanged compared to one parent, |
|
987 # don't write a new revision |
|
988 if m.unmodifiedsince(m1) or m.unmodifiedsince(m2): |
|
989 return m.node() |
|
990 def writesubtree(subm, subp1, subp2): |
|
991 sublog = self.dirlog(subm.dir()) |
|
992 sublog.add(subm, transaction, link, subp1, subp2, None, None) |
|
993 m.writesubtrees(m1, m2, writesubtree) |
|
994 text = m.dirtext(self._usemanifestv2) |
|
995 # Double-check whether contents are unchanged to one parent |
|
996 if text == m1.dirtext(self._usemanifestv2): |
|
997 n = m1.node() |
|
998 elif text == m2.dirtext(self._usemanifestv2): |
|
999 n = m2.node() |
|
1000 else: |
|
1001 n = self.addrevision(text, transaction, link, m1.node(), m2.node()) |
|
1002 # Save nodeid so parent manifest can calculate its nodeid |
|
1003 m.setnode(n) |
|
1004 return n |
|
1005 |
949 class manifestlog(object): |
1006 class manifestlog(object): |
950 """A collection class representing the collection of manifest snapshots |
1007 """A collection class representing the collection of manifest snapshots |
951 referenced by commits in the repository. |
1008 referenced by commits in the repository. |
952 |
1009 |
953 In this situation, 'manifest' refers to the abstract concept of a snapshot |
1010 In this situation, 'manifest' refers to the abstract concept of a snapshot |
1231 try: |
1288 try: |
1232 return m.find(f) |
1289 return m.find(f) |
1233 except KeyError: |
1290 except KeyError: |
1234 return None, None |
1291 return None, None |
1235 |
1292 |
1236 def add(self, m, transaction, link, p1, p2, added, removed): |
|
1237 if (p1 in self.fulltextcache and util.safehasattr(m, 'fastdelta') |
|
1238 and not self._usemanifestv2): |
|
1239 # If our first parent is in the manifest cache, we can |
|
1240 # compute a delta here using properties we know about the |
|
1241 # manifest up-front, which may save time later for the |
|
1242 # revlog layer. |
|
1243 |
|
1244 _checkforbidden(added) |
|
1245 # combine the changed lists into one sorted iterator |
|
1246 work = heapq.merge([(x, False) for x in added], |
|
1247 [(x, True) for x in removed]) |
|
1248 |
|
1249 arraytext, deltatext = m.fastdelta(self.fulltextcache[p1], work) |
|
1250 cachedelta = self.rev(p1), deltatext |
|
1251 text = util.buffer(arraytext) |
|
1252 n = self.addrevision(text, transaction, link, p1, p2, cachedelta) |
|
1253 else: |
|
1254 # The first parent manifest isn't already loaded, so we'll |
|
1255 # just encode a fulltext of the manifest and pass that |
|
1256 # through to the revlog layer, and let it handle the delta |
|
1257 # process. |
|
1258 if self._treeondisk: |
|
1259 m1 = self.read(p1) |
|
1260 m2 = self.read(p2) |
|
1261 n = self._addtree(m, transaction, link, m1, m2) |
|
1262 arraytext = None |
|
1263 else: |
|
1264 text = m.text(self._usemanifestv2) |
|
1265 n = self.addrevision(text, transaction, link, p1, p2) |
|
1266 arraytext = array.array('c', text) |
|
1267 |
|
1268 self._mancache[n] = m |
|
1269 self.fulltextcache[n] = arraytext |
|
1270 |
|
1271 return n |
|
1272 |
|
1273 def _addtree(self, m, transaction, link, m1, m2): |
|
1274 # If the manifest is unchanged compared to one parent, |
|
1275 # don't write a new revision |
|
1276 if m.unmodifiedsince(m1) or m.unmodifiedsince(m2): |
|
1277 return m.node() |
|
1278 def writesubtree(subm, subp1, subp2): |
|
1279 sublog = self.dirlog(subm.dir()) |
|
1280 sublog.add(subm, transaction, link, subp1, subp2, None, None) |
|
1281 m.writesubtrees(m1, m2, writesubtree) |
|
1282 text = m.dirtext(self._usemanifestv2) |
|
1283 # Double-check whether contents are unchanged to one parent |
|
1284 if text == m1.dirtext(self._usemanifestv2): |
|
1285 n = m1.node() |
|
1286 elif text == m2.dirtext(self._usemanifestv2): |
|
1287 n = m2.node() |
|
1288 else: |
|
1289 n = self.addrevision(text, transaction, link, m1.node(), m2.node()) |
|
1290 # Save nodeid so parent manifest can calculate its nodeid |
|
1291 m.setnode(n) |
|
1292 return n |
|
1293 |
|
1294 def clearcaches(self): |
1293 def clearcaches(self): |
1295 super(manifest, self).clearcaches() |
1294 super(manifest, self).clearcaches() |
1296 self._mancache.clear() |
1295 self._mancache.clear() |