feat: Fixes small issues and added the sync command

Signed-off-by: alexis-opolka <contact@alexis-opolka.dev>
This commit is contained in:
alexis-opolka 2026-03-12 13:48:27 +01:00
parent 01f374ca53
commit 5f4abc7c73
3 changed files with 70 additions and 33 deletions

View file

@ -162,8 +162,7 @@ pub fn main(uri: String, yes_flag: bool, branch: &Option<String>) -> Result<()>
})?;
}
println!("Temp cheats folder: {:?}", &tmp_repository_path_str);
println!("Final cheats folder: {:?}", cheat_pathbuf.to_string());
fs::remove_dir_all(&tmp_repository_pathbuf).with_context(|| format!("Unable to delete {}", &tmp_repository_path_str))?;
Ok(())
}

View file

@ -1,10 +1,10 @@
use crate::common::git;
use std::fs;
use std::path::MAIN_SEPARATOR;
use crate::filesystem::{all_cheat_files, all_git_files, local_cheatsheet_repositories};
use crate::prelude::*;
use git2::Repository;
use std::{fs, path};
use walkdir::WalkDir;
use crate::common::git::reset_to_remote_state;
use crate::commands::repo::{HELP_NO_GIVEN_REPOSITORIES_FOUND, HELP_NO_REPOSITORIES_FOUND};
pub fn main(uri: Option<String>) -> Result<()> {
@ -21,19 +21,13 @@ pub fn main(uri: Option<String>) -> Result<()> {
if uri.is_some() {
let given_uri = uri.as_ref().unwrap();
// let repository = cheat_repos.iter()
// .filter(|repository| repository == &given_uri)
// .next();
let repository = cheat_repos.iter()
.filter(|repository| repository.uri().eq(given_uri))
.next().unwrap();
println!("Repo: {given_uri:#}");
let repository_object = Repository::open(repository.path())?;
// repository.map(|_| {
// let cheat_repo_index = cheats_repo_uris.iter().position(|repository| repository == given_uri);
// let given_repository = Repository::open(Path::new(cheats_repo_paths.get(cheat_repo_index.unwrap()).unwrap()));
// let repo_object = given_repository.as_ref().unwrap();
//
// synchronize(repo_object).expect("Unable to sync repository");
// }).expect(format!("{}", HELP_NO_GIVEN_REPOSITORIES_FOUND).as_str());
synchronize(&repository_object).expect("Unable to sync repository");
return Ok(());
}
@ -50,13 +44,36 @@ pub fn main(uri: Option<String>) -> Result<()> {
}
fn synchronize(cheat_repo: &Repository) -> Result<()> {
let cheat_path = cheat_repo.path();
eprintln!("Checking repo {:?}", &cheat_path);
let repo_path = cheat_repo.path().parent().unwrap();
// We retrieve all existing cheat files
let cheat_files = all_cheat_files(&cheat_path);
let git_files = all_git_files(cheat_path);
let mut cheat_dirs: Vec<String> = Vec::new();
// 1 - Before doing an actual reset, we remove the current cheatsheets
let mut cheat_files = all_cheat_files(repo_path);
for cheat_file in cheat_files {
fs::remove_file(Path::new(cheat_file.as_str()))
.with_context(|| format!("Unable to remove {}", cheat_file))?;
}
// 2 - We reset the repository to its remote equivalent
reset_to_remote_state(cheat_repo)?;
// 3 - We reshuffle the files
cheat_files = all_cheat_files(repo_path);
for cheat_file in cheat_files {
let source = Path::new(cheat_file.as_str());
let filename = cheat_file.replace(&format!("{}", &repo_path.to_str().unwrap()), "")
.replace(MAIN_SEPARATOR, "__");
let destination = repo_path.join(filename);
println!("[Repo::sync](DEBUG) - {} => {:?}", cheat_file, destination);
fs::copy(source, &destination).with_context(|| format!("Unable to copy {} to {}", cheat_file, destination.display()))?;
fs::remove_file(source).with_context(|| format!("Unable to remove {}", cheat_file))?;
}
Ok(())
}

View file

@ -1,8 +1,8 @@
use crate::common::shell::ShellSpawnError;
use crate::filesystem::remove_dir;
use crate::prelude::*;
use git2::Repository;
use std::fmt::Error;
use git2::{BranchType, Repository, ResetType};
use std::fmt::{Display, Error, Formatter};
use std::process::Command;
pub struct CheatRepositoryRecord {
@ -33,6 +33,12 @@ impl CheatRepositoryRecord {
}
}
impl Display for CheatRepositoryRecord {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{} -> {}", self.uri, self.path)
}
}
pub fn shallow_clone(remote_uri: &str, target: &str, branch: &Option<String>, overwrite: bool) -> Result<()> {
let target_path = PathBuf::from(target);
@ -54,18 +60,15 @@ pub fn shallow_clone(remote_uri: &str, target: &str, branch: &Option<String>, ov
);
}
println!("Cloning {} to {}", remote_uri, target);
let repository =
Repository::clone(remote_uri, target).expect(format!("Failed to clone {}", remote_uri).as_str());
// Prepare fetch options.
let mut builder = git2::build::RepoBuilder::new();
if branch.is_some() {
let branch = branch.as_ref().unwrap();
repository
.set_head(branch)
.context("Failed to set the HEAD to the given branch")
.expect("Failed to set the HEAD to the given branch");
builder.branch(branch.as_ref().unwrap());
}
println!("Cloning {} to {}", remote_uri, target);
builder.clone(remote_uri, target.as_ref()).expect(format!("Failed to clone {}", remote_uri).as_str());
Ok(())
}
@ -111,6 +114,24 @@ pub fn get_remote_uri(repository: Repository) -> String {
returned_remotes.get(0).unwrap().to_string()
}
/// Takes a repository instance and updates it to its remote equivalent with a hard reset.
///
/// 3 steps function:
/// - Fetch latest tree state
/// - Grabs the latest commit ID
/// - hard reset to the latest commit
pub fn reset_to_remote_state(repository: &Repository) -> Result<()> {
repository.find_remote("origin")?.fetch(&["main"], None, None)?;
// Get the latest commit ID from the remote branch (origin/main)
let latest_commit_id = repository.find_branch("origin/main", BranchType::Remote)?.into_reference().peel_to_commit()?;
// Hard reset onto this commit
repository.reset(latest_commit_id.as_object(), ResetType::Hard, None)?;
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;