- Hash encoded path are in .hg/store/dh instead of .hg/store/data.
- Path encoded index and data files may not have the same parent path. It is not just about replacing .i by .d
Alphare |
hg-reviewers |
Automatic diff as part of commit; lint not applicable. |
Automatic diff as part of commit; unit tests not applicable. |
Path | Packages | |||
---|---|---|---|---|
M | rust/hg-core/src/operations/cat.rs (33 lines) | |||
M | rust/hg-core/src/operations/debugdata.rs (2 lines) | |||
M | rust/hg-core/src/revlog/changelog.rs (2 lines) | |||
M | rust/hg-core/src/revlog/manifest.rs (2 lines) | |||
M | rust/hg-core/src/revlog/revlog.rs (12 lines) |
.parse::<Revision>() | .parse::<Revision>() | ||||
.or(Err(DebugDataErrorKind::InvalidRevision))?; | .or(Err(DebugDataErrorKind::InvalidRevision))?; | ||||
let root = find_root::FindRoot::new().run()?; | let root = find_root::FindRoot::new().run()?; | ||||
let index_file = match self.kind { | let index_file = match self.kind { | ||||
DebugDataKind::Changelog => root.join(".hg/store/00changelog.i"), | DebugDataKind::Changelog => root.join(".hg/store/00changelog.i"), | ||||
DebugDataKind::Manifest => root.join(".hg/store/00manifest.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)?; | let data = revlog.get_rev_data(rev)?; | ||||
Ok(data) | Ok(data) | ||||
} | } | ||||
} | } |
use crate::revlog::revlog::{Revlog, RevlogError}; | use crate::revlog::revlog::{Revlog, RevlogError}; | ||||
use crate::revlog::Revision; | use crate::revlog::Revision; | ||||
use std::path::PathBuf; | use std::path::PathBuf; | ||||
/// A specialized `Revlog` to work with `changelog` data format. | /// A specialized `Revlog` to work with `changelog` data format. | ||||
pub struct Changelog { | pub struct Changelog { | ||||
/// The generic `revlog` format. | /// The generic `revlog` format. | ||||
revlog: Revlog, | revlog: Revlog, | ||||
} | } | ||||
impl Changelog { | impl Changelog { | ||||
/// Open the `changelog` of a repository given by its root. | /// Open the `changelog` of a repository given by its root. | ||||
pub fn open(root: &PathBuf) -> Result<Self, RevlogError> { | pub fn open(root: &PathBuf) -> Result<Self, RevlogError> { | ||||
let index_file = root.join(".hg/store/00changelog.i"); | 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 }) | Ok(Self { revlog }) | ||||
} | } | ||||
/// Return the `ChangelogEntry` a given node id. | /// Return the `ChangelogEntry` a given node id. | ||||
pub fn get_node( | pub fn get_node( | ||||
&self, | &self, | ||||
node: &[u8], | node: &[u8], | ||||
) -> Result<ChangelogEntry, RevlogError> { | ) -> Result<ChangelogEntry, RevlogError> { |
use crate::revlog::revlog::{Revlog, RevlogError}; | use crate::revlog::revlog::{Revlog, RevlogError}; | ||||
use crate::revlog::Revision; | use crate::revlog::Revision; | ||||
use crate::utils::hg_path::HgPath; | use crate::utils::hg_path::HgPath; | ||||
use std::path::PathBuf; | use std::path::PathBuf; | ||||
/// A specialized `Revlog` to work with `manifest` data format. | /// A specialized `Revlog` to work with `manifest` data format. | ||||
pub struct Manifest { | pub struct Manifest { | ||||
/// The generic `revlog` format. | /// The generic `revlog` format. | ||||
revlog: Revlog, | revlog: Revlog, | ||||
} | } | ||||
impl Manifest { | impl Manifest { | ||||
/// Open the `manifest` of a repository given by its root. | /// Open the `manifest` of a repository given by its root. | ||||
pub fn open(root: &PathBuf) -> Result<Self, RevlogError> { | pub fn open(root: &PathBuf) -> Result<Self, RevlogError> { | ||||
let index_file = root.join(".hg/store/00manifest.i"); | 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 }) | Ok(Self { revlog }) | ||||
} | } | ||||
/// Return the `ManifestEntry` of a given node id. | /// Return the `ManifestEntry` of a given node id. | ||||
pub fn get_node(&self, node: &[u8]) -> Result<ManifestEntry, RevlogError> { | pub fn get_node(&self, node: &[u8]) -> Result<ManifestEntry, RevlogError> { | ||||
let rev = self.revlog.get_node_rev(node)?; | let rev = self.revlog.get_node_rev(node)?; | ||||
self.get_rev(rev) | self.get_rev(rev) | ||||
} | } |
} | } | ||||
impl Revlog { | impl Revlog { | ||||
/// Open a revlog index file. | /// Open a revlog index file. | ||||
/// | /// | ||||
/// It will also open the associated data file if index and data are not | /// It will also open the associated data file if index and data are not | ||||
/// interleaved. | /// interleaved. | ||||
#[timed] | #[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 = | let index_mmap = | ||||
mmap_open(&index_path).map_err(RevlogError::IoError)?; | mmap_open(&index_path).map_err(RevlogError::IoError)?; | ||||
let version = get_version(&index_mmap); | let version = get_version(&index_mmap); | ||||
if version != 1 { | if version != 1 { | ||||
return Err(RevlogError::UnsuportedVersion(version)); | return Err(RevlogError::UnsuportedVersion(version)); | ||||
} | } | ||||
let index = Index::new(Box::new(index_mmap))?; | 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 | // type annotation required | ||||
// won't recognize Mmap as Deref<Target = [u8]> | // won't recognize Mmap as Deref<Target = [u8]> | ||||
let data_bytes: Option<Box<dyn Deref<Target = [u8]> + Send>> = | let data_bytes: Option<Box<dyn Deref<Target = [u8]> + Send>> = | ||||
if index.is_inline() { | if index.is_inline() { | ||||
None | None | ||||
} else { | } else { | ||||
let data_path = index_path.with_extension("d"); | let data_path = data_path.unwrap_or(&default_data_path); | ||||
let data_mmap = | let data_mmap = | ||||
mmap_open(&data_path).map_err(RevlogError::IoError)?; | mmap_open(data_path).map_err(RevlogError::IoError)?; | ||||
Some(Box::new(data_mmap)) | Some(Box::new(data_mmap)) | ||||
}; | }; | ||||
Ok(Revlog { index, data_bytes }) | Ok(Revlog { index, data_bytes }) | ||||
} | } | ||||
/// Return number of entries of the `Revlog`. | /// Return number of entries of the `Revlog`. | ||||
pub fn len(&self) -> usize { | pub fn len(&self) -> usize { |
I don't like the use of format! instead of get_path_from_bytes, no need for UTF8 lossy conversion, that just gives the wrong impression. Maybe that wouldn't work on some platforms, even.