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 |
|
|
|
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:: |
|
|
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