rust: use new revlog configs in all revlog opening code
authorRaphaël Gomès <rgomes@octobus.net>
Wed, 19 Jun 2024 12:49:26 +0200
changeset 51867 69b804c8e09e
parent 51866 09ece563609a
child 51868 db7dbe6f7bb2
rust: use new revlog configs in all revlog opening code This centralizes the more complex logic needed for the upcoming code and creates stronger APIs with fewer booleans. We also reuse `RevlogType` where needed.
rust/hg-core/src/operations/debugdata.rs
rust/hg-core/src/operations/mod.rs
rust/hg-core/src/repo.rs
rust/hg-core/src/revlog/changelog.rs
rust/hg-core/src/revlog/mod.rs
rust/rhg/src/commands/debugdata.rs
rust/rhg/src/commands/status.rs
--- a/rust/hg-core/src/operations/debugdata.rs	Tue Sep 17 10:18:32 2024 +0200
+++ b/rust/hg-core/src/operations/debugdata.rs	Wed Jun 19 12:49:26 2024 +0200
@@ -5,31 +5,33 @@
 // This software may be used and distributed according to the terms of the
 // GNU General Public License version 2 or any later version.
 
+use crate::errors::HgError;
 use crate::repo::Repo;
-use crate::revlog::{Revlog, RevlogError};
-
-/// Kind of data to debug
-#[derive(Debug, Copy, Clone, PartialEq, Eq)]
-pub enum DebugDataKind {
-    Changelog,
-    Manifest,
-}
+use crate::revlog::Revlog;
+use crate::{exit_codes, RevlogError, RevlogType};
 
 /// Dump the contents data of a revision.
 pub fn debug_data(
     repo: &Repo,
     revset: &str,
-    kind: DebugDataKind,
+    kind: RevlogType,
 ) -> Result<Vec<u8>, RevlogError> {
     let index_file = match kind {
-        DebugDataKind::Changelog => "00changelog.i",
-        DebugDataKind::Manifest => "00manifest.i",
+        RevlogType::Changelog => "00changelog.i",
+        RevlogType::Manifestlog => "00manifest.i",
+        _ => {
+            return Err(RevlogError::Other(HgError::abort(
+                format!("invalid revlog type {}", kind),
+                exit_codes::ABORT,
+                None,
+            )))
+        }
     };
     let revlog = Revlog::open(
         &repo.store_vfs(),
         index_file,
         None,
-        repo.default_revlog_options(kind == DebugDataKind::Changelog)?,
+        repo.default_revlog_options(RevlogType::Changelog)?,
     )?;
     let rev =
         crate::revset::resolve_rev_number_or_hex_prefix(revset, &revlog)?;
--- a/rust/hg-core/src/operations/mod.rs	Tue Sep 17 10:18:32 2024 +0200
+++ b/rust/hg-core/src/operations/mod.rs	Wed Jun 19 12:49:26 2024 +0200
@@ -7,6 +7,6 @@
 mod list_tracked_files;
 mod status_rev_rev;
 pub use cat::{cat, CatOutput};
-pub use debugdata::{debug_data, DebugDataKind};
+pub use debugdata::debug_data;
 pub use list_tracked_files::{list_rev_tracked_files, FilesForRev};
 pub use status_rev_rev::{status_rev_rev_no_copies, DiffStatus, StatusRevRev};
--- a/rust/hg-core/src/repo.rs	Tue Sep 17 10:18:32 2024 +0200
+++ b/rust/hg-core/src/repo.rs	Wed Jun 19 12:49:26 2024 +0200
@@ -20,7 +20,8 @@
 use crate::utils::SliceExt;
 use crate::vfs::{is_dir, is_file, Vfs};
 use crate::{
-    requirements, NodePrefix, RevlogVersionOptions, UncheckedRevision,
+    requirements, NodePrefix, RevlogDataConfig, RevlogDeltaConfig,
+    RevlogFeatureConfig, RevlogType, RevlogVersionOptions, UncheckedRevision,
 };
 use crate::{DirstateError, RevlogOpenOptions};
 use std::cell::{Ref, RefCell, RefMut};
@@ -529,7 +530,10 @@
     }
 
     fn new_changelog(&self) -> Result<Changelog, HgError> {
-        Changelog::open(&self.store_vfs(), self.default_revlog_options(true)?)
+        Changelog::open(
+            &self.store_vfs(),
+            self.default_revlog_options(RevlogType::Changelog)?,
+        )
     }
 
     pub fn changelog(&self) -> Result<Ref<Changelog>, HgError> {
@@ -543,7 +547,7 @@
     fn new_manifestlog(&self) -> Result<Manifestlog, HgError> {
         Manifestlog::open(
             &self.store_vfs(),
-            self.default_revlog_options(false)?,
+            self.default_revlog_options(RevlogType::Manifestlog)?,
         )
     }
 
@@ -590,9 +594,12 @@
     }
 
     pub fn filelog(&self, path: &HgPath) -> Result<Filelog, HgError> {
-        Filelog::open(self, path, self.default_revlog_options(false)?)
+        Filelog::open(
+            self,
+            path,
+            self.default_revlog_options(RevlogType::Filelog)?,
+        )
     }
