##// END OF EJS Templates
rhg: centralize parsing of `--rev` CLI arguments...
Simon Sapin -
r47162:4b381dbb default
parent child Browse files
Show More
@@ -0,0 +1,53 b''
1 //! The revset query language
2 //!
3 //! <https://www.mercurial-scm.org/repo/hg/help/revsets>
4
5 use crate::repo::Repo;
6 use crate::revlog::changelog::Changelog;
7 use crate::revlog::revlog::{Revlog, RevlogError};
8 use crate::revlog::NodePrefix;
9 use crate::revlog::{Revision, NULL_REVISION};
10
11 /// Resolve a query string into a single revision.
12 ///
13 /// Only some of the revset language is implemented yet.
14 pub fn resolve_single(
15 input: &str,
16 repo: &Repo,
17 ) -> Result<Revision, RevlogError> {
18 let changelog = Changelog::open(repo)?;
19
20 match resolve_rev_number_or_hex_prefix(input, &changelog.revlog) {
21 Err(RevlogError::InvalidRevision) => {} // Try other syntax
22 result => return result,
23 }
24
25 if input == "null" {
26 return Ok(NULL_REVISION);
27 }
28
29 // TODO: support for the rest of the language here.
30
31 Err(RevlogError::InvalidRevision)
32 }
33
34 /// Resolve the small subset of the language suitable for revlogs other than
35 /// the changelog, such as in `hg debugdata --manifest` CLI argument.
36 ///
37 /// * A non-negative decimal integer for a revision number, or
38 /// * An hexadecimal string, for the unique node ID that starts with this
39 /// prefix
40 pub fn resolve_rev_number_or_hex_prefix(
41 input: &str,
42 revlog: &Revlog,
43 ) -> Result<Revision, RevlogError> {
44 if let Ok(integer) = input.parse::<i32>() {
45 if integer >= 0 && revlog.has_rev(integer) {
46 return Ok(integer);
47 }
48 }
49 if let Ok(prefix) = NodePrefix::from_hex(input) {
50 return revlog.get_node_rev(prefix);
51 }
52 Err(RevlogError::InvalidRevision)
53 }
@@ -28,6 +28,7 b' pub mod revlog;'
28 28 pub use revlog::*;
29 29 pub mod config;
30 30 pub mod operations;
31 pub mod revset;
31 32 pub mod utils;
32 33
33 34 use crate::utils::hg_path::{HgPathBuf, HgPathError};
@@ -15,8 +15,6 b' use crate::revlog::path_encode::path_enc'
15 15 use crate::revlog::revlog::Revlog;
16 16 use crate::revlog::revlog::RevlogError;
17 17 use crate::revlog::Node;
18 use crate::revlog::NodePrefix;
19 use crate::revlog::Revision;
20 18 use crate::utils::files::get_path_from_bytes;
21 19 use crate::utils::hg_path::{HgPath, HgPathBuf};
22 20
@@ -77,23 +75,15 b' impl From<RevlogError> for CatRevError {'
77 75 /// * `files`: The files to output.
78 76 pub fn cat(
79 77 repo: &Repo,
80 rev: &str,
78 revset: &str,
81 79 files: &[HgPathBuf],
82 80 ) -> Result<Vec<u8>, CatRevError> {
81 let rev = crate::revset::resolve_single(revset, repo)?;
83 82 let changelog = Changelog::open(repo)?;
84 83 let manifest = Manifest::open(repo)?;
85
86 let changelog_entry = match rev.parse::<Revision>() {
87 Ok(rev) => changelog.get_rev(rev)?,
88 _ => {
89 let changelog_node = NodePrefix::from_hex(&rev)
90 .map_err(|_| CatRevErrorKind::InvalidRevision)?;
91 changelog.get_node(changelog_node)?
92 }
93 };
84 let changelog_entry = changelog.get_rev(rev)?;
94 85 let manifest_node = Node::from_hex(&changelog_entry.manifest_node()?)
95 86 .map_err(|_| CatRevErrorKind::CorruptedRevlog)?;
96
97 87 let manifest_entry = manifest.get_node(manifest_node.into())?;
98 88 let mut bytes = vec![];
99 89
@@ -7,8 +7,6 b''
7 7
8 8 use crate::repo::Repo;
9 9 use crate::revlog::revlog::{Revlog, RevlogError};
10 use crate::revlog::NodePrefix;
11 use crate::revlog::Revision;
12 10
13 11 /// Kind of data to debug
14 12 #[derive(Debug, Copy, Clone)]
@@ -79,7 +77,7 b' impl From<RevlogError> for DebugDataErro'
79 77 /// Dump the contents data of a revision.
80 78 pub fn debug_data(
81 79 repo: &Repo,
82 rev: &str,
80 revset: &str,
83 81 kind: DebugDataKind,
84 82 ) -> Result<Vec<u8>, DebugDataError> {
85 83 let index_file = match kind {
@@ -87,16 +85,8 b' pub fn debug_data('
87 85 DebugDataKind::Manifest => "00manifest.i",
88 86 };
89 87 let revlog = Revlog::open(repo, index_file, None)?;
90
91 let data = match rev.parse::<Revision>() {
92 Ok(rev) => revlog.get_rev_data(rev)?,
93 _ => {
94 let node = NodePrefix::from_hex(&rev)
95 .map_err(|_| DebugDataErrorKind::InvalidRevision)?;
96 let rev = revlog.get_node_rev(node)?;
97 revlog.get_rev_data(rev)?
98 }
99 };
100
88 let rev =
89 crate::revset::resolve_rev_number_or_hex_prefix(revset, &revlog)?;
90 let data = revlog.get_rev_data(rev)?;
101 91 Ok(data)
102 92 }
@@ -9,9 +9,8 b' use crate::dirstate::parsers::parse_dirs'
9 9 use crate::repo::Repo;
10 10 use crate::revlog::changelog::Changelog;
11 11 use crate::revlog::manifest::{Manifest, ManifestEntry};
12 use crate::revlog::node::{Node, NodePrefix};
12 use crate::revlog::node::Node;
13 13 use crate::revlog::revlog::RevlogError;
14 use crate::revlog::Revision;
15 14 use crate::utils::hg_path::HgPath;
16 15 use crate::{DirstateParseError, EntryState};
17 16 use rayon::prelude::*;
@@ -137,19 +136,12 b' impl From<RevlogError> for ListRevTracke'
137 136 /// List files under Mercurial control at a given revision.
138 137 pub fn list_rev_tracked_files(
139 138 repo: &Repo,
140 rev: &str,
139 revset: &str,
141 140 ) -> Result<FilesForRev, ListRevTrackedFilesError> {
141 let rev = crate::revset::resolve_single(revset, repo)?;
142 142 let changelog = Changelog::open(repo)?;
143 143 let manifest = Manifest::open(repo)?;
144
145 let changelog_entry = match rev.parse::<Revision>() {
146 Ok(rev) => changelog.get_rev(rev)?,
147 _ => {
148 let changelog_node = NodePrefix::from_hex(&rev)
149 .or(Err(ListRevTrackedFilesErrorKind::InvalidRevision))?;
150 changelog.get_node(changelog_node)?
151 }
152 };
144 let changelog_entry = changelog.get_rev(rev)?;
153 145 let manifest_node = Node::from_hex(&changelog_entry.manifest_node()?)
154 146 .or(Err(ListRevTrackedFilesErrorKind::CorruptedRevlog))?;
155 147 let manifest_entry = manifest.get_node(manifest_node.into())?;
@@ -6,7 +6,7 b' use crate::revlog::Revision;'
6 6 /// A specialized `Revlog` to work with `changelog` data format.
7 7 pub struct Changelog {
8 8 /// The generic `revlog` format.
9 revlog: Revlog,
9 pub(crate) revlog: Revlog,
10 10 }
11 11
12 12 impl Changelog {
@@ -150,6 +150,11 b' impl Revlog {'
150 150 found_by_prefix.ok_or(RevlogError::InvalidRevision)
151 151 }
152 152
153 /// Returns whether the given revision exists in this revlog.
154 pub fn has_rev(&self, rev: Revision) -> bool {
155 self.index.get_entry(rev).is_some()
156 }
157
153 158 /// Return the full data associated to a revision.
154 159 ///
155 160 /// All entries required to build the final data out of deltas will be
General Comments 0
You need to be logged in to leave comments. Login now