rust/hg-core/src/dirstate_tree/on_disk.rs
author Pierre-Yves David <pierre-yves.david@octobus.net>
Fri, 15 Oct 2021 16:33:19 +0200
changeset 48251 dfc5a505ddc5
parent 48250 1730b2fceaa1
child 48253 948570aa7630
permissions -rw-r--r--
dirstate-v2: adds two flag to track the presence of some unrecorded files Right now, we don't record ignored or unknown files in the dirstate. However the structure would allow it. So we introduce two flags that can be used to clarify whether all unknown/ignored children are recorded or not. This will allow for more information to be stored in the future if this end up being relevant. Differential Revision: https://phab.mercurial-scm.org/D11682
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
47283
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
     1
//! The "version 2" disk representation of the dirstate
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
     2
//!
48166
e8a576de703f dirstate-v2: Add internal documentation
Simon Sapin <simon.sapin@octobus.net>
parents: 48165
diff changeset
     3
//! See `mercurial/helptext/internals/dirstate-v2.txt`
47283
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
     4
48193
320de901896a dirstate-v2: Truncate directory mtimes to 31 bits of seconds
Simon Sapin <simon.sapin@octobus.net>
parents: 48192
diff changeset
     5
use crate::dirstate::TruncatedTimestamp;
47333
69530e5d4fe5 dirstate-tree: Add `NodeRef` and `ChildNodesRef` enums
Simon Sapin <simon.sapin@octobus.net>
parents: 47331
diff changeset
     6
use crate::dirstate_tree::dirstate_map::{self, DirstateMap, NodeRef};
47283
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
     7
use crate::dirstate_tree::path_with_basename::WithBasename;
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
     8
use crate::errors::HgError;
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
     9
use crate::utils::hg_path::HgPath;
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
    10
use crate::DirstateEntry;
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
    11
use crate::DirstateError;
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
    12
use crate::DirstateParents;
48139
ab5a7fdbf75c dirstate-v2: Store a bitfield on disk instead of v1-like state
Simon Sapin <simon.sapin@octobus.net>
parents: 48022
diff changeset
    13
use bitflags::bitflags;
48194
1000db4a71f1 dirstate-v2: Store unsigned integers inside DirstateEntry
Simon Sapin <simon.sapin@octobus.net>
parents: 48193
diff changeset
    14
use bytes_cast::unaligned::{U16Be, U32Be};
47283
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
    15
use bytes_cast::BytesCast;
47674
ff97e793ed36 dirstate-v2: Introduce a docket file
Simon Sapin <simon.sapin@octobus.net>
parents: 47491
diff changeset
    16
use format_bytes::format_bytes;
47283
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
    17
use std::borrow::Cow;
47675
48aec076b8fb dirstate-v2: Enforce data size read from the docket file
Simon Sapin <simon.sapin@octobus.net>
parents: 47674
diff changeset
    18
use std::convert::{TryFrom, TryInto};
47283
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
    19
47280
1766130fe9ba dirstate-v2: Change the on-disk format when the requirement is enabled
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    20
/// Added at the start of `.hg/dirstate` when the "v2" format is used.
47283
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
    21
/// This a redundant sanity check more than an actual "magic number" since
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
    22
/// `.hg/requires` already governs which format should be used.
47280
1766130fe9ba dirstate-v2: Change the on-disk format when the requirement is enabled
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    23
pub const V2_FORMAT_MARKER: &[u8; 12] = b"dirstate-v2\n";
47283
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
    24
47674
ff97e793ed36 dirstate-v2: Introduce a docket file
Simon Sapin <simon.sapin@octobus.net>
parents: 47491
diff changeset
    25
/// Keep space for 256-bit hashes
ff97e793ed36 dirstate-v2: Introduce a docket file
Simon Sapin <simon.sapin@octobus.net>
parents: 47491
diff changeset
    26
const STORED_NODE_ID_BYTES: usize = 32;
ff97e793ed36 dirstate-v2: Introduce a docket file
Simon Sapin <simon.sapin@octobus.net>
parents: 47491
diff changeset
    27
ff97e793ed36 dirstate-v2: Introduce a docket file
Simon Sapin <simon.sapin@octobus.net>
parents: 47491
diff changeset
    28
/// … even though only 160 bits are used for now, with SHA-1
ff97e793ed36 dirstate-v2: Introduce a docket file
Simon Sapin <simon.sapin@octobus.net>
parents: 47491
diff changeset
    29
const USED_NODE_ID_BYTES: usize = 20;
ff97e793ed36 dirstate-v2: Introduce a docket file
Simon Sapin <simon.sapin@octobus.net>
parents: 47491
diff changeset
    30
47409
0ef8231e413f dirstate-v2: Store a hash of ignore patterns (.hgignore)
Simon Sapin <simon.sapin@octobus.net>
parents: 47374
diff changeset
    31
pub(super) const IGNORE_PATTERNS_HASH_LEN: usize = 20;
0ef8231e413f dirstate-v2: Store a hash of ignore patterns (.hgignore)
Simon Sapin <simon.sapin@octobus.net>
parents: 47374
diff changeset
    32
pub(super) type IgnorePatternsHash = [u8; IGNORE_PATTERNS_HASH_LEN];
0ef8231e413f dirstate-v2: Store a hash of ignore patterns (.hgignore)
Simon Sapin <simon.sapin@octobus.net>
parents: 47374
diff changeset
    33
48221
a32a96079e2d dirstate-v2: initial Python parser
Simon Sapin <simon.sapin@octobus.net>
parents: 48219
diff changeset
    34
/// Must match constants of the same names in `mercurial/dirstateutils/v2.py`
47684
852262e2e7d9 dirstate-v2: Reserve a few bytes of space for future extensions
Simon Sapin <simon.sapin@octobus.net>
parents: 47682
diff changeset
    35
const TREE_METADATA_SIZE: usize = 44;
48231
0524c1359bfc dirstate-v2: Extend node flags to 16 bits
Simon Sapin <simon.sapin@octobus.net>
parents: 48221
diff changeset
    36
const NODE_SIZE: usize = 44;
48196
47fabca85457 dirstate-v2: Name a constant in the Rust implementation
Simon Sapin <simon.sapin@octobus.net>
parents: 48195
diff changeset
    37
47682
78f7f0d490ee dirstate-v2: Move fixed-size tree metadata into the docket file
Simon Sapin <simon.sapin@octobus.net>
parents: 47681
diff changeset
    38
/// Make sure that size-affecting changes are made knowingly
78f7f0d490ee dirstate-v2: Move fixed-size tree metadata into the docket file
Simon Sapin <simon.sapin@octobus.net>
parents: 47681
diff changeset
    39
#[allow(unused)]
78f7f0d490ee dirstate-v2: Move fixed-size tree metadata into the docket file
Simon Sapin <simon.sapin@octobus.net>
parents: 47681
diff changeset
    40
fn static_assert_size_of() {
78f7f0d490ee dirstate-v2: Move fixed-size tree metadata into the docket file
Simon Sapin <simon.sapin@octobus.net>
parents: 47681
diff changeset
    41
    let _ = std::mem::transmute::<TreeMetadata, [u8; TREE_METADATA_SIZE]>;
47684
852262e2e7d9 dirstate-v2: Reserve a few bytes of space for future extensions
Simon Sapin <simon.sapin@octobus.net>
parents: 47682
diff changeset
    42
    let _ = std::mem::transmute::<DocketHeader, [u8; TREE_METADATA_SIZE + 81]>;
48196
47fabca85457 dirstate-v2: Name a constant in the Rust implementation
Simon Sapin <simon.sapin@octobus.net>
parents: 48195
diff changeset
    43
    let _ = std::mem::transmute::<Node, [u8; NODE_SIZE]>;
47682
78f7f0d490ee dirstate-v2: Move fixed-size tree metadata into the docket file
Simon Sapin <simon.sapin@octobus.net>
parents: 47681
diff changeset
    44
}
78f7f0d490ee dirstate-v2: Move fixed-size tree metadata into the docket file
Simon Sapin <simon.sapin@octobus.net>
parents: 47681
diff changeset
    45
47674
ff97e793ed36 dirstate-v2: Introduce a docket file
Simon Sapin <simon.sapin@octobus.net>
parents: 47491
diff changeset
    46
// Must match `HEADER` in `mercurial/dirstateutils/docket.py`
ff97e793ed36 dirstate-v2: Introduce a docket file
Simon Sapin <simon.sapin@octobus.net>
parents: 47491
diff changeset
    47
#[derive(BytesCast)]
ff97e793ed36 dirstate-v2: Introduce a docket file
Simon Sapin <simon.sapin@octobus.net>
parents: 47491
diff changeset
    48
#[repr(C)]
ff97e793ed36 dirstate-v2: Introduce a docket file
Simon Sapin <simon.sapin@octobus.net>
parents: 47491
diff changeset
    49
struct DocketHeader {
ff97e793ed36 dirstate-v2: Introduce a docket file
Simon Sapin <simon.sapin@octobus.net>
parents: 47491
diff changeset
    50
    marker: [u8; V2_FORMAT_MARKER.len()],
ff97e793ed36 dirstate-v2: Introduce a docket file
Simon Sapin <simon.sapin@octobus.net>
parents: 47491
diff changeset
    51
    parent_1: [u8; STORED_NODE_ID_BYTES],
ff97e793ed36 dirstate-v2: Introduce a docket file
Simon Sapin <simon.sapin@octobus.net>
parents: 47491
diff changeset
    52
    parent_2: [u8; STORED_NODE_ID_BYTES],
47677
da1c0cd68d53 dirstate-v2: shrink on-disk path lengths to 16-bits
Simon Sapin <simon.sapin@octobus.net>
parents: 47676
diff changeset
    53
48165
d467e44f71d7 dirstate-v2: Move data file info in the docket closer together
Simon Sapin <simon.sapin@octobus.net>
parents: 48139
diff changeset
    54
    metadata: TreeMetadata,
d467e44f71d7 dirstate-v2: Move data file info in the docket closer together
Simon Sapin <simon.sapin@octobus.net>
parents: 48139
diff changeset
    55
47677
da1c0cd68d53 dirstate-v2: shrink on-disk path lengths to 16-bits
Simon Sapin <simon.sapin@octobus.net>
parents: 47676
diff changeset
    56
    /// Counted in bytes
47674
ff97e793ed36 dirstate-v2: Introduce a docket file
Simon Sapin <simon.sapin@octobus.net>
parents: 47491
diff changeset
    57
    data_size: Size,
47677
da1c0cd68d53 dirstate-v2: shrink on-disk path lengths to 16-bits
Simon Sapin <simon.sapin@octobus.net>
parents: 47676
diff changeset
    58
47674
ff97e793ed36 dirstate-v2: Introduce a docket file
Simon Sapin <simon.sapin@octobus.net>
parents: 47491
diff changeset
    59
    uuid_size: u8,
ff97e793ed36 dirstate-v2: Introduce a docket file
Simon Sapin <simon.sapin@octobus.net>
parents: 47491
diff changeset
    60
}
ff97e793ed36 dirstate-v2: Introduce a docket file
Simon Sapin <simon.sapin@octobus.net>
parents: 47491
diff changeset
    61
ff97e793ed36 dirstate-v2: Introduce a docket file
Simon Sapin <simon.sapin@octobus.net>
parents: 47491
diff changeset
    62
pub struct Docket<'on_disk> {
ff97e793ed36 dirstate-v2: Introduce a docket file
Simon Sapin <simon.sapin@octobus.net>
parents: 47491
diff changeset
    63
    header: &'on_disk DocketHeader,
ff97e793ed36 dirstate-v2: Introduce a docket file
Simon Sapin <simon.sapin@octobus.net>
parents: 47491
diff changeset
    64
    uuid: &'on_disk [u8],
ff97e793ed36 dirstate-v2: Introduce a docket file
Simon Sapin <simon.sapin@octobus.net>
parents: 47491
diff changeset
    65
}
ff97e793ed36 dirstate-v2: Introduce a docket file
Simon Sapin <simon.sapin@octobus.net>
parents: 47491
diff changeset
    66
48188
77fc340acad7 dirstate-v2: Document flags/mode/size/mtime fields of tree nodes
Simon Sapin <simon.sapin@octobus.net>
parents: 48166
diff changeset
    67
/// Fields are documented in the *Tree metadata in the docket file*
77fc340acad7 dirstate-v2: Document flags/mode/size/mtime fields of tree nodes
Simon Sapin <simon.sapin@octobus.net>
parents: 48166
diff changeset
    68
/// section of `mercurial/helptext/internals/dirstate-v2.txt`
47283
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
    69
#[derive(BytesCast)]
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
    70
#[repr(C)]
47682
78f7f0d490ee dirstate-v2: Move fixed-size tree metadata into the docket file
Simon Sapin <simon.sapin@octobus.net>
parents: 47681
diff changeset
    71
struct TreeMetadata {
47676
096ee2e260a3 dirstate-v2: Rename Header to Root, move it to the end of the data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47675
diff changeset
    72
    root_nodes: ChildNodes,
47283
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
    73
    nodes_with_entry_count: Size,
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
    74
    nodes_with_copy_source_count: Size,
47681
d94118365ec5 dirstate-v2: Add heuristic for when to create a new data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47680
diff changeset
    75
    unreachable_bytes: Size,
47684
852262e2e7d9 dirstate-v2: Reserve a few bytes of space for future extensions
Simon Sapin <simon.sapin@octobus.net>
parents: 47682
diff changeset
    76
    unused: [u8; 4],
852262e2e7d9 dirstate-v2: Reserve a few bytes of space for future extensions
Simon Sapin <simon.sapin@octobus.net>
parents: 47682
diff changeset
    77
48188
77fc340acad7 dirstate-v2: Document flags/mode/size/mtime fields of tree nodes
Simon Sapin <simon.sapin@octobus.net>
parents: 48166
diff changeset
    78
    /// See *Optional hash of ignore patterns* section of
77fc340acad7 dirstate-v2: Document flags/mode/size/mtime fields of tree nodes
Simon Sapin <simon.sapin@octobus.net>
parents: 48166
diff changeset
    79
    /// `mercurial/helptext/internals/dirstate-v2.txt`
47409
0ef8231e413f dirstate-v2: Store a hash of ignore patterns (.hgignore)
Simon Sapin <simon.sapin@octobus.net>
parents: 47374
diff changeset
    80
    ignore_patterns_hash: IgnorePatternsHash,
47283
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
    81
}
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
    82
48188
77fc340acad7 dirstate-v2: Document flags/mode/size/mtime fields of tree nodes
Simon Sapin <simon.sapin@octobus.net>
parents: 48166
diff changeset
    83
/// Fields are documented in the *The data file format*
77fc340acad7 dirstate-v2: Document flags/mode/size/mtime fields of tree nodes
Simon Sapin <simon.sapin@octobus.net>
parents: 48166
diff changeset
    84
/// section of `mercurial/helptext/internals/dirstate-v2.txt`
47283
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
    85
#[derive(BytesCast)]
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
    86
#[repr(C)]
47337
0654b3b3d2b5 dirstate-v2: Parse the dirstate lazily, with copy-on-write nodes
Simon Sapin <simon.sapin@octobus.net>
parents: 47336
diff changeset
    87
pub(super) struct Node {
47283
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
    88
    full_path: PathSlice,
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
    89
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
    90
    /// In bytes from `self.full_path.start`
47677
da1c0cd68d53 dirstate-v2: shrink on-disk path lengths to 16-bits
Simon Sapin <simon.sapin@octobus.net>
parents: 47676
diff changeset
    91
    base_name_start: PathSize,
47283
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
    92
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
    93
    copy_source: OptPathSlice,
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
    94
    children: ChildNodes,
47478
ca8121d26732 dirstate-tree: Keep a counter of descendant nodes that have an entry
Simon Sapin <simon.sapin@octobus.net>
parents: 47476
diff changeset
    95
    pub(super) descendants_with_entry_count: Size,
47337
0654b3b3d2b5 dirstate-v2: Parse the dirstate lazily, with copy-on-write nodes
Simon Sapin <simon.sapin@octobus.net>
parents: 47336
diff changeset
    96
    pub(super) tracked_descendants_count: Size,
48231
0524c1359bfc dirstate-v2: Extend node flags to 16 bits
Simon Sapin <simon.sapin@octobus.net>
parents: 48221
diff changeset
    97
    flags: U16Be,
48219
308d9c245337 dirstate-v2: Add storage space for nanoseconds precision in file mtimes
Simon Sapin <simon.sapin@octobus.net>
parents: 48196
diff changeset
    98
    size: U32Be,
308d9c245337 dirstate-v2: Add storage space for nanoseconds precision in file mtimes
Simon Sapin <simon.sapin@octobus.net>
parents: 48196
diff changeset
    99
    mtime: PackedTruncatedTimestamp,
47283
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
   100
}
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
   101
