mod git_tools; use std::env; use std::fs; use std::io::{Result, Error, ErrorKind}; use std::path::Path; use std::process::exit; use git_tools::*; fn main() -> Result<()> { if let Ok(cwd) = env::current_dir() { if let Err(e) = scan_directories_to_synchronize(&cwd) { eprintln!("Could not check directory for git repositories: {}", e); exit(1); } } else { eprintln!("Could not find current directory."); exit(1); } Ok(()) } fn scan_directories_to_synchronize(path: &Path) -> Result<()> { let sync_ignore_file = path.join(".syncignore"); if sync_ignore_file.exists() { return Ok(()) } let git_directory = path.join(".git"); if git_directory.exists() { if let Err(e) = synchronize_directory(&path) { let relative_path = get_relative_path(path).unwrap(); eprintln!("Sync failed for {:?}. {}", relative_path, e); } } else { for entry in fs::read_dir(path)? { let path = entry?.path(); if path.is_dir() { scan_directories_to_synchronize(&path)?; } } } Ok(()) } fn synchronize_directory(path: &Path) -> Result<()> { let previous_branch = git_save_previous_branch(path)?; git_checkout(path, "main")?; let result = attempt_synchronization(path); git_checkout(path, &previous_branch)?; result } fn attempt_synchronization(path: &Path) -> Result<()> { let relative_path = get_relative_path(path).unwrap(); eprint!("{:?}. ", relative_path); let previous_commit = get_commit(path, "HEAD")?; git_fetch(path)?; let remote_commit = get_commit(path, "origin/main")?; if previous_commit == remote_commit { eprintln!("Already up to date."); return Ok(()); } match git_check_for_conflicts(path) { Ok(conflicts) => { if !conflicts { git_merge(path)?; let new_commit = get_commit(path, "HEAD")?; eprint!("Merged origin {:?}->{:?}. ", previous_commit, new_commit); git_push(path)?; eprintln!("Pushed."); } else { return Err(Error::new(ErrorKind::Other, "Conflicts detected")); } }, Err(e) => { return Err(e); } } Ok(()) } // Path Helpers fn get_relative_path(path: &Path) -> Option { let cwd = env::current_dir().unwrap(); path.strip_prefix(cwd) .ok() .and_then(|p| p.to_str()) .map(|s| s.to_string()) }