rust/hg-core/src/revlog/manifest.rs
author Raphaël Gomès <rgomes@octobus.net>
Tue, 10 Jan 2023 11:20:54 +0100
changeset 49937 750409505286
parent 49090 a5ef50becea8
child 50977 1928b770e3e7
permissions -rw-r--r--
rust-clippy: merge "revlog" module definition and struct implementation Module inception is confusing when looking for code and almost never the right choice.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
47963
001d747c2baf rust: Return HgError instead of RevlogError in revlog constructors
Simon Sapin <simon.sapin@octobus.net>
parents: 47957
diff changeset
     1
use crate::errors::HgError;
45533
89ac95bd4993 hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
     2
use crate::revlog::Revision;
47964
796206e74b10 rhg: Reuse manifest when checking status of multiple ambiguous files
Simon Sapin <simon.sapin@octobus.net>
parents: 47963
diff changeset
     3
use crate::revlog::{Node, NodePrefix};
49937
750409505286 rust-clippy: merge "revlog" module definition and struct implementation
Raphaël Gomès <rgomes@octobus.net>
parents: 49090
diff changeset
     4
use crate::revlog::{Revlog, RevlogError};
45533
89ac95bd4993 hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
     5
use crate::utils::hg_path::HgPath;
48343
eb428010aad2 rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents: 48342
diff changeset
     6
use crate::utils::SliceExt;
49090
a5ef50becea8 rust-revlog: make `Changelog` and `ManifestLog` unaware of `Repo`
Martin von Zweigbergk <martinvonz@google.com>
parents: 49089
diff changeset
     7
use crate::vfs::Vfs;
45533
89ac95bd4993 hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
     8
89ac95bd4993 hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
     9
/// A specialized `Revlog` to work with `manifest` data format.
47957
d44740725b95 rust: Rename Manifest to Manifestlog, ManifestEntry to Manifest
Simon Sapin <simon.sapin@octobus.net>
parents: 46431
diff changeset
    10
pub struct Manifestlog {
45533
89ac95bd4993 hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    11
    /// The generic `revlog` format.
89ac95bd4993 hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    12
    revlog: Revlog,
89ac95bd4993 hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    13
}
89ac95bd4993 hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    14
47957
d44740725b95 rust: Rename Manifest to Manifestlog, ManifestEntry to Manifest
Simon Sapin <simon.sapin@octobus.net>
parents: 46431
diff changeset
    15
impl Manifestlog {
45533
89ac95bd4993 hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    16
    /// Open the `manifest` of a repository given by its root.
49090
a5ef50becea8 rust-revlog: make `Changelog` and `ManifestLog` unaware of `Repo`
Martin von Zweigbergk <martinvonz@google.com>
parents: 49089
diff changeset
    17
    pub fn open(store_vfs: &Vfs, use_nodemap: bool) -> Result<Self, HgError> {
a5ef50becea8 rust-revlog: make `Changelog` and `ManifestLog` unaware of `Repo`
Martin von Zweigbergk <martinvonz@google.com>
parents: 49089
diff changeset
    18
        let revlog =
a5ef50becea8 rust-revlog: make `Changelog` and `ManifestLog` unaware of `Repo`
Martin von Zweigbergk <martinvonz@google.com>
parents: 49089
diff changeset
    19
            Revlog::open(store_vfs, "00manifest.i", None, use_nodemap)?;
45533
89ac95bd4993 hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    20
        Ok(Self { revlog })
89ac95bd4993 hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    21
    }
89ac95bd4993 hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    22
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
    23
    /// Return the `Manifest` for the given node ID.
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
    24
    ///
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
    25
    /// Note: this is a node ID in the manifestlog, typically found through
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
    26
    /// `ChangelogEntry::manifest_node`. It is *not* the node ID of any
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
    27
    /// changeset.
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
    28
    ///
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
    29
    /// See also `Repo::manifest_for_node`
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
    30
    pub fn data_for_node(
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
    31
        &self,
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
    32
        node: NodePrefix,
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
    33
    ) -> Result<Manifest, RevlogError> {
47968
6f579618ea7b rust: Rename the `Revlog::get_node_rev` method to `rev_from_node`
Simon Sapin <simon.sapin@octobus.net>
parents: 47964
diff changeset
    34
        let rev = self.revlog.rev_from_node(node)?;
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
    35
        self.data_for_rev(rev)
45533
89ac95bd4993 hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    36
    }
89ac95bd4993 hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    37
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
    38
    /// Return the `Manifest` of a given revision number.
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
    39
    ///
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
    40
    /// Note: this is a revision number in the manifestlog, *not* of any
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
    41
    /// changeset.
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
    42
    ///
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
    43
    /// See also `Repo::manifest_for_rev`
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
    44
    pub fn data_for_rev(
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
    45
        &self,
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
    46
        rev: Revision,
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
    47
    ) -> Result<Manifest, RevlogError> {
48541
f2f57724d4eb rhg: Add RevlogEntry::data that does delta resolution
Simon Sapin <simon.sapin@octobus.net>
parents: 48495
diff changeset
    48
        let bytes = self.revlog.get_rev_data(rev)?.into_owned();
47957
d44740725b95 rust: Rename Manifest to Manifestlog, ManifestEntry to Manifest
Simon Sapin <simon.sapin@octobus.net>
parents: 46431
diff changeset
    49
        Ok(Manifest { bytes })
45533
89ac95bd4993 hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    50
    }
89ac95bd4993 hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    51
}
89ac95bd4993 hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    52
47957
d44740725b95 rust: Rename Manifest to Manifestlog, ManifestEntry to Manifest
Simon Sapin <simon.sapin@octobus.net>
parents: 46431
diff changeset
    53
