view rust/hg-core/src/revlog/manifest.rs @ 46243:63c923fd7fa8

setup: when possible, build and bundle man pages This makes it so the manual pages are built as part of the Python build, and includes them in any wheel generated. This should make Python wheels a much more useful and complete way of distributing Mercurial binaries. Differential Revision: https://phab.mercurial-scm.org/D9640
author Dan Villiom Podlaski Christiansen <danchr@gmail.com>
date Mon, 21 Dec 2020 15:50:01 +0100
parents 8a4914397d02
children 645ee7225fab
line wrap: on
line source

use crate::repo::Repo;
use crate::revlog::revlog::{Revlog, RevlogError};
use crate::revlog::NodePrefixRef;
use crate::revlog::Revision;
use crate::utils::hg_path::HgPath;

/// A specialized `Revlog` to work with `manifest` data format.
pub struct Manifest {
    /// The generic `revlog` format.
    revlog: Revlog,
}

impl Manifest {
    /// Open the `manifest` of a repository given by its root.
    pub fn open(repo: &Repo) -> Result<Self, RevlogError> {
        let revlog = Revlog::open(repo, "00manifest.i", None)?;
        Ok(Self { revlog })
    }

    /// Return the `ManifestEntry` of a given node id.
    pub fn get_node(
        &self,
        node: NodePrefixRef,
    ) -> Result<ManifestEntry, RevlogError> {
        let rev = self.revlog.get_node_rev(node)?;
        self.get_rev(rev)
    }

    /// Return the `ManifestEntry` of a given node revision.
    pub fn get_rev(
        &self,
        rev: Revision,
    ) -> Result<ManifestEntry, RevlogError> {
        let bytes = self.revlog.get_rev_data(rev)?;
        Ok(ManifestEntry { bytes })
    }
}

/// `Manifest` entry which knows how to interpret the `manifest` data bytes.
#[derive(Debug)]
pub struct ManifestEntry {
    bytes: Vec<u8>,
}

impl ManifestEntry {
    /// Return an iterator over the lines of the entry.
    pub fn lines(&self) -> impl Iterator<Item = &[u8]> {
        self.bytes
            .split(|b| b == &b'\n')
            .filter(|line| !line.is_empty())
    }

    /// Return an iterator over the files of the entry.
    pub fn files(&self) -> impl Iterator<Item = &HgPath> {
        self.lines().filter(|line| !line.is_empty()).map(|line| {
            let pos = line
                .iter()
                .position(|x| x == &b'\0')
                .expect("manifest line should contain \\0");
            HgPath::new(&line[..pos])
        })
    }

    /// Return an iterator over the files of the entry.
    pub fn files_with_nodes(&self) -> impl Iterator<Item = (&HgPath, &[u8])> {
        self.lines().filter(|line| !line.is_empty()).map(|line| {
            let pos = line
                .iter()
                .position(|x| x == &b'\0')
                .expect("manifest line should contain \\0");
            let hash_start = pos + 1;
            let hash_end = hash_start + 40;
            (HgPath::new(&line[..pos]), &line[hash_start..hash_end])
        })
    }
}