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