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
use crate::common::*;
use clap::Arg;
use std::env;
use std::error::Error;
use std::ffi::OsStr;
use std::fs;
use std::fs::File;
use std::io::{BufRead, BufReader};
use std::path::PathBuf;
mod checks;
mod common;
fn get_args(current_dir: &OsStr) -> clap::ArgMatches {
clap::App::new(env!("CARGO_PKG_NAME"))
.about(env!("CARGO_PKG_DESCRIPTION"))
.author(env!("CARGO_PKG_AUTHORS"))
.version(env!("CARGO_PKG_VERSION"))
.version_short("v")
.arg(
Arg::with_name("input")
.help("files or paths")
.index(1)
.default_value_os(current_dir)
.required(true)
.multiple(true),
)
.arg(
Arg::with_name("exclude")
.short("e")
.long("exclude")
.value_name("FILE_NAME")
.help("Excludes files from check")
.multiple(true)
.takes_value(true),
)
.get_matches()
}
#[allow(clippy::redundant_closure)]
pub fn run() -> Result<Vec<Warning>, Box<dyn Error>> {
let current_dir = match env::current_dir() {
Ok(dir) => dir,
Err(e) => return Err(Box::new(e)),
};
let current_dir = current_dir.as_os_str();
let args = get_args(current_dir);
let mut paths: Vec<PathBuf> = vec![];
let mut files: Vec<FileEntry> = vec![];
if let Some(inputs) = args.values_of("input") {
paths = inputs
.clone()
.filter_map(|s| fs::canonicalize(s).ok())
.filter(|p| p.is_dir())
.collect();
files = inputs
.filter_map(|s| fs::canonicalize(s).ok())
.filter(|p| p.is_file())
.filter_map(|p| FileEntry::from(p))
.collect();
}
for path in paths {
let entries = path.read_dir()?;
let mut file_paths: Vec<FileEntry> = entries
.filter_map(|e| e.ok())
.filter_map(|e| FileEntry::from(e.path()))
.filter(|f| f.is_env_file())
.collect();
files.append(file_paths.as_mut());
}
if let Some(excluded) = args.values_of("exclude") {
let excluded_paths: Vec<PathBuf> =
excluded.filter_map(|f| fs::canonicalize(f).ok()).collect();
files.retain(|f| !excluded_paths.contains(&f.path));
}
files.sort();
files.dedup();
let mut new_files: Vec<FileEntry> = vec![];
for file in files {
let result = file.path.strip_prefix(¤t_dir);
let strip_path = match result {
Ok(p) => p,
Err(_) => continue,
};
let new_file = match FileEntry::from(strip_path.to_owned()) {
Some(f) => f,
None => continue,
};
new_files.push(new_file);
}
let mut warnings: Vec<Warning> = Vec::new();
for file in new_files {
let f = File::open(&file.path)?;
let reader = BufReader::new(f);
let mut lines: Vec<LineEntry> = Vec::new();
for (index, line) in reader.lines().enumerate() {
let number = index + 1;
let raw_string = line?;
lines.push(LineEntry {
number,
file_path: file.path.clone(),
raw_string,
})
}
let result = checks::run(lines);
warnings.extend(result);
}
Ok(warnings)
}