diff mercurial/dirstatemap.py @ 48223:b4f83c9e7905

dirstate-v2: Add support when Rust is not enabled This wires into `dirstatemap` the parser and serializer added in previous changesets. The memory representation is still the same, with a flat `dict` for `DirstateItem`s and another one for copy sources. Serialization always creates a new dirstate-v2 data file and does not support (when Rust is not enabled) appending to an existing one, since we don’t keep track of which tree nodes are new or modified. Instead the tree is reconstructed during serialization. Differential Revision: https://phab.mercurial-scm.org/D11520
author Simon Sapin <simon.sapin@octobus.net>
date Fri, 16 Jul 2021 18:42:20 +0200
parents a32a96079e2d
children 269ff8978086
line wrap: on
line diff
--- a/mercurial/dirstatemap.py	Thu Jul 22 17:31:37 2021 +0200
+++ b/mercurial/dirstatemap.py	Fri Jul 16 18:42:20 2021 +0200
@@ -332,15 +332,6 @@
       denormalized form that they appear as in the dirstate.
     """
 
-    def __init__(self, ui, opener, root, nodeconstants, use_dirstate_v2):
-        super(dirstatemap, self).__init__(
-            ui, opener, root, nodeconstants, use_dirstate_v2
-        )
-        if self._use_dirstate_v2:
-            msg = "Dirstate V2 not supportedi"
-            msg += "(should have detected unsupported requirement)"
-            raise error.ProgrammingError(msg)
-
     ### Core data storage and access
 
     @propertycache
@@ -406,19 +397,17 @@
             self._opener.join(self._filename)
         )
 
-        try:
-            fp = self._opendirstatefile()
-            try:
-                st = fp.read()
-            finally:
-                fp.close()
-        except IOError as err:
-            if err.errno != errno.ENOENT:
-                raise
-            return
+        if self._use_dirstate_v2:
+            if not self.docket.uuid:
+                return
+            st = self._opener.read(self.docket.data_filename())
+        else:
+            st = self._readdirstatefile()
+
         if not st:
             return
 
+        # TODO: adjust this estimate for dirstate-v2
         if util.safehasattr(parsers, b'dict_new_presized'):
             # Make an estimate of the number of files in the dirstate based on
             # its size. This trades wasting some memory for avoiding costly
@@ -440,8 +429,14 @@
         # parsing the dirstate.
         #
         # (we cannot decorate the function directly since it is in a C module)
-        parse_dirstate = util.nogc(parsers.parse_dirstate)
-        p = parse_dirstate(self._map, self.copymap, st)
+        if self._use_dirstate_v2:
+            p = self.docket.parents
+            meta = self.docket.tree_metadata
+            parse_dirstate = util.nogc(v2.parse_dirstate)
+            parse_dirstate(self._map, self.copymap, st, meta)
+        else:
+            parse_dirstate = util.nogc(parsers.parse_dirstate)
+            p = parse_dirstate(self._map, self.copymap, st)
         if not self._dirtyparents:
             self.setparents(*p)
 
@@ -450,10 +445,16 @@
         self.__getitem__ = self._map.__getitem__
         self.get = self._map.get
 
-    def write(self, _tr, st, now):
-        d = parsers.pack_dirstate(self._map, self.copymap, self.parents(), now)
-        st.write(d)
-        st.close()
+    def write(self, tr, st, now):
+        if self._use_dirstate_v2:
+            packed, meta = v2.pack_dirstate(self._map, self.copymap, now)
+            self.write_v2_no_append(tr, st, meta, packed)
+        else:
+            packed = parsers.pack_dirstate(
+                self._map, self.copymap, self.parents(), now
+            )
+            st.write(packed)
+            st.close()
         self._dirtyparents = False
 
     @propertycache