rust/hg-core/src/revlog/revlog.rs
author Arseniy Alekseyev <aalekseyev@janestreet.com>
Sun, 22 May 2022 14:21:59 +0200
branchstable
changeset 49210 cc92ad0e8185
parent 48546 e91aa800ae5b
child 49217 13dfad0f9f7a
permissions -rw-r--r--
rhg: correctly handle the case where diffs are encoded relative to nullrev returning a valid entry for nullrev fix chain that delta against nullrev.
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;
48543
0a4ac916673e rhg: RevlogEntry::uncompressed_len is signed
Simon Sapin <simon.sapin@octobus.net>
parents: 48542
diff changeset
     2
use std::convert::TryFrom;
45526
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
     3
use std::io::Read;
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
     4
use std::ops::Deref;
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
     5
use std::path::Path;
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
     6
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
48546
e91aa800ae5b rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents: 48544
diff changeset
    23
const REVISION_FLAG_CENSORED: u16 = 1 << 15;
e91aa800ae5b rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents: 48544
diff changeset
    24
const REVISION_FLAG_ELLIPSIS: u16 = 1 << 14;
e91aa800ae5b rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents: 48544
diff changeset
    25
const REVISION_FLAG_EXTSTORED: u16 = 1 << 13;
e91aa800ae5b rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents: 48544
diff changeset
    26
const REVISION_FLAG_HASCOPIESINFO: u16 = 1 << 12;
e91aa800ae5b rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents: 48544
diff changeset
    27
e91aa800ae5b rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents: 48544
diff changeset
    28
// Keep this in sync with REVIDX_KNOWN_FLAGS in
e91aa800ae5b rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents: 48544
diff changeset
    29
// mercurial/revlogutils/flagutil.py
e91aa800ae5b rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents: 48544
diff changeset
    30
const REVIDX_KNOWN_FLAGS: u16 = REVISION_FLAG_CENSORED
e91aa800ae5b rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents: 48544
diff changeset
    31
    | REVISION_FLAG_ELLIPSIS
e91aa800ae5b rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents: 48544
diff changeset
    32
    | REVISION_FLAG_EXTSTORED
e91aa800ae5b rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents: 48544
diff changeset
    33
    | REVISION_FLAG_HASCOPIESINFO;
e91aa800ae5b rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents: 48544
diff changeset
    34
49210
cc92ad0e8185 rhg: correctly handle the case where diffs are encoded relative to nullrev
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48546
diff changeset
    35
const NULL_REVLOG_ENTRY_FLAGS: u16 = 0;
cc92ad0e8185 rhg: correctly handle the case where diffs are encoded relative to nullrev
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48546
diff changeset
    36
46443
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46433
diff changeset
    37
#[derive(derive_more::From)]
45526
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    38
pub enum RevlogError {
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    39
    InvalidRevision,
46821
e8ae91b1a63d rhg: raise wdir specific error for `hg debugdata`
Pulkit Goyal <7895pulkit@gmail.com>
parents: 46744
diff changeset
    40
    /// Working directory is not supported
e8ae91b1a63d rhg: raise wdir specific error for `hg debugdata`
Pulkit Goyal <7895pulkit@gmail.com>
parents: 46744
diff changeset
    41
    WDirUnsupported,
46032
8d6164098782 rhg: allow specifying a changeset ID prefix
Simon Sapin <simon-commits@exyr.org>
parents: 45806
diff changeset
    42
    /// 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
    43
    AmbiguousPrefix,
46443
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46433
diff changeset
    44
    #[from]
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46433
diff changeset
    45
    Other(HgError),
45526
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    46
}
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    47
46443
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46433
diff changeset
    48
impl From<NodeMapError> for RevlogError {
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46433
diff changeset
    49
    fn from(error: NodeMapError) -> Self {
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46433
diff changeset
    50
        match error {
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46433
diff changeset
    51
            NodeMapError::MultipleResults => RevlogError::AmbiguousPrefix,
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46433
diff changeset
    52
            NodeMapError::RevisionNotInIndex(_) => RevlogError::corrupted(),
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46433
diff changeset
    53
        }
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46433
diff changeset
    54
    }
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46433
diff changeset
    55
}
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46433
diff changeset
    56
48542
35c47015b9b7 rhg: Expose FilelogEntry that wraps RevlogEntry
Simon Sapin <simon.sapin@octobus.net>
parents: 48541
diff changeset
    57
fn corrupted() -> HgError {
35c47015b9b7 rhg: Expose FilelogEntry that wraps RevlogEntry
Simon Sapin <simon.sapin@octobus.net>
parents: 48541
diff changeset
    58
    HgError::corrupted("corrupted revlog")
35c47015b9b7 rhg: Expose FilelogEntry that wraps RevlogEntry
Simon Sapin <simon.sapin@octobus.net>
parents: 48541
diff changeset
    59
}
35c47015b9b7 rhg: Expose FilelogEntry that wraps RevlogEntry
Simon Sapin <simon.sapin@octobus.net>
parents: 48541
diff changeset
    60
46443
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46433
diff changeset
    61
impl RevlogError {
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46433
diff changeset
    62
    fn corrupted() -> Self {
48542
35c47015b9b7 rhg: Expose FilelogEntry that wraps RevlogEntry
Simon Sapin <simon.sapin@octobus.net>
parents: 48541
diff changeset
    63
        RevlogError::Other(corrupted())
46390
0800aa42bb4c rust: use the bytes-cast crate to parse persistent nodemaps
Simon Sapin <simon.sapin@octobus.net>
parents: 46167
diff changeset
    64
    }
0800aa42bb4c rust: use the bytes-cast crate to parse persistent nodemaps
Simon Sapin <simon.sapin@octobus.net>
parents: 46167
diff changeset
    65
}
0800aa42bb4c rust: use the bytes-cast crate to parse persistent nodemaps
Simon Sapin <simon.sapin@octobus.net>
parents: 46167
diff changeset
    66
