Details
Details
- Reviewers
Alphare - Group Reviewers
hg-reviewers
Diff Detail
Diff Detail
- Repository
- rHG Mercurial
- Branch
- default
- Lint
No Linters Available - Unit
No Unit Test Coverage
( )
Alphare |
hg-reviewers |
No Linters Available |
No Unit Test Coverage |
Path | Packages | |||
---|---|---|---|---|
M | rust/hg-core/src/revlog/nodemap_docket.rs (12 lines) | |||
M | rust/hg-core/src/revlog/revlog.rs (2 lines) |
Commit | Parents | Author | Summary | Date |
---|---|---|---|---|
ea65c742e121 | dedd6ed19123 | Martin von Zweigbergk | Fri, Apr 1, 1:54 AM |
Status | Author | Revision | |
---|---|---|---|
Needs Review | martinvonz | ||
Needs Review | martinvonz | ||
Accepted | martinvonz | ||
Accepted | martinvonz | ||
Needs Review | martinvonz | ||
Needs Review | martinvonz | ||
Needs Review | martinvonz | ||
Needs Review | martinvonz | ||
Needs Review | martinvonz | ||
Closed | martinvonz | ||
Accepted | martinvonz | ||
Accepted | martinvonz | ||
Needs Review | martinvonz | ||
Accepted | martinvonz | ||
Accepted | martinvonz | ||
Closed | martinvonz | ||
Closed | martinvonz | ||
Closed | martinvonz | ||
Closed | martinvonz |
use crate::errors::{HgError, HgResultExt}; | use crate::errors::{HgError, HgResultExt}; | ||||
use bytes_cast::{unaligned, BytesCast}; | use bytes_cast::{unaligned, BytesCast}; | ||||
use memmap2::Mmap; | use memmap2::Mmap; | ||||
use std::path::{Path, PathBuf}; | use std::path::{Path, PathBuf}; | ||||
use crate::repo::Repo; | |||||
use crate::utils::strip_suffix; | use crate::utils::strip_suffix; | ||||
use crate::vfs::Vfs; | |||||
const ONDISK_VERSION: u8 = 1; | const ONDISK_VERSION: u8 = 1; | ||||
pub(super) struct NodeMapDocket { | pub(super) struct NodeMapDocket { | ||||
pub data_length: usize, | pub data_length: usize, | ||||
// TODO: keep here more of the data from `parse()` when we need it | // TODO: keep here more of the data from `parse()` when we need it | ||||
} | } | ||||
/// | /// | ||||
/// * This revlog does not have a `.n` docket file (it is not generated for | /// * This revlog does not have a `.n` docket file (it is not generated for | ||||
/// small revlogs), or | /// small revlogs), or | ||||
/// * The docket has an unsupported version number (repositories created by | /// * The docket has an unsupported version number (repositories created by | ||||
/// later hg, maybe that should be a requirement instead?), or | /// later hg, maybe that should be a requirement instead?), or | ||||
/// * The docket file points to a missing (likely deleted) data file (this | /// * The docket file points to a missing (likely deleted) data file (this | ||||
/// can happen in a rare race condition). | /// can happen in a rare race condition). | ||||
pub fn read_from_file( | pub fn read_from_file( | ||||
repo: &Repo, | store_vfs: &Vfs, | ||||
index_path: &Path, | index_path: &Path, | ||||
) -> Result<Option<(Self, Mmap)>, HgError> { | ) -> Result<Option<(Self, Mmap)>, HgError> { | ||||
let docket_path = index_path.with_extension("n"); | let docket_path = index_path.with_extension("n"); | ||||
let docket_bytes = if let Some(bytes) = | let docket_bytes = if let Some(bytes) = | ||||
repo.store_vfs().read(&docket_path).io_not_found_as_none()? | store_vfs.read(&docket_path).io_not_found_as_none()? | ||||
{ | { | ||||
bytes | bytes | ||||
} else { | } else { | ||||
return Ok(None); | return Ok(None); | ||||
}; | }; | ||||
let input = if let Some((&ONDISK_VERSION, rest)) = | let input = if let Some((&ONDISK_VERSION, rest)) = | ||||
docket_bytes.split_first() | docket_bytes.split_first() | ||||
let (_tip_node, _rest) = | let (_tip_node, _rest) = | ||||
parse(u8::slice_from_bytes(rest, tip_node_size))?; | parse(u8::slice_from_bytes(rest, tip_node_size))?; | ||||
let uid = parse(std::str::from_utf8(uid))?; | let uid = parse(std::str::from_utf8(uid))?; | ||||
let docket = NodeMapDocket { data_length }; | let docket = NodeMapDocket { data_length }; | ||||
let data_path = rawdata_path(&docket_path, uid); | let data_path = rawdata_path(&docket_path, uid); | ||||
// TODO: use `vfs.read()` here when the `persistent-nodemap.mmap` | // TODO: use `vfs.read()` here when the `persistent-nodemap.mmap` | ||||
// config is false? | // config is false? | ||||
if let Some(mmap) = repo | if let Some(mmap) = | ||||
.store_vfs() | store_vfs.mmap_open(&data_path).io_not_found_as_none()? | ||||
.mmap_open(&data_path) | |||||
.io_not_found_as_none()? | |||||
{ | { | ||||
if mmap.len() >= data_length { | if mmap.len() >= data_length { | ||||
Ok(Some((docket, mmap))) | Ok(Some((docket, mmap))) | ||||
} else { | } else { | ||||
Err(HgError::corrupted("persistent nodemap too short")) | Err(HgError::corrupted("persistent nodemap too short")) | ||||
} | } | ||||
} else { | } else { | ||||
// Even if .hg/requires opted in, some revlogs are deemed small | // Even if .hg/requires opted in, some revlogs are deemed small |
None | None | ||||
} else if !repo | } else if !repo | ||||
.requirements() | .requirements() | ||||
.contains(requirements::NODEMAP_REQUIREMENT) | .contains(requirements::NODEMAP_REQUIREMENT) | ||||
{ | { | ||||
// If .hg/requires does not opt it, don’t try to open a nodemap | // If .hg/requires does not opt it, don’t try to open a nodemap | ||||
None | None | ||||
} else { | } else { | ||||
NodeMapDocket::read_from_file(repo, index_path)?.map( | NodeMapDocket::read_from_file(&repo.store_vfs(), index_path)?.map( | ||||
|(docket, data)| { | |(docket, data)| { | ||||
nodemap::NodeTree::load_bytes( | nodemap::NodeTree::load_bytes( | ||||
Box::new(data), | Box::new(data), | ||||
docket.data_length, | docket.data_length, | ||||
) | ) | ||||
}, | }, | ||||
) | ) | ||||
}; | }; |