diff rust/rhg/src/commands/status.rs @ 47674:ff97e793ed36

dirstate-v2: Introduce a docket file .hg/dirstate now only contains some metadata to point to a separate data file named .hg/dirstate.{}.d with a random hexadecimal identifier. For now every update creates a new data file and removes the old one, but later we?ll (usually) append to an existing file. Separating into two files allows doing the "write to a temporary file then atomically rename into destination" dance with only a small docket file, without always rewriting a lot of data. Differential Revision: https://phab.mercurial-scm.org/D11088
author Simon Sapin <simon.sapin@octobus.net>
date Thu, 08 Jul 2021 12:18:21 +0200
parents bd88b6bfd8da
children 48aec076b8fb
line wrap: on
line diff
--- a/rust/rhg/src/commands/status.rs	Thu Jul 15 17:24:09 2021 +0200
+++ b/rust/rhg/src/commands/status.rs	Thu Jul 08 12:18:21 2021 +0200
@@ -10,6 +10,7 @@
 use clap::{Arg, SubCommand};
 use hg;
 use hg::dirstate_tree::dirstate_map::DirstateMap;
+use hg::dirstate_tree::on_disk;
 use hg::errors::HgResultExt;
 use hg::errors::IoResultExt;
 use hg::matchers::AlwaysMatcher;
@@ -165,17 +166,33 @@
     };
 
     let repo = invocation.repo?;
-    let dirstate_data =
-        repo.hg_vfs().mmap_open("dirstate").io_not_found_as_none()?;
-    let dirstate_data = match &dirstate_data {
-        Some(mmap) => &**mmap,
-        None => b"",
-    };
+    let dirstate_data_mmap;
     let (mut dmap, parents) = if repo.has_dirstate_v2() {
-        DirstateMap::new_v2(dirstate_data)?
+        let parents;
+        let dirstate_data;
+        if let Some(docket_data) =
+            repo.hg_vfs().read("dirstate").io_not_found_as_none()?
+        {
+            let docket = on_disk::read_docket(&docket_data)?;
+            parents = Some(docket.parents());
+            dirstate_data_mmap = repo
+                .hg_vfs()
+                .mmap_open(docket.data_filename())
+                .io_not_found_as_none()?;
+            dirstate_data = dirstate_data_mmap.as_deref().unwrap_or(b"");
+        } else {
+            parents = None;
+            dirstate_data = b"";
+        }
+        let dmap = DirstateMap::new_v2(dirstate_data)?;
+        (dmap, parents)
     } else {
+        dirstate_data_mmap =
+            repo.hg_vfs().mmap_open("dirstate").io_not_found_as_none()?;
+        let dirstate_data = dirstate_data_mmap.as_deref().unwrap_or(b"");
         DirstateMap::new_v1(dirstate_data)?
     };
+
     let options = StatusOptions {
         // TODO should be provided by the dirstate parsing and
         // hence be stored on dmap. Using a value that assumes we aren't