45526
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    67
/// Read only implementation of revlog.
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    68
pub struct Revlog {
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    69
    /// 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
    70
    /// 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
    71
    /// data.
47967
6c653d9d41b8 rust: Make private the `index` field of the `Revlog` struct
Simon Sapin <simon.sapin@octobus.net>
parents: 47963
diff changeset
    72
    index: Index,
45526
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    73
    /// 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
    74
    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
    75
    /// 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
    76
    nodemap: Option<nodemap::NodeTree>,
45526
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    77
}
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    78
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    79
impl Revlog {
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    80
    /// Open a revlog index file.
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    81
    ///
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    82
    /// 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
    83
    /// interleaved.
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    84
    #[timed]
45806
7252f5237352 hg-core: fix path encoding usage
Antoine cezar<acezar@chwitlabs.fr>
parents: 45603
diff changeset
    85
    pub fn open(
46167
8a4914397d02 rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents: 46090
diff changeset
    86
        repo: &Repo,
8a4914397d02 rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents: 46090
diff changeset
    87
        index_path: impl AsRef<Path>,
45806
7252f5237352 hg-core: fix path encoding usage
Antoine cezar<acezar@chwitlabs.fr>
parents: 45603
diff changeset
    88
        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
    89
    ) -> Result<Self, HgError> {
46167
8a4914397d02 rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents: 46090
diff changeset
    90
        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
    91
        let index = {
9d0e5629cfbf rhg: do not fail when the repo is empty
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48198
diff changeset
    92
            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
    93
                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
    94
                Some(index_mmap) => {
9d0e5629cfbf rhg: do not fail when the repo is empty
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48198
diff changeset
    95
                    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
    96
                    Ok(index)
9d0e5629cfbf rhg: do not fail when the repo is empty
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48198
diff changeset
    97
                }
9d0e5629cfbf rhg: do not fail when the repo is empty
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48198
diff changeset
    98
            }
9d0e5629cfbf rhg: do not fail when the repo is empty
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48198
diff changeset
    99
        }?;
45526
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   100
45806
7252f5237352 hg-core: fix path encoding usage
Antoine cezar<acezar@chwitlabs.fr>
parents: 45603
diff changeset
   101
        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
   102
45526
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   103
        // type annotation required
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   104
        // 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
   105
        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
   106
            if index.is_inline() {
45526
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   107
                None
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   108
            } else {
45806
7252f5237352 hg-core: fix path encoding usage
Antoine cezar<acezar@chwitlabs.fr>
parents: 45603
diff changeset
   109
                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
   110
                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
   111
                Some(Box::new(data_mmap))
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   112
            };
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   113
48226
5e77bdc29d56 rhg: do not try to open a nodemap for an inline index
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48199
diff changeset
   114
        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
   115
            None
5e77bdc29d56 rhg: do not try to open a nodemap for an inline index
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48199
diff changeset
   116
        } else {
5e77bdc29d56 rhg: do not try to open a nodemap for an inline index
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48199
diff changeset
   117
            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
   118
                |(docket, data)| {
5e77bdc29d56 rhg: do not try to open a nodemap for an inline index
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48199
diff changeset
   119
                    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
   120
                        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
   121
                        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
   122
                    )
5e77bdc29d56 rhg: do not try to open a nodemap for an inline index
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48199
diff changeset
   123
                },
5e77bdc29d56 rhg: do not try to open a nodemap for an inline index
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48199
diff changeset
   124
            )
5e77bdc29d56 rhg: do not try to open a nodemap for an inline index
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48199
diff changeset
   125
        };
46090
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents: 46033
diff changeset
   126
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents: 46033
diff changeset
   127
        Ok(Revlog {
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents: 46033
diff changeset
   128
            index,
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents: 46033
diff changeset
   129
            data_bytes,
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents: 46033
diff changeset
   130
            nodemap,
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents: 46033
diff changeset
   131
        })
45526
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   132
    }
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   133
45534
4f11a67a12fb hg-core: add `Revlog.get_node_rev`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45531
diff changeset
   134
    /// 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
   135
    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
   136
        self.index.len()
45534
4f11a67a12fb hg-core: add `Revlog.get_node_rev`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45531
diff changeset
   137
    }
4f11a67a12fb hg-core: add `Revlog.get_node_rev`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45531
diff changeset
   138
4f11a67a12fb hg-core: add `Revlog.get_node_rev`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45531
diff changeset
   139
    /// 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
   140
    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
   141
        self.index.is_empty()
45534
4f11a67a12fb hg-core: add `Revlog.get_node_rev`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45531
diff changeset
   142
    }
4f11a67a12fb hg-core: add `Revlog.get_node_rev`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45531
diff changeset
   143
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
   144
    /// 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
   145
    /// revlog
47967
6c653d9d41b8 rust: Make private the `index` field of the `Revlog` struct
Simon Sapin <simon.sapin@octobus.net>
parents: 47963
diff changeset
   146
    pub fn node_from_rev(&self, rev: Revision) -> Option<&Node> {
48236
f8dc78716ad2 rhg: fix `hg cat` interaction with null revision
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48227
diff changeset
   147
        if rev == NULL_REVISION {
f8dc78716ad2 rhg: fix `hg cat` interaction with null revision
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48227
diff changeset
   148
            return Some(&NULL_NODE);
f8dc78716ad2 rhg: fix `hg cat` interaction with null revision
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48227
diff changeset
   149
        }
47967
6c653d9d41b8 rust: Make private the `index` field of the `Revlog` struct
Simon Sapin <simon.sapin@octobus.net>
parents: 47963
diff changeset
   150
        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
   151
    }
6c653d9d41b8 rust: Make private the `index` field of the `Revlog` struct
Simon Sapin <simon.sapin@octobus.net>
parents: 47963
diff changeset
   152
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
   153
    /// 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
   154
    /// revlog
45534
4f11a67a12fb hg-core: add `Revlog.get_node_rev`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45531
diff changeset
   155
    #[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
   156
    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
   157
        &self,
46431
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46390
diff changeset
   158
        node: NodePrefix,
46033
88e741bf2d93 rust: use NodePrefix::from_hex instead of hex::decode directly
Simon Sapin <simon-commits@exyr.org>
parents: 46032
diff changeset
   159
    ) -> 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
   160
        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
   161
            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
   162
        }
8c29af0f6d6e rhg: Align with Python on some revset parsing corner cases
Simon Sapin <simon.sapin@octobus.net>
parents: 47380
diff changeset
   163
