comparison rust/rhg/src/commands/status.rs @ 47956:81aedf1fc897

rust: Add Repo::dirstate_map and use it in `rhg status` This moves low-level dirstate wrangling out of the status command and into a more reusable location. The open dirstate map is lazily initialized and kept on the Repo object, for reuse by sub-sequent calls. Differential Revision: https://phab.mercurial-scm.org/D11398
author Simon Sapin <simon.sapin@octobus.net>
date Thu, 09 Sep 2021 21:04:55 +0200
parents 78f7f0d490ee
children 796206e74b10
comparison
equal deleted inserted replaced
47955:e834b79def74 47956:81aedf1fc897
7 7
8 use crate::error::CommandError; 8 use crate::error::CommandError;
9 use crate::ui::Ui; 9 use crate::ui::Ui;
10 use clap::{Arg, SubCommand}; 10 use clap::{Arg, SubCommand};
11 use hg; 11 use hg;
12 use hg::dirstate_tree::dirstate_map::DirstateMap; 12 use hg::dirstate_tree::dispatch::DirstateMapMethods;
13 use hg::dirstate_tree::on_disk;
14 use hg::errors::HgResultExt;
15 use hg::errors::IoResultExt; 13 use hg::errors::IoResultExt;
16 use hg::matchers::AlwaysMatcher; 14 use hg::matchers::AlwaysMatcher;
17 use hg::operations::cat; 15 use hg::operations::cat;
18 use hg::repo::Repo; 16 use hg::repo::Repo;
19 use hg::revlog::node::Node; 17 use hg::revlog::node::Node;
164 requested 162 requested
165 } 163 }
166 }; 164 };
167 165
168 let repo = invocation.repo?; 166 let repo = invocation.repo?;
169 let dirstate_data_mmap; 167 let mut dmap = repo.dirstate_map_mut()?;
170 let (mut dmap, parents) = if repo.has_dirstate_v2() {
171 let docket_data =
172 repo.hg_vfs().read("dirstate").io_not_found_as_none()?;
173 let parents;
174 let dirstate_data;
175 let data_size;
176 let docket;
177 let tree_metadata;
178 if let Some(docket_data) = &docket_data {
179 docket = on_disk::read_docket(docket_data)?;
180 tree_metadata = docket.tree_metadata();
181 parents = Some(docket.parents());
182 data_size = docket.data_size();
183 dirstate_data_mmap = repo
184 .hg_vfs()
185 .mmap_open(docket.data_filename())
186 .io_not_found_as_none()?;
187 dirstate_data = dirstate_data_mmap.as_deref().unwrap_or(b"");
188 } else {
189 parents = None;
190 tree_metadata = b"";
191 data_size = 0;
192 dirstate_data = b"";
193 }
194 let dmap =
195 DirstateMap::new_v2(dirstate_data, data_size, tree_metadata)?;
196 (dmap, parents)
197 } else {
198 dirstate_data_mmap =
199 repo.hg_vfs().mmap_open("dirstate").io_not_found_as_none()?;
200 let dirstate_data = dirstate_data_mmap.as_deref().unwrap_or(b"");
201 DirstateMap::new_v1(dirstate_data)?
202 };
203 168
204 let options = StatusOptions { 169 let options = StatusOptions {
205 // TODO should be provided by the dirstate parsing and 170 // TODO should be provided by the dirstate parsing and
206 // hence be stored on dmap. Using a value that assumes we aren't 171 // hence be stored on dmap. Using a value that assumes we aren't
207 // below the time resolution granularity of the FS and the 172 // below the time resolution granularity of the FS and the
214 list_unknown: display_states.unknown, 179 list_unknown: display_states.unknown,
215 list_ignored: display_states.ignored, 180 list_ignored: display_states.ignored,
216 collect_traversed_dirs: false, 181 collect_traversed_dirs: false,
217 }; 182 };
218 let ignore_file = repo.working_directory_vfs().join(".hgignore"); // TODO hardcoded 183 let ignore_file = repo.working_directory_vfs().join(".hgignore"); // TODO hardcoded
219 let (mut ds_status, pattern_warnings) = hg::dirstate_tree::status::status( 184 let (mut ds_status, pattern_warnings) = dmap.status(
220 &mut dmap,
221 &AlwaysMatcher, 185 &AlwaysMatcher,
222 repo.working_directory_path().to_owned(), 186 repo.working_directory_path().to_owned(),
223 vec![ignore_file], 187 vec![ignore_file],
224 options, 188 options,
225 )?; 189 )?;
237 ); 201 );
238 } 202 }
239 if !ds_status.unsure.is_empty() 203 if !ds_status.unsure.is_empty()
240 && (display_states.modified || display_states.clean) 204 && (display_states.modified || display_states.clean)
241 { 205 {
242 let p1: Node = parents 206 let p1: Node = repo.dirstate_parents()?.p1.into();
243 .expect(
244 "Dirstate with no parents should not list any file to
245 be rechecked for modifications",
246 )
247 .p1
248 .into();
249 let p1_hex = format!("{:x}", p1); 207 let p1_hex = format!("{:x}", p1);
250 for to_check in ds_status.unsure { 208 for to_check in ds_status.unsure {
251 if cat_file_is_modified(repo, &to_check, &p1_hex)? { 209 if cat_file_is_modified(repo, &to_check, &p1_hex)? {
252 if display_states.modified { 210 if display_states.modified {
253 ds_status.modified.push(to_check); 211 ds_status.modified.push(to_check);