From 5f1d78099b11212917f05f2df205d53cb0cbf39f Mon Sep 17 00:00:00 2001 From: "Tristan Poland (Trident_For_U)" <34868944+tristanpoland@users.noreply.github.com> Date: Mon, 21 Oct 2024 11:56:56 -0400 Subject: [PATCH 1/6] Adding the cd command --- src/cli.rs | 10 ++++- src/core/api.rs | 65 ++++++++++++++++++++++++++++++++- src/main.rs | 12 ++++++ tests/cd.rs | 89 +++++++++++++++++++++++++++++++++++++++++++++ tests/common/mod.rs | 6 +++ 5 files changed, 180 insertions(+), 2 deletions(-) create mode 100644 tests/cd.rs diff --git a/src/cli.rs b/src/cli.rs index 1ea9b0b..8a2737b 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -68,5 +68,13 @@ pub enum Commands { #[arg(short, long, group = "output")] #[arg(default_value_t = false)] remotes: bool - } + }, + /// Change directory to a tracked repository + Cd { + /// Name of the repository to change to + #[arg(required = true)] + repo_name: String, + }, + /// Enable CD functionality by adding an alias to your shell configuration + EnableCd } diff --git a/src/core/api.rs b/src/core/api.rs index 9c253ee..841618c 100644 --- a/src/core/api.rs +++ b/src/core/api.rs @@ -14,9 +14,11 @@ use crate::utils::{ repos_valid }; -use std::fs::{self, OpenOptions}; +use std::fs::{self, OpenOptions, File}; use std::io::Write as _; +use std::io::Read; use std::path::Path; +use std::env; /// Scans only specified directories pub fn scan_dirs(mut dirs: Vec, tracking_file: &TrackingFile, scan_hidden: bool) -> Result<(), String> { @@ -219,3 +221,64 @@ pub async fn check_all(tracking_file: &TrackingFile, flags: &[bool]) -> Result<( Ok(()) } + +/// Changes the current directory to the specified repository's path +pub fn cd_to_repo(repo_name: &str, tracking_file: &TrackingFile) -> Result<(), String> { + if tracking_file.contents.is_empty() { + return Err(String::from("No repository is being tracked")); + } + + let repo_path = tracking_file.contents + .lines() + .find(|line| Path::new(line).file_name().and_then(|name| name.to_str()) == Some(repo_name)) + .ok_or_else(|| format!("Repository '{}' not found in tracking file", repo_name))?; + + env::set_current_dir(repo_path) + .map_err(|e| format!("Failed to change directory to '{}': {}", repo_path, e))?; + + println!("Changed directory to: {}", repo_path); + Ok(()) +} + +/// Enables the CD functionality by adding an alias or function to the user's shell configuration +pub fn enable_cd() -> Result<(), String> { + let home_dir = env::var("HOME").map_err(|_| "Failed to get home directory")?; + let shell = env::var("SHELL").map_err(|_| "Failed to get current shell")?; + + let (config_file, alias_content) = if shell.ends_with("bash") { + ( + format!("{}/.bashrc", home_dir), + "\ngitconform() {\n if [[ $1 == \"cd\" ]]; then\n cd \"$(/path/to/git-conform cd \"${@:2}\")\" || return\n else\n /path/to/git-conform \"$@\"\n fi\n}\n" + ) + } else if shell.ends_with("zsh") { + ( + format!("{}/.zshrc", home_dir), + "\ngitconform() {\n if [[ $1 == \"cd\" ]]; then\n cd \"$(/path/to/git-conform cd \"${@:2}\")\" || return\n else\n /path/to/git-conform \"$@\"\n fi\n}\n" + ) + } else { + return Err(format!("Unsupported shell: {}", shell)); + }; + + // Check if the alias already exists + let mut file_content = String::new(); + File::open(&config_file) + .and_then(|mut file| file.read_to_string(&mut file_content)) + .map_err(|e| format!("Failed to read shell config file: {}", e))?; + + if file_content.contains("gitconform()") { + println!("CD functionality is already enabled."); + return Ok(()); + } + + // Append the alias to the shell configuration file + let mut file = OpenOptions::new() + .append(true) + .open(&config_file) + .map_err(|e| format!("Failed to open shell config file: {}", e))?; + + file.write_all(alias_content.as_bytes()) + .map_err(|e| format!("Failed to write to shell config file: {}", e))?; + + println!("CD functionality enabled. Please restart your shell or run 'source {}' to apply changes.", config_file); + Ok(()) +} \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 7c1e77d..8013288 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,6 +7,8 @@ use crate::core::api::{ scan_all, list, add, + cd_to_repo, + enable_cd, remove_repos, remove_all, check_repos, @@ -128,6 +130,16 @@ async fn main() { else if let Err(e) = check_repos(repos.to_owned(), &[*status, *remotes]).await { handle_error(&e, 6); } + }, + Commands::Cd { repo_name } => { + if let Err(e) = cd_to_repo(&repo_name, &tracking_file) { + handle_error(&e, 7); + } + }, + Commands::EnableCd => { + if let Err(e) = enable_cd() { + handle_error(&e, 8); + } } }; } diff --git a/tests/cd.rs b/tests/cd.rs new file mode 100644 index 0000000..3297bb2 --- /dev/null +++ b/tests/cd.rs @@ -0,0 +1,89 @@ +mod common; + +use git_conform::core::api::{add, cd_to_repo}; +use std::fs; +use std::path::Path; +use std::env; +use serial_test::serial; + +#[test] +#[serial] +fn case_cd_real() { + let (_home_dir, tracking_file, tests_dir) = common::setup().unwrap(); + // Remove the tracking file if it already exists + if Path::new(tracking_file.path.as_str()).try_exists().unwrap() { + fs::remove_file(&tracking_file.path).unwrap(); + } + + // Add some repositories to the tracking file + let mut repos: Vec = Vec::new(); + for n in 1..=3 { + repos.push(format!("{}/repo{}", tests_dir, n)); + } + assert_eq!(add(repos, &tracking_file), Ok(())); + + // Test cd_to_repo for each added repository + for n in 1..=3 { + let repo_name = format!("repo{}", n); + assert_eq!(cd_to_repo(&repo_name, &tracking_file), Ok(())); + assert_eq!(env::current_dir().unwrap(), Path::new(&format!("{}/repo{}", tests_dir, n))); + } + + common::cleanup(&tests_dir).unwrap(); +} + +#[test] +fn case_cd_fake() { + let (_home_dir, tracking_file, tests_dir) = common::setup().unwrap(); + + // Try to cd to a non-existent repository + let fake_repo = "fake_repo"; + assert_eq!( + cd_to_repo(fake_repo, &tracking_file), + Err(format!("Repository '{}' not found in tracking file", fake_repo)) + ); + + common::cleanup(&tests_dir).unwrap(); +} + +#[test] +fn case_cd_empty_tracking_file() { + let (_home_dir, tracking_file, tests_dir) = common::setup().unwrap(); + + // Ensure the tracking file is empty + fs::write(&tracking_file.path, "").unwrap(); + + // Try to cd to any repository with an empty tracking file + let repo_name = "any_repo"; + assert_eq!( + cd_to_repo(repo_name, &tracking_file), + Err(String::from("No repository is being tracked")) + ); + + common::cleanup(&tests_dir).unwrap(); +} + +#[test] +#[serial] +fn case_cd_multiple_repos_same_name() { + let (_home_dir, tracking_file, tests_dir) = common::setup().unwrap(); + // Remove the tracking file if it already exists + if Path::new(tracking_file.path.as_str()).try_exists().unwrap() { + fs::remove_file(&tracking_file.path).unwrap(); + } + + // Add repositories with the same name in different directories + let repos = vec![ + format!("{}/dir1/repo1", tests_dir), + format!("{}/dir2/repo1", tests_dir), + ]; + assert_eq!(add(repos, &tracking_file), Ok(())); + + // Test cd_to_repo with a repo name that exists multiple times + let repo_name = "repo1"; + assert_eq!(cd_to_repo(repo_name, &tracking_file), Ok(())); + // It should change to the first occurrence in the tracking file + assert_eq!(env::current_dir().unwrap(), Path::new(&format!("{}/dir1/repo1", tests_dir))); + + common::cleanup(&tests_dir).unwrap(); +} \ No newline at end of file diff --git a/tests/common/mod.rs b/tests/common/mod.rs index f99f48d..7dd0d43 100644 --- a/tests/common/mod.rs +++ b/tests/common/mod.rs @@ -108,3 +108,9 @@ pub fn setup() -> Result<(String, TrackingFile, String), String> { Ok((home_dir, tracking_file, tests_dir)) } + +pub fn cleanup(tests_dir: &str) -> Result<(), String> { + fs::remove_dir_all(tests_dir) + .map_err(|e| format!("Failed to remove test directory: {}", e))?; + Ok(()) +} \ No newline at end of file From 5a88b1baf2aee09ae5556540d1642aec9e6938d2 Mon Sep 17 00:00:00 2001 From: "Tristan Poland (Trident_For_U)" <34868944+tristanpoland@users.noreply.github.com> Date: Mon, 21 Oct 2024 12:03:41 -0400 Subject: [PATCH 2/6] Update cd.rs --- tests/cd.rs | 61 +++++++++++++++++++++++++++++------------------------ 1 file changed, 34 insertions(+), 27 deletions(-) diff --git a/tests/cd.rs b/tests/cd.rs index 3297bb2..023b6d4 100644 --- a/tests/cd.rs +++ b/tests/cd.rs @@ -6,32 +6,6 @@ use std::path::Path; use std::env; use serial_test::serial; -#[test] -#[serial] -fn case_cd_real() { - let (_home_dir, tracking_file, tests_dir) = common::setup().unwrap(); - // Remove the tracking file if it already exists - if Path::new(tracking_file.path.as_str()).try_exists().unwrap() { - fs::remove_file(&tracking_file.path).unwrap(); - } - - // Add some repositories to the tracking file - let mut repos: Vec = Vec::new(); - for n in 1..=3 { - repos.push(format!("{}/repo{}", tests_dir, n)); - } - assert_eq!(add(repos, &tracking_file), Ok(())); - - // Test cd_to_repo for each added repository - for n in 1..=3 { - let repo_name = format!("repo{}", n); - assert_eq!(cd_to_repo(&repo_name, &tracking_file), Ok(())); - assert_eq!(env::current_dir().unwrap(), Path::new(&format!("{}/repo{}", tests_dir, n))); - } - - common::cleanup(&tests_dir).unwrap(); -} - #[test] fn case_cd_fake() { let (_home_dir, tracking_file, tests_dir) = common::setup().unwrap(); @@ -40,7 +14,7 @@ fn case_cd_fake() { let fake_repo = "fake_repo"; assert_eq!( cd_to_repo(fake_repo, &tracking_file), - Err(format!("Repository '{}' not found in tracking file", fake_repo)) + Err(String::from("No repository is being tracked")) ); common::cleanup(&tests_dir).unwrap(); @@ -63,6 +37,32 @@ fn case_cd_empty_tracking_file() { common::cleanup(&tests_dir).unwrap(); } +#[test] +#[serial] +fn case_cd_real() { + let (_home_dir, tracking_file, tests_dir) = common::setup().unwrap(); + // Remove the tracking file if it already exists + if Path::new(tracking_file.path.as_str()).try_exists().unwrap() { + fs::remove_file(&tracking_file.path).unwrap(); + } + + // Add some repositories to the tracking file + let mut repos: Vec = Vec::new(); + for n in 1..=3 { + repos.push(format!("{}/repo{}", tests_dir, n)); + } + assert_eq!(add(repos, &tracking_file), Ok(())); + + // Test cd_to_repo for each added repository + for n in 1..=3 { + let repo_name = format!("repo{}", n); + assert_eq!(cd_to_repo(&repo_name, &tracking_file), Ok(())); + assert_eq!(env::current_dir().unwrap(), Path::new(&format!("{}/repo{}", tests_dir, n))); + } + + common::cleanup(&tests_dir).unwrap(); +} + #[test] #[serial] fn case_cd_multiple_repos_same_name() { @@ -72,6 +72,13 @@ fn case_cd_multiple_repos_same_name() { fs::remove_file(&tracking_file.path).unwrap(); } + // Create directories and initialize git repos + for dir in ["dir1", "dir2"].iter() { + let repo_path = format!("{}/{}/repo1", tests_dir, dir); + fs::create_dir_all(&repo_path).unwrap(); + git2::Repository::init(&repo_path).unwrap(); + } + // Add repositories with the same name in different directories let repos = vec![ format!("{}/dir1/repo1", tests_dir), From dd4ef7a9de0effbfef26959c73c37e0d2db45f01 Mon Sep 17 00:00:00 2001 From: "Tristan Poland (Trident_For_U)" <34868944+tristanpoland@users.noreply.github.com> Date: Mon, 21 Oct 2024 14:23:03 -0400 Subject: [PATCH 3/6] Updated CD --- src/core/api.rs | 37 ++++++++----------------------------- src/main.rs | 5 +++-- 2 files changed, 11 insertions(+), 31 deletions(-) diff --git a/src/core/api.rs b/src/core/api.rs index 841618c..e063ad1 100644 --- a/src/core/api.rs +++ b/src/core/api.rs @@ -222,22 +222,15 @@ pub async fn check_all(tracking_file: &TrackingFile, flags: &[bool]) -> Result<( Ok(()) } -/// Changes the current directory to the specified repository's path -pub fn cd_to_repo(repo_name: &str, tracking_file: &TrackingFile) -> Result<(), String> { +pub fn cd_to_repo(repo_name: &str, tracking_file: &TrackingFile) -> Result { if tracking_file.contents.is_empty() { return Err(String::from("No repository is being tracked")); } - let repo_path = tracking_file.contents + tracking_file.contents .lines() .find(|line| Path::new(line).file_name().and_then(|name| name.to_str()) == Some(repo_name)) - .ok_or_else(|| format!("Repository '{}' not found in tracking file", repo_name))?; - - env::set_current_dir(repo_path) - .map_err(|e| format!("Failed to change directory to '{}': {}", repo_path, e))?; - - println!("Changed directory to: {}", repo_path); - Ok(()) + .ok_or_else(|| format!("Repository '{}' not found in tracking file", repo_name)) } /// Enables the CD functionality by adding an alias or function to the user's shell configuration @@ -248,36 +241,22 @@ pub fn enable_cd() -> Result<(), String> { let (config_file, alias_content) = if shell.ends_with("bash") { ( format!("{}/.bashrc", home_dir), - "\ngitconform() {\n if [[ $1 == \"cd\" ]]; then\n cd \"$(/path/to/git-conform cd \"${@:2}\")\" || return\n else\n /path/to/git-conform \"$@\"\n fi\n}\n" + "\ngitconform_cd() {\n cd \"$(git-conform cd \"$1\")\" || return\n}\n" ) } else if shell.ends_with("zsh") { ( format!("{}/.zshrc", home_dir), - "\ngitconform() {\n if [[ $1 == \"cd\" ]]; then\n cd \"$(/path/to/git-conform cd \"${@:2}\")\" || return\n else\n /path/to/git-conform \"$@\"\n fi\n}\n" + "\ngitconform_cd() {\n cd \"$(git-conform cd \"$1\")\" || return\n}\n" ) } else { return Err(format!("Unsupported shell: {}", shell)); }; - // Check if the alias already exists - let mut file_content = String::new(); - File::open(&config_file) - .and_then(|mut file| file.read_to_string(&mut file_content)) - .map_err(|e| format!("Failed to read shell config file: {}", e))?; - - if file_content.contains("gitconform()") { - println!("CD functionality is already enabled."); - return Ok(()); - } - - // Append the alias to the shell configuration file - let mut file = OpenOptions::new() + fs::OpenOptions::new() .append(true) .open(&config_file) - .map_err(|e| format!("Failed to open shell config file: {}", e))?; - - file.write_all(alias_content.as_bytes()) - .map_err(|e| format!("Failed to write to shell config file: {}", e))?; + .and_then(|mut file| file.write_all(alias_content.as_bytes())) + .map_err(|e| format!("Failed to update shell config: {}", e))?; println!("CD functionality enabled. Please restart your shell or run 'source {}' to apply changes.", config_file); Ok(()) diff --git a/src/main.rs b/src/main.rs index 8013288..bced107 100644 --- a/src/main.rs +++ b/src/main.rs @@ -132,8 +132,9 @@ async fn main() { } }, Commands::Cd { repo_name } => { - if let Err(e) = cd_to_repo(&repo_name, &tracking_file) { - handle_error(&e, 7); + match cd_to_repo(&repo_name, &tracking_file) { + Ok(path) => println!("{}", path), + Err(e) => eprintln!("Error: {}", e), } }, Commands::EnableCd => { From 2a6930596f25e56cfec72253781751108b7e0caf Mon Sep 17 00:00:00 2001 From: "Tristan Poland (Trident_For_U)" <34868944+tristanpoland@users.noreply.github.com> Date: Mon, 21 Oct 2024 14:25:07 -0400 Subject: [PATCH 4/6] updated to fix errors --- src/core/api.rs | 4 ++-- tests/cd.rs | 29 +++++++++++++++++++---------- 2 files changed, 21 insertions(+), 12 deletions(-) diff --git a/src/core/api.rs b/src/core/api.rs index e063ad1..859f203 100644 --- a/src/core/api.rs +++ b/src/core/api.rs @@ -14,9 +14,8 @@ use crate::utils::{ repos_valid }; -use std::fs::{self, OpenOptions, File}; +use std::fs::{self, OpenOptions}; use std::io::Write as _; -use std::io::Read; use std::path::Path; use std::env; @@ -230,6 +229,7 @@ pub fn cd_to_repo(repo_name: &str, tracking_file: &TrackingFile) -> Result = Vec::new(); for n in 1..=3 { - repos.push(format!("{}/repo{}", tests_dir, n)); + let repo_path = format!("{}/repo{}", tests_dir, n); + fs::create_dir_all(&repo_path).unwrap(); + // Initialize git repository + Command::new("git") + .args(&["init", &repo_path]) + .output() + .expect("Failed to initialize git repository"); + repos.push(repo_path); } assert_eq!(add(repos, &tracking_file), Ok(())); // Test cd_to_repo for each added repository for n in 1..=3 { let repo_name = format!("repo{}", n); - assert_eq!(cd_to_repo(&repo_name, &tracking_file), Ok(())); - assert_eq!(env::current_dir().unwrap(), Path::new(&format!("{}/repo{}", tests_dir, n))); + let expected_path = format!("{}/repo{}", tests_dir, n); + assert_eq!(cd_to_repo(&repo_name, &tracking_file), Ok(expected_path)); } common::cleanup(&tests_dir).unwrap(); @@ -76,7 +83,10 @@ fn case_cd_multiple_repos_same_name() { for dir in ["dir1", "dir2"].iter() { let repo_path = format!("{}/{}/repo1", tests_dir, dir); fs::create_dir_all(&repo_path).unwrap(); - git2::Repository::init(&repo_path).unwrap(); + Command::new("git") + .args(&["init", &repo_path]) + .output() + .expect("Failed to initialize git repository"); } // Add repositories with the same name in different directories @@ -88,9 +98,8 @@ fn case_cd_multiple_repos_same_name() { // Test cd_to_repo with a repo name that exists multiple times let repo_name = "repo1"; - assert_eq!(cd_to_repo(repo_name, &tracking_file), Ok(())); - // It should change to the first occurrence in the tracking file - assert_eq!(env::current_dir().unwrap(), Path::new(&format!("{}/dir1/repo1", tests_dir))); + let expected_path = format!("{}/dir1/repo1", tests_dir); + assert_eq!(cd_to_repo(repo_name, &tracking_file), Ok(expected_path)); common::cleanup(&tests_dir).unwrap(); } \ No newline at end of file From 16f0e008ffdcdc69699fa93fea5666e0d092305b Mon Sep 17 00:00:00 2001 From: "Tristan Poland (Trident_For_U)" <34868944+tristanpoland@users.noreply.github.com> Date: Mon, 21 Oct 2024 14:28:47 -0400 Subject: [PATCH 5/6] CD updates --- src/core/api.rs | 23 ++++++++++++++--------- src/main.rs | 2 +- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/src/core/api.rs b/src/core/api.rs index 859f203..dc17070 100644 --- a/src/core/api.rs +++ b/src/core/api.rs @@ -238,15 +238,20 @@ pub fn enable_cd() -> Result<(), String> { let home_dir = env::var("HOME").map_err(|_| "Failed to get home directory")?; let shell = env::var("SHELL").map_err(|_| "Failed to get current shell")?; - let (config_file, alias_content) = if shell.ends_with("bash") { + let (config_file, function_content) = if shell.ends_with("bash") || shell.ends_with("zsh") { ( - format!("{}/.bashrc", home_dir), - "\ngitconform_cd() {\n cd \"$(git-conform cd \"$1\")\" || return\n}\n" - ) - } else if shell.ends_with("zsh") { - ( - format!("{}/.zshrc", home_dir), - "\ngitconform_cd() {\n cd \"$(git-conform cd \"$1\")\" || return\n}\n" + format!("{}/.{}rc", home_dir, shell.split('/').last().unwrap()), + r#" +gitconform_cd() { + local repo_path + repo_path=$(git-conform cd "$1") + if [ $? -eq 0 ]; then + cd "$repo_path" || return + else + echo "$repo_path" # This will print the error message + fi +} +"# ) } else { return Err(format!("Unsupported shell: {}", shell)); @@ -255,7 +260,7 @@ pub fn enable_cd() -> Result<(), String> { fs::OpenOptions::new() .append(true) .open(&config_file) - .and_then(|mut file| file.write_all(alias_content.as_bytes())) + .and_then(|mut file| file.write_all(function_content.as_bytes())) .map_err(|e| format!("Failed to update shell config: {}", e))?; println!("CD functionality enabled. Please restart your shell or run 'source {}' to apply changes.", config_file); diff --git a/src/main.rs b/src/main.rs index bced107..aaf7e93 100644 --- a/src/main.rs +++ b/src/main.rs @@ -139,7 +139,7 @@ async fn main() { }, Commands::EnableCd => { if let Err(e) = enable_cd() { - handle_error(&e, 8); + eprintln!("Error enabling CD functionality: {}", e); } } }; From dcd3c5bb18de584b63cbf57289d25530ad3f816e Mon Sep 17 00:00:00 2001 From: tristanpoland <34868944+tristanpoland@users.noreply.github.com> Date: Mon, 21 Oct 2024 14:56:17 -0400 Subject: [PATCH 6/6] Finished CD tests --- src/core/api.rs | 20 +++++-- src/main.rs | 2 +- tests/cd.rs | 138 +++++++++++++++++++++++++++++------------------- 3 files changed, 99 insertions(+), 61 deletions(-) diff --git a/src/core/api.rs b/src/core/api.rs index dc17070..f89de89 100644 --- a/src/core/api.rs +++ b/src/core/api.rs @@ -242,14 +242,24 @@ pub fn enable_cd() -> Result<(), String> { ( format!("{}/.{}rc", home_dir, shell.split('/').last().unwrap()), r#" -gitconform_cd() { +alias gls='git conform ls' +alias gcd='git_conform_cd' + +git_conform_cd() { + if [ -z "$1" ]; then + echo "Usage: git_conform_cd " + return 1 + fi + local repo_path repo_path=$(git-conform cd "$1") - if [ $? -eq 0 ]; then - cd "$repo_path" || return - else - echo "$repo_path" # This will print the error message + + if [ $? -ne 0 ]; then + echo "$repo_path" # This will be the error message + return 1 fi + + cd "$repo_path" || return 1 } "# ) diff --git a/src/main.rs b/src/main.rs index aaf7e93..7574054 100644 --- a/src/main.rs +++ b/src/main.rs @@ -141,6 +141,6 @@ async fn main() { if let Err(e) = enable_cd() { eprintln!("Error enabling CD functionality: {}", e); } - } + }, }; } diff --git a/tests/cd.rs b/tests/cd.rs index 84401b5..c55a8a5 100644 --- a/tests/cd.rs +++ b/tests/cd.rs @@ -1,31 +1,65 @@ +mod common; + use git_conform::core::api::{add, cd_to_repo}; +use git_conform::utils::TrackingFile; use std::fs; use std::path::Path; -use std::process::Command; use serial_test::serial; -mod common; +#[test] +#[serial] +fn test_cd_to_existing_repo() { + let (_home_dir, mut tracking_file, tests_dir) = common::setup().unwrap(); + + // Add some repositories to the tracking file + let repos = vec![ + format!("{}/repo1", tests_dir), + format!("{}/repo2", tests_dir), + format!("{}/repo3", tests_dir), + ]; + assert!(add(repos.clone(), &tracking_file).is_ok()); + + // Manually update tracking_file contents + tracking_file.contents = repos.join("\n"); + + // Test cd_to_repo for each added repository + for n in 1..=3 { + let repo_name = format!("repo{}", n); + let expected_path = format!("{}/repo{}", tests_dir, n); + assert_eq!(cd_to_repo(&repo_name, &tracking_file), Ok(expected_path)); + } + + common::cleanup(&tests_dir).unwrap(); +} #[test] -fn case_cd_fake() { - let (_home_dir, tracking_file, tests_dir) = common::setup().unwrap(); +#[serial] +fn test_cd_to_nonexistent_repo() { + let (_home_dir, mut tracking_file, tests_dir) = common::setup().unwrap(); + // Add a repository to ensure the tracking file is not empty + let repo = format!("{}/repo1", tests_dir); + assert!(add(vec![repo.clone()], &tracking_file).is_ok()); + + // Manually update tracking_file contents + tracking_file.contents = repo; + // Try to cd to a non-existent repository let fake_repo = "fake_repo"; assert_eq!( cd_to_repo(fake_repo, &tracking_file), - Err(String::from("No repository is being tracked")) + Err(format!("Repository '{}' not found in tracking file", fake_repo)) ); common::cleanup(&tests_dir).unwrap(); } #[test] -fn case_cd_empty_tracking_file() { +#[serial] +fn test_cd_with_empty_tracking_file() { let (_home_dir, tracking_file, tests_dir) = common::setup().unwrap(); - // Ensure the tracking file is empty - fs::write(&tracking_file.path, "").unwrap(); + // Ensure the tracking file is empty (this is already the case after setup) // Try to cd to any repository with an empty tracking file let repo_name = "any_repo"; @@ -39,67 +73,61 @@ fn case_cd_empty_tracking_file() { #[test] #[serial] -fn case_cd_real() { - let (_home_dir, tracking_file, tests_dir) = common::setup().unwrap(); - // Remove the tracking file if it already exists - if Path::new(tracking_file.path.as_str()).try_exists().unwrap() { - fs::remove_file(&tracking_file.path).unwrap(); - } +fn test_cd_to_hidden_repo() { + let (_home_dir, mut tracking_file, tests_dir) = common::setup().unwrap(); - // Add some repositories to the tracking file - let mut repos: Vec = Vec::new(); - for n in 1..=3 { - let repo_path = format!("{}/repo{}", tests_dir, n); - fs::create_dir_all(&repo_path).unwrap(); - // Initialize git repository - Command::new("git") - .args(&["init", &repo_path]) - .output() - .expect("Failed to initialize git repository"); - repos.push(repo_path); - } - assert_eq!(add(repos, &tracking_file), Ok(())); + // Add a hidden repository to the tracking file + let hidden_repo = format!("{}/.hidden/repo1", tests_dir); + assert!(add(vec![hidden_repo.clone()], &tracking_file).is_ok()); - // Test cd_to_repo for each added repository - for n in 1..=3 { - let repo_name = format!("repo{}", n); - let expected_path = format!("{}/repo{}", tests_dir, n); - assert_eq!(cd_to_repo(&repo_name, &tracking_file), Ok(expected_path)); - } + // Manually update tracking_file contents + tracking_file.contents = hidden_repo.clone(); + + // Test cd_to_repo for the hidden repository + assert_eq!(cd_to_repo("repo1", &tracking_file), Ok(hidden_repo)); common::cleanup(&tests_dir).unwrap(); } #[test] #[serial] -fn case_cd_multiple_repos_same_name() { - let (_home_dir, tracking_file, tests_dir) = common::setup().unwrap(); - // Remove the tracking file if it already exists - if Path::new(tracking_file.path.as_str()).try_exists().unwrap() { - fs::remove_file(&tracking_file.path).unwrap(); - } - - // Create directories and initialize git repos - for dir in ["dir1", "dir2"].iter() { - let repo_path = format!("{}/{}/repo1", tests_dir, dir); - fs::create_dir_all(&repo_path).unwrap(); - Command::new("git") - .args(&["init", &repo_path]) - .output() - .expect("Failed to initialize git repository"); - } +fn test_cd_multiple_repos_same_name() { + let (_home_dir, mut tracking_file, tests_dir) = common::setup().unwrap(); // Add repositories with the same name in different directories let repos = vec![ - format!("{}/dir1/repo1", tests_dir), - format!("{}/dir2/repo1", tests_dir), + format!("{}/repo1", tests_dir), + format!("{}/.hidden/repo1", tests_dir), ]; - assert_eq!(add(repos, &tracking_file), Ok(())); + assert!(add(repos.clone(), &tracking_file).is_ok()); + + // Manually update tracking_file contents + tracking_file.contents = repos.join("\n"); // Test cd_to_repo with a repo name that exists multiple times - let repo_name = "repo1"; - let expected_path = format!("{}/dir1/repo1", tests_dir); - assert_eq!(cd_to_repo(repo_name, &tracking_file), Ok(expected_path)); + let expected_path = format!("{}/repo1", tests_dir); + assert_eq!(cd_to_repo("repo1", &tracking_file), Ok(expected_path)); + + common::cleanup(&tests_dir).unwrap(); +} + +#[test] +#[serial] +fn test_cd_to_fake_repo() { + let (_home_dir, mut tracking_file, tests_dir) = common::setup().unwrap(); + + // Add a real repository to ensure the tracking file is not empty + let real_repo = format!("{}/repo1", tests_dir); + assert!(add(vec![real_repo.clone()], &tracking_file).is_ok()); + + // Manually update tracking_file contents + tracking_file.contents = real_repo; + + // Try to cd to a fake repository + assert_eq!( + cd_to_repo("fake_repo1", &tracking_file), + Err(String::from("Repository 'fake_repo1' not found in tracking file")) + ); common::cleanup(&tests_dir).unwrap(); } \ No newline at end of file