46090
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents: 46033
diff changeset
   164
        if let Some(nodemap) = &self.nodemap {
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents: 46033
diff changeset
   165
            return nodemap
46443
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46433
diff changeset
   166
                .find_bin(&self.index, node)?
46090
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents: 46033
diff changeset
   167
                .ok_or(RevlogError::InvalidRevision);
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents: 46033
diff changeset
   168
        }
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents: 46033
diff changeset
   169
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents: 46033
diff changeset
   170
        // 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
   171
        // 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
   172
        // enabled, or for small revlogs.
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents: 46033
diff changeset
   173
        //
9eb07ab3f2d4 rhg: use persistent nodemap when available
Simon Sapin <simon-commits@exyr.org>
parents: 46033
diff changeset
   174
        // 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
   175
        // optimize these cases.
46032
8d6164098782 rhg: allow specifying a changeset ID prefix
Simon Sapin <simon-commits@exyr.org>
parents: 45806
diff changeset
   176
        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
   177
        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
   178
            let index_entry =
46443
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46433
diff changeset
   179
                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
   180
                    "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
   181
                ))?;
46033
88e741bf2d93 rust: use NodePrefix::from_hex instead of hex::decode directly
Simon Sapin <simon-commits@exyr.org>
parents: 46032
diff changeset
   182
            if node == *index_entry.hash() {
45534
4f11a67a12fb hg-core: add `Revlog.get_node_rev`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45531
diff changeset
   183
                return Ok(rev);
4f11a67a12fb hg-core: add `Revlog.get_node_rev`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45531
diff changeset
   184
            }
46033
88e741bf2d93 rust: use NodePrefix::from_hex instead of hex::decode directly
Simon Sapin <simon-commits@exyr.org>
parents: 46032
diff changeset
   185
            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
   186
                if found_by_prefix.is_some() {
8d6164098782 rhg: allow specifying a changeset ID prefix
Simon Sapin <simon-commits@exyr.org>
parents: 45806
diff changeset
   187
                    return Err(RevlogError::AmbiguousPrefix);
8d6164098782 rhg: allow specifying a changeset ID prefix
Simon Sapin <simon-commits@exyr.org>
parents: 45806
diff changeset
   188
                }
8d6164098782 rhg: allow specifying a changeset ID prefix
Simon Sapin <simon-commits@exyr.org>
parents: 45806
diff changeset
   189
                found_by_prefix = Some(rev)
8d6164098782 rhg: allow specifying a changeset ID prefix
Simon Sapin <simon-commits@exyr.org>
parents: 45806
diff changeset
   190
            }
45534
4f11a67a12fb hg-core: add `Revlog.get_node_rev`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45531
diff changeset
   191
        }
46032
8d6164098782 rhg: allow specifying a changeset ID prefix
Simon Sapin <simon-commits@exyr.org>
parents: 45806
diff changeset
   192
        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
   193
    }
4f11a67a12fb hg-core: add `Revlog.get_node_rev`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45531
diff changeset
   194
46433
4b381dbbf8b7 rhg: centralize parsing of `--rev` CLI arguments
Simon Sapin <simon.sapin@octobus.net>
parents: 46431
diff changeset
   195
    /// 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
   196
    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
   197
        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
   198
    }
4b381dbbf8b7 rhg: centralize parsing of `--rev` CLI arguments
Simon Sapin <simon.sapin@octobus.net>
parents: 46431
diff changeset
   199
45526
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   200
    /// 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
   201
    ///
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   202
    /// 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
   203
    /// 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
   204
    /// 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
   205
    #[timed]
48541
f2f57724d4eb rhg: Add RevlogEntry::data that does delta resolution
Simon Sapin <simon.sapin@octobus.net>
parents: 48540
diff changeset
   206
    pub fn get_rev_data(
f2f57724d4eb rhg: Add RevlogEntry::data that does delta resolution
Simon Sapin <simon.sapin@octobus.net>
parents: 48540
diff changeset
   207
        &self,
f2f57724d4eb rhg: Add RevlogEntry::data that does delta resolution
Simon Sapin <simon.sapin@octobus.net>
parents: 48540
diff changeset
   208
        rev: Revision,
f2f57724d4eb rhg: Add RevlogEntry::data that does delta resolution
Simon Sapin <simon.sapin@octobus.net>
parents: 48540
diff changeset
   209
    ) -> Result<Cow<[u8]>, RevlogError> {
48198
61ce70fd420e rhg: handle null changelog and manifest revisions
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48083
diff changeset
   210
        if rev == NULL_REVISION {
48541
f2f57724d4eb rhg: Add RevlogEntry::data that does delta resolution
Simon Sapin <simon.sapin@octobus.net>
parents: 48540
diff changeset
   211
            return Ok(Cow::Borrowed(&[]));
48198
61ce70fd420e rhg: handle null changelog and manifest revisions
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48083
diff changeset
   212
        };
48542
35c47015b9b7 rhg: Expose FilelogEntry that wraps RevlogEntry
Simon Sapin <simon.sapin@octobus.net>
parents: 48541
diff changeset
   213
        Ok(self.get_entry(rev)?.data()?)
45526
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   214
    }
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   215
45531
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45526
diff changeset
   216
    /// 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
   217
    pub fn check_hash(
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45526
diff changeset
   218
        &self,
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45526
diff changeset
   219
        p1: Revision,
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45526
diff changeset
   220
        p2: Revision,
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45526
diff changeset
   221
        expected: &[u8],
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45526
diff changeset
   222
        data: &[u8],
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45526
diff changeset
   223
    ) -> 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
   224
        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
   225
        let h1 = match e1 {
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45526
diff changeset
   226
            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
   227
            None => &NULL_NODE,
45531
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45526
diff changeset
   228
        };
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
   229
        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
   230
        let h2 = match e2 {
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45526
diff changeset
   231
            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
   232
            None => &NULL_NODE,
45531
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45526
diff changeset
   233
        };
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45526
diff changeset
   234
47380
fad504cfc94b rust: Use a maintained crate for SHA-1 hashing
Simon Sapin <simon.sapin@octobus.net>
parents: 46821
diff changeset
   235
        &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
   236
    }
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45526
diff changeset
   237