/// `Manifestlog` entry which knows how to interpret the `manifest` data bytes.
45533
89ac95bd4993 hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    54
#[derive(Debug)]
47957
d44740725b95 rust: Rename Manifest to Manifestlog, ManifestEntry to Manifest
Simon Sapin <simon.sapin@octobus.net>
parents: 46431
diff changeset
    55
pub struct Manifest {
48495
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
    56
    /// Format for a manifest: flat sequence of variable-size entries,
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
    57
    /// sorted by path, each as:
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
    58
    ///
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
    59
    /// ```text
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
    60
    /// <path> \0 <hex_node_id> <flags> \n
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
    61
    /// ```
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
    62
    ///
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
    63
    /// The last entry is also terminated by a newline character.
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
    64
    /// Flags is one of `b""` (the empty string), `b"x"`, `b"l"`, or `b"t"`.
45533
89ac95bd4993 hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    65
    bytes: Vec<u8>,
89ac95bd4993 hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    66
}
89ac95bd4993 hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    67
47957
d44740725b95 rust: Rename Manifest to Manifestlog, ManifestEntry to Manifest
Simon Sapin <simon.sapin@octobus.net>
parents: 46431
diff changeset
    68
impl Manifest {
48343
eb428010aad2 rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents: 48342
diff changeset
    69
    pub fn iter(
eb428010aad2 rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents: 48342
diff changeset
    70
        &self,
eb428010aad2 rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents: 48342
diff changeset
    71
    ) -> impl Iterator<Item = Result<ManifestEntry, HgError>> {
45533
89ac95bd4993 hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    72
        self.bytes
89ac95bd4993 hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    73
            .split(|b| b == &b'\n')
89ac95bd4993 hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    74
            .filter(|line| !line.is_empty())
48495
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
    75
            .map(ManifestEntry::from_raw)
45540
f2de24c2b1f6 hg-core: add `files_with_nodes` to `Manifest`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45533
diff changeset
    76
    }
47964
796206e74b10 rhg: Reuse manifest when checking status of multiple ambiguous files
Simon Sapin <simon.sapin@octobus.net>
parents: 47963
diff changeset
    77
796206e74b10 rhg: Reuse manifest when checking status of multiple ambiguous files
Simon Sapin <simon.sapin@octobus.net>
parents: 47963
diff changeset
    78
    /// If the given path is in this manifest, return its filelog node ID
48495
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
    79
    pub fn find_by_path(
48343
eb428010aad2 rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents: 48342
diff changeset
    80
        &self,
eb428010aad2 rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents: 48342
diff changeset
    81
        path: &HgPath,
eb428010aad2 rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents: 48342
diff changeset
    82
    ) -> Result<Option<ManifestEntry>, HgError> {
48495
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
    83
        use std::cmp::Ordering::*;
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
    84
        let path = path.as_bytes();
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
    85
        // Both boundaries of this `&[u8]` slice are always at the boundary of
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
    86
        // an entry
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
    87
        let mut bytes = &*self.bytes;
48343
eb428010aad2 rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents: 48342
diff changeset
    88
48495
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
    89
        // Binary search algorithm derived from `[T]::binary_search_by`
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
    90
        // <https://github.com/rust-lang/rust/blob/1.57.0/library/core/src/slice/mod.rs#L2221>
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
    91
        // except we don’t have a slice of entries. Instead we jump to the
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
    92
        // middle of the byte slice and look around for entry delimiters
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
    93
        // (newlines).
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
    94
        while let Some(entry_range) = Self::find_entry_near_middle_of(bytes)? {
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
    95
            let (entry_path, rest) =
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
    96
                ManifestEntry::split_path(&bytes[entry_range.clone()])?;
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
    97
            let cmp = entry_path.cmp(path);
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
    98
            if cmp == Less {
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
    99
                let after_newline = entry_range.end + 1;
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
   100
                bytes = &bytes[after_newline..];
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
   101
            } else if cmp == Greater {
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
   102
                bytes = &bytes[..entry_range.start];
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
   103
            } else {
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
   104
                return Ok(Some(ManifestEntry::from_path_and_rest(
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
   105
                    entry_path, rest,
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
   106
                )));
47964
796206e74b10 rhg: Reuse manifest when checking status of multiple ambiguous files
Simon Sapin <simon.sapin@octobus.net>
parents: 47963
diff changeset
   107
            }
796206e74b10 rhg: Reuse manifest when checking status of multiple ambiguous files
Simon Sapin <simon.sapin@octobus.net>
parents: 47963
diff changeset
   108
        }
796206e74b10 rhg: Reuse manifest when checking status of multiple ambiguous files
Simon Sapin <simon.sapin@octobus.net>
parents: 47963
diff changeset
   109
        Ok(None)
796206e74b10 rhg: Reuse manifest when checking status of multiple ambiguous files
Simon Sapin <simon.sapin@octobus.net>
parents: 47963
diff changeset
   110
    }
48495
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
   111
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
   112
    /// If there is at least one, return the byte range of an entry *excluding*
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
   113
    /// the final newline.
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
   114
    fn find_entry_near_middle_of(
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
   115
        bytes: &[u8],
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
   116
    ) -> Result<Option<std::ops::Range<usize>>, HgError> {
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
   117
        let len = bytes.len();
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
   118
        if len > 0 {
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
   119
            let middle = bytes.len() / 2;
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
   120
            // Integer division rounds down, so `middle < len`.
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
   121
            let (before, after) = bytes.split_at(middle);
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
   122
            let is_newline = |&byte: &u8| byte == b'\n';
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
   123
            let entry_start = match before.iter().rposition(is_newline) {
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
   124
                Some(i) => i + 1,
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
   125
                None => 0, // We choose the first entry in `bytes`
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
   126
            };
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
   127
            let entry_end = match after.iter().position(is_newline) {
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
   128
                Some(i) => {
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
   129
                    // No `+ 1` here to exclude this newline from the range
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
   130
                    middle + i
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
   131
                }
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
   132
                None => {
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
   133
                    // In a well-formed manifest:
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
   134
                    //
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
   135
                    // * Since `len > 0`, `bytes` contains at least one entry
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
   136
                    // * Every entry ends with a newline
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
   137
                    // * Since `middle < len`, `after` contains at least the
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
   138
                    //   newline at the end of the last entry of `bytes`.
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
   139
                    //
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
   140
                    // We didn’t find a newline, so this manifest is not
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
   141
                    // well-formed.
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
   142
                    return Err(HgError::corrupted(
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
   143
                        "manifest entry without \\n delimiter",
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
   144
                    ));
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
   145
                }
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
   146
            };
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
   147
            Ok(Some(entry_start..entry_end))
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
   148
        } else {
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
   149
            // len == 0
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
   150
            Ok(None)
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
   151
        }
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
   152
    }
45533
89ac95bd4993 hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
   153
}
48343
eb428010aad2 rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents: 48342
diff changeset
   154
