#![allow(clippy::missing_errors_doc)]
#![allow(clippy::missing_panics_doc)]
use crate::core::backend::{
search_for_repos,
exec_async_check
};
use crate::utils::{
APP_NAME,
TrackingFile,
repo_is_tracked,
repos_valid
};
use std::fs::{self, OpenOptions};
use std::io::Write as _;
use std::path::Path;
use colored::Colorize;
pub fn scan_dirs(mut dirs: Vec<String>, tracking_file: &TrackingFile, scan_hidden: bool) -> Result<String, String> {
dirs.sort_unstable();
dirs.dedup();
let mut dirs_ok = true;
for dir in &mut dirs {
let path = Path::new(&dir);
if let Ok(p) = path.try_exists() {
if !p {
eprintln!("{APP_NAME}: Directory '{dir}' does not exist");
dirs_ok = false;
continue;
}
}
else {
eprintln!("{APP_NAME}: Cannot check the existance of directory '{dir}'");
dirs_ok = false;
continue;
}
if path.is_file() {
eprintln!("{APP_NAME}: '{dir}' is not a directory");
dirs_ok = false;
}
if let Some(s) = fs::canonicalize(&dir)
.map_err(|e| format!("{dir}: {e}"))?
.to_str() {
*dir = s.to_string();
}
else {
eprintln!("{APP_NAME}: {dir}: The path contains invalid UTF-8 characters");
dirs_ok = false;
}
}
if !dirs_ok {
return Err(String::from("Directories validation failed"));
}
Ok(search_for_repos(dirs.as_slice(), tracking_file, scan_hidden)?)
}
pub fn scan_all(home_dir: String, tracking_file: &TrackingFile, scan_hidden: bool) -> Result<String, String> {
Ok(search_for_repos(&[home_dir], tracking_file, scan_hidden)?)
}
pub fn list(track_file_contents: &str) -> Result<(), String> {
if track_file_contents.is_empty() {
return Err(String::from("No repository is being tracked"));
}
print!("{}", track_file_contents.bold());
Ok(())
}
pub fn add(mut repos: Vec<String>, tracking_file: &TrackingFile) -> Result<(), String> {
repos.sort_unstable();
repos.dedup();
repos = repos_valid(repos.as_slice())?;
let mut track_file = OpenOptions::new()
.create(true)
.append(true)
.open(tracking_file.path.clone())
.map_err(|e| format!("{}: {e}", tracking_file.path))?;
for repo in repos {
if repo_is_tracked(repo.as_str(), tracking_file.contents.as_str()) {
println!("{APP_NAME}: '{repo}' is already being tracked");
continue;
}
track_file.write_all(
format!("{repo}\n").as_bytes())
.map_err(|e| format!("{}: {e}", tracking_file.path))?;
}
Ok(())
}
pub fn remove_repos(mut repos: Vec<String>, tracking_file: &TrackingFile) -> Result<(), String> {
if tracking_file.contents.is_empty() {
return Err(String::from("No repository is being tracked"));
}
repos.sort_unstable();
repos.dedup();
let mut repos_ok = true;
for repo in &repos {
if !repo_is_tracked(repo.as_str(), tracking_file.contents.as_str()) {
eprintln!("{APP_NAME}: '{repo}' is not being tracked");
repos_ok = false;
}
}
if !repos_ok {
return Err(String::from("Repositories validation failed"));
}
let mut track_file_lines: Vec<&str> = tracking_file.contents.lines().collect();
let mut track_file = OpenOptions::new()
.write(true)
.truncate(true)
.open(tracking_file.path.clone())
.map_err(|e| format!("{}: {e}", tracking_file.path))?;
for repo in repos {
if let Some(last) = track_file_lines.last() {
if repo.trim() == last.trim() {
track_file_lines.pop();
}
else {
track_file_lines.retain(|&x| x.trim() != repo.trim());
}
}
}
track_file.write_all(track_file_lines.join("\n").as_bytes())
.map_err(|e| format!("{}: {e}", tracking_file.path))?;
Ok(())
}
pub fn remove_all(tracking_file: &TrackingFile) -> Result<(), String> {
if tracking_file.contents.is_empty() {
return Err(String::from("No repository is being tracked"));
}
fs::remove_file(tracking_file.path.clone()).map_err(|e| format!("{}: {e}", tracking_file.path))?;
Ok(())
}
pub async fn check_repos(mut repos: Vec<String>, flags: &[bool]) -> Result<(), String> {
repos.sort_unstable();
repos.dedup();
repos = repos_valid(repos.as_slice())?;
exec_async_check(repos, flags.to_vec()).await?;
Ok(())
}
pub async fn check_all(tracking_file: &TrackingFile, flags: &[bool]) -> Result<(), String> {
if tracking_file.contents.is_empty() {
return Err(String::from("No repository is being tracked"));
}
let track_file_lines: Vec<String> = tracking_file.contents
.lines()
.map(String::from)
.collect();
exec_async_check(track_file_lines, flags.to_vec()).await?;
Ok(())
}