45526
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   238
    /// 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
   239
    /// and its deltas.
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   240
    #[timed]
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   241
    fn build_data_from_deltas(
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   242
        snapshot: RevlogEntry,
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   243
        deltas: &[RevlogEntry],
48542
35c47015b9b7 rhg: Expose FilelogEntry that wraps RevlogEntry
Simon Sapin <simon.sapin@octobus.net>
parents: 48541
diff changeset
   244
    ) -> Result<Vec<u8>, HgError> {
48540
20d0d896183e rhg: Rename some revlog-related types and methods
Simon Sapin <simon.sapin@octobus.net>
parents: 48458
diff changeset
   245
        let snapshot = snapshot.data_chunk()?;
45526
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   246
        let deltas = deltas
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   247
            .iter()
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   248
            .rev()
48540
20d0d896183e rhg: Rename some revlog-related types and methods
Simon Sapin <simon.sapin@octobus.net>
parents: 48458
diff changeset
   249
            .map(RevlogEntry::data_chunk)
48542
35c47015b9b7 rhg: Expose FilelogEntry that wraps RevlogEntry
Simon Sapin <simon.sapin@octobus.net>
parents: 48541
diff changeset
   250
            .collect::<Result<Vec<_>, _>>()?;
45526
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   251
        let patches: Vec<_> =
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   252
            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
   253
        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
   254
        Ok(patch.apply(&snapshot))
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   255
    }
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   256
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   257
    /// Return the revlog data.
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   258
    fn data(&self) -> &[u8] {
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   259
        match self.data_bytes {
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   260
            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
   261
            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
   262
                "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
   263
            ),
45526
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   264
        }
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   265
    }
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   266
49210
cc92ad0e8185 rhg: correctly handle the case where diffs are encoded relative to nullrev
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48546
diff changeset
   267
    pub fn make_null_entry(&self) -> RevlogEntry {
cc92ad0e8185 rhg: correctly handle the case where diffs are encoded relative to nullrev
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48546
diff changeset
   268
        RevlogEntry {
cc92ad0e8185 rhg: correctly handle the case where diffs are encoded relative to nullrev
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48546
diff changeset
   269
            revlog: self,
cc92ad0e8185 rhg: correctly handle the case where diffs are encoded relative to nullrev
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48546
diff changeset
   270
            rev: NULL_REVISION,
cc92ad0e8185 rhg: correctly handle the case where diffs are encoded relative to nullrev
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48546
diff changeset
   271
            bytes: b"",
cc92ad0e8185 rhg: correctly handle the case where diffs are encoded relative to nullrev
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48546
diff changeset
   272
            compressed_len: 0,
cc92ad0e8185 rhg: correctly handle the case where diffs are encoded relative to nullrev
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48546
diff changeset
   273
            uncompressed_len: 0,
cc92ad0e8185 rhg: correctly handle the case where diffs are encoded relative to nullrev
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48546
diff changeset
   274
            base_rev_or_base_of_delta_chain: None,
cc92ad0e8185 rhg: correctly handle the case where diffs are encoded relative to nullrev
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48546
diff changeset
   275
            p1: NULL_REVISION,
cc92ad0e8185 rhg: correctly handle the case where diffs are encoded relative to nullrev
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48546
diff changeset
   276
            p2: NULL_REVISION,
cc92ad0e8185 rhg: correctly handle the case where diffs are encoded relative to nullrev
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48546
diff changeset
   277
            flags: NULL_REVLOG_ENTRY_FLAGS,
cc92ad0e8185 rhg: correctly handle the case where diffs are encoded relative to nullrev
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48546
diff changeset
   278
            hash: NULL_NODE,
cc92ad0e8185 rhg: correctly handle the case where diffs are encoded relative to nullrev
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48546
diff changeset
   279
        }
cc92ad0e8185 rhg: correctly handle the case where diffs are encoded relative to nullrev
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48546
diff changeset
   280
    }
cc92ad0e8185 rhg: correctly handle the case where diffs are encoded relative to nullrev
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48546
diff changeset
   281
45526
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   282
    /// Get an entry of the revlog.
48542
35c47015b9b7 rhg: Expose FilelogEntry that wraps RevlogEntry
Simon Sapin <simon.sapin@octobus.net>
parents: 48541
diff changeset
   283
    pub fn get_entry(
35c47015b9b7 rhg: Expose FilelogEntry that wraps RevlogEntry
Simon Sapin <simon.sapin@octobus.net>
parents: 48541
diff changeset
   284
        &self,
35c47015b9b7 rhg: Expose FilelogEntry that wraps RevlogEntry
Simon Sapin <simon.sapin@octobus.net>
parents: 48541
diff changeset
   285
        rev: Revision,
35c47015b9b7 rhg: Expose FilelogEntry that wraps RevlogEntry
Simon Sapin <simon.sapin@octobus.net>
parents: 48541
diff changeset
   286
    ) -> Result<RevlogEntry, RevlogError> {
49210
cc92ad0e8185 rhg: correctly handle the case where diffs are encoded relative to nullrev
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48546
diff changeset
   287
        if rev == NULL_REVISION {
cc92ad0e8185 rhg: correctly handle the case where diffs are encoded relative to nullrev
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48546
diff changeset
   288
            return Ok(self.make_null_entry());
cc92ad0e8185 rhg: correctly handle the case where diffs are encoded relative to nullrev
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48546
diff changeset
   289
        }
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
   290
        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
   291
            .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
   292
            .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
   293
            .ok_or(RevlogError::InvalidRevision)?;
45526
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   294
        let start = index_entry.offset();
48543
0a4ac916673e rhg: RevlogEntry::uncompressed_len is signed
Simon Sapin <simon.sapin@octobus.net>
parents: 48542
diff changeset
   295
        let end = start + index_entry.compressed_len() as 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
   296
        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
   297
            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
   298
        } 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
   299
            &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
   300
        };
