Show More
@@ -366,6 +366,7 b' pub fn parse_one_pattern(' | |||
|
366 | 366 | pattern: &[u8], |
|
367 | 367 | source: &Path, |
|
368 | 368 | default: PatternSyntax, |
|
369 | normalize: bool, | |
|
369 | 370 | ) -> IgnorePattern { |
|
370 | 371 | let mut pattern_bytes: &[u8] = pattern; |
|
371 | 372 | let mut syntax = default; |
@@ -378,7 +379,19 b' pub fn parse_one_pattern(' | |||
|
378 | 379 | } |
|
379 | 380 | } |
|
380 | 381 | |
|
381 | let pattern = pattern_bytes.to_vec(); | |
|
382 | let pattern = match syntax { | |
|
383 | PatternSyntax::RootGlob | |
|
384 | | PatternSyntax::Path | |
|
385 | | PatternSyntax::Glob | |
|
386 | | PatternSyntax::RelGlob | |
|
387 | | PatternSyntax::RelPath | |
|
388 | | PatternSyntax::RootFiles | |
|
389 | if normalize => | |
|
390 | { | |
|
391 | normalize_path_bytes(pattern_bytes) | |
|
392 | } | |
|
393 | _ => pattern_bytes.to_vec(), | |
|
394 | }; | |
|
382 | 395 | |
|
383 | 396 | IgnorePattern { |
|
384 | 397 | syntax, |
@@ -438,6 +451,7 b' pub fn parse_pattern_file_contents(' | |||
|
438 | 451 | line, |
|
439 | 452 | file_path, |
|
440 | 453 | current_syntax.clone(), |
|
454 | false, | |
|
441 | 455 | ); |
|
442 | 456 | inputs.push(if relativize { |
|
443 | 457 | pattern.to_relative() |
@@ -449,6 +463,35 b' pub fn parse_pattern_file_contents(' | |||
|
449 | 463 | Ok((inputs, warnings)) |
|
450 | 464 | } |
|
451 | 465 | |
|
466 | pub fn parse_pattern_args( | |
|
467 | patterns: Vec<Vec<u8>>, | |
|
468 | cwd: &Path, | |
|
469 | root: &Path, | |
|
470 | ) -> Result<Vec<IgnorePattern>, HgPathError> { | |
|
471 | let mut ignore_patterns: Vec<IgnorePattern> = Vec::new(); | |
|
472 | for pattern in patterns { | |
|
473 | let pattern = parse_one_pattern( | |
|
474 | &pattern, | |
|
475 | Path::new("<args>"), | |
|
476 | PatternSyntax::RelPath, | |
|
477 | true, | |
|
478 | ); | |
|
479 | match pattern.syntax { | |
|
480 | PatternSyntax::RelGlob | PatternSyntax::RelPath => { | |
|
481 | let name = get_path_from_bytes(&pattern.pattern); | |
|
482 | let canon = canonical_path(root, cwd, name)?; | |
|
483 | ignore_patterns.push(IgnorePattern { | |
|
484 | syntax: pattern.syntax, | |
|
485 | pattern: get_bytes_from_path(canon), | |
|
486 | source: pattern.source, | |
|
487 | }) | |
|
488 | } | |
|
489 | _ => ignore_patterns.push(pattern.to_owned()), | |
|
490 | }; | |
|
491 | } | |
|
492 | Ok(ignore_patterns) | |
|
493 | } | |
|
494 | ||
|
452 | 495 | pub fn read_pattern_file( |
|
453 | 496 | file_path: &Path, |
|
454 | 497 | warn: bool, |
@@ -25,7 +25,7 b' pub use dirstate::{' | |||
|
25 | 25 | DirstateEntry, DirstateParents, EntryState, |
|
26 | 26 | }; |
|
27 | 27 | pub mod copy_tracing; |
|
28 | mod filepatterns; | |
|
28 | pub mod filepatterns; | |
|
29 | 29 | pub mod matchers; |
|
30 | 30 | pub mod repo; |
|
31 | 31 | pub mod revlog; |
@@ -18,13 +18,15 b' use hg::dirstate::has_exec_bit;' | |||
|
18 | 18 | use hg::dirstate::status::StatusPath; |
|
19 | 19 | use hg::dirstate::TruncatedTimestamp; |
|
20 | 20 | use hg::errors::{HgError, IoResultExt}; |
|
21 | use hg::filepatterns::parse_pattern_args; | |
|
21 | 22 | use hg::lock::LockError; |
|
22 | 23 | use hg::manifest::Manifest; |
|
23 | 24 | use hg::matchers::{AlwaysMatcher, IntersectionMatcher}; |
|
24 | 25 | use hg::repo::Repo; |
|
25 | 26 | use hg::utils::debug::debug_wait_for_file; |
|
26 |
use hg::utils::files:: |
|
|
27 | use hg::utils::files::get_path_from_bytes; | |
|
27 | use hg::utils::files::{ | |
|
28 | get_bytes_from_os_str, get_bytes_from_os_string, get_path_from_bytes, | |
|
29 | }; | |
|
28 | 30 | use hg::utils::hg_path::{hg_path_to_path_buf, HgPath}; |
|
29 | 31 | use hg::DirstateStatus; |
|
30 | 32 | use hg::PatternFileWarning; |
@@ -49,6 +51,12 b' pub fn args() -> clap::Command {' | |||
|
49 | 51 | .alias("st") |
|
50 | 52 | .about(HELP_TEXT) |
|
51 | 53 | .arg( |
|
54 | Arg::new("file") | |
|
55 | .value_parser(clap::value_parser!(std::ffi::OsString)) | |
|
56 | .help("show only these files") | |
|
57 | .action(clap::ArgAction::Append), | |
|
58 | ) | |
|
59 | .arg( | |
|
52 | 60 | Arg::new("all") |
|
53 | 61 | .help("show status of all files") |
|
54 | 62 | .short('A') |
@@ -367,10 +375,8 b' pub fn run(invocation: &crate::CliInvoca' | |||
|
367 | 375 | .expect("commands.status.relative should have a default value"); |
|
368 | 376 | |
|
369 | 377 | let relativize_paths = relative_status || { |
|
370 | // TODO should be dependent on whether patterns are passed once | |
|
371 | // we support those. | |
|
372 | 378 | // See in Python code with `getuipathfn` usage in `commands.py`. |
|
373 |
let legacy_relative_behavior = |
|
|
379 | let legacy_relative_behavior = args.contains_id("file"); | |
|
374 | 380 | match relative_paths(invocation.config)? { |
|
375 | 381 | RelativePaths::Legacy => legacy_relative_behavior, |
|
376 | 382 | RelativePaths::Bool(v) => v, |
@@ -429,6 +435,29 b' pub fn run(invocation: &crate::CliInvoca' | |||
|
429 | 435 | (false, true) => sparse_matcher, |
|
430 | 436 | (false, false) => Box::new(AlwaysMatcher), |
|
431 | 437 | }; |
|
438 | let matcher = match args.get_many::<std::ffi::OsString>("file") { | |
|
439 | None => matcher, | |
|
440 | Some(files) => { | |
|
441 | let patterns: Vec<Vec<u8>> = files | |
|
442 | .filter(|s| !s.is_empty()) | |
|
443 | .map(get_bytes_from_os_str) | |
|
444 | .collect(); | |
|
445 | for file in &patterns { | |
|
446 | if file.starts_with(b"set:") { | |
|
447 | return Err(CommandError::unsupported("fileset")); | |
|
448 | } | |
|
449 | } | |
|
450 | let cwd = hg::utils::current_dir()?; | |
|
451 | let root = repo.working_directory_path(); | |
|
452 | let ignore_patterns = parse_pattern_args(patterns, &cwd, root)?; | |
|
453 | let files_matcher = | |
|
454 | hg::matchers::PatternMatcher::new(ignore_patterns)?; | |
|
455 | Box::new(IntersectionMatcher::new( | |
|
456 | Box::new(files_matcher), | |
|
457 | matcher, | |
|
458 | )) | |
|
459 | } | |
|
460 | }; | |
|
432 | 461 | |
|
433 | 462 | print_narrow_sparse_warnings( |
|
434 | 463 | &narrow_warnings, |
@@ -10,7 +10,8 b' use hg::repo::RepoError;' | |||
|
10 | 10 | use hg::revlog::RevlogError; |
|
11 | 11 | use hg::sparse::SparseConfigError; |
|
12 | 12 | use hg::utils::files::get_bytes_from_path; |
|
13 | use hg::{DirstateError, DirstateMapError, StatusError}; | |
|
13 | use hg::utils::hg_path::HgPathError; | |
|
14 | use hg::{DirstateError, DirstateMapError, PatternError, StatusError}; | |
|
14 | 15 | use std::convert::From; |
|
15 | 16 | |
|
16 | 17 | /// The kind of command error |
@@ -230,6 +231,18 b' impl From<StatusError> for CommandError ' | |||
|
230 | 231 | } |
|
231 | 232 | } |
|
232 | 233 | |
|
234 | impl From<HgPathError> for CommandError { | |
|
235 | fn from(error: HgPathError) -> Self { | |
|
236 | CommandError::unsupported(format!("{}", error)) | |
|
237 | } | |
|
238 | } | |
|
239 | ||
|
240 | impl From<PatternError> for CommandError { | |
|
241 | fn from(error: PatternError) -> Self { | |
|
242 | CommandError::unsupported(format!("{}", error)) | |
|
243 | } | |
|
244 | } | |
|
245 | ||
|
233 | 246 | impl From<DirstateMapError> for CommandError { |
|
234 | 247 | fn from(error: DirstateMapError) -> Self { |
|
235 | 248 | CommandError::abort(format!("{}", error)) |
General Comments 0
You need to be logged in to leave comments.
Login now