eb428010aad2 rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents: 48342
diff changeset
   155
/// `Manifestlog` entry which knows how to interpret the `manifest` data bytes.
eb428010aad2 rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents: 48342
diff changeset
   156
#[derive(Debug)]
eb428010aad2 rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents: 48342
diff changeset
   157
pub struct ManifestEntry<'manifest> {
eb428010aad2 rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents: 48342
diff changeset
   158
    pub path: &'manifest HgPath,
eb428010aad2 rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents: 48342
diff changeset
   159
    pub hex_node_id: &'manifest [u8],
eb428010aad2 rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents: 48342
diff changeset
   160
eb428010aad2 rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents: 48342
diff changeset
   161
    /// `Some` values are b'x', b'l', or 't'
eb428010aad2 rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents: 48342
diff changeset
   162
    pub flags: Option<u8>,
eb428010aad2 rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents: 48342
diff changeset
   163
}
eb428010aad2 rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents: 48342
diff changeset
   164
48495
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
   165
impl<'a> ManifestEntry<'a> {
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
   166
    fn split_path(bytes: &[u8]) -> Result<(&[u8], &[u8]), HgError> {
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
   167
        bytes.split_2(b'\0').ok_or_else(|| {
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
   168
            HgError::corrupted("manifest entry without \\0 delimiter")
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
   169
        })
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
   170
    }
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
   171
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
   172
    fn from_path_and_rest(path: &'a [u8], rest: &'a [u8]) -> Self {
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
   173
        let (hex_node_id, flags) = match rest.split_last() {
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
   174
            Some((&b'x', rest)) => (rest, Some(b'x')),
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
   175
            Some((&b'l', rest)) => (rest, Some(b'l')),
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
   176
            Some((&b't', rest)) => (rest, Some(b't')),
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
   177
            _ => (rest, None),
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
   178
        };
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
   179
        Self {
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
   180
            path: HgPath::new(path),
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
   181
            hex_node_id,
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
   182
            flags,
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
   183
        }
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
   184
    }
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
   185
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
   186
    fn from_raw(bytes: &'a [u8]) -> Result<Self, HgError> {
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
   187
        let (path, rest) = Self::split_path(bytes)?;
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
   188
        Ok(Self::from_path_and_rest(path, rest))
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
   189
    }
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
   190
48343
eb428010aad2 rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents: 48342
diff changeset
   191
    pub fn node_id(&self) -> Result<Node, HgError> {
eb428010aad2 rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents: 48342
diff changeset
   192
        Node::from_hex_for_repo(self.hex_node_id)
eb428010aad2 rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents: 48342
diff changeset
   193
    }
eb428010aad2 rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents: 48342
diff changeset
   194
}