##// END OF EJS Templates
tests: use sha256line.py instead of /dev/random in test-censor.t (issue6858)...
tests: use sha256line.py instead of /dev/random in test-censor.t (issue6858) Sometimes the systems that run our test suite don't have enough entropy and they cannot produce target file of the expected size using /dev/random, which results in test failures. Switching to /dev/urandom would give us way more available data at the cost of it being less "random", but we don't really need to use entropy for this task at all, since we only care if the file size after compression is big enough to not be stored inline in the revlog. So let's use something that we already have used to generate this kind of data in other tests.

File last commit:

r52013:532e74ad default
r52255:e7be2ddf stable
Show More
nodemap_docket.rs
108 lines | 3.6 KiB | application/rls-services+xml | RustLexer
Simon Sapin
rust: use HgError in RevlogError and Vfs...
r47172 use crate::errors::{HgError, HgResultExt};
Simon Sapin
rust: use the bytes-cast crate to parse persistent nodemaps...
r47119 use bytes_cast::{unaligned, BytesCast};
Simon Sapin
rust: Switch to the memmap2-rs crate...
r48767 use memmap2::Mmap;
Simon Sapin
rhg: use persistent nodemap when available...
r46706 use std::path::{Path, PathBuf};
Martin von Zweigbergk
rust-nodemap-docket: make unaware of `Repo`...
r49977 use crate::vfs::Vfs;
Simon Sapin
rhg: use persistent nodemap when available...
r46706
const ONDISK_VERSION: u8 = 1;
pub(super) struct NodeMapDocket {
pub data_length: usize,
// TODO: keep here more of the data from `parse()` when we need it
}
Simon Sapin
rust: use the bytes-cast crate to parse persistent nodemaps...
r47119 #[derive(BytesCast)]
#[repr(C)]
struct DocketHeader {
uid_size: u8,
_tip_rev: unaligned::U64Be,
data_length: unaligned::U64Be,
_data_unused: unaligned::U64Be,
tip_node_size: unaligned::U64Be,
}
Simon Sapin
rhg: use persistent nodemap when available...
r46706 impl NodeMapDocket {
/// Return `Ok(None)` when the caller should proceed without a persistent
/// nodemap:
///
/// * This revlog does not have a `.n` docket file (it is not generated for
/// small revlogs), or
/// * The docket has an unsupported version number (repositories created by
/// later hg, maybe that should be a requirement instead?), or
/// * The docket file points to a missing (likely deleted) data file (this
/// can happen in a rare race condition).
pub fn read_from_file(
Martin von Zweigbergk
rust-nodemap-docket: make unaware of `Repo`...
r49977 store_vfs: &Vfs,
Simon Sapin
rhg: use persistent nodemap when available...
r46706 index_path: &Path,
Simon Sapin
rust: Return HgError instead of RevlogError in revlog constructors...
r48777 ) -> Result<Option<(Self, Mmap)>, HgError> {
Simon Sapin
rhg: use persistent nodemap when available...
r46706 let docket_path = index_path.with_extension("n");
Simon Sapin
rust: use HgError in RevlogError and Vfs...
r47172 let docket_bytes = if let Some(bytes) =
Martin von Zweigbergk
rust-nodemap-docket: make unaware of `Repo`...
r49977 store_vfs.read(&docket_path).io_not_found_as_none()?
Simon Sapin
rust: use HgError in RevlogError and Vfs...
r47172 {
bytes
} else {
return Ok(None);
Simon Sapin
rhg: use persistent nodemap when available...
r46706 };
Simon Sapin
rust: use the bytes-cast crate to parse persistent nodemaps...
r47119 let input = if let Some((&ONDISK_VERSION, rest)) =
Simon Sapin
rhg: use persistent nodemap when available...
r46706 docket_bytes.split_first()
{
rest
} else {
return Ok(None);
};
Simon Sapin
rust: use HgError in RevlogError and Vfs...
r47172 /// Treat any error as a parse error
Simon Sapin
rust: Return HgError instead of RevlogError in revlog constructors...
r48777 fn parse<T, E>(result: Result<T, E>) -> Result<T, HgError> {
result
.map_err(|_| HgError::corrupted("nodemap docket parse error"))
Simon Sapin
rust: use HgError in RevlogError and Vfs...
r47172 }
let (header, rest) = parse(DocketHeader::from_bytes(input))?;
Simon Sapin
rust: use the bytes-cast crate to parse persistent nodemaps...
r47119 let uid_size = header.uid_size as usize;
Simon Sapin
rhg: use persistent nodemap when available...
r46706 // TODO: do we care about overflow for 4 GB+ nodemap files on 32-bit
// systems?
Simon Sapin
rust: use the bytes-cast crate to parse persistent nodemaps...
r47119 let tip_node_size = header.tip_node_size.get() as usize;
let data_length = header.data_length.get() as usize;
Simon Sapin
rust: use HgError in RevlogError and Vfs...
r47172 let (uid, rest) = parse(u8::slice_from_bytes(rest, uid_size))?;
let (_tip_node, _rest) =
parse(u8::slice_from_bytes(rest, tip_node_size))?;
let uid = parse(std::str::from_utf8(uid))?;
Simon Sapin
rhg: use persistent nodemap when available...
r46706 let docket = NodeMapDocket { data_length };
let data_path = rawdata_path(&docket_path, uid);
Simon Sapin
rust: use HgError in RevlogError and Vfs...
r47172 // TODO: use `vfs.read()` here when the `persistent-nodemap.mmap`
Simon Sapin
rhg: use persistent nodemap when available...
r46706 // config is false?
Martin von Zweigbergk
rust-nodemap-docket: make unaware of `Repo`...
r49977 if let Some(mmap) =
Raphaël Gomès
rust: run a clippy pass with the latest stable version...
r52013 store_vfs.mmap_open(data_path).io_not_found_as_none()?
Simon Sapin
rust: use HgError in RevlogError and Vfs...
r47172 {
if mmap.len() >= data_length {
Ok(Some((docket, mmap)))
} else {
Simon Sapin
rust: Return HgError instead of RevlogError in revlog constructors...
r48777 Err(HgError::corrupted("persistent nodemap too short"))
Simon Sapin
rhg: use persistent nodemap when available...
r46706 }
Simon Sapin
rust: use HgError in RevlogError and Vfs...
r47172 } else {
Simon Sapin
rhg: Don’t attempt to read persistent nodemap without .hg/requires opt-in...
r47375 // Even if .hg/requires opted in, some revlogs are deemed small
// enough to not need a persistent nodemap.
Simon Sapin
rust: use HgError in RevlogError and Vfs...
r47172 Ok(None)
Simon Sapin
rhg: use persistent nodemap when available...
r46706 }
}
}
fn rawdata_path(docket_path: &Path, uid: &str) -> PathBuf {
let docket_name = docket_path
.file_name()
.expect("expected a base name")
.to_str()
.expect("expected an ASCII file name in the store");
Raphaël Gomès
hg-core: remove unneeded util now that we support Rust 1.42+
r50527 let prefix = docket_name
.strip_suffix(".n.a")
.or_else(|| docket_name.strip_suffix(".n"))
Simon Sapin
rhg: use persistent nodemap when available...
r46706 .expect("expected docket path in .n or .n.a");
let name = format!("{}-{}.nd", prefix, uid);
docket_path
.parent()
.expect("expected a non-root path")
.join(name)
}