Skip to content

Commit

Permalink
Stack: update / set git references on branch name change
Browse files Browse the repository at this point in the history
  • Loading branch information
krlvi committed Feb 19, 2025
1 parent 0a09c00 commit 25b6900
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 5 deletions.
2 changes: 1 addition & 1 deletion crates/gitbutler-stack/src/stack.rs
Original file line number Diff line number Diff line change
Expand Up @@ -480,7 +480,7 @@ impl Stack {
.iter_mut()
.find(|h: &&mut StackBranch| *h.name() == branch_name);
if let Some(head) = head {
head.set_name(name);
head.set_name(name, &ctx.gix_repository()?)?;
validate_name(head, &state)?;
head.pr_number = None; // reset pr_number
}
Expand Down
49 changes: 46 additions & 3 deletions crates/gitbutler-stack/src/stack_branch.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
use anyhow::Result;
use anyhow::{Ok, Result};
use bstr::BString;
use git2::{Commit, Oid};
use gitbutler_commit::commit_ext::CommitVecExt;
use gitbutler_repo::logging::{LogUntil, RepositoryExt as _};
use gix::refs::transaction::PreviousValue;
use gix::refs::{
transaction::{Change, LogChange, PreviousValue, RefEdit, RefLog},
Target,
};
use itertools::Itertools;
use serde::{Deserialize, Serialize};
use std::{fmt::Display, str::FromStr};
Expand Down Expand Up @@ -107,8 +110,48 @@ impl StackBranch {
&self.name
}

pub fn set_name(&mut self, name: String) {
pub fn set_name(&mut self, name: String, repo: &gix::Repository) -> Result<()> {
let current_name: BString = qualified_reference_name(self.name()).into();

let oid = match self.head.clone() {
CommitOrChangeId::CommitId(id) => gix::ObjectId::from_str(&id)?,
CommitOrChangeId::ChangeId(_) => return Ok(()), // noop
};

if let Some(reference) = repo.try_find_reference(&current_name)? {
let delete = RefEdit {
change: Change::Delete {
expected: PreviousValue::MustExistAndMatch(oid.into()),
log: RefLog::AndReference,
},
name: reference.name().into(),
deref: false,
};
let create = RefEdit {
change: Change::Update {
log: LogChange {
mode: RefLog::AndReference,
force_create_reflog: false,
message: "GitButler reference".into(),
},
expected: PreviousValue::ExistingMustMatch(oid.into()),
new: Target::Object(oid),
},
name: qualified_reference_name(&name).try_into()?,
deref: false,
};
repo.edit_references([delete, create])?;
} else {
repo.reference(
qualified_reference_name(&name),
oid,
PreviousValue::MustNotExist,
"GitButler reference",
)?;
};

self.name = name;
Ok(())
}

/// Creates or updates a real git reference using the head information (target commit, name)
Expand Down
5 changes: 4 additions & 1 deletion crates/gitbutler-stack/tests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -368,7 +368,10 @@ fn update_series_name_fails_validation() -> Result<()> {
let result = test_ctx
.stack
.update_series(&ctx, "a-branch-2".into(), &update);
assert_eq!(result.err().unwrap().to_string(), "Invalid branch name");
assert_eq!(
result.err().unwrap().to_string(),
"A reference must be a valid tag name as well"
);
Ok(())
}

Expand Down

0 comments on commit 25b6900

Please sign in to comment.