Adds a basic sync function + cargo fmt + cargo clippy compliance + minor refactors

Signed-off-by: alexis-opolka <53085471+alexis-opolka@users.noreply.github.com>
This commit is contained in:
alexis-opolka 2025-05-03 01:50:53 +02:00
parent 9b2d001195
commit d279f8fc55
5 changed files with 111 additions and 49 deletions

View file

@ -1,54 +1,8 @@
use crate::common::git;
use crate::config::CONFIG;
use crate::filesystem::{all_cheat_files, default_cheat_pathbuf};
use crate::filesystem::local_cheatsheet_repositories;
use crate::libs::terminal::hyperlink;
use crate::prelude::*;
pub fn main() {
let mut cheats_repos: Vec<String> = Vec::new();
let cheats = CONFIG.path().unwrap_or_else(|| {
// if we don't have a path, use the default value
let mut _cheats = default_cheat_pathbuf().unwrap();
_cheats.push("navi");
_cheats.push("cheats");
_cheats.to_string()
});
// We're checking each given paths possible
for cheat_path in cheats.split(':') {
// If the path doesn't exist, continue to the next one
if !std::fs::exists(cheat_path).unwrap() {
continue;
}
let curr_dir = std::fs::read_dir(cheat_path).unwrap();
// We're checking subfolders -> they should contain at least one .cheat files
for entry in curr_dir {
let entry = entry.unwrap();
if entry.file_type().unwrap().is_dir() {
// If the directory doesn't have at least one cheat file -> ignore it and continue
if all_cheat_files(&entry.path()).is_empty() {
continue;
};
// If the directory have at least one cheat file -> add it to the list
// Note: for the list, we are registering the git remote name and not the
// folder name since we modify it internally.
let git_path = format!("{}/{}", &entry.path().display(), ".git");
if std::fs::exists(&git_path).unwrap() {
let remote_uri = git::get_remote(&entry.path().to_string()).unwrap();
cheats_repos.push(remote_uri);
} else {
cheats_repos.push(entry.path().display().to_string());
}
}
}
}
let (cheats_repos, _) = local_cheatsheet_repositories();
// Now that we have our list of cheatsheet repositories, we loop through them
// Two behaviours:

View file

@ -1,7 +1,35 @@
use crate::common::git;
use crate::filesystem;
use crate::filesystem::local_cheatsheet_repositories;
use crate::prelude::*;
pub fn main(name: Option<String>) -> Result<()> {
let (cheats_repo_uris, cheats_repo_paths) = local_cheatsheet_repositories();
if name.clone().is_some() {
let name = name.clone().unwrap();
// We have been given a repository uri to check
if cheats_repo_uris.contains(&name) {
let folder_index = cheats_repo_uris.iter().position(|r| r == &name).unwrap();
let repo_path = cheats_repo_paths[folder_index].clone();
git::pull(&repo_path)?;
} else {
eprintln!("I don't find {} locally, are you sure you downloaded it?", &name);
}
return Ok(());
}
// We haven't been given a name -> We synchronize every cheatsheet repository we've found
for cheat_repo in cheats_repo_paths {
eprintln!("Pulling the latest version of {}", cheat_repo);
git::pull(&cheat_repo)?;
}
// TODO: Sanitize the cheatsheet folder of any file that is not a cheat file
// Ref: https://github.com/denisidoro/navi/issues/733
Ok(())
}

View file

@ -27,6 +27,8 @@ pub fn meta(uri: &str) -> (String, String, String) {
(actual_uri, user.to_string(), repo)
}
/// Retrieves the remote URI of a git repository
/// Works best with a repository containing only one remote.
pub fn get_remote(uri: &str) -> Result<String> {
// We consider the repository having only one remote
// In case of multiple occurrences, we return the first one and discard the others
@ -63,6 +65,17 @@ pub fn get_remote(uri: &str) -> Result<String> {
Ok(remotes_uri[0].clone())
}
/// Pulls the latest version of a git repository
pub fn pull(uri: &str) -> Result<()> {
Command::new("git")
.current_dir(uri)
.args(["pull", "origin"])
.spawn()?
.wait()
.expect("Unable to git pull");
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;

View file

@ -26,3 +26,11 @@ impl EnvConfig {
}
}
}
/// A default implementation for EnvConfig
/// to satisfy cargo clippy.
impl Default for EnvConfig {
fn default() -> Self {
Self::new()
}
}

View file

@ -10,6 +10,7 @@ use regex::Regex;
use std::cell::RefCell;
use std::path::MAIN_SEPARATOR;
use crate::common::git;
use walkdir::WalkDir;
/// Multiple paths are joint by a platform-specific separator.
@ -114,6 +115,16 @@ pub fn cheat_paths(path: Option<String>) -> Result<String> {
}
}
/// Returns the cheats path defined at run time
pub fn running_cheats_path() -> String {
CONFIG.path().unwrap_or_else(|| {
// if we don't have a path, use the default value
let _cheats = default_cheat_pathbuf().unwrap();
_cheats.to_string()
})
}
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Here are other functions, unrelated to CLI commands (or at least not directly related)
@ -150,6 +161,54 @@ fn get_config_dir_by_platform() -> Result<PathBuf> {
}
}
/// Goes through the cheats path(s) defined within the configuration
/// and sends back any cheatsheet repository remote URI it finds.
pub fn local_cheatsheet_repositories() -> (Vec<String>, Vec<String>) {
let mut cheats_repos_uri: Vec<String> = Vec::new();
let mut cheats_repos_paths: Vec<String> = Vec::new();
let cheats = running_cheats_path();
// We're checking each given paths possible
for cheat_path in cheats.split(':') {
// If the path doesn't exist, continue to the next one
if !std::fs::exists(cheat_path).unwrap() {
continue;
}
let curr_dir = std::fs::read_dir(cheat_path).unwrap();
// We're checking subfolders -> they should contain at least one .cheat files
for entry in curr_dir {
let entry = entry.unwrap();
if entry.file_type().unwrap().is_dir() {
// If the directory doesn't have at least one cheat file -> ignore it and continue
if all_cheat_files(&entry.path()).is_empty() {
continue;
};
// If the directory have at least one cheat file -> add it to the list
// Note: for the list, we are registering the git remote name and not the
// folder name since we modify it internally.
let git_path = format!("{}/{}", &entry.path().display(), ".git");
let folder_path = entry.path().display().to_string();
if std::fs::exists(&git_path).unwrap() {
let remote_uri = git::get_remote(&entry.path().to_string()).unwrap();
cheats_repos_uri.push(remote_uri);
} else {
cheats_repos_uri.push(folder_path.clone());
}
cheats_repos_paths.push(folder_path);
}
}
}
(cheats_repos_uri, cheats_repos_paths)
}
pub fn tmp_pathbuf() -> Result<PathBuf> {
let mut root = default_cheat_pathbuf()?;
root.push("tmp");