rust/hg-core/src/update.rs
author Rapha?l Gom?s <rgomes@octobus.net>
Tue, 05 Nov 2024 15:21:09 +0100
branchstable
changeset 52186 e6a44bc91bc2
parent 52056 8b7123c8947b
child 52213 96b113d22b34
permissions -rw-r--r--
rust-update: make `update_from_null` respect `worker.numcpu` config option This was overlooked in the original series. This is important for tests (because we run many at once), and for the occasional end user that wants to keep their CPU usage in check. A future series should clean up this `worker` parameter tunelling business by rewriting the config in Rust, but doing so on stable would be a very bad idea.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
52056
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
     1
//! Tools for moving the repository to a given revision
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
     2
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
     3
use std::{
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
     4
    fs::Permissions,
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
     5
    io::Write,
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
     6
    os::unix::fs::{MetadataExt, PermissionsExt},
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
     7
    path::Path,
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
     8
    time::Duration,
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
     9
};
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    10
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    11
use crate::{
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    12
    dirstate::{ParentFileData, TruncatedTimestamp},
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    13
    dirstate_tree::{
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    14
        dirstate_map::DirstateEntryReset, on_disk::write_tracked_key,
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    15
    },
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    16
    errors::{HgError, IoResultExt},
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    17
    exit_codes,
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    18
    filelog::Filelog,
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    19
    narrow,
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    20
    node::NULL_NODE,
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    21
    operations::{list_rev_tracked_files, ExpandedManifestEntry},
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    22
    progress::Progress,
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    23
    repo::Repo,
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    24
    sparse,
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    25
    utils::{
52186
e6a44bc91bc2 rust-update: make `update_from_null` respect `worker.numcpu` config option
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52056
diff changeset
    26
        cap_default_rayon_threads,
52056
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    27
        files::{filesystem_now, get_path_from_bytes},
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    28
        hg_path::{hg_path_to_path_buf, HgPath, HgPathError},
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    29
        path_auditor::PathAuditor,
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    30
    },
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    31
    vfs::{is_on_nfs_mount, VfsImpl},
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    32
    DirstateParents, RevlogError, RevlogOpenOptions, UncheckedRevision,
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    33
};
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    34
use crossbeam_channel::{Receiver, Sender};
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    35
use rayon::prelude::*;
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    36
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    37
fn write_dirstate(repo: &Repo) -> Result<(), HgError> {
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    38
    repo.write_dirstate()
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    39
        .map_err(|e| HgError::abort(e.to_string(), exit_codes::ABORT, None))?;
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    40
    write_tracked_key(repo)
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    41
}
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    42
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    43
/// Update the current working copy of `repo` to the given revision `to`, from
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    44
/// the null revision and set + write out the dirstate to reflect that.
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    45
///
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    46
/// Do not call this outside of a Python context. This does *not* handle any
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    47
/// of the checks, hooks, lock taking needed to setup and get out of this
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    48
/// update from the null revision.
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    49
pub fn update_from_null(
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    50
    repo: &Repo,
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    51
    to: UncheckedRevision,
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    52
    progress: &dyn Progress,
52186
e6a44bc91bc2 rust-update: make `update_from_null` respect `worker.numcpu` config option
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52056
diff changeset
    53
    workers: Option<usize>,
52056
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    54
) -> Result<usize, HgError> {
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    55
    // Ignore the warnings, they've been displayed by Python already
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    56
    // TODO non-Python clients: display narrow warnings
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    57
    let (narrow_matcher, _) = narrow::matcher(repo)?;
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    58
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    59
    let files_for_rev = list_rev_tracked_files(repo, to, narrow_matcher)
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    60
        .map_err(handle_revlog_error)?;
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    61
    repo.manually_set_parents(DirstateParents {
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    62
        p1: repo.node(to).expect("update target should exist"),
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    63
        p2: NULL_NODE,
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    64
    })?;
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    65
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    66
    // Filter the working copy according to the sparse spec
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    67
    let tracked_files: Result<Vec<_>, _> = if !repo.has_sparse() {
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    68
        files_for_rev.iter().collect()
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    69
    } else {
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    70
        // Ignore the warnings, they've been displayed by Python already
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    71
        // TODO non-Python clients: display sparse warnings
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    72
        let (sparse_matcher, _) = sparse::matcher(repo)?;
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    73
        files_for_rev
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    74
            .iter()
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    75
            .filter(|f| {
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    76
                match f {
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    77
                    Ok(f) => sparse_matcher.matches(f.0),
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    78
                    Err(_) => true, // Errors stop the update, include them
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    79
                }
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    80
            })
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    81
            .collect()
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    82
    };
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    83
    let tracked_files = tracked_files?;
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    84
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    85
    if tracked_files.is_empty() {
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    86
        // Still write the dirstate because we might not be in the null
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    87
        // revision.
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    88
        // This can happen in narrow repos where all paths are excluded in
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    89
        // this revision.
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    90
        write_dirstate(repo)?;
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    91
        return Ok(0);
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    92
    }
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    93
    let store_vfs = &repo.store_vfs();
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    94
    let options = repo.default_revlog_options(crate::RevlogType::Filelog)?;
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    95
    let (errors_sender, errors_receiver) = crossbeam_channel::unbounded();
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    96
    let (files_sender, files_receiver) = crossbeam_channel::unbounded();
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    97
    let working_directory_path = &repo.working_directory_path();
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    98
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    99
    let files_count = tracked_files.len();
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   100
    let chunks = chunk_tracked_files(tracked_files);
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   101
    progress.update(0, Some(files_count as u64));
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   102
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   103
    create_working_copy(
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   104
        chunks,
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   105
        working_directory_path,
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   106
        store_vfs,
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   107
        options,
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   108
        files_sender,
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   109
        errors_sender,
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   110
        progress,
52186
e6a44bc91bc2 rust-update: make `update_from_null` respect `worker.numcpu` config option
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52056
diff changeset
   111
        workers,
52056
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   112
    );
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   113
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   114
    let errors: Vec<HgError> = errors_receiver.iter().collect();
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   115
    if !errors.is_empty() {
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   116
        log::debug!("{} errors during update (see trace logs)", errors.len());
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   117
        for error in errors.iter() {
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   118
            log::trace!("{}", error);
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   119
        }
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   120
        // Best we can do is raise the first error (in order of the channel)
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   121
        return Err(errors.into_iter().next().expect("can never be empty"));
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   122
    }
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   123
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   124
    // TODO try to run this concurrently to update the dirstate while we're
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   125
    // still writing out the working copy to see if that improves performance.
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   126
    let total = update_dirstate(repo, files_receiver)?;
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   127
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   128
    write_dirstate(repo)?;
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   129
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   130
    Ok(total)
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   131
}
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   132
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   133
fn handle_revlog_error(e: RevlogError) -> HgError {
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   134
    match e {
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   135
        crate::RevlogError::Other(hg_error) => hg_error,
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   136
        e => HgError::abort(
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   137
            format!("revlog error: {}", e),
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   138
            exit_codes::ABORT,
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   139
            None,
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   140
        ),
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   141
    }
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   142
}
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   143
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   144
/// Preallocated size of Vec holding directory contents. This aims at
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   145
/// preventing the need for re-allocating the Vec in most cases.
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   146
///
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   147
/// The value is arbitrarily picked as a little over an average number of files
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   148
/// per directory done by looking at a few larger open-source repos.
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   149
/// Most of the runtime is IO anyway, so this doesn't matter too much.
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   150
const FILES_PER_DIRECTORY: usize = 16;
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   151
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   152
/// Chunk files per directory prefix, so almost every directory is handled
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   153
/// in a separate thread, which works around the FS inode mutex.
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   154
/// Chunking less (and doing approximately `files_count`/`threads`) actually
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   155
/// ends up being less performant: my hypothesis is `rayon`'s work stealing
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   156
/// being more efficient with tasks of varying lengths.
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   157
#[logging_timer::time("trace")]
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   158
fn chunk_tracked_files(
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   159
    tracked_files: Vec<ExpandedManifestEntry>,
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   160
) -> Vec<(&HgPath, Vec<ExpandedManifestEntry>)> {
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   161
    let files_count = tracked_files.len();
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   162
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   163
    let mut chunks = Vec::with_capacity(files_count / FILES_PER_DIRECTORY);
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   164
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   165
    let mut current_chunk = Vec::with_capacity(FILES_PER_DIRECTORY);
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   166
    let mut last_directory = tracked_files[0].0.parent();
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   167
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   168
    for file_info in tracked_files {
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   169
        let current_directory = file_info.0.parent();
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   170
        let different_directory = current_directory != last_directory;
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   171
        if different_directory {
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   172
            chunks.push((last_directory, current_chunk));
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   173
            current_chunk = Vec::with_capacity(FILES_PER_DIRECTORY);
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   174
        }
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   175
        current_chunk.push(file_info);
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   176
        last_directory = current_directory;
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   177
    }
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   178
    chunks.push((last_directory, current_chunk));
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   179
    chunks
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   180
}
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   181
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   182
#[logging_timer::time("trace")]
52186
e6a44bc91bc2 rust-update: make `update_from_null` respect `worker.numcpu` config option
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52056
diff changeset
   183
