changeset 45806:7252f5237352

hg-core: fix path encoding usage 1. Hash encoded path are in `.hg/store/dh` instead of `.hg/store/data`. 2. Path encoded index and data files may not have the same parent path. It is not just about replacing `.i` by `.d` Differential Revision: https://phab.mercurial-scm.org/D9121
author Antoine cezar<acezar@chwitlabs.fr>
date Mon, 28 Sep 2020 17:13:15 +0200
parents 49535e56fab8
children f90943d753ef
files rust/hg-core/src/operations/cat.rs rust/hg-core/src/operations/debugdata.rs rust/hg-core/src/revlog/changelog.rs rust/hg-core/src/revlog/manifest.rs rust/hg-core/src/revlog/revlog.rs
diffstat 5 files changed, 33 insertions(+), 18 deletions(-) [+]
line wrap: on
line diff
--- a/rust/hg-core/src/operations/cat.rs	Mon Oct 26 11:45:32 2020 +0100
+++ b/rust/hg-core/src/operations/cat.rs	Mon Sep 28 17:13:15 2020 +0200
@@ -6,7 +6,7 @@
 // GNU General Public License version 2 or any later version.
 
 use std::convert::From;
-use std::path::PathBuf;
+use std::path::{Path, PathBuf};
 
 use crate::revlog::changelog::Changelog;
 use crate::revlog::manifest::{Manifest, ManifestEntry};
@@ -14,7 +14,8 @@
 use crate::revlog::revlog::Revlog;
 use crate::revlog::revlog::RevlogError;
 use crate::revlog::Revision;
-use crate::utils::hg_path::HgPathBuf;
+use crate::utils::files::get_path_from_bytes;
+use crate::utils::hg_path::{HgPath, HgPathBuf};
 
 const METADATA_DELIMITER: [u8; 2] = [b'\x01', b'\n'];
 
@@ -121,15 +122,13 @@
             {
                 for cat_file in self.files.iter() {
                     if cat_file.as_bytes() == manifest_file.as_bytes() {
-                        let encoded_bytes =
-                            path_encode(manifest_file.as_bytes());
-                        let revlog_index_string = format!(
-                            ".hg/store/data/{}.i",
-                            String::from_utf8_lossy(&encoded_bytes),
-                        );
-                        let revlog_index_path =
-                            self.root.join(&revlog_index_string);
-                        let file_log = Revlog::open(&revlog_index_path)?;
+                        let index_path =
+                            store_path(self.root, manifest_file, b".i");
+                        let data_path =
+                            store_path(self.root, manifest_file, b".d");
+
+                        let file_log =
+                            Revlog::open(&index_path, Some(&data_path))?;
                         let file_node = hex::decode(&node_bytes)
                             .map_err(|_| CatRevErrorKind::CorruptedRevlog)?;
                         let file_rev = file_log.get_node_rev(&file_node)?;
@@ -156,3 +155,15 @@
         }
     }
 }
+
+fn store_path(root: &Path, hg_path: &HgPath, suffix: &[u8]) -> PathBuf {
+    let encoded_bytes =
+        path_encode(&[b"data/", hg_path.as_bytes(), suffix].concat());
+    [
+        root,
+        &Path::new(".hg/store/"),
+        get_path_from_bytes(&encoded_bytes),
+    ]
+    .iter()
+    .collect()
+}
--- a/rust/hg-core/src/operations/debugdata.rs	Mon Oct 26 11:45:32 2020 +0100
+++ b/rust/hg-core/src/operations/debugdata.rs	Mon Sep 28 17:13:15 2020 +0200
@@ -102,7 +102,7 @@
             DebugDataKind::Changelog => root.join(".hg/store/00changelog.i"),
             DebugDataKind::Manifest => root.join(".hg/store/00manifest.i"),
         };
-        let revlog = Revlog::open(&index_file)?;
+        let revlog = Revlog::open(&index_file, None)?;
         let data = revlog.get_rev_data(rev)?;
 
         Ok(data)
--- a/rust/hg-core/src/revlog/changelog.rs	Mon Oct 26 11:45:32 2020 +0100
+++ b/rust/hg-core/src/revlog/changelog.rs	Mon Sep 28 17:13:15 2020 +0200
@@ -12,7 +12,7 @@
     /// Open the `changelog` of a repository given by its root.
     pub fn open(root: &PathBuf) -> Result<Self, RevlogError> {
         let index_file = root.join(".hg/store/00changelog.i");
-        let revlog = Revlog::open(&index_file)?;
+        let revlog = Revlog::open(&index_file, None)?;
         Ok(Self { revlog })
     }
 
--- a/rust/hg-core/src/revlog/manifest.rs	Mon Oct 26 11:45:32 2020 +0100
+++ b/rust/hg-core/src/revlog/manifest.rs	Mon Sep 28 17:13:15 2020 +0200
@@ -13,7 +13,7 @@
     /// Open the `manifest` of a repository given by its root.
     pub fn open(root: &PathBuf) -> Result<Self, RevlogError> {
         let index_file = root.join(".hg/store/00manifest.i");
-        let revlog = Revlog::open(&index_file)?;
+        let revlog = Revlog::open(&index_file, None)?;
         Ok(Self { revlog })
     }
 
--- a/rust/hg-core/src/revlog/revlog.rs	Mon Oct 26 11:45:32 2020 +0100
+++ b/rust/hg-core/src/revlog/revlog.rs	Mon Sep 28 17:13:15 2020 +0200
@@ -47,7 +47,10 @@
     /// It will also open the associated data file if index and data are not
     /// interleaved.
     #[timed]
-    pub fn open(index_path: &Path) -> Result<Self, RevlogError> {
+    pub fn open(
+        index_path: &Path,
+        data_path: Option<&Path>,
+    ) -> Result<Self, RevlogError> {
         let index_mmap =
             mmap_open(&index_path).map_err(RevlogError::IoError)?;
 
@@ -58,16 +61,17 @@
 
         let index = Index::new(Box::new(index_mmap))?;
 
-        // TODO load data only when needed //
+        let default_data_path = index_path.with_extension("d");
+
         // type annotation required
         // won't recognize Mmap as Deref<Target = [u8]>
         let data_bytes: Option<Box<dyn Deref<Target = [u8]> + Send>> =
             if index.is_inline() {
                 None
             } else {
-                let data_path = index_path.with_extension("d");
+                let data_path = data_path.unwrap_or(&default_data_path);
                 let data_mmap =
-                    mmap_open(&data_path).map_err(RevlogError::IoError)?;
+                    mmap_open(data_path).map_err(RevlogError::IoError)?;
                 Some(Box::new(data_mmap))
             };