45526
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   301
        let entry = RevlogEntry {
48541
f2f57724d4eb rhg: Add RevlogEntry::data that does delta resolution
Simon Sapin <simon.sapin@octobus.net>
parents: 48540
diff changeset
   302
            revlog: self,
45526
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   303
            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
   304
            bytes: data,
45526
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   305
            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
   306
            uncompressed_len: index_entry.uncompressed_len(),
48458
96ea4db4741b rhg: fix a crash on non-generaldelta revlogs
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48457
diff changeset
   307
            base_rev_or_base_of_delta_chain: if index_entry
96ea4db4741b rhg: fix a crash on non-generaldelta revlogs
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48457
diff changeset
   308
                .base_revision_or_base_of_delta_chain()
96ea4db4741b rhg: fix a crash on non-generaldelta revlogs
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48457
diff changeset
   309
                == rev
96ea4db4741b rhg: fix a crash on non-generaldelta revlogs
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48457
diff changeset
   310
            {
45526
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   311
                None
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   312
            } else {
48458
96ea4db4741b rhg: fix a crash on non-generaldelta revlogs
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48457
diff changeset
   313
                Some(index_entry.base_revision_or_base_of_delta_chain())
45526
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   314
            },
48544
faa243f345cc rhg: Store p1, p2, and hash in RevlogEntry
Simon Sapin <simon.sapin@octobus.net>
parents: 48543
diff changeset
   315
            p1: index_entry.p1(),
faa243f345cc rhg: Store p1, p2, and hash in RevlogEntry
Simon Sapin <simon.sapin@octobus.net>
parents: 48543
diff changeset
   316
            p2: index_entry.p2(),
48546
e91aa800ae5b rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents: 48544
diff changeset
   317
            flags: index_entry.flags(),
48544
faa243f345cc rhg: Store p1, p2, and hash in RevlogEntry
Simon Sapin <simon.sapin@octobus.net>
parents: 48543
diff changeset
   318
            hash: *index_entry.hash(),
45526
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
        Ok(entry)
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   321
    }
48458
96ea4db4741b rhg: fix a crash on non-generaldelta revlogs
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48457
diff changeset
   322
96ea4db4741b rhg: fix a crash on non-generaldelta revlogs
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48457
diff changeset
   323
    /// when resolving internal references within revlog, any errors
96ea4db4741b rhg: fix a crash on non-generaldelta revlogs
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48457
diff changeset
   324
    /// should be reported as corruption, instead of e.g. "invalid revision"
96ea4db4741b rhg: fix a crash on non-generaldelta revlogs
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48457
diff changeset
   325
    fn get_entry_internal(
96ea4db4741b rhg: fix a crash on non-generaldelta revlogs
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48457
diff changeset
   326
        &self,
96ea4db4741b rhg: fix a crash on non-generaldelta revlogs
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48457
diff changeset
   327
        rev: Revision,
48542
35c47015b9b7 rhg: Expose FilelogEntry that wraps RevlogEntry
Simon Sapin <simon.sapin@octobus.net>
parents: 48541
diff changeset
   328
    ) -> Result<RevlogEntry, HgError> {
35c47015b9b7 rhg: Expose FilelogEntry that wraps RevlogEntry
Simon Sapin <simon.sapin@octobus.net>
parents: 48541
diff changeset
   329
        return self.get_entry(rev).map_err(|_| corrupted());
48458
96ea4db4741b rhg: fix a crash on non-generaldelta revlogs
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48457
diff changeset
   330
    }
45526
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   331
}
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   332
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   333
/// 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
   334
/// the entry's data.
48541
f2f57724d4eb rhg: Add RevlogEntry::data that does delta resolution
Simon Sapin <simon.sapin@octobus.net>
parents: 48540
diff changeset
   335
#[derive(Clone)]
45526
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   336
pub struct RevlogEntry<'a> {
48541
f2f57724d4eb rhg: Add RevlogEntry::data that does delta resolution
Simon Sapin <simon.sapin@octobus.net>
parents: 48540
diff changeset
   337
    revlog: &'a Revlog,
45526
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   338
    rev: Revision,
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   339
    bytes: &'a [u8],
48543
0a4ac916673e rhg: RevlogEntry::uncompressed_len is signed
Simon Sapin <simon.sapin@octobus.net>
parents: 48542
diff changeset
   340
    compressed_len: u32,
0a4ac916673e rhg: RevlogEntry::uncompressed_len is signed
Simon Sapin <simon.sapin@octobus.net>
parents: 48542
diff changeset
   341
    uncompressed_len: i32,
48458
96ea4db4741b rhg: fix a crash on non-generaldelta revlogs
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48457
diff changeset
   342
    base_rev_or_base_of_delta_chain: Option<Revision>,
48544
faa243f345cc rhg: Store p1, p2, and hash in RevlogEntry
Simon Sapin <simon.sapin@octobus.net>
parents: 48543
diff changeset
   343
    p1: Revision,
faa243f345cc rhg: Store p1, p2, and hash in RevlogEntry
Simon Sapin <simon.sapin@octobus.net>
parents: 48543
diff changeset
   344
    p2: Revision,
48546
e91aa800ae5b rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents: 48544
diff changeset
   345
    flags: u16,
48544
faa243f345cc rhg: Store p1, p2, and hash in RevlogEntry
Simon Sapin <simon.sapin@octobus.net>
parents: 48543
diff changeset
   346
    hash: Node,
45526
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   347
}
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   348
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   349
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
   350
    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
   351
        self.rev
fecfea658127 hg-core: silence dead-code warning by adding RevlogEntry::revion() accessor
Martin von Zweigbergk <martinvonz@google.com>
parents: 47969
diff changeset
   352
    }
fecfea658127 hg-core: silence dead-code warning by adding RevlogEntry::revion() accessor
Martin von Zweigbergk <martinvonz@google.com>
parents: 47969
diff changeset
   353
48543
0a4ac916673e rhg: RevlogEntry::uncompressed_len is signed
Simon Sapin <simon.sapin@octobus.net>
parents: 48542
diff changeset
   354
    pub fn uncompressed_len(&self) -> Option<u32> {
0a4ac916673e rhg: RevlogEntry::uncompressed_len is signed
Simon Sapin <simon.sapin@octobus.net>
parents: 48542
diff changeset
   355
        u32::try_from(self.uncompressed_len).ok()
0a4ac916673e rhg: RevlogEntry::uncompressed_len is signed
Simon Sapin <simon.sapin@octobus.net>
parents: 48542
diff changeset
   356
    }
0a4ac916673e rhg: RevlogEntry::uncompressed_len is signed
Simon Sapin <simon.sapin@octobus.net>
parents: 48542
diff changeset
   357
