1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
use regex::{escape, Regex};
use crate::helpers::{read_file, Result};
pub fn check_contains_regex(
path: &str,
template: &str,
pkg_name: &str,
pkg_version: &str,
) -> Result<()> {
let orig_regex = template
.replace("{name}", &escape(pkg_name))
.replace("{version}", &escape(pkg_version));
let re = match Regex::new(&orig_regex) {
Ok(_) => {
let regex = String::from("(?m)") + &orig_regex;
Regex::new(®ex).unwrap()
}
Err(err) => return Err(format!("could not parse template: {}", err)),
};
let text = read_file(path).map_err(|err| format!("could not read {}: {}", path, err))?;
println!("Searching for \"{}\" in {}...", orig_regex, path);
match re.find(&text) {
Some(m) => {
let line_no = text[..m.start()].lines().count();
println!("{} (line {}) ... ok", path, line_no + 1);
Ok(())
}
None => Err(format!("could not find \"{}\" in {}", orig_regex, path)),
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn bad_regex() {
assert_eq!(
check_contains_regex("README.md", "Version {version} [ups", "foobar", "1.2.3"),
Err(String::from(
[
r"could not parse template: regex parse error:",
r" Version 1\.2\.3 [ups",
r" ^",
r"error: unclosed character class"
]
.join("\n")
))
)
}
#[test]
fn not_found() {
assert_eq!(
check_contains_regex("README.md", "should not be found", "foobar", "1.2.3"),
Err(String::from(
"could not find \"should not be found\" in README.md"
))
)
}
#[test]
fn escaping() {
assert_eq!(
check_contains_regex(
"README.md",
"escaped: {name}-{version}, not escaped: foo*bar-1.2.3",
"foo*bar",
"1.2.3"
),
Err(String::from(
[
r#"could not find "escaped: foo\*bar-1\.2\.3,"#,
r#"not escaped: foo*bar-1.2.3" in README.md"#
]
.join(" ")
))
)
}
#[test]
fn good_pattern() {
assert_eq!(
check_contains_regex("README.md", "{name}", "version-sync", "1.2.3"),
Ok(())
)
}
#[test]
fn line_boundaries() {
use std::io::Write;
let mut file = tempfile::NamedTempFile::new().unwrap();
println!("Path: {}", file.path().to_str().unwrap());
file.write_all(b"first line\r\nsecond line\r\nthird line\r\n")
.unwrap();
assert_eq!(
check_contains_regex(file.path().to_str().unwrap(), "^second line$", "", ""),
Ok(())
)
}
}