diff --git a/src/process.rs b/src/process.rs index 0c336b6..a6d7dfa 100644 --- a/src/process.rs +++ b/src/process.rs @@ -43,3 +43,45 @@ pub fn exec_result(command: &str, args: Vec<&str>) -> Result Vec { + output + .split('\n') + .filter(|s| !s.is_empty() && s.contains("refs/heads/")) + .map(|s| s.split(' ').collect::>()[1].replace("refs/heads/", "")) + .collect() +} + +fn parse_current_branches(output: &str) -> Vec { + output + .split('\n') + .filter(|s| !s.is_empty()) + .map(|s| s.replace(['*', ' '], "")) + .collect() +} + +fn find_main_branch(branches: &[String]) -> &str { + branches + .iter() + .find(|b| *b == "develop" || *b == "master") + .map_or("main", |b| b) +} + #[derive(Error, Debug)] pub enum SyncError { #[error("ProcessError: {0}")] @@ -37,22 +60,14 @@ impl Sync { vec!["bundle", "list-heads", &self.bundle.display().to_string()], )?; - self.bundle_branches = bundle_branches_str - .split("\n") - .filter(|s| !s.is_empty() && s.contains("refs/heads/")) - .map(|s| s.split(" ").collect::>()[1].replace("refs/heads/", "")) - .collect(); + self.bundle_branches = parse_bundle_branches(&bundle_branches_str); Ok(()) } fn get_current_branches(&mut self) -> Result<(), SyncError> { let current_branches_str = exec_result("git", vec!["branch"])?; - self.current_branches = current_branches_str - .split("\n") - .filter(|s| !s.is_empty()) - .map(|s| s.replace("*", "").replace(" ", "")) - .collect(); + self.current_branches = parse_current_branches(¤t_branches_str); Ok(()) } @@ -65,11 +80,7 @@ impl Sync { fn checkout_to_main_branch(&self) -> Result<(), SyncError> { let current_branch = self.get_current_branch()?; - let main_branch = self - .current_branches - .iter() - .find(|b| *b == "develop" || *b == "master") - .map_or("main", |b| b); + let main_branch = find_main_branch(&self.current_branches); if !exec_result("git", vec!["status", "--porcelain"])?.is_empty() { exec("git", vec!["stash", "--include-untracked"])?; @@ -150,3 +161,100 @@ impl Sync { Ok(()) } } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_parse_bundle_branches() { + let output = + "abc123 refs/heads/main\ndef456 refs/heads/feature-branch\nghi789 refs/heads/develop\n"; + let branches = parse_bundle_branches(output); + + assert_eq!(branches.len(), 3); + assert!(branches.contains(&"main".to_string())); + assert!(branches.contains(&"feature-branch".to_string())); + assert!(branches.contains(&"develop".to_string())); + } + + #[test] + fn test_parse_bundle_branches_empty() { + let output = ""; + let branches = parse_bundle_branches(output); + assert!(branches.is_empty()); + } + + #[test] + fn test_parse_bundle_branches_filters_non_heads() { + let output = "abc123 refs/tags/v1.0.0\ndef456 refs/heads/main\n"; + let branches = parse_bundle_branches(output); + + assert_eq!(branches.len(), 1); + assert!(branches.contains(&"main".to_string())); + } + + #[test] + fn test_parse_current_branches() { + let output = " feature-branch\n* main\n develop\n"; + let branches = parse_current_branches(output); + + assert_eq!(branches.len(), 3); + assert!(branches.contains(&"main".to_string())); + assert!(branches.contains(&"feature-branch".to_string())); + assert!(branches.contains(&"develop".to_string())); + } + + #[test] + fn test_parse_current_branches_empty() { + let output = ""; + let branches = parse_current_branches(output); + + assert!(branches.is_empty()); + } + + #[test] + fn test_find_main_branch_with_develop() { + let branches = vec![ + "feature".to_string(), + "develop".to_string(), + "test".to_string(), + ]; + + assert_eq!(find_main_branch(&branches), "develop"); + } + + #[test] + fn test_find_main_branch_with_master() { + let branches = vec![ + "feature".to_string(), + "master".to_string(), + "test".to_string(), + ]; + + assert_eq!(find_main_branch(&branches), "master"); + } + + #[test] + fn test_find_main_branch_fallback_to_main() { + let branches = vec!["feature".to_string(), "test".to_string()]; + + assert_eq!(find_main_branch(&branches), "main"); + } + + #[test] + fn test_find_main_branch_empty() { + let branches: Vec = vec![]; + + assert_eq!(find_main_branch(&branches), "main"); + } + + #[test] + fn test_sync_new() { + let sync = Sync::new(PathBuf::from("/tmp/test.bundle")); + + assert_eq!(sync.bundle, PathBuf::from("/tmp/test.bundle")); + assert!(sync.bundle_branches.is_empty()); + assert!(sync.current_branches.is_empty()); + } +}