Show More
@@ -366,6 +366,7 b' pub fn parse_one_pattern(' | |||||
366 | pattern: &[u8], |
|
366 | pattern: &[u8], | |
367 | source: &Path, |
|
367 | source: &Path, | |
368 | default: PatternSyntax, |
|
368 | default: PatternSyntax, | |
|
369 | normalize: bool, | |||
369 | ) -> IgnorePattern { |
|
370 | ) -> IgnorePattern { | |
370 | let mut pattern_bytes: &[u8] = pattern; |
|
371 | let mut pattern_bytes: &[u8] = pattern; | |
371 | let mut syntax = default; |
|
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 | IgnorePattern { |
|
396 | IgnorePattern { | |
384 | syntax, |
|
397 | syntax, | |
@@ -438,6 +451,7 b' pub fn parse_pattern_file_contents(' | |||||
438 | line, |
|
451 | line, | |
439 | file_path, |
|
452 | file_path, | |
440 | current_syntax.clone(), |
|
453 | current_syntax.clone(), | |
|
454 | false, | |||
441 | ); |
|
455 | ); | |
442 | inputs.push(if relativize { |
|
456 | inputs.push(if relativize { | |
443 | pattern.to_relative() |
|
457 | pattern.to_relative() | |
@@ -449,6 +463,35 b' pub fn parse_pattern_file_contents(' | |||||
449 | Ok((inputs, warnings)) |
|
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 | pub fn read_pattern_file( |
|
495 | pub fn read_pattern_file( | |
453 | file_path: &Path, |
|
496 | file_path: &Path, | |
454 | warn: bool, |
|
497 | warn: bool, |
@@ -25,7 +25,7 b' pub use dirstate::{' | |||||
25 | DirstateEntry, DirstateParents, EntryState, |
|
25 | DirstateEntry, DirstateParents, EntryState, | |
26 | }; |
|
26 | }; | |
27 | pub mod copy_tracing; |
|
27 | pub mod copy_tracing; | |
28 | mod filepatterns; |
|
28 | pub mod filepatterns; | |
29 | pub mod matchers; |
|
29 | pub mod matchers; | |
30 | pub mod repo; |
|
30 | pub mod repo; | |
31 | pub mod revlog; |
|
31 | pub mod revlog; |
@@ -18,13 +18,15 b' use hg::dirstate::has_exec_bit;' | |||||
18 | use hg::dirstate::status::StatusPath; |
|
18 | use hg::dirstate::status::StatusPath; | |
19 | use hg::dirstate::TruncatedTimestamp; |
|
19 | use hg::dirstate::TruncatedTimestamp; | |
20 | use hg::errors::{HgError, IoResultExt}; |
|
20 | use hg::errors::{HgError, IoResultExt}; | |
|
21 | use hg::filepatterns::parse_pattern_args; | |||
21 | use hg::lock::LockError; |
|
22 | use hg::lock::LockError; | |
22 | use hg::manifest::Manifest; |
|
23 | use hg::manifest::Manifest; | |
23 | use hg::matchers::{AlwaysMatcher, IntersectionMatcher}; |
|
24 | use hg::matchers::{AlwaysMatcher, IntersectionMatcher}; | |
24 | use hg::repo::Repo; |
|
25 | use hg::repo::Repo; | |
25 | use hg::utils::debug::debug_wait_for_file; |
|
26 | use hg::utils::debug::debug_wait_for_file; | |
26 |
use hg::utils::files:: |
|
27 | use hg::utils::files::{ | |
27 | use hg::utils::files::get_path_from_bytes; |
|
28 | get_bytes_from_os_str, get_bytes_from_os_string, get_path_from_bytes, | |
|
29 | }; | |||
28 | use hg::utils::hg_path::{hg_path_to_path_buf, HgPath}; |
|
30 | use hg::utils::hg_path::{hg_path_to_path_buf, HgPath}; | |
29 | use hg::DirstateStatus; |
|
31 | use hg::DirstateStatus; | |
30 | use hg::PatternFileWarning; |
|
32 | use hg::PatternFileWarning; | |
@@ -49,6 +51,12 b' pub fn args() -> clap::Command {' | |||||
49 | .alias("st") |
|
51 | .alias("st") | |
50 | .about(HELP_TEXT) |
|
52 | .about(HELP_TEXT) | |
51 | .arg( |
|
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 | Arg::new("all") |
|
60 | Arg::new("all") | |
53 | .help("show status of all files") |
|
61 | .help("show status of all files") | |
54 | .short('A') |
|
62 | .short('A') | |
@@ -367,10 +375,8 b' pub fn run(invocation: &crate::CliInvoca' | |||||
367 | .expect("commands.status.relative should have a default value"); |
|
375 | .expect("commands.status.relative should have a default value"); | |
368 |
|
376 | |||
369 | let relativize_paths = relative_status || { |
|
377 | let relativize_paths = relative_status || { | |
370 | // TODO should be dependent on whether patterns are passed once |
|
|||
371 | // we support those. |
|
|||
372 | // See in Python code with `getuipathfn` usage in `commands.py`. |
|
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 | match relative_paths(invocation.config)? { |
|
380 | match relative_paths(invocation.config)? { | |
375 | RelativePaths::Legacy => legacy_relative_behavior, |
|
381 | RelativePaths::Legacy => legacy_relative_behavior, | |
376 | RelativePaths::Bool(v) => v, |
|
382 | RelativePaths::Bool(v) => v, | |
@@ -429,6 +435,29 b' pub fn run(invocation: &crate::CliInvoca' | |||||
429 | (false, true) => sparse_matcher, |
|
435 | (false, true) => sparse_matcher, | |
430 | (false, false) => Box::new(AlwaysMatcher), |
|
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 | print_narrow_sparse_warnings( |
|
462 | print_narrow_sparse_warnings( | |
434 | &narrow_warnings, |
|
463 | &narrow_warnings, |
@@ -10,7 +10,8 b' use hg::repo::RepoError;' | |||||
10 | use hg::revlog::RevlogError; |
|
10 | use hg::revlog::RevlogError; | |
11 | use hg::sparse::SparseConfigError; |
|
11 | use hg::sparse::SparseConfigError; | |
12 | use hg::utils::files::get_bytes_from_path; |
|
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 | use std::convert::From; |
|
15 | use std::convert::From; | |
15 |
|
16 | |||
16 | /// The kind of command error |
|
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 | impl From<DirstateMapError> for CommandError { |
|
246 | impl From<DirstateMapError> for CommandError { | |
234 | fn from(error: DirstateMapError) -> Self { |
|
247 | fn from(error: DirstateMapError) -> Self { | |
235 | CommandError::abort(format!("{}", error)) |
|
248 | CommandError::abort(format!("{}", error)) |
General Comments 0
You need to be logged in to leave comments.
Login now