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
--- 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))
};