-
     /// Write to disk any updates that were made through `dirstate_map_mut`.
     ///
     /// The "wlock" must be held while calling this.
@@ -742,10 +749,11 @@
 
     pub fn default_revlog_options(
         &self,
-        changelog: bool,
+        revlog_type: RevlogType,
     ) -> Result<RevlogOpenOptions, HgError> {
         let requirements = self.requirements();
-        let version = if changelog
+        let is_changelog = revlog_type == RevlogType::Changelog;
+        let version = if is_changelog
             && requirements.contains(CHANGELOGV2_REQUIREMENT)
         {
             let compute_rank = self
@@ -756,7 +764,8 @@
             RevlogVersionOptions::V2
         } else if requirements.contains(REVLOGV1_REQUIREMENT) {
             RevlogVersionOptions::V1 {
-                generaldelta: requirements.contains(GENERALDELTA_REQUIREMENT),
+                general_delta: requirements.contains(GENERALDELTA_REQUIREMENT),
+                inline: !is_changelog,
             }
         } else {
             RevlogVersionOptions::V0
@@ -766,6 +775,19 @@
             // We don't need to dance around the slow path like in the Python
             // implementation since we know we have access to the fast code.
             use_nodemap: requirements.contains(NODEMAP_REQUIREMENT),
+            delta_config: RevlogDeltaConfig::new(
+                self.config(),
+                self.requirements(),
+                revlog_type,
+            )?,
+            data_config: RevlogDataConfig::new(
+                self.config(),
+                self.requirements(),
+            )?,
+            feature_config: RevlogFeatureConfig::new(
+                self.config(),
+                requirements,
+            )?,
         })
     }
 }
--- a/rust/hg-core/src/revlog/changelog.rs	Tue Sep 17 10:18:32 2024 +0200
+++ b/rust/hg-core/src/revlog/changelog.rs	Wed Jun 19 12:49:26 2024 +0200
@@ -501,7 +501,10 @@
 mod tests {
     use super::*;
     use crate::vfs::Vfs;
-    use crate::NULL_REVISION;
+    use crate::{
+        RevlogDataConfig, RevlogDeltaConfig, RevlogFeatureConfig,
+        NULL_REVISION,
+    };
     use pretty_assertions::assert_eq;
 
     #[test]
@@ -562,9 +565,19 @@
         let temp = tempfile::tempdir().unwrap();
         let vfs = Vfs { base: temp.path() };
         std::fs::write(temp.path().join("foo.i"), b"").unwrap();
-        let revlog =
-            Revlog::open(&vfs, "foo.i", None, RevlogOpenOptions::new())
-                .unwrap();
+        std::fs::write(temp.path().join("foo.d"), b"").unwrap();
+        let revlog = Revlog::open(
+            &vfs,
+            "foo.i",
+            None,
+            RevlogOpenOptions::new(
+                false,
+                RevlogDataConfig::default(),
+                RevlogDeltaConfig::default(),
+                RevlogFeatureConfig::default(),
+            ),
+        )
+        .unwrap();
 
         let changelog = Changelog { revlog };
         assert_eq!(
--- a/rust/hg-core/src/revlog/mod.rs	Tue Sep 17 10:18:32 2024 +0200
+++ b/rust/hg-core/src/revlog/mod.rs	Wed Jun 19 12:49:26 2024 +0200
@@ -223,7 +223,7 @@
     }
 }
 
