1#![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
13pub struct TrackingFile {
15 pub path: String,
16 pub contents: String
17}
18
19#[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
29pub 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
41pub fn repos_valid(repos: &[String]) -> Result<Vec<String>, String> {
44 let mut repos_abs = Vec::from(repos);
46
47 let mut repos_ok = true;
48
49 for repo in &mut repos_abs {
50 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 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 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
95pub fn handle_error(error: &str, code: i32) {
98 eprintln!("{APP_NAME}: {error}");
99 process::exit(code);
100}