##// 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 pub use revlog::*;
28 pub use revlog::*;
29 pub mod config;
29 pub mod config;
30 pub mod operations;
30 pub mod operations;
31 pub mod revset;
31 pub mod utils;
32 pub mod utils;
32
33
33 use crate::utils::hg_path::{HgPathBuf, HgPathError};
34 use crate::utils::hg_path::{HgPathBuf, HgPathError};
@@ -15,8 +15,6 b' use crate::revlog::path_encode::path_enc'
15 use crate::revlog::revlog::Revlog;
15 use crate::revlog::revlog::Revlog;
16 use crate::revlog::revlog::RevlogError;
16 use crate::revlog::revlog::RevlogError;
17 use crate::revlog::Node;
17 use crate::revlog::Node;
18 use crate::revlog::NodePrefix;
19 use crate::revlog::Revision;
20 use crate::utils::files::get_path_from_bytes;
18 use crate::utils::files::get_path_from_bytes;
21 use crate::utils::hg_path::{HgPath, HgPathBuf};
19 use crate::utils::hg_path::{HgPath, HgPathBuf};
22
20
@@ -77,23 +75,15 b' impl From<RevlogError> for CatRevError {'
77 /// * `files`: The files to output.
75 /// * `files`: The files to output.
78 pub fn cat(
76 pub fn cat(
79 repo: &Repo,
77 repo: &Repo,
80 rev: &str,
78 revset: &str,
81 files: &[HgPathBuf],
79 files: &[HgPathBuf],
82 ) -> Result<Vec<u8>, CatRevError> {
80 ) -> Result<Vec<u8>, CatRevError> {
81 let rev = crate::revset::resolve_single(revset, repo)?;
83 let changelog = Changelog::open(repo)?;
82 let changelog = Changelog::open(repo)?;
84 let manifest = Manifest::open(repo)?;
83 let manifest = Manifest::open(repo)?;
85
84 let changelog_entry = changelog.get_rev(rev)?;
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 };
94 let manifest_node = Node::from_hex(&changelog_entry.manifest_node()?)
85 let manifest_node = Node::from_hex(&changelog_entry.manifest_node()?)
95 .map_err(|_| CatRevErrorKind::CorruptedRevlog)?;
86 .map_err(|_| CatRevErrorKind::CorruptedRevlog)?;
96
97 let manifest_entry = manifest.get_node(manifest_node.into())?;
87 let manifest_entry = manifest.get_node(manifest_node.into())?;
98 let mut bytes = vec![];
88 let mut bytes = vec![];
99
89
@@ -7,8 +7,6 b''
7
7
8 use crate::repo::Repo;
8 use crate::repo::Repo;
9 use crate::revlog::revlog::{Revlog, RevlogError};
9 use crate::revlog::revlog::{Revlog, RevlogError};
10 use crate::revlog::NodePrefix;
11 use crate::revlog::Revision;
12
10
13 /// Kind of data to debug
11 /// Kind of data to debug
14 #[derive(Debug, Copy, Clone)]
12 #[derive(Debug, Copy, Clone)]
@@ -79,7 +77,7 b' impl From<RevlogError> for DebugDataErro'
79 /// Dump the contents data of a revision.
77 /// Dump the contents data of a revision.
80 pub fn debug_data(
78 pub fn debug_data(
81 repo: &Repo,
79 repo: &Repo,
82 rev: &str,
80 revset: &str,
83 kind: DebugDataKind,
81 kind: DebugDataKind,
84 ) -> Result<Vec<u8>, DebugDataError> {
82 ) -> Result<Vec<u8>, DebugDataError> {
85 let index_file = match kind {
83 let index_file = match kind {
@@ -87,16 +85,8 b' pub fn debug_data('
87 DebugDataKind::Manifest => "00manifest.i",
85 DebugDataKind::Manifest => "00manifest.i",
88 };
86 };
89 let revlog = Revlog::open(repo, index_file, None)?;
87 let revlog = Revlog::open(repo, index_file, None)?;
90
88 let rev =
91 let data = match rev.parse::<Revision>() {
89 crate::revset::resolve_rev_number_or_hex_prefix(revset, &revlog)?;
92 Ok(rev) => revlog.get_rev_data(rev)?,
90 let data = 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
101 Ok(data)
91 Ok(data)
102 }
92 }
@@ -9,9 +9,8 b' use crate::dirstate::parsers::parse_dirs'
9 use crate::repo::Repo;
9 use crate::repo::Repo;
10 use crate::revlog::changelog::Changelog;
10 use crate::revlog::changelog::Changelog;
11 use crate::revlog::manifest::{Manifest, ManifestEntry};
11 use crate::revlog::manifest::{Manifest, ManifestEntry};
12 use crate::revlog::node::{Node, NodePrefix};
12 use crate::revlog::node::Node;
13 use crate::revlog::revlog::RevlogError;
13 use crate::revlog::revlog::RevlogError;
14 use crate::revlog::Revision;
15 use crate::utils::hg_path::HgPath;
14 use crate::utils::hg_path::HgPath;
16 use crate::{DirstateParseError, EntryState};
15 use crate::{DirstateParseError, EntryState};
17 use rayon::prelude::*;
16 use rayon::prelude::*;
@@ -137,19 +136,12 b' impl From<RevlogError> for ListRevTracke'
137 /// List files under Mercurial control at a given revision.
136 /// List files under Mercurial control at a given revision.
138 pub fn list_rev_tracked_files(
137 pub fn list_rev_tracked_files(
139 repo: &Repo,
138 repo: &Repo,
140 rev: &str,
139 revset: &str,
141 ) -> Result<FilesForRev, ListRevTrackedFilesError> {
140 ) -> Result<FilesForRev, ListRevTrackedFilesError> {
141 let rev = crate::revset::resolve_single(revset, repo)?;
142 let changelog = Changelog::open(repo)?;
142 let changelog = Changelog::open(repo)?;
143 let manifest = Manifest::open(repo)?;
143 let manifest = Manifest::open(repo)?;
144
144 let changelog_entry = changelog.get_rev(rev)?;
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 };
153 let manifest_node = Node::from_hex(&changelog_entry.manifest_node()?)
145 let manifest_node = Node::from_hex(&changelog_entry.manifest_node()?)
154 .or(Err(ListRevTrackedFilesErrorKind::CorruptedRevlog))?;
146 .or(Err(ListRevTrackedFilesErrorKind::CorruptedRevlog))?;
155 let manifest_entry = manifest.get_node(manifest_node.into())?;
147 let manifest_entry = manifest.get_node(manifest_node.into())?;
@@ -6,7 +6,7 b' use crate::revlog::Revision;'
6 /// A specialized `Revlog` to work with `changelog` data format.
6 /// A specialized `Revlog` to work with `changelog` data format.
7 pub struct Changelog {
7 pub struct Changelog {
8 /// The generic `revlog` format.
8 /// The generic `revlog` format.
9 revlog: Revlog,
9 pub(crate) revlog: Revlog,
10 }
10 }
11
11
12 impl Changelog {
12 impl Changelog {
@@ -150,6 +150,11 b' impl Revlog {'
150 found_by_prefix.ok_or(RevlogError::InvalidRevision)
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 /// Return the full data associated to a revision.
158 /// Return the full data associated to a revision.
154 ///
159 ///
155 /// All entries required to build the final data out of deltas will be
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