diff --git a/src/commands/switch.rs b/src/commands/switch.rs index 59b85399..e376775a 100644 --- a/src/commands/switch.rs +++ b/src/commands/switch.rs @@ -135,6 +135,123 @@ mod tests { ); } + #[tokio::test] + async fn switch_branch_exists_remote_only() { + let cmd: SwitchCommand = SwitchCommand {}; + + let temp = tempdir().unwrap(); + let repo: Repo = core::Repo::new( + "github.com/sierrasoftworks/test-git-switch-command", + temp.path().join("repo").into(), + ); + + let origin_repo = core::Repo::new( + "github.com/sierrasoftworks/test-git-switch-command2", + temp.path().join("repo2").into(), + ); + + let core = core::Core::builder() + .with_config(&core::Config::for_dev_directory(temp.path())) + .build(); + + Resolver::get_current_repo.mock_safe(move |_| { + MockResult::Return(Ok(core::Repo::new( + "github.com/sierrasoftworks/test-git-switch-command", + temp.path().join("repo").into(), + ))) + }); + + sequence!( + // Run a `git init` to setup the repo + tasks::GitInit {}, + tasks::GitRemote { name: "origin" }, + // Create the branch we want to switch to + tasks::GitCheckout { + branch: "feature/test".into(), + }, + tasks::WriteFile { + path: "README.md".into(), + content: "This is an example README file.", + }, + tasks::GitAdd { + paths: vec!["README.md"], + }, + tasks::GitCommit { + message: "Add README.md", + paths: vec!["README.md"], + }, + tasks::GitCheckout { + branch: "main".into(), + } + ) + .apply_repo(&core, &origin_repo) + .await + .unwrap(); + + sequence!(tasks::GitInit {}, tasks::GitRemote { name: "origin" }) + .apply_repo(&core, &repo) + .await + .unwrap(); + + git::git_remote_set_url( + &repo.get_path(), + "origin", + origin_repo.get_path().to_str().unwrap(), + ) + .await + .unwrap(); + + git::git_fetch(&repo.get_path(), "origin").await.unwrap(); + + sequence!( + tasks::GitCheckout { + branch: "main".into(), + }, + tasks::WriteFile { + path: "README.md".into(), + content: "This is an example README file with some changes.", + }, + tasks::GitAdd { + paths: vec!["README.md"], + }, + tasks::GitCommit { + message: "Update README.md", + paths: vec!["README.md"], + } + ) + .apply_repo(&core, &repo) + .await + .unwrap(); + + eprintln!( + "branches: {:?}", + git::git_branches(&repo.get_path()).await.unwrap() + ); + + assert!(repo.valid(), "the repository should exist and be valid"); + + let args: ArgMatches = cmd.app().get_matches_from(vec!["switch", "feature/test"]); + cmd.run(&core, &args).await.unwrap(); + + assert!(repo.valid(), "the repository should still be valid"); + assert_eq!( + git::git_current_branch(&repo.get_path()).await.unwrap(), + "feature/test" + ); + + let target_ref = git::git_rev_parse(&repo.get_path(), "origin/feature/test") + .await + .unwrap(); + let true_ref = git::git_rev_parse(&repo.get_path(), "feature/test") + .await + .unwrap(); + + assert_eq!( + true_ref, target_ref, + "the current branch should be pointing at the original origin ref" + ); + } + #[tokio::test] async fn switch_no_create_branch_exists() { let cmd: SwitchCommand = SwitchCommand {}; diff --git a/src/git/branch.rs b/src/git/branch.rs index 5f511538..c659e713 100644 --- a/src/git/branch.rs +++ b/src/git/branch.rs @@ -23,9 +23,9 @@ pub async fn git_branches(repo: &path::Path) -> Result, errors::Erro let output = git_cmd( Command::new("git") .current_dir(repo) - .arg("for-each-ref") - .arg("--format=%(refname:lstrip=2)") - .arg("refs/heads/"), + .arg("branch") + .arg("-a") + .arg("--format=%(refname:lstrip=2)"), ) .await?; diff --git a/src/git/fetch.rs b/src/git/fetch.rs new file mode 100644 index 00000000..ad352595 --- /dev/null +++ b/src/git/fetch.rs @@ -0,0 +1,18 @@ +use super::git_cmd; +use crate::errors; +use std::path; +use tokio::process::Command; + +#[allow(dead_code)] +pub async fn git_fetch(repo: &path::Path, origin: &str) -> Result<(), errors::Error> { + info!("Running `git fetch $ORIGIN`"); + git_cmd( + Command::new("git") + .current_dir(repo) + .arg("fetch") + .arg(origin), + ) + .await?; + + Ok(()) +} diff --git a/src/git/mod.rs b/src/git/mod.rs index 25349b92..1e9e365f 100644 --- a/src/git/mod.rs +++ b/src/git/mod.rs @@ -4,6 +4,7 @@ mod checkout; mod clone; mod cmd; mod commit; +mod fetch; mod init; mod remote; mod switch; @@ -17,6 +18,7 @@ pub use checkout::git_checkout; pub use clone::git_clone; pub use cmd::git_cmd; pub use commit::git_commit; +pub use fetch::git_fetch; pub use init::git_init; pub use remote::{git_remote_add, git_remote_list, git_remote_set_url}; pub use switch::git_switch; diff --git a/src/tasks/git_switch.rs b/src/tasks/git_switch.rs index 3befccd0..b5db55b4 100644 --- a/src/tasks/git_switch.rs +++ b/src/tasks/git_switch.rs @@ -14,7 +14,8 @@ impl Task for GitSwitch { if create && git::git_branches(&repo.get_path()) .await? - .contains(&self.branch) + .iter() + .any(|v| v == &self.branch || v == &format!("origin/{}", &self.branch)) { create = false; }