diff --git a/rust/hg-core/src/operations/cat.rs b/rust/hg-core/src/operations/cat.rs --- a/rust/hg-core/src/operations/cat.rs +++ b/rust/hg-core/src/operations/cat.rs @@ -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() +} diff --git a/rust/hg-core/src/operations/debugdata.rs b/rust/hg-core/src/operations/debugdata.rs --- a/rust/hg-core/src/operations/debugdata.rs +++ b/rust/hg-core/src/operations/debugdata.rs @@ -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) diff --git a/rust/hg-core/src/revlog/changelog.rs b/rust/hg-core/src/revlog/changelog.rs --- a/rust/hg-core/src/revlog/changelog.rs +++ b/rust/hg-core/src/revlog/changelog.rs @@ -12,7 +12,7 @@ /// Open the `changelog` of a repository given by its root. pub fn open(root: &PathBuf) -> Result { 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 }) } diff --git a/rust/hg-core/src/revlog/manifest.rs b/rust/hg-core/src/revlog/manifest.rs --- a/rust/hg-core/src/revlog/manifest.rs +++ b/rust/hg-core/src/revlog/manifest.rs @@ -13,7 +13,7 @@ /// Open the `manifest` of a repository given by its root. pub fn open(root: &PathBuf) -> Result { 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 }) } diff --git a/rust/hg-core/src/revlog/revlog.rs b/rust/hg-core/src/revlog/revlog.rs --- a/rust/hg-core/src/revlog/revlog.rs +++ b/rust/hg-core/src/revlog/revlog.rs @@ -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 { + pub fn open( + index_path: &Path, + data_path: Option<&Path>, + ) -> Result { 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 let data_bytes: Option + 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)) };