mirror of
https://github.com/gitbutlerapp/gitbutler.git
synced 2025-01-06 01:27:24 +03:00
add can apply methods
This commit is contained in:
parent
c5dc6785a2
commit
2cfe510fc4
@ -337,6 +337,13 @@ impl Repository {
|
||||
.map_err(Into::into)
|
||||
}
|
||||
|
||||
pub fn get_wd_tree(&self) -> Result<Tree> {
|
||||
let mut index = self.0.index()?;
|
||||
index.add_all(["*"], git2::IndexAddOption::DEFAULT, None)?;
|
||||
let oid = index.write_tree()?;
|
||||
self.0.find_tree(oid).map(Into::into).map_err(Into::into)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub fn remote(&self, name: &str, url: &str) -> Result<Remote> {
|
||||
self.0.remote(name, url).map(Into::into).map_err(Into::into)
|
||||
|
@ -682,6 +682,8 @@ async fn main() {
|
||||
virtual_branches::commands::unapply_branch,
|
||||
virtual_branches::commands::push_virtual_branch,
|
||||
virtual_branches::commands::create_virtual_branch_from_branch,
|
||||
virtual_branches::commands::can_apply_virtual_branch,
|
||||
virtual_branches::commands::can_apply_remote_branch,
|
||||
fetch_from_target,
|
||||
mark_resolved,
|
||||
git_set_global_config,
|
||||
|
@ -46,6 +46,11 @@ impl<'repository> Repository<'repository> {
|
||||
Ok(head)
|
||||
}
|
||||
|
||||
pub fn get_wd_tree(&self) -> Result<git::Tree> {
|
||||
let tree = self.git_repository.get_wd_tree()?;
|
||||
Ok(tree)
|
||||
}
|
||||
|
||||
pub fn is_path_ignored<P: AsRef<std::path::Path>>(&self, path: P) -> Result<bool> {
|
||||
let path = path.as_ref();
|
||||
let ignored = self.git_repository.is_path_ignored(path)?;
|
||||
|
@ -409,7 +409,9 @@ pub fn update_base_branch(
|
||||
|
||||
// ok, now all the problematic branches have been unapplied, so we can try to merge the upstream branch into our current working directory
|
||||
// first, get a new wd tree
|
||||
let wd_tree = super::get_wd_tree(repo)?;
|
||||
let wd_tree = project_repository
|
||||
.get_wd_tree()
|
||||
.context("failed to get wd tree")?;
|
||||
|
||||
// and try to merge it
|
||||
let mut merge_index = repo
|
||||
|
@ -168,3 +168,31 @@ pub async fn push_virtual_branch(
|
||||
.await
|
||||
.map_err(Into::into)
|
||||
}
|
||||
|
||||
#[tauri::command(async)]
|
||||
#[instrument(skip(handle))]
|
||||
pub async fn can_apply_virtual_branch(
|
||||
handle: AppHandle,
|
||||
project_id: &str,
|
||||
branch_id: &str,
|
||||
) -> Result<bool, Error> {
|
||||
handle
|
||||
.state::<Controller>()
|
||||
.can_apply_virtual_branch(project_id, branch_id)
|
||||
.await
|
||||
.map_err(Into::into)
|
||||
}
|
||||
|
||||
#[tauri::command(async)]
|
||||
#[instrument(skip(handle))]
|
||||
pub async fn can_apply_remote_branch(
|
||||
handle: AppHandle,
|
||||
project_id: &str,
|
||||
branch: git::BranchName,
|
||||
) -> Result<bool, Error> {
|
||||
handle
|
||||
.state::<Controller>()
|
||||
.can_apply_remote_branch(project_id, &branch)
|
||||
.await
|
||||
.map_err(Into::into)
|
||||
}
|
||||
|
@ -85,6 +85,34 @@ impl Controller {
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn can_apply_remote_branch(
|
||||
&self,
|
||||
project_id: &str,
|
||||
branch_name: &git::BranchName,
|
||||
) -> Result<bool, Error> {
|
||||
self.with_lock(project_id, || {
|
||||
self.with_verify_branch(project_id, |gb_repository, project_repository| {
|
||||
super::is_remote_branch_mergeable(gb_repository, project_repository, branch_name)
|
||||
.map_err(Error::Other)
|
||||
})
|
||||
})
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn can_apply_virtual_branch(
|
||||
&self,
|
||||
project_id: &str,
|
||||
branch_id: &str,
|
||||
) -> Result<bool, Error> {
|
||||
self.with_lock(project_id, || {
|
||||
self.with_verify_branch(project_id, |gb_repository, project_repository| {
|
||||
super::is_virtual_branch_mergeable(gb_repository, project_repository, branch_id)
|
||||
.map_err(Error::Other)
|
||||
})
|
||||
})
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn list_virtual_branches(
|
||||
&self,
|
||||
project_id: &str,
|
||||
|
@ -319,7 +319,7 @@ pub fn apply_branch(
|
||||
}
|
||||
}
|
||||
|
||||
let wd_tree = get_wd_tree(repo)?;
|
||||
let wd_tree = project_repository.get_wd_tree()?;
|
||||
|
||||
// check index for conflicts
|
||||
let mut merge_index = repo
|
||||
@ -499,7 +499,7 @@ pub fn list_remote_branches(
|
||||
.find_commit(main_oid)
|
||||
.context("failed to find target commit")?;
|
||||
|
||||
let wd_tree = get_wd_tree(repo)?;
|
||||
let wd_tree = project_repository.get_wd_tree()?;
|
||||
|
||||
let virtual_branches_names = Iterator::new(¤t_session_reader)
|
||||
.context("failed to create branch iterator")?
|
||||
@ -687,14 +687,6 @@ fn list_remote_commit_files(
|
||||
Ok(files)
|
||||
}
|
||||
|
||||
pub fn get_wd_tree(repo: &git::Repository) -> Result<git::Tree> {
|
||||
let mut index = repo.index()?;
|
||||
index.add_all(["*"], git2::IndexAddOption::DEFAULT, None)?;
|
||||
let oid = index.write_tree()?;
|
||||
let tree = repo.find_tree(oid)?;
|
||||
Ok(tree)
|
||||
}
|
||||
|
||||
fn find_base_tree<'a>(
|
||||
repo: &'a git::Repository,
|
||||
branch_commit: &'a git::Commit<'a>,
|
||||
@ -733,7 +725,7 @@ pub fn list_virtual_branches(
|
||||
None => return Ok(vec![]),
|
||||
};
|
||||
|
||||
let wd_tree = get_wd_tree(&project_repository.git_repository)?;
|
||||
let wd_tree = project_repository.get_wd_tree()?;
|
||||
|
||||
let statuses = get_status_by_branch(gb_repository, project_repository)?;
|
||||
for (branch, files) in &statuses {
|
||||
@ -2085,3 +2077,110 @@ fn is_commit_integrated(
|
||||
// then the vbranch is fully merged
|
||||
Ok(merge_tree_oid == upstream_tree_oid)
|
||||
}
|
||||
|
||||
pub fn is_remote_branch_mergeable(
|
||||
gb_repository: &gb_repository::Repository,
|
||||
project_repository: &project_repository::Repository,
|
||||
branch_name: &git::BranchName,
|
||||
) -> Result<bool> {
|
||||
// get the current target
|
||||
let current_session = gb_repository
|
||||
.get_or_create_current_session()
|
||||
.context("failed to get or create currnt session")?;
|
||||
let current_session_reader = sessions::Reader::open(gb_repository, ¤t_session)
|
||||
.context("failed to open current session")?;
|
||||
|
||||
let default_target =
|
||||
get_default_target(¤t_session_reader)?.context("no default target set")?;
|
||||
|
||||
let target_commit = project_repository
|
||||
.git_repository
|
||||
.find_commit(default_target.sha)
|
||||
.context("failed to find target commit")?;
|
||||
|
||||
let branch = project_repository.git_repository.find_branch(branch_name)?;
|
||||
let branch_oid = branch.target().context("detatched head")?;
|
||||
let branch_commit = project_repository
|
||||
.git_repository
|
||||
.find_commit(branch_oid)
|
||||
.context("failed to find branch commit")?;
|
||||
|
||||
let base_tree = find_base_tree(
|
||||
&project_repository.git_repository,
|
||||
&branch_commit,
|
||||
&target_commit,
|
||||
)?;
|
||||
|
||||
let wd_tree = project_repository.get_wd_tree()?;
|
||||
|
||||
let branch_tree = branch_commit.tree()?;
|
||||
let mergeable = !project_repository
|
||||
.git_repository
|
||||
.merge_trees(&base_tree, &branch_tree, &wd_tree)?
|
||||
.has_conflicts();
|
||||
|
||||
Ok(mergeable)
|
||||
}
|
||||
|
||||
pub fn is_virtual_branch_mergeable(
|
||||
gb_repository: &gb_repository::Repository,
|
||||
project_repository: &project_repository::Repository,
|
||||
branch_id: &str,
|
||||
) -> Result<bool> {
|
||||
let current_session = gb_repository
|
||||
.get_or_create_current_session()
|
||||
.context("failed to get or create currnt session")?;
|
||||
let current_session_reader = sessions::Reader::open(gb_repository, ¤t_session)
|
||||
.context("failed to open current session reader")?;
|
||||
let branch_reader = branch::Reader::new(¤t_session_reader);
|
||||
let branch = branch_reader
|
||||
.read(branch_id)
|
||||
.context("failed to read branch")?;
|
||||
if branch.applied {
|
||||
bail!("branch {} is applied", branch.name);
|
||||
}
|
||||
|
||||
let default_target = get_default_target(¤t_session_reader)
|
||||
.context("failed to read default target")?
|
||||
.context("no default target set")?;
|
||||
|
||||
// determine if this branch is up to date with the target/base
|
||||
let merge_base = project_repository
|
||||
.git_repository
|
||||
.merge_base(default_target.sha, branch.head)?;
|
||||
|
||||
if merge_base != default_target.sha {
|
||||
return Ok(false);
|
||||
}
|
||||
|
||||
let branch_commit = project_repository
|
||||
.git_repository
|
||||
.find_commit(branch.head)
|
||||
.context("failed to find branch commit")?;
|
||||
|
||||
let target_commit = project_repository
|
||||
.git_repository
|
||||
.find_commit(default_target.sha)
|
||||
.context("failed to find target commit")?;
|
||||
|
||||
let base_tree = find_base_tree(
|
||||
&project_repository.git_repository,
|
||||
&branch_commit,
|
||||
&target_commit,
|
||||
)?;
|
||||
|
||||
let wd_tree = project_repository.get_wd_tree()?;
|
||||
|
||||
// determine if this tree is mergeable
|
||||
let branch_tree = project_repository
|
||||
.git_repository
|
||||
.find_tree(branch.tree)
|
||||
.context("failed to find branch tree")?;
|
||||
|
||||
let is_mergeable = !project_repository
|
||||
.git_repository
|
||||
.merge_trees(&base_tree, &branch_tree, &wd_tree)?
|
||||
.has_conflicts();
|
||||
|
||||
Ok(is_mergeable)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user