48139
ab5a7fdbf75c dirstate-v2: Store a bitfield on disk instead of v1-like state
Simon Sapin <simon.sapin@octobus.net>
parents: 48022
diff changeset
   102
bitflags! {
ab5a7fdbf75c dirstate-v2: Store a bitfield on disk instead of v1-like state
Simon Sapin <simon.sapin@octobus.net>
parents: 48022
diff changeset
   103
    #[repr(C)]
48231
0524c1359bfc dirstate-v2: Extend node flags to 16 bits
Simon Sapin <simon.sapin@octobus.net>
parents: 48221
diff changeset
   104
    struct Flags: u16 {
48139
ab5a7fdbf75c dirstate-v2: Store a bitfield on disk instead of v1-like state
Simon Sapin <simon.sapin@octobus.net>
parents: 48022
diff changeset
   105
        const WDIR_TRACKED = 1 << 0;
ab5a7fdbf75c dirstate-v2: Store a bitfield on disk instead of v1-like state
Simon Sapin <simon.sapin@octobus.net>
parents: 48022
diff changeset
   106
        const P1_TRACKED = 1 << 1;
ab5a7fdbf75c dirstate-v2: Store a bitfield on disk instead of v1-like state
Simon Sapin <simon.sapin@octobus.net>
parents: 48022
diff changeset
   107
        const P2_INFO = 1 << 2;
ab5a7fdbf75c dirstate-v2: Store a bitfield on disk instead of v1-like state
Simon Sapin <simon.sapin@octobus.net>
parents: 48022
diff changeset
   108
        const HAS_MODE_AND_SIZE = 1 << 3;
48232
f7fd629ffb98 dirstate-v2: Separate HAS_FILE_MTIME and HAS_DIRECTORY_MTIME flags
Simon Sapin <simon.sapin@octobus.net>
parents: 48231
diff changeset
   109
        const HAS_FILE_MTIME = 1 << 4;
f7fd629ffb98 dirstate-v2: Separate HAS_FILE_MTIME and HAS_DIRECTORY_MTIME flags
Simon Sapin <simon.sapin@octobus.net>
parents: 48231
diff changeset
   110
        const HAS_DIRECTORY_MTIME = 1 << 5;
f7fd629ffb98 dirstate-v2: Separate HAS_FILE_MTIME and HAS_DIRECTORY_MTIME flags
Simon Sapin <simon.sapin@octobus.net>
parents: 48231
diff changeset
   111
        const MODE_EXEC_PERM = 1 << 6;
f7fd629ffb98 dirstate-v2: Separate HAS_FILE_MTIME and HAS_DIRECTORY_MTIME flags
Simon Sapin <simon.sapin@octobus.net>
parents: 48231
diff changeset
   112
        const MODE_IS_SYMLINK = 1 << 7;
48250
1730b2fceaa1 dirstate-v2: adds a flag to mark a file as modified
Simon Sapin <simon.sapin@octobus.net>
parents: 48232
diff changeset
   113
        const EXPECTED_STATE_IS_MODIFIED = 1 << 8;
48251
dfc5a505ddc5 dirstate-v2: adds two flag to track the presence of some unrecorded files
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48250
diff changeset
   114
        const ALL_UNKNOWN_RECORDED = 1 << 9;
dfc5a505ddc5 dirstate-v2: adds two flag to track the presence of some unrecorded files
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48250
diff changeset
   115
        const ALL_IGNORED_RECORDED = 1 << 10;
48139
ab5a7fdbf75c dirstate-v2: Store a bitfield on disk instead of v1-like state
Simon Sapin <simon.sapin@octobus.net>
parents: 48022
diff changeset
   116
    }
ab5a7fdbf75c dirstate-v2: Store a bitfield on disk instead of v1-like state
Simon Sapin <simon.sapin@octobus.net>
parents: 48022
diff changeset
   117
}
ab5a7fdbf75c dirstate-v2: Store a bitfield on disk instead of v1-like state
Simon Sapin <simon.sapin@octobus.net>
parents: 48022
diff changeset
   118
47348
a4de570e61fa dirstate-v2: Allow tree nodes without an entry to store a timestamp
Simon Sapin <simon.sapin@octobus.net>
parents: 47337
diff changeset
   119
/// Duration since the Unix epoch
48192
d2f760c2c91c dirstate-v2: Separate Rust structs for Timestamp and PackedTimestamp
Simon Sapin <simon.sapin@octobus.net>
parents: 48191
diff changeset
   120
#[derive(BytesCast, Copy, Clone)]
47348
a4de570e61fa dirstate-v2: Allow tree nodes without an entry to store a timestamp
Simon Sapin <simon.sapin@octobus.net>
parents: 47337
diff changeset
   121
#[repr(C)]
48219
308d9c245337 dirstate-v2: Add storage space for nanoseconds precision in file mtimes
Simon Sapin <simon.sapin@octobus.net>
parents: 48196
diff changeset
   122
struct PackedTruncatedTimestamp {
48193
320de901896a dirstate-v2: Truncate directory mtimes to 31 bits of seconds
Simon Sapin <simon.sapin@octobus.net>
parents: 48192
diff changeset
   123
    truncated_seconds: U32Be,
47348
a4de570e61fa dirstate-v2: Allow tree nodes without an entry to store a timestamp
Simon Sapin <simon.sapin@octobus.net>
parents: 47337
diff changeset
   124
    nanoseconds: U32Be,
a4de570e61fa dirstate-v2: Allow tree nodes without an entry to store a timestamp
Simon Sapin <simon.sapin@octobus.net>
parents: 47337
diff changeset
   125
}
a4de570e61fa dirstate-v2: Allow tree nodes without an entry to store a timestamp
Simon Sapin <simon.sapin@octobus.net>
parents: 47337
diff changeset
   126
47283
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
   127
/// Counted in bytes from the start of the file
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
   128
///
47476
f23eafb036af dirstate-v2: Use 32-bit integers instead of 64-bit for offsets
Simon Sapin <simon.sapin@octobus.net>
parents: 47475
diff changeset
   129
/// NOTE: not supporting `.hg/dirstate` files larger than 4 GiB.
f23eafb036af dirstate-v2: Use 32-bit integers instead of 64-bit for offsets
Simon Sapin <simon.sapin@octobus.net>
parents: 47475
diff changeset
   130
type Offset = U32Be;
47283
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
   131
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
   132
/// Counted in number of items
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
   133
///
47677
da1c0cd68d53 dirstate-v2: shrink on-disk path lengths to 16-bits
Simon Sapin <simon.sapin@octobus.net>
parents: 47676
diff changeset
   134
/// NOTE: we choose not to support counting more than 4 billion nodes anywhere.
47283
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
   135
type Size = U32Be;
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
   136
47677
da1c0cd68d53 dirstate-v2: shrink on-disk path lengths to 16-bits
Simon Sapin <simon.sapin@octobus.net>
parents: 47676
diff changeset
   137
/// Counted in bytes
47283
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
   138
///
47677
da1c0cd68d53 dirstate-v2: shrink on-disk path lengths to 16-bits
Simon Sapin <simon.sapin@octobus.net>
parents: 47676
diff changeset
   139
/// NOTE: we choose not to support file names/paths longer than 64 KiB.
da1c0cd68d53 dirstate-v2: shrink on-disk path lengths to 16-bits
Simon Sapin <simon.sapin@octobus.net>
parents: 47676
diff changeset
   140
type PathSize = U16Be;
47283
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
   141
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
   142
/// A contiguous sequence of `len` times `Node`, representing the child nodes
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
   143
/// of either some other node or of the repository root.
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
   144
///
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
   145
/// Always sorted by ascending `full_path`, to allow binary search.
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
   146
/// Since nodes with the same parent nodes also have the same parent path,
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
   147
/// only the `base_name`s need to be compared during binary search.
47677
da1c0cd68d53 dirstate-v2: shrink on-disk path lengths to 16-bits
Simon Sapin <simon.sapin@octobus.net>
parents: 47676
diff changeset
   148
#[derive(BytesCast, Copy, Clone)]
da1c0cd68d53 dirstate-v2: shrink on-disk path lengths to 16-bits
Simon Sapin <simon.sapin@octobus.net>
parents: 47676
diff changeset
   149
#[repr(C)]
da1c0cd68d53 dirstate-v2: shrink on-disk path lengths to 16-bits
Simon Sapin <simon.sapin@octobus.net>
parents: 47676
diff changeset
   150
struct ChildNodes {
da1c0cd68d53 dirstate-v2: shrink on-disk path lengths to 16-bits
Simon Sapin <simon.sapin@octobus.net>
parents: 47676
diff changeset
   151
    start: Offset,
da1c0cd68d53 dirstate-v2: shrink on-disk path lengths to 16-bits
Simon Sapin <simon.sapin@octobus.net>
parents: 47676
diff changeset
   152
    len: Size,
da1c0cd68d53 dirstate-v2: shrink on-disk path lengths to 16-bits
Simon Sapin <simon.sapin@octobus.net>
parents: 47676
diff changeset
   153
}
47283
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
   154
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
   155
/// A `HgPath` of `len` bytes
47677
da1c0cd68d53 dirstate-v2: shrink on-disk path lengths to 16-bits
Simon Sapin <simon.sapin@octobus.net>
parents: 47676
diff changeset
   156
#[derive(BytesCast, Copy, Clone)]
da1c0cd68d53 dirstate-v2: shrink on-disk path lengths to 16-bits
Simon Sapin <simon.sapin@octobus.net>
parents: 47676
diff changeset
   157
#[repr(C)]
da1c0cd68d53 dirstate-v2: shrink on-disk path lengths to 16-bits
Simon Sapin <simon.sapin@octobus.net>
parents: 47676
diff changeset
   158
struct PathSlice {
da1c0cd68d53 dirstate-v2: shrink on-disk path lengths to 16-bits
Simon Sapin <simon.sapin@octobus.net>
parents: 47676
diff changeset
   159
    start: Offset,
da1c0cd68d53 dirstate-v2: shrink on-disk path lengths to 16-bits
Simon Sapin <simon.sapin@octobus.net>
parents: 47676
diff changeset
   160
    len: PathSize,
da1c0cd68d53 dirstate-v2: shrink on-disk path lengths to 16-bits
Simon Sapin <simon.sapin@octobus.net>
parents: 47676
diff changeset
   161
}
47283
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
   162
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
   163
/// Either nothing if `start == 0`, or a `HgPath` of `len` bytes
47677
da1c0cd68d53 dirstate-v2: shrink on-disk path lengths to 16-bits
Simon Sapin <simon.sapin@octobus.net>
parents: 47676
diff changeset
   164
type OptPathSlice = PathSlice;
47283
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
   165
47334
18b3060fe598 dirstate-v2: Add a zero-size error type for dirstate v2 parse errors
Simon Sapin <simon.sapin@octobus.net>
parents: 47333
diff changeset
   166
/// Unexpected file format found in `.hg/dirstate` with the "v2" format.
47335
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47334
diff changeset
   167
///
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47334
diff changeset
   168
/// This should only happen if Mercurial is buggy or a repository is corrupted.
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47334
diff changeset
   169
#[derive(Debug)]
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47334
diff changeset
   170
pub struct DirstateV2ParseError;
47334
18b3060fe598 dirstate-v2: Add a zero-size error type for dirstate v2 parse errors
Simon Sapin <simon.sapin@octobus.net>
parents: 47333
diff changeset
   171
18b3060fe598 dirstate-v2: Add a zero-size error type for dirstate v2 parse errors
Simon Sapin <simon.sapin@octobus.net>
parents: 47333
diff changeset
   172
impl From<DirstateV2ParseError> for HgError {
18b3060fe598 dirstate-v2: Add a zero-size error type for dirstate v2 parse errors
Simon Sapin <simon.sapin@octobus.net>
parents: 47333
diff changeset
   173
    fn from(_: DirstateV2ParseError) -> Self {
18b3060fe598 dirstate-v2: Add a zero-size error type for dirstate v2 parse errors
Simon Sapin <simon.sapin@octobus.net>
parents: 47333
diff changeset
   174
        HgError::corrupted("dirstate-v2 parse error")
18b3060fe598 dirstate-v2: Add a zero-size error type for dirstate v2 parse errors
Simon Sapin <simon.sapin@octobus.net>
parents: 47333
diff changeset
   175
    }
18b3060fe598 dirstate-v2: Add a zero-size error type for dirstate v2 parse errors
Simon Sapin <simon.sapin@octobus.net>
parents: 47333
diff changeset
   176
}
18b3060fe598 dirstate-v2: Add a zero-size error type for dirstate v2 parse errors
Simon Sapin <simon.sapin@octobus.net>
parents: 47333
diff changeset
   177
18b3060fe598 dirstate-v2: Add a zero-size error type for dirstate v2 parse errors
Simon Sapin <simon.sapin@octobus.net>
parents: 47333
diff changeset
   178
impl From<DirstateV2ParseError> for crate::DirstateError {
18b3060fe598 dirstate-v2: Add a zero-size error type for dirstate v2 parse errors
Simon Sapin <simon.sapin@octobus.net>
parents: 47333
diff changeset
   179
    fn from(error: DirstateV2ParseError) -> Self {
18b3060fe598 dirstate-v2: Add a zero-size error type for dirstate v2 parse errors
Simon Sapin <simon.sapin@octobus.net>
parents: 47333
diff changeset
   180
        HgError::from(error).into()
18b3060fe598 dirstate-v2: Add a zero-size error type for dirstate v2 parse errors
Simon Sapin <simon.sapin@octobus.net>
parents: 47333
diff changeset
   181
    }
18b3060fe598 dirstate-v2: Add a zero-size error type for dirstate v2 parse errors
Simon Sapin <simon.sapin@octobus.net>
parents: 47333
diff changeset
   182
}
18b3060fe598 dirstate-v2: Add a zero-size error type for dirstate v2 parse errors
Simon Sapin <simon.sapin@octobus.net>
parents: 47333
diff changeset
   183
47674
ff97e793ed36 dirstate-v2: Introduce a docket file
Simon Sapin <simon.sapin@octobus.net>
parents: 47491
diff changeset
   184
