use branch name to lookup branch

This commit is contained in:
Nikita Galaiko 2023-08-31 15:20:25 +02:00 committed by GitButler
parent 60b65685be
commit b06cce901d
17 changed files with 117 additions and 111 deletions

View File

@ -272,7 +272,7 @@ impl App {
.map_err(|e| Error::Other(e.into()))?;
project_repository
.fetch(&default_target.remote_name, &key)
.fetch(&default_target.branch.remote(), &key)
.map_err(Error::FetchError)
}
@ -484,7 +484,7 @@ impl App {
}
}
pub fn git_switch_branch(&self, project_id: &str, branch: &str) -> Result<()> {
pub fn git_switch_branch(&self, project_id: &str, branch: &git::LocalBranchName) -> Result<()> {
let project = self.gb_project(project_id)?;
let project_repository = project_repository::Repository::open(&project)
.context("failed to open project repository")?;

View File

@ -18,6 +18,18 @@ pub enum Name {
Local(LocalName),
}
impl From<RemoteName> for Name {
fn from(value: RemoteName) -> Self {
Self::Remote(value)
}
}
impl From<LocalName> for Name {
fn from(value: LocalName) -> Self {
Self::Local(value)
}
}
impl Name {
pub fn branch(&self) -> &str {
match self {

View File

@ -15,6 +15,13 @@ pub struct Name {
}
impl Name {
pub fn new(remote: &str, branch: &str) -> Self {
Self {
remote: remote.to_string(),
branch: branch.to_string(),
}
}
pub fn with_branch(&self, branch: &str) -> Self {
Self {
branch: branch.to_string(),

View File

@ -1,7 +1,8 @@
use std::path;
use super::{
AnnotatedCommit, Branch, Commit, Index, Oid, Reference, Remote, Result, Tree, TreeBuilder,
AnnotatedCommit, Branch, BranchName, Commit, Index, Oid, Reference, Remote, Result, Tree,
TreeBuilder,
};
// wrapper around git2::Repository to get control over how it's used.
@ -269,9 +270,20 @@ impl Repository {
self.0.find_remote(name).map(Into::into).map_err(Into::into)
}
pub fn find_branch(&self, name: &str, branch_type: git2::BranchType) -> Result<Branch> {
pub fn find_branch(&self, name: &BranchName) -> Result<Branch> {
self.0
.find_branch(name, branch_type)
.find_branch(
&match name {
BranchName::Local(local) => local.branch().to_string(),
BranchName::Remote(remote) => {
format!("{}/{}", remote.remote(), remote.branch())
}
},
match name {
BranchName::Local(_) => git2::BranchType::Local,
BranchName::Remote(_) => git2::BranchType::Remote,
},
)
.map(Into::into)
.map_err(Into::into)
}

View File

@ -423,10 +423,10 @@ async fn git_head(handle: tauri::AppHandle, project_id: &str) -> Result<String,
async fn git_switch_branch(
handle: tauri::AppHandle,
project_id: &str,
branch: &str,
branch: git::LocalBranchName,
) -> Result<(), Error> {
let app = handle.state::<app::App>();
app.git_switch_branch(project_id, branch)
app.git_switch_branch(project_id, &branch)
.with_context(|| format!("failed to switch git branch for project {}", project_id))?;
Ok(())
}

View File

@ -320,10 +320,8 @@ impl<'repository> Repository<'repository> {
Ok(oids.len().try_into()?)
}
pub fn git_switch_branch(&self, branch: &str) -> Result<()> {
let branch = self
.git_repository
.find_branch(branch, git2::BranchType::Local)?;
pub fn git_switch_branch(&self, branch: &git::LocalBranchName) -> Result<()> {
let branch = self.git_repository.find_branch(&branch.clone().into())?;
self.git_repository
.set_head(branch.name().unwrap())
.context("failed to set head")?;

View File

@ -27,12 +27,12 @@ pub fn get_base_branch_data(
pub fn set_base_branch(
gb_repository: &gb_repository::Repository,
project_repository: &project_repository::Repository,
target_branch: &str,
target_branch: &git::RemoteBranchName,
) -> Result<super::BaseBranch> {
let repo = &project_repository.git_repository;
// lookup a branch by name
let branch = repo.find_branch(target_branch, git2::BranchType::Remote)?;
let branch = repo.find_branch(&target_branch.clone().into())?;
let remote_name = repo.branch_remote_name(branch.refname().unwrap())?;
let remote = repo.find_remote(&remote_name)?;
@ -64,8 +64,7 @@ pub fn set_base_branch(
}
let target = target::Target {
branch_name: branch.name().unwrap().to_string(),
remote_name: remote.name().unwrap().to_string(),
branch: target_branch.clone(),
remote_url: remote_url.to_string(),
sha: commit_oid,
};
@ -144,13 +143,12 @@ pub fn update_base_branch(
let repo = &project_repository.git_repository;
let target_branch = repo
.find_branch(&target.branch_name, git2::BranchType::Remote)
.context(format!("failed to find branch {}", target.branch_name))?;
.find_branch(&target.branch.clone().into())
.context(format!("failed to find branch {}", target.branch))?;
let new_target_commit = target_branch.peel_to_commit().context(format!(
"failed to peel branch {} to commit",
target.branch_name
))?;
let new_target_commit = target_branch
.peel_to_commit()
.context(format!("failed to peel branch {} to commit", target.branch))?;
let new_target_commit_oid = new_target_commit.id();
// if the target has not changed, do nothing
@ -443,7 +441,7 @@ pub fn target_to_base_branch(
target: &target::Target,
) -> Result<super::BaseBranch> {
let repo = &project_repository.git_repository;
let branch = repo.find_branch(&target.branch_name, git2::BranchType::Remote)?;
let branch = repo.find_branch(&target.branch.clone().into())?;
let commit = branch.peel_to_commit()?;
let oid = commit.id();
@ -464,8 +462,8 @@ pub fn target_to_base_branch(
.collect::<Result<Vec<_>>>()?;
let base = super::BaseBranch {
branch_name: target.branch_name.clone(),
remote_name: target.remote_name.clone(),
branch_name: target.branch.branch().to_string(),
remote_name: target.branch.remote().to_string(),
remote_url: target.remote_url.clone(),
base_sha: target.sha.to_string(),
current_sha: oid.to_string(),
@ -513,8 +511,8 @@ pub fn create_virtual_branch_from_branch(
let upstream_branch = match upstream {
git::BranchName::Remote(remote) => Some(remote.clone()),
git::BranchName::Local(local) => {
let remote_name = format!("{}/{}", default_target.remote_name, local.branch());
if remote_name != default_target.branch_name {
let remote_name = format!("{}/{}", default_target.branch.remote(), local.branch());
if remote_name != default_target.branch.branch() {
Some(format!("refs/remotes/{}", remote_name).parse().unwrap())
} else {
None

View File

@ -79,11 +79,11 @@ pub async fn get_base_branch_data(
pub async fn set_base_branch(
handle: AppHandle,
project_id: &str,
branch: &str,
branch: git::RemoteBranchName,
) -> Result<super::BaseBranch, Error> {
handle
.state::<Controller>()
.set_base_branch(project_id, branch)
.set_base_branch(project_id, &branch)
.await
.map_err(Into::into)
}

View File

@ -155,7 +155,7 @@ impl Controller {
pub async fn set_base_branch(
&self,
project_id: &str,
target_branch: &str,
target_branch: &git::RemoteBranchName,
) -> Result<super::BaseBranch, Error> {
let project = self
.projects_storage

View File

@ -88,8 +88,11 @@ mod tests {
fn test_target() -> target::Target {
target::Target {
branch_name: format!("branch name{}", unsafe { TEST_TARGET_INDEX }),
remote_name: format!("remote name {}", unsafe { TEST_TARGET_INDEX }),
branch: format!(
"refs/remotes/branch name{}/remote name {}",
unsafe { TEST_TARGET_INDEX },
unsafe { TEST_TARGET_INDEX }
).parse().unwrap(),
remote_url: format!("remote url {}", unsafe { TEST_TARGET_INDEX }),
sha: format!("0123456789abcdef0123456789abcdef0123456{}", unsafe {
TEST_TARGET_INDEX

View File

@ -10,9 +10,7 @@ use crate::git;
#[derive(Debug, PartialEq, Clone)]
pub struct Target {
// TODO: use project_repository::branch::RemoteName here.
pub branch_name: String,
pub remote_name: String,
pub branch: git::RemoteBranchName,
pub remote_url: String,
pub sha: git::Oid,
}
@ -23,8 +21,8 @@ impl Serialize for Target {
S: Serializer,
{
let mut state = serializer.serialize_struct("Target", 5)?;
state.serialize_field("branchName", &self.branch_name)?;
state.serialize_field("remoteName", &self.remote_name)?;
state.serialize_field("branchName", &self.branch.branch())?;
state.serialize_field("remoteName", &self.branch.remote())?;
state.serialize_field("remoteUrl", &self.remote_url)?;
state.serialize_field("sha", &self.sha.to_string())?;
state.end()
@ -93,8 +91,7 @@ impl TryFrom<&dyn crate::reader::Reader> for Target {
})?;
Ok(Self {
branch_name,
remote_name,
branch: git::RemoteBranchName::new(&remote_name, &branch_name),
remote_url,
sha,
})

View File

@ -138,8 +138,8 @@ mod tests {
let reader = TargetReader::new(&session_reader);
let read = reader.read_default().unwrap();
assert_eq!(read.branch_name, "origin/master");
assert_eq!(read.remote_name, "origin");
assert_eq!(read.branch.branch(), "origin/master");
assert_eq!(read.branch.remote(), "origin");
assert_eq!(
read.remote_url,
"git@github.com:gitbutlerapp/gitbutler-client.git"
@ -167,15 +167,15 @@ mod tests {
let branch = test_branch();
let target = Target {
remote_name: "remote".to_string(),
branch_name: "branch".to_string(),
branch: "refs/remotes/remote/branch".parse().unwrap(),
remote_url: "remote url".to_string(),
sha: "fedcba9876543210fedcba9876543210fedcba98".parse().unwrap(),
};
let default_target = Target {
remote_name: "default remote".to_string(),
branch_name: "default branch".to_string(),
branch: "refs/remotes/default remote/default branch"
.parse()
.unwrap(),
remote_url: "default remote url".to_string(),
sha: "0123456789abcdef0123456789abcdef01234567".parse().unwrap(),
};

View File

@ -28,10 +28,10 @@ impl<'writer> TargetWriter<'writer> {
let _lock = self.repository.lock();
self.writer
.write_string("branches/target/branch_name", &target.branch_name)
.write_string("branches/target/branch_name", &target.branch.branch())
.context("Failed to write default target branch name")?;
self.writer
.write_string("branches/target/remote_name", &target.remote_name)
.write_string("branches/target/remote_name", &target.branch.remote())
.context("Failed to write default target remote name ")?;
self.writer
.write_string("branches/target/remote_url", &target.remote_url)
@ -52,13 +52,13 @@ impl<'writer> TargetWriter<'writer> {
self.writer
.write_string(
&format!("branches/{}/target/branch_name", id),
&target.branch_name,
&target.branch.branch(),
)
.context("Failed to write branch target branch name")?;
self.writer
.write_string(
&format!("branches/{}/target/remote_name", id),
&target.remote_name,
&target.branch.remote(),
)
.context("Failed to write branch target remote")?;
self.writer
@ -138,8 +138,9 @@ mod tests {
let branch = test_branch();
let target = Target {
branch_name: "branch name".to_string(),
remote_name: "remote name".to_string(),
branch: format!("refs/remotes/remote name/branch name")
.parse()
.unwrap(),
remote_url: "remote url".to_string(),
sha: "0123456789abcdef0123456789abcdef01234567".parse().unwrap(),
};
@ -160,12 +161,12 @@ mod tests {
assert_eq!(
fs::read_to_string(root.join("target").join("branch_name").to_str().unwrap())
.context("Failed to read branch target name")?,
target.branch_name
target.branch.branch()
);
assert_eq!(
fs::read_to_string(root.join("target").join("remote_name").to_str().unwrap())
.context("Failed to read branch target name name")?,
target.remote_name
target.branch.remote()
);
assert_eq!(
fs::read_to_string(root.join("target").join("remote_url").to_str().unwrap())
@ -230,8 +231,9 @@ mod tests {
let branch = test_branch();
let target = Target {
remote_name: "remote name".to_string(),
branch_name: "branch name".to_string(),
branch: format!("refs/remotes/remote name/branch name")
.parse()
.unwrap(),
remote_url: "remote url".to_string(),
sha: "0123456789abcdef0123456789abcdef01234567".parse().unwrap(),
};
@ -242,8 +244,9 @@ mod tests {
target_writer.write(&branch.id, &target)?;
let updated_target = Target {
remote_name: "updated remote name".to_string(),
branch_name: "updated branch name".to_string(),
branch: format!("refs/remotes/updated remote name/updated branch name")
.parse()
.unwrap(),
remote_url: "updated remote url".to_string(),
sha: "fedcba9876543210fedcba9876543210fedcba98".parse().unwrap(),
};
@ -255,13 +258,13 @@ mod tests {
assert_eq!(
fs::read_to_string(root.join("target").join("branch_name").to_str().unwrap())
.context("Failed to read branch target branch name")?,
updated_target.branch_name
updated_target.branch.branch()
);
assert_eq!(
fs::read_to_string(root.join("target").join("remote_name").to_str().unwrap())
.context("Failed to read branch target remote name")?,
updated_target.remote_name
updated_target.branch.remote()
);
assert_eq!(
fs::read_to_string(root.join("target").join("remote_url").to_str().unwrap())

View File

@ -56,8 +56,7 @@ fn set_test_target(
repository: &git::Repository,
) -> Result<()> {
target::Writer::new(gb_repo).write_default(&target::Target {
branch_name: "origin/master".to_string(),
remote_name: "origin".to_string(),
branch: "refs/remotes/origin/master".parse().unwrap(),
remote_url: "origin".to_string(),
sha: repository.head().unwrap().target().unwrap(),
})?;
@ -253,8 +252,7 @@ fn test_create_branch_with_ownership() -> Result<()> {
let project_repository = project_repository::Repository::open(&project)?;
target::Writer::new(&gb_repo).write_default(&target::Target {
remote_name: "origin".to_string(),
branch_name: "master".to_string(),
branch: "refs/remotes/origin/master".parse().unwrap(),
remote_url: "origin".to_string(),
sha: repository.head().unwrap().target().unwrap(),
})?;
@ -312,8 +310,7 @@ fn test_create_branch_in_the_middle() -> Result<()> {
let project_repository = project_repository::Repository::open(&project)?;
target::Writer::new(&gb_repo).write_default(&target::Target {
branch_name: "master".to_string(),
remote_name: "origin".to_string(),
branch: "refs/remotes/origin/master".parse().unwrap(),
remote_url: "origin".to_string(),
sha: repository.head().unwrap().target().unwrap(),
})?;
@ -358,8 +355,7 @@ fn test_create_branch_no_arguments() -> Result<()> {
let project_repository = project_repository::Repository::open(&project)?;
target::Writer::new(&gb_repo).write_default(&target::Target {
branch_name: "master".to_string(),
remote_name: "origin".to_string(),
branch: "refs/remotes/origin/master".parse().unwrap(),
remote_url: "origin".to_string(),
sha: repository.head().unwrap().target().unwrap(),
})?;
@ -541,8 +537,7 @@ fn test_get_status_files_by_branch_no_hunks_no_branches() -> Result<()> {
let project_repository = project_repository::Repository::open(&project)?;
target::Writer::new(&gb_repo).write_default(&target::Target {
branch_name: "master".to_string(),
remote_name: "origin".to_string(),
branch: "refs/remotes/origin/master".parse().unwrap(),
remote_url: "origin".to_string(),
sha: repository.head().unwrap().target().unwrap(),
})?;
@ -567,8 +562,7 @@ fn test_get_status_files_by_branch() -> Result<()> {
let project_repository = project_repository::Repository::open(&project)?;
target::Writer::new(&gb_repo).write_default(&target::Target {
branch_name: "master".to_string(),
remote_name: "origin".to_string(),
branch: "refs/remotes/origin/master".parse().unwrap(),
remote_url: "origin".to_string(),
sha: repository.head().unwrap().target().unwrap(),
})?;
@ -624,8 +618,7 @@ fn test_updated_ownership_should_bubble_up() -> Result<()> {
let project_repository = project_repository::Repository::open(&project)?;
target::Writer::new(&gb_repo).write_default(&target::Target {
branch_name: "master".to_string(),
remote_name: "origin".to_string(),
branch: "refs/remotes/origin/master".parse().unwrap(),
remote_url: "origin".to_string(),
sha: repository.head().unwrap().target().unwrap(),
})?;
@ -737,8 +730,7 @@ fn test_move_hunks_multiple_sources() -> Result<()> {
let project_repository = project_repository::Repository::open(&project)?;
target::Writer::new(&gb_repo).write_default(&target::Target {
branch_name: "master".to_string(),
remote_name: "origin".to_string(),
branch: "refs/remotes/origin/master".parse().unwrap(),
remote_url: "origin".to_string(),
sha: repository.head().unwrap().target().unwrap(),
})?;
@ -851,8 +843,7 @@ fn test_move_hunks_partial_explicitly() -> Result<()> {
let project_repository = project_repository::Repository::open(&project)?;
target::Writer::new(&gb_repo).write_default(&target::Target {
branch_name: "master".to_string(),
remote_name: "origin".to_string(),
branch: "refs/remotes/origin/master".parse().unwrap(),
remote_url: "origin".to_string(),
sha: repository.head().unwrap().target().unwrap(),
})?;
@ -945,8 +936,7 @@ fn test_add_new_hunk_to_the_end() -> Result<()> {
let project_repository = project_repository::Repository::open(&project)?;
target::Writer::new(&gb_repo).write_default(&target::Target {
branch_name: "master".to_string(),
remote_name: "origin".to_string(),
branch: "refs/remotes/origin/master".parse().unwrap(),
remote_url: "origin".to_string(),
sha: repository.head().unwrap().target().unwrap(),
})?;
@ -1008,8 +998,7 @@ fn test_update_base_branch_base() -> Result<()> {
let project_repository = project_repository::Repository::open(&project)?;
target::Writer::new(&gb_repo).write_default(&target::Target {
branch_name: "origin/master".to_string(),
remote_name: "origin".to_string(),
branch: "refs/remotes/origin/master".parse().unwrap(),
remote_url: "origin".to_string(),
sha: repository.head().unwrap().target().unwrap(),
})?;
@ -1116,8 +1105,7 @@ fn test_update_base_branch_detect_integrated_branches() -> Result<()> {
let project_repository = project_repository::Repository::open(&project)?;
target::Writer::new(&gb_repo).write_default(&target::Target {
branch_name: "origin/master".to_string(),
remote_name: "origin".to_string(),
branch: "refs/remotes/origin/master".parse().unwrap(),
remote_url: "origin".to_string(),
sha: repository.head().unwrap().target().unwrap(),
})?;
@ -1198,8 +1186,7 @@ fn test_update_base_branch_detect_integrated_branches_with_more_work() -> Result
let project_repository = project_repository::Repository::open(&project)?;
target::Writer::new(&gb_repo).write_default(&target::Target {
branch_name: "origin/master".to_string(),
remote_name: "origin".to_string(),
branch: "refs/remotes/origin/master".parse().unwrap(),
remote_url: "origin".to_string(),
sha: repository.head().unwrap().target().unwrap(),
})?;
@ -1373,8 +1360,7 @@ fn test_update_target_with_conflicts_in_vbranches() -> Result<()> {
test_utils::commit_all(&repository);
target::Writer::new(&gb_repo).write_default(&target::Target {
branch_name: "origin/master".to_string(),
remote_name: "origin".to_string(),
branch: "refs/remotes/origin/master".parse().unwrap(),
remote_url: "origin".to_string(),
sha: repository.head().unwrap().target().unwrap(),
})?;
@ -2372,8 +2358,7 @@ fn test_upstream_integrated_vbranch() -> Result<()> {
)?;
target::Writer::new(&gb_repo).write_default(&target::Target {
remote_name: "origin".to_string(),
branch_name: "origin/master".to_string(),
branch: "refs/remotes/origin/master".parse().unwrap(),
remote_url: "http://origin.com/project".to_string(),
sha: base_commit,
})?;
@ -2810,8 +2795,7 @@ fn test_apply_out_of_date_vbranch() -> Result<()> {
let base_commit = repository.head().unwrap().target().unwrap();
target::Writer::new(&gb_repo).write_default(&target::Target {
branch_name: "origin/master".to_string(),
remote_name: "origin".to_string(),
branch: "refs/remotes/origin/master".parse().unwrap(),
remote_url: "http://origin.com/project".to_string(),
sha: base_commit,
})?;
@ -2945,8 +2929,7 @@ fn test_apply_out_of_date_conflicting_vbranch() -> Result<()> {
let base_commit = repository.head().unwrap().target().unwrap();
target::Writer::new(&gb_repo).write_default(&target::Target {
branch_name: "origin/master".to_string(),
remote_name: "origin".to_string(),
branch: "refs/remotes/origin/master".parse().unwrap(),
remote_url: "http://origin.com/project".to_string(),
sha: base_commit,
})?;

View File

@ -510,25 +510,13 @@ pub fn list_remote_branches(
// skip the default target branch (both local and remote)
match branch_name {
git::BranchName::Remote(ref remote_branch_name) => {
if format!(
"{}/{}",
remote_branch_name.remote(),
remote_branch_name.branch()
)
.eq(&default_target.branch_name)
{
if *remote_branch_name == default_target.branch {
continue;
}
}
git::BranchName::Local(ref local_branch_name) => {
if let Some(upstream_branch_name) = local_branch_name.remote() {
if format!(
"{}/{}",
upstream_branch_name.remote(),
upstream_branch_name.branch()
)
.eq(&default_target.branch_name)
{
if *upstream_branch_name == default_target.branch {
continue;
}
}
@ -1920,7 +1908,7 @@ pub fn push(
let remote_branch = match get_default_target(&current_session_reader)? {
Some(target) => format!(
"refs/remotes/{}/{}",
target.remote_name,
target.branch.remote(),
name_to_branch(&vbranch.name)
)
.parse::<git::RemoteBranchName>()
@ -1979,7 +1967,7 @@ fn is_commit_integrated(
) -> Result<bool> {
let remote_branch = project_repository
.git_repository
.find_branch(&target.branch_name, git2::BranchType::Remote)?;
.find_branch(&target.branch.clone().into())?;
let remote_head = remote_branch.peel_to_commit()?;
let upstream_commits = project_repository.l(
remote_head.id(),

View File

@ -102,7 +102,7 @@ impl HandlerInner {
let project_repository = project_repository::Repository::open(&project)?;
let fetch_result =
if let Err(err) = project_repository.fetch(&default_target.remote_name, &key) {
if let Err(err) = project_repository.fetch(&default_target.branch.remote(), &key) {
tracing::error!("{}: failed to fetch project data: {:#}", project_id, err);
projects::FetchResult::Error {
attempt: project

View File

@ -220,8 +220,13 @@ mod test {
fn test_target() -> virtual_branches::target::Target {
virtual_branches::target::Target {
branch_name: format!("branch name {}", unsafe { TEST_TARGET_INDEX }),
remote_name: format!("remote name {}", unsafe { TEST_TARGET_INDEX }),
branch: format!(
"refs/remotes/remote name {}/branch name {}",
unsafe { TEST_TARGET_INDEX },
unsafe { TEST_TARGET_INDEX }
)
.parse()
.unwrap(),
remote_url: format!("remote url {}", unsafe { TEST_TARGET_INDEX }),
sha: format!("0123456789abcdef0123456789abcdef0123456{}", unsafe {
TEST_TARGET_INDEX