annotate rust/hg-core/src/filepatterns.rs @ 42437:9609430d3625

rust-filepatterns: use bytes instead of String In my initial patch, I introduced an unnecessary hard constraint on UTF-8 filenames and patterns which I forgot to remove. Although the performance penalty for using String might be negligible, we don't want to break compatibility with non-UTF-8 encodings for no reason. Moreover, this change allows for a cleaner Rust core API. This patch introduces a new utils module that is used with this fix. Finally, PatternError was not put inside the Python module generated by Rust, which would have raised a NameError. Differential Revision: https://phab.mercurial-scm.org/D6485
author Raphaël Gomès <rgomes@octobus.net>
date Thu, 06 Jun 2019 15:30:56 +0200
parents e8f3740cc067
children 48f1f864d928
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
42327
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
1 use crate::{LineNumber, PatternError, PatternFileError};
42437
9609430d3625 rust-filepatterns: use bytes instead of String
Raphaël Gomès <rgomes@octobus.net>
parents: 42327
diff changeset
2 use regex::bytes::Regex;
42327
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
3 use std::collections::HashMap;
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
4 use std::fs::File;
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
5 use std::io::Read;
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
6 use std::vec::Vec;
42437
9609430d3625 rust-filepatterns: use bytes instead of String
Raphaël Gomès <rgomes@octobus.net>
parents: 42327
diff changeset
7 use utils::files::get_path_from_bytes;
9609430d3625 rust-filepatterns: use bytes instead of String
Raphaël Gomès <rgomes@octobus.net>
parents: 42327
diff changeset
8 use utils::{replace_slice, SliceExt};
42327
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
9
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
10 lazy_static! {
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
11 static ref reescape: Vec<Vec<u8>> = {
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
12 let mut v: Vec<Vec<u8>> = (0..=255).map(|byte| vec![byte]).collect();
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
13 let to_escape = b"()[]{}?*+-|^$\\.&~# \t\n\r\x0b\x0c";
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
14 for byte in to_escape {
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
15 v[*byte as usize].insert(0, b'\\');
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
16 }
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
17 v
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
18 };
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
19 }
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
20
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
21 /// These are matched in order
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
22 const GLOB_REPLACEMENTS: &[(&[u8], &[u8])] =
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
23 &[(b"*/", b"(?:.*/)?"), (b"*", b".*"), (b"", b"[^/]*")];
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
24
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
25 #[derive(Debug, Copy, Clone, PartialEq, Eq)]
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
26 pub enum PatternSyntax {
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
27 Regexp,
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
28 /// Glob that matches at the front of the path
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
29 RootGlob,
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
30 /// Glob that matches at any suffix of the path (still anchored at slashes)
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
31 Glob,
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
32 Path,
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
33 RelPath,
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
34 RelGlob,
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
35 RelRegexp,
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
36 RootFiles,
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
37 }
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
38
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
39 /// Transforms a glob pattern into a regex
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
40 fn glob_to_re(pat: &[u8]) -> Vec<u8> {
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
41 let mut input = pat;
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
42 let mut res: Vec<u8> = vec![];
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
43 let mut group_depth = 0;
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
44
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
45 while let Some((c, rest)) = input.split_first() {
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
46 input = rest;
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
47
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
48 match c {
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
49 b'*' => {
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
50 for (source, repl) in GLOB_REPLACEMENTS {
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
51 if input.starts_with(source) {
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
52 input = &input[source.len()..];
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
53 res.extend(*repl);
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
54 break;
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
55 }
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
56 }
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
57 }
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
58 b'?' => res.extend(b"."),
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
59 b'[' => {
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
60 match input.iter().skip(1).position(|b| *b == b']') {
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
61 None => res.extend(b"\\["),
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
62 Some(end) => {
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
63 // Account for the one we skipped
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
64 let end = end + 1;
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
65
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
66 res.extend(b"[");
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
67
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
68 for (i, b) in input[..end].iter().enumerate() {
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
69 if *b == b'!' && i == 0 {
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
70 res.extend(b"^")
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
71 } else if *b == b'^' && i == 0 {
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
72 res.extend(b"\\^")
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
73 } else if *b == b'\\' {
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
74 res.extend(b"\\\\")
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
75 } else {
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
76 res.push(*b)
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
77 }
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
78 }
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
79 res.extend(b"]");
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
80 input = &input[end + 1..];
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
81 }
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
82 }
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
83 }
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
84 b'{' => {
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
85 group_depth += 1;
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
86 res.extend(b"(?:")
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
87 }
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
88 b'}' if group_depth > 0 => {
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
89 group_depth -= 1;
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
90 res.extend(b")");
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
91 }
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
92 b',' if group_depth > 0 => res.extend(b"|"),
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
93 b'\\' => {
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
94 let c = {
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
95 if let Some((c, rest)) = input.split_first() {
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
96 input = rest;
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
97 c
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
98 } else {
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
99 c
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
100 }
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
101 };
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
102 res.extend(&reescape[*c as usize])
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
103 }
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
104 _ => res.extend(&reescape[*c as usize]),
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
105 }
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
106 }
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
107 res
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
108 }
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
109
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
110 fn escape_pattern(pattern: &[u8]) -> Vec<u8> {
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
111 pattern
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
112 .iter()
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
113 .flat_map(|c| reescape[*c as usize].clone())
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
114 .collect()
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
115 }
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
116
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
117 fn parse_pattern_syntax(kind: &[u8]) -> Result<PatternSyntax, PatternError> {
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
118 match kind {
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
119 b"re" => Ok(PatternSyntax::Regexp),
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
120 b"path" => Ok(PatternSyntax::Path),
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
121 b"relpath" => Ok(PatternSyntax::RelPath),
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
122 b"rootfilesin" => Ok(PatternSyntax::RootFiles),
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
123 b"relglob" => Ok(PatternSyntax::RelGlob),
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
124 b"relre" => Ok(PatternSyntax::RelRegexp),
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
125 b"glob" => Ok(PatternSyntax::Glob),
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
126 b"rootglob" => Ok(PatternSyntax::RootGlob),
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
127 _ => Err(PatternError::UnsupportedSyntax(
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
128 String::from_utf8_lossy(kind).to_string(),
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
129 )),
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
130 }
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
131 }
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
132
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
133 /// Builds the regex that corresponds to the given pattern.
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
134 /// If within a `syntax: regexp` context, returns the pattern,
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
135 /// otherwise, returns the corresponding regex.
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
136 fn _build_single_regex(
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
137 syntax: PatternSyntax,
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
138 pattern: &[u8],
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
139 globsuffix: &[u8],
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
140 ) -> Vec<u8> {
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
141 if pattern.is_empty() {
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
142 return vec![];
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
143 }
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
144 match syntax {
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
145 PatternSyntax::Regexp => pattern.to_owned(),
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
146 PatternSyntax::RelRegexp => {
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
147 if pattern[0] == b'^' {
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
148 return pattern.to_owned();
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
149 }
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
150 let mut res = b".*".to_vec();
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
151 res.extend(pattern);
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
152 res
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
153 }
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
154 PatternSyntax::Path | PatternSyntax::RelPath => {
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
155 if pattern == b"." {
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
156 return vec![];
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
157 }
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
158 let mut pattern = escape_pattern(pattern);
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
159 pattern.extend(b"(?:/|$)");
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
160 pattern
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
161 }
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
162 PatternSyntax::RootFiles => {
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
163 let mut res = if pattern == b"." {
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
164 vec![]
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
165 } else {
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
166 // Pattern is a directory name.
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
167 let mut as_vec: Vec<u8> = escape_pattern(pattern);
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
168 as_vec.push(b'/');
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
169 as_vec
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
170 };
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
171
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
172 // Anything after the pattern must be a non-directory.
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
173 res.extend(b"[^/]+$");
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
174 res
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
175 }
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
176 PatternSyntax::Glob
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
177 | PatternSyntax::RelGlob
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
178 | PatternSyntax::RootGlob => {
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
179 let mut res: Vec<u8> = vec![];
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
180 if syntax == PatternSyntax::RelGlob {
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
181 res.extend(b"(?:|.*/)");
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
182 }
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
183
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
184 res.extend(glob_to_re(pattern));
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
185 res.extend(globsuffix.iter());
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
186 res
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
187 }
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
188 }
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
189 }
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
190
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
191 const GLOB_SPECIAL_CHARACTERS: [u8; 7] =
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
192 [b'*', b'?', b'[', b']', b'{', b'}', b'\\'];
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
193
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
194 /// Wrapper function to `_build_single_regex` that short-circuits 'exact' globs
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
195 /// that don't need to be transformed into a regex.
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
196 pub fn build_single_regex(
42437
9609430d3625 rust-filepatterns: use bytes instead of String
Raphaël Gomès <rgomes@octobus.net>
parents: 42327
diff changeset
197 kind: &[u8],
42327
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
198 pat: &[u8],
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
199 globsuffix: &[u8],
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
200 ) -> Result<Vec<u8>, PatternError> {
42437
9609430d3625 rust-filepatterns: use bytes instead of String
Raphaël Gomès <rgomes@octobus.net>
parents: 42327
diff changeset
201 let enum_kind = parse_pattern_syntax(kind)?;
42327
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
202 if enum_kind == PatternSyntax::RootGlob
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
203 && pat.iter().all(|b| GLOB_SPECIAL_CHARACTERS.contains(b))
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
204 {
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
205 Ok(pat.to_vec())
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
206 } else {
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
207 Ok(_build_single_regex(enum_kind, pat, globsuffix))
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
208 }
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
209 }
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
210
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
211 lazy_static! {
42437
9609430d3625 rust-filepatterns: use bytes instead of String
Raphaël Gomès <rgomes@octobus.net>
parents: 42327
diff changeset
212 static ref SYNTAXES: HashMap<&'static [u8], &'static [u8]> = {
42327
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
213 let mut m = HashMap::new();
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
214
42437
9609430d3625 rust-filepatterns: use bytes instead of String
Raphaël Gomès <rgomes@octobus.net>
parents: 42327
diff changeset
215 m.insert(b"re".as_ref(), b"relre:".as_ref());
9609430d3625 rust-filepatterns: use bytes instead of String
Raphaël Gomès <rgomes@octobus.net>
parents: 42327
diff changeset
216 m.insert(b"regexp".as_ref(), b"relre:".as_ref());
9609430d3625 rust-filepatterns: use bytes instead of String
Raphaël Gomès <rgomes@octobus.net>
parents: 42327
diff changeset
217 m.insert(b"glob".as_ref(), b"relglob:".as_ref());
9609430d3625 rust-filepatterns: use bytes instead of String
Raphaël Gomès <rgomes@octobus.net>
parents: 42327
diff changeset
218 m.insert(b"rootglob".as_ref(), b"rootglob:".as_ref());
9609430d3625 rust-filepatterns: use bytes instead of String
Raphaël Gomès <rgomes@octobus.net>
parents: 42327
diff changeset
219 m.insert(b"include".as_ref(), b"include".as_ref());
9609430d3625 rust-filepatterns: use bytes instead of String
Raphaël Gomès <rgomes@octobus.net>
parents: 42327
diff changeset
220 m.insert(b"subinclude".as_ref(), b"subinclude".as_ref());
42327
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
221 m
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
222 };
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
223 }
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
224
42437
9609430d3625 rust-filepatterns: use bytes instead of String
Raphaël Gomès <rgomes@octobus.net>
parents: 42327
diff changeset
225 pub type PatternTuple = (Vec<u8>, LineNumber, Vec<u8>);
42327
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
226 type WarningTuple = (String, String);
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
227
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
228 pub fn parse_pattern_file_contents(
42437
9609430d3625 rust-filepatterns: use bytes instead of String
Raphaël Gomès <rgomes@octobus.net>
parents: 42327
diff changeset
229 lines: &[u8],
9609430d3625 rust-filepatterns: use bytes instead of String
Raphaël Gomès <rgomes@octobus.net>
parents: 42327
diff changeset
230 file_path: &[u8],
42327
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
231 warn: bool,
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
232 ) -> (Vec<PatternTuple>, Vec<WarningTuple>) {
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
233 let comment_regex = Regex::new(r"((?:^|[^\\])(?:\\\\)*)#.*").unwrap();
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
234 let mut inputs: Vec<PatternTuple> = vec![];
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
235 let mut warnings: Vec<WarningTuple> = vec![];
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
236
42437
9609430d3625 rust-filepatterns: use bytes instead of String
Raphaël Gomès <rgomes@octobus.net>
parents: 42327
diff changeset
237 let mut current_syntax = b"relre:".as_ref();
42327
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
238
42437
9609430d3625 rust-filepatterns: use bytes instead of String
Raphaël Gomès <rgomes@octobus.net>
parents: 42327
diff changeset
239 for (line_number, mut line) in lines.split(|c| *c == b'\n').enumerate() {
42327
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
240 let line_number = line_number + 1;
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
241
42437
9609430d3625 rust-filepatterns: use bytes instead of String
Raphaël Gomès <rgomes@octobus.net>
parents: 42327
diff changeset
242 if line.contains(&('#' as u8)) {
9609430d3625 rust-filepatterns: use bytes instead of String
Raphaël Gomès <rgomes@octobus.net>
parents: 42327
diff changeset
243 if let Some(cap) = comment_regex.captures(line) {
9609430d3625 rust-filepatterns: use bytes instead of String
Raphaël Gomès <rgomes@octobus.net>
parents: 42327
diff changeset
244 line = &line[..cap.get(1).unwrap().end()]
42327
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
245 }
42437
9609430d3625 rust-filepatterns: use bytes instead of String
Raphaël Gomès <rgomes@octobus.net>
parents: 42327
diff changeset
246 let mut line = line.to_owned();
9609430d3625 rust-filepatterns: use bytes instead of String
Raphaël Gomès <rgomes@octobus.net>
parents: 42327
diff changeset
247 replace_slice(&mut line, br"\#", b"#");
42327
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
248 }
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
249
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
250 let mut line = line.trim_end();
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
251
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
252 if line.is_empty() {
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
253 continue;
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
254 }
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
255
42437
9609430d3625 rust-filepatterns: use bytes instead of String
Raphaël Gomès <rgomes@octobus.net>
parents: 42327
diff changeset
256 if line.starts_with(b"syntax:") {
9609430d3625 rust-filepatterns: use bytes instead of String
Raphaël Gomès <rgomes@octobus.net>
parents: 42327
diff changeset
257 let syntax = line[b"syntax:".len()..].trim();
42327
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
258
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
259 if let Some(rel_syntax) = SYNTAXES.get(syntax) {
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
260 current_syntax = rel_syntax;
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
261 } else if warn {
42437
9609430d3625 rust-filepatterns: use bytes instead of String
Raphaël Gomès <rgomes@octobus.net>
parents: 42327
diff changeset
262 warnings.push((
9609430d3625 rust-filepatterns: use bytes instead of String
Raphaël Gomès <rgomes@octobus.net>
parents: 42327
diff changeset
263 String::from_utf8_lossy(file_path).to_string(),
9609430d3625 rust-filepatterns: use bytes instead of String
Raphaël Gomès <rgomes@octobus.net>
parents: 42327
diff changeset
264 String::from_utf8_lossy(syntax).to_string(),
9609430d3625 rust-filepatterns: use bytes instead of String
Raphaël Gomès <rgomes@octobus.net>
parents: 42327
diff changeset
265 ));
42327
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
266 }
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
267 continue;
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
268 }
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
269
42437
9609430d3625 rust-filepatterns: use bytes instead of String
Raphaël Gomès <rgomes@octobus.net>
parents: 42327
diff changeset
270 let mut line_syntax: &[u8] = &current_syntax;
42327
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
271
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
272 for (s, rels) in SYNTAXES.iter() {
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
273 if line.starts_with(rels) {
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
274 line_syntax = rels;
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
275 line = &line[rels.len()..];
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
276 break;
42437
9609430d3625 rust-filepatterns: use bytes instead of String
Raphaël Gomès <rgomes@octobus.net>
parents: 42327
diff changeset
277 } else if line.starts_with(&[s, b":".as_ref()].concat()) {
42327
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
278 line_syntax = rels;
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
279 line = &line[s.len() + 1..];
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
280 break;
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
281 }
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
282 }
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
283
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
284 inputs.push((
42437
9609430d3625 rust-filepatterns: use bytes instead of String
Raphaël Gomès <rgomes@octobus.net>
parents: 42327
diff changeset
285 [line_syntax, line].concat(),
42327
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
286 line_number,
42437
9609430d3625 rust-filepatterns: use bytes instead of String
Raphaël Gomès <rgomes@octobus.net>
parents: 42327
diff changeset
287 line.to_owned(),
42327
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
288 ));
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
289 }
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
290 (inputs, warnings)
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
291 }
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
292
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
293 pub fn read_pattern_file(
42437
9609430d3625 rust-filepatterns: use bytes instead of String
Raphaël Gomès <rgomes@octobus.net>
parents: 42327
diff changeset
294 file_path: &[u8],
42327
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
295 warn: bool,
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
296 ) -> Result<(Vec<PatternTuple>, Vec<WarningTuple>), PatternFileError> {
42437
9609430d3625 rust-filepatterns: use bytes instead of String
Raphaël Gomès <rgomes@octobus.net>
parents: 42327
diff changeset
297 let mut f = File::open(get_path_from_bytes(file_path))?;
9609430d3625 rust-filepatterns: use bytes instead of String
Raphaël Gomès <rgomes@octobus.net>
parents: 42327
diff changeset
298 let mut contents = Vec::new();
42327
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
299
42437
9609430d3625 rust-filepatterns: use bytes instead of String
Raphaël Gomès <rgomes@octobus.net>
parents: 42327
diff changeset
300 f.read_to_end(&mut contents)?;
42327
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
301
42437
9609430d3625 rust-filepatterns: use bytes instead of String
Raphaël Gomès <rgomes@octobus.net>
parents: 42327
diff changeset
302 Ok(parse_pattern_file_contents(&contents, file_path, warn))
42327
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
303 }
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
304
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
305 #[cfg(test)]
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
306 mod tests {
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
307 use super::*;
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
308
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
309 #[test]
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
310 fn escape_pattern_test() {
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
311 let untouched = br#"!"%',/0123456789:;<=>@ABCDEFGHIJKLMNOPQRSTUVWXYZ_`abcdefghijklmnopqrstuvwxyz"#;
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
312 assert_eq!(escape_pattern(untouched), untouched.to_vec());
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
313 // All escape codes
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
314 assert_eq!(
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
315 escape_pattern(br#"()[]{}?*+-|^$\\.&~# \t\n\r\v\f"#),
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
316 br#"\(\)\[\]\{\}\?\*\+\-\|\^\$\\\\\.\&\~\#\ \\t\\n\\r\\v\\f"#
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
317 .to_vec()
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
318 );
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
319 }
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
320
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
321 #[test]
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
322 fn glob_test() {
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
323 assert_eq!(glob_to_re(br#"?"#), br#"."#);
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
324 assert_eq!(glob_to_re(br#"*"#), br#"[^/]*"#);
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
325 assert_eq!(glob_to_re(br#"**"#), br#".*"#);
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
326 assert_eq!(glob_to_re(br#"**/a"#), br#"(?:.*/)?a"#);
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
327 assert_eq!(glob_to_re(br#"a/**/b"#), br#"a/(?:.*/)?b"#);
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
328 assert_eq!(glob_to_re(br#"[a*?!^][^b][!c]"#), br#"[a*?!^][\^b][^c]"#);
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
329 assert_eq!(glob_to_re(br#"{a,b}"#), br#"(?:a|b)"#);
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
330 assert_eq!(glob_to_re(br#".\*\?"#), br#"\.\*\?"#);
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
331 }
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
332
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
333 #[test]
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
334 fn test_parse_pattern_file_contents() {
42437
9609430d3625 rust-filepatterns: use bytes instead of String
Raphaël Gomès <rgomes@octobus.net>
parents: 42327
diff changeset
335 let lines = b"syntax: glob\n*.elc";
42327
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
336
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
337 assert_eq!(
42437
9609430d3625 rust-filepatterns: use bytes instead of String
Raphaël Gomès <rgomes@octobus.net>
parents: 42327
diff changeset
338 vec![(b"relglob:*.elc".to_vec(), 2, b"*.elc".to_vec())],
9609430d3625 rust-filepatterns: use bytes instead of String
Raphaël Gomès <rgomes@octobus.net>
parents: 42327
diff changeset
339 parse_pattern_file_contents(lines, b"file_path", false).0,
42327
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
340 );
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
341
42437
9609430d3625 rust-filepatterns: use bytes instead of String
Raphaël Gomès <rgomes@octobus.net>
parents: 42327
diff changeset
342 let lines = b"syntax: include\nsyntax: glob";
42327
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
343
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
344 assert_eq!(
42437
9609430d3625 rust-filepatterns: use bytes instead of String
Raphaël Gomès <rgomes@octobus.net>
parents: 42327
diff changeset
345 parse_pattern_file_contents(lines, b"file_path", false).0,
42327
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
346 vec![]
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
347 );
42437
9609430d3625 rust-filepatterns: use bytes instead of String
Raphaël Gomès <rgomes@octobus.net>
parents: 42327
diff changeset
348 let lines = b"glob:**.o";
9609430d3625 rust-filepatterns: use bytes instead of String
Raphaël Gomès <rgomes@octobus.net>
parents: 42327
diff changeset
349 assert_eq!(
9609430d3625 rust-filepatterns: use bytes instead of String
Raphaël Gomès <rgomes@octobus.net>
parents: 42327
diff changeset
350 parse_pattern_file_contents(lines, b"file_path", false).0,
9609430d3625 rust-filepatterns: use bytes instead of String
Raphaël Gomès <rgomes@octobus.net>
parents: 42327
diff changeset
351 vec![(b"relglob:**.o".to_vec(), 1, b"**.o".to_vec())]
9609430d3625 rust-filepatterns: use bytes instead of String
Raphaël Gomès <rgomes@octobus.net>
parents: 42327
diff changeset
352 );
42327
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
353 }
e8f3740cc067 rust-filepatterns: add a Rust implementation of pattern-related utils
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
354 }