impl<'on_disk> Docket<'on_disk> {
ff97e793ed36 dirstate-v2: Introduce a docket file
Simon Sapin <simon.sapin@octobus.net>
parents: 47491
diff changeset
   185
    pub fn parents(&self) -> DirstateParents {
ff97e793ed36 dirstate-v2: Introduce a docket file
Simon Sapin <simon.sapin@octobus.net>
parents: 47491
diff changeset
   186
        use crate::Node;
ff97e793ed36 dirstate-v2: Introduce a docket file
Simon Sapin <simon.sapin@octobus.net>
parents: 47491
diff changeset
   187
        let p1 = Node::try_from(&self.header.parent_1[..USED_NODE_ID_BYTES])
ff97e793ed36 dirstate-v2: Introduce a docket file
Simon Sapin <simon.sapin@octobus.net>
parents: 47491
diff changeset
   188
            .unwrap()
ff97e793ed36 dirstate-v2: Introduce a docket file
Simon Sapin <simon.sapin@octobus.net>
parents: 47491
diff changeset
   189
            .clone();
ff97e793ed36 dirstate-v2: Introduce a docket file
Simon Sapin <simon.sapin@octobus.net>
parents: 47491
diff changeset
   190
        let p2 = Node::try_from(&self.header.parent_2[..USED_NODE_ID_BYTES])
ff97e793ed36 dirstate-v2: Introduce a docket file
Simon Sapin <simon.sapin@octobus.net>
parents: 47491
diff changeset
   191
            .unwrap()
ff97e793ed36 dirstate-v2: Introduce a docket file
Simon Sapin <simon.sapin@octobus.net>
parents: 47491
diff changeset
   192
            .clone();
ff97e793ed36 dirstate-v2: Introduce a docket file
Simon Sapin <simon.sapin@octobus.net>
parents: 47491
diff changeset
   193
        DirstateParents { p1, p2 }
ff97e793ed36 dirstate-v2: Introduce a docket file
Simon Sapin <simon.sapin@octobus.net>
parents: 47491
diff changeset
   194
    }
ff97e793ed36 dirstate-v2: Introduce a docket file
Simon Sapin <simon.sapin@octobus.net>
parents: 47491
diff changeset
   195
47682
78f7f0d490ee dirstate-v2: Move fixed-size tree metadata into the docket file
Simon Sapin <simon.sapin@octobus.net>
parents: 47681
diff changeset
   196
    pub fn tree_metadata(&self) -> &[u8] {
78f7f0d490ee dirstate-v2: Move fixed-size tree metadata into the docket file
Simon Sapin <simon.sapin@octobus.net>
parents: 47681
diff changeset
   197
        self.header.metadata.as_bytes()
78f7f0d490ee dirstate-v2: Move fixed-size tree metadata into the docket file
Simon Sapin <simon.sapin@octobus.net>
parents: 47681
diff changeset
   198
    }
78f7f0d490ee dirstate-v2: Move fixed-size tree metadata into the docket file
Simon Sapin <simon.sapin@octobus.net>
parents: 47681
diff changeset
   199
47675
48aec076b8fb dirstate-v2: Enforce data size read from the docket file
Simon Sapin <simon.sapin@octobus.net>
parents: 47674
diff changeset
   200
    pub fn data_size(&self) -> usize {
48aec076b8fb dirstate-v2: Enforce data size read from the docket file
Simon Sapin <simon.sapin@octobus.net>
parents: 47674
diff changeset
   201
        // This `unwrap` could only panic on a 16-bit CPU
48aec076b8fb dirstate-v2: Enforce data size read from the docket file
Simon Sapin <simon.sapin@octobus.net>
parents: 47674
diff changeset
   202
        self.header.data_size.get().try_into().unwrap()
48aec076b8fb dirstate-v2: Enforce data size read from the docket file
Simon Sapin <simon.sapin@octobus.net>
parents: 47674
diff changeset
   203
    }
48aec076b8fb dirstate-v2: Enforce data size read from the docket file
Simon Sapin <simon.sapin@octobus.net>
parents: 47674
diff changeset
   204
47674
ff97e793ed36 dirstate-v2: Introduce a docket file
Simon Sapin <simon.sapin@octobus.net>
parents: 47491
diff changeset
   205
    pub fn data_filename(&self) -> String {
47966
681851d6409b dirstate-v2: Remove the `.d` suffix in data file names
Simon Sapin <simon.sapin@octobus.net>
parents: 47684
diff changeset
   206
        String::from_utf8(format_bytes!(b"dirstate.{}", self.uuid)).unwrap()
47674
ff97e793ed36 dirstate-v2: Introduce a docket file
Simon Sapin <simon.sapin@octobus.net>
parents: 47491
diff changeset
   207
    }
ff97e793ed36 dirstate-v2: Introduce a docket file
Simon Sapin <simon.sapin@octobus.net>
parents: 47491
diff changeset
   208
}
ff97e793ed36 dirstate-v2: Introduce a docket file
Simon Sapin <simon.sapin@octobus.net>
parents: 47491
diff changeset
   209
ff97e793ed36 dirstate-v2: Introduce a docket file
Simon Sapin <simon.sapin@octobus.net>
parents: 47491
diff changeset
   210
pub fn read_docket(
ff97e793ed36 dirstate-v2: Introduce a docket file
Simon Sapin <simon.sapin@octobus.net>
parents: 47491
diff changeset
   211
    on_disk: &[u8],
ff97e793ed36 dirstate-v2: Introduce a docket file
Simon Sapin <simon.sapin@octobus.net>
parents: 47491
diff changeset
   212
) -> Result<Docket<'_>, DirstateV2ParseError> {
ff97e793ed36 dirstate-v2: Introduce a docket file
Simon Sapin <simon.sapin@octobus.net>
parents: 47491
diff changeset
   213
    let (header, uuid) =
ff97e793ed36 dirstate-v2: Introduce a docket file
Simon Sapin <simon.sapin@octobus.net>
parents: 47491
diff changeset
   214
        DocketHeader::from_bytes(on_disk).map_err(|_| DirstateV2ParseError)?;
ff97e793ed36 dirstate-v2: Introduce a docket file
Simon Sapin <simon.sapin@octobus.net>
parents: 47491
diff changeset
   215
    let uuid_size = header.uuid_size as usize;
ff97e793ed36 dirstate-v2: Introduce a docket file
Simon Sapin <simon.sapin@octobus.net>
parents: 47491
diff changeset
   216
    if header.marker == *V2_FORMAT_MARKER && uuid.len() == uuid_size {
ff97e793ed36 dirstate-v2: Introduce a docket file
Simon Sapin <simon.sapin@octobus.net>
parents: 47491
diff changeset
   217
        Ok(Docket { header, uuid })
47374
bd88b6bfd8da rhg: Add support for dirstate-v2
Simon Sapin <simon.sapin@octobus.net>
parents: 47351
diff changeset
   218
    } else {
bd88b6bfd8da rhg: Add support for dirstate-v2
Simon Sapin <simon.sapin@octobus.net>
parents: 47351
diff changeset
   219
        Err(DirstateV2ParseError)
bd88b6bfd8da rhg: Add support for dirstate-v2
Simon Sapin <simon.sapin@octobus.net>
parents: 47351
diff changeset
   220
    }
bd88b6bfd8da rhg: Add support for dirstate-v2
Simon Sapin <simon.sapin@octobus.net>
parents: 47351
diff changeset
   221
}
bd88b6bfd8da rhg: Add support for dirstate-v2
Simon Sapin <simon.sapin@octobus.net>
parents: 47351
diff changeset
   222
47283
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
   223
pub(super) fn read<'on_disk>(
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
   224
    on_disk: &'on_disk [u8],
47682
78f7f0d490ee dirstate-v2: Move fixed-size tree metadata into the docket file
Simon Sapin <simon.sapin@octobus.net>
parents: 47681
diff changeset
   225
    metadata: &[u8],
47674
ff97e793ed36 dirstate-v2: Introduce a docket file
Simon Sapin <simon.sapin@octobus.net>
parents: 47491
diff changeset
   226
) -> Result<DirstateMap<'on_disk>, DirstateV2ParseError> {
47283
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
   227
    if on_disk.is_empty() {
47674
ff97e793ed36 dirstate-v2: Introduce a docket file
Simon Sapin <simon.sapin@octobus.net>
parents: 47491
diff changeset
   228
        return Ok(DirstateMap::empty(on_disk));
47283
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
   229
    }
47682
78f7f0d490ee dirstate-v2: Move fixed-size tree metadata into the docket file
Simon Sapin <simon.sapin@octobus.net>
parents: 47681
diff changeset
   230
    let (meta, _) = TreeMetadata::from_bytes(metadata)
78f7f0d490ee dirstate-v2: Move fixed-size tree metadata into the docket file
Simon Sapin <simon.sapin@octobus.net>
parents: 47681
diff changeset
   231
        .map_err(|_| DirstateV2ParseError)?;
47283
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
   232
    let dirstate_map = DirstateMap {
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
   233
        on_disk,
47677
da1c0cd68d53 dirstate-v2: shrink on-disk path lengths to 16-bits
Simon Sapin <simon.sapin@octobus.net>
parents: 47676
diff changeset
   234
        root: dirstate_map::ChildNodes::OnDisk(read_nodes(
47374
bd88b6bfd8da rhg: Add support for dirstate-v2
Simon Sapin <simon.sapin@octobus.net>
parents: 47351
diff changeset
   235
            on_disk,
47682
78f7f0d490ee dirstate-v2: Move fixed-size tree metadata into the docket file
Simon Sapin <simon.sapin@octobus.net>
parents: 47681
diff changeset
   236
            meta.root_nodes,
47337
0654b3b3d2b5 dirstate-v2: Parse the dirstate lazily, with copy-on-write nodes
Simon Sapin <simon.sapin@octobus.net>
parents: 47336
diff changeset
   237
        )?),
47682
78f7f0d490ee dirstate-v2: Move fixed-size tree metadata into the docket file
Simon Sapin <simon.sapin@octobus.net>
parents: 47681
diff changeset
   238
        nodes_with_entry_count: meta.nodes_with_entry_count.get(),
78f7f0d490ee dirstate-v2: Move fixed-size tree metadata into the docket file
Simon Sapin <simon.sapin@octobus.net>
parents: 47681
diff changeset
   239
        nodes_with_copy_source_count: meta.nodes_with_copy_source_count.get(),
78f7f0d490ee dirstate-v2: Move fixed-size tree metadata into the docket file
Simon Sapin <simon.sapin@octobus.net>
parents: 47681
diff changeset
   240
        ignore_patterns_hash: meta.ignore_patterns_hash,
78f7f0d490ee dirstate-v2: Move fixed-size tree metadata into the docket file
Simon Sapin <simon.sapin@octobus.net>
parents: 47681
diff changeset
   241
        unreachable_bytes: meta.unreachable_bytes.get(),
47283
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
   242
    };
47674
ff97e793ed36 dirstate-v2: Introduce a docket file
Simon Sapin <simon.sapin@octobus.net>
parents: 47491
diff changeset
   243
    Ok(dirstate_map)
47283
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
   244
}
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
   245
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
   246
impl Node {
47337
0654b3b3d2b5 dirstate-v2: Parse the dirstate lazily, with copy-on-write nodes
Simon Sapin <simon.sapin@octobus.net>
parents: 47336
diff changeset
   247
    pub(super) fn full_path<'on_disk>(
47283
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
   248
        &self,
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
   249
        on_disk: &'on_disk [u8],
47337
0654b3b3d2b5 dirstate-v2: Parse the dirstate lazily, with copy-on-write nodes
Simon Sapin <simon.sapin@octobus.net>
parents: 47336
diff changeset
   250
    ) -> Result<&'on_disk HgPath, DirstateV2ParseError> {
0654b3b3d2b5 dirstate-v2: Parse the dirstate lazily, with copy-on-write nodes
Simon Sapin <simon.sapin@octobus.net>
parents: 47336
diff changeset
   251
        read_hg_path(on_disk, self.full_path)
0654b3b3d2b5 dirstate-v2: Parse the dirstate lazily, with copy-on-write nodes
Simon Sapin <simon.sapin@octobus.net>
parents: 47336
diff changeset
   252
    }
0654b3b3d2b5 dirstate-v2: Parse the dirstate lazily, with copy-on-write nodes
Simon Sapin <simon.sapin@octobus.net>
parents: 47336
diff changeset
   253
0654b3b3d2b5 dirstate-v2: Parse the dirstate lazily, with copy-on-write nodes
Simon Sapin <simon.sapin@octobus.net>
parents: 47336
diff changeset
   254
    pub(super) fn base_name_start<'on_disk>(
0654b3b3d2b5 dirstate-v2: Parse the dirstate lazily, with copy-on-write nodes
Simon Sapin <simon.sapin@octobus.net>
parents: 47336
diff changeset
   255
        &self,
0654b3b3d2b5 dirstate-v2: Parse the dirstate lazily, with copy-on-write nodes
Simon Sapin <simon.sapin@octobus.net>
parents: 47336
diff changeset
   256
    ) -> Result<usize, DirstateV2ParseError> {
0654b3b3d2b5 dirstate-v2: Parse the dirstate lazily, with copy-on-write nodes
Simon Sapin <simon.sapin@octobus.net>
parents: 47336
diff changeset
   257
        let start = self.base_name_start.get();
0654b3b3d2b5 dirstate-v2: Parse the dirstate lazily, with copy-on-write nodes
Simon Sapin <simon.sapin@octobus.net>
parents: 47336
diff changeset
   258
        if start < self.full_path.len.get() {
0654b3b3d2b5 dirstate-v2: Parse the dirstate lazily, with copy-on-write nodes
Simon Sapin <simon.sapin@octobus.net>
parents: 47336
diff changeset
   259
            let start = usize::try_from(start)
0654b3b3d2b5 dirstate-v2: Parse the dirstate lazily, with copy-on-write nodes
Simon Sapin <simon.sapin@octobus.net>
parents: 47336
diff changeset
   260
                // u32 -> usize, could only panic on a 16-bit CPU
0654b3b3d2b5 dirstate-v2: Parse the dirstate lazily, with copy-on-write nodes
Simon Sapin <simon.sapin@octobus.net>
parents: 47336
diff changeset
   261
                .expect("dirstate-v2 base_name_start out of bounds");
0654b3b3d2b5 dirstate-v2: Parse the dirstate lazily, with copy-on-write nodes
Simon Sapin <simon.sapin@octobus.net>
parents: 47336
diff changeset
   262
            Ok(start)
47283
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
   263
        } else {
47334
18b3060fe598 dirstate-v2: Add a zero-size error type for dirstate v2 parse errors
Simon Sapin <simon.sapin@octobus.net>
parents: 47333
diff changeset
   264
            Err(DirstateV2ParseError)
47283
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
   265
        }
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
   266
    }
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
   267
47337
0654b3b3d2b5 dirstate-v2: Parse the dirstate lazily, with copy-on-write nodes
Simon Sapin <simon.sapin@octobus.net>
parents: 47336
diff changeset
   268
    pub(super) fn base_name<'on_disk>(
0654b3b3d2b5 dirstate-v2: Parse the dirstate lazily, with copy-on-write nodes
Simon Sapin <simon.sapin@octobus.net>
parents: 47336
diff changeset
   269
        &self,
0654b3b3d2b5 dirstate-v2: Parse the dirstate lazily, with copy-on-write nodes
Simon Sapin <simon.sapin@octobus.net>
parents: 47336
diff changeset
   270
        on_disk: &'on_disk [u8],
0654b3b3d2b5 dirstate-v2: Parse the dirstate lazily, with copy-on-write nodes
Simon Sapin <simon.sapin@octobus.net>
parents: 47336
diff changeset
   271
    ) -> Result<&'on_disk HgPath, DirstateV2ParseError> {
0654b3b3d2b5 dirstate-v2: Parse the dirstate lazily, with copy-on-write nodes
Simon Sapin <simon.sapin@octobus.net>
parents: 47336
diff changeset
   272
        let full_path = self.full_path(on_disk)?;
0654b3b3d2b5 dirstate-v2: Parse the dirstate lazily, with copy-on-write nodes
Simon Sapin <simon.sapin@octobus.net>
parents: 47336
diff changeset
   273
        let base_name_start = self.base_name_start()?;
0654b3b3d2b5 dirstate-v2: Parse the dirstate lazily, with copy-on-write nodes
Simon Sapin <simon.sapin@octobus.net>
parents: 47336
diff changeset
   274
        Ok(HgPath::new(&full_path.as_bytes()[base_name_start..]))
0654b3b3d2b5 dirstate-v2: Parse the dirstate lazily, with copy-on-write nodes
Simon Sapin <simon.sapin@octobus.net>
parents: 47336
diff changeset
   275
    }
0654b3b3d2b5 dirstate-v2: Parse the dirstate lazily, with copy-on-write nodes
Simon Sapin <simon.sapin@octobus.net>
parents: 47336
diff changeset
   276
0654b3b3d2b5 dirstate-v2: Parse the dirstate lazily, with copy-on-write nodes
Simon Sapin <simon.sapin@octobus.net>
parents: 47336
diff changeset
   277
    pub(super) fn path<'on_disk>(
0654b3b3d2b5 dirstate-v2: Parse the dirstate lazily, with copy-on-write nodes
Simon Sapin <simon.sapin@octobus.net>
parents: 47336
diff changeset
   278
        &self,
0654b3b3d2b5 dirstate-v2: Parse the dirstate lazily, with copy-on-write nodes
Simon Sapin <simon.sapin@octobus.net>
parents: 47336
diff changeset
   279
        on_disk: &'on_disk [u8],
