git_conform/
utils.rs

1//! Custom helper utilities
2
3#![allow(clippy::missing_errors_doc)]
4#![allow(clippy::missing_panics_doc)]
5
6use std::fs;
7use std::path::Path;
8use std::process::{self, Command, Stdio};
9
10pub const APP_NAME: &str = env!("CARGO_PKG_NAME");
11pub const SPINNER_TICK: u64 = 60;
12
13/// Represents the file storing entries of tracked repositories
14pub struct TrackingFile {
15    pub path: String,
16    pub contents: String
17}
18
19/// Checks if a given repository has an entry in the tracking file
20#[allow(clippy::must_use_candidate)]
21pub fn repo_is_tracked(repo: &str, track_file_contents: &str) -> bool {
22    let track_file_lines: Vec<&str> = track_file_contents
23        .lines()
24        .collect();
25
26    track_file_lines.contains(&repo)
27}
28
29/// Checks if a given path is a git repository
30pub fn path_is_repo(path: &str) -> Result<bool, String> {
31    let git_status = Command::new("git")
32        .args(["-C", path, "status"])
33        .stdout(Stdio::null())
34        .stderr(Stdio::null())
35        .status()
36        .map_err(|e| format!("git: {e}"))?;
37
38    Ok(git_status.success())
39}
40
41/// Checks if the given repositories are valid and makes
42/// their paths absolute, prints an error message for every invalid entry
43pub fn repos_valid(repos: &[String]) -> Result<Vec<String>, String> {
44    // Vector containing absolute paths of the repos
45    let mut repos_abs = Vec::from(repos);
46
47    let mut repos_ok = true;
48
49    for repo in &mut repos_abs {
50        // Check if the path exists
51        if let Ok(p) = Path::new(&repo).try_exists() {
52            if !p {
53                eprintln!("{APP_NAME}: Repository '{repo}' does not exist");
54                repos_ok = false;
55                continue;
56            }
57        }
58        else {
59            eprintln!("{APP_NAME}: Cannot check the existance of repository '{repo}'");
60            repos_ok = false;
61            continue;
62        }
63
64        // Check if the path is a git repository
65        match path_is_repo(repo) {
66            Ok(is_repo) => {
67                if !is_repo {
68                    eprintln!("{APP_NAME}: '{repo}' is not a git repository");
69                    repos_ok = false;
70                }
71            },
72            Err(e) => return Err(e)
73        };
74
75        // Check if the path contains valid UTF-8 characters
76        // and make it absolute, if it does
77        if let Some(s) = fs::canonicalize(&repo)
78            .map_err(|e| format!("{repo}: {e}"))?
79            .to_str() {
80            *repo = s.to_string();
81        }
82        else {
83            eprintln!("{APP_NAME}: {repo}: The path contains invalid UTF-8 characters");
84            repos_ok = false;
85        }
86    }
87
88    if !repos_ok {
89        return Err(String::from("Repositories validation failed"));
90    }
91
92    Ok(repos_abs)
93}
94
95/// Prints given error message to the standard error with application name
96/// and then exits the application with specified error code
97pub fn handle_error(error: &str, code: i32) {
98    eprintln!("{APP_NAME}: {error}");
99    process::exit(code);
100}