rust/hg-core/src/operations/cat.rs
author Simon Sapin <simon.sapin@octobus.net>
Mon, 13 Sep 2021 13:01:25 +0200
changeset 47985 d44740725b95
parent 46757 b1f2c2b336ec
child 47987 21d25e9ee58e
permissions -rw-r--r--
rust: Rename Manifest to Manifestlog, ManifestEntry to Manifest This appears to match the terminology used in Python code and on https://www.mercurial-scm.org/wiki/Manifest Differential Revision: https://phab.mercurial-scm.org/D11404
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
45547
522ec3dc44b9 hg-core: add a `CatRev` operation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
     1
// list_tracked_files.rs
522ec3dc44b9 hg-core: add a `CatRev` operation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
     2
//
522ec3dc44b9 hg-core: add a `CatRev` operation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
     3
// Copyright 2020 Antoine Cezar <antoine.cezar@octobus.net>
522ec3dc44b9 hg-core: add a `CatRev` operation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
     4
//
522ec3dc44b9 hg-core: add a `CatRev` operation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
     5
// This software may be used and distributed according to the terms of the
522ec3dc44b9 hg-core: add a `CatRev` operation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
     6
// GNU General Public License version 2 or any later version.
522ec3dc44b9 hg-core: add a `CatRev` operation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
     7
46167
8a4914397d02 rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents: 46136
diff changeset
     8
use std::path::PathBuf;
45547
522ec3dc44b9 hg-core: add a `CatRev` operation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
     9
46167
8a4914397d02 rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents: 46136
diff changeset
    10
use crate::repo::Repo;
45547
522ec3dc44b9 hg-core: add a `CatRev` operation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    11
use crate::revlog::changelog::Changelog;
47985
d44740725b95 rust: Rename Manifest to Manifestlog, ManifestEntry to Manifest
Simon Sapin <simon.sapin@octobus.net>
parents: 46757
diff changeset
    12
use crate::revlog::manifest::Manifestlog;
45547
522ec3dc44b9 hg-core: add a `CatRev` operation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    13
use crate::revlog::path_encode::path_encode;
522ec3dc44b9 hg-core: add a `CatRev` operation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    14
use crate::revlog::revlog::Revlog;
522ec3dc44b9 hg-core: add a `CatRev` operation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    15
use crate::revlog::revlog::RevlogError;
46037
88e741bf2d93 rust: use NodePrefix::from_hex instead of hex::decode directly
Simon Sapin <simon-commits@exyr.org>
parents: 46036
diff changeset
    16
use crate::revlog::Node;
45825
7252f5237352 hg-core: fix path encoding usage
Antoine cezar<acezar@chwitlabs.fr>
parents: 45823
diff changeset
    17
use crate::utils::files::get_path_from_bytes;
7252f5237352 hg-core: fix path encoding usage
Antoine cezar<acezar@chwitlabs.fr>
parents: 45823
diff changeset
    18
use crate::utils::hg_path::{HgPath, HgPathBuf};
45547
522ec3dc44b9 hg-core: add a `CatRev` operation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    19
46757
b1f2c2b336ec rhg: `cat` command: print error messages for missing files
Simon Sapin <simon.sapin@octobus.net>
parents: 46511
diff changeset
    20
pub struct CatOutput {
b1f2c2b336ec rhg: `cat` command: print error messages for missing files
Simon Sapin <simon.sapin@octobus.net>
parents: 46511
diff changeset
    21
    /// Whether any file in the manifest matched the paths given as CLI
b1f2c2b336ec rhg: `cat` command: print error messages for missing files
Simon Sapin <simon.sapin@octobus.net>
parents: 46511
diff changeset
    22
    /// arguments
b1f2c2b336ec rhg: `cat` command: print error messages for missing files
Simon Sapin <simon.sapin@octobus.net>
parents: 46511
diff changeset
    23
    pub found_any: bool,
b1f2c2b336ec rhg: `cat` command: print error messages for missing files
Simon Sapin <simon.sapin@octobus.net>
parents: 46511
diff changeset
    24
    /// The contents of matching files, in manifest order
b1f2c2b336ec rhg: `cat` command: print error messages for missing files
Simon Sapin <simon.sapin@octobus.net>
parents: 46511
diff changeset
    25
    pub concatenated: Vec<u8>,
b1f2c2b336ec rhg: `cat` command: print error messages for missing files
Simon Sapin <simon.sapin@octobus.net>
parents: 46511
diff changeset
    26
    /// Which of the CLI arguments did not match any manifest file
b1f2c2b336ec rhg: `cat` command: print error messages for missing files
Simon Sapin <simon.sapin@octobus.net>
parents: 46511
diff changeset
    27
    pub missing: Vec<HgPathBuf>,
b1f2c2b336ec rhg: `cat` command: print error messages for missing files
Simon Sapin <simon.sapin@octobus.net>
parents: 46511
diff changeset
    28
    /// The node ID that the given revset was resolved to
b1f2c2b336ec rhg: `cat` command: print error messages for missing files
Simon Sapin <simon.sapin@octobus.net>
parents: 46511
diff changeset
    29
    pub node: Node,
b1f2c2b336ec rhg: `cat` command: print error messages for missing files
Simon Sapin <simon.sapin@octobus.net>
parents: 46511
diff changeset
    30
}
b1f2c2b336ec rhg: `cat` command: print error messages for missing files
Simon Sapin <simon.sapin@octobus.net>
parents: 46511
diff changeset
    31