-#[derive(Debug, Copy, Clone, PartialEq, Eq)]
+#[derive(derive_more::Display, Debug, Copy, Clone, PartialEq, Eq)]
 pub enum RevlogType {
     Changelog,
     Manifestlog,
@@ -368,8 +368,8 @@
             }
         }
 
-        if let Some(mmap_index_threshold) =
-            config.get_byte_size(b"experimental", b"mmapindexthreshold")?
+        if let Some(mmap_index_threshold) = config
+            .get_byte_size(b"storage", b"revlog.mmap.index:size-threshold")?
         {
             data_config.mmap_index_threshold = Some(mmap_index_threshold);
         }
@@ -618,10 +618,10 @@
     }
 }
 
-#[derive(Debug, Copy, Clone)]
+#[derive(Debug, Copy, Clone, PartialEq)]
 pub enum RevlogVersionOptions {
     V0,
-    V1 { generaldelta: bool },
+    V1 { general_delta: bool, inline: bool },
     V2,
     ChangelogV2 { compute_rank: bool },
 }
@@ -634,24 +634,65 @@
     pub version: RevlogVersionOptions,
     /// Whether the revlog uses a persistent nodemap.
     pub use_nodemap: bool,
-    // TODO other non-header/version options,
+    pub delta_config: RevlogDeltaConfig,
+    pub data_config: RevlogDataConfig,
+    pub feature_config: RevlogFeatureConfig,
+}
+
+#[cfg(test)]
+impl Default for RevlogOpenOptions {
+    fn default() -> Self {
+        Self {
+            version: RevlogVersionOptions::V1 {
+                general_delta: true,
+                inline: false,
+            },
+            use_nodemap: true,
+            data_config: Default::default(),
+            delta_config: Default::default(),
+            feature_config: Default::default(),
+        }
+    }
 }
 
 impl RevlogOpenOptions {
-    pub fn new() -> Self {
+    pub fn new(
+        inline: bool,
+        data_config: RevlogDataConfig,
+        delta_config: RevlogDeltaConfig,
+        feature_config: RevlogFeatureConfig,
+    ) -> Self {
         Self {
-            version: RevlogVersionOptions::V1 { generaldelta: true },
+            version: RevlogVersionOptions::V1 {
+                general_delta: data_config.general_delta,
+                inline,
+            },
             use_nodemap: false,
+            data_config,
+            delta_config,
+            feature_config,
         }
     }
 
-    fn default_index_header(&self) -> index::IndexHeader {
+    pub fn index_header(&self) -> index::IndexHeader {
         index::IndexHeader {
             header_bytes: match self.version {
                 RevlogVersionOptions::V0 => [0, 0, 0, 0],
-                RevlogVersionOptions::V1 { generaldelta } => {
-                    [0, if generaldelta { 3 } else { 1 }, 0, 1]
-                }
+                RevlogVersionOptions::V1 {
+                    general_delta,
+                    inline,
+                } => [
+                    0,
+                    if general_delta && inline {
+                        3
+                    } else if general_delta {
+                        2
+                    } else {
+                        u8::from(inline)
+                    },
+                    0,
+                    1,
+                ],
                 RevlogVersionOptions::V2 => 0xDEADu32.to_be_bytes(),
                 RevlogVersionOptions::ChangelogV2 { compute_rank: _ } => {
                     0xD34Du32.to_be_bytes()
@@ -661,12 +702,6 @@
     }
 }
 
-impl Default for RevlogOpenOptions {
-    fn default() -> Self {
-        Self::new()
-    }
-}
-
 impl Revlog {
     /// Open a revlog index file.
     ///
@@ -693,12 +728,12 @@
             match store_vfs.mmap_open_opt(index_path)? {
                 None => Index::new(
                     Box::<Vec<_>>::default(),
-                    options.default_index_header(),
+                    options.index_header(),
                 ),
                 Some(index_mmap) => {
                     let index = Index::new(
                         Box::new(index_mmap),
-                        options.default_index_header(),
+                        options.index_header(),
                     )?;
                     Ok(index)
                 }
@@ -1265,8 +1300,9 @@
         let temp = tempfile::tempdir().unwrap();
         let vfs = Vfs { base: temp.path() };
         std::fs::write(temp.path().join("foo.i"), b"").unwrap();
+        std::fs::write(temp.path().join("foo.d"), b"").unwrap();
         let revlog =
-            Revlog::open(&vfs, "foo.i", None, RevlogOpenOptions::new())
+            Revlog::open(&vfs, "foo.i", None, RevlogOpenOptions::default())
                 .unwrap();
         assert!(revlog.is_empty());
         assert_eq!(revlog.len(), 0);
@@ -1309,7 +1345,7 @@
             .collect_vec();
         std::fs::write(temp.path().join("foo.i"), contents).unwrap();
         let revlog =
-            Revlog::open(&vfs, "foo.i", None, RevlogOpenOptions::new())
+            Revlog::open(&vfs, "foo.i", None, RevlogOpenOptions::default())
                 .unwrap();
 
         let entry0 = revlog.get_entry(0.into()).ok().unwrap();
@@ -1381,7 +1417,7 @@
             &vfs,
             "foo.i",
             None,
-            RevlogOpenOptions::new(),
+            RevlogOpenOptions::default(),
             Some(idx.nt),
         )
         .unwrap();
--- a/rust/rhg/src/commands/debugdata.rs	Tue Sep 17 10:18:32 2024 +0200
+++ b/rust/rhg/src/commands/debugdata.rs	Wed Jun 19 12:49:26 2024 +0200
@@ -1,7 +1,8 @@
 use crate::error::CommandError;
 use clap::Arg;
 use clap::ArgGroup;
-use hg::operations::{debug_data, DebugDataKind};
+use hg::operations::debug_data;
+use hg::RevlogType;
 
 pub const HELP_TEXT: &str = "
 Dump the contents of a data file revision
@@ -45,8 +46,8 @@
         args.get_one::<bool>("changelog").unwrap(),
         args.get_one::<bool>("manifest").unwrap(),
     ) {
-        (true, false) => DebugDataKind::Changelog,
-        (false, true) => DebugDataKind::Manifest,
+        (true, false) => RevlogType::Changelog,
+        (false, true) => RevlogType::Manifestlog,
         (true, true) => {
             unreachable!("Should not happen since options are exclusive")
         }
--- a/rust/rhg/src/commands/status.rs	Tue Sep 17 10:18:32 2024 +0200
+++ b/rust/rhg/src/commands/status.rs	Wed Jun 19 12:49:26 2024 +0200
@@ -28,12 +28,12 @@
     get_bytes_from_os_str, get_bytes_from_os_string, get_path_from_bytes,
 };
 use hg::utils::hg_path::{hg_path_to_path_buf, HgPath};
-use hg::PatternFileWarning;
 use hg::Revision;
 use hg::StatusError;
 use hg::StatusOptions;
 use hg::{self, narrow, sparse};
 use hg::{DirstateStatus, RevlogOpenOptions};
+use hg::{PatternFileWarning, RevlogType};
 use log::info;
 use rayon::prelude::*;
 use std::borrow::Cow;
@@ -383,7 +383,8 @@
             })?;
             let working_directory_vfs = repo.working_directory_vfs();
             let store_vfs = repo.store_vfs();
-            let revlog_open_options = repo.default_revlog_options(false)?;
+            let revlog_open_options =
+                repo.default_revlog_options(RevlogType::Manifestlog)?;
             let res: Vec<_> = take(&mut ds_status.unsure)
                 .into_par_iter()
                 .map(|to_check| {