##// END OF EJS Templates
dirstate: remove need_delay logic...
dirstate: remove need_delay logic Now that allĀ¹ stored mtime are non ambiguous, we no longer need to apply the `need_delay` step. The need delay logic was not great are mtime gathered during longer operation could be ambiguous but younger than the `dirstate.write` call time. So, we don't need that logic anymore and can drop it This make the code much simpler. The code related to the test extension faking the dirstate write is now obsolete and associated test will be migrated as follow up. They currently do not break. [1] except the ones from `hg update`, but `need_delay` no longer help for them either. Differential Revision: https://phab.mercurial-scm.org/D11796

File last commit:

r49166:eb428010 default
r49221:434de129 default
Show More
manifest.rs
119 lines | 3.6 KiB | application/rls-services+xml | RustLexer
use crate::errors::HgError;
use crate::repo::Repo;
use crate::revlog::revlog::{Revlog, RevlogError};
use crate::revlog::Revision;
use crate::revlog::{Node, NodePrefix};
use crate::utils::hg_path::HgPath;
use crate::utils::SliceExt;
/// A specialized `Revlog` to work with `manifest` data format.
pub struct Manifestlog {
/// The generic `revlog` format.
revlog: Revlog,
}
impl Manifestlog {
/// Open the `manifest` of a repository given by its root.
pub fn open(repo: &Repo) -> Result<Self, HgError> {
let revlog = Revlog::open(repo, "00manifest.i", None)?;
Ok(Self { revlog })
}
/// Return the `Manifest` for the given node ID.
///
/// Note: this is a node ID in the manifestlog, typically found through
/// `ChangelogEntry::manifest_node`. It is *not* the node ID of any
/// changeset.
///
/// See also `Repo::manifest_for_node`
pub fn data_for_node(
&self,
node: NodePrefix,
) -> Result<Manifest, RevlogError> {
let rev = self.revlog.rev_from_node(node)?;
self.data_for_rev(rev)
}
/// Return the `Manifest` of a given revision number.
///
/// Note: this is a revision number in the manifestlog, *not* of any
/// changeset.
///
/// See also `Repo::manifest_for_rev`
pub fn data_for_rev(
&self,
rev: Revision,
) -> Result<Manifest, RevlogError> {
let bytes = self.revlog.get_rev_data(rev)?;
Ok(Manifest { bytes })
}
}
/// `Manifestlog` entry which knows how to interpret the `manifest` data bytes.
#[derive(Debug)]
pub struct Manifest {
bytes: Vec<u8>,
}
impl Manifest {
pub fn iter(
&self,
) -> impl Iterator<Item = Result<ManifestEntry, HgError>> {
self.bytes
.split(|b| b == &b'\n')
.filter(|line| !line.is_empty())
.map(|line| {
let (path, rest) = line.split_2(b'\0').ok_or_else(|| {
HgError::corrupted("manifest line should contain \\0")
})?;
let path = HgPath::new(path);
let (hex_node_id, flags) = match rest.split_last() {
Some((&b'x', rest)) => (rest, Some(b'x')),
Some((&b'l', rest)) => (rest, Some(b'l')),
Some((&b't', rest)) => (rest, Some(b't')),
_ => (rest, None),
};
Ok(ManifestEntry {
path,
hex_node_id,
flags,
})
})
}
/// If the given path is in this manifest, return its filelog node ID
pub fn find_file(
&self,
path: &HgPath,
) -> Result<Option<ManifestEntry>, HgError> {
// TODO: use binary search instead of linear scan. This may involve
// building (and caching) an index of the byte indicex of each manifest
// line.
// TODO: use try_find when available (if still using linear scan)
// https://github.com/rust-lang/rust/issues/63178
for entry in self.iter() {
let entry = entry?;
if entry.path == path {
return Ok(Some(entry));
}
}
Ok(None)
}
}
/// `Manifestlog` entry which knows how to interpret the `manifest` data bytes.
#[derive(Debug)]
pub struct ManifestEntry<'manifest> {
pub path: &'manifest HgPath,
pub hex_node_id: &'manifest [u8],
/// `Some` values are b'x', b'l', or 't'
pub flags: Option<u8>,
}
impl ManifestEntry<'_> {
pub fn node_id(&self) -> Result<Node, HgError> {
Node::from_hex_for_repo(self.hex_node_id)
}
}