diff options
Diffstat (limited to 'support/pkgcheck/src/utils.rs')
-rw-r--r-- | support/pkgcheck/src/utils.rs | 227 |
1 files changed, 164 insertions, 63 deletions
diff --git a/support/pkgcheck/src/utils.rs b/support/pkgcheck/src/utils.rs index 6b2d0a8753..8a34bfe7c1 100644 --- a/support/pkgcheck/src/utils.rs +++ b/support/pkgcheck/src/utils.rs @@ -10,9 +10,173 @@ use std::borrow::Cow; use std::io; use std::process::Command; +use colored::*; +use std::sync::atomic::Ordering; use std::fs; +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum CheckType { + TDS, + PACKAGE, +} + +pub struct Utils { + kind: CheckType, +} + +impl Utils { + pub fn new(kind: CheckType) -> Utils { + Utils { kind } + } + + pub fn check_filesize(&self, fsize: u64, dir_entry_str: &str) -> bool { + // if it is an empty file we don't need + // to check further + if fsize == 0 { + e0005!(dir_entry_str); + return false; + } + if fsize > 40 * 1024 * 1024 { + if self.kind == CheckType::PACKAGE { + w0005!(dir_entry_str, fsize / 1024 / 1024); + } else { + w0006!(dir_entry_str, fsize / 1024 / 1024); + } + return false; + } + + true + } + + pub fn filename_has_bad_chars(&self, entry: &DirEntry, dir_entry_str: &str) { + let s = entry.file_name().to_str().unwrap(); + + for (i, c) in s.char_indices() { + match c { + '\x00'..='\x1f' => { + e0001!(c, dir_entry_str, i); + } + ' ' | '!' | '"' | '#' | '$' | '%' | '&' | '\'' => { + e0001!(c, dir_entry_str, i); + } + '(' | ')' | '*' => { + e0001!(c, dir_entry_str, i); + } + '+' | ',' | '-' | '.' => (), + '0'..='9' => (), + ':' | ';' | '<' | '=' | '>' | '?' | '@' => { + e0001!(c, dir_entry_str, i); + } + 'A'..='Z' => (), + '[' | '\\' | ']' | '^' => { + e0001!(c, dir_entry_str, i); + } + '_' => (), + '`' => { + e0001!(c, dir_entry_str, i); + } + 'a'..='z' => (), + '{' | '|' | '}' | '~' => { + e0001!(c, dir_entry_str, i); + } + '/' => return, + _ => { + return { + e0001!(c, dir_entry_str, i); + } + } + }; + } + } + + pub fn is_unwanted_directory(&self, entry: &str, dir_entry_str: &str) { + let names = ["__MACOSX"]; + for n in &names { + if *n == entry { + e0018!(dir_entry_str); + }; + } + } + + pub fn check_for_hidden_file(&self, entry: &str, dir_entry_str: &str) { + if entry.starts_with('.') { + match self.kind { + CheckType::PACKAGE => { + e0007!(dir_entry_str); + } + CheckType::TDS => { + e0007t!(dir_entry_str); + } + } + } + } + + // fname is the base name without the directory part + pub fn check_for_hidden_directory(&self, fname: &str, dir_entry_str: &str) { + + // We have to single out '.' and './' as they denote just the current directory + // That case may happen if pkgcheck gets called like: `pkgcheck -d .` or `pkgcheck -d ./` + if fname == "." || fname == "./" { + return; + }; + + //if fname.map(|s| s.starts_with('.')).unwrap_or(false) { + if fname.starts_with('.') { + match self.kind { + CheckType::PACKAGE => { + e0006!(dir_entry_str); + } + CheckType::TDS => { + e0006t!(dir_entry_str); + } + } + } + } + + pub fn check_for_temporary_file(&self, dir_entry_str: &str) { + lazy_static! { + static ref RE: Regex = regex_temporary_file_endings(); + } + + if RE.is_match(dir_entry_str) { + match self.kind { + CheckType::PACKAGE => { + e0008!(dir_entry_str); + } + CheckType::TDS => { + e0008t!(dir_entry_str); + } + } + } + } + + pub fn check_for_empty_directory(&self, dir_entry_str: &str, dir_entry_display: &str) { + match read_dir(dir_entry_str) { + // try to read the directory specified + Ok(contents) => { + if contents.count() == 0 { + match self.kind { + CheckType::PACKAGE => { + e0004!(dir_entry_display); + } + CheckType::TDS => { + // Note: Karl Berry recommended to issue a warning only + // as an empty directory in a TDS zip archive + // - is automatically deleted before including + // it in texlive + w0007!(dir_entry_display); + } + } + } + } + Err(e) => { + e0027!(dir_entry_display, e); + } + } + } +} + pub fn temp_file_endings() -> Vec<(&'static str, &'static str)> { // https://github.com/github/gitignore/blob/master/TeX.gitignore // http://hopf.math.purdue.edu/doc/html/suffixes.html @@ -125,53 +289,6 @@ pub fn regex_temporary_file_endings() -> Regex { Regex::new(&rv).unwrap() } -pub fn is_temporary_file(entry: &str) -> bool { - lazy_static! { - static ref RE: Regex = regex_temporary_file_endings(); - } - - RE.is_match(entry) -} - -pub fn is_empty_directory(entry: &DirEntry) -> Result<bool, io::Error> { - let s = entry.path().to_str().unwrap(); - match read_dir(s) { - // try to read the directory specified - Ok(contents) => Ok(contents.count() == 0), - Err(e) => Err(e), - } -} - -pub fn is_unwanted_directory(entry: &str) -> bool { - let names = ["__MACOSX"]; - for n in &names { - if *n == entry { - return true; - }; - } - - false -} - -// is_hidden checks for files or directories starting with a dot -pub fn is_hidden(entry: &str) -> bool { - entry.starts_with('.') -} - -// is_hidden checks for files or directories starting with a dot -pub fn is_hidden_directory(entry: &DirEntry) -> bool { - let fname = entry.file_name(); - - if fname == "." { - return false; - }; - if fname == "./" { - return false; - }; - - fname.to_str().map(|s| s.starts_with('.')).unwrap_or(false) -} - pub fn get_symlink(entry: &DirEntry) -> Result<Option<PathBuf>, io::Error> { let r = entry.path().to_str().unwrap(); @@ -309,22 +426,6 @@ pub fn run_cmd(cmd: &str, argument: &[&str]) -> CmdReturn { } } -// Sets permissions for a file or directory -// Sample invocation: set_perms("somfile", 0o644); -pub fn set_perms(entry: &str, p: u32) -> bool { - let ps = &format!("{:o}", p); - let rc = run_cmd("chmod", &["-v", ps, entry]); - - if rc.status { - if let Some(op) = rc.output { - print!("{}", op); - } - true - } else { - false - } -} - // returns true if file is a directory and does exist // returns false otherwise pub fn exists_dir(file: &str) -> bool { |