45823
6991f3014311 rhg: strip copied files metadata from `cat` output
Antoine cezar<acezar@chwitlabs.fr>
parents: 45547
diff changeset
    32
const METADATA_DELIMITER: [u8; 2] = [b'\x01', b'\n'];
6991f3014311 rhg: strip copied files metadata from `cat` output
Antoine cezar<acezar@chwitlabs.fr>
parents: 45547
diff changeset
    33
46757
b1f2c2b336ec rhg: `cat` command: print error messages for missing files
Simon Sapin <simon.sapin@octobus.net>
parents: 46511
diff changeset
    34
/// Output the given revision of files
46136
dca9cb99971c rust: replace most "operation" structs with functions
Simon Sapin <simon.sapin@octobus.net>
parents: 46135
diff changeset
    35
///
dca9cb99971c rust: replace most "operation" structs with functions
Simon Sapin <simon.sapin@octobus.net>
parents: 46135
diff changeset
    36
/// * `root`: Repository root
dca9cb99971c rust: replace most "operation" structs with functions
Simon Sapin <simon.sapin@octobus.net>
parents: 46135
diff changeset
    37
/// * `rev`: The revision to cat the files from.
dca9cb99971c rust: replace most "operation" structs with functions
Simon Sapin <simon.sapin@octobus.net>
parents: 46135
diff changeset
    38
/// * `files`: The files to output.
46757
b1f2c2b336ec rhg: `cat` command: print error messages for missing files
Simon Sapin <simon.sapin@octobus.net>
parents: 46511
diff changeset
    39
pub fn cat<'a>(
46167
8a4914397d02 rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents: 46136
diff changeset
    40
    repo: &Repo,
46501
4b381dbbf8b7 rhg: centralize parsing of `--rev` CLI arguments
Simon Sapin <simon.sapin@octobus.net>
parents: 46499
diff changeset
    41
    revset: &str,
46757
b1f2c2b336ec rhg: `cat` command: print error messages for missing files
Simon Sapin <simon.sapin@octobus.net>
parents: 46511
diff changeset
    42
    files: &'a [HgPathBuf],
