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::error::CommandError; |
8 use crate::error::CommandError; |
9 use crate::ui::Ui; |
9 use crate::ui::{ |
|
10 format_pattern_file_warning, print_narrow_sparse_warnings, Ui, |
|
11 }; |
10 use crate::utils::path_utils::RelativizePaths; |
12 use crate::utils::path_utils::RelativizePaths; |
11 use clap::Arg; |
13 use clap::Arg; |
12 use format_bytes::format_bytes; |
14 use format_bytes::format_bytes; |
13 use hg::config::Config; |
15 use hg::config::Config; |
14 use hg::dirstate::has_exec_bit; |
16 use hg::dirstate::has_exec_bit; |
18 use hg::lock::LockError; |
20 use hg::lock::LockError; |
19 use hg::manifest::Manifest; |
21 use hg::manifest::Manifest; |
20 use hg::matchers::{AlwaysMatcher, IntersectionMatcher}; |
22 use hg::matchers::{AlwaysMatcher, IntersectionMatcher}; |
21 use hg::repo::Repo; |
23 use hg::repo::Repo; |
22 use hg::utils::files::get_bytes_from_os_string; |
24 use hg::utils::files::get_bytes_from_os_string; |
23 use hg::utils::files::get_bytes_from_path; |
|
24 use hg::utils::files::get_path_from_bytes; |
25 use hg::utils::files::get_path_from_bytes; |
25 use hg::utils::hg_path::{hg_path_to_path_buf, HgPath}; |
26 use hg::utils::hg_path::{hg_path_to_path_buf, HgPath}; |
26 use hg::DirstateStatus; |
27 use hg::DirstateStatus; |
27 use hg::PatternFileWarning; |
28 use hg::PatternFileWarning; |
28 use hg::StatusError; |
29 use hg::StatusError; |
267 Result<(DirstateStatus<'a>, Vec<PatternFileWarning>), StatusError>; |
268 Result<(DirstateStatus<'a>, Vec<PatternFileWarning>), StatusError>; |
268 |
269 |
269 let after_status = |res: StatusResult| -> Result<_, CommandError> { |
270 let after_status = |res: StatusResult| -> Result<_, CommandError> { |
270 let (mut ds_status, pattern_warnings) = res?; |
271 let (mut ds_status, pattern_warnings) = res?; |
271 for warning in pattern_warnings { |
272 for warning in pattern_warnings { |
272 ui.write_stderr(&print_pattern_file_warning(&warning, repo))?; |
273 ui.write_stderr(&format_pattern_file_warning(&warning, repo))?; |
273 } |
274 } |
274 |
275 |
275 for (path, error) in ds_status.bad { |
276 for (path, error) in ds_status.bad { |
276 let error = match error { |
277 let error = match error { |
277 hg::BadMatch::OsError(code) => { |
278 hg::BadMatch::OsError(code) => { |
383 (true, false) => narrow_matcher, |
384 (true, false) => narrow_matcher, |
384 (false, true) => sparse_matcher, |
385 (false, true) => sparse_matcher, |
385 (false, false) => Box::new(AlwaysMatcher), |
386 (false, false) => Box::new(AlwaysMatcher), |
386 }; |
387 }; |
387 |
388 |
388 for warning in narrow_warnings.into_iter().chain(sparse_warnings) { |
389 print_narrow_sparse_warnings( |
389 match &warning { |
390 &narrow_warnings, |
390 sparse::SparseWarning::RootWarning { context, line } => { |
391 &sparse_warnings, |
391 let msg = format_bytes!( |
392 ui, |
392 b"warning: {} profile cannot use paths \" |
393 repo, |
393 starting with /, ignoring {}\n", |
394 )?; |
394 context, |
|
395 line |
|
396 ); |
|
397 ui.write_stderr(&msg)?; |
|
398 } |
|
399 sparse::SparseWarning::ProfileNotFound { profile, rev } => { |
|
400 let msg = format_bytes!( |
|
401 b"warning: sparse profile '{}' not found \" |
|
402 in rev {} - ignoring it\n", |
|
403 profile, |
|
404 rev |
|
405 ); |
|
406 ui.write_stderr(&msg)?; |
|
407 } |
|
408 sparse::SparseWarning::Pattern(e) => { |
|
409 ui.write_stderr(&print_pattern_file_warning(e, repo))?; |
|
410 } |
|
411 } |
|
412 } |
|
413 let (fixup, mut dirstate_write_needed, filesystem_time_at_status_start) = |
395 let (fixup, mut dirstate_write_needed, filesystem_time_at_status_start) = |
414 dmap.with_status( |
396 dmap.with_status( |
415 matcher.as_ref(), |
397 matcher.as_ref(), |
416 repo.working_directory_path().to_owned(), |
398 repo.working_directory_path().to_owned(), |
417 ignore_files(repo, config), |
399 ignore_files(repo, config), |
615 } else { |
597 } else { |
616 vfs.read(fs_path)? |
598 vfs.read(fs_path)? |
617 }; |
599 }; |
618 Ok(p1_contents != &*fs_contents) |
600 Ok(p1_contents != &*fs_contents) |
619 } |
601 } |
620 |
|
621 fn print_pattern_file_warning( |
|
622 warning: &PatternFileWarning, |
|
623 repo: &Repo, |
|
624 ) -> Vec<u8> { |
|
625 match warning { |
|
626 PatternFileWarning::InvalidSyntax(path, syntax) => format_bytes!( |
|
627 b"{}: ignoring invalid syntax '{}'\n", |
|
628 get_bytes_from_path(path), |
|
629 &*syntax |
|
630 ), |
|
631 PatternFileWarning::NoSuchFile(path) => { |
|
632 let path = if let Ok(relative) = |
|
633 path.strip_prefix(repo.working_directory_path()) |
|
634 { |
|
635 relative |
|
636 } else { |
|
637 &*path |
|
638 }; |
|
639 format_bytes!( |
|
640 b"skipping unreadable pattern file '{}': \ |
|
641 No such file or directory\n", |
|
642 get_bytes_from_path(path), |
|
643 ) |
|
644 } |
|
645 } |
|
646 } |
|