feat: Open default remote branch if no upstream exists

pull/1/head
sgoudham 2 years ago
parent ba0eb0f315
commit 80465ec514
Signed by: hammy
GPG Key ID: 44E818FD5457EEA4

@ -48,7 +48,7 @@ impl<'a> GitView<'a> {
// Retrieve the remote // Retrieve the remote
let remote = self.populate_remote(&local_ref, &git)?; let remote = self.populate_remote(&local_ref, &git)?;
// Retrieve the remote reference // Retrieve the remote reference
let remote_ref = self.get_remote_reference(&local_ref, &git)?; let remote_ref = self.get_remote_reference(&local_ref, &remote, &git)?;
// Retrieve the full git_url // Retrieve the full git_url
// e.g https://github.com/sgoudham/git-view.git // e.g https://github.com/sgoudham/git-view.git
@ -121,6 +121,7 @@ impl<'a> GitView<'a> {
fn get_remote_reference( fn get_remote_reference(
&self, &self,
local: &'a Local, local: &'a Local,
remote: &'a str,
git: &impl GitTrait, git: &impl GitTrait,
) -> Result<Cow<'a, str>, AppError> { ) -> Result<Cow<'a, str>, AppError> {
match local { match local {
@ -129,23 +130,16 @@ impl<'a> GitView<'a> {
GitOutput::Ok(output) => Ok(Cow::Owned( GitOutput::Ok(output) => Ok(Cow::Owned(
output.trim_start_matches("refs/heads/").to_string(), output.trim_start_matches("refs/heads/").to_string(),
)), )),
// If retrieving the upstream_branch fails, that means that there is no valid // Upstream branch doesn't exist, try to retrieve default remote branch
// upstream branch (surprise surprise) GitOutput::Err(_) => match git.get_default_branch(remote)? {
// GitOutput::Ok(default_branch) => match default_branch.split_once('/') {
// When there's no valid remote branch, we should default to the repository's Some((_, split_branch)) => Ok(Cow::Owned(split_branch.into())),
// default branch, for the vast majority of cases, this will be either "main" None => Ok(Cow::Borrowed(branch)),
// or "master" but it could be different for whatever INSANE person has changed },
// their default to differ from those two terms. // Default branch couldn't be retrieved, just use the local branch
// // (this WILL result in a 404 error on the user but better than failing?)
// Thankfully, we have a command 'git rev-parse --abbrev-ref <remote>/HEAD' GitOutput::Err(_) => Ok(Cow::Borrowed(branch)),
// to let us retrieve the default branch (we also need to split on the first / },
// encountered and take the second split part)
//
// However, it's a bit dodgy so we can't guarantee it will work everytime. If
// the command 'git rev-parse --abbrev-ref <remote>/HEAD' fails, we should just
// default to the local branch and the user will just have to suck it up and
// deal with the 404 error that they will probably get.
GitOutput::Err(_) => Ok(Cow::Borrowed(branch)),
} }
} }
// Priority is given to the current tag // Priority is given to the current tag
@ -509,6 +503,121 @@ mod lib_tests {
} }
} }
mod get_remote_reference {
use std::borrow::Cow;
use crate::{
error::ErrorType,
git::{GitOutput, MockGitTrait},
GitView, Local,
};
fn handler<'a>() -> GitView<'a> {
GitView::new(None, None, None, false, false)
}
#[test]
fn is_branch_and_exists_on_remote() {
let handler = handler();
let local = Local::Branch(Cow::Borrowed("main"));
let mut mock = MockGitTrait::default();
mock.expect_get_upstream_branch()
.returning(|_| Ok(GitOutput::Ok("refs/heads/main".into())));
let actual_upstream_branch = handler.get_remote_reference(&local, "origin", &mock);
assert!(actual_upstream_branch.is_ok());
assert_eq!(actual_upstream_branch.unwrap(), "main");
}
#[test]
fn is_branch_and_successfully_get_default() {
let handler = handler();
let local = Local::Branch(Cow::Borrowed("main"));
let mut mock = MockGitTrait::default();
mock.expect_get_upstream_branch()
.returning(|_| Ok(GitOutput::Err("error".into())));
mock.expect_get_default_branch()
.returning(|_| Ok(GitOutput::Ok("origin/main".into())));
let actual_upstream_branch = handler.get_remote_reference(&local, "origin", &mock);
assert!(actual_upstream_branch.is_ok());
assert_eq!(actual_upstream_branch.unwrap(), "main")
}
#[test]
fn is_branch_and_fail_to_get_default() {
let handler = handler();
let local = Local::Branch(Cow::Borrowed("main"));
let mut mock = MockGitTrait::default();
mock.expect_get_upstream_branch()
.returning(|_| Ok(GitOutput::Err("error".into())));
mock.expect_get_default_branch()
.returning(|_| Ok(GitOutput::Err("error".into())));
let actual_upstream_branch = handler.get_remote_reference(&local, "origin", &mock);
assert!(actual_upstream_branch.is_ok());
assert_eq!(actual_upstream_branch.unwrap(), "main")
}
#[test]
fn not_branch_and_get_current_tag() {
let handler = handler();
let local = Local::NotBranch;
let mut mock = MockGitTrait::default();
mock.expect_get_current_tag()
.returning(|| Ok(GitOutput::Ok("v1.0.0".into())));
let actual_upstream_branch = handler.get_remote_reference(&local, "origin", &mock);
assert!(actual_upstream_branch.is_ok());
assert_eq!(actual_upstream_branch.unwrap(), "v1.0.0")
}
#[test]
fn not_branch_and_get_current_commit() {
let handler = handler();
let local = Local::NotBranch;
let mut mock = MockGitTrait::default();
mock.expect_get_current_tag()
.returning(|| Ok(GitOutput::Err("error".into())));
mock.expect_get_current_commit()
.returning(|| Ok(GitOutput::Ok("hash".into())));
let actual_upstream_branch = handler.get_remote_reference(&local, "origin", &mock);
assert!(actual_upstream_branch.is_ok());
assert_eq!(actual_upstream_branch.unwrap(), "hash")
}
#[test]
fn not_branch_and_no_tag_or_commit() {
let handler = handler();
let local = Local::NotBranch;
let mut mock = MockGitTrait::default();
mock.expect_get_current_tag()
.returning(|| Ok(GitOutput::Err("error".into())));
mock.expect_get_current_commit()
.returning(|| Ok(GitOutput::Err("error".into())));
let actual_upstream_branch = handler.get_remote_reference(&local, "origin", &mock);
assert!(actual_upstream_branch.is_err());
let error = actual_upstream_branch.as_ref().unwrap_err();
assert_eq!(error.error_type, ErrorType::CommandFailed);
assert_eq!(error.error_str, "error");
}
}
mod parse_git_url { mod parse_git_url {
use crate::{error::AppError, lib_tests::instantiate_handler}; use crate::{error::AppError, lib_tests::instantiate_handler};
use test_case::test_case; use test_case::test_case;

Loading…
Cancel
Save