view rust/hg-core/src/operations/debugdata.rs @ 46059:dacb771f6dd2

copies-rust: extract the processing of a ChangedFiles in its own function This is a reasonably independent piece of code that we can extract in its own function. This extraction will be very useful for the next changeset, where we will change the iteration order (but still do the same kind of processing). Differential Revision: https://phab.mercurial-scm.org/D9421
author Pierre-Yves David <pierre-yves.david@octobus.net>
date Fri, 20 Nov 2020 14:17:08 +0100
parents 88e741bf2d93
children dca9cb99971c
line wrap: on
line source

// debugdata.rs
//
// Copyright 2020 Antoine Cezar <antoine.cezar@octobus.net>
//
// This software may be used and distributed according to the terms of the
// GNU General Public License version 2 or any later version.

use super::find_root;
use crate::revlog::revlog::{Revlog, RevlogError};
use crate::revlog::NodePrefix;
use crate::revlog::Revision;

/// Kind of data to debug
#[derive(Debug, Copy, Clone)]
pub enum DebugDataKind {
    Changelog,
    Manifest,
}

/// Kind of error encountered by DebugData
#[derive(Debug)]
pub enum DebugDataErrorKind {
    FindRootError(find_root::FindRootError),
    /// Error when reading a `revlog` file.
    IoError(std::io::Error),
    /// The revision has not been found.
    InvalidRevision,
    /// Found more than one revision whose ID match the requested prefix
    AmbiguousPrefix,
    /// A `revlog` file is corrupted.
    CorruptedRevlog,
    /// The `revlog` format version is not supported.
    UnsuportedRevlogVersion(u16),
    /// The `revlog` data format is not supported.
    UnknowRevlogDataFormat(u8),
}

/// A DebugData error
#[derive(Debug)]
pub struct DebugDataError {
    /// Kind of error encountered by DebugData
    pub kind: DebugDataErrorKind,
}

impl From<DebugDataErrorKind> for DebugDataError {
    fn from(kind: DebugDataErrorKind) -> Self {
        DebugDataError { kind }
    }
}

impl From<find_root::FindRootError> for DebugDataError {
    fn from(err: find_root::FindRootError) -> Self {
        let kind = DebugDataErrorKind::FindRootError(err);
        DebugDataError { kind }
    }
}

impl From<std::io::Error> for DebugDataError {
    fn from(err: std::io::Error) -> Self {
        let kind = DebugDataErrorKind::IoError(err);
        DebugDataError { kind }
    }
}

impl From<RevlogError> for DebugDataError {
    fn from(err: RevlogError) -> Self {
        match err {
            RevlogError::IoError(err) => DebugDataErrorKind::IoError(err),
            RevlogError::UnsuportedVersion(version) => {
                DebugDataErrorKind::UnsuportedRevlogVersion(version)
            }
            RevlogError::InvalidRevision => {
                DebugDataErrorKind::InvalidRevision
            }
            RevlogError::AmbiguousPrefix => {
                DebugDataErrorKind::AmbiguousPrefix
            }
            RevlogError::Corrupted => DebugDataErrorKind::CorruptedRevlog,
            RevlogError::UnknowDataFormat(format) => {
                DebugDataErrorKind::UnknowRevlogDataFormat(format)
            }
        }
        .into()
    }
}

/// Dump the contents data of a revision.
pub struct DebugData<'a> {
    /// Revision or hash of the revision.
    rev: &'a str,
    /// Kind of data to debug.
    kind: DebugDataKind,
}

impl<'a> DebugData<'a> {
    pub fn new(rev: &'a str, kind: DebugDataKind) -> Self {
        DebugData { rev, kind }
    }

    pub fn run(&mut self) -> Result<Vec<u8>, DebugDataError> {
        let root = find_root::FindRoot::new().run()?;
        let index_file = match self.kind {
            DebugDataKind::Changelog => root.join(".hg/store/00changelog.i"),
            DebugDataKind::Manifest => root.join(".hg/store/00manifest.i"),
        };
        let revlog = Revlog::open(&index_file, None)?;

        let data = match self.rev.parse::<Revision>() {
            Ok(rev) => revlog.get_rev_data(rev)?,
            _ => {
                let node = NodePrefix::from_hex(&self.rev)
                    .map_err(|_| DebugDataErrorKind::InvalidRevision)?;
                let rev = revlog.get_node_rev(node.borrow())?;
                revlog.get_rev_data(rev)?
            }
        };

        Ok(data)
    }
}