rust/hg-core/src/revlog/revlog.rs
author Simon Sapin <simon.sapin@octobus.net>
Thu, 14 Oct 2021 13:58:25 +0200
changeset 48227 4518d91f02d8
parent 48226 5e77bdc29d56
child 48236 f8dc78716ad2
permissions -rw-r--r--
rust: Reformat source code This fixes test-check-rust-format.t which is currently failing on the default branch. Differential Revision: https://phab.mercurial-scm.org/D11657
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
45526
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
     1
use std::borrow::Cow;
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
     2
use std::io::Read;
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
     3
use std::ops::Deref;
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
     4
use std::path::Path;
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
     5
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
     6
use byteorder::{BigEndian, ByteOrder};
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
     7
use flate2::read::ZlibDecoder;
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
     8
use micro_timer::timed;
47380
fad504cfc94b rust: Use a maintained crate for SHA-1 hashing
Simon Sapin <simon.sapin@octobus.net>
parents: 46821
diff changeset
     9
use sha1::{Digest, Sha1};
45526
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    10
use zstd;
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    11
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    12
use super::index::Index;
46431
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46390
diff changeset
    13
use super::node::{NodePrefix, NODE_BYTES_LENGTH, NULL_NODE};
46090
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents: 46033
diff changeset
    14
use super::nodemap;
46443
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46433
diff changeset
    15
use super::nodemap::{NodeMap, NodeMapError};
46090
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents: 46033
diff changeset
    16
use super::nodemap_docket::NodeMapDocket;
45526
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    17
use super::patch;
46443
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46433
diff changeset
    18
use crate::errors::HgError;
46167
8a4914397d02 rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents: 46090
diff changeset
    19
use crate::repo::Repo;
45526
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    20
use crate::revlog::Revision;
47967
6c653d9d41b8 rust: Make private the `index` field of the `Revlog` struct
Simon Sapin <simon.sapin@octobus.net>
parents: 47963
diff changeset
    21
use crate::{Node, NULL_REVISION};
45526
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    22
46443
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46433
diff changeset
    23
#[derive(derive_more::From)]
45526
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    24
pub enum RevlogError {
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    25
    InvalidRevision,
46821
e8ae91b1a63d rhg: raise wdir specific error for `hg debugdata`
Pulkit Goyal <7895pulkit@gmail.com>
parents: 46744
diff changeset
    26
    /// Working directory is not supported
e8ae91b1a63d rhg: raise wdir specific error for `hg debugdata`
Pulkit Goyal <7895pulkit@gmail.com>
parents: 46744
diff changeset
    27
    WDirUnsupported,
46032
8d6164098782 rhg: allow specifying a changeset ID prefix
Simon Sapin <simon-commits@exyr.org>
parents: 45806
diff changeset
    28
    /// Found more than one entry whose ID match the requested prefix
8d6164098782 rhg: allow specifying a changeset ID prefix
Simon Sapin <simon-commits@exyr.org>
parents: 45806
diff changeset
    29
    AmbiguousPrefix,
46443
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46433
diff changeset
    30
    #[from]
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46433
diff changeset
    31
    Other(HgError),
45526
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    32
}
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    33
46443
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46433
diff changeset
    34
impl From<NodeMapError> for RevlogError {
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46433
diff changeset
    35
    fn from(error: NodeMapError) -> Self {
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46433
diff changeset
    36
        match error {
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46433
diff changeset
    37
            NodeMapError::MultipleResults => RevlogError::AmbiguousPrefix,
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46433
diff changeset
    38
            NodeMapError::RevisionNotInIndex(_) => RevlogError::corrupted(),
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46433
diff changeset
    39
        }
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46433
diff changeset
    40
    }
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46433
diff changeset
    41
}
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46433
diff changeset
    42
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46433
diff changeset
    43
impl RevlogError {
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46433
diff changeset
    44
    fn corrupted() -> Self {
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46433
diff changeset
    45
        RevlogError::Other(HgError::corrupted("corrupted revlog"))
46390
0800aa42bb4c rust: use the bytes-cast crate to parse persistent nodemaps
Simon Sapin <simon.sapin@octobus.net>
parents: 46167
diff changeset
    46
    }
0800aa42bb4c rust: use the bytes-cast crate to parse persistent nodemaps
Simon Sapin <simon.sapin@octobus.net>
parents: 46167
diff changeset
    47
}
0800aa42bb4c rust: use the bytes-cast crate to parse persistent nodemaps
Simon Sapin <simon.sapin@octobus.net>
parents: 46167
diff changeset
    48
45526
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    49
/// Read only implementation of revlog.
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    50
pub struct Revlog {
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    51
    /// When index and data are not interleaved: bytes of the revlog index.
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    52
    /// When index and data are interleaved: bytes of the revlog index and
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    53
    /// data.
47967
6c653d9d41b8 rust: Make private the `index` field of the `Revlog` struct
Simon Sapin <simon.sapin@octobus.net>
parents: 47963
diff changeset
    54
    index: Index,
45526
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    55
    /// When index and data are not interleaved: bytes of the revlog data
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    56
    data_bytes: Option<Box<dyn Deref<Target = [u8]> + Send>>,
46090
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents: 46033
diff changeset
    57
    /// When present on disk: the persistent nodemap for this revlog
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents: 46033
diff changeset
    58
    nodemap: Option<nodemap::NodeTree>,
45526
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    59
}
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    60
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    61
impl Revlog {
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    62
    /// Open a revlog index file.
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    63
    ///
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    64
    /// It will also open the associated data file if index and data are not
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    65
    /// interleaved.
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    66
    #[timed]
45806
7252f5237352 hg-core: fix path encoding usage
Antoine cezar<acezar@chwitlabs.fr>
parents: 45603
diff changeset
    67
    pub fn open(
46167
8a4914397d02 rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents: 46090
diff changeset
    68
        repo: &Repo,
8a4914397d02 rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents: 46090
diff changeset
    69
        index_path: impl AsRef<Path>,
45806
7252f5237352 hg-core: fix path encoding usage
Antoine cezar<acezar@chwitlabs.fr>
parents: 45603
diff changeset
    70
        data_path: Option<&Path>,
47963
001d747c2baf rust: Return HgError instead of RevlogError in revlog constructors
Simon Sapin <simon.sapin@octobus.net>
parents: 47962
diff changeset
    71
    ) -> Result<Self, HgError> {
46167
8a4914397d02 rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents: 46090
diff changeset
    72
        let index_path = index_path.as_ref();
48199
9d0e5629cfbf rhg: do not fail when the repo is empty
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48198
diff changeset
    73
        let index = {
9d0e5629cfbf rhg: do not fail when the repo is empty
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48198
diff changeset
    74
            match repo.store_vfs().mmap_open_opt(&index_path)? {
9d0e5629cfbf rhg: do not fail when the repo is empty
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48198
diff changeset
    75
                None => Index::new(Box::new(vec![])),
9d0e5629cfbf rhg: do not fail when the repo is empty
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48198
diff changeset
    76
                Some(index_mmap) => {
9d0e5629cfbf rhg: do not fail when the repo is empty
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48198
diff changeset
    77
                    let version = get_version(&index_mmap)?;
9d0e5629cfbf rhg: do not fail when the repo is empty
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48198
diff changeset
    78
                    if version != 1 {
48227
4518d91f02d8 rust: Reformat source code
Simon Sapin <simon.sapin@octobus.net>
parents: 48226
diff changeset
    79
                        // A proper new version should have had a repo/store
4518d91f02d8 rust: Reformat source code
Simon Sapin <simon.sapin@octobus.net>
parents: 48226
diff changeset
    80
                        // requirement.
48199
9d0e5629cfbf rhg: do not fail when the repo is empty
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48198
diff changeset
    81
                        return Err(HgError::corrupted("corrupted revlog"));
9d0e5629cfbf rhg: do not fail when the repo is empty
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48198
diff changeset
    82
                    }
45526
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    83
48199
9d0e5629cfbf rhg: do not fail when the repo is empty
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48198
diff changeset
    84
                    let index = Index::new(Box::new(index_mmap))?;
9d0e5629cfbf rhg: do not fail when the repo is empty
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48198
diff changeset
    85
                    Ok(index)
9d0e5629cfbf rhg: do not fail when the repo is empty
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48198
diff changeset
    86
                }
9d0e5629cfbf rhg: do not fail when the repo is empty
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48198
diff changeset
    87
            }
9d0e5629cfbf rhg: do not fail when the repo is empty
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48198
diff changeset
    88
        }?;
45526
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    89
45806
7252f5237352 hg-core: fix path encoding usage
Antoine cezar<acezar@chwitlabs.fr>
parents: 45603
diff changeset
    90
        let default_data_path = index_path.with_extension("d");
7252f5237352 hg-core: fix path encoding usage
Antoine cezar<acezar@chwitlabs.fr>
parents: 45603
diff changeset
    91
45526
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    92
        // type annotation required
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    93
        // won't recognize Mmap as Deref<Target = [u8]>
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    94
        let data_bytes: Option<Box<dyn Deref<Target = [u8]> + Send>> =
45601
900b9b79b99c hg-core: make `Index` owner of its bytes (D8958#inline-14994 followup 1/2)
Antoine cezar<acezar@chwitlabs.fr>
parents: 45595
diff changeset
    95
            if index.is_inline() {
45526
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    96
                None
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    97
            } else {
45806
7252f5237352 hg-core: fix path encoding usage
Antoine cezar<acezar@chwitlabs.fr>
parents: 45603
diff changeset
    98
                let data_path = data_path.unwrap_or(&default_data_path);
46443
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46433
diff changeset
    99
                let data_mmap = repo.store_vfs().mmap_open(data_path)?;
45526
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   100
                Some(Box::new(data_mmap))
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   101
            };
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   102
48226
5e77bdc29d56 rhg: do not try to open a nodemap for an inline index
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48199
diff changeset
   103
        let nodemap = if index.is_inline() {
5e77bdc29d56 rhg: do not try to open a nodemap for an inline index
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48199
diff changeset
   104
            None
5e77bdc29d56 rhg: do not try to open a nodemap for an inline index
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48199
diff changeset
   105
        } else {
5e77bdc29d56 rhg: do not try to open a nodemap for an inline index
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48199
diff changeset
   106
            NodeMapDocket::read_from_file(repo, index_path)?.map(
5e77bdc29d56 rhg: do not try to open a nodemap for an inline index
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48199
diff changeset
   107
                |(docket, data)| {
5e77bdc29d56 rhg: do not try to open a nodemap for an inline index
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48199
diff changeset
   108
                    nodemap::NodeTree::load_bytes(
5e77bdc29d56 rhg: do not try to open a nodemap for an inline index
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48199
diff changeset
   109
                        Box::new(data),
5e77bdc29d56 rhg: do not try to open a nodemap for an inline index
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48199
diff changeset
   110
                        docket.data_length,
5e77bdc29d56 rhg: do not try to open a nodemap for an inline index
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48199
diff changeset
   111
                    )
5e77bdc29d56 rhg: do not try to open a nodemap for an inline index
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48199
diff changeset
   112
                },
5e77bdc29d56 rhg: do not try to open a nodemap for an inline index
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48199
diff changeset
   113
            )
5e77bdc29d56 rhg: do not try to open a nodemap for an inline index
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48199
diff changeset
   114
        };
46090
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents: 46033
diff changeset
   115
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents: 46033
diff changeset
   116
        Ok(Revlog {
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents: 46033
diff changeset
   117
            index,
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents: 46033
diff changeset
   118
            data_bytes,
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents: 46033
diff changeset
   119
            nodemap,
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents: 46033
diff changeset
   120
        })
45526
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   121
    }
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   122
45534
4f11a67a12fb hg-core: add `Revlog.get_node_rev`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45531
diff changeset
   123
    /// Return number of entries of the `Revlog`.
4f11a67a12fb hg-core: add `Revlog.get_node_rev`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45531
diff changeset
   124
    pub fn len(&self) -> usize {
45601
900b9b79b99c hg-core: make `Index` owner of its bytes (D8958#inline-14994 followup 1/2)
Antoine cezar<acezar@chwitlabs.fr>
parents: 45595
diff changeset
   125
        self.index.len()
45534
4f11a67a12fb hg-core: add `Revlog.get_node_rev`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45531
diff changeset
   126
    }
4f11a67a12fb hg-core: add `Revlog.get_node_rev`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45531
diff changeset
   127
4f11a67a12fb hg-core: add `Revlog.get_node_rev`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45531
diff changeset
   128
    /// Returns `true` if the `Revlog` has zero `entries`.
4f11a67a12fb hg-core: add `Revlog.get_node_rev`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45531
diff changeset
   129
    pub fn is_empty(&self) -> bool {
45601
900b9b79b99c hg-core: make `Index` owner of its bytes (D8958#inline-14994 followup 1/2)
Antoine cezar<acezar@chwitlabs.fr>
parents: 45595
diff changeset
   130
        self.index.is_empty()
45534
4f11a67a12fb hg-core: add `Revlog.get_node_rev`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45531
diff changeset
   131
    }
4f11a67a12fb hg-core: add `Revlog.get_node_rev`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45531
diff changeset
   132
47969
87e3f878e65f rust: Rename get_node methods to data_for_node, get_rev to data_for_rev
Simon Sapin <simon.sapin@octobus.net>
parents: 47968
diff changeset
   133
    /// Returns the node ID for the given revision number, if it exists in this
87e3f878e65f rust: Rename get_node methods to data_for_node, get_rev to data_for_rev
Simon Sapin <simon.sapin@octobus.net>
parents: 47968
diff changeset
   134
    /// revlog
47967
6c653d9d41b8 rust: Make private the `index` field of the `Revlog` struct
Simon Sapin <simon.sapin@octobus.net>
parents: 47963
diff changeset
   135
    pub fn node_from_rev(&self, rev: Revision) -> Option<&Node> {
6c653d9d41b8 rust: Make private the `index` field of the `Revlog` struct
Simon Sapin <simon.sapin@octobus.net>
parents: 47963
diff changeset
   136
        Some(self.index.get_entry(rev)?.hash())
6c653d9d41b8 rust: Make private the `index` field of the `Revlog` struct
Simon Sapin <simon.sapin@octobus.net>
parents: 47963
diff changeset
   137
    }
6c653d9d41b8 rust: Make private the `index` field of the `Revlog` struct
Simon Sapin <simon.sapin@octobus.net>
parents: 47963
diff changeset
   138
47969
87e3f878e65f rust: Rename get_node methods to data_for_node, get_rev to data_for_rev
Simon Sapin <simon.sapin@octobus.net>
parents: 47968
diff changeset
   139
    /// Return the revision number for the given node ID, if it exists in this
87e3f878e65f rust: Rename get_node methods to data_for_node, get_rev to data_for_rev
Simon Sapin <simon.sapin@octobus.net>
parents: 47968
diff changeset
   140
    /// revlog
45534
4f11a67a12fb hg-core: add `Revlog.get_node_rev`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45531
diff changeset
   141
    #[timed]
47968
6f579618ea7b rust: Rename the `Revlog::get_node_rev` method to `rev_from_node`
Simon Sapin <simon.sapin@octobus.net>
parents: 47967
diff changeset
   142
    pub fn rev_from_node(
46033
88e741bf2d93 rust: use NodePrefix::from_hex instead of hex::decode directly
Simon Sapin <simon-commits@exyr.org>
parents: 46032
diff changeset
   143
        &self,
46431
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46390
diff changeset
   144
        node: NodePrefix,
46033
88e741bf2d93 rust: use NodePrefix::from_hex instead of hex::decode directly
Simon Sapin <simon-commits@exyr.org>
parents: 46032
diff changeset
   145
    ) -> Result<Revision, RevlogError> {
47962
8c29af0f6d6e rhg: Align with Python on some revset parsing corner cases
Simon Sapin <simon.sapin@octobus.net>
parents: 47380
diff changeset
   146
        if node.is_prefix_of(&NULL_NODE) {
8c29af0f6d6e rhg: Align with Python on some revset parsing corner cases
Simon Sapin <simon.sapin@octobus.net>
parents: 47380
diff changeset
   147
            return Ok(NULL_REVISION);
8c29af0f6d6e rhg: Align with Python on some revset parsing corner cases
Simon Sapin <simon.sapin@octobus.net>
parents: 47380
diff changeset
   148
        }
8c29af0f6d6e rhg: Align with Python on some revset parsing corner cases
Simon Sapin <simon.sapin@octobus.net>
parents: 47380
diff changeset
   149
46090
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents: 46033
diff changeset
   150
        if let Some(nodemap) = &self.nodemap {
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents: 46033
diff changeset
   151
            return nodemap
46443
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46433
diff changeset
   152
                .find_bin(&self.index, node)?
46090
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents: 46033
diff changeset
   153
                .ok_or(RevlogError::InvalidRevision);
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents: 46033
diff changeset
   154
        }
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents: 46033
diff changeset
   155
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents: 46033
diff changeset
   156
        // Fallback to linear scan when a persistent nodemap is not present.
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents: 46033
diff changeset
   157
        // This happens when the persistent-nodemap experimental feature is not
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents: 46033
diff changeset
   158
        // enabled, or for small revlogs.
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents: 46033
diff changeset
   159
        //
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents: 46033
diff changeset
   160
        // TODO: consider building a non-persistent nodemap in memory to
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents: 46033
diff changeset
   161
        // optimize these cases.
46032
8d6164098782 rhg: allow specifying a changeset ID prefix
Simon Sapin <simon-commits@exyr.org>
parents: 45806
diff changeset
   162
        let mut found_by_prefix = None;
45534
4f11a67a12fb hg-core: add `Revlog.get_node_rev`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45531
diff changeset
   163
        for rev in (0..self.len() as Revision).rev() {
4f11a67a12fb hg-core: add `Revlog.get_node_rev`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45531
diff changeset
   164
            let index_entry =
46443
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46433
diff changeset
   165
                self.index.get_entry(rev).ok_or(HgError::corrupted(
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46433
diff changeset
   166
                    "revlog references a revision not in the index",
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46433
diff changeset
   167
                ))?;
46033
88e741bf2d93 rust: use NodePrefix::from_hex instead of hex::decode directly
Simon Sapin <simon-commits@exyr.org>
parents: 46032
diff changeset
   168
            if node == *index_entry.hash() {
45534
4f11a67a12fb hg-core: add `Revlog.get_node_rev`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45531
diff changeset
   169
                return Ok(rev);
4f11a67a12fb hg-core: add `Revlog.get_node_rev`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45531
diff changeset
   170
            }
46033
88e741bf2d93 rust: use NodePrefix::from_hex instead of hex::decode directly
Simon Sapin <simon-commits@exyr.org>
parents: 46032
diff changeset
   171
            if node.is_prefix_of(index_entry.hash()) {
46032
8d6164098782 rhg: allow specifying a changeset ID prefix
Simon Sapin <simon-commits@exyr.org>
parents: 45806
diff changeset
   172
                if found_by_prefix.is_some() {
8d6164098782 rhg: allow specifying a changeset ID prefix
Simon Sapin <simon-commits@exyr.org>
parents: 45806
diff changeset
   173
                    return Err(RevlogError::AmbiguousPrefix);
8d6164098782 rhg: allow specifying a changeset ID prefix
Simon Sapin <simon-commits@exyr.org>
parents: 45806
diff changeset
   174
                }
8d6164098782 rhg: allow specifying a changeset ID prefix
Simon Sapin <simon-commits@exyr.org>
parents: 45806
diff changeset
   175
                found_by_prefix = Some(rev)
8d6164098782 rhg: allow specifying a changeset ID prefix
Simon Sapin <simon-commits@exyr.org>
parents: 45806
diff changeset
   176
            }
45534
4f11a67a12fb hg-core: add `Revlog.get_node_rev`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45531
diff changeset
   177
        }
46032
8d6164098782 rhg: allow specifying a changeset ID prefix
Simon Sapin <simon-commits@exyr.org>
parents: 45806
diff changeset
   178
        found_by_prefix.ok_or(RevlogError::InvalidRevision)
45534
4f11a67a12fb hg-core: add `Revlog.get_node_rev`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45531
diff changeset
   179
    }
4f11a67a12fb hg-core: add `Revlog.get_node_rev`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45531
diff changeset
   180
46433
4b381dbbf8b7 rhg: centralize parsing of `--rev` CLI arguments
Simon Sapin <simon.sapin@octobus.net>
parents: 46431
diff changeset
   181
    /// Returns whether the given revision exists in this revlog.
4b381dbbf8b7 rhg: centralize parsing of `--rev` CLI arguments
Simon Sapin <simon.sapin@octobus.net>
parents: 46431
diff changeset
   182
    pub fn has_rev(&self, rev: Revision) -> bool {
4b381dbbf8b7 rhg: centralize parsing of `--rev` CLI arguments
Simon Sapin <simon.sapin@octobus.net>
parents: 46431
diff changeset
   183
        self.index.get_entry(rev).is_some()
4b381dbbf8b7 rhg: centralize parsing of `--rev` CLI arguments
Simon Sapin <simon.sapin@octobus.net>
parents: 46431
diff changeset
   184
    }
4b381dbbf8b7 rhg: centralize parsing of `--rev` CLI arguments
Simon Sapin <simon.sapin@octobus.net>
parents: 46431
diff changeset
   185
45526
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   186
    /// Return the full data associated to a revision.
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   187
    ///
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   188
    /// All entries required to build the final data out of deltas will be
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   189
    /// retrieved as needed, and the deltas will be applied to the inital
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   190
    /// snapshot to rebuild the final data.
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   191
    #[timed]
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   192
    pub fn get_rev_data(&self, rev: Revision) -> Result<Vec<u8>, RevlogError> {
48198
61ce70fd420e rhg: handle null changelog and manifest revisions
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48083
diff changeset
   193
        if rev == NULL_REVISION {
61ce70fd420e rhg: handle null changelog and manifest revisions
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48083
diff changeset
   194
            return Ok(vec![]);
61ce70fd420e rhg: handle null changelog and manifest revisions
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48083
diff changeset
   195
        };
45526
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   196
        // Todo return -> Cow
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   197
        let mut entry = self.get_entry(rev)?;
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   198
        let mut delta_chain = vec![];
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   199
        while let Some(base_rev) = entry.base_rev {
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   200
            delta_chain.push(entry);
46443
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46433
diff changeset
   201
            entry = self
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46433
diff changeset
   202
                .get_entry(base_rev)
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46433
diff changeset
   203
                .map_err(|_| RevlogError::corrupted())?;
45526
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   204
        }
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   205
45531
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45526
diff changeset
   206
        // TODO do not look twice in the index
45601
900b9b79b99c hg-core: make `Index` owner of its bytes (D8958#inline-14994 followup 1/2)
Antoine cezar<acezar@chwitlabs.fr>
parents: 45595
diff changeset
   207
        let index_entry = self
900b9b79b99c hg-core: make `Index` owner of its bytes (D8958#inline-14994 followup 1/2)
Antoine cezar<acezar@chwitlabs.fr>
parents: 45595
diff changeset
   208
            .index
900b9b79b99c hg-core: make `Index` owner of its bytes (D8958#inline-14994 followup 1/2)
Antoine cezar<acezar@chwitlabs.fr>
parents: 45595
diff changeset
   209
            .get_entry(rev)
900b9b79b99c hg-core: make `Index` owner of its bytes (D8958#inline-14994 followup 1/2)
Antoine cezar<acezar@chwitlabs.fr>
parents: 45595
diff changeset
   210
            .ok_or(RevlogError::InvalidRevision)?;
45531
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45526
diff changeset
   211
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45526
diff changeset
   212
        let data: Vec<u8> = if delta_chain.is_empty() {
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45526
diff changeset
   213
            entry.data()?.into()
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45526
diff changeset
   214
        } else {
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45526
diff changeset
   215
            Revlog::build_data_from_deltas(entry, &delta_chain)?
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45526
diff changeset
   216
        };
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45526
diff changeset
   217
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45526
diff changeset
   218
        if self.check_hash(
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45526
diff changeset
   219
            index_entry.p1(),
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45526
diff changeset
   220
            index_entry.p2(),
46033
88e741bf2d93 rust: use NodePrefix::from_hex instead of hex::decode directly
Simon Sapin <simon-commits@exyr.org>
parents: 46032
diff changeset
   221
            index_entry.hash().as_bytes(),
45531
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45526
diff changeset
   222
            &data,
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45526
diff changeset
   223
        ) {
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45526
diff changeset
   224
            Ok(data)
45526
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   225
        } else {
46443
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46433
diff changeset
   226
            Err(RevlogError::corrupted())
45526
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   227
        }
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   228
    }
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   229
45531
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45526
diff changeset
   230
    /// Check the hash of some given data against the recorded hash.
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45526
diff changeset
   231
    pub fn check_hash(
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45526
diff changeset
   232
        &self,
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45526
diff changeset
   233
        p1: Revision,
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45526
diff changeset
   234
        p2: Revision,
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45526
diff changeset
   235
        expected: &[u8],
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45526
diff changeset
   236
        data: &[u8],
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45526
diff changeset
   237
    ) -> bool {
45601
900b9b79b99c hg-core: make `Index` owner of its bytes (D8958#inline-14994 followup 1/2)
Antoine cezar<acezar@chwitlabs.fr>
parents: 45595
diff changeset
   238
        let e1 = self.index.get_entry(p1);
45531
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45526
diff changeset
   239
        let h1 = match e1 {
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45526
diff changeset
   240
            Some(ref entry) => entry.hash(),
46033
88e741bf2d93 rust: use NodePrefix::from_hex instead of hex::decode directly
Simon Sapin <simon-commits@exyr.org>
parents: 46032
diff changeset
   241
            None => &NULL_NODE,
45531
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45526
diff changeset
   242
        };
45601
900b9b79b99c hg-core: make `Index` owner of its bytes (D8958#inline-14994 followup 1/2)
Antoine cezar<acezar@chwitlabs.fr>
parents: 45595
diff changeset
   243
        let e2 = self.index.get_entry(p2);
45531
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45526
diff changeset
   244
        let h2 = match e2 {
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45526
diff changeset
   245
            Some(ref entry) => entry.hash(),
46033
88e741bf2d93 rust: use NodePrefix::from_hex instead of hex::decode directly
Simon Sapin <simon-commits@exyr.org>
parents: 46032
diff changeset
   246
            None => &NULL_NODE,
45531
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45526
diff changeset
   247
        };
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45526
diff changeset
   248
47380
fad504cfc94b rust: Use a maintained crate for SHA-1 hashing
Simon Sapin <simon.sapin@octobus.net>
parents: 46821
diff changeset
   249
        &hash(data, h1.as_bytes(), h2.as_bytes()) == expected
45531
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45526
diff changeset
   250
    }
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45526
diff changeset
   251
45526
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   252
    /// Build the full data of a revision out its snapshot
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   253
    /// and its deltas.
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   254
    #[timed]
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   255
    fn build_data_from_deltas(
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   256
        snapshot: RevlogEntry,
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   257
        deltas: &[RevlogEntry],
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   258
    ) -> Result<Vec<u8>, RevlogError> {
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   259
        let snapshot = snapshot.data()?;
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   260
        let deltas = deltas
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   261
            .iter()
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   262
            .rev()
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   263
            .map(RevlogEntry::data)
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   264
            .collect::<Result<Vec<Cow<'_, [u8]>>, RevlogError>>()?;
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   265
        let patches: Vec<_> =
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   266
            deltas.iter().map(|d| patch::PatchList::new(d)).collect();
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   267
        let patch = patch::fold_patch_lists(&patches);
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   268
        Ok(patch.apply(&snapshot))
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   269
    }
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   270
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   271
    /// Return the revlog data.
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   272
    fn data(&self) -> &[u8] {
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   273
        match self.data_bytes {
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   274
            Some(ref data_bytes) => &data_bytes,
45601
900b9b79b99c hg-core: make `Index` owner of its bytes (D8958#inline-14994 followup 1/2)
Antoine cezar<acezar@chwitlabs.fr>
parents: 45595
diff changeset
   275
            None => panic!(
900b9b79b99c hg-core: make `Index` owner of its bytes (D8958#inline-14994 followup 1/2)
Antoine cezar<acezar@chwitlabs.fr>
parents: 45595
diff changeset
   276
                "forgot to load the data or trying to access inline data"
900b9b79b99c hg-core: make `Index` owner of its bytes (D8958#inline-14994 followup 1/2)
Antoine cezar<acezar@chwitlabs.fr>
parents: 45595
diff changeset
   277
            ),
45526
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   278
        }
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   279
    }
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   280
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   281
    /// Get an entry of the revlog.
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   282
    fn get_entry(&self, rev: Revision) -> Result<RevlogEntry, RevlogError> {
45601
900b9b79b99c hg-core: make `Index` owner of its bytes (D8958#inline-14994 followup 1/2)
Antoine cezar<acezar@chwitlabs.fr>
parents: 45595
diff changeset
   283
        let index_entry = self
900b9b79b99c hg-core: make `Index` owner of its bytes (D8958#inline-14994 followup 1/2)
Antoine cezar<acezar@chwitlabs.fr>
parents: 45595
diff changeset
   284
            .index
900b9b79b99c hg-core: make `Index` owner of its bytes (D8958#inline-14994 followup 1/2)
Antoine cezar<acezar@chwitlabs.fr>
parents: 45595
diff changeset
   285
            .get_entry(rev)
900b9b79b99c hg-core: make `Index` owner of its bytes (D8958#inline-14994 followup 1/2)
Antoine cezar<acezar@chwitlabs.fr>
parents: 45595
diff changeset
   286
            .ok_or(RevlogError::InvalidRevision)?;
45526
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   287
        let start = index_entry.offset();
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   288
        let end = start + index_entry.compressed_len();
45601
900b9b79b99c hg-core: make `Index` owner of its bytes (D8958#inline-14994 followup 1/2)
Antoine cezar<acezar@chwitlabs.fr>
parents: 45595
diff changeset
   289
        let data = if self.index.is_inline() {
900b9b79b99c hg-core: make `Index` owner of its bytes (D8958#inline-14994 followup 1/2)
Antoine cezar<acezar@chwitlabs.fr>
parents: 45595
diff changeset
   290
            self.index.data(start, end)
900b9b79b99c hg-core: make `Index` owner of its bytes (D8958#inline-14994 followup 1/2)
Antoine cezar<acezar@chwitlabs.fr>
parents: 45595
diff changeset
   291
        } else {
900b9b79b99c hg-core: make `Index` owner of its bytes (D8958#inline-14994 followup 1/2)
Antoine cezar<acezar@chwitlabs.fr>
parents: 45595
diff changeset
   292
            &self.data()[start..end]
900b9b79b99c hg-core: make `Index` owner of its bytes (D8958#inline-14994 followup 1/2)
Antoine cezar<acezar@chwitlabs.fr>
parents: 45595
diff changeset
   293
        };
45526
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   294
        let entry = RevlogEntry {
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   295
            rev,
45601
900b9b79b99c hg-core: make `Index` owner of its bytes (D8958#inline-14994 followup 1/2)
Antoine cezar<acezar@chwitlabs.fr>
parents: 45595
diff changeset
   296
            bytes: data,
45526
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   297
            compressed_len: index_entry.compressed_len(),
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   298
            uncompressed_len: index_entry.uncompressed_len(),
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   299
            base_rev: if index_entry.base_revision() == rev {
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   300
                None
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   301
            } else {
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   302
                Some(index_entry.base_revision())
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   303
            },
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   304
        };
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   305
        Ok(entry)
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   306
    }
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   307
}
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   308
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   309
/// The revlog entry's bytes and the necessary informations to extract
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   310
/// the entry's data.
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   311
#[derive(Debug)]
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   312
pub struct RevlogEntry<'a> {
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   313
    rev: Revision,
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   314
    bytes: &'a [u8],
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   315
    compressed_len: usize,
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   316
    uncompressed_len: usize,
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   317
    base_rev: Option<Revision>,
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   318
}
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   319
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   320
impl<'a> RevlogEntry<'a> {
48083
fecfea658127 hg-core: silence dead-code warning by adding RevlogEntry::revion() accessor
Martin von Zweigbergk <martinvonz@google.com>
parents: 47969
diff changeset
   321
    pub fn revision(&self) -> Revision {
fecfea658127 hg-core: silence dead-code warning by adding RevlogEntry::revion() accessor
Martin von Zweigbergk <martinvonz@google.com>
parents: 47969
diff changeset
   322
        self.rev
fecfea658127 hg-core: silence dead-code warning by adding RevlogEntry::revion() accessor
Martin von Zweigbergk <martinvonz@google.com>
parents: 47969
diff changeset
   323
    }
fecfea658127 hg-core: silence dead-code warning by adding RevlogEntry::revion() accessor
Martin von Zweigbergk <martinvonz@google.com>
parents: 47969
diff changeset
   324
45526
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   325
    /// Extract the data contained in the entry.
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   326
    pub fn data(&self) -> Result<Cow<'_, [u8]>, RevlogError> {
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   327
        if self.bytes.is_empty() {
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   328
            return Ok(Cow::Borrowed(&[]));
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   329
        }
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   330
        match self.bytes[0] {
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   331
            // Revision data is the entirety of the entry, including this
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   332
            // header.
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   333
            b'\0' => Ok(Cow::Borrowed(self.bytes)),
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   334
            // Raw revision data follows.
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   335
            b'u' => Ok(Cow::Borrowed(&self.bytes[1..])),
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   336
            // zlib (RFC 1950) data.
45595
497657895b54 hg-core: return `Err` on decompression error (D8958#inline-15004 followup)
Antoine cezar<acezar@chwitlabs.fr>
parents: 45536
diff changeset
   337
            b'x' => Ok(Cow::Owned(self.uncompressed_zlib_data()?)),
45526
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   338
            // zstd data.
45595
497657895b54 hg-core: return `Err` on decompression error (D8958#inline-15004 followup)
Antoine cezar<acezar@chwitlabs.fr>
parents: 45536
diff changeset
   339
            b'\x28' => Ok(Cow::Owned(self.uncompressed_zstd_data()?)),
46443
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46433
diff changeset
   340
            // A proper new format should have had a repo/store requirement.
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46433
diff changeset
   341
            _format_type => Err(RevlogError::corrupted()),
45526
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   342
        }
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   343
    }
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   344
45595
497657895b54 hg-core: return `Err` on decompression error (D8958#inline-15004 followup)
Antoine cezar<acezar@chwitlabs.fr>
parents: 45536
diff changeset
   345
    fn uncompressed_zlib_data(&self) -> Result<Vec<u8>, RevlogError> {
45526
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   346
        let mut decoder = ZlibDecoder::new(self.bytes);
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   347
        if self.is_delta() {
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   348
            let mut buf = Vec::with_capacity(self.compressed_len);
45595
497657895b54 hg-core: return `Err` on decompression error (D8958#inline-15004 followup)
Antoine cezar<acezar@chwitlabs.fr>
parents: 45536
diff changeset
   349
            decoder
497657895b54 hg-core: return `Err` on decompression error (D8958#inline-15004 followup)
Antoine cezar<acezar@chwitlabs.fr>
parents: 45536
diff changeset
   350
                .read_to_end(&mut buf)
46443
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46433
diff changeset
   351
                .map_err(|_| RevlogError::corrupted())?;
45595
497657895b54 hg-core: return `Err` on decompression error (D8958#inline-15004 followup)
Antoine cezar<acezar@chwitlabs.fr>
parents: 45536
diff changeset
   352
            Ok(buf)
45526
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   353
        } else {
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   354
            let mut buf = vec![0; self.uncompressed_len];
45595
497657895b54 hg-core: return `Err` on decompression error (D8958#inline-15004 followup)
Antoine cezar<acezar@chwitlabs.fr>
parents: 45536
diff changeset
   355
            decoder
497657895b54 hg-core: return `Err` on decompression error (D8958#inline-15004 followup)
Antoine cezar<acezar@chwitlabs.fr>
parents: 45536
diff changeset
   356
                .read_exact(&mut buf)
46443
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46433
diff changeset
   357
                .map_err(|_| RevlogError::corrupted())?;
45595
497657895b54 hg-core: return `Err` on decompression error (D8958#inline-15004 followup)
Antoine cezar<acezar@chwitlabs.fr>
parents: 45536
diff changeset
   358
            Ok(buf)
45526
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   359
        }
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   360
    }
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   361
45595
497657895b54 hg-core: return `Err` on decompression error (D8958#inline-15004 followup)
Antoine cezar<acezar@chwitlabs.fr>
parents: 45536
diff changeset
   362
    fn uncompressed_zstd_data(&self) -> Result<Vec<u8>, RevlogError> {
45526
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   363
        if self.is_delta() {
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   364
            let mut buf = Vec::with_capacity(self.compressed_len);
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   365
            zstd::stream::copy_decode(self.bytes, &mut buf)
46443
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46433
diff changeset
   366
                .map_err(|_| RevlogError::corrupted())?;
45595
497657895b54 hg-core: return `Err` on decompression error (D8958#inline-15004 followup)
Antoine cezar<acezar@chwitlabs.fr>
parents: 45536
diff changeset
   367
            Ok(buf)
45526
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   368
        } else {
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   369
            let mut buf = vec![0; self.uncompressed_len];
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   370
            let len = zstd::block::decompress_to_buffer(self.bytes, &mut buf)
46443
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46433
diff changeset
   371
                .map_err(|_| RevlogError::corrupted())?;
45595
497657895b54 hg-core: return `Err` on decompression error (D8958#inline-15004 followup)
Antoine cezar<acezar@chwitlabs.fr>
parents: 45536
diff changeset
   372
            if len != self.uncompressed_len {
46443
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46433
diff changeset
   373
                Err(RevlogError::corrupted())
45595
497657895b54 hg-core: return `Err` on decompression error (D8958#inline-15004 followup)
Antoine cezar<acezar@chwitlabs.fr>
parents: 45536
diff changeset
   374
            } else {
497657895b54 hg-core: return `Err` on decompression error (D8958#inline-15004 followup)
Antoine cezar<acezar@chwitlabs.fr>
parents: 45536
diff changeset
   375
                Ok(buf)
497657895b54 hg-core: return `Err` on decompression error (D8958#inline-15004 followup)
Antoine cezar<acezar@chwitlabs.fr>
parents: 45536
diff changeset
   376
            }
45526
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   377
        }
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   378
    }
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   379
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   380
    /// Tell if the entry is a snapshot or a delta
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   381
    /// (influences on decompression).
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   382
    fn is_delta(&self) -> bool {
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   383
        self.base_rev.is_some()
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   384
    }
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   385
}
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   386
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   387
/// Format version of the revlog.
48198
61ce70fd420e rhg: handle null changelog and manifest revisions
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48083
diff changeset
   388
pub fn get_version(index_bytes: &[u8]) -> Result<u16, HgError> {
61ce70fd420e rhg: handle null changelog and manifest revisions
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48083
diff changeset
   389
    if index_bytes.len() == 0 {
61ce70fd420e rhg: handle null changelog and manifest revisions
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48083
diff changeset
   390
        return Ok(1);
61ce70fd420e rhg: handle null changelog and manifest revisions
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48083
diff changeset
   391
    };
61ce70fd420e rhg: handle null changelog and manifest revisions
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48083
diff changeset
   392
    if index_bytes.len() < 4 {
61ce70fd420e rhg: handle null changelog and manifest revisions
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48083
diff changeset
   393
        return Err(HgError::corrupted(
61ce70fd420e rhg: handle null changelog and manifest revisions
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48083
diff changeset
   394
            "corrupted revlog: can't read the index format header",
61ce70fd420e rhg: handle null changelog and manifest revisions
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48083
diff changeset
   395
        ));
61ce70fd420e rhg: handle null changelog and manifest revisions
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48083
diff changeset
   396
    };
61ce70fd420e rhg: handle null changelog and manifest revisions
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48083
diff changeset
   397
    Ok(BigEndian::read_u16(&index_bytes[2..=3]))
45526
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   398
}
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   399
45531
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45526
diff changeset
   400
/// Calculate the hash of a revision given its data and its parents.
47380
fad504cfc94b rust: Use a maintained crate for SHA-1 hashing
Simon Sapin <simon.sapin@octobus.net>
parents: 46821
diff changeset
   401
fn hash(
fad504cfc94b rust: Use a maintained crate for SHA-1 hashing
Simon Sapin <simon.sapin@octobus.net>
parents: 46821
diff changeset
   402
    data: &[u8],
fad504cfc94b rust: Use a maintained crate for SHA-1 hashing
Simon Sapin <simon.sapin@octobus.net>
parents: 46821
diff changeset
   403
    p1_hash: &[u8],
fad504cfc94b rust: Use a maintained crate for SHA-1 hashing
Simon Sapin <simon.sapin@octobus.net>
parents: 46821
diff changeset
   404
    p2_hash: &[u8],
fad504cfc94b rust: Use a maintained crate for SHA-1 hashing
Simon Sapin <simon.sapin@octobus.net>
parents: 46821
diff changeset
   405
) -> [u8; NODE_BYTES_LENGTH] {
45531
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45526
diff changeset
   406
    let mut hasher = Sha1::new();
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45526
diff changeset
   407
    let (a, b) = (p1_hash, p2_hash);
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45526
diff changeset
   408
    if a > b {
47380
fad504cfc94b rust: Use a maintained crate for SHA-1 hashing
Simon Sapin <simon.sapin@octobus.net>
parents: 46821
diff changeset
   409
        hasher.update(b);
fad504cfc94b rust: Use a maintained crate for SHA-1 hashing
Simon Sapin <simon.sapin@octobus.net>
parents: 46821
diff changeset
   410
        hasher.update(a);
45531
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45526
diff changeset
   411
    } else {
47380
fad504cfc94b rust: Use a maintained crate for SHA-1 hashing
Simon Sapin <simon.sapin@octobus.net>
parents: 46821
diff changeset
   412
        hasher.update(a);
fad504cfc94b rust: Use a maintained crate for SHA-1 hashing
Simon Sapin <simon.sapin@octobus.net>
parents: 46821
diff changeset
   413
        hasher.update(b);
45531
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45526
diff changeset
   414
    }
47380
fad504cfc94b rust: Use a maintained crate for SHA-1 hashing
Simon Sapin <simon.sapin@octobus.net>
parents: 46821
diff changeset
   415
    hasher.update(data);
fad504cfc94b rust: Use a maintained crate for SHA-1 hashing
Simon Sapin <simon.sapin@octobus.net>
parents: 46821
diff changeset
   416
    *hasher.finalize().as_ref()
45531
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45526
diff changeset
   417
}
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45526
diff changeset
   418
45526
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   419
#[cfg(test)]
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   420
mod tests {
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   421
    use super::*;
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   422
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   423
    use super::super::index::IndexEntryBuilder;
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   424
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   425
    #[test]
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   426
    fn version_test() {
45601
900b9b79b99c hg-core: make `Index` owner of its bytes (D8958#inline-14994 followup 1/2)
Antoine cezar<acezar@chwitlabs.fr>
parents: 45595
diff changeset
   427
        let bytes = IndexEntryBuilder::new()
900b9b79b99c hg-core: make `Index` owner of its bytes (D8958#inline-14994 followup 1/2)
Antoine cezar<acezar@chwitlabs.fr>
parents: 45595
diff changeset
   428
            .is_first(true)
45526
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   429
            .with_version(1)
45601
900b9b79b99c hg-core: make `Index` owner of its bytes (D8958#inline-14994 followup 1/2)
Antoine cezar<acezar@chwitlabs.fr>
parents: 45595
diff changeset
   430
            .build();
45526
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   431
48227
4518d91f02d8 rust: Reformat source code
Simon Sapin <simon.sapin@octobus.net>
parents: 48226
diff changeset
   432
        assert_eq!(get_version(&bytes).map_err(|_err| ()), Ok(1))
45526
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   433
    }
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   434
}