0654b3b3d2b5 dirstate-v2: Parse the dirstate lazily, with copy-on-write nodes
Simon Sapin <simon.sapin@octobus.net>
parents: 47336
diff changeset
   280
    ) -> Result<dirstate_map::NodeKey<'on_disk>, DirstateV2ParseError> {
0654b3b3d2b5 dirstate-v2: Parse the dirstate lazily, with copy-on-write nodes
Simon Sapin <simon.sapin@octobus.net>
parents: 47336
diff changeset
   281
        Ok(WithBasename::from_raw_parts(
0654b3b3d2b5 dirstate-v2: Parse the dirstate lazily, with copy-on-write nodes
Simon Sapin <simon.sapin@octobus.net>
parents: 47336
diff changeset
   282
            Cow::Borrowed(self.full_path(on_disk)?),
0654b3b3d2b5 dirstate-v2: Parse the dirstate lazily, with copy-on-write nodes
Simon Sapin <simon.sapin@octobus.net>
parents: 47336
diff changeset
   283
            self.base_name_start()?,
0654b3b3d2b5 dirstate-v2: Parse the dirstate lazily, with copy-on-write nodes
Simon Sapin <simon.sapin@octobus.net>
parents: 47336
diff changeset
   284
        ))
0654b3b3d2b5 dirstate-v2: Parse the dirstate lazily, with copy-on-write nodes
Simon Sapin <simon.sapin@octobus.net>
parents: 47336
diff changeset
   285
    }
0654b3b3d2b5 dirstate-v2: Parse the dirstate lazily, with copy-on-write nodes
Simon Sapin <simon.sapin@octobus.net>
parents: 47336
diff changeset
   286
0654b3b3d2b5 dirstate-v2: Parse the dirstate lazily, with copy-on-write nodes
Simon Sapin <simon.sapin@octobus.net>
parents: 47336
diff changeset
   287
    pub(super) fn has_copy_source<'on_disk>(&self) -> bool {
0654b3b3d2b5 dirstate-v2: Parse the dirstate lazily, with copy-on-write nodes
Simon Sapin <simon.sapin@octobus.net>
parents: 47336
diff changeset
   288
        self.copy_source.start.get() != 0
0654b3b3d2b5 dirstate-v2: Parse the dirstate lazily, with copy-on-write nodes
Simon Sapin <simon.sapin@octobus.net>
parents: 47336
diff changeset
   289
    }
0654b3b3d2b5 dirstate-v2: Parse the dirstate lazily, with copy-on-write nodes
Simon Sapin <simon.sapin@octobus.net>
parents: 47336
diff changeset
   290
47283
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
   291
    pub(super) fn copy_source<'on_disk>(
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
   292
        &self,
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
   293
        on_disk: &'on_disk [u8],
47337
0654b3b3d2b5 dirstate-v2: Parse the dirstate lazily, with copy-on-write nodes
Simon Sapin <simon.sapin@octobus.net>
parents: 47336
diff changeset
   294
    ) -> Result<Option<&'on_disk HgPath>, DirstateV2ParseError> {
0654b3b3d2b5 dirstate-v2: Parse the dirstate lazily, with copy-on-write nodes
Simon Sapin <simon.sapin@octobus.net>
parents: 47336
diff changeset
   295
        Ok(if self.has_copy_source() {
47283
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
   296
            Some(read_hg_path(on_disk, self.copy_source)?)
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
   297
        } else {
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
   298
            None
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
   299
        })
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
   300
    }
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
   301
48231
0524c1359bfc dirstate-v2: Extend node flags to 16 bits
Simon Sapin <simon.sapin@octobus.net>
parents: 48221
diff changeset
   302
    fn flags(&self) -> Flags {
0524c1359bfc dirstate-v2: Extend node flags to 16 bits
Simon Sapin <simon.sapin@octobus.net>
parents: 48221
diff changeset
   303
        Flags::from_bits_truncate(self.flags.get())
0524c1359bfc dirstate-v2: Extend node flags to 16 bits
Simon Sapin <simon.sapin@octobus.net>
parents: 48221
diff changeset
   304
    }
0524c1359bfc dirstate-v2: Extend node flags to 16 bits
Simon Sapin <simon.sapin@octobus.net>
parents: 48221
diff changeset
   305
48139
ab5a7fdbf75c dirstate-v2: Store a bitfield on disk instead of v1-like state
Simon Sapin <simon.sapin@octobus.net>
parents: 48022
diff changeset
   306
    fn has_entry(&self) -> bool {
48231
0524c1359bfc dirstate-v2: Extend node flags to 16 bits
Simon Sapin <simon.sapin@octobus.net>
parents: 48221
diff changeset
   307
        self.flags().intersects(
48139
ab5a7fdbf75c dirstate-v2: Store a bitfield on disk instead of v1-like state
Simon Sapin <simon.sapin@octobus.net>
parents: 48022
diff changeset
   308
            Flags::WDIR_TRACKED | Flags::P1_TRACKED | Flags::P2_INFO,
ab5a7fdbf75c dirstate-v2: Store a bitfield on disk instead of v1-like state
Simon Sapin <simon.sapin@octobus.net>
parents: 48022
diff changeset
   309
        )
ab5a7fdbf75c dirstate-v2: Store a bitfield on disk instead of v1-like state
Simon Sapin <simon.sapin@octobus.net>
parents: 48022
diff changeset
   310
    }
ab5a7fdbf75c dirstate-v2: Store a bitfield on disk instead of v1-like state
Simon Sapin <simon.sapin@octobus.net>
parents: 48022
diff changeset
   311
47348
a4de570e61fa dirstate-v2: Allow tree nodes without an entry to store a timestamp
Simon Sapin <simon.sapin@octobus.net>
parents: 47337
diff changeset
   312
    pub(super) fn node_data(
a4de570e61fa dirstate-v2: Allow tree nodes without an entry to store a timestamp
Simon Sapin <simon.sapin@octobus.net>
parents: 47337
diff changeset
   313
        &self,
a4de570e61fa dirstate-v2: Allow tree nodes without an entry to store a timestamp
Simon Sapin <simon.sapin@octobus.net>
parents: 47337
diff changeset
   314
    ) -> Result<dirstate_map::NodeData, DirstateV2ParseError> {
48139
ab5a7fdbf75c dirstate-v2: Store a bitfield on disk instead of v1-like state
Simon Sapin <simon.sapin@octobus.net>
parents: 48022
diff changeset
   315
        if self.has_entry() {
ab5a7fdbf75c dirstate-v2: Store a bitfield on disk instead of v1-like state
Simon Sapin <simon.sapin@octobus.net>
parents: 48022
diff changeset
   316
            Ok(dirstate_map::NodeData::Entry(self.assume_entry()))
48193
320de901896a dirstate-v2: Truncate directory mtimes to 31 bits of seconds
Simon Sapin <simon.sapin@octobus.net>
parents: 48192
diff changeset
   317
        } else if let Some(mtime) = self.cached_directory_mtime()? {
48139
ab5a7fdbf75c dirstate-v2: Store a bitfield on disk instead of v1-like state
Simon Sapin <simon.sapin@octobus.net>
parents: 48022
diff changeset
   318
            Ok(dirstate_map::NodeData::CachedDirectory { mtime })
ab5a7fdbf75c dirstate-v2: Store a bitfield on disk instead of v1-like state
Simon Sapin <simon.sapin@octobus.net>
parents: 48022
diff changeset
   319
        } else {
ab5a7fdbf75c dirstate-v2: Store a bitfield on disk instead of v1-like state
Simon Sapin <simon.sapin@octobus.net>
parents: 48022
diff changeset
   320
            Ok(dirstate_map::NodeData::None)
47348
a4de570e61fa dirstate-v2: Allow tree nodes without an entry to store a timestamp
Simon Sapin <simon.sapin@octobus.net>
parents: 47337
diff changeset
   321
        }
47337
0654b3b3d2b5 dirstate-v2: Parse the dirstate lazily, with copy-on-write nodes
Simon Sapin <simon.sapin@octobus.net>
parents: 47336
diff changeset
   322
    }
0654b3b3d2b5 dirstate-v2: Parse the dirstate lazily, with copy-on-write nodes
Simon Sapin <simon.sapin@octobus.net>
parents: 47336
diff changeset
   323
48193
320de901896a dirstate-v2: Truncate directory mtimes to 31 bits of seconds
Simon Sapin <simon.sapin@octobus.net>
parents: 48192
diff changeset
   324
    pub(super) fn cached_directory_mtime(
320de901896a dirstate-v2: Truncate directory mtimes to 31 bits of seconds
Simon Sapin <simon.sapin@octobus.net>
parents: 48192
diff changeset
   325
        &self,
320de901896a dirstate-v2: Truncate directory mtimes to 31 bits of seconds
Simon Sapin <simon.sapin@octobus.net>
parents: 48192
diff changeset
   326
    ) -> Result<Option<TruncatedTimestamp>, DirstateV2ParseError> {
48251
dfc5a505ddc5 dirstate-v2: adds two flag to track the presence of some unrecorded files
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48250
diff changeset
   327
        // For now we do not have code to handle ALL_UNKNOWN_RECORDED, so we
dfc5a505ddc5 dirstate-v2: adds two flag to track the presence of some unrecorded files
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48250
diff changeset
   328
        // ignore the mtime if the flag is set.
dfc5a505ddc5 dirstate-v2: adds two flag to track the presence of some unrecorded files
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48250
diff changeset
   329
        if self.flags().contains(Flags::HAS_DIRECTORY_MTIME)
dfc5a505ddc5 dirstate-v2: adds two flag to track the presence of some unrecorded files
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48250
diff changeset
   330
            && self.flags().contains(Flags::ALL_UNKNOWN_RECORDED)
dfc5a505ddc5 dirstate-v2: adds two flag to track the presence of some unrecorded files
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48250
diff changeset
   331
        {
48232
f7fd629ffb98 dirstate-v2: Separate HAS_FILE_MTIME and HAS_DIRECTORY_MTIME flags
Simon Sapin <simon.sapin@octobus.net>
parents: 48231
diff changeset
   332
            if self.flags().contains(Flags::HAS_FILE_MTIME) {
f7fd629ffb98 dirstate-v2: Separate HAS_FILE_MTIME and HAS_DIRECTORY_MTIME flags
Simon Sapin <simon.sapin@octobus.net>
parents: 48231
diff changeset
   333
                Err(DirstateV2ParseError)
48193
320de901896a dirstate-v2: Truncate directory mtimes to 31 bits of seconds
Simon Sapin <simon.sapin@octobus.net>
parents: 48192
diff changeset
   334
            } else {
48232
f7fd629ffb98 dirstate-v2: Separate HAS_FILE_MTIME and HAS_DIRECTORY_MTIME flags
Simon Sapin <simon.sapin@octobus.net>
parents: 48231
diff changeset
   335
                Ok(Some(self.mtime.try_into()?))
f7fd629ffb98 dirstate-v2: Separate HAS_FILE_MTIME and HAS_DIRECTORY_MTIME flags
Simon Sapin <simon.sapin@octobus.net>
parents: 48231
diff changeset
   336
            }
f7fd629ffb98 dirstate-v2: Separate HAS_FILE_MTIME and HAS_DIRECTORY_MTIME flags
Simon Sapin <simon.sapin@octobus.net>
parents: 48231
diff changeset
   337
        } else {
f7fd629ffb98 dirstate-v2: Separate HAS_FILE_MTIME and HAS_DIRECTORY_MTIME flags
Simon Sapin <simon.sapin@octobus.net>
parents: 48231
diff changeset
   338
            Ok(None)
f7fd629ffb98 dirstate-v2: Separate HAS_FILE_MTIME and HAS_DIRECTORY_MTIME flags
Simon Sapin <simon.sapin@octobus.net>
parents: 48231
diff changeset
   339
        }
47349
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47348
diff changeset
   340
    }
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47348
diff changeset
   341
48195
4d5a13253d34 dirstate-v2: Replace the 32-bit `mode` field with two bits
Simon Sapin <simon.sapin@octobus.net>
parents: 48194
diff changeset
   342
    fn synthesize_unix_mode(&self) -> u32 {
48231
0524c1359bfc dirstate-v2: Extend node flags to 16 bits
Simon Sapin <simon.sapin@octobus.net>
parents: 48221
diff changeset
   343
        let file_type = if self.flags().contains(Flags::MODE_IS_SYMLINK) {
48195
4d5a13253d34 dirstate-v2: Replace the 32-bit `mode` field with two bits
Simon Sapin <simon.sapin@octobus.net>
parents: 48194
diff changeset
   344
            libc::S_IFLNK
4d5a13253d34 dirstate-v2: Replace the 32-bit `mode` field with two bits
Simon Sapin <simon.sapin@octobus.net>
parents: 48194
diff changeset
   345
        } else {
4d5a13253d34 dirstate-v2: Replace the 32-bit `mode` field with two bits
Simon Sapin <simon.sapin@octobus.net>
parents: 48194
diff changeset
   346
            libc::S_IFREG
4d5a13253d34 dirstate-v2: Replace the 32-bit `mode` field with two bits
Simon Sapin <simon.sapin@octobus.net>
parents: 48194
diff changeset
   347
        };
48231
0524c1359bfc dirstate-v2: Extend node flags to 16 bits
Simon Sapin <simon.sapin@octobus.net>
parents: 48221
diff changeset
   348
        let permisions = if self.flags().contains(Flags::MODE_EXEC_PERM) {
48195
4d5a13253d34 dirstate-v2: Replace the 32-bit `mode` field with two bits
Simon Sapin <simon.sapin@octobus.net>
parents: 48194
diff changeset
   349
            0o755
4d5a13253d34 dirstate-v2: Replace the 32-bit `mode` field with two bits
Simon Sapin <simon.sapin@octobus.net>
parents: 48194
diff changeset
   350
        } else {
4d5a13253d34 dirstate-v2: Replace the 32-bit `mode` field with two bits
Simon Sapin <simon.sapin@octobus.net>
parents: 48194
diff changeset
   351
            0o644
4d5a13253d34 dirstate-v2: Replace the 32-bit `mode` field with two bits
Simon Sapin <simon.sapin@octobus.net>
parents: 48194
diff changeset
   352
        };
4d5a13253d34 dirstate-v2: Replace the 32-bit `mode` field with two bits
Simon Sapin <simon.sapin@octobus.net>
parents: 48194
diff changeset
   353
        file_type | permisions
4d5a13253d34 dirstate-v2: Replace the 32-bit `mode` field with two bits
Simon Sapin <simon.sapin@octobus.net>
parents: 48194
diff changeset
   354
    }
4d5a13253d34 dirstate-v2: Replace the 32-bit `mode` field with two bits
Simon Sapin <simon.sapin@octobus.net>
parents: 48194
diff changeset
   355