#[allow(clippy::too_many_arguments)]
52056
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   184
fn create_working_copy<'a: 'b, 'b>(
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   185
    chunks: Vec<(&HgPath, Vec<ExpandedManifestEntry<'a>>)>,
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   186
    working_directory_path: &Path,
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   187
    store_vfs: &VfsImpl,
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   188
    options: RevlogOpenOptions,
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   189
    files_sender: Sender<(&'b HgPath, u32, usize, TruncatedTimestamp)>,
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   190
    error_sender: Sender<HgError>,
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   191
    progress: &dyn Progress,
52186
e6a44bc91bc2 rust-update: make `update_from_null` respect `worker.numcpu` config option
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52056
diff changeset
   192
    workers: Option<usize>,
52056
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   193
) {
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   194
    let auditor = PathAuditor::new(working_directory_path);
52186
e6a44bc91bc2 rust-update: make `update_from_null` respect `worker.numcpu` config option
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52056
diff changeset
   195
    let work_closure = |(dir_path, chunk)| {
52056
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   196
        if let Err(e) = working_copy_worker(
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   197
            dir_path,
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   198
            chunk,
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   199
            working_directory_path,
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   200
            store_vfs,
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   201
            options,
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   202
            &files_sender,
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   203
            progress,
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   204
            &auditor,
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   205
        ) {
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   206
            error_sender
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   207
                .send(e)
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   208
                .expect("channel should not be disconnected")
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   209
        }
52186
e6a44bc91bc2 rust-update: make `update_from_null` respect `worker.numcpu` config option
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52056
diff changeset
   210
    };
e6a44bc91bc2 rust-update: make `update_from_null` respect `worker.numcpu` config option
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52056
diff changeset
   211
    if let Some(workers) = workers {
e6a44bc91bc2 rust-update: make `update_from_null` respect `worker.numcpu` config option
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52056
diff changeset
   212
        if workers > 1 {
e6a44bc91bc2 rust-update: make `update_from_null` respect `worker.numcpu` config option
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52056
diff changeset
   213
            // Work in parallel, potentially restricting the number of threads
e6a44bc91bc2 rust-update: make `update_from_null` respect `worker.numcpu` config option
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52056
diff changeset
   214
            match rayon::ThreadPoolBuilder::new().num_threads(workers).build()
e6a44bc91bc2 rust-update: make `update_from_null` respect `worker.numcpu` config option
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52056
diff changeset
   215
            {
e6a44bc91bc2 rust-update: make `update_from_null` respect `worker.numcpu` config option
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52056
diff changeset
   216
                Err(error) => error_sender
e6a44bc91bc2 rust-update: make `update_from_null` respect `worker.numcpu` config option
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52056
diff changeset
   217
                    .send(HgError::abort(
e6a44bc91bc2 rust-update: make `update_from_null` respect `worker.numcpu` config option
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52056
diff changeset
   218
                        error.to_string(),
e6a44bc91bc2 rust-update: make `update_from_null` respect `worker.numcpu` config option
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52056
diff changeset
   219
                        exit_codes::ABORT,
e6a44bc91bc2 rust-update: make `update_from_null` respect `worker.numcpu` config option
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52056
diff changeset
   220
                        None,
e6a44bc91bc2 rust-update: make `update_from_null` respect `worker.numcpu` config option
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52056
diff changeset
   221
                    ))
e6a44bc91bc2 rust-update: make `update_from_null` respect `worker.numcpu` config option
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52056
diff changeset
   222
                    .expect("channel should not be disconnected"),
e6a44bc91bc2 rust-update: make `update_from_null` respect `worker.numcpu` config option
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52056
diff changeset
   223
                Ok(pool) => {
e6a44bc91bc2 rust-update: make `update_from_null` respect `worker.numcpu` config option
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52056
diff changeset
   224
                    log::trace!("restricting update to {} threads", workers);
e6a44bc91bc2 rust-update: make `update_from_null` respect `worker.numcpu` config option
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52056
diff changeset
   225
                    pool.install(|| {
e6a44bc91bc2 rust-update: make `update_from_null` respect `worker.numcpu` config option
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52056
diff changeset
   226
                        chunks.into_par_iter().for_each(work_closure);
e6a44bc91bc2 rust-update: make `update_from_null` respect `worker.numcpu` config option
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52056
diff changeset
   227
                    });
e6a44bc91bc2 rust-update: make `update_from_null` respect `worker.numcpu` config option
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52056
diff changeset
   228
                }
e6a44bc91bc2 rust-update: make `update_from_null` respect `worker.numcpu` config option
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52056
diff changeset
   229
            }
e6a44bc91bc2 rust-update: make `update_from_null` respect `worker.numcpu` config option
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52056
diff changeset
   230
        } else {
e6a44bc91bc2 rust-update: make `update_from_null` respect `worker.numcpu` config option
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52056
diff changeset
   231
            // Work sequentially, don't even invoke rayon
e6a44bc91bc2 rust-update: make `update_from_null` respect `worker.numcpu` config option
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52056
diff changeset
   232
            chunks.into_iter().for_each(work_closure);
e6a44bc91bc2 rust-update: make `update_from_null` respect `worker.numcpu` config option
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52056
diff changeset
   233
        }
e6a44bc91bc2 rust-update: make `update_from_null` respect `worker.numcpu` config option
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52056
diff changeset
   234
    } else {
e6a44bc91bc2 rust-update: make `update_from_null` respect `worker.numcpu` config option
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52056
diff changeset
   235
        // Work in parallel by default in the global threadpool
e6a44bc91bc2 rust-update: make `update_from_null` respect `worker.numcpu` config option
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52056
diff changeset
   236
        let _ = cap_default_rayon_threads();
e6a44bc91bc2 rust-update: make `update_from_null` respect `worker.numcpu` config option
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52056
diff changeset
   237
        chunks.into_par_iter().for_each(work_closure);
e6a44bc91bc2 rust-update: make `update_from_null` respect `worker.numcpu` config option
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52056
diff changeset
   238
    }
52056
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   239
}
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   240
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   241
/// Represents a work unit for a single thread, responsible for this set of
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   242
/// files and restoring them to the working copy.
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   243
#[allow(clippy::too_many_arguments)]
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   244
fn working_copy_worker<'a: 'b, 'b>(
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   245
    dir_path: &HgPath,
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   246
    chunk: Vec<ExpandedManifestEntry<'a>>,
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   247
    working_directory_path: &Path,
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   248
    store_vfs: &VfsImpl,
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   249
    options: RevlogOpenOptions,
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   250
    files_sender: &Sender<(&'b HgPath, u32, usize, TruncatedTimestamp)>,
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   251
    progress: &dyn Progress,
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   252
    auditor: &PathAuditor,
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   253
) -> Result<(), HgError> {
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   254
    let dir_path =
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   255
        hg_path_to_path_buf(dir_path).expect("invalid path in manifest");
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   256
    let dir_path = working_directory_path.join(dir_path);
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   257
    std::fs::create_dir_all(&dir_path).when_writing_file(&dir_path)?;
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   258
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   259
    for (file, file_node, flags) in chunk {
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   260
        auditor.audit_path(file)?;
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   261
        let flags = flags.map(|f| f.into());
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   262
        let path =
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   263
            working_directory_path.join(get_path_from_bytes(file.as_bytes()));
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   264
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   265
        // Treemanifest is not supported
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   266
        assert!(flags != Some(b't'));
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   267
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   268
        let filelog = Filelog::open_vfs(store_vfs, file, options)?;
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   269
        let filelog_revision_data = &filelog
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   270
            .data_for_node(file_node)
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   271
            .map_err(handle_revlog_error)?;
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   272
        let file_data = filelog_revision_data.file_data()?;
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   273
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   274
        if flags == Some(b'l') {
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   275
            let target = get_path_from_bytes(file_data);
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   276
            if let Err(e) = std::os::unix::fs::symlink(target, &path) {
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   277
                // If the path already exists either:
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   278
                //   - another process created this file while ignoring the
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   279
                //     lock => error
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   280
                //   - our check for the fast path is incorrect => error
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   281
                //   - this is a malicious repo/bundle and this is symlink that
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   282
                //     tries to write things where it shouldn't be able to.
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   283
                match e.kind() {
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   284
                    std::io::ErrorKind::AlreadyExists => {
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   285
                        let metadata = std::fs::symlink_metadata(&path)
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   286
                            .when_reading_file(&path)?;
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   287
                        if metadata.is_dir() {
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   288
                            return Err(HgError::Path(
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   289
                                HgPathError::TraversesSymbolicLink {
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   290
                                    // Technically it should be one of the
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   291
                                    // children, but good enough
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   292
                                    path: file
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   293
                                        .join(HgPath::new(b"*"))
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   294
                                        .to_owned(),
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   295
                                    symlink: file.to_owned(),
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   296
                                },
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   297
                            ));
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   298
                        }
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   299
                        return Err(e).when_writing_file(&path);
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   300
                    }
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   301
                    _ => return Err(e).when_writing_file(&path),
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   302
                }
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   303
            }
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   304
        } else {
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   305
            let mut f =
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   306
                std::fs::File::create(&path).when_writing_file(&path)?;
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   307
            f.write_all(file_data).when_writing_file(&path)?;
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   308
        }
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   309
        if flags == Some(b'x') {
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   310
            std::fs::set_permissions(&path, Permissions::from_mode(0o755))
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   311
                .when_writing_file(&path)?;
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   312
        }
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   313
        let metadata =
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   314
            std::fs::symlink_metadata(&path).when_reading_file(&path)?;
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   315
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   316
        let mode = metadata.mode();
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   317
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   318
        files_sender
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   319
            .send((
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   320
                file,
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   321
                mode,
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   322
                file_data.len(),
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   323
                TruncatedTimestamp::for_mtime_of(&metadata)
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   324
                    .when_reading_file(&path)?,
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   325
            ))
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   326
            .expect("channel should not be closed");
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   327
        progress.increment(1, None);
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   328
    }
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   329
    Ok(())
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   330
}
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   331
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   332
#[logging_timer::time("trace")]
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   333
fn update_dirstate(
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   334
    repo: &Repo,
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   335
    files_receiver: Receiver<(&HgPath, u32, usize, TruncatedTimestamp)>,
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   336
) -> Result<usize, HgError> {
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   337
    let mut dirstate = repo
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   338
        .dirstate_map_mut()
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   339
        .map_err(|e| HgError::abort(e.to_string(), exit_codes::ABORT, None))?;
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   340
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   341
    // (see the comments in `filter_ambiguous_files` in `merge.py` for more)
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   342
    // It turns out that (on Linux at least) the filesystem resolution time
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   343
    // for most filesystems is based on the HZ kernel config. Their internal
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   344
    // clocks do return nanoseconds if the hardware clock is precise enough,
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   345
    // which should be the case on most recent computers but are only updated
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   346
    // every few milliseconds at best (every "jiffy").
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   347
    //
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   348
    // We are still not concerned with fixing the race with other
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   349
    // processes that might modify the working copy right after it was created
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   350
    // within the same tick, because it is impossible to catch.
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   351
    // However, we might as well not race with operations that could run right
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   352
    // after this one, especially other Mercurial operations that could be
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   353
    // waiting for the wlock to change file contents and the dirstate.
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   354
    //
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   355
    // Thus: wait until the filesystem clock has ticked to filter ambiguous
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   356
    // entries and write the dirstate, but only for dirstate-v2, since v1 only
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   357
    // has second-level granularity and waiting for a whole second is too much
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   358
    // of a penalty in the general case.
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   359
    // Although we're assuming that people running dirstate-v2 on Linux
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   360
    // don't have a second-granularity FS (with the exclusion of NFS), users
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   361
    // can be surprising, and at some point in the future dirstate-v2 will
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   362
    // become the default. To that end, we limit the wait time to 100ms and
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   363
    // fall back to the filter method in case of a timeout.
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   364
    //
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   365
    // +------------+------+--------------+
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   366
    // |   version  | wait | filter level |
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   367
    // +------------+------+--------------+
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   368
    // |     V1     | No   | Second       |
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   369
    // |     V2     | Yes  | Nanosecond   |
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   370
    // | V2-slow-fs | No   | Second       |
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   371
    // +------------+------+--------------+
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   372
    let dirstate_v2 = repo.use_dirstate_v2();
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   373
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   374
    // Let's ignore NFS right off the bat
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   375
    let mut fast_enough_fs = !is_on_nfs_mount(repo.working_directory_path());
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   376
    let fs_time_now = if dirstate_v2 && fast_enough_fs {
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   377
        match wait_until_fs_tick(repo.working_directory_path()) {
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   378
            None => None,
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   379
            Some(Ok(time)) => Some(time),
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   380
            Some(Err(time)) => {
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   381
                fast_enough_fs = false;
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   382
                Some(time)
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   383
            }
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   384
        }
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   385
    } else {
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   386
        filesystem_now(repo.working_directory_path())
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   387
            .ok()
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   388
            .map(TruncatedTimestamp::from)
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   389
    };
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   390
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   391
    let mut total = 0;
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   392
    for (filename, mode, size, mtime) in files_receiver.into_iter() {
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   393
        total += 1;
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   394
        // When using dirstate-v2 on a filesystem with reasonable performance
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   395
        // this is basically always true unless you get a mtime from the
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   396
        // far future.
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   397
        let has_meaningful_mtime = if let Some(fs_time) = fs_time_now {
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   398
            mtime.for_reliable_mtime_of_self(&fs_time).is_some_and(|t| {
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   399
                // Dirstate-v1 only has second-level information
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   400
                !t.second_ambiguous || dirstate_v2 && fast_enough_fs
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   401
            })
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   402
        } else {
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   403
            // We somehow failed to write to the filesystem, so don't store
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   404
            // the cache information.
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   405
            false
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   406
        };
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   407
        let reset = DirstateEntryReset {
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   408
            filename,
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   409
            wc_tracked: true,
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   410
            p1_tracked: true,
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   411
            p2_info: false,
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   412
            has_meaningful_mtime,
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   413
            parent_file_data_opt: Some(ParentFileData {
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   414
                mode_size: Some((
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   415
                    mode,
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   416
                    size.try_into().expect("invalid file size in manifest"),
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   417
                )),
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   418
                mtime: Some(mtime),
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   419
            }),
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   420
            from_empty: true,
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   421
        };
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   422
        dirstate.reset_state(reset).map_err(|e| {
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   423
            HgError::abort(e.to_string(), exit_codes::ABORT, None)
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   424
        })?;
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   425
    }
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   426
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   427
    Ok(total)
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   428
}
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   429
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   430
/// Wait until the next update from the filesystem time by writing in a loop
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   431
/// a new temporary file inside the working directory and checking if its time
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   432
/// differs from the first one observed.
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   433
///
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   434
/// Returns `None` if we are unable to get the filesystem time,
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   435
/// `Some(Err(timestamp))` if we've timed out waiting for the filesystem clock
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   436
/// to tick, and `Some(Ok(timestamp))` if we've waited successfully.
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   437
///
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   438
/// On Linux, your average tick is going to be a "jiffy", or 1/HZ.
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   439
/// HZ is your kernel's tick rate (if it has one configured) and the value
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   440
/// is the one returned by `grep 'CONFIG_HZ=' /boot/config-$(uname -r)`,
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   441
/// again assuming a normal setup.
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   442
///
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   443
/// In my case (Alphare) at the time of writing, I get `CONFIG_HZ=250`,
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   444
/// which equates to 4ms.
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   445
///
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   446
/// This might change with a series that could make it to Linux 6.12:
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   447
/// https://lore.kernel.org/all/20241002-mgtime-v10-8-d1c4717f5284@kernel.org
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   448
fn wait_until_fs_tick(
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   449
    working_directory_path: &Path,
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   450
) -> Option<Result<TruncatedTimestamp, TruncatedTimestamp>> {
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   451
    let start = std::time::Instant::now();
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   452
    let old_fs_time = filesystem_now(working_directory_path).ok()?;
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   453
    let mut fs_time = filesystem_now(working_directory_path).ok()?;
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   454
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   455
    const FS_TICK_WAIT_TIMEOUT: Duration = Duration::from_millis(100);
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   456
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   457
    while fs_time == old_fs_time {
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   458
        if std::time::Instant::now() - start > FS_TICK_WAIT_TIMEOUT {
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   459
            log::trace!(
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   460
                "timed out waiting for the fs clock to tick after {:?}",
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   461
                FS_TICK_WAIT_TIMEOUT
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   462
            );
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   463
            return Some(Err(TruncatedTimestamp::from(old_fs_time)));
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   464
        }
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   465
        fs_time = filesystem_now(working_directory_path).ok()?;
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   466
    }
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   467
    log::trace!(
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   468
        "waited for {:?} before writing the dirstate",
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   469
        fs_time.duration_since(old_fs_time)
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   470
    );
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   471
    Some(Ok(TruncatedTimestamp::from(fs_time)))
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   472
}
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   473
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   474
#[cfg(test)]
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   475
mod test {
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   476
    use super::*;
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   477
    use pretty_assertions::assert_eq;
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   478
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   479
    #[test]
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   480
    fn test_chunk_tracked_files() {
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   481
        fn chunk(v: Vec<&'static str>) -> Vec<ExpandedManifestEntry> {
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   482
            v.into_iter()
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   483
                .map(|f| (HgPath::new(f.as_bytes()), NULL_NODE, None))
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   484
                .collect()
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   485
        }
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   486
        let p = HgPath::new;
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   487
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   488
        let files = chunk(vec!["a"]);
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   489
        let expected = vec![(p(""), chunk(vec!["a"]))];
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   490
        assert_eq!(chunk_tracked_files(files), expected);
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   491
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   492
        let files = chunk(vec!["a", "b", "c"]);
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   493
        let expected = vec![(p(""), chunk(vec!["a", "b", "c"]))];
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   494
        assert_eq!(chunk_tracked_files(files), expected);
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   495
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   496
        let files = chunk(vec![
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   497
            "dir/a-new",
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   498
            "dir/a/mut",
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   499
            "dir/a/mut-mut",
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   500
            "dir/albert",
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   501
            "dir/b",
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   502
            "dir/subdir/c",
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   503
            "dir/subdir/d",
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   504
            "file",
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   505
        ]);
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   506
        let expected = vec![
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   507
            (p("dir"), chunk(vec!["dir/a-new"])),
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   508
            (p("dir/a"), chunk(vec!["dir/a/mut", "dir/a/mut-mut"])),
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   509
            (p("dir"), chunk(vec!["dir/albert", "dir/b"])),
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   510
            (p("dir/subdir"), chunk(vec!["dir/subdir/c", "dir/subdir/d"])),
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   511
            (p(""), chunk(vec!["file"])),
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   512
        ];
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   513
        assert_eq!(chunk_tracked_files(files), expected);
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   514
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   515
        // Doesn't get split
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   516
        let large_dir = vec![
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   517
            "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12",
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   518
            "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23",
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   519
        ];
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   520
        let files = chunk(large_dir.clone());
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   521
        let expected = vec![(p(""), chunk(large_dir))];
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   522
        assert_eq!(chunk_tracked_files(files), expected);
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   523
    }
8b7123c8947b update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   524
}