refactor - move given_name_for_branch from the context to an extension on git2::Reference

This commit is contained in:
Kiril Videlov 2024-07-25 19:29:13 +02:00
parent 3afabc2a30
commit 69b7aa3d8a
No known key found for this signature in database
GPG Key ID: A4C733025427C471
4 changed files with 53 additions and 50 deletions

View File

@ -2,7 +2,7 @@ use std::path::Path;
use anyhow::{Context, Result};
use bstr::BString;
use gitbutler_branch::{Target, VirtualBranchesHandle};
use gitbutler_branch::{ReferenceExt, Target, VirtualBranchesHandle};
use gitbutler_command_context::ProjectRepository;
use gitbutler_commit::commit_ext::CommitExt;
use gitbutler_reference::{Refname, RemoteRefname};
@ -122,7 +122,7 @@ pub(crate) fn branch_to_remote_branch(
.context("could not get branch name")
.ok()?;
let given_name = ctx.given_name_for_branch(branch).ok()?;
let given_name = branch.get().given_name(ctx.repo().remotes().ok()?).ok()?;
branch.get().target().map(|sha| RemoteBranch {
sha,

View File

@ -2,6 +2,8 @@ mod branch;
pub use branch::{Branch, BranchCreateRequest, BranchId, BranchUpdateRequest};
mod branch_ext;
pub use branch_ext::BranchExt;
mod reference_ext;
pub use reference_ext::ReferenceExt;
mod dedup;
pub use dedup::{dedup, dedup_fmt};
mod file_ownership;

View File

@ -0,0 +1,48 @@
use anyhow::Result;
use itertools::Itertools;
pub trait ReferenceExt {
/// Fetches a branches name without the remote name attached
///
/// refs/heads/my-branch -> my-branch
/// refs/remotes/origin/my-branch -> my-branch
/// refs/remotes/Byron/gitbutler/my-branch -> my-branch (where the remote is Byron/gitbutler)
///
/// An ideal implementation wouldn't require us to list all the references,
/// but there doesn't seem to be a libgit2 solution to this.
fn given_name(&self, remotes: git2::string_array::StringArray) -> Result<String>;
}
impl<'repo> ReferenceExt for git2::Reference<'repo> {
fn given_name(&self, remotes: git2::string_array::StringArray) -> Result<String> {
if self.is_remote() {
let shorthand_name = self
.shorthand()
.ok_or(anyhow::anyhow!("Branch name was not utf-8"))?;
let longest_remote = remotes
.iter()
.flatten()
.sorted_by_key(|remote_name| -(remote_name.len() as i32))
.find(|reference_name| shorthand_name.starts_with(reference_name))
.ok_or(anyhow::anyhow!(
"Failed to find remote branch's corresponding remote"
))?;
let shorthand_name = shorthand_name
.strip_prefix(longest_remote)
.and_then(|str| str.strip_prefix("/"))
.ok_or(anyhow::anyhow!(
"Failed to cut remote name {} off of shorthand name {}",
longest_remote,
shorthand_name
))?;
Ok(shorthand_name.to_string())
} else {
self.shorthand()
.ok_or(anyhow::anyhow!("Branch name was not utf-8"))
.map(String::from)
}
}
}

View File

@ -1,6 +1,5 @@
use anyhow::{Context, Result};
use anyhow::Result;
use gitbutler_project::Project;
use itertools::Itertools;
pub struct ProjectRepository {
git_repository: git2::Repository,
@ -71,50 +70,4 @@ impl ProjectRepository {
pub fn repo(&self) -> &git2::Repository {
&self.git_repository
}
/// Fetches a branches name without the remote name attached
///
/// refs/heads/my-branch -> my-branch
/// refs/remotes/origin/my-branch -> my-branch
/// refs/remotes/Byron/gitbutler/my-branch -> my-branch (where the remote is Byron/gitbutler)
///
/// An ideal implementation wouldn't require us to list all the references,
/// but there doesn't seem to be a libgit2 solution to this.
pub fn given_name_for_branch(&self, branch: &git2::Branch) -> Result<String> {
let reference = branch.get();
let repo = self.repo();
if reference.is_remote() {
let shorthand_name = reference
.shorthand()
.ok_or(anyhow::anyhow!("Branch name was not utf-8"))?;
let remotes = repo.remotes().context("Failed to get remotes")?;
let longest_remote = remotes
.iter()
.flatten()
.sorted_by_key(|remote_name| -(remote_name.len() as i32))
.find(|reference_name| shorthand_name.starts_with(reference_name))
.ok_or(anyhow::anyhow!(
"Failed to find remote branch's corresponding remote"
))?;
let shorthand_name = shorthand_name
.strip_prefix(longest_remote)
.and_then(|str| str.strip_prefix("/"))
.ok_or(anyhow::anyhow!(
"Failed to cut remote name {} off of shorthand name {}",
longest_remote,
shorthand_name
))?;
Ok(shorthand_name.to_string())
} else {
reference
.shorthand()
.ok_or(anyhow::anyhow!("Branch name was not utf-8"))
.map(String::from)
}
}
}