48139
ab5a7fdbf75c dirstate-v2: Store a bitfield on disk instead of v1-like state
Simon Sapin <simon.sapin@octobus.net>
parents: 48022
diff changeset
   356
    fn assume_entry(&self) -> DirstateEntry {
ab5a7fdbf75c dirstate-v2: Store a bitfield on disk instead of v1-like state
Simon Sapin <simon.sapin@octobus.net>
parents: 48022
diff changeset
   357
        // TODO: convert through raw bits instead?
48231
0524c1359bfc dirstate-v2: Extend node flags to 16 bits
Simon Sapin <simon.sapin@octobus.net>
parents: 48221
diff changeset
   358
        let wdir_tracked = self.flags().contains(Flags::WDIR_TRACKED);
0524c1359bfc dirstate-v2: Extend node flags to 16 bits
Simon Sapin <simon.sapin@octobus.net>
parents: 48221
diff changeset
   359
        let p1_tracked = self.flags().contains(Flags::P1_TRACKED);
0524c1359bfc dirstate-v2: Extend node flags to 16 bits
Simon Sapin <simon.sapin@octobus.net>
parents: 48221
diff changeset
   360
        let p2_info = self.flags().contains(Flags::P2_INFO);
48250
1730b2fceaa1 dirstate-v2: adds a flag to mark a file as modified
Simon Sapin <simon.sapin@octobus.net>
parents: 48232
diff changeset
   361
        let mode_size = if self.flags().contains(Flags::HAS_MODE_AND_SIZE)
1730b2fceaa1 dirstate-v2: adds a flag to mark a file as modified
Simon Sapin <simon.sapin@octobus.net>
parents: 48232
diff changeset
   362
            && !self.flags().contains(Flags::EXPECTED_STATE_IS_MODIFIED)
1730b2fceaa1 dirstate-v2: adds a flag to mark a file as modified
Simon Sapin <simon.sapin@octobus.net>
parents: 48232
diff changeset
   363
        {
48219
308d9c245337 dirstate-v2: Add storage space for nanoseconds precision in file mtimes
Simon Sapin <simon.sapin@octobus.net>
parents: 48196
diff changeset
   364
            Some((self.synthesize_unix_mode(), self.size.into()))
48139
ab5a7fdbf75c dirstate-v2: Store a bitfield on disk instead of v1-like state
Simon Sapin <simon.sapin@octobus.net>
parents: 48022
diff changeset
   365
        } else {
ab5a7fdbf75c dirstate-v2: Store a bitfield on disk instead of v1-like state
Simon Sapin <simon.sapin@octobus.net>
parents: 48022
diff changeset
   366
            None
ab5a7fdbf75c dirstate-v2: Store a bitfield on disk instead of v1-like state
Simon Sapin <simon.sapin@octobus.net>
parents: 48022
diff changeset
   367
        };
48250
1730b2fceaa1 dirstate-v2: adds a flag to mark a file as modified
Simon Sapin <simon.sapin@octobus.net>
parents: 48232
diff changeset
   368
        let mtime = if self.flags().contains(Flags::HAS_FILE_MTIME)
1730b2fceaa1 dirstate-v2: adds a flag to mark a file as modified
Simon Sapin <simon.sapin@octobus.net>
parents: 48232
diff changeset
   369
            && !self.flags().contains(Flags::EXPECTED_STATE_IS_MODIFIED)
1730b2fceaa1 dirstate-v2: adds a flag to mark a file as modified
Simon Sapin <simon.sapin@octobus.net>
parents: 48232
diff changeset
   370
        {
48219
308d9c245337 dirstate-v2: Add storage space for nanoseconds precision in file mtimes
Simon Sapin <simon.sapin@octobus.net>
parents: 48196
diff changeset
   371
            Some(self.mtime.truncated_seconds.into())
48139
ab5a7fdbf75c dirstate-v2: Store a bitfield on disk instead of v1-like state
Simon Sapin <simon.sapin@octobus.net>
parents: 48022
diff changeset
   372
        } else {
ab5a7fdbf75c dirstate-v2: Store a bitfield on disk instead of v1-like state
Simon Sapin <simon.sapin@octobus.net>
parents: 48022
diff changeset
   373
            None
ab5a7fdbf75c dirstate-v2: Store a bitfield on disk instead of v1-like state
Simon Sapin <simon.sapin@octobus.net>
parents: 48022
diff changeset
   374
        };
ab5a7fdbf75c dirstate-v2: Store a bitfield on disk instead of v1-like state
Simon Sapin <simon.sapin@octobus.net>
parents: 48022
diff changeset
   375
        DirstateEntry::from_v2_data(
ab5a7fdbf75c dirstate-v2: Store a bitfield on disk instead of v1-like state
Simon Sapin <simon.sapin@octobus.net>
parents: 48022
diff changeset
   376
            wdir_tracked,
ab5a7fdbf75c dirstate-v2: Store a bitfield on disk instead of v1-like state
Simon Sapin <simon.sapin@octobus.net>
parents: 48022
diff changeset
   377
            p1_tracked,
ab5a7fdbf75c dirstate-v2: Store a bitfield on disk instead of v1-like state
Simon Sapin <simon.sapin@octobus.net>
parents: 48022
diff changeset
   378
            p2_info,
ab5a7fdbf75c dirstate-v2: Store a bitfield on disk instead of v1-like state
Simon Sapin <simon.sapin@octobus.net>
parents: 48022
diff changeset
   379
            mode_size,
ab5a7fdbf75c dirstate-v2: Store a bitfield on disk instead of v1-like state
Simon Sapin <simon.sapin@octobus.net>
parents: 48022
diff changeset
   380
            mtime,
48022
f2a9db29cb2d rust: Make the fields of DirstateEntry private
Simon Sapin <simon.sapin@octobus.net>
parents: 47966
diff changeset
   381
        )
47337
0654b3b3d2b5 dirstate-v2: Parse the dirstate lazily, with copy-on-write nodes
Simon Sapin <simon.sapin@octobus.net>
parents: 47336
diff changeset
   382
    }
0654b3b3d2b5 dirstate-v2: Parse the dirstate lazily, with copy-on-write nodes
Simon Sapin <simon.sapin@octobus.net>
parents: 47336
diff changeset
   383
47334
18b3060fe598 dirstate-v2: Add a zero-size error type for dirstate v2 parse errors
Simon Sapin <simon.sapin@octobus.net>
parents: 47333
diff changeset
   384
    pub(super) fn entry(
18b3060fe598 dirstate-v2: Add a zero-size error type for dirstate v2 parse errors
Simon Sapin <simon.sapin@octobus.net>
parents: 47333
diff changeset
   385
        &self,
18b3060fe598 dirstate-v2: Add a zero-size error type for dirstate v2 parse errors
Simon Sapin <simon.sapin@octobus.net>
parents: 47333
diff changeset
   386
    ) -> Result<Option<DirstateEntry>, DirstateV2ParseError> {
48139
ab5a7fdbf75c dirstate-v2: Store a bitfield on disk instead of v1-like state
Simon Sapin <simon.sapin@octobus.net>
parents: 48022
diff changeset
   387
        if self.has_entry() {
ab5a7fdbf75c dirstate-v2: Store a bitfield on disk instead of v1-like state
Simon Sapin <simon.sapin@octobus.net>
parents: 48022
diff changeset
   388
            Ok(Some(self.assume_entry()))
ab5a7fdbf75c dirstate-v2: Store a bitfield on disk instead of v1-like state
Simon Sapin <simon.sapin@octobus.net>
parents: 48022
diff changeset
   389
        } else {
ab5a7fdbf75c dirstate-v2: Store a bitfield on disk instead of v1-like state
Simon Sapin <simon.sapin@octobus.net>
parents: 48022
diff changeset
   390
            Ok(None)
ab5a7fdbf75c dirstate-v2: Store a bitfield on disk instead of v1-like state
Simon Sapin <simon.sapin@octobus.net>
parents: 48022
diff changeset
   391
        }
47337
0654b3b3d2b5 dirstate-v2: Parse the dirstate lazily, with copy-on-write nodes
Simon Sapin <simon.sapin@octobus.net>
parents: 47336
diff changeset
   392
    }
0654b3b3d2b5 dirstate-v2: Parse the dirstate lazily, with copy-on-write nodes
Simon Sapin <simon.sapin@octobus.net>
parents: 47336
diff changeset
   393
0654b3b3d2b5 dirstate-v2: Parse the dirstate lazily, with copy-on-write nodes
Simon Sapin <simon.sapin@octobus.net>
parents: 47336
diff changeset
   394
    pub(super) fn children<'on_disk>(
0654b3b3d2b5 dirstate-v2: Parse the dirstate lazily, with copy-on-write nodes
Simon Sapin <simon.sapin@octobus.net>
parents: 47336
diff changeset
   395
        &self,
0654b3b3d2b5 dirstate-v2: Parse the dirstate lazily, with copy-on-write nodes
Simon Sapin <simon.sapin@octobus.net>
parents: 47336
diff changeset
   396
        on_disk: &'on_disk [u8],
0654b3b3d2b5 dirstate-v2: Parse the dirstate lazily, with copy-on-write nodes
Simon Sapin <simon.sapin@octobus.net>
parents: 47336
diff changeset
   397
    ) -> Result<&'on_disk [Node], DirstateV2ParseError> {
47677
da1c0cd68d53 dirstate-v2: shrink on-disk path lengths to 16-bits
Simon Sapin <simon.sapin@octobus.net>
parents: 47676
diff changeset
   398
        read_nodes(on_disk, self.children)
47283
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
   399
    }
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
   400
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
   401
    pub(super) fn to_in_memory_node<'on_disk>(
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
   402
        &self,
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
   403
        on_disk: &'on_disk [u8],
47334
18b3060fe598 dirstate-v2: Add a zero-size error type for dirstate v2 parse errors
Simon Sapin <simon.sapin@octobus.net>
parents: 47333
diff changeset
   404
    ) -> Result<dirstate_map::Node<'on_disk>, DirstateV2ParseError> {
47283
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
   405
        Ok(dirstate_map::Node {
47337
0654b3b3d2b5 dirstate-v2: Parse the dirstate lazily, with copy-on-write nodes
Simon Sapin <simon.sapin@octobus.net>
parents: 47336
diff changeset
   406
            children: dirstate_map::ChildNodes::OnDisk(
0654b3b3d2b5 dirstate-v2: Parse the dirstate lazily, with copy-on-write nodes
Simon Sapin <simon.sapin@octobus.net>
parents: 47336
diff changeset
   407
                self.children(on_disk)?,
0654b3b3d2b5 dirstate-v2: Parse the dirstate lazily, with copy-on-write nodes
Simon Sapin <simon.sapin@octobus.net>
parents: 47336
diff changeset
   408
            ),
0654b3b3d2b5 dirstate-v2: Parse the dirstate lazily, with copy-on-write nodes
Simon Sapin <simon.sapin@octobus.net>
parents: 47336
diff changeset
   409
            copy_source: self.copy_source(on_disk)?.map(Cow::Borrowed),
47348
a4de570e61fa dirstate-v2: Allow tree nodes without an entry to store a timestamp
Simon Sapin <simon.sapin@octobus.net>
parents: 47337
diff changeset
   410
            data: self.node_data()?,
47478
ca8121d26732 dirstate-tree: Keep a counter of descendant nodes that have an entry
Simon Sapin <simon.sapin@octobus.net>
parents: 47476
diff changeset
   411
            descendants_with_entry_count: self
ca8121d26732 dirstate-tree: Keep a counter of descendant nodes that have an entry
Simon Sapin <simon.sapin@octobus.net>
parents: 47476
diff changeset
   412
                .descendants_with_entry_count
ca8121d26732 dirstate-tree: Keep a counter of descendant nodes that have an entry
Simon Sapin <simon.sapin@octobus.net>
parents: 47476
diff changeset
   413
                .get(),
47283
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
   414
            tracked_descendants_count: self.tracked_descendants_count.get(),
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
   415
        })
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
   416
    }
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
   417
48219
308d9c245337 dirstate-v2: Add storage space for nanoseconds precision in file mtimes
Simon Sapin <simon.sapin@octobus.net>
parents: 48196
diff changeset
   418
    fn from_dirstate_entry(
308d9c245337 dirstate-v2: Add storage space for nanoseconds precision in file mtimes
Simon Sapin <simon.sapin@octobus.net>
parents: 48196
diff changeset
   419
        entry: &DirstateEntry,
308d9c245337 dirstate-v2: Add storage space for nanoseconds precision in file mtimes
Simon Sapin <simon.sapin@octobus.net>
parents: 48196
diff changeset
   420
    ) -> (Flags, U32Be, PackedTruncatedTimestamp) {
48139
ab5a7fdbf75c dirstate-v2: Store a bitfield on disk instead of v1-like state
Simon Sapin <simon.sapin@octobus.net>
parents: 48022
diff changeset
   421
        let (wdir_tracked, p1_tracked, p2_info, mode_size_opt, mtime_opt) =
ab5a7fdbf75c dirstate-v2: Store a bitfield on disk instead of v1-like state
Simon Sapin <simon.sapin@octobus.net>
parents: 48022
diff changeset
   422
            entry.v2_data();
ab5a7fdbf75c dirstate-v2: Store a bitfield on disk instead of v1-like state
Simon Sapin <simon.sapin@octobus.net>
parents: 48022
diff changeset
   423
        // TODO: convert throug raw flag bits instead?
ab5a7fdbf75c dirstate-v2: Store a bitfield on disk instead of v1-like state
Simon Sapin <simon.sapin@octobus.net>
parents: 48022
diff changeset
   424
        let mut flags = Flags::empty();
ab5a7fdbf75c dirstate-v2: Store a bitfield on disk instead of v1-like state
Simon Sapin <simon.sapin@octobus.net>
parents: 48022
diff changeset
   425
        flags.set(Flags::WDIR_TRACKED, wdir_tracked);
ab5a7fdbf75c dirstate-v2: Store a bitfield on disk instead of v1-like state
Simon Sapin <simon.sapin@octobus.net>
parents: 48022
diff changeset
   426
        flags.set(Flags::P1_TRACKED, p1_tracked);
ab5a7fdbf75c dirstate-v2: Store a bitfield on disk instead of v1-like state
Simon Sapin <simon.sapin@octobus.net>
parents: 48022
diff changeset
   427
        flags.set(Flags::P2_INFO, p2_info);
48219
308d9c245337 dirstate-v2: Add storage space for nanoseconds precision in file mtimes
Simon Sapin <simon.sapin@octobus.net>
parents: 48196
diff changeset
   428
        let size = if let Some((m, s)) = mode_size_opt {
48195
4d5a13253d34 dirstate-v2: Replace the 32-bit `mode` field with two bits
Simon Sapin <simon.sapin@octobus.net>
parents: 48194
diff changeset
   429
            let exec_perm = m & libc::S_IXUSR != 0;
4d5a13253d34 dirstate-v2: Replace the 32-bit `mode` field with two bits
Simon Sapin <simon.sapin@octobus.net>
parents: 48194
diff changeset
   430
            let is_symlink = m & libc::S_IFMT == libc::S_IFLNK;
4d5a13253d34 dirstate-v2: Replace the 32-bit `mode` field with two bits
Simon Sapin <simon.sapin@octobus.net>
parents: 48194
diff changeset
   431
            flags.set(Flags::MODE_EXEC_PERM, exec_perm);
4d5a13253d34 dirstate-v2: Replace the 32-bit `mode` field with two bits
Simon Sapin <simon.sapin@octobus.net>
parents: 48194
diff changeset
   432
            flags.set(Flags::MODE_IS_SYMLINK, is_symlink);
48219
308d9c245337 dirstate-v2: Add storage space for nanoseconds precision in file mtimes
Simon Sapin <simon.sapin@octobus.net>
parents: 48196
diff changeset
   433
            flags.insert(Flags::HAS_MODE_AND_SIZE);
308d9c245337 dirstate-v2: Add storage space for nanoseconds precision in file mtimes
Simon Sapin <simon.sapin@octobus.net>
parents: 48196
diff changeset
   434
            s.into()
48139
ab5a7fdbf75c dirstate-v2: Store a bitfield on disk instead of v1-like state
Simon Sapin <simon.sapin@octobus.net>
parents: 48022
diff changeset
   435
        } else {
48219
308d9c245337 dirstate-v2: Add storage space for nanoseconds precision in file mtimes
Simon Sapin <simon.sapin@octobus.net>
parents: 48196
diff changeset
   436
            0.into()
48139
ab5a7fdbf75c dirstate-v2: Store a bitfield on disk instead of v1-like state
Simon Sapin <simon.sapin@octobus.net>
parents: 48022
diff changeset
   437
        };
48219
308d9c245337 dirstate-v2: Add storage space for nanoseconds precision in file mtimes
Simon Sapin <simon.sapin@octobus.net>
parents: 48196
diff changeset
   438
        let mtime = if let Some(m) = mtime_opt {
48232
f7fd629ffb98 dirstate-v2: Separate HAS_FILE_MTIME and HAS_DIRECTORY_MTIME flags
Simon Sapin <simon.sapin@octobus.net>
parents: 48231
diff changeset
   439
            flags.insert(Flags::HAS_FILE_MTIME);
48219
308d9c245337 dirstate-v2: Add storage space for nanoseconds precision in file mtimes
Simon Sapin <simon.sapin@octobus.net>
parents: 48196
diff changeset
   440
            PackedTruncatedTimestamp {
308d9c245337 dirstate-v2: Add storage space for nanoseconds precision in file mtimes
Simon Sapin <simon.sapin@octobus.net>
parents: 48196
diff changeset
   441
                truncated_seconds: m.into(),
308d9c245337 dirstate-v2: Add storage space for nanoseconds precision in file mtimes
Simon Sapin <simon.sapin@octobus.net>
parents: 48196
diff changeset
   442
                nanoseconds: 0.into(),
308d9c245337 dirstate-v2: Add storage space for nanoseconds precision in file mtimes
Simon Sapin <simon.sapin@octobus.net>
parents: 48196
diff changeset
   443
            }
308d9c245337 dirstate-v2: Add storage space for nanoseconds precision in file mtimes
Simon Sapin <simon.sapin@octobus.net>
parents: 48196
diff changeset
   444
        } else {
308d9c245337 dirstate-v2: Add storage space for nanoseconds precision in file mtimes
Simon Sapin <simon.sapin@octobus.net>
parents: 48196
diff changeset
   445
            PackedTruncatedTimestamp::null()
48192
d2f760c2c91c dirstate-v2: Separate Rust structs for Timestamp and PackedTimestamp
Simon Sapin <simon.sapin@octobus.net>
parents: 48191
diff changeset
   446
        };
48219
308d9c245337 dirstate-v2: Add storage space for nanoseconds precision in file mtimes
Simon Sapin <simon.sapin@octobus.net>
parents: 48196
diff changeset
   447
        (flags, size, mtime)
47348
a4de570e61fa dirstate-v2: Allow tree nodes without an entry to store a timestamp
Simon Sapin <simon.sapin@octobus.net>
parents: 47337
diff changeset
   448
    }
