##// END OF EJS Templates
typing: add basic type hints to localrepo.py...
typing: add basic type hints to localrepo.py There's a lot more that could be done, but this sticks to the obviously correct stuff that is either related to existing imports or primitives. Hopefully this helps smoke out more path related bytes vs str issues in TortoiseHg. I'm avoiding the interfaces for now, because they seem to confuse pytype and/or PyCharm. It might be worth typing the return of `makelocalrepository` to `localrepository`, but that leaks an implementation detail, so that can be revisited later.

File last commit:

r49977:704e993e default
r50466:8fa3f7c3 default
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};
use crate::utils::strip_suffix;
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) =
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");
let prefix = strip_suffix(docket_name, ".n.a")
.or_else(|| strip_suffix(docket_name, ".n"))
.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)
}