48546
e91aa800ae5b rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents: 48544
diff changeset
   358
    pub fn has_p1(&self) -> bool {
e91aa800ae5b rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents: 48544
diff changeset
   359
        self.p1 != NULL_REVISION
e91aa800ae5b rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents: 48544
diff changeset
   360
    }
e91aa800ae5b rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents: 48544
diff changeset
   361
e91aa800ae5b rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents: 48544
diff changeset
   362
    pub fn is_cencored(&self) -> bool {
e91aa800ae5b rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents: 48544
diff changeset
   363
        (self.flags & REVISION_FLAG_CENSORED) != 0
e91aa800ae5b rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents: 48544
diff changeset
   364
    }
e91aa800ae5b rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents: 48544
diff changeset
   365
e91aa800ae5b rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents: 48544
diff changeset
   366
    pub fn has_length_affecting_flag_processor(&self) -> bool {
e91aa800ae5b rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents: 48544
diff changeset
   367
        // Relevant Python code: revlog.size()
e91aa800ae5b rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents: 48544
diff changeset
   368
        // note: ELLIPSIS is known to not change the content
e91aa800ae5b rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents: 48544
diff changeset
   369
        (self.flags & (REVIDX_KNOWN_FLAGS ^ REVISION_FLAG_ELLIPSIS)) != 0
e91aa800ae5b rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents: 48544
diff changeset
   370
    }
e91aa800ae5b rhg: desambiguate status without decompressing filelog if possible
Simon Sapin <simon.sapin@octobus.net>
parents: 48544
diff changeset
   371
48541
f2f57724d4eb rhg: Add RevlogEntry::data that does delta resolution
Simon Sapin <simon.sapin@octobus.net>
parents: 48540
diff changeset
   372
    /// The data for this entry, after resolving deltas if any.
48542
35c47015b9b7 rhg: Expose FilelogEntry that wraps RevlogEntry
Simon Sapin <simon.sapin@octobus.net>
parents: 48541
diff changeset
   373
    pub fn data(&self) -> Result<Cow<'a, [u8]>, HgError> {
48541
f2f57724d4eb rhg: Add RevlogEntry::data that does delta resolution
Simon Sapin <simon.sapin@octobus.net>
parents: 48540
diff changeset
   374
        let mut entry = self.clone();
f2f57724d4eb rhg: Add RevlogEntry::data that does delta resolution
Simon Sapin <simon.sapin@octobus.net>
parents: 48540
diff changeset
   375
        let mut delta_chain = vec![];
f2f57724d4eb rhg: Add RevlogEntry::data that does delta resolution
Simon Sapin <simon.sapin@octobus.net>
parents: 48540
diff changeset
   376
f2f57724d4eb rhg: Add RevlogEntry::data that does delta resolution
Simon Sapin <simon.sapin@octobus.net>
parents: 48540
diff changeset
   377
        // The meaning of `base_rev_or_base_of_delta_chain` depends on
f2f57724d4eb rhg: Add RevlogEntry::data that does delta resolution
Simon Sapin <simon.sapin@octobus.net>
parents: 48540
diff changeset
   378
        // generaldelta. See the doc on `ENTRY_DELTA_BASE` in
f2f57724d4eb rhg: Add RevlogEntry::data that does delta resolution
Simon Sapin <simon.sapin@octobus.net>
parents: 48540
diff changeset
   379
        // `mercurial/revlogutils/constants.py` and the code in
f2f57724d4eb rhg: Add RevlogEntry::data that does delta resolution
Simon Sapin <simon.sapin@octobus.net>
parents: 48540
diff changeset
   380
        // [_chaininfo] and in [index_deltachain].
f2f57724d4eb rhg: Add RevlogEntry::data that does delta resolution
Simon Sapin <simon.sapin@octobus.net>
parents: 48540
diff changeset
   381
        let uses_generaldelta = self.revlog.index.uses_generaldelta();
f2f57724d4eb rhg: Add RevlogEntry::data that does delta resolution
Simon Sapin <simon.sapin@octobus.net>
parents: 48540
diff changeset
   382
        while let Some(base_rev) = entry.base_rev_or_base_of_delta_chain {
f2f57724d4eb rhg: Add RevlogEntry::data that does delta resolution
Simon Sapin <simon.sapin@octobus.net>
parents: 48540
diff changeset
   383
            let base_rev = if uses_generaldelta {
f2f57724d4eb rhg: Add RevlogEntry::data that does delta resolution
Simon Sapin <simon.sapin@octobus.net>
parents: 48540
diff changeset
   384
                base_rev
f2f57724d4eb rhg: Add RevlogEntry::data that does delta resolution
Simon Sapin <simon.sapin@octobus.net>
parents: 48540
diff changeset
   385
            } else {
f2f57724d4eb rhg: Add RevlogEntry::data that does delta resolution
Simon Sapin <simon.sapin@octobus.net>
parents: 48540
diff changeset
   386
                entry.rev - 1
f2f57724d4eb rhg: Add RevlogEntry::data that does delta resolution
Simon Sapin <simon.sapin@octobus.net>
parents: 48540
diff changeset
   387
            };
f2f57724d4eb rhg: Add RevlogEntry::data that does delta resolution
Simon Sapin <simon.sapin@octobus.net>
parents: 48540
diff changeset
   388
            delta_chain.push(entry);
f2f57724d4eb rhg: Add RevlogEntry::data that does delta resolution
Simon Sapin <simon.sapin@octobus.net>
parents: 48540
diff changeset
   389
            entry = self.revlog.get_entry_internal(base_rev)?;
f2f57724d4eb rhg: Add RevlogEntry::data that does delta resolution
Simon Sapin <simon.sapin@octobus.net>
parents: 48540
diff changeset
   390
        }
f2f57724d4eb rhg: Add RevlogEntry::data that does delta resolution
Simon Sapin <simon.sapin@octobus.net>
parents: 48540
diff changeset
   391