a4de570e61fa dirstate-v2: Allow tree nodes without an entry to store a timestamp
Simon Sapin <simon.sapin@octobus.net>
parents: 47337
diff changeset
   449
}
a4de570e61fa dirstate-v2: Allow tree nodes without an entry to store a timestamp
Simon Sapin <simon.sapin@octobus.net>
parents: 47337
diff changeset
   450
47334
18b3060fe598 dirstate-v2: Add a zero-size error type for dirstate v2 parse errors
Simon Sapin <simon.sapin@octobus.net>
parents: 47333
diff changeset
   451
fn read_hg_path(
18b3060fe598 dirstate-v2: Add a zero-size error type for dirstate v2 parse errors
Simon Sapin <simon.sapin@octobus.net>
parents: 47333
diff changeset
   452
    on_disk: &[u8],
47677
da1c0cd68d53 dirstate-v2: shrink on-disk path lengths to 16-bits
Simon Sapin <simon.sapin@octobus.net>
parents: 47676
diff changeset
   453
    slice: PathSlice,
47337
0654b3b3d2b5 dirstate-v2: Parse the dirstate lazily, with copy-on-write nodes
Simon Sapin <simon.sapin@octobus.net>
parents: 47336
diff changeset
   454
) -> Result<&HgPath, DirstateV2ParseError> {
47677
da1c0cd68d53 dirstate-v2: shrink on-disk path lengths to 16-bits
Simon Sapin <simon.sapin@octobus.net>
parents: 47676
diff changeset
   455
    read_slice(on_disk, slice.start, slice.len.get()).map(HgPath::new)
47283
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
   456
}
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
   457
47677
da1c0cd68d53 dirstate-v2: shrink on-disk path lengths to 16-bits
Simon Sapin <simon.sapin@octobus.net>
parents: 47676
diff changeset
   458
fn read_nodes(
47334
18b3060fe598 dirstate-v2: Add a zero-size error type for dirstate v2 parse errors
Simon Sapin <simon.sapin@octobus.net>
parents: 47333
diff changeset
   459
    on_disk: &[u8],
47677
da1c0cd68d53 dirstate-v2: shrink on-disk path lengths to 16-bits
Simon Sapin <simon.sapin@octobus.net>
parents: 47676
diff changeset
   460
    slice: ChildNodes,
da1c0cd68d53 dirstate-v2: shrink on-disk path lengths to 16-bits
Simon Sapin <simon.sapin@octobus.net>
parents: 47676
diff changeset
   461
) -> Result<&[Node], DirstateV2ParseError> {
da1c0cd68d53 dirstate-v2: shrink on-disk path lengths to 16-bits
Simon Sapin <simon.sapin@octobus.net>
parents: 47676
diff changeset
   462
    read_slice(on_disk, slice.start, slice.len.get())
da1c0cd68d53 dirstate-v2: shrink on-disk path lengths to 16-bits
Simon Sapin <simon.sapin@octobus.net>
parents: 47676
diff changeset
   463
}
da1c0cd68d53 dirstate-v2: shrink on-disk path lengths to 16-bits
Simon Sapin <simon.sapin@octobus.net>
parents: 47676
diff changeset
   464
da1c0cd68d53 dirstate-v2: shrink on-disk path lengths to 16-bits
Simon Sapin <simon.sapin@octobus.net>
parents: 47676
diff changeset
   465
fn read_slice<T, Len>(
da1c0cd68d53 dirstate-v2: shrink on-disk path lengths to 16-bits
Simon Sapin <simon.sapin@octobus.net>
parents: 47676
diff changeset
   466
    on_disk: &[u8],
da1c0cd68d53 dirstate-v2: shrink on-disk path lengths to 16-bits
Simon Sapin <simon.sapin@octobus.net>
parents: 47676
diff changeset
   467
    start: Offset,
da1c0cd68d53 dirstate-v2: shrink on-disk path lengths to 16-bits
Simon Sapin <simon.sapin@octobus.net>
parents: 47676
diff changeset
   468
    len: Len,
47334
18b3060fe598 dirstate-v2: Add a zero-size error type for dirstate v2 parse errors
Simon Sapin <simon.sapin@octobus.net>
parents: 47333
diff changeset
   469
) -> Result<&[T], DirstateV2ParseError>
47283
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
   470
where
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
   471
    T: BytesCast,
47677
da1c0cd68d53 dirstate-v2: shrink on-disk path lengths to 16-bits
Simon Sapin <simon.sapin@octobus.net>
parents: 47676
diff changeset
   472
    Len: TryInto<usize>,
47283
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
   473
{
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
   474
    // Either `usize::MAX` would result in "out of bounds" error since a single
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
   475
    // `&[u8]` cannot occupy the entire addess space.
47677
da1c0cd68d53 dirstate-v2: shrink on-disk path lengths to 16-bits
Simon Sapin <simon.sapin@octobus.net>
parents: 47676
diff changeset
   476
    let start = start.get().try_into().unwrap_or(std::usize::MAX);
da1c0cd68d53 dirstate-v2: shrink on-disk path lengths to 16-bits
Simon Sapin <simon.sapin@octobus.net>
parents: 47676
diff changeset
   477
    let len = len.try_into().unwrap_or(std::usize::MAX);
47283
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
   478
    on_disk
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
   479
        .get(start..)
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
   480
        .and_then(|bytes| T::slice_from_bytes(bytes, len).ok())
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
   481
        .map(|(slice, _rest)| slice)
47334
18b3060fe598 dirstate-v2: Add a zero-size error type for dirstate v2 parse errors
Simon Sapin <simon.sapin@octobus.net>
parents: 47333
diff changeset
   482
        .ok_or_else(|| DirstateV2ParseError)
47283
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
   483
}
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
   484
47374
bd88b6bfd8da rhg: Add support for dirstate-v2
Simon Sapin <simon.sapin@octobus.net>
parents: 47351
diff changeset
   485
pub(crate) fn for_each_tracked_path<'on_disk>(
bd88b6bfd8da rhg: Add support for dirstate-v2
Simon Sapin <simon.sapin@octobus.net>
parents: 47351
diff changeset
   486
    on_disk: &'on_disk [u8],
47682
78f7f0d490ee dirstate-v2: Move fixed-size tree metadata into the docket file
Simon Sapin <simon.sapin@octobus.net>
parents: 47681
diff changeset
   487
    metadata: &[u8],
47374
bd88b6bfd8da rhg: Add support for dirstate-v2
Simon Sapin <simon.sapin@octobus.net>
parents: 47351
diff changeset
   488
    mut f: impl FnMut(&'on_disk HgPath),
bd88b6bfd8da rhg: Add support for dirstate-v2
Simon Sapin <simon.sapin@octobus.net>
parents: 47351
diff changeset
   489
) -> Result<(), DirstateV2ParseError> {
47682
78f7f0d490ee dirstate-v2: Move fixed-size tree metadata into the docket file
Simon Sapin <simon.sapin@octobus.net>
parents: 47681
diff changeset
   490
    let (meta, _) = TreeMetadata::from_bytes(metadata)
78f7f0d490ee dirstate-v2: Move fixed-size tree metadata into the docket file
Simon Sapin <simon.sapin@octobus.net>
parents: 47681
diff changeset
   491
        .map_err(|_| DirstateV2ParseError)?;
47374
bd88b6bfd8da rhg: Add support for dirstate-v2
Simon Sapin <simon.sapin@octobus.net>
parents: 47351
diff changeset
   492
    fn recur<'on_disk>(
bd88b6bfd8da rhg: Add support for dirstate-v2
Simon Sapin <simon.sapin@octobus.net>
parents: 47351
diff changeset
   493
        on_disk: &'on_disk [u8],
47677
da1c0cd68d53 dirstate-v2: shrink on-disk path lengths to 16-bits
Simon Sapin <simon.sapin@octobus.net>
parents: 47676
diff changeset
   494
        nodes: ChildNodes,
47374
bd88b6bfd8da rhg: Add support for dirstate-v2
Simon Sapin <simon.sapin@octobus.net>
parents: 47351
diff changeset
   495
        f: &mut impl FnMut(&'on_disk HgPath),
bd88b6bfd8da rhg: Add support for dirstate-v2
Simon Sapin <simon.sapin@octobus.net>
parents: 47351
diff changeset
   496
    ) -> Result<(), DirstateV2ParseError> {
47677
da1c0cd68d53 dirstate-v2: shrink on-disk path lengths to 16-bits
Simon Sapin <simon.sapin@octobus.net>
parents: 47676
diff changeset
   497
        for node in read_nodes(on_disk, nodes)? {
48139
ab5a7fdbf75c dirstate-v2: Store a bitfield on disk instead of v1-like state
Simon Sapin <simon.sapin@octobus.net>
parents: 48022
diff changeset
   498
            if let Some(entry) = node.entry()? {
ab5a7fdbf75c dirstate-v2: Store a bitfield on disk instead of v1-like state
Simon Sapin <simon.sapin@octobus.net>
parents: 48022
diff changeset
   499
                if entry.state().is_tracked() {
47374
bd88b6bfd8da rhg: Add support for dirstate-v2
Simon Sapin <simon.sapin@octobus.net>
parents: 47351
diff changeset
   500
                    f(node.full_path(on_disk)?)
bd88b6bfd8da rhg: Add support for dirstate-v2
Simon Sapin <simon.sapin@octobus.net>
parents: 47351
diff changeset
   501
                }
bd88b6bfd8da rhg: Add support for dirstate-v2
Simon Sapin <simon.sapin@octobus.net>
parents: 47351
diff changeset
   502
            }
bd88b6bfd8da rhg: Add support for dirstate-v2
Simon Sapin <simon.sapin@octobus.net>
parents: 47351
diff changeset
   503
            recur(on_disk, node.children, f)?
bd88b6bfd8da rhg: Add support for dirstate-v2
Simon Sapin <simon.sapin@octobus.net>
parents: 47351
diff changeset
   504
        }
bd88b6bfd8da rhg: Add support for dirstate-v2
Simon Sapin <simon.sapin@octobus.net>
parents: 47351
diff changeset
   505
        Ok(())
bd88b6bfd8da rhg: Add support for dirstate-v2
Simon Sapin <simon.sapin@octobus.net>
parents: 47351
diff changeset
   506
    }
47682
78f7f0d490ee dirstate-v2: Move fixed-size tree metadata into the docket file
Simon Sapin <simon.sapin@octobus.net>
parents: 47681
diff changeset
   507
    recur(on_disk, meta.root_nodes, &mut f)
47374
bd88b6bfd8da rhg: Add support for dirstate-v2
Simon Sapin <simon.sapin@octobus.net>
parents: 47351
diff changeset
   508
}
bd88b6bfd8da rhg: Add support for dirstate-v2
Simon Sapin <simon.sapin@octobus.net>
parents: 47351
diff changeset
   509
47682
78f7f0d490ee dirstate-v2: Move fixed-size tree metadata into the docket file
Simon Sapin <simon.sapin@octobus.net>
parents: 47681
diff changeset
   510
/// Returns new data and metadata, together with whether that data should be
78f7f0d490ee dirstate-v2: Move fixed-size tree metadata into the docket file
Simon Sapin <simon.sapin@octobus.net>
parents: 47681
diff changeset
   511
/// appended to the existing data file whose content is at
78f7f0d490ee dirstate-v2: Move fixed-size tree metadata into the docket file
Simon Sapin <simon.sapin@octobus.net>
parents: 47681
diff changeset
   512
/// `dirstate_map.on_disk` (true), instead of written to a new data file
78f7f0d490ee dirstate-v2: Move fixed-size tree metadata into the docket file
Simon Sapin <simon.sapin@octobus.net>
parents: 47681
diff changeset
   513
/// (false).
47283
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
   514
pub(super) fn write(
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
   515
    dirstate_map: &mut DirstateMap,
47678
065e61628980 dirstate-v2: Support appending to the same data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47677
diff changeset
   516
    can_append: bool,
47682
78f7f0d490ee dirstate-v2: Move fixed-size tree metadata into the docket file
Simon Sapin <simon.sapin@octobus.net>
parents: 47681
diff changeset
   517
) -> Result<(Vec<u8>, Vec<u8>, bool), DirstateError> {
47678
065e61628980 dirstate-v2: Support appending to the same data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47677
diff changeset
   518
    let append = can_append && dirstate_map.write_should_append();
47283
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
   519
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
   520
    // This ignores the space for paths, and for nodes without an entry.
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
   521
    // TODO: better estimate? Skip the `Vec` and write to a file directly?
47682
78f7f0d490ee dirstate-v2: Move fixed-size tree metadata into the docket file
Simon Sapin <simon.sapin@octobus.net>
parents: 47681
diff changeset
   522
    let size_guess = std::mem::size_of::<Node>()
78f7f0d490ee dirstate-v2: Move fixed-size tree metadata into the docket file
Simon Sapin <simon.sapin@octobus.net>
parents: 47681
diff changeset
   523
        * dirstate_map.nodes_with_entry_count as usize;
47283
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
   524
47678
065e61628980 dirstate-v2: Support appending to the same data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47677
diff changeset
   525
    let mut writer = Writer {
065e61628980 dirstate-v2: Support appending to the same data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47677
diff changeset
   526
        dirstate_map,
065e61628980 dirstate-v2: Support appending to the same data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47677
diff changeset
   527
        append,
065e61628980 dirstate-v2: Support appending to the same data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47677
diff changeset
   528
        out: Vec::with_capacity(size_guess),
065e61628980 dirstate-v2: Support appending to the same data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47677
diff changeset
   529
    };
065e61628980 dirstate-v2: Support appending to the same data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47677
diff changeset
   530
065e61628980 dirstate-v2: Support appending to the same data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47677
diff changeset
   531
    let root_nodes = writer.write_nodes(dirstate_map.root.as_ref())?;
47283
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
   532
47682
78f7f0d490ee dirstate-v2: Move fixed-size tree metadata into the docket file
Simon Sapin <simon.sapin@octobus.net>
parents: 47681
diff changeset
   533
    let meta = TreeMetadata {
47676
096ee2e260a3 dirstate-v2: Rename Header to Root, move it to the end of the data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47675
diff changeset
   534
        root_nodes,
47283
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
   535
        nodes_with_entry_count: dirstate_map.nodes_with_entry_count.into(),
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
   536
        nodes_with_copy_source_count: dirstate_map
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
   537
            .nodes_with_copy_source_count
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
   538
            .into(),
47681
d94118365ec5 dirstate-v2: Add heuristic for when to create a new data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47680
diff changeset
   539
        unreachable_bytes: dirstate_map.unreachable_bytes.into(),
47684
852262e2e7d9 dirstate-v2: Reserve a few bytes of space for future extensions
Simon Sapin <simon.sapin@octobus.net>
parents: 47682
diff changeset
   540
        unused: [0; 4],
47409
0ef8231e413f dirstate-v2: Store a hash of ignore patterns (.hgignore)
Simon Sapin <simon.sapin@octobus.net>
parents: 47374
diff changeset
   541
        ignore_patterns_hash: dirstate_map.ignore_patterns_hash,
47283
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
   542
    };
47682
78f7f0d490ee dirstate-v2: Move fixed-size tree metadata into the docket file
Simon Sapin <simon.sapin@octobus.net>
parents: 47681
diff changeset
   543
    Ok((writer.out, meta.as_bytes().to_vec(), append))
47678
065e61628980 dirstate-v2: Support appending to the same data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47677
diff changeset
   544
}
065e61628980 dirstate-v2: Support appending to the same data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47677
diff changeset
   545
