summaryrefslogtreecommitdiff
path: root/support/pkgcheck/src/utils.rs
diff options
context:
space:
mode:
Diffstat (limited to 'support/pkgcheck/src/utils.rs')
-rw-r--r--support/pkgcheck/src/utils.rs227
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 {