mirror of
https://github.com/gitbutlerapp/gitbutler.git
synced 2025-01-01 14:04:57 +03:00
Check we are on the right branch in verify_branch
Ensures we don't accidentally run commands while HEAD is pointing to something other than the gitbutler/integration branch.
This commit is contained in:
parent
2911155e33
commit
e7f25e29c5
@ -608,8 +608,8 @@ pub fn update_base_branch(
|
||||
..target
|
||||
})?;
|
||||
|
||||
// Rewriting the integration commit is necessary after changing target sha.
|
||||
super::integration::update_gitbutler_integration(&vb_state, project_repository)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -65,9 +65,13 @@ pub enum VerifyError {
|
||||
DetachedHead,
|
||||
#[error("head is {0}")]
|
||||
InvalidHead(String),
|
||||
#[error("head not found")]
|
||||
HeadNotFound,
|
||||
#[error("integration commit not found")]
|
||||
NoIntegrationCommit,
|
||||
#[error(transparent)]
|
||||
GitError(#[from] git::Error),
|
||||
#[error(transparent)]
|
||||
Other(#[from] anyhow::Error),
|
||||
}
|
||||
|
||||
@ -93,6 +97,12 @@ impl ErrorWithContext for VerifyError {
|
||||
Code::ProjectHead,
|
||||
"GibButler's integration commit not found on head.",
|
||||
),
|
||||
VerifyError::HeadNotFound => {
|
||||
error::Context::new_static(Code::Validation, "Repo HEAD is unavailable")
|
||||
}
|
||||
VerifyError::GitError(error) => {
|
||||
error::Context::new(Code::Validation, error.to_string())
|
||||
}
|
||||
VerifyError::Other(error) => return error.custom_context_or_root_cause().into(),
|
||||
})
|
||||
}
|
||||
|
@ -4,7 +4,7 @@ use anyhow::{anyhow, Context, Result};
|
||||
use bstr::ByteSlice;
|
||||
use lazy_static::lazy_static;
|
||||
|
||||
use super::{errors, VirtualBranchesHandle};
|
||||
use super::{errors::VerifyError, VirtualBranchesHandle};
|
||||
use crate::{
|
||||
git::{self},
|
||||
project_repository::{self, LogUntil},
|
||||
@ -274,7 +274,8 @@ pub fn update_gitbutler_integration(
|
||||
|
||||
pub fn verify_branch(
|
||||
project_repository: &project_repository::Repository,
|
||||
) -> Result<(), errors::VerifyError> {
|
||||
) -> Result<(), VerifyError> {
|
||||
verify_current_branch_name(project_repository)?;
|
||||
verify_head_is_set(project_repository)?;
|
||||
verify_head_is_clean(project_repository)?;
|
||||
Ok(())
|
||||
@ -282,7 +283,7 @@ pub fn verify_branch(
|
||||
|
||||
fn verify_head_is_clean(
|
||||
project_repository: &project_repository::Repository,
|
||||
) -> Result<(), errors::VerifyError> {
|
||||
) -> Result<(), VerifyError> {
|
||||
let head_commit = project_repository
|
||||
.git_repository
|
||||
.head()
|
||||
@ -303,7 +304,7 @@ fn verify_head_is_clean(
|
||||
|
||||
if integration_commit.is_none() {
|
||||
// no integration commit found
|
||||
return Err(errors::VerifyError::NoIntegrationCommit);
|
||||
return Err(VerifyError::NoIntegrationCommit);
|
||||
}
|
||||
|
||||
if extra_commits.is_empty() {
|
||||
@ -377,17 +378,32 @@ fn verify_head_is_clean(
|
||||
|
||||
fn verify_head_is_set(
|
||||
project_repository: &project_repository::Repository,
|
||||
) -> Result<(), errors::VerifyError> {
|
||||
) -> Result<(), VerifyError> {
|
||||
match project_repository
|
||||
.get_head()
|
||||
.context("failed to get head")
|
||||
.map_err(errors::VerifyError::Other)?
|
||||
.map_err(VerifyError::Other)?
|
||||
.name()
|
||||
{
|
||||
Some(refname) if refname.to_string() == GITBUTLER_INTEGRATION_REFERENCE.to_string() => {
|
||||
Ok(())
|
||||
}
|
||||
None => Err(errors::VerifyError::DetachedHead),
|
||||
Some(head_name) => Err(errors::VerifyError::InvalidHead(head_name.to_string())),
|
||||
None => Err(VerifyError::DetachedHead),
|
||||
Some(head_name) => Err(VerifyError::InvalidHead(head_name.to_string())),
|
||||
}
|
||||
}
|
||||
|
||||
// Returns an error if repo head is not pointing to the integration branch.
|
||||
pub fn verify_current_branch_name(
|
||||
project_repository: &project_repository::Repository,
|
||||
) -> Result<bool, VerifyError> {
|
||||
match project_repository.get_head()?.name() {
|
||||
Some(head) => {
|
||||
if head.to_string() != GITBUTLER_INTEGRATION_REFERENCE.to_string() {
|
||||
return Err(VerifyError::InvalidHead(head.to_string()));
|
||||
}
|
||||
Ok(true)
|
||||
}
|
||||
None => Err(VerifyError::HeadNotFound),
|
||||
}
|
||||
}
|
||||
|
@ -72,6 +72,7 @@ mod undo_commit;
|
||||
mod update_base_branch;
|
||||
mod update_commit_message;
|
||||
mod upstream;
|
||||
mod verify_branch;
|
||||
|
||||
#[tokio::test]
|
||||
async fn resolve_conflict_flow() {
|
||||
|
@ -0,0 +1,25 @@
|
||||
use gitbutler_core::virtual_branches::errors::VerifyError;
|
||||
|
||||
use super::*;
|
||||
|
||||
// Ensures that `verify_branch` returns an error when not on the integration branch.
|
||||
#[tokio::test]
|
||||
async fn should_fail_on_incorrect_branch() {
|
||||
let Test {
|
||||
repository,
|
||||
project_id,
|
||||
controller,
|
||||
..
|
||||
} = &Test::default();
|
||||
|
||||
let branch_name: git::LocalRefname = "refs/heads/somebranch".parse().unwrap();
|
||||
repository.checkout(&branch_name);
|
||||
let result = controller.list_virtual_branches(project_id).await;
|
||||
|
||||
let error = result.err();
|
||||
assert!(&error.is_some());
|
||||
|
||||
let error = error.unwrap();
|
||||
let error = error.downcast_ref::<VerifyError>();
|
||||
assert!(matches!(error, Some(VerifyError::InvalidHead(_))));
|
||||
}
|
Loading…
Reference in New Issue
Block a user