065e61628980 dirstate-v2: Support appending to the same data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47677
diff changeset
   546
struct Writer<'dmap, 'on_disk> {
065e61628980 dirstate-v2: Support appending to the same data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47677
diff changeset
   547
    dirstate_map: &'dmap DirstateMap<'on_disk>,
065e61628980 dirstate-v2: Support appending to the same data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47677
diff changeset
   548
    append: bool,
065e61628980 dirstate-v2: Support appending to the same data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47677
diff changeset
   549
    out: Vec<u8>,
47283
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
   550
}
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
   551
47678
065e61628980 dirstate-v2: Support appending to the same data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47677
diff changeset
   552
impl Writer<'_, '_> {
065e61628980 dirstate-v2: Support appending to the same data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47677
diff changeset
   553
    fn write_nodes(
065e61628980 dirstate-v2: Support appending to the same data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47677
diff changeset
   554
        &mut self,
065e61628980 dirstate-v2: Support appending to the same data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47677
diff changeset
   555
        nodes: dirstate_map::ChildNodesRef,
065e61628980 dirstate-v2: Support appending to the same data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47677
diff changeset
   556
    ) -> Result<ChildNodes, DirstateError> {
47679
731286dc5321 dirstate-v2: Reuse existing nodes when appending to a data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47678
diff changeset
   557
        // Reuse already-written nodes if possible
731286dc5321 dirstate-v2: Reuse existing nodes when appending to a data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47678
diff changeset
   558
        if self.append {
731286dc5321 dirstate-v2: Reuse existing nodes when appending to a data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47678
diff changeset
   559
            if let dirstate_map::ChildNodesRef::OnDisk(nodes_slice) = nodes {
47680
a8b0f29dc0d7 dirstate-v2: Reuse existing paths when appending to a data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47679
diff changeset
   560
                let start = self.on_disk_offset_of(nodes_slice).expect(
a8b0f29dc0d7 dirstate-v2: Reuse existing paths when appending to a data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47679
diff changeset
   561
                    "dirstate-v2 OnDisk nodes not found within on_disk",
a8b0f29dc0d7 dirstate-v2: Reuse existing paths when appending to a data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47679
diff changeset
   562
                );
47679
731286dc5321 dirstate-v2: Reuse existing nodes when appending to a data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47678
diff changeset
   563
                let len = child_nodes_len_from_usize(nodes_slice.len());
731286dc5321 dirstate-v2: Reuse existing nodes when appending to a data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47678
diff changeset
   564
                return Ok(ChildNodes { start, len });
731286dc5321 dirstate-v2: Reuse existing nodes when appending to a data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47678
diff changeset
   565
            }
731286dc5321 dirstate-v2: Reuse existing nodes when appending to a data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47678
diff changeset
   566
        }
731286dc5321 dirstate-v2: Reuse existing nodes when appending to a data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47678
diff changeset
   567
731286dc5321 dirstate-v2: Reuse existing nodes when appending to a data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47678
diff changeset
   568
        // `dirstate_map::ChildNodes::InMemory` contains a `HashMap` which has
731286dc5321 dirstate-v2: Reuse existing nodes when appending to a data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47678
diff changeset
   569
        // undefined iteration order. Sort to enable binary search in the
731286dc5321 dirstate-v2: Reuse existing nodes when appending to a data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47678
diff changeset
   570
        // written file.
47678
065e61628980 dirstate-v2: Support appending to the same data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47677
diff changeset
   571
        let nodes = nodes.sorted();
065e61628980 dirstate-v2: Support appending to the same data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47677
diff changeset
   572
        let nodes_len = nodes.len();
47283
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
   573
47678
065e61628980 dirstate-v2: Support appending to the same data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47677
diff changeset
   574
        // First accumulate serialized nodes in a `Vec`
065e61628980 dirstate-v2: Support appending to the same data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47677
diff changeset
   575
        let mut on_disk_nodes = Vec::with_capacity(nodes_len);
065e61628980 dirstate-v2: Support appending to the same data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47677
diff changeset
   576
        for node in nodes {
065e61628980 dirstate-v2: Support appending to the same data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47677
diff changeset
   577
            let children =
065e61628980 dirstate-v2: Support appending to the same data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47677
diff changeset
   578
                self.write_nodes(node.children(self.dirstate_map.on_disk)?)?;
065e61628980 dirstate-v2: Support appending to the same data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47677
diff changeset
   579
            let full_path = node.full_path(self.dirstate_map.on_disk)?;
065e61628980 dirstate-v2: Support appending to the same data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47677
diff changeset
   580
            let full_path = self.write_path(full_path.as_bytes());
065e61628980 dirstate-v2: Support appending to the same data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47677
diff changeset
   581
            let copy_source = if let Some(source) =
065e61628980 dirstate-v2: Support appending to the same data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47677
diff changeset
   582
                node.copy_source(self.dirstate_map.on_disk)?
065e61628980 dirstate-v2: Support appending to the same data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47677
diff changeset
   583
            {
065e61628980 dirstate-v2: Support appending to the same data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47677
diff changeset
   584
                self.write_path(source.as_bytes())
47336
8d0260d0dbc9 dirstate-v2: Make the dirstate bytes buffer available in more places
Simon Sapin <simon.sapin@octobus.net>
parents: 47335
diff changeset
   585
            } else {
47677
da1c0cd68d53 dirstate-v2: shrink on-disk path lengths to 16-bits
Simon Sapin <simon.sapin@octobus.net>
parents: 47676
diff changeset
   586
                PathSlice {
47336
8d0260d0dbc9 dirstate-v2: Make the dirstate bytes buffer available in more places
Simon Sapin <simon.sapin@octobus.net>
parents: 47335
diff changeset
   587
                    start: 0.into(),
8d0260d0dbc9 dirstate-v2: Make the dirstate bytes buffer available in more places
Simon Sapin <simon.sapin@octobus.net>
parents: 47335
diff changeset
   588
                    len: 0.into(),
8d0260d0dbc9 dirstate-v2: Make the dirstate bytes buffer available in more places
Simon Sapin <simon.sapin@octobus.net>
parents: 47335
diff changeset
   589
                }
8d0260d0dbc9 dirstate-v2: Make the dirstate bytes buffer available in more places
Simon Sapin <simon.sapin@octobus.net>
parents: 47335
diff changeset
   590
            };
47678
065e61628980 dirstate-v2: Support appending to the same data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47677
diff changeset
   591
            on_disk_nodes.push(match node {
065e61628980 dirstate-v2: Support appending to the same data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47677
diff changeset
   592
                NodeRef::InMemory(path, node) => {
48219
308d9c245337 dirstate-v2: Add storage space for nanoseconds precision in file mtimes
Simon Sapin <simon.sapin@octobus.net>
parents: 48196
diff changeset
   593
                    let (flags, size, mtime) = match &node.data {
48139
ab5a7fdbf75c dirstate-v2: Store a bitfield on disk instead of v1-like state
Simon Sapin <simon.sapin@octobus.net>
parents: 48022
diff changeset
   594
                        dirstate_map::NodeData::Entry(entry) => {
48219
308d9c245337 dirstate-v2: Add storage space for nanoseconds precision in file mtimes
Simon Sapin <simon.sapin@octobus.net>
parents: 48196
diff changeset
   595
                            Node::from_dirstate_entry(entry)
48139
ab5a7fdbf75c dirstate-v2: Store a bitfield on disk instead of v1-like state
Simon Sapin <simon.sapin@octobus.net>
parents: 48022
diff changeset
   596
                        }
48232
f7fd629ffb98 dirstate-v2: Separate HAS_FILE_MTIME and HAS_DIRECTORY_MTIME flags
Simon Sapin <simon.sapin@octobus.net>
parents: 48231
diff changeset
   597
                        dirstate_map::NodeData::CachedDirectory { mtime } => (
48251
dfc5a505ddc5 dirstate-v2: adds two flag to track the presence of some unrecorded files
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48250
diff changeset
   598
                            // we currently never set a mtime if unknown file
dfc5a505ddc5 dirstate-v2: adds two flag to track the presence of some unrecorded files
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48250
diff changeset
   599
                            // are present.
dfc5a505ddc5 dirstate-v2: adds two flag to track the presence of some unrecorded files
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48250
diff changeset
   600
                            // So if we have a mtime for a directory, we know
dfc5a505ddc5 dirstate-v2: adds two flag to track the presence of some unrecorded files
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48250
diff changeset
   601
                            // they are no unknown
dfc5a505ddc5 dirstate-v2: adds two flag to track the presence of some unrecorded files
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48250
diff changeset
   602
                            // files and we
dfc5a505ddc5 dirstate-v2: adds two flag to track the presence of some unrecorded files
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48250
diff changeset
   603
                            // blindly set ALL_UNKNOWN_RECORDED.
dfc5a505ddc5 dirstate-v2: adds two flag to track the presence of some unrecorded files
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48250
diff changeset
   604
                            //
dfc5a505ddc5 dirstate-v2: adds two flag to track the presence of some unrecorded files
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48250
diff changeset
   605
                            // We never set ALL_IGNORED_RECORDED since we
dfc5a505ddc5 dirstate-v2: adds two flag to track the presence of some unrecorded files
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48250
diff changeset
   606
                            // don't track that case
dfc5a505ddc5 dirstate-v2: adds two flag to track the presence of some unrecorded files
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48250
diff changeset
   607
                            // currently.
dfc5a505ddc5 dirstate-v2: adds two flag to track the presence of some unrecorded files
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48250
diff changeset
   608
                            Flags::HAS_DIRECTORY_MTIME
dfc5a505ddc5 dirstate-v2: adds two flag to track the presence of some unrecorded files
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48250
diff changeset
   609
                                | Flags::ALL_UNKNOWN_RECORDED,
48232
f7fd629ffb98 dirstate-v2: Separate HAS_FILE_MTIME and HAS_DIRECTORY_MTIME flags
Simon Sapin <simon.sapin@octobus.net>
parents: 48231
diff changeset
   610
                            0.into(),
f7fd629ffb98 dirstate-v2: Separate HAS_FILE_MTIME and HAS_DIRECTORY_MTIME flags
Simon Sapin <simon.sapin@octobus.net>
parents: 48231
diff changeset
   611
                            (*mtime).into(),
f7fd629ffb98 dirstate-v2: Separate HAS_FILE_MTIME and HAS_DIRECTORY_MTIME flags
Simon Sapin <simon.sapin@octobus.net>
parents: 48231
diff changeset
   612
                        ),
47678
065e61628980 dirstate-v2: Support appending to the same data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47677
diff changeset
   613
                        dirstate_map::NodeData::None => (
48139
ab5a7fdbf75c dirstate-v2: Store a bitfield on disk instead of v1-like state
Simon Sapin <simon.sapin@octobus.net>
parents: 48022
diff changeset
   614
                            Flags::empty(),
48219
308d9c245337 dirstate-v2: Add storage space for nanoseconds precision in file mtimes
Simon Sapin <simon.sapin@octobus.net>
parents: 48196
diff changeset
   615
                            0.into(),
308d9c245337 dirstate-v2: Add storage space for nanoseconds precision in file mtimes
Simon Sapin <simon.sapin@octobus.net>
parents: 48196
diff changeset
   616
                            PackedTruncatedTimestamp::null(),
47678
065e61628980 dirstate-v2: Support appending to the same data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47677
diff changeset
   617
                        ),
065e61628980 dirstate-v2: Support appending to the same data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47677
diff changeset
   618
                    };
065e61628980 dirstate-v2: Support appending to the same data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47677
diff changeset
   619
                    Node {
065e61628980 dirstate-v2: Support appending to the same data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47677
diff changeset
   620
                        children,
065e61628980 dirstate-v2: Support appending to the same data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47677
diff changeset
   621
                        copy_source,
065e61628980 dirstate-v2: Support appending to the same data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47677
diff changeset
   622
                        full_path,
065e61628980 dirstate-v2: Support appending to the same data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47677
diff changeset
   623
                        base_name_start: u16::try_from(path.base_name_start())
065e61628980 dirstate-v2: Support appending to the same data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47677
diff changeset
   624
                            // Could only panic for paths over 64 KiB
065e61628980 dirstate-v2: Support appending to the same data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47677
diff changeset
   625
                            .expect("dirstate-v2 path length overflow")
065e61628980 dirstate-v2: Support appending to the same data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47677
diff changeset
   626
                            .into(),
065e61628980 dirstate-v2: Support appending to the same data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47677
diff changeset
   627
                        descendants_with_entry_count: node
065e61628980 dirstate-v2: Support appending to the same data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47677
diff changeset
   628
                            .descendants_with_entry_count
065e61628980 dirstate-v2: Support appending to the same data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47677
diff changeset
   629
                            .into(),
065e61628980 dirstate-v2: Support appending to the same data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47677
diff changeset
   630
                        tracked_descendants_count: node
065e61628980 dirstate-v2: Support appending to the same data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47677
diff changeset
   631
                            .tracked_descendants_count
065e61628980 dirstate-v2: Support appending to the same data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47677
diff changeset
   632
                            .into(),
48231
0524c1359bfc dirstate-v2: Extend node flags to 16 bits
Simon Sapin <simon.sapin@octobus.net>
parents: 48221
diff changeset
   633
                        flags: flags.bits().into(),
48219
308d9c245337 dirstate-v2: Add storage space for nanoseconds precision in file mtimes
Simon Sapin <simon.sapin@octobus.net>
parents: 48196
diff changeset
   634
                        size,
308d9c245337 dirstate-v2: Add storage space for nanoseconds precision in file mtimes
Simon Sapin <simon.sapin@octobus.net>
parents: 48196
diff changeset
   635
                        mtime,
47333
69530e5d4fe5 dirstate-tree: Add `NodeRef` and `ChildNodesRef` enums
Simon Sapin <simon.sapin@octobus.net>
parents: 47331
diff changeset
   636
                    }
47678
065e61628980 dirstate-v2: Support appending to the same data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47677
diff changeset
   637
                }
065e61628980 dirstate-v2: Support appending to the same data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47677
diff changeset
   638
                NodeRef::OnDisk(node) => Node {
47348
a4de570e61fa dirstate-v2: Allow tree nodes without an entry to store a timestamp
Simon Sapin <simon.sapin@octobus.net>
parents: 47337
diff changeset
   639
                    children,
a4de570e61fa dirstate-v2: Allow tree nodes without an entry to store a timestamp
Simon Sapin <simon.sapin@octobus.net>
parents: 47337
diff changeset
   640
                    copy_source,
a4de570e61fa dirstate-v2: Allow tree nodes without an entry to store a timestamp
Simon Sapin <simon.sapin@octobus.net>
parents: 47337
diff changeset
   641
                    full_path,
47678
065e61628980 dirstate-v2: Support appending to the same data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47677
diff changeset
   642
                    ..*node
065e61628980 dirstate-v2: Support appending to the same data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47677
diff changeset
   643
                },
065e61628980 dirstate-v2: Support appending to the same data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47677
diff changeset
   644
            })
065e61628980 dirstate-v2: Support appending to the same data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47677
diff changeset
   645
        }
065e61628980 dirstate-v2: Support appending to the same data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47677
diff changeset
   646
        // … so we can write them contiguously, after writing everything else
065e61628980 dirstate-v2: Support appending to the same data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47677
diff changeset
   647
        // they refer to.
065e61628980 dirstate-v2: Support appending to the same data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47677
diff changeset
   648
        let start = self.current_offset();
47679
731286dc5321 dirstate-v2: Reuse existing nodes when appending to a data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47678
diff changeset
   649
        let len = child_nodes_len_from_usize(nodes_len);
47678
065e61628980 dirstate-v2: Support appending to the same data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47677
diff changeset
   650
        self.out.extend(on_disk_nodes.as_bytes());
065e61628980 dirstate-v2: Support appending to the same data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47677
diff changeset
   651
        Ok(ChildNodes { start, len })
47283
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
   652
    }
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
   653
47680
a8b0f29dc0d7 dirstate-v2: Reuse existing paths when appending to a data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47679
diff changeset
   654
    /// If the given slice of items is within `on_disk`, returns its offset
a8b0f29dc0d7 dirstate-v2: Reuse existing paths when appending to a data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47679
diff changeset
   655
    /// from the start of `on_disk`.
a8b0f29dc0d7 dirstate-v2: Reuse existing paths when appending to a data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47679
diff changeset
   656
    fn on_disk_offset_of<T>(&self, slice: &[T]) -> Option<Offset>
47679
731286dc5321 dirstate-v2: Reuse existing nodes when appending to a data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47678
diff changeset
   657
    where
731286dc5321 dirstate-v2: Reuse existing nodes when appending to a data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47678
diff changeset
   658
        T: BytesCast,
731286dc5321 dirstate-v2: Reuse existing nodes when appending to a data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47678
diff changeset
   659
    {
731286dc5321 dirstate-v2: Reuse existing nodes when appending to a data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47678
diff changeset
   660
        fn address_range(slice: &[u8]) -> std::ops::RangeInclusive<usize> {
731286dc5321 dirstate-v2: Reuse existing nodes when appending to a data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47678
diff changeset
   661
            let start = slice.as_ptr() as usize;
731286dc5321 dirstate-v2: Reuse existing nodes when appending to a data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47678
diff changeset
   662
            let end = start + slice.len();
731286dc5321 dirstate-v2: Reuse existing nodes when appending to a data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47678
diff changeset
   663
            start..=end
731286dc5321 dirstate-v2: Reuse existing nodes when appending to a data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47678
diff changeset
   664
        }
731286dc5321 dirstate-v2: Reuse existing nodes when appending to a data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47678
diff changeset
   665
        let slice_addresses = address_range(slice.as_bytes());
731286dc5321 dirstate-v2: Reuse existing nodes when appending to a data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47678
diff changeset
   666
        let on_disk_addresses = address_range(self.dirstate_map.on_disk);
47680
a8b0f29dc0d7 dirstate-v2: Reuse existing paths when appending to a data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47679
diff changeset
   667
        if on_disk_addresses.contains(slice_addresses.start())
a8b0f29dc0d7 dirstate-v2: Reuse existing paths when appending to a data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47679
diff changeset
   668
            && on_disk_addresses.contains(slice_addresses.end())
a8b0f29dc0d7 dirstate-v2: Reuse existing paths when appending to a data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47679
diff changeset
   669
        {
a8b0f29dc0d7 dirstate-v2: Reuse existing paths when appending to a data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47679
diff changeset
   670
            let offset = slice_addresses.start() - on_disk_addresses.start();
a8b0f29dc0d7 dirstate-v2: Reuse existing paths when appending to a data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47679
diff changeset
   671
            Some(offset_from_usize(offset))
a8b0f29dc0d7 dirstate-v2: Reuse existing paths when appending to a data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47679
diff changeset
   672
        } else {
a8b0f29dc0d7 dirstate-v2: Reuse existing paths when appending to a data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47679
diff changeset
   673
            None
a8b0f29dc0d7 dirstate-v2: Reuse existing paths when appending to a data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47679
diff changeset
   674
        }
47679
731286dc5321 dirstate-v2: Reuse existing nodes when appending to a data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47678
diff changeset
   675
    }
731286dc5321 dirstate-v2: Reuse existing nodes when appending to a data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47678
diff changeset
   676
47678
065e61628980 dirstate-v2: Support appending to the same data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47677
diff changeset
   677
    fn current_offset(&mut self) -> Offset {
065e61628980 dirstate-v2: Support appending to the same data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47677
diff changeset
   678
        let mut offset = self.out.len();
065e61628980 dirstate-v2: Support appending to the same data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47677
diff changeset
   679
        if self.append {
065e61628980 dirstate-v2: Support appending to the same data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47677
diff changeset
   680
            offset += self.dirstate_map.on_disk.len()
065e61628980 dirstate-v2: Support appending to the same data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47677
diff changeset
   681
        }
47679
731286dc5321 dirstate-v2: Reuse existing nodes when appending to a data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47678
diff changeset
   682
        offset_from_usize(offset)
47678
065e61628980 dirstate-v2: Support appending to the same data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47677
diff changeset
   683
    }
47677
da1c0cd68d53 dirstate-v2: shrink on-disk path lengths to 16-bits
Simon Sapin <simon.sapin@octobus.net>
parents: 47676
diff changeset
   684
47678
065e61628980 dirstate-v2: Support appending to the same data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47677
diff changeset
   685
    fn write_path(&mut self, slice: &[u8]) -> PathSlice {
47680
a8b0f29dc0d7 dirstate-v2: Reuse existing paths when appending to a data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47679
diff changeset
   686
        let len = path_len_from_usize(slice.len());
a8b0f29dc0d7 dirstate-v2: Reuse existing paths when appending to a data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47679
diff changeset
   687
        // Reuse an already-written path if possible
a8b0f29dc0d7 dirstate-v2: Reuse existing paths when appending to a data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47679
diff changeset
   688
        if self.append {
a8b0f29dc0d7 dirstate-v2: Reuse existing paths when appending to a data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47679
diff changeset
   689
            if let Some(start) = self.on_disk_offset_of(slice) {
a8b0f29dc0d7 dirstate-v2: Reuse existing paths when appending to a data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47679
diff changeset
   690
                return PathSlice { start, len };
a8b0f29dc0d7 dirstate-v2: Reuse existing paths when appending to a data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47679
diff changeset
   691
            }
a8b0f29dc0d7 dirstate-v2: Reuse existing paths when appending to a data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47679
diff changeset
   692
        }
47678
065e61628980 dirstate-v2: Support appending to the same data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47677
diff changeset
   693
        let start = self.current_offset();
065e61628980 dirstate-v2: Support appending to the same data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47677
diff changeset
   694
        self.out.extend(slice.as_bytes());
065e61628980 dirstate-v2: Support appending to the same data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47677
diff changeset
   695
        PathSlice { start, len }
065e61628980 dirstate-v2: Support appending to the same data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47677
diff changeset
   696
    }
47283
2a9ddc8094c7 dirstate-v2: Change the on-disk format to be tree-shaped
Simon Sapin <simon.sapin@octobus.net>
parents: 47280
diff changeset
   697
}
47679
731286dc5321 dirstate-v2: Reuse existing nodes when appending to a data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47678
diff changeset
   698
