##// END OF EJS Templates
backout: backed out changeset 5d83a40cd3f8...
backout: backed out changeset 5d83a40cd3f8 This is the re-send of the backout in D11757 that I accidentally queued. I'll rewrite the original commit message: ...sigh We do not have Python 3 packaging for thg on Windows where the vast majority of of users use the thg installer for Mercurial. Until this is done (hopefully this cycle), we're keeping Python. (end of the old commit message) On top of this, we have a solid lead to have competent people take care of this packaging issue for us in time for the 6.1 release, which is really the main reason for us to wait. We're trying our best to make this work, so please bear with us. Differential Revision: https://phab.mercurial-scm.org/D11770

File last commit:

r48777:001d747c default
r49233:0ad593b6 default
Show More
nodemap_docket.rs
119 lines | 3.9 KiB | application/rls-services+xml | RustLexer
use crate::errors::{HgError, HgResultExt};
use crate::requirements;
use bytes_cast::{unaligned, BytesCast};
use memmap2::Mmap;
use std::path::{Path, PathBuf};
use crate::repo::Repo;
use crate::utils::strip_suffix;
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
}
#[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,
}
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(
repo: &Repo,
index_path: &Path,
) -> Result<Option<(Self, Mmap)>, HgError> {
if !repo
.requirements()
.contains(requirements::NODEMAP_REQUIREMENT)
{
// If .hg/requires does not opt it, don’t try to open a nodemap
return Ok(None);
}
let docket_path = index_path.with_extension("n");
let docket_bytes = if let Some(bytes) =
repo.store_vfs().read(&docket_path).io_not_found_as_none()?
{
bytes
} else {
return Ok(None);
};
let input = if let Some((&ONDISK_VERSION, rest)) =
docket_bytes.split_first()
{
rest
} else {
return Ok(None);
};
/// Treat any error as a parse error
fn parse<T, E>(result: Result<T, E>) -> Result<T, HgError> {
result
.map_err(|_| HgError::corrupted("nodemap docket parse error"))
}
let (header, rest) = parse(DocketHeader::from_bytes(input))?;
let uid_size = header.uid_size as usize;
// TODO: do we care about overflow for 4 GB+ nodemap files on 32-bit
// systems?
let tip_node_size = header.tip_node_size.get() as usize;
let data_length = header.data_length.get() as usize;
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))?;
let docket = NodeMapDocket { data_length };
let data_path = rawdata_path(&docket_path, uid);
// TODO: use `vfs.read()` here when the `persistent-nodemap.mmap`
// config is false?
if let Some(mmap) = repo
.store_vfs()
.mmap_open(&data_path)
.io_not_found_as_none()?
{
if mmap.len() >= data_length {
Ok(Some((docket, mmap)))
} else {
Err(HgError::corrupted("persistent nodemap too short"))
}
} else {
// Even if .hg/requires opted in, some revlogs are deemed small
// enough to not need a persistent nodemap.
Ok(None)
}
}
}
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)
}