comparison rust/hg-core/src/operations/list_tracked_files.rs @ 45536:639f33f22faf

hg-core: add a `ListRevTrackedFiles` operation List files tracked at a given revision. Differential Revision: https://phab.mercurial-scm.org/D9014
author Antoine Cezar <antoine.cezar@octobus.net>
date Fri, 18 Sep 2020 16:52:16 +0200
parents 72b7d58d6e35
children be951ca95b08
comparison
equal deleted inserted replaced
45535:72b7d58d6e35 45536:639f33f22faf
4 // 4 //
5 // This software may be used and distributed according to the terms of the 5 // This software may be used and distributed according to the terms of the
6 // GNU General Public License version 2 or any later version. 6 // GNU General Public License version 2 or any later version.
7 7
8 use crate::dirstate::parsers::parse_dirstate; 8 use crate::dirstate::parsers::parse_dirstate;
9 use crate::revlog::changelog::Changelog;
10 use crate::revlog::manifest::{Manifest, ManifestEntry};
11 use crate::revlog::revlog::RevlogError;
12 use crate::revlog::Revision;
9 use crate::utils::hg_path::HgPath; 13 use crate::utils::hg_path::HgPath;
10 use crate::{DirstateParseError, EntryState}; 14 use crate::{DirstateParseError, EntryState};
11 use rayon::prelude::*; 15 use rayon::prelude::*;
12 use std::convert::From; 16 use std::convert::From;
13 use std::fmt;
14 use std::fs; 17 use std::fs;
15 use std::ops::Deref; 18 use std::path::PathBuf;
16 use std::path::{Path, PathBuf};
17 19
18 /// Kind of error encountered by `ListDirstateTrackedFiles` 20 /// Kind of error encountered by `ListDirstateTrackedFiles`
19 #[derive(Debug)] 21 #[derive(Debug)]
20 pub enum ListDirstateTrackedFilesErrorKind { 22 pub enum ListDirstateTrackedFilesErrorKind {
21 /// Error when reading the `dirstate` file 23 /// Error when reading the `dirstate` file
27 /// A `ListDirstateTrackedFiles` error 29 /// A `ListDirstateTrackedFiles` error
28 #[derive(Debug)] 30 #[derive(Debug)]
29 pub struct ListDirstateTrackedFilesError { 31 pub struct ListDirstateTrackedFilesError {
30 /// Kind of error encountered by `ListDirstateTrackedFiles` 32 /// Kind of error encountered by `ListDirstateTrackedFiles`
31 pub kind: ListDirstateTrackedFilesErrorKind, 33 pub kind: ListDirstateTrackedFilesErrorKind,
32 }
33
34 impl std::error::Error for ListDirstateTrackedFilesError {}
35
36 impl fmt::Display for ListDirstateTrackedFilesError {
37 fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
38 unimplemented!()
39 }
40 } 34 }
41 35
42 impl From<ListDirstateTrackedFilesErrorKind> 36 impl From<ListDirstateTrackedFilesErrorKind>
43 for ListDirstateTrackedFilesError 37 for ListDirstateTrackedFilesError
44 { 38 {
82 .collect(); 76 .collect();
83 files.par_sort_unstable(); 77 files.par_sort_unstable();
84 Ok(files) 78 Ok(files)
85 } 79 }
86 } 80 }
81
82 /// Kind of error encountered by `ListRevTrackedFiles`
83 #[derive(Debug)]
84 pub enum ListRevTrackedFilesErrorKind {
85 /// Error when reading a `revlog` file.
86 IoError(std::io::Error),
87 /// The revision has not been found.
88 InvalidRevision,
89 /// A `revlog` file is corrupted.
90 CorruptedRevlog,
91 /// The `revlog` format version is not supported.
92 UnsuportedRevlogVersion(u16),
93 /// The `revlog` data format is not supported.
94 UnknowRevlogDataFormat(u8),
95 }
96
97 /// A `ListRevTrackedFiles` error
98 #[derive(Debug)]
99 pub struct ListRevTrackedFilesError {
100 /// Kind of error encountered by `ListRevTrackedFiles`
101 pub kind: ListRevTrackedFilesErrorKind,
102 }
103
104 impl From<ListRevTrackedFilesErrorKind> for ListRevTrackedFilesError {
105 fn from(kind: ListRevTrackedFilesErrorKind) -> Self {
106 ListRevTrackedFilesError { kind }
107 }
108 }
109
110 impl From<RevlogError> for ListRevTrackedFilesError {
111 fn from(err: RevlogError) -> Self {
112 match err {
113 RevlogError::IoError(err) => {
114 ListRevTrackedFilesErrorKind::IoError(err)
115 }
116 RevlogError::UnsuportedVersion(version) => {
117 ListRevTrackedFilesErrorKind::UnsuportedRevlogVersion(version)
118 }
119 RevlogError::InvalidRevision => {
120 ListRevTrackedFilesErrorKind::InvalidRevision
121 }
122 RevlogError::Corrupted => {
123 ListRevTrackedFilesErrorKind::CorruptedRevlog
124 }
125 RevlogError::UnknowDataFormat(format) => {
126 ListRevTrackedFilesErrorKind::UnknowRevlogDataFormat(format)
127 }
128 }
129 .into()
130 }
131 }
132
133 /// List files under Mercurial control at a given revision.
134 pub struct ListRevTrackedFiles<'a> {
135 /// The revision to list the files from.
136 rev: &'a str,
137 /// The changelog file
138 changelog: Changelog,
139 /// The manifest file
140 manifest: Manifest,
141 /// The manifest entry corresponding to the revision.
142 ///
143 /// Used to hold the owner of the returned references.
144 manifest_entry: Option<ManifestEntry>,
145 }
146
147 impl<'a> ListRevTrackedFiles<'a> {
148 pub fn new(
149 root: &PathBuf,
150 rev: &'a str,
151 ) -> Result<Self, ListRevTrackedFilesError> {
152 let changelog = Changelog::open(&root)?;
153 let manifest = Manifest::open(&root)?;
154
155 Ok(Self {
156 rev,
157 changelog,
158 manifest,
159 manifest_entry: None,
160 })
161 }
162
163 pub fn run(
164 &mut self,
165 ) -> Result<impl Iterator<Item = &HgPath>, ListRevTrackedFilesError> {
166 let changelog_entry = match self.rev.parse::<Revision>() {
167 Ok(rev) => self.changelog.get_rev(rev)?,
168 _ => {
169 let changelog_node = hex::decode(&self.rev).map_err(|_| {
170 ListRevTrackedFilesErrorKind::InvalidRevision
171 })?;
172 self.changelog.get_node(&changelog_node)?
173 }
174 };
175 let manifest_node = hex::decode(&changelog_entry.manifest_node()?)
176 .map_err(|_| ListRevTrackedFilesErrorKind::CorruptedRevlog)?;
177
178 self.manifest_entry = Some(self.manifest.get_node(&manifest_node)?);
179
180 if let Some(ref manifest_entry) = self.manifest_entry {
181 Ok(manifest_entry.files())
182 } else {
183 panic!(
184 "manifest entry should have been stored in self.manifest_node to ensure its lifetime since references are returned from it"
185 )
186 }
187 }
188 }