731286dc5321 dirstate-v2: Reuse existing nodes when appending to a data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47678
diff changeset
   699
fn offset_from_usize(x: usize) -> Offset {
731286dc5321 dirstate-v2: Reuse existing nodes when appending to a data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47678
diff changeset
   700
    u32::try_from(x)
731286dc5321 dirstate-v2: Reuse existing nodes when appending to a data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47678
diff changeset
   701
        // Could only panic for a dirstate file larger than 4 GiB
731286dc5321 dirstate-v2: Reuse existing nodes when appending to a data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47678
diff changeset
   702
        .expect("dirstate-v2 offset overflow")
731286dc5321 dirstate-v2: Reuse existing nodes when appending to a data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47678
diff changeset
   703
        .into()
731286dc5321 dirstate-v2: Reuse existing nodes when appending to a data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47678
diff changeset
   704
}
731286dc5321 dirstate-v2: Reuse existing nodes when appending to a data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47678
diff changeset
   705
731286dc5321 dirstate-v2: Reuse existing nodes when appending to a data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47678
diff changeset
   706
fn child_nodes_len_from_usize(x: usize) -> Size {
731286dc5321 dirstate-v2: Reuse existing nodes when appending to a data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47678
diff changeset
   707
    u32::try_from(x)
731286dc5321 dirstate-v2: Reuse existing nodes when appending to a data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47678
diff changeset
   708
        // Could only panic with over 4 billion nodes
731286dc5321 dirstate-v2: Reuse existing nodes when appending to a data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47678
diff changeset
   709
        .expect("dirstate-v2 slice length overflow")
731286dc5321 dirstate-v2: Reuse existing nodes when appending to a data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47678
diff changeset
   710
        .into()
731286dc5321 dirstate-v2: Reuse existing nodes when appending to a data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47678
diff changeset
   711
}
731286dc5321 dirstate-v2: Reuse existing nodes when appending to a data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47678
diff changeset
   712
731286dc5321 dirstate-v2: Reuse existing nodes when appending to a data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47678
diff changeset
   713
fn path_len_from_usize(x: usize) -> PathSize {
731286dc5321 dirstate-v2: Reuse existing nodes when appending to a data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47678
diff changeset
   714
    u16::try_from(x)
731286dc5321 dirstate-v2: Reuse existing nodes when appending to a data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47678
diff changeset
   715
        // Could only panic for paths over 64 KiB
731286dc5321 dirstate-v2: Reuse existing nodes when appending to a data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47678
diff changeset
   716
        .expect("dirstate-v2 path length overflow")
731286dc5321 dirstate-v2: Reuse existing nodes when appending to a data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47678
diff changeset
   717
        .into()
731286dc5321 dirstate-v2: Reuse existing nodes when appending to a data file
Simon Sapin <simon.sapin@octobus.net>
parents: 47678
diff changeset
   718
}
48219
308d9c245337 dirstate-v2: Add storage space for nanoseconds precision in file mtimes
Simon Sapin <simon.sapin@octobus.net>
parents: 48196
diff changeset
   719
308d9c245337 dirstate-v2: Add storage space for nanoseconds precision in file mtimes
Simon Sapin <simon.sapin@octobus.net>
parents: 48196
diff changeset
   720
impl From<TruncatedTimestamp> for PackedTruncatedTimestamp {
308d9c245337 dirstate-v2: Add storage space for nanoseconds precision in file mtimes
Simon Sapin <simon.sapin@octobus.net>
parents: 48196
diff changeset
   721
    fn from(timestamp: TruncatedTimestamp) -> Self {
308d9c245337 dirstate-v2: Add storage space for nanoseconds precision in file mtimes
Simon Sapin <simon.sapin@octobus.net>
parents: 48196
diff changeset
   722
        Self {
308d9c245337 dirstate-v2: Add storage space for nanoseconds precision in file mtimes
Simon Sapin <simon.sapin@octobus.net>
parents: 48196
diff changeset
   723
            truncated_seconds: timestamp.truncated_seconds().into(),
308d9c245337 dirstate-v2: Add storage space for nanoseconds precision in file mtimes
Simon Sapin <simon.sapin@octobus.net>
parents: 48196
diff changeset
   724
            nanoseconds: timestamp.nanoseconds().into(),
308d9c245337 dirstate-v2: Add storage space for nanoseconds precision in file mtimes
Simon Sapin <simon.sapin@octobus.net>
parents: 48196
diff changeset
   725
        }
308d9c245337 dirstate-v2: Add storage space for nanoseconds precision in file mtimes
Simon Sapin <simon.sapin@octobus.net>
parents: 48196
diff changeset
   726
    }
308d9c245337 dirstate-v2: Add storage space for nanoseconds precision in file mtimes
Simon Sapin <simon.sapin@octobus.net>
parents: 48196
diff changeset
   727
}
308d9c245337 dirstate-v2: Add storage space for nanoseconds precision in file mtimes
Simon Sapin <simon.sapin@octobus.net>
parents: 48196
diff changeset
   728
308d9c245337 dirstate-v2: Add storage space for nanoseconds precision in file mtimes
Simon Sapin <simon.sapin@octobus.net>
parents: 48196
diff changeset
   729
impl TryFrom<PackedTruncatedTimestamp> for TruncatedTimestamp {
308d9c245337 dirstate-v2: Add storage space for nanoseconds precision in file mtimes
Simon Sapin <simon.sapin@octobus.net>
parents: 48196
diff changeset
   730
    type Error = DirstateV2ParseError;
308d9c245337 dirstate-v2: Add storage space for nanoseconds precision in file mtimes
Simon Sapin <simon.sapin@octobus.net>
parents: 48196
diff changeset
   731
308d9c245337 dirstate-v2: Add storage space for nanoseconds precision in file mtimes
Simon Sapin <simon.sapin@octobus.net>
parents: 48196
diff changeset
   732
    fn try_from(
308d9c245337 dirstate-v2: Add storage space for nanoseconds precision in file mtimes
Simon Sapin <simon.sapin@octobus.net>
parents: 48196
diff changeset
   733
        timestamp: PackedTruncatedTimestamp,
308d9c245337 dirstate-v2: Add storage space for nanoseconds precision in file mtimes
Simon Sapin <simon.sapin@octobus.net>
parents: 48196
diff changeset
   734
    ) -> Result<Self, Self::Error> {
308d9c245337 dirstate-v2: Add storage space for nanoseconds precision in file mtimes
Simon Sapin <simon.sapin@octobus.net>
parents: 48196
diff changeset
   735
        Self::from_already_truncated(
308d9c245337 dirstate-v2: Add storage space for nanoseconds precision in file mtimes
Simon Sapin <simon.sapin@octobus.net>
parents: 48196
diff changeset
   736
            timestamp.truncated_seconds.get(),
308d9c245337 dirstate-v2: Add storage space for nanoseconds precision in file mtimes
Simon Sapin <simon.sapin@octobus.net>
parents: 48196
diff changeset
   737
            timestamp.nanoseconds.get(),
308d9c245337 dirstate-v2: Add storage space for nanoseconds precision in file mtimes
Simon Sapin <simon.sapin@octobus.net>
parents: 48196
diff changeset
   738
        )
308d9c245337 dirstate-v2: Add storage space for nanoseconds precision in file mtimes
Simon Sapin <simon.sapin@octobus.net>
parents: 48196
diff changeset
   739
    }
308d9c245337 dirstate-v2: Add storage space for nanoseconds precision in file mtimes
Simon Sapin <simon.sapin@octobus.net>
parents: 48196
diff changeset
   740
}
308d9c245337 dirstate-v2: Add storage space for nanoseconds precision in file mtimes
Simon Sapin <simon.sapin@octobus.net>
parents: 48196
diff changeset
   741
impl PackedTruncatedTimestamp {
308d9c245337 dirstate-v2: Add storage space for nanoseconds precision in file mtimes
Simon Sapin <simon.sapin@octobus.net>
parents: 48196
diff changeset
   742
    fn null() -> Self {
308d9c245337 dirstate-v2: Add storage space for nanoseconds precision in file mtimes
Simon Sapin <simon.sapin@octobus.net>
parents: 48196
diff changeset
   743
        Self {
308d9c245337 dirstate-v2: Add storage space for nanoseconds precision in file mtimes
Simon Sapin <simon.sapin@octobus.net>
parents: 48196
diff changeset
   744
            truncated_seconds: 0.into(),
308d9c245337 dirstate-v2: Add storage space for nanoseconds precision in file mtimes
Simon Sapin <simon.sapin@octobus.net>
parents: 48196
diff changeset
   745
            nanoseconds: 0.into(),
308d9c245337 dirstate-v2: Add storage space for nanoseconds precision in file mtimes
Simon Sapin <simon.sapin@octobus.net>
parents: 48196
diff changeset
   746
        }
308d9c245337 dirstate-v2: Add storage space for nanoseconds precision in file mtimes
Simon Sapin <simon.sapin@octobus.net>
parents: 48196
diff changeset
   747
    }
308d9c245337 dirstate-v2: Add storage space for nanoseconds precision in file mtimes
Simon Sapin <simon.sapin@octobus.net>
parents: 48196
diff changeset
   748
}