b1f2c2b336ec rhg: `cat` command: print error messages for missing files
Simon Sapin <simon.sapin@octobus.net>
parents: 46511
diff changeset
    43
) -> Result<CatOutput, RevlogError> {
46501
4b381dbbf8b7 rhg: centralize parsing of `--rev` CLI arguments
Simon Sapin <simon.sapin@octobus.net>
parents: 46499
diff changeset
    44
    let rev = crate::revset::resolve_single(revset, repo)?;
46167
8a4914397d02 rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents: 46136
diff changeset
    45
    let changelog = Changelog::open(repo)?;
47985
d44740725b95 rust: Rename Manifest to Manifestlog, ManifestEntry to Manifest
Simon Sapin <simon.sapin@octobus.net>
parents: 46757
diff changeset
    46
    let manifest = Manifestlog::open(repo)?;
46501
4b381dbbf8b7 rhg: centralize parsing of `--rev` CLI arguments
Simon Sapin <simon.sapin@octobus.net>
parents: 46499
diff changeset
    47
    let changelog_entry = changelog.get_rev(rev)?;
46757
b1f2c2b336ec rhg: `cat` command: print error messages for missing files
Simon Sapin <simon.sapin@octobus.net>
parents: 46511
diff changeset
    48
    let node = *changelog
b1f2c2b336ec rhg: `cat` command: print error messages for missing files
Simon Sapin <simon.sapin@octobus.net>
parents: 46511
diff changeset
    49
        .node_from_rev(rev)
b1f2c2b336ec rhg: `cat` command: print error messages for missing files
Simon Sapin <simon.sapin@octobus.net>
parents: 46511
diff changeset
    50
        .expect("should succeed when changelog.get_rev did");
46511
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46505
diff changeset
    51
    let manifest_node =
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46505
diff changeset
    52
        Node::from_hex_for_repo(&changelog_entry.manifest_node()?)?;
46499
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46167
diff changeset
    53
    let manifest_entry = manifest.get_node(manifest_node.into())?;
46136
dca9cb99971c rust: replace most "operation" structs with functions
Simon Sapin <simon.sapin@octobus.net>
parents: 46135
diff changeset
    54
    let mut bytes = vec![];
46757
b1f2c2b336ec rhg: `cat` command: print error messages for missing files
Simon Sapin <simon.sapin@octobus.net>
parents: 46511
diff changeset
    55
    let mut matched = vec![false; files.len()];
b1f2c2b336ec rhg: `cat` command: print error messages for missing files
Simon Sapin <simon.sapin@octobus.net>
parents: 46511
diff changeset
    56
    let mut found_any = false;
45547
522ec3dc44b9 hg-core: add a `CatRev` operation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    57
46136
dca9cb99971c rust: replace most "operation" structs with functions
Simon Sapin <simon.sapin@octobus.net>
parents: 46135
diff changeset
    58
    for (manifest_file, node_bytes) in manifest_entry.files_with_nodes() {
46757
b1f2c2b336ec rhg: `cat` command: print error messages for missing files
Simon Sapin <simon.sapin@octobus.net>
parents: 46511
diff changeset
    59
        for (cat_file, is_matched) in files.iter().zip(&mut matched) {
46136
dca9cb99971c rust: replace most "operation" structs with functions
Simon Sapin <simon.sapin@octobus.net>
parents: 46135
diff changeset
    60
            if cat_file.as_bytes() == manifest_file.as_bytes() {
46757
b1f2c2b336ec rhg: `cat` command: print error messages for missing files
Simon Sapin <simon.sapin@octobus.net>
parents: 46511
diff changeset
    61
                *is_matched = true;
b1f2c2b336ec rhg: `cat` command: print error messages for missing files
Simon Sapin <simon.sapin@octobus.net>
parents: 46511
diff changeset
    62
                found_any = true;
46167
8a4914397d02 rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents: 46136
diff changeset
    63
                let index_path = store_path(manifest_file, b".i");
8a4914397d02 rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents: 46136
diff changeset
    64
                let data_path = store_path(manifest_file, b".d");
45547
522ec3dc44b9 hg-core: add a `CatRev` operation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    65
46167
8a4914397d02 rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents: 46136
diff changeset
    66
                let file_log =
8a4914397d02 rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents: 46136
diff changeset
    67
                    Revlog::open(repo, &index_path, Some(&data_path))?;
46511
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46505
diff changeset
    68
                let file_node = Node::from_hex_for_repo(node_bytes)?;
46499
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46167
diff changeset
    69
                let file_rev = file_log.get_node_rev(file_node.into())?;
46136
dca9cb99971c rust: replace most "operation" structs with functions
Simon Sapin <simon.sapin@octobus.net>
parents: 46135
diff changeset
    70
                let data = file_log.get_rev_data(file_rev)?;
dca9cb99971c rust: replace most "operation" structs with functions
Simon Sapin <simon.sapin@octobus.net>
parents: 46135
diff changeset
    71
                if data.starts_with(&METADATA_DELIMITER) {
dca9cb99971c rust: replace most "operation" structs with functions
Simon Sapin <simon.sapin@octobus.net>
parents: 46135
diff changeset
    72
                    let end_delimiter_position = data
dca9cb99971c rust: replace most "operation" structs with functions
Simon Sapin <simon.sapin@octobus.net>
parents: 46135
diff changeset
    73
                        [METADATA_DELIMITER.len()..]
dca9cb99971c rust: replace most "operation" structs with functions
Simon Sapin <simon.sapin@octobus.net>
parents: 46135
diff changeset
    74
                        .windows(METADATA_DELIMITER.len())
dca9cb99971c rust: replace most "operation" structs with functions
Simon Sapin <simon.sapin@octobus.net>
parents: 46135
diff changeset
    75
                        .position(|bytes| bytes == METADATA_DELIMITER);
dca9cb99971c rust: replace most "operation" structs with functions
Simon Sapin <simon.sapin@octobus.net>
parents: 46135
diff changeset
    76
                    if let Some(position) = end_delimiter_position {
dca9cb99971c rust: replace most "operation" structs with functions
Simon Sapin <simon.sapin@octobus.net>
parents: 46135
diff changeset
    77
                        let offset = METADATA_DELIMITER.len() * 2;
dca9cb99971c rust: replace most "operation" structs with functions
Simon Sapin <simon.sapin@octobus.net>
parents: 46135
diff changeset
    78
                        bytes.extend(data[position + offset..].iter());
dca9cb99971c rust: replace most "operation" structs with functions
Simon Sapin <simon.sapin@octobus.net>
parents: 46135
diff changeset
    79
                    }
dca9cb99971c rust: replace most "operation" structs with functions
Simon Sapin <simon.sapin@octobus.net>
parents: 46135
diff changeset
    80
                } else {
dca9cb99971c rust: replace most "operation" structs with functions
Simon Sapin <simon.sapin@octobus.net>
parents: 46135
diff changeset
    81
                    bytes.extend(data);
dca9cb99971c rust: replace most "operation" structs with functions
Simon Sapin <simon.sapin@octobus.net>
parents: 46135
diff changeset
    82
                }
dca9cb99971c rust: replace most "operation" structs with functions
Simon Sapin <simon.sapin@octobus.net>
parents: 46135
diff changeset
    83
            }
dca9cb99971c rust: replace most "operation" structs with functions
Simon Sapin <simon.sapin@octobus.net>
parents: 46135
diff changeset
    84
        }
45547
522ec3dc44b9 hg-core: add a `CatRev` operation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    85
    }
522ec3dc44b9 hg-core: add a `CatRev` operation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    86
46757
b1f2c2b336ec rhg: `cat` command: print error messages for missing files
Simon Sapin <simon.sapin@octobus.net>
parents: 46511
diff changeset
    87
    let missing: Vec<_> = files
b1f2c2b336ec rhg: `cat` command: print error messages for missing files
Simon Sapin <simon.sapin@octobus.net>
parents: 46511
diff changeset
    88
        .iter()
b1f2c2b336ec rhg: `cat` command: print error messages for missing files
Simon Sapin <simon.sapin@octobus.net>
parents: 46511
diff changeset
    89
        .zip(&matched)
b1f2c2b336ec rhg: `cat` command: print error messages for missing files
Simon Sapin <simon.sapin@octobus.net>
parents: 46511
diff changeset
    90
        .filter(|pair| !*pair.1)
b1f2c2b336ec rhg: `cat` command: print error messages for missing files
Simon Sapin <simon.sapin@octobus.net>
parents: 46511
diff changeset
    91
        .map(|pair| pair.0.clone())
b1f2c2b336ec rhg: `cat` command: print error messages for missing files
Simon Sapin <simon.sapin@octobus.net>
parents: 46511
diff changeset
    92
        .collect();
b1f2c2b336ec rhg: `cat` command: print error messages for missing files
Simon Sapin <simon.sapin@octobus.net>
parents: 46511
diff changeset
    93
    Ok(CatOutput {
b1f2c2b336ec rhg: `cat` command: print error messages for missing files
Simon Sapin <simon.sapin@octobus.net>
parents: 46511
diff changeset
    94
        found_any,
b1f2c2b336ec rhg: `cat` command: print error messages for missing files
Simon Sapin <simon.sapin@octobus.net>
parents: 46511
diff changeset
    95
        concatenated: bytes,
b1f2c2b336ec rhg: `cat` command: print error messages for missing files
Simon Sapin <simon.sapin@octobus.net>
parents: 46511
diff changeset
    96
        missing,
b1f2c2b336ec rhg: `cat` command: print error messages for missing files
Simon Sapin <simon.sapin@octobus.net>
parents: 46511
diff changeset
    97
        node,
b1f2c2b336ec rhg: `cat` command: print error messages for missing files
Simon Sapin <simon.sapin@octobus.net>
parents: 46511
diff changeset
    98
    })
45547
522ec3dc44b9 hg-core: add a `CatRev` operation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
    99
}
45825
7252f5237352 hg-core: fix path encoding usage
Antoine cezar<acezar@chwitlabs.fr>
parents: 45823
diff changeset
   100
46167
8a4914397d02 rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents: 46136
diff changeset
   101
fn store_path(hg_path: &HgPath, suffix: &[u8]) -> PathBuf {
45825
7252f5237352 hg-core: fix path encoding usage
Antoine cezar<acezar@chwitlabs.fr>
parents: 45823
diff changeset
   102
    let encoded_bytes =
7252f5237352 hg-core: fix path encoding usage
Antoine cezar<acezar@chwitlabs.fr>
parents: 45823
diff changeset
   103
        path_encode(&[b"data/", hg_path.as_bytes(), suffix].concat());
46167
8a4914397d02 rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents: 46136
diff changeset
   104
    get_path_from_bytes(&encoded_bytes).into()
45825
7252f5237352 hg-core: fix path encoding usage
Antoine cezar<acezar@chwitlabs.fr>
parents: 45823
diff changeset
   105
}