f2f57724d4eb rhg: Add RevlogEntry::data that does delta resolution
Simon Sapin <simon.sapin@octobus.net>
parents: 48540
diff changeset
   392
        let data = if delta_chain.is_empty() {
f2f57724d4eb rhg: Add RevlogEntry::data that does delta resolution
Simon Sapin <simon.sapin@octobus.net>
parents: 48540
diff changeset
   393
            entry.data_chunk()?
f2f57724d4eb rhg: Add RevlogEntry::data that does delta resolution
Simon Sapin <simon.sapin@octobus.net>
parents: 48540
diff changeset
   394
        } else {
f2f57724d4eb rhg: Add RevlogEntry::data that does delta resolution
Simon Sapin <simon.sapin@octobus.net>
parents: 48540
diff changeset
   395
            Revlog::build_data_from_deltas(entry, &delta_chain)?.into()
f2f57724d4eb rhg: Add RevlogEntry::data that does delta resolution
Simon Sapin <simon.sapin@octobus.net>
parents: 48540
diff changeset
   396
        };
f2f57724d4eb rhg: Add RevlogEntry::data that does delta resolution
Simon Sapin <simon.sapin@octobus.net>
parents: 48540
diff changeset
   397
f2f57724d4eb rhg: Add RevlogEntry::data that does delta resolution
Simon Sapin <simon.sapin@octobus.net>
parents: 48540
diff changeset
   398
        if self.revlog.check_hash(
48544
faa243f345cc rhg: Store p1, p2, and hash in RevlogEntry
Simon Sapin <simon.sapin@octobus.net>
parents: 48543
diff changeset
   399
            self.p1,
faa243f345cc rhg: Store p1, p2, and hash in RevlogEntry
Simon Sapin <simon.sapin@octobus.net>
parents: 48543
diff changeset
   400
            self.p2,
faa243f345cc rhg: Store p1, p2, and hash in RevlogEntry
Simon Sapin <simon.sapin@octobus.net>
parents: 48543
diff changeset
   401
            self.hash.as_bytes(),
48541
f2f57724d4eb rhg: Add RevlogEntry::data that does delta resolution
Simon Sapin <simon.sapin@octobus.net>
parents: 48540
diff changeset
   402
            &data,
f2f57724d4eb rhg: Add RevlogEntry::data that does delta resolution
Simon Sapin <simon.sapin@octobus.net>
parents: 48540
diff changeset
   403
        ) {
f2f57724d4eb rhg: Add RevlogEntry::data that does delta resolution
Simon Sapin <simon.sapin@octobus.net>
parents: 48540
diff changeset
   404
            Ok(data)
f2f57724d4eb rhg: Add RevlogEntry::data that does delta resolution
Simon Sapin <simon.sapin@octobus.net>
parents: 48540
diff changeset
   405
        } else {
48542
35c47015b9b7 rhg: Expose FilelogEntry that wraps RevlogEntry
Simon Sapin <simon.sapin@octobus.net>
parents: 48541
diff changeset
   406
            Err(corrupted())
48541
f2f57724d4eb rhg: Add RevlogEntry::data that does delta resolution
Simon Sapin <simon.sapin@octobus.net>
parents: 48540
diff changeset
   407
        }
f2f57724d4eb rhg: Add RevlogEntry::data that does delta resolution
Simon Sapin <simon.sapin@octobus.net>
parents: 48540
diff changeset
   408
    }
f2f57724d4eb rhg: Add RevlogEntry::data that does delta resolution
Simon Sapin <simon.sapin@octobus.net>
parents: 48540
diff changeset
   409
45526
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   410
    /// Extract the data contained in the entry.
48540
20d0d896183e rhg: Rename some revlog-related types and methods
Simon Sapin <simon.sapin@octobus.net>
parents: 48458
diff changeset
   411
    /// This may be a delta. (See `is_delta`.)
48542
35c47015b9b7 rhg: Expose FilelogEntry that wraps RevlogEntry
Simon Sapin <simon.sapin@octobus.net>
parents: 48541
diff changeset
   412
    fn data_chunk(&self) -> Result<Cow<'a, [u8]>, HgError> {
45526
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   413
        if self.bytes.is_empty() {
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   414
            return Ok(Cow::Borrowed(&[]));
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   415
        }
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   416
        match self.bytes[0] {
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   417
            // 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
   418
            // header.
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   419
            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
   420
            // Raw revision data follows.
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   421
            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
   422
            // 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
   423
            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
   424
            // zstd data.
45595
497657895b54 hg-core: return `Err` on decompression error (D8958#inline-15004 followup)
Antoine cezar<acezar@chwitlabs.fr>
parents: 45536
diff changeset
   425
            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
   426
            // A proper new format should have had a repo/store requirement.
48542
35c47015b9b7 rhg: Expose FilelogEntry that wraps RevlogEntry
Simon Sapin <simon.sapin@octobus.net>
parents: 48541
diff changeset
   427
            _format_type => Err(corrupted()),
45526
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   428
        }
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   429
    }
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   430
48542
35c47015b9b7 rhg: Expose FilelogEntry that wraps RevlogEntry
Simon Sapin <simon.sapin@octobus.net>
parents: 48541
diff changeset
   431
    fn uncompressed_zlib_data(&self) -> Result<Vec<u8>, HgError> {
45526
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   432
        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
   433
        if self.is_delta() {
48543
0a4ac916673e rhg: RevlogEntry::uncompressed_len is signed
Simon Sapin <simon.sapin@octobus.net>
parents: 48542
diff changeset
   434
            let mut buf = Vec::with_capacity(self.compressed_len as usize);
48542
35c47015b9b7 rhg: Expose FilelogEntry that wraps RevlogEntry
Simon Sapin <simon.sapin@octobus.net>
parents: 48541
diff changeset
   435
            decoder.read_to_end(&mut buf).map_err(|_| corrupted())?;
45595
497657895b54 hg-core: return `Err` on decompression error (D8958#inline-15004 followup)
Antoine cezar<acezar@chwitlabs.fr>
parents: 45536
diff changeset
   436
            Ok(buf)
45526
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   437
        } else {
48543
0a4ac916673e rhg: RevlogEntry::uncompressed_len is signed
Simon Sapin <simon.sapin@octobus.net>
parents: 48542
diff changeset
   438
            let cap = self.uncompressed_len.max(0) as usize;
0a4ac916673e rhg: RevlogEntry::uncompressed_len is signed
Simon Sapin <simon.sapin@octobus.net>
parents: 48542
diff changeset
   439
            let mut buf = vec![0; cap];
48542
35c47015b9b7 rhg: Expose FilelogEntry that wraps RevlogEntry
Simon Sapin <simon.sapin@octobus.net>
parents: 48541
diff changeset
   440
            decoder.read_exact(&mut buf).map_err(|_| corrupted())?;
45595
497657895b54 hg-core: return `Err` on decompression error (D8958#inline-15004 followup)
Antoine cezar<acezar@chwitlabs.fr>
parents: 45536
diff changeset
   441
            Ok(buf)
45526
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   442
        }
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   443
    }
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   444
48542
35c47015b9b7 rhg: Expose FilelogEntry that wraps RevlogEntry
Simon Sapin <simon.sapin@octobus.net>
parents: 48541
diff changeset
   445
    fn uncompressed_zstd_data(&self) -> Result<Vec<u8>, HgError> {
45526
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   446
        if self.is_delta() {
48543
0a4ac916673e rhg: RevlogEntry::uncompressed_len is signed
Simon Sapin <simon.sapin@octobus.net>
parents: 48542
diff changeset
   447
            let mut buf = Vec::with_capacity(self.compressed_len as usize);
45526
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   448
            zstd::stream::copy_decode(self.bytes, &mut buf)
48542
35c47015b9b7 rhg: Expose FilelogEntry that wraps RevlogEntry
Simon Sapin <simon.sapin@octobus.net>
parents: 48541
diff changeset
   449
                .map_err(|_| corrupted())?;
45595
497657895b54 hg-core: return `Err` on decompression error (D8958#inline-15004 followup)
Antoine cezar<acezar@chwitlabs.fr>
parents: 45536
diff changeset
   450
            Ok(buf)
45526
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   451
        } else {
48543
0a4ac916673e rhg: RevlogEntry::uncompressed_len is signed
Simon Sapin <simon.sapin@octobus.net>
parents: 48542
diff changeset
   452
            let cap = self.uncompressed_len.max(0) as usize;
0a4ac916673e rhg: RevlogEntry::uncompressed_len is signed
Simon Sapin <simon.sapin@octobus.net>
parents: 48542
diff changeset
   453
            let mut buf = vec![0; cap];
45526
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   454
            let len = zstd::block::decompress_to_buffer(self.bytes, &mut buf)
48542
35c47015b9b7 rhg: Expose FilelogEntry that wraps RevlogEntry
Simon Sapin <simon.sapin@octobus.net>
parents: 48541
diff changeset
   455
                .map_err(|_| corrupted())?;
48543
0a4ac916673e rhg: RevlogEntry::uncompressed_len is signed
Simon Sapin <simon.sapin@octobus.net>
parents: 48542
diff changeset
   456
            if len != self.uncompressed_len as usize {
48542
35c47015b9b7 rhg: Expose FilelogEntry that wraps RevlogEntry
Simon Sapin <simon.sapin@octobus.net>
parents: 48541
diff changeset
   457
                Err(corrupted())
45595
497657895b54 hg-core: return `Err` on decompression error (D8958#inline-15004 followup)
Antoine cezar<acezar@chwitlabs.fr>
parents: 45536
diff changeset
   458
            } else {
497657895b54 hg-core: return `Err` on decompression error (D8958#inline-15004 followup)
Antoine cezar<acezar@chwitlabs.fr>
parents: 45536
diff changeset
   459
                Ok(buf)
497657895b54 hg-core: return `Err` on decompression error (D8958#inline-15004 followup)
Antoine cezar<acezar@chwitlabs.fr>
parents: 45536
diff changeset
   460
            }
45526
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   461
        }
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   462
    }
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   463
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   464
    /// 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
   465
    /// (influences on decompression).
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   466
    fn is_delta(&self) -> bool {
48458
96ea4db4741b rhg: fix a crash on non-generaldelta revlogs
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48457
diff changeset
   467
        self.base_rev_or_base_of_delta_chain.is_some()
45526
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   468
    }
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   469
}
26c53ee51c68 hg-core: Add a limited read only `revlog` implementation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   470
45531
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45526
diff changeset
   471
/// 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
   472
fn hash(
fad504cfc94b rust: Use a maintained crate for SHA-1 hashing
Simon Sapin <simon.sapin@octobus.net>
parents: 46821
diff changeset
   473
    data: &[u8],
fad504cfc94b rust: Use a maintained crate for SHA-1 hashing
Simon Sapin <simon.sapin@octobus.net>
parents: 46821
diff changeset
   474
    p1_hash: &[u8],
fad504cfc94b rust: Use a maintained crate for SHA-1 hashing
Simon Sapin <simon.sapin@octobus.net>
parents: 46821
diff changeset
   475
    p2_hash: &[u8],
fad504cfc94b rust: Use a maintained crate for SHA-1 hashing
Simon Sapin <simon.sapin@octobus.net>
parents: 46821
diff changeset
   476
) -> [u8; NODE_BYTES_LENGTH] {
45531
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45526
diff changeset
   477
    let mut hasher = Sha1::new();
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45526
diff changeset
   478
    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
   479
    if a > b {
47380
fad504cfc94b rust: Use a maintained crate for SHA-1 hashing
Simon Sapin <simon.sapin@octobus.net>
parents: 46821
diff changeset
   480
        hasher.update(b);
fad504cfc94b rust: Use a maintained crate for SHA-1 hashing
Simon Sapin <simon.sapin@octobus.net>
parents: 46821
diff changeset
   481
        hasher.update(a);
45531
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45526
diff changeset
   482
    } else {
47380
fad504cfc94b rust: Use a maintained crate for SHA-1 hashing
Simon Sapin <simon.sapin@octobus.net>
parents: 46821
diff changeset
   483
        hasher.update(a);
fad504cfc94b rust: Use a maintained crate for SHA-1 hashing
Simon Sapin <simon.sapin@octobus.net>
parents: 46821
diff changeset
   484
        hasher.update(b);
45531
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45526
diff changeset
   485
    }
47380
fad504cfc94b rust: Use a maintained crate for SHA-1 hashing
Simon Sapin <simon.sapin@octobus.net>
parents: 46821
diff changeset
   486
    hasher.update(data);
fad504cfc94b rust: Use a maintained crate for SHA-1 hashing
Simon Sapin <simon.sapin@octobus.net>
parents: 46821
diff changeset
   487
    *hasher.finalize().as_ref()
45531
b0d6309ff50c hg-core: check data integrity in `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45526
diff changeset
   488
}