mirror of
https://github.com/gitbutlerapp/gitbutler.git
synced 2025-01-04 07:25:44 +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
|
..target
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
|
// Rewriting the integration commit is necessary after changing target sha.
|
||||||
super::integration::update_gitbutler_integration(&vb_state, project_repository)?;
|
super::integration::update_gitbutler_integration(&vb_state, project_repository)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,9 +65,13 @@ pub enum VerifyError {
|
|||||||
DetachedHead,
|
DetachedHead,
|
||||||
#[error("head is {0}")]
|
#[error("head is {0}")]
|
||||||
InvalidHead(String),
|
InvalidHead(String),
|
||||||
|
#[error("head not found")]
|
||||||
|
HeadNotFound,
|
||||||
#[error("integration commit not found")]
|
#[error("integration commit not found")]
|
||||||
NoIntegrationCommit,
|
NoIntegrationCommit,
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
|
GitError(#[from] git::Error),
|
||||||
|
#[error(transparent)]
|
||||||
Other(#[from] anyhow::Error),
|
Other(#[from] anyhow::Error),
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -93,6 +97,12 @@ impl ErrorWithContext for VerifyError {
|
|||||||
Code::ProjectHead,
|
Code::ProjectHead,
|
||||||
"GibButler's integration commit not found on head.",
|
"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(),
|
VerifyError::Other(error) => return error.custom_context_or_root_cause().into(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@ use anyhow::{anyhow, Context, Result};
|
|||||||
use bstr::ByteSlice;
|
use bstr::ByteSlice;
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
|
|
||||||
use super::{errors, VirtualBranchesHandle};
|
use super::{errors::VerifyError, VirtualBranchesHandle};
|
||||||
use crate::{
|
use crate::{
|
||||||
git::{self},
|
git::{self},
|
||||||
project_repository::{self, LogUntil},
|
project_repository::{self, LogUntil},
|
||||||
@ -274,7 +274,8 @@ pub fn update_gitbutler_integration(
|
|||||||
|
|
||||||
pub fn verify_branch(
|
pub fn verify_branch(
|
||||||
project_repository: &project_repository::Repository,
|
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_set(project_repository)?;
|
||||||
verify_head_is_clean(project_repository)?;
|
verify_head_is_clean(project_repository)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -282,7 +283,7 @@ pub fn verify_branch(
|
|||||||
|
|
||||||
fn verify_head_is_clean(
|
fn verify_head_is_clean(
|
||||||
project_repository: &project_repository::Repository,
|
project_repository: &project_repository::Repository,
|
||||||
) -> Result<(), errors::VerifyError> {
|
) -> Result<(), VerifyError> {
|
||||||
let head_commit = project_repository
|
let head_commit = project_repository
|
||||||
.git_repository
|
.git_repository
|
||||||
.head()
|
.head()
|
||||||
@ -303,7 +304,7 @@ fn verify_head_is_clean(
|
|||||||
|
|
||||||
if integration_commit.is_none() {
|
if integration_commit.is_none() {
|
||||||
// no integration commit found
|
// no integration commit found
|
||||||
return Err(errors::VerifyError::NoIntegrationCommit);
|
return Err(VerifyError::NoIntegrationCommit);
|
||||||
}
|
}
|
||||||
|
|
||||||
if extra_commits.is_empty() {
|
if extra_commits.is_empty() {
|
||||||
@ -377,17 +378,32 @@ fn verify_head_is_clean(
|
|||||||
|
|
||||||
fn verify_head_is_set(
|
fn verify_head_is_set(
|
||||||
project_repository: &project_repository::Repository,
|
project_repository: &project_repository::Repository,
|
||||||
) -> Result<(), errors::VerifyError> {
|
) -> Result<(), VerifyError> {
|
||||||
match project_repository
|
match project_repository
|
||||||
.get_head()
|
.get_head()
|
||||||
.context("failed to get head")
|
.context("failed to get head")
|
||||||
.map_err(errors::VerifyError::Other)?
|
.map_err(VerifyError::Other)?
|
||||||
.name()
|
.name()
|
||||||
{
|
{
|
||||||
Some(refname) if refname.to_string() == GITBUTLER_INTEGRATION_REFERENCE.to_string() => {
|
Some(refname) if refname.to_string() == GITBUTLER_INTEGRATION_REFERENCE.to_string() => {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
None => Err(errors::VerifyError::DetachedHead),
|
None => Err(VerifyError::DetachedHead),
|
||||||
Some(head_name) => Err(errors::VerifyError::InvalidHead(head_name.to_string())),
|
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_base_branch;
|
||||||
mod update_commit_message;
|
mod update_commit_message;
|
||||||
mod upstream;
|
mod upstream;
|
||||||
|
mod verify_branch;
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn resolve_conflict_flow() {
|
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