Merge pull request #4523 from gitbutlerapp/Boosting-my-contribution-score

Boosting my contribution score
This commit is contained in:
Caleb Owens 2024-07-29 11:18:58 +02:00 committed by GitHub
commit d37dcefdf5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
29 changed files with 905 additions and 1213 deletions

View File

@ -1,6 +1,6 @@
use anyhow::Result;
use gitbutler_branch::{BranchCreateRequest, BranchId, BranchOwnershipClaims, BranchUpdateRequest};
use gitbutler_command_context::ProjectRepository;
use gitbutler_command_context::CommandContext;
use gitbutler_oplog::{
entry::{OperationKind, SnapshotDetails},
OplogExt, SnapshotExt,
@ -34,21 +34,13 @@ impl VirtualBranchActions {
ownership: Option<&BranchOwnershipClaims>,
run_hooks: bool,
) -> Result<git2::Oid> {
let project_repository = open_with_verify(project)?;
let ctx = open_with_verify(project)?;
let mut guard = project.exclusive_worktree_access();
let snapshot_tree = project_repository
.project()
.prepare_snapshot(guard.read_permission());
let result = branch::commit(
&project_repository,
branch_id,
message,
ownership,
run_hooks,
)
.map_err(Into::into);
let snapshot_tree = ctx.project().prepare_snapshot(guard.read_permission());
let result =
branch::commit(&ctx, branch_id, message, ownership, run_hooks).map_err(Into::into);
let _ = snapshot_tree.and_then(|snapshot_tree| {
project_repository.project().snapshot_commit_creation(
ctx.project().snapshot_commit_creation(
snapshot_tree,
result.as_ref().err(),
message.to_owned(),
@ -64,8 +56,8 @@ impl VirtualBranchActions {
project: &Project,
branch_name: &RemoteRefname,
) -> Result<bool> {
let project_repository = ProjectRepository::open(project)?;
branch::is_remote_branch_mergeable(&project_repository, branch_name).map_err(Into::into)
let ctx = CommandContext::open(project)?;
branch::is_remote_branch_mergeable(&ctx, branch_name).map_err(Into::into)
}
pub fn list_virtual_branches(
@ -84,9 +76,9 @@ impl VirtualBranchActions {
project: &Project,
create: &BranchCreateRequest,
) -> Result<BranchId> {
let project_repository = open_with_verify(project)?;
let ctx = open_with_verify(project)?;
let mut guard = project.exclusive_worktree_access();
let branch_manager = project_repository.branch_manager();
let branch_manager = ctx.branch_manager();
let branch_id = branch_manager
.create_virtual_branch(create, guard.write_permission())?
.id;
@ -95,8 +87,8 @@ impl VirtualBranchActions {
#[instrument(skip(project), err(Debug))]
pub fn get_base_branch_data(project: &Project) -> Result<BaseBranch> {
let project_repository = ProjectRepository::open(project)?;
get_base_branch_data(&project_repository)
let ctx = CommandContext::open(project)?;
get_base_branch_data(&ctx)
}
pub fn list_remote_commit_files(
@ -104,9 +96,8 @@ impl VirtualBranchActions {
project: &Project,
commit_oid: git2::Oid,
) -> Result<Vec<RemoteBranchFile>> {
let project_repository = ProjectRepository::open(project)?;
crate::file::list_remote_commit_files(project_repository.repo(), commit_oid)
.map_err(Into::into)
let ctx = CommandContext::open(project)?;
crate::file::list_remote_commit_files(ctx.repository(), commit_oid).map_err(Into::into)
}
pub fn set_base_branch(
@ -114,38 +105,38 @@ impl VirtualBranchActions {
project: &Project,
target_branch: &RemoteRefname,
) -> Result<BaseBranch> {
let project_repository = ProjectRepository::open(project)?;
let ctx = CommandContext::open(project)?;
let mut guard = project.exclusive_worktree_access();
let _ = project_repository.project().create_snapshot(
let _ = ctx.project().create_snapshot(
SnapshotDetails::new(OperationKind::SetBaseBranch),
guard.write_permission(),
);
set_base_branch(&project_repository, target_branch)
set_base_branch(&ctx, target_branch)
}
pub fn set_target_push_remote(&self, project: &Project, push_remote: &str) -> Result<()> {
let project_repository = ProjectRepository::open(project)?;
set_target_push_remote(&project_repository, push_remote)
let ctx = CommandContext::open(project)?;
set_target_push_remote(&ctx, push_remote)
}
pub fn integrate_upstream_commits(&self, project: &Project, branch_id: BranchId) -> Result<()> {
let project_repository = open_with_verify(project)?;
let ctx = open_with_verify(project)?;
let mut guard = project.exclusive_worktree_access();
let _ = project_repository.project().create_snapshot(
let _ = ctx.project().create_snapshot(
SnapshotDetails::new(OperationKind::MergeUpstream),
guard.write_permission(),
);
branch::integrate_upstream_commits(&project_repository, branch_id).map_err(Into::into)
branch::integrate_upstream_commits(&ctx, branch_id).map_err(Into::into)
}
pub fn update_base_branch(&self, project: &Project) -> Result<Vec<ReferenceName>> {
let project_repository = open_with_verify(project)?;
let ctx = open_with_verify(project)?;
let mut guard = project.exclusive_worktree_access();
let _ = project_repository.project().create_snapshot(
let _ = ctx.project().create_snapshot(
SnapshotDetails::new(OperationKind::UpdateWorkspaceBase),
guard.write_permission(),
);
update_base_branch(&project_repository, guard.write_permission()).map_err(Into::into)
update_base_branch(&ctx, guard.write_permission()).map_err(Into::into)
}
pub fn update_virtual_branch(
@ -153,18 +144,16 @@ impl VirtualBranchActions {
project: &Project,
branch_update: BranchUpdateRequest,
) -> Result<()> {
let project_repository = open_with_verify(project)?;
let ctx = open_with_verify(project)?;
let mut guard = project.exclusive_worktree_access();
let snapshot_tree = project_repository
.project()
.prepare_snapshot(guard.read_permission());
let old_branch = project_repository
let snapshot_tree = ctx.project().prepare_snapshot(guard.read_permission());
let old_branch = ctx
.project()
.virtual_branches()
.get_branch_in_workspace(branch_update.id)?;
let result = branch::update_branch(&project_repository, &branch_update);
let result = branch::update_branch(&ctx, &branch_update);
let _ = snapshot_tree.and_then(|snapshot_tree| {
project_repository.project().snapshot_branch_update(
ctx.project().snapshot_branch_update(
snapshot_tree,
&old_branch,
&branch_update,
@ -181,22 +170,22 @@ impl VirtualBranchActions {
project: &Project,
branch_updates: Vec<BranchUpdateRequest>,
) -> Result<()> {
let project_repository = open_with_verify(project)?;
let ctx = open_with_verify(project)?;
for branch_update in branch_updates {
let branch = project_repository
let branch = ctx
.project()
.virtual_branches()
.get_branch_in_workspace(branch_update.id)?;
if branch_update.order != Some(branch.order) {
branch::update_branch(&project_repository, &branch_update)?;
branch::update_branch(&ctx, &branch_update)?;
}
}
Ok(())
}
pub fn delete_virtual_branch(&self, project: &Project, branch_id: BranchId) -> Result<()> {
let project_repository = open_with_verify(project)?;
let branch_manager = project_repository.branch_manager();
let ctx = open_with_verify(project)?;
let branch_manager = ctx.branch_manager();
let mut guard = project.exclusive_worktree_access();
branch_manager.delete_branch(branch_id, guard.write_permission())
}
@ -206,24 +195,23 @@ impl VirtualBranchActions {
project: &Project,
ownership: &BranchOwnershipClaims,
) -> Result<()> {
let project_repository = open_with_verify(project)?;
let ctx = open_with_verify(project)?;
let mut guard = project.exclusive_worktree_access();
let _ = project_repository.project().create_snapshot(
let _ = ctx.project().create_snapshot(
SnapshotDetails::new(OperationKind::DiscardHunk),
guard.write_permission(),
);
branch::unapply_ownership(&project_repository, ownership, guard.write_permission())
.map_err(Into::into)
branch::unapply_ownership(&ctx, ownership, guard.write_permission()).map_err(Into::into)
}
pub fn reset_files(&self, project: &Project, files: &Vec<String>) -> Result<()> {
let project_repository = open_with_verify(project)?;
let ctx = open_with_verify(project)?;
let mut guard = project.exclusive_worktree_access();
let _ = project_repository.project().create_snapshot(
let _ = ctx.project().create_snapshot(
SnapshotDetails::new(OperationKind::DiscardFile),
guard.write_permission(),
);
branch::reset_files(&project_repository, files).map_err(Into::into)
branch::reset_files(&ctx, files).map_err(Into::into)
}
pub fn amend(
@ -233,13 +221,13 @@ impl VirtualBranchActions {
commit_oid: git2::Oid,
ownership: &BranchOwnershipClaims,
) -> Result<git2::Oid> {
let project_repository = open_with_verify(project)?;
let ctx = open_with_verify(project)?;
let mut guard = project.exclusive_worktree_access();
let _ = project_repository.project().create_snapshot(
let _ = ctx.project().create_snapshot(
SnapshotDetails::new(OperationKind::AmendCommit),
guard.write_permission(),
);
branch::amend(&project_repository, branch_id, commit_oid, ownership)
branch::amend(&ctx, branch_id, commit_oid, ownership)
}
pub fn move_commit_file(
@ -250,20 +238,14 @@ impl VirtualBranchActions {
to_commit_oid: git2::Oid,
ownership: &BranchOwnershipClaims,
) -> Result<git2::Oid> {
let project_repository = open_with_verify(project)?;
let ctx = open_with_verify(project)?;
let mut guard = project.exclusive_worktree_access();
let _ = project_repository.project().create_snapshot(
let _ = ctx.project().create_snapshot(
SnapshotDetails::new(OperationKind::MoveCommitFile),
guard.write_permission(),
);
branch::move_commit_file(
&project_repository,
branch_id,
from_commit_oid,
to_commit_oid,
ownership,
)
.map_err(Into::into)
branch::move_commit_file(&ctx, branch_id, from_commit_oid, to_commit_oid, ownership)
.map_err(Into::into)
}
pub fn undo_commit(
@ -272,15 +254,13 @@ impl VirtualBranchActions {
branch_id: BranchId,
commit_oid: git2::Oid,
) -> Result<()> {
let project_repository = open_with_verify(project)?;
let ctx = open_with_verify(project)?;
let mut guard = project.exclusive_worktree_access();
let snapshot_tree = project_repository
.project()
.prepare_snapshot(guard.read_permission());
let snapshot_tree = ctx.project().prepare_snapshot(guard.read_permission());
let result: Result<()> =
branch::undo_commit(&project_repository, branch_id, commit_oid).map_err(Into::into);
branch::undo_commit(&ctx, branch_id, commit_oid).map_err(Into::into);
let _ = snapshot_tree.and_then(|snapshot_tree| {
project_repository.project().snapshot_commit_undo(
ctx.project().snapshot_commit_undo(
snapshot_tree,
result.as_ref(),
commit_oid,
@ -297,14 +277,13 @@ impl VirtualBranchActions {
commit_oid: git2::Oid,
offset: i32,
) -> Result<()> {
let project_repository = open_with_verify(project)?;
let ctx = open_with_verify(project)?;
let mut guard = project.exclusive_worktree_access();
let _ = project_repository.project().create_snapshot(
let _ = ctx.project().create_snapshot(
SnapshotDetails::new(OperationKind::InsertBlankCommit),
guard.write_permission(),
);
branch::insert_blank_commit(&project_repository, branch_id, commit_oid, offset)
.map_err(Into::into)
branch::insert_blank_commit(&ctx, branch_id, commit_oid, offset).map_err(Into::into)
}
pub fn reorder_commit(
@ -314,14 +293,13 @@ impl VirtualBranchActions {
commit_oid: git2::Oid,
offset: i32,
) -> Result<()> {
let project_repository = open_with_verify(project)?;
let ctx = open_with_verify(project)?;
let mut guard = project.exclusive_worktree_access();
let _ = project_repository.project().create_snapshot(
let _ = ctx.project().create_snapshot(
SnapshotDetails::new(OperationKind::ReorderCommit),
guard.write_permission(),
);
branch::reorder_commit(&project_repository, branch_id, commit_oid, offset)
.map_err(Into::into)
branch::reorder_commit(&ctx, branch_id, commit_oid, offset).map_err(Into::into)
}
pub fn reset_virtual_branch(
@ -330,13 +308,13 @@ impl VirtualBranchActions {
branch_id: BranchId,
target_commit_oid: git2::Oid,
) -> Result<()> {
let project_repository = open_with_verify(project)?;
let ctx = open_with_verify(project)?;
let mut guard = project.exclusive_worktree_access();
let _ = project_repository.project().create_snapshot(
let _ = ctx.project().create_snapshot(
SnapshotDetails::new(OperationKind::UndoCommit),
guard.write_permission(),
);
branch::reset_branch(&project_repository, branch_id, target_commit_oid).map_err(Into::into)
branch::reset_branch(&ctx, branch_id, target_commit_oid).map_err(Into::into)
}
pub fn convert_to_real_branch(
@ -344,16 +322,14 @@ impl VirtualBranchActions {
project: &Project,
branch_id: BranchId,
) -> Result<ReferenceName> {
let project_repository = open_with_verify(project)?;
let ctx = open_with_verify(project)?;
let mut guard = project.exclusive_worktree_access();
let snapshot_tree = project_repository
.project()
.prepare_snapshot(guard.read_permission());
let branch_manager = project_repository.branch_manager();
let snapshot_tree = ctx.project().prepare_snapshot(guard.read_permission());
let branch_manager = ctx.branch_manager();
let result = branch_manager.convert_to_real_branch(branch_id, guard.write_permission());
let _ = snapshot_tree.and_then(|snapshot_tree| {
project_repository.project().snapshot_branch_unapplied(
ctx.project().snapshot_branch_unapplied(
snapshot_tree,
result.as_ref(),
guard.write_permission(),
@ -371,13 +347,13 @@ impl VirtualBranchActions {
askpass: Option<Option<BranchId>>,
) -> Result<()> {
let helper = Helper::default();
let project_repository = open_with_verify(project)?;
branch::push(&project_repository, branch_id, with_force, &helper, askpass)
let ctx = open_with_verify(project)?;
branch::push(&ctx, branch_id, with_force, &helper, askpass)
}
pub fn list_remote_branches(project: Project) -> Result<Vec<RemoteBranch>> {
let project_repository = ProjectRepository::open(&project)?;
list_remote_branches(&project_repository)
let ctx = CommandContext::open(&project)?;
list_remote_branches(&ctx)
}
pub fn get_remote_branch_data(
@ -385,8 +361,8 @@ impl VirtualBranchActions {
project: &Project,
refname: &Refname,
) -> Result<RemoteBranchData> {
let project_repository = ProjectRepository::open(project)?;
get_branch_data(&project_repository, refname)
let ctx = CommandContext::open(project)?;
get_branch_data(&ctx, refname)
}
pub fn squash(
@ -395,13 +371,13 @@ impl VirtualBranchActions {
branch_id: BranchId,
commit_oid: git2::Oid,
) -> Result<()> {
let project_repository = open_with_verify(project)?;
let ctx = open_with_verify(project)?;
let mut guard = project.exclusive_worktree_access();
let _ = project_repository.project().create_snapshot(
let _ = ctx.project().create_snapshot(
SnapshotDetails::new(OperationKind::SquashCommit),
guard.write_permission(),
);
branch::squash(&project_repository, branch_id, commit_oid).map_err(Into::into)
branch::squash(&ctx, branch_id, commit_oid).map_err(Into::into)
}
pub fn update_commit_message(
@ -411,14 +387,13 @@ impl VirtualBranchActions {
commit_oid: git2::Oid,
message: &str,
) -> Result<()> {
let project_repository = open_with_verify(project)?;
let ctx = open_with_verify(project)?;
let mut guard = project.exclusive_worktree_access();
let _ = project_repository.project().create_snapshot(
let _ = ctx.project().create_snapshot(
SnapshotDetails::new(OperationKind::UpdateCommitMessage),
guard.write_permission(),
);
branch::update_commit_message(&project_repository, branch_id, commit_oid, message)
.map_err(Into::into)
branch::update_commit_message(&ctx, branch_id, commit_oid, message).map_err(Into::into)
}
pub fn fetch_from_remotes(
@ -426,15 +401,14 @@ impl VirtualBranchActions {
project: &Project,
askpass: Option<String>,
) -> Result<FetchResult> {
let project_repository = ProjectRepository::open(project)?;
let ctx = CommandContext::open(project)?;
let helper = Helper::default();
let remotes = project_repository.repo().remotes_as_string()?;
let remotes = ctx.repository().remotes_as_string()?;
let fetch_errors: Vec<_> = remotes
.iter()
.filter_map(|remote| {
project_repository
.fetch(remote, &helper, askpass.clone())
ctx.fetch(remote, &helper, askpass.clone())
.err()
.map(|err| err.to_string())
})
@ -459,13 +433,13 @@ impl VirtualBranchActions {
target_branch_id: BranchId,
commit_oid: git2::Oid,
) -> Result<()> {
let project_repository = open_with_verify(project)?;
let ctx = open_with_verify(project)?;
let mut guard = project.exclusive_worktree_access();
let _ = project_repository.project().create_snapshot(
let _ = ctx.project().create_snapshot(
SnapshotDetails::new(OperationKind::MoveCommit),
guard.write_permission(),
);
branch::move_commit(&project_repository, target_branch_id, commit_oid).map_err(Into::into)
branch::move_commit(&ctx, target_branch_id, commit_oid).map_err(Into::into)
}
pub fn create_virtual_branch_from_branch(
@ -474,8 +448,8 @@ impl VirtualBranchActions {
branch: &Refname,
remote: Option<RemoteRefname>,
) -> Result<BranchId> {
let project_repository = open_with_verify(project)?;
let branch_manager = project_repository.branch_manager();
let ctx = open_with_verify(project)?;
let branch_manager = ctx.branch_manager();
let mut guard = project.exclusive_worktree_access();
branch_manager
.create_virtual_branch_from_branch(branch, remote, guard.write_permission())
@ -483,9 +457,9 @@ impl VirtualBranchActions {
}
}
fn open_with_verify(project: &Project) -> Result<ProjectRepository> {
let project_repository = ProjectRepository::open(project)?;
fn open_with_verify(project: &Project) -> Result<CommandContext> {
let ctx = CommandContext::open(project)?;
let mut guard = project.exclusive_worktree_access();
crate::integration::verify_branch(&project_repository, guard.write_permission())?;
Ok(project_repository)
crate::integration::verify_branch(&ctx, guard.write_permission())?;
Ok(ctx)
}

View File

@ -6,7 +6,7 @@ use gitbutler_branch::{
self, Branch, BranchId, BranchOwnershipClaims, Target, VirtualBranchesHandle,
GITBUTLER_INTEGRATION_REFERENCE,
};
use gitbutler_command_context::ProjectRepository;
use gitbutler_command_context::CommandContext;
use gitbutler_error::error::Marker;
use gitbutler_project::{access::WorktreeWritePermission, FetchResult};
use gitbutler_reference::{ReferenceName, Refname, RemoteRefname};
@ -41,18 +41,15 @@ pub struct BaseBranch {
pub last_fetched_ms: Option<u128>,
}
pub(crate) fn get_base_branch_data(project_repository: &ProjectRepository) -> Result<BaseBranch> {
let target = default_target(&project_repository.project().gb_dir())?;
let base = target_to_base_branch(project_repository, &target)?;
pub(crate) fn get_base_branch_data(ctx: &CommandContext) -> Result<BaseBranch> {
let target = default_target(&ctx.project().gb_dir())?;
let base = target_to_base_branch(ctx, &target)?;
Ok(base)
}
fn go_back_to_integration(
project_repository: &ProjectRepository,
default_target: &Target,
) -> Result<BaseBranch> {
let statuses = project_repository
.repo()
fn go_back_to_integration(ctx: &CommandContext, default_target: &Target) -> Result<BaseBranch> {
let statuses = ctx
.repository()
.statuses(Some(
git2::StatusOptions::new()
.show(git2::StatusShow::IndexAndWorkdir)
@ -63,13 +60,13 @@ fn go_back_to_integration(
return Err(anyhow!("current HEAD is dirty")).context(Marker::ProjectConflict);
}
let vb_state = project_repository.project().virtual_branches();
let vb_state = ctx.project().virtual_branches();
let virtual_branches = vb_state
.list_branches_in_workspace()
.context("failed to read virtual branches")?;
let target_commit = project_repository
.repo()
let target_commit = ctx
.repository()
.find_commit(default_target.sha)
.context("failed to find target commit")?;
@ -81,48 +78,47 @@ fn go_back_to_integration(
.context("failed to get base tree from commit")?;
for branch in &virtual_branches {
// merge this branches tree with our tree
let branch_head = project_repository
.repo()
let branch_head = ctx
.repository()
.find_commit(branch.head)
.context("failed to find branch head")?;
let branch_tree = branch_head
.tree()
.context("failed to get branch head tree")?;
let mut result = project_repository
.repo()
let mut result = ctx
.repository()
.merge_trees(&base_tree, &final_tree, &branch_tree, None)
.context("failed to merge")?;
let final_tree_oid = result
.write_tree_to(project_repository.repo())
.write_tree_to(ctx.repository())
.context("failed to write tree")?;
final_tree = project_repository
.repo()
final_tree = ctx
.repository()
.find_tree(final_tree_oid)
.context("failed to find written tree")?;
}
project_repository
.repo()
ctx.repository()
.checkout_tree_builder(&final_tree)
.force()
.checkout()
.context("failed to checkout tree")?;
let base = target_to_base_branch(project_repository, default_target)?;
update_gitbutler_integration(&vb_state, project_repository)?;
let base = target_to_base_branch(ctx, default_target)?;
update_gitbutler_integration(&vb_state, ctx)?;
Ok(base)
}
pub(crate) fn set_base_branch(
project_repository: &ProjectRepository,
ctx: &CommandContext,
target_branch_ref: &RemoteRefname,
) -> Result<BaseBranch> {
let repo = project_repository.repo();
let repo = ctx.repository();
// if target exists, and it is the same as the requested branch, we should go back
if let Ok(target) = default_target(&project_repository.project().gb_dir()) {
if let Ok(target) = default_target(&ctx.project().gb_dir()) {
if target.branch.eq(target_branch_ref) {
return go_back_to_integration(project_repository, &target);
return go_back_to_integration(ctx, &target);
}
}
@ -154,7 +150,7 @@ pub(crate) fn set_base_branch(
.peel_to_commit()
.context("Failed to peel HEAD reference to commit")?;
// calculate the commit as the merge-base between HEAD in project_repository and this target commit
// calculate the commit as the merge-base between HEAD in ctx and this target commit
let target_commit_oid = repo
.merge_base(current_head_commit.id(), target_branch_head.id())
.context(format!(
@ -170,7 +166,7 @@ pub(crate) fn set_base_branch(
push_remote_name: None,
};
let vb_state = project_repository.project().virtual_branches();
let vb_state = ctx.project().virtual_branches();
vb_state.set_default_target(target.clone())?;
// TODO: make sure this is a real branch
@ -244,14 +240,14 @@ pub(crate) fn set_base_branch(
updated_timestamp_ms: now_ms,
head: current_head_commit.id(),
tree: gitbutler_diff::write::hunks_onto_commit(
project_repository,
ctx,
current_head_commit.id(),
gitbutler_diff::diff_files_into_hunks(wd_diff),
)?,
ownership,
order: 0,
selected_for_changes: None,
allow_rebasing: project_repository.project().ok_with_force_push.into(),
allow_rebasing: ctx.project().ok_with_force_push.into(),
applied: true,
in_workspace: true,
not_in_workspace_wip_change_id: None,
@ -261,38 +257,35 @@ pub(crate) fn set_base_branch(
}
}
set_exclude_decoration(project_repository)?;
set_exclude_decoration(ctx)?;
update_gitbutler_integration(&vb_state, project_repository)?;
update_gitbutler_integration(&vb_state, ctx)?;
let base = target_to_base_branch(project_repository, &target)?;
let base = target_to_base_branch(ctx, &target)?;
Ok(base)
}
pub(crate) fn set_target_push_remote(
project_repository: &ProjectRepository,
push_remote_name: &str,
) -> Result<()> {
let remote = project_repository
.repo()
pub(crate) fn set_target_push_remote(ctx: &CommandContext, push_remote_name: &str) -> Result<()> {
let remote = ctx
.repository()
.find_remote(push_remote_name)
.context(format!("failed to find remote {}", push_remote_name))?;
// if target exists, and it is the same as the requested branch, we should go back
let mut target = default_target(&project_repository.project().gb_dir())?;
let mut target = default_target(&ctx.project().gb_dir())?;
target.push_remote_name = remote
.name()
.context("failed to get remote name")?
.to_string()
.into();
let vb_state = project_repository.project().virtual_branches();
let vb_state = ctx.project().virtual_branches();
vb_state.set_default_target(target)?;
Ok(())
}
fn set_exclude_decoration(project_repository: &ProjectRepository) -> Result<()> {
let repo = project_repository.repo();
fn set_exclude_decoration(ctx: &CommandContext) -> Result<()> {
let repo = ctx.repository();
let mut config = repo.config()?;
config
.set_multivar("log.excludeDecoration", "refs/gitbutler", "refs/gitbutler")
@ -327,14 +320,14 @@ fn _print_tree(repo: &git2::Repository, tree: &git2::Tree) -> Result<()> {
// merge the target branch into our current working directory
// update the target sha
pub(crate) fn update_base_branch(
project_repository: &ProjectRepository,
ctx: &CommandContext,
perm: &mut WorktreeWritePermission,
) -> anyhow::Result<Vec<ReferenceName>> {
project_repository.assure_resolved()?;
ctx.assure_resolved()?;
// look up the target and see if there is a new oid
let target = default_target(&project_repository.project().gb_dir())?;
let repo = project_repository.repo();
let target = default_target(&ctx.project().gb_dir())?;
let repo = ctx.repository();
let target_branch = repo
.find_branch_by_refname(&target.branch.clone().into())
.context(format!("failed to find branch {}", target.branch))?;
@ -360,10 +353,10 @@ pub(crate) fn update_base_branch(
target.sha
))?;
let vb_state = project_repository.project().virtual_branches();
let vb_state = ctx.project().virtual_branches();
// try to update every branch
let updated_vbranches = get_applied_status(project_repository, None)?
let updated_vbranches = get_applied_status(ctx, None)?
.branches
.into_iter()
.map(|(branch, _)| branch)
@ -390,16 +383,13 @@ pub(crate) fn update_base_branch(
branch.upstream = None;
branch.upstream_head = None;
let non_commited_files = gitbutler_diff::trees(
project_repository.repo(),
&branch_head_tree,
&branch_tree,
)?;
let non_commited_files =
gitbutler_diff::trees(ctx.repository(), &branch_head_tree, &branch_tree)?;
if non_commited_files.is_empty() {
// if there are no commited files, then the branch is fully merged
// and we can delete it.
vb_state.mark_as_not_in_workspace(branch.id)?;
project_repository.delete_branch_reference(&branch)?;
ctx.delete_branch_reference(&branch)?;
Ok(None)
} else {
vb_state.set_branch(branch.clone())?;
@ -418,7 +408,7 @@ pub(crate) fn update_base_branch(
if branch_tree_merge_index.has_conflicts() {
// branch tree conflicts with new target, unapply branch for now. we'll handle it later, when user applies it back.
let branch_manager = project_repository.branch_manager();
let branch_manager = ctx.branch_manager();
let unapplied_real_branch =
branch_manager.convert_to_real_branch(branch.id, perm)?;
@ -428,7 +418,7 @@ pub(crate) fn update_base_branch(
}
let branch_merge_index_tree_oid =
branch_tree_merge_index.write_tree_to(project_repository.repo())?;
branch_tree_merge_index.write_tree_to(ctx.repository())?;
if branch_merge_index_tree_oid == new_target_tree.id() {
return result_integrated_detected(branch);
@ -452,7 +442,7 @@ pub(crate) fn update_base_branch(
if branch_head_merge_index.has_conflicts() {
// branch commits conflict with new target, make sure the branch is
// unapplied. conflicts witll be dealt with when applying it back.
let branch_manager = project_repository.branch_manager();
let branch_manager = ctx.branch_manager();
let unapplied_real_branch =
branch_manager.convert_to_real_branch(branch.id, perm)?;
unapplied_branch_names.push(unapplied_real_branch);
@ -462,7 +452,7 @@ pub(crate) fn update_base_branch(
// branch commits do not conflict with new target, so lets merge them
let branch_head_merge_tree_oid = branch_head_merge_index
.write_tree_to(project_repository.repo())
.write_tree_to(ctx.repository())
.context(format!(
"failed to write head merge index for {}",
branch.id
@ -477,7 +467,7 @@ pub(crate) fn update_base_branch(
.find_tree(branch_head_merge_tree_oid)
.context("failed to find tree")?;
let new_target_head = project_repository
let new_target_head = ctx
.commit(
format!(
"Merged {}/{} into {}",
@ -504,7 +494,7 @@ pub(crate) fn update_base_branch(
// branch was not pushed to upstream yet. attempt a rebase,
let rebased_head_oid = cherry_rebase(
project_repository,
ctx,
new_target_commit.id(),
new_target_commit.id(),
branch.head,
@ -558,15 +548,12 @@ pub(crate) fn update_base_branch(
})?;
// Rewriting the integration commit is necessary after changing target sha.
crate::integration::update_gitbutler_integration(&vb_state, project_repository)?;
crate::integration::update_gitbutler_integration(&vb_state, ctx)?;
Ok(unapplied_branch_names)
}
pub(crate) fn target_to_base_branch(
project_repository: &ProjectRepository,
target: &Target,
) -> Result<BaseBranch> {
let repo = project_repository.repo();
pub(crate) fn target_to_base_branch(ctx: &CommandContext, target: &Target) -> Result<BaseBranch> {
let repo = ctx.repository();
let branch = repo
.find_branch_by_refname(&target.branch.clone().into())?
.ok_or(anyhow!("failed to get branch"))?;
@ -574,7 +561,7 @@ pub(crate) fn target_to_base_branch(
let oid = commit.id();
// gather a list of commits between oid and target.sha
let upstream_commits = project_repository
let upstream_commits = ctx
.log(oid, LogUntil::Commit(target.sha))
.context("failed to get upstream commits")?
.iter()
@ -582,7 +569,7 @@ pub(crate) fn target_to_base_branch(
.collect::<Vec<_>>();
// get some recent commits
let recent_commits = project_repository
let recent_commits = ctx
.log(target.sha, LogUntil::Take(20))
.context("failed to get recent commits")?
.iter()
@ -612,7 +599,7 @@ pub(crate) fn target_to_base_branch(
behind: upstream_commits.len(),
upstream_commits,
recent_commits,
last_fetched_ms: project_repository
last_fetched_ms: ctx
.project()
.project_data_last_fetch
.as_ref()

View File

@ -9,7 +9,7 @@ use bstr::{BString, ByteSlice};
use gitbutler_branch::{
Branch as GitButlerBranch, BranchId, ReferenceExt, Target, VirtualBranchesHandle,
};
use gitbutler_command_context::ProjectRepository;
use gitbutler_command_context::CommandContext;
use gitbutler_reference::normalize_branch_name;
use gitbutler_repo::RepoActionsExt;
use itertools::Itertools;
@ -19,7 +19,7 @@ use crate::VirtualBranchesExt;
/// Returns a list of branches associated with this project.
pub fn list_branches(
ctx: &ProjectRepository,
ctx: &CommandContext,
filter: Option<BranchListingFilter>,
) -> Result<Vec<BranchListing>> {
let vb_handle = ctx.project().virtual_branches();
@ -33,7 +33,7 @@ pub fn list_branches(
_ => None,
});
let mut git_branches: Vec<GroupBranch> = vec![];
for result in ctx.repo().branches(branch_filter)? {
for result in ctx.repository().branches(branch_filter)? {
match result {
Ok((branch, branch_type)) => match branch_type {
git2::BranchType::Local => {
@ -98,10 +98,10 @@ fn matches_all(branch: &BranchListing, filter: &Option<BranchListingFilter>) ->
fn combine_branches(
mut group_branches: Vec<GroupBranch>,
virtual_branches: impl Iterator<Item = GitButlerBranch>,
ctx: &ProjectRepository,
ctx: &CommandContext,
vb_handle: &VirtualBranchesHandle,
) -> Result<Vec<BranchListing>> {
let repo = ctx.repo();
let repo = ctx.repository();
for branch in virtual_branches {
group_branches.push(GroupBranch::Virtual(branch));
}
@ -393,10 +393,10 @@ pub struct VirtualBranchReference {
/// Takes a list of branch names (the given name, as returned by `BranchListing`) and returns
/// a list of enriched branch data in the form of `BranchData`.
pub fn get_branch_listing_details(
ctx: &ProjectRepository,
ctx: &CommandContext,
branch_names: Vec<String>,
) -> Result<Vec<BranchListingDetails>> {
let repo = ctx.repo();
let repo = ctx.repository();
// Can we do this in a more efficient way?
let branches = list_branches(ctx, None)?
.into_iter()

View File

@ -25,12 +25,12 @@ impl BranchManager<'_> {
create: &BranchCreateRequest,
perm: &mut WorktreeWritePermission,
) -> Result<Branch> {
let vb_state = self.project_repository.project().virtual_branches();
let vb_state = self.ctx.project().virtual_branches();
let default_target = vb_state.get_default_target()?;
let commit = self
.project_repository
.repo()
.ctx
.repository()
.find_commit(default_target.sha)
.context("failed to find default target commit")?;
@ -54,7 +54,7 @@ impl BranchManager<'_> {
);
_ = self
.project_repository
.ctx
.project()
.snapshot_branch_creation(name.clone(), perm);
@ -107,7 +107,7 @@ impl BranchManager<'_> {
ownership: BranchOwnershipClaims::default(),
order,
selected_for_changes,
allow_rebasing: self.project_repository.project().ok_with_force_push.into(),
allow_rebasing: self.ctx.project().ok_with_force_push.into(),
applied: true,
in_workspace: true,
not_in_workspace_wip_change_id: None,
@ -119,7 +119,7 @@ impl BranchManager<'_> {
}
vb_state.set_branch(branch.clone())?;
self.project_repository.add_branch_reference(&branch)?;
self.ctx.add_branch_reference(&branch)?;
Ok(branch)
}
@ -151,11 +151,11 @@ impl BranchManager<'_> {
.to_string();
let _ = self
.project_repository
.ctx
.project()
.snapshot_branch_creation(branch_name.clone(), perm);
let vb_state = self.project_repository.project().virtual_branches();
let vb_state = self.ctx.project().virtual_branches();
let default_target = vb_state.get_default_target()?;
@ -165,7 +165,7 @@ impl BranchManager<'_> {
}
}
let repo = self.project_repository.repo();
let repo = self.ctx.repository();
let head_reference = repo
.find_reference(&target.to_string())
.map_err(|err| match err {
@ -200,11 +200,8 @@ impl BranchManager<'_> {
let merge_base_tree = repo.find_commit(merge_base_oid)?.tree()?;
// do a diff between the head of this branch and the target base
let diff = gitbutler_diff::trees(
self.project_repository.repo(),
&merge_base_tree,
&head_commit_tree,
)?;
let diff =
gitbutler_diff::trees(self.ctx.repository(), &merge_base_tree, &head_commit_tree)?;
// assign ownership to the branch
let ownership = diff.iter().fold(
@ -235,7 +232,7 @@ impl BranchManager<'_> {
branch.ownership = ownership;
branch.order = order;
branch.selected_for_changes = selected_for_changes;
branch.allow_rebasing = self.project_repository.project().ok_with_force_push.into();
branch.allow_rebasing = self.ctx.project().ok_with_force_push.into();
branch.applied = true;
branch.in_workspace = true;
@ -255,7 +252,7 @@ impl BranchManager<'_> {
ownership,
order,
selected_for_changes,
allow_rebasing: self.project_repository.project().ok_with_force_push.into(),
allow_rebasing: self.ctx.project().ok_with_force_push.into(),
applied: true,
in_workspace: true,
not_in_workspace_wip_change_id: None,
@ -263,7 +260,7 @@ impl BranchManager<'_> {
};
vb_state.set_branch(branch.clone())?;
self.project_repository.add_branch_reference(&branch)?;
self.ctx.add_branch_reference(&branch)?;
match self.apply_branch(branch.id, perm) {
Ok(_) => Ok(branch.id),
@ -287,11 +284,11 @@ impl BranchManager<'_> {
branch_id: BranchId,
perm: &mut WorktreeWritePermission,
) -> Result<String> {
self.project_repository.assure_resolved()?;
self.project_repository.assure_unconflicted()?;
let repo = self.project_repository.repo();
self.ctx.assure_resolved()?;
self.ctx.assure_unconflicted()?;
let repo = self.ctx.repository();
let vb_state = self.project_repository.project().virtual_branches();
let vb_state = self.ctx.project().virtual_branches();
let default_target = vb_state.get_default_target()?;
let mut branch = vb_state.get_branch_in_workspace(branch_id)?;
@ -358,11 +355,7 @@ impl BranchManager<'_> {
merge_conflicts.push(path);
}
}
conflicts::mark(
self.project_repository,
&merge_conflicts,
Some(default_target.sha),
)?;
conflicts::mark(self.ctx, &merge_conflicts, Some(default_target.sha))?;
return Ok(branch.name);
}
@ -372,7 +365,7 @@ impl BranchManager<'_> {
.context("failed to find head commit")?;
let merged_branch_tree_oid = merge_index
.write_tree_to(self.project_repository.repo())
.write_tree_to(self.ctx.repository())
.context("failed to write tree")?;
let merged_branch_tree = repo
@ -384,7 +377,7 @@ impl BranchManager<'_> {
// branch was pushed to upstream, and user doesn't like force pushing.
// create a merge commit to avoid the need of force pushing then.
let new_branch_head = self.project_repository.commit(
let new_branch_head = self.ctx.commit(
format!(
"Merged {}/{} into {}",
default_target.branch.remote(),
@ -401,7 +394,7 @@ impl BranchManager<'_> {
branch.head = new_branch_head;
} else {
let rebase = cherry_rebase(
self.project_repository,
self.ctx,
target_commit.id(),
target_commit.id(),
branch.head,
@ -432,7 +425,7 @@ impl BranchManager<'_> {
// commit the merge tree oid
let new_branch_head = self
.project_repository
.ctx
.commit(
format!(
"Merged {}/{} into {}",
@ -459,7 +452,7 @@ impl BranchManager<'_> {
vb_state.set_branch(branch.clone())?;
}
let wd_tree = self.project_repository.repo().get_wd_tree()?;
let wd_tree = self.ctx.repository().get_wd_tree()?;
let branch_tree = repo
.find_tree(branch.tree)
@ -482,11 +475,7 @@ impl BranchManager<'_> {
merge_conflicts.push(path);
}
}
conflicts::mark(
self.project_repository,
&merge_conflicts,
Some(default_target.sha),
)?;
conflicts::mark(self.ctx, &merge_conflicts, Some(default_target.sha))?;
}
// apply the branch
@ -508,7 +497,7 @@ impl BranchManager<'_> {
if let Some(headers) = potential_wip_commit.gitbutler_headers() {
if headers.change_id == wip_commit_to_unapply {
undo_commit(self.project_repository, branch.id, branch.head)?;
undo_commit(self.ctx, branch.id, branch.head)?;
}
}
@ -517,7 +506,7 @@ impl BranchManager<'_> {
}
}
update_gitbutler_integration(&vb_state, self.project_repository)?;
update_gitbutler_integration(&vb_state, self.ctx)?;
Ok(branch.name)
}

View File

@ -24,7 +24,7 @@ impl BranchManager<'_> {
branch_id: BranchId,
perm: &mut WorktreeWritePermission,
) -> Result<ReferenceName> {
let vb_state = self.project_repository.project().virtual_branches();
let vb_state = self.ctx.project().virtual_branches();
let mut target_branch = vb_state.get_branch(branch_id)?;
@ -34,8 +34,8 @@ impl BranchManager<'_> {
self.delete_branch(branch_id, perm)?;
// If we were conflicting, it means that it was the only branch applied. Since we've now unapplied it we can clear all conflicts
if conflicts::is_conflicting(self.project_repository, None)? {
conflicts::clear(self.project_repository)?;
if conflicts::is_conflicting(self.ctx, None)? {
conflicts::clear(self.ctx)?;
}
vb_state.update_ordering()?;
@ -43,7 +43,7 @@ impl BranchManager<'_> {
// Ensure we still have a default target
ensure_selected_for_changes(&vb_state).context("failed to ensure selected for changes")?;
crate::integration::update_gitbutler_integration(&vb_state, self.project_repository)?;
crate::integration::update_gitbutler_integration(&vb_state, self.ctx)?;
real_branch.reference_name()
}
@ -53,7 +53,7 @@ impl BranchManager<'_> {
branch_id: BranchId,
perm: &mut WorktreeWritePermission,
) -> Result<()> {
let vb_state = self.project_repository.project().virtual_branches();
let vb_state = self.ctx.project().virtual_branches();
let Some(branch) = vb_state.try_branch(branch_id)? else {
return Ok(());
};
@ -64,16 +64,16 @@ impl BranchManager<'_> {
}
_ = self
.project_repository
.ctx
.project()
.snapshot_branch_deletion(branch.name.clone(), perm);
let repo = self.project_repository.repo();
let repo = self.ctx.repository();
let target_commit = repo.target_commit()?;
let base_tree = target_commit.tree().context("failed to get target tree")?;
let applied_statuses = get_applied_status(self.project_repository, None)
let applied_statuses = get_applied_status(self.ctx, None)
.context("failed to get status by branch")?
.branches;
@ -97,11 +97,8 @@ impl BranchManager<'_> {
.into_iter()
.map(|file| (file.path, file.hunks))
.collect::<Vec<(PathBuf, Vec<VirtualBranchHunk>)>>();
let tree_oid = gitbutler_diff::write::hunks_onto_oid(
self.project_repository,
&branch.head,
files,
)?;
let tree_oid =
gitbutler_diff::write::hunks_onto_oid(self.ctx, &branch.head, files)?;
let branch_tree = repo.find_tree(tree_oid)?;
let mut result =
repo.merge_trees(&base_tree, &final_tree, &branch_tree, None)?;
@ -118,7 +115,7 @@ impl BranchManager<'_> {
.checkout()
.context("failed to checkout tree")?;
self.project_repository.delete_branch_reference(&branch)?;
self.ctx.delete_branch_reference(&branch)?;
ensure_selected_for_changes(&vb_state).context("failed to ensure selected for changes")?;
@ -128,12 +125,12 @@ impl BranchManager<'_> {
impl BranchManager<'_> {
fn build_real_branch(&self, vbranch: &mut Branch) -> Result<git2::Branch<'_>> {
let repo = self.project_repository.repo();
let repo = self.ctx.repository();
let target_commit = repo.find_commit(vbranch.head)?;
let branch_name = vbranch.name.clone();
let branch_name = normalize_branch_name(&branch_name);
let vb_state = self.project_repository.project().virtual_branches();
let vb_state = self.ctx.project().virtual_branches();
let branch = repo.branch(&branch_name, &target_commit, true)?;
vbranch.source_refname = Some(Refname::try_from(&branch)?);
vb_state.set_branch(vbranch.clone())?;
@ -148,7 +145,7 @@ impl BranchManager<'_> {
vbranch: &mut Branch,
branch: &git2::Branch<'_>,
) -> Result<Option<git2::Oid>> {
let repo = self.project_repository.repo();
let repo = self.ctx.repository();
// Build wip tree as either any uncommitted changes or an empty tree
let vbranch_wip_tree = repo.find_tree(vbranch.tree)?;
@ -181,7 +178,7 @@ impl BranchManager<'_> {
Some(commit_headers.clone()),
)?;
let vb_state = self.project_repository.project().virtual_branches();
let vb_state = self.ctx.project().virtual_branches();
// vbranch.head = commit_oid;
vbranch.not_in_workspace_wip_change_id = Some(commit_headers.change_id);
vb_state.set_branch(vbranch.clone())?;

View File

@ -1,20 +1,18 @@
use gitbutler_command_context::ProjectRepository;
use gitbutler_command_context::CommandContext;
mod branch_creation;
mod branch_removal;
pub struct BranchManager<'l> {
project_repository: &'l ProjectRepository,
ctx: &'l CommandContext,
}
pub trait BranchManagerExt {
fn branch_manager(&self) -> BranchManager;
}
impl BranchManagerExt for ProjectRepository {
impl BranchManagerExt for CommandContext {
fn branch_manager(&self) -> BranchManager {
BranchManager {
project_repository: self,
}
BranchManager { ctx: self }
}
}

View File

@ -1,7 +1,7 @@
use anyhow::{Context, Result};
use bstr::BString;
use gitbutler_branch::{Branch, BranchId};
use gitbutler_command_context::ProjectRepository;
use gitbutler_command_context::CommandContext;
use gitbutler_commit::commit_ext::CommitExt;
use serde::Serialize;
@ -38,7 +38,7 @@ pub struct VirtualBranchCommit {
}
pub(crate) fn commit_to_vbranch_commit(
repository: &ProjectRepository,
repository: &CommandContext,
branch: &Branch,
commit: &git2::Commit,
is_integrated: bool,

View File

@ -12,11 +12,11 @@ use std::{
use anyhow::{anyhow, bail, Context, Result};
use bstr::ByteSlice;
use gitbutler_command_context::ProjectRepository;
use gitbutler_command_context::CommandContext;
use gitbutler_error::error::Marker;
pub(crate) fn mark<P: AsRef<Path>, A: AsRef<[P]>>(
ctx: &ProjectRepository,
ctx: &CommandContext,
paths: A,
parent: Option<git2::Oid>,
) -> Result<()> {
@ -45,15 +45,15 @@ pub(crate) fn mark<P: AsRef<Path>, A: AsRef<[P]>>(
Ok(())
}
fn conflicts_path(ctx: &ProjectRepository) -> PathBuf {
ctx.repo().path().join("conflicts")
fn conflicts_path(ctx: &CommandContext) -> PathBuf {
ctx.repository().path().join("conflicts")
}
fn merge_parent_path(ctx: &ProjectRepository) -> PathBuf {
ctx.repo().path().join("base_merge_parent")
fn merge_parent_path(ctx: &CommandContext) -> PathBuf {
ctx.repository().path().join("base_merge_parent")
}
pub(crate) fn merge_parent(ctx: &ProjectRepository) -> Result<Option<git2::Oid>> {
pub(crate) fn merge_parent(ctx: &CommandContext) -> Result<Option<git2::Oid>> {
use std::io::BufRead;
let merge_path = merge_parent_path(ctx);
@ -73,7 +73,7 @@ pub(crate) fn merge_parent(ctx: &ProjectRepository) -> Result<Option<git2::Oid>>
}
}
pub fn resolve<P: AsRef<Path>>(ctx: &ProjectRepository, path_to_resolve: P) -> Result<()> {
pub fn resolve<P: AsRef<Path>>(ctx: &CommandContext, path_to_resolve: P) -> Result<()> {
let path_to_resolve = path_to_resolve.as_ref();
let path_to_resolve = path_to_resolve.as_os_str().as_encoded_bytes();
let conflicts_path = conflicts_path(ctx);
@ -93,7 +93,7 @@ pub fn resolve<P: AsRef<Path>>(ctx: &ProjectRepository, path_to_resolve: P) -> R
Ok(())
}
pub(crate) fn conflicting_files(ctx: &ProjectRepository) -> Result<Vec<PathBuf>> {
pub(crate) fn conflicting_files(ctx: &CommandContext) -> Result<Vec<PathBuf>> {
let conflicts_path = conflicts_path(ctx);
if !conflicts_path.exists() {
return Ok(vec![]);
@ -108,7 +108,7 @@ pub(crate) fn conflicting_files(ctx: &ProjectRepository) -> Result<Vec<PathBuf>>
/// Check if `path` is conflicting in `repository`, or if `None`, check if there is any conflict.
// TODO(ST): Should this not rather check the conflicting state in the index?
pub(crate) fn is_conflicting(repository: &ProjectRepository, path: Option<&Path>) -> Result<bool> {
pub(crate) fn is_conflicting(repository: &CommandContext, path: Option<&Path>) -> Result<bool> {
let conflicts_path = conflicts_path(repository);
if !conflicts_path.exists() {
return Ok(false);
@ -128,11 +128,11 @@ pub(crate) fn is_conflicting(repository: &ProjectRepository, path: Option<&Path>
// is this project still in a resolving conflict state?
// - could be that there are no more conflicts, but the state is not committed
pub(crate) fn is_resolving(ctx: &ProjectRepository) -> bool {
pub(crate) fn is_resolving(ctx: &CommandContext) -> bool {
merge_parent_path(ctx).exists()
}
pub(crate) fn clear(ctx: &ProjectRepository) -> Result<()> {
pub(crate) fn clear(ctx: &CommandContext) -> Result<()> {
remove_file_ignore_missing(merge_parent_path(ctx))?;
remove_file_ignore_missing(conflicts_path(ctx))?;
Ok(())
@ -154,7 +154,7 @@ pub(crate) trait RepoConflictsExt {
fn is_resolving(&self) -> bool;
}
impl RepoConflictsExt for ProjectRepository {
impl RepoConflictsExt for CommandContext {
fn is_resolving(&self) -> bool {
is_resolving(self)
}

View File

@ -4,7 +4,7 @@ use std::{
};
use anyhow::{anyhow, Context, Result};
use gitbutler_command_context::ProjectRepository;
use gitbutler_command_context::CommandContext;
use gitbutler_diff::FileDiff;
use serde::Serialize;
@ -86,7 +86,7 @@ impl Get<VirtualBranchFile> for Vec<VirtualBranchFile> {
}
pub(crate) fn list_virtual_commit_files(
project_repository: &ProjectRepository,
ctx: &CommandContext,
commit: &git2::Commit,
) -> Result<Vec<VirtualBranchFile>> {
if commit.parent_count() == 0 {
@ -95,12 +95,9 @@ pub(crate) fn list_virtual_commit_files(
let parent = commit.parent(0).context("failed to get parent commit")?;
let commit_tree = commit.tree().context("failed to get commit tree")?;
let parent_tree = parent.tree().context("failed to get parent tree")?;
let diff = gitbutler_diff::trees(project_repository.repo(), &parent_tree, &commit_tree)?;
let hunks_by_filepath = virtual_hunks_by_file_diffs(&project_repository.project().path, diff);
Ok(virtual_hunks_into_virtual_files(
project_repository,
hunks_by_filepath,
))
let diff = gitbutler_diff::trees(ctx.repository(), &parent_tree, &commit_tree)?;
let hunks_by_filepath = virtual_hunks_by_file_diffs(&ctx.project().path, diff);
Ok(virtual_hunks_into_virtual_files(ctx, hunks_by_filepath))
}
fn virtual_hunks_by_file_diffs<'a>(
@ -117,15 +114,14 @@ fn virtual_hunks_by_file_diffs<'a>(
/// NOTE: There is no use returning an iterator here as this acts like the final product.
pub(crate) fn virtual_hunks_into_virtual_files(
project_repository: &ProjectRepository,
ctx: &CommandContext,
hunks: impl IntoIterator<Item = (PathBuf, Vec<VirtualBranchHunk>)>,
) -> Vec<VirtualBranchFile> {
hunks
.into_iter()
.map(|(path, hunks)| {
let id = path.display().to_string();
let conflicted =
conflicts::is_conflicting(project_repository, Some(&path)).unwrap_or(false);
let conflicted = conflicts::is_conflicting(ctx, Some(&path)).unwrap_or(false);
let binary = hunks.iter().any(|h| h.binary);
let modified_at = hunks.iter().map(|h| h.modified_at).max().unwrap_or(0);
debug_assert!(hunks.iter().all(|hunk| hunk.file_path == path));

View File

@ -7,7 +7,7 @@ use gitbutler_branch::{
GITBUTLER_INTEGRATION_COMMIT_AUTHOR_EMAIL, GITBUTLER_INTEGRATION_COMMIT_AUTHOR_NAME,
GITBUTLER_INTEGRATION_REFERENCE,
};
use gitbutler_command_context::ProjectRepository;
use gitbutler_command_context::CommandContext;
use gitbutler_commit::commit_ext::CommitExt;
use gitbutler_error::error::Marker;
use gitbutler_project::access::WorktreeWritePermission;
@ -28,12 +28,12 @@ pub(crate) fn get_integration_commiter<'a>() -> Result<git2::Signature<'a>> {
//
// This is the base against which we diff the working directory to understand
// what files have been modified.
pub(crate) fn get_workspace_head(project_repo: &ProjectRepository) -> Result<git2::Oid> {
let vb_state = project_repo.project().virtual_branches();
pub(crate) fn get_workspace_head(ctx: &CommandContext) -> Result<git2::Oid> {
let vb_state = ctx.project().virtual_branches();
let target = vb_state
.get_default_target()
.context("failed to get target")?;
let repo: &git2::Repository = project_repo.repo();
let repo: &git2::Repository = ctx.repository();
let mut virtual_branches: Vec<Branch> = vb_state.list_branches_in_workspace()?;
@ -51,9 +51,8 @@ pub(crate) fn get_workspace_head(project_repo: &ProjectRepository) -> Result<git
return Ok(target_commit.id());
}
if conflicts::is_conflicting(project_repo, None)? {
let merge_parent =
conflicts::merge_parent(project_repo)?.ok_or(anyhow!("No merge parent"))?;
if conflicts::is_conflicting(ctx, None)? {
let merge_parent = conflicts::merge_parent(ctx)?.ok_or(anyhow!("No merge parent"))?;
let first_branch = virtual_branches.first().ok_or(anyhow!("No branches"))?;
let merge_base = repo.merge_base(first_branch.head, merge_parent)?;
@ -135,13 +134,13 @@ fn write_integration_file(head: &git2::Reference, path: PathBuf) -> Result<()> {
}
pub fn update_gitbutler_integration(
vb_state: &VirtualBranchesHandle,
project_repository: &ProjectRepository,
ctx: &CommandContext,
) -> Result<git2::Oid> {
let target = vb_state
.get_default_target()
.context("failed to get target")?;
let repo: &git2::Repository = project_repository.repo();
let repo: &git2::Repository = ctx.repository();
// get commit object from target.sha
let target_commit = repo.find_commit(target.sha)?;
@ -162,14 +161,14 @@ pub fn update_gitbutler_integration(
}
}
let vb_state = project_repository.project().virtual_branches();
let vb_state = ctx.project().virtual_branches();
// get all virtual branches, we need to try to update them all
let virtual_branches: Vec<Branch> = vb_state
.list_branches_in_workspace()
.context("failed to list virtual branches")?;
let integration_commit = repo.find_commit(get_workspace_head(project_repository)?)?;
let integration_commit = repo.find_commit(get_workspace_head(ctx)?)?;
let integration_tree = integration_commit.tree()?;
// message that says how to get back to where they were
@ -279,7 +278,7 @@ pub fn update_gitbutler_integration(
Ok(final_commit)
}
pub fn verify_branch(ctx: &ProjectRepository, perm: &mut WorktreeWritePermission) -> Result<()> {
pub fn verify_branch(ctx: &CommandContext, perm: &mut WorktreeWritePermission) -> Result<()> {
verify_current_branch_name(ctx)
.and_then(verify_head_is_set)
.and_then(|()| verify_head_is_clean(ctx, perm))
@ -287,8 +286,13 @@ pub fn verify_branch(ctx: &ProjectRepository, perm: &mut WorktreeWritePermission
Ok(())
}
fn verify_head_is_set(ctx: &ProjectRepository) -> Result<()> {
match ctx.repo().head().context("failed to get head")?.name() {
fn verify_head_is_set(ctx: &CommandContext) -> Result<()> {
match ctx
.repository()
.head()
.context("failed to get head")?
.name()
{
Some(refname) if *refname == GITBUTLER_INTEGRATION_REFERENCE.to_string() => Ok(()),
Some(head_name) => Err(invalid_head_err(head_name)),
None => Err(anyhow!(
@ -299,8 +303,8 @@ fn verify_head_is_set(ctx: &ProjectRepository) -> Result<()> {
}
// Returns an error if repo head is not pointing to the integration branch.
fn verify_current_branch_name(ctx: &ProjectRepository) -> Result<&ProjectRepository> {
match ctx.repo().head()?.name() {
fn verify_current_branch_name(ctx: &CommandContext) -> Result<&CommandContext> {
match ctx.repository().head()?.name() {
Some(head) => {
let head_name = head.to_string();
if head_name != GITBUTLER_INTEGRATION_REFERENCE.to_string() {
@ -313,9 +317,9 @@ fn verify_current_branch_name(ctx: &ProjectRepository) -> Result<&ProjectReposit
}
// TODO(ST): Probably there should not be an implicit vbranch creation here.
fn verify_head_is_clean(ctx: &ProjectRepository, perm: &mut WorktreeWritePermission) -> Result<()> {
fn verify_head_is_clean(ctx: &CommandContext, perm: &mut WorktreeWritePermission) -> Result<()> {
let head_commit = ctx
.repo()
.repository()
.head()
.context("failed to get head")?
.peel_to_commit()
@ -342,7 +346,7 @@ fn verify_head_is_clean(ctx: &ProjectRepository, perm: &mut WorktreeWritePermiss
return Ok(());
}
ctx.repo()
ctx.repository()
.reset(
integration_commit.as_ref().unwrap().as_object(),
git2::ResetType::Soft,
@ -369,12 +373,12 @@ fn verify_head_is_clean(ctx: &ProjectRepository, perm: &mut WorktreeWritePermiss
let mut head = new_branch.head;
for commit in extra_commits {
let new_branch_head = ctx
.repo()
.repository()
.find_commit(head)
.context("failed to find new branch head")?;
let rebased_commit_oid = ctx
.repo()
.repository()
.commit_with_signature(
None,
&commit.author(),
@ -389,10 +393,13 @@ fn verify_head_is_clean(ctx: &ProjectRepository, perm: &mut WorktreeWritePermiss
commit.id()
))?;
let rebased_commit = ctx.repo().find_commit(rebased_commit_oid).context(format!(
"failed to find rebased commit {}",
rebased_commit_oid
))?;
let rebased_commit = ctx
.repository()
.find_commit(rebased_commit_oid)
.context(format!(
"failed to find rebased commit {}",
rebased_commit_oid
))?;
new_branch.head = rebased_commit.id();
new_branch.tree = rebased_commit.tree_id();

View File

@ -3,7 +3,7 @@ use std::path::Path;
use anyhow::{Context, Result};
use bstr::BString;
use gitbutler_branch::{ReferenceExt, Target, VirtualBranchesHandle};
use gitbutler_command_context::ProjectRepository;
use gitbutler_command_context::CommandContext;
use gitbutler_commit::commit_ext::CommitExt;
use gitbutler_reference::{Refname, RemoteRefname};
use gitbutler_repo::{LogUntil, RepoActionsExt, RepositoryExt};
@ -61,17 +61,17 @@ pub struct RemoteCommit {
// for legacy purposes, this is still named "remote" branches, but it's actually
// a list of all the normal (non-gitbutler) git branches.
pub fn list_remote_branches(project_repository: &ProjectRepository) -> Result<Vec<RemoteBranch>> {
let default_target = default_target(&project_repository.project().gb_dir())?;
pub fn list_remote_branches(ctx: &CommandContext) -> Result<Vec<RemoteBranch>> {
let default_target = default_target(&ctx.project().gb_dir())?;
let mut remote_branches = vec![];
for (branch, _) in project_repository
.repo()
for (branch, _) in ctx
.repository()
.branches(None)
.context("failed to list remote branches")?
.flatten()
{
let branch = branch_to_remote_branch(project_repository, &branch);
let branch = branch_to_remote_branch(ctx, &branch);
if let Some(branch) = branch {
let branch_is_trunk = branch.name.branch() == Some(default_target.branch.branch())
@ -88,14 +88,11 @@ pub fn list_remote_branches(project_repository: &ProjectRepository) -> Result<Ve
Ok(remote_branches)
}
pub(crate) fn get_branch_data(
ctx: &ProjectRepository,
refname: &Refname,
) -> Result<RemoteBranchData> {
pub(crate) fn get_branch_data(ctx: &CommandContext, refname: &Refname) -> Result<RemoteBranchData> {
let default_target = default_target(&ctx.project().gb_dir())?;
let branch = ctx
.repo()
.repository()
.find_branch_by_refname(refname)?
.ok_or(anyhow::anyhow!("failed to find branch {}", refname))?;
@ -104,7 +101,7 @@ pub(crate) fn get_branch_data(
}
pub(crate) fn branch_to_remote_branch(
ctx: &ProjectRepository,
ctx: &CommandContext,
branch: &git2::Branch,
) -> Option<RemoteBranch> {
let commit = match branch.get().peel_to_commit() {
@ -122,7 +119,10 @@ pub(crate) fn branch_to_remote_branch(
.context("could not get branch name")
.ok()?;
let given_name = branch.get().given_name(&ctx.repo().remotes().ok()?).ok()?;
let given_name = branch
.get()
.given_name(&ctx.repository().remotes().ok()?)
.ok()?;
branch.get().target().map(|sha| RemoteBranch {
sha,
@ -145,7 +145,7 @@ pub(crate) fn branch_to_remote_branch(
}
pub(crate) fn branch_to_remote_branch_data(
project_repository: &ProjectRepository,
ctx: &CommandContext,
branch: &git2::Branch,
base: git2::Oid,
) -> Result<Option<RemoteBranchData>> {
@ -153,13 +153,13 @@ pub(crate) fn branch_to_remote_branch_data(
.get()
.target()
.map(|sha| {
let ahead = project_repository
let ahead = ctx
.log(sha, LogUntil::Commit(base))
.context("failed to get ahead commits")?;
let name = Refname::try_from(branch).context("could not get branch name")?;
let count_behind = project_repository
let count_behind = ctx
.distance(base, sha)
.context("failed to get behind count")?;

View File

@ -4,7 +4,7 @@ use anyhow::{bail, Context, Result};
use gitbutler_branch::{
Branch, BranchCreateRequest, BranchId, BranchOwnershipClaims, OwnershipClaim,
};
use gitbutler_command_context::ProjectRepository;
use gitbutler_command_context::CommandContext;
use gitbutler_diff::{diff_files_into_hunks, GitHunk, Hunk, HunkHash};
use gitbutler_project::access::WorktreeWritePermission;
use gitbutler_repo::RepositoryExt;
@ -29,17 +29,16 @@ pub struct VirtualBranchesStatus {
/// of skipped files.
// TODO(kv): make this side effect free
pub fn get_applied_status(
project_repository: &ProjectRepository,
ctx: &CommandContext,
perm: Option<&mut WorktreeWritePermission>,
) -> Result<VirtualBranchesStatus> {
let integration_commit = get_workspace_head(project_repository)?;
let mut virtual_branches = project_repository
let integration_commit = get_workspace_head(ctx)?;
let mut virtual_branches = ctx
.project()
.virtual_branches()
.list_branches_in_workspace()?;
let base_file_diffs =
gitbutler_diff::workdir(project_repository.repo(), &integration_commit.to_owned())
.context("failed to diff workdir")?;
let base_file_diffs = gitbutler_diff::workdir(ctx.repository(), &integration_commit.to_owned())
.context("failed to diff workdir")?;
let mut skipped_files: Vec<gitbutler_diff::FileDiff> = Vec::new();
for file_diff in base_file_diffs.values() {
@ -52,7 +51,7 @@ pub fn get_applied_status(
// sort by order, so that the default branch is first (left in the ui)
virtual_branches.sort_by(|a, b| a.order.cmp(&b.order));
let branch_manager = project_repository.branch_manager();
let branch_manager = ctx.branch_manager();
if virtual_branches.is_empty() && !base_diffs.is_empty() {
if let Some(perm) = perm {
@ -70,7 +69,7 @@ pub fn get_applied_status(
.map(|branch| (branch.id, HashMap::new()))
.collect();
let locks = compute_locks(project_repository.repo(), &base_diffs, &virtual_branches)?;
let locks = compute_locks(ctx.repository(), &base_diffs, &virtual_branches)?;
for branch in &mut virtual_branches {
let old_claims = branch.ownership.claims.clone();
@ -187,11 +186,10 @@ pub fn get_applied_status(
.collect::<Vec<_>>();
// write updated state if not resolving
if !project_repository.is_resolving() {
let vb_state = project_repository.project().virtual_branches();
if !ctx.is_resolving() {
let vb_state = ctx.project().virtual_branches();
for (vbranch, files) in &mut hunks_by_branch {
vbranch.tree =
gitbutler_diff::write::hunks_onto_oid(project_repository, &vbranch.head, files)?;
vbranch.tree = gitbutler_diff::write::hunks_onto_oid(ctx, &vbranch.head, files)?;
vb_state
.set_branch(vbranch.clone())
.context(format!("failed to write virtual branch {}", vbranch.name))?;
@ -200,11 +198,7 @@ pub fn get_applied_status(
let hunks_by_branch: Vec<(Branch, HashMap<PathBuf, Vec<VirtualBranchHunk>>)> = hunks_by_branch
.iter()
.map(|(branch, hunks)| {
let hunks = file_hunks_from_diffs(
&project_repository.project().path,
hunks.clone(),
Some(&locks),
);
let hunks = file_hunks_from_diffs(&ctx.project().path, hunks.clone(), Some(&locks));
(branch.clone(), hunks)
})
.collect();
@ -212,7 +206,7 @@ pub fn get_applied_status(
let files_by_branch: Vec<(Branch, Vec<VirtualBranchFile>)> = hunks_by_branch
.iter()
.map(|(branch, hunks)| {
let files = virtual_hunks_into_virtual_files(project_repository, hunks.clone());
let files = virtual_hunks_into_virtual_files(ctx, hunks.clone());
(branch.clone(), files)
})
.collect();

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
use anyhow::Result;
use gitbutler_branch_actions::{list_branches, Author};
use gitbutler_command_context::ProjectRepository;
use gitbutler_command_context::CommandContext;
#[test]
fn on_main_single_branch_no_vbranch() -> Result<()> {
@ -128,6 +128,6 @@ fn default_author() -> Author {
}
}
fn project_ctx(name: &str) -> anyhow::Result<ProjectRepository> {
fn project_ctx(name: &str) -> anyhow::Result<CommandContext> {
gitbutler_testsupport::read_only::fixture("for-listing.sh", name)
}

View File

@ -1,2 +1,2 @@
mod repository;
pub use repository::ProjectRepository;
pub use repository::CommandContext;

View File

@ -1,12 +1,12 @@
use anyhow::Result;
use gitbutler_project::Project;
pub struct ProjectRepository {
pub struct CommandContext {
git_repository: git2::Repository,
project: Project,
}
impl ProjectRepository {
impl CommandContext {
pub fn open(project: &Project) -> Result<Self> {
let repo = git2::Repository::open(&project.path)?;
@ -67,7 +67,7 @@ impl ProjectRepository {
&self.project
}
pub fn repo(&self) -> &git2::Repository {
pub fn repository(&self) -> &git2::Repository {
&self.git_repository
}
}

View File

@ -5,7 +5,7 @@ use std::{borrow::Borrow, path::PathBuf};
use anyhow::{anyhow, Context, Result};
use bstr::{BString, ByteSlice, ByteVec};
use diffy::{apply_bytes as diffy_apply, Line, Patch};
use gitbutler_command_context::ProjectRepository;
use gitbutler_command_context::CommandContext;
use hex::ToHex;
use crate::GitHunk;
@ -14,18 +14,18 @@ use crate::GitHunk;
// constructs a tree from those changes on top of the target
// and writes it as a new tree for storage
pub fn hunks_onto_oid<T>(
project_repository: &ProjectRepository,
ctx: &CommandContext,
target: &git2::Oid,
files: impl IntoIterator<Item = (impl Borrow<PathBuf>, impl Borrow<Vec<T>>)>,
) -> Result<git2::Oid>
where
T: Into<GitHunk> + Clone,
{
hunks_onto_commit(project_repository, *target, files)
hunks_onto_commit(ctx, *target, files)
}
pub fn hunks_onto_commit<T>(
project_repository: &ProjectRepository,
ctx: &CommandContext,
commit_oid: git2::Oid,
files: impl IntoIterator<Item = (impl Borrow<PathBuf>, impl Borrow<Vec<T>>)>,
) -> Result<git2::Oid>
@ -33,29 +33,29 @@ where
T: Into<GitHunk> + Clone,
{
// read the base sha into an index
let git_repository: &git2::Repository = project_repository.repo();
let git_repository: &git2::Repository = ctx.repository();
let head_commit = git_repository.find_commit(commit_oid)?;
let base_tree = head_commit.tree()?;
hunks_onto_tree(project_repository, &base_tree, files)
hunks_onto_tree(ctx, &base_tree, files)
}
pub fn hunks_onto_tree<T>(
project_repository: &ProjectRepository,
ctx: &CommandContext,
base_tree: &git2::Tree,
files: impl IntoIterator<Item = (impl Borrow<PathBuf>, impl Borrow<Vec<T>>)>,
) -> Result<git2::Oid>
where
T: Into<GitHunk> + Clone,
{
let git_repository = project_repository.repo();
let git_repository = ctx.repository();
let mut builder = git2::build::TreeUpdateBuilder::new();
// now update the index with content in the working directory for each file
for (rel_path, hunks) in files {
let rel_path = rel_path.borrow();
let hunks: Vec<GitHunk> = hunks.borrow().iter().map(|h| h.clone().into()).collect();
let full_path = project_repository.project().worktree_path().join(rel_path);
let full_path = ctx.project().worktree_path().join(rel_path);
let is_submodule = full_path.is_dir()
&& hunks.len() == 1
@ -102,7 +102,7 @@ where
// if the link target is inside the project repository, make it relative
let link_target = link_target
.strip_prefix(project_repository.project().worktree_path())
.strip_prefix(ctx.project().worktree_path())
.unwrap_or(&link_target);
let blob_oid = git_repository.blob(
@ -193,7 +193,7 @@ where
// now write out the tree
let tree_oid = builder
.create_updated(project_repository.repo(), base_tree)
.create_updated(ctx.repository(), base_tree)
.context("failed to write updated tree")?;
Ok(tree_oid)

View File

@ -1,6 +1,6 @@
use anyhow::Result;
use bstr::BString;
use gitbutler_command_context::ProjectRepository;
use gitbutler_command_context::CommandContext;
use gitbutler_project::Project;
use crate::{Config, RepositoryExt};
@ -15,20 +15,22 @@ pub trait RepoCommands {
impl RepoCommands for Project {
fn get_local_config(&self, key: &str) -> Result<Option<String>> {
let project_repo = ProjectRepository::open(self)?;
let config: Config = project_repo.repo().into();
let ctx = CommandContext::open(self)?;
let config: Config = ctx.repository().into();
config.get_local(key)
}
fn set_local_config(&self, key: &str, value: &str) -> Result<()> {
let project_repo = ProjectRepository::open(self)?;
let config: Config = project_repo.repo().into();
let ctx = CommandContext::open(self)?;
let config: Config = ctx.repository().into();
config.set_local(key, value)
}
fn check_signing_settings(&self) -> Result<bool> {
let repo = ProjectRepository::open(self)?;
let signed = repo.repo().sign_buffer(&BString::new("test".into()).into());
let repo = CommandContext::open(self)?;
let signed = repo
.repository()
.sign_buffer(&BString::new("test".into()).into());
match signed {
Ok(_) => Ok(true),
Err(e) => Err(e),
@ -36,13 +38,13 @@ impl RepoCommands for Project {
}
fn remotes(&self) -> Result<Vec<String>> {
let project_repository = ProjectRepository::open(self)?;
project_repository.repo().remotes_as_string()
let ctx = CommandContext::open(self)?;
ctx.repository().remotes_as_string()
}
fn add_remote(&self, name: &str, url: &str) -> Result<()> {
let project_repository = ProjectRepository::open(self)?;
project_repository.repo().remote(name, url)?;
let ctx = CommandContext::open(self)?;
ctx.repository().remote(name, url)?;
Ok(())
}
}

View File

@ -1,7 +1,7 @@
use std::{path::PathBuf, str::FromStr, vec};
use anyhow::Context;
use gitbutler_command_context::ProjectRepository;
use gitbutler_command_context::CommandContext;
use gitbutler_project::AuthKey;
use gitbutler_url::{ConvertError, Scheme, Url};
@ -81,10 +81,10 @@ pub enum HelpError {
impl Helper {
pub fn help<'a>(
&'a self,
project_repository: &'a ProjectRepository,
ctx: &'a CommandContext,
remote_name: &str,
) -> Result<Vec<(git2::Remote, Vec<Credential>)>, HelpError> {
let remote = project_repository.repo().find_remote(remote_name)?;
let remote = ctx.repository().find_remote(remote_name)?;
let remote_url = Url::from_str(remote.url().ok_or(HelpError::NoUrlSet)?)
.context("failed to parse remote url")?;
@ -93,15 +93,13 @@ impl Helper {
return Ok(vec![(remote, vec![Credential::Noop])]);
}
match &project_repository.project().preferred_key {
match &ctx.project().preferred_key {
AuthKey::Local { private_key_path } => {
let ssh_remote = if remote_url.scheme == Scheme::Ssh {
Ok(remote)
} else {
let ssh_url = remote_url.as_ssh()?;
project_repository
.repo()
.remote_anonymous(&ssh_url.to_string())
ctx.repository().remote_anonymous(&ssh_url.to_string())
}?;
Ok(vec![(
@ -117,9 +115,9 @@ impl Helper {
Ok(remote)
} else {
let url = remote_url.as_https()?;
project_repository.repo().remote_anonymous(&url.to_string())
ctx.repository().remote_anonymous(&url.to_string())
}?;
let flow = Self::https_flow(project_repository, &remote_url)?
let flow = Self::https_flow(ctx, &remote_url)?
.into_iter()
.map(Credential::Https)
.collect::<Vec<_>>();
@ -133,13 +131,13 @@ impl Helper {
}
fn https_flow(
project_repository: &ProjectRepository,
ctx: &CommandContext,
remote_url: &Url,
) -> Result<Vec<HttpsCredential>, HelpError> {
let mut flow = vec![];
let mut helper = git2::CredentialHelper::new(&remote_url.to_string());
let config = project_repository.repo().config()?;
let config = ctx.repository().config()?;
helper.config(&config);
if let Some((username, password)) = helper.execute() {
flow.push(HttpsCredential::CredentialHelper { username, password });

View File

@ -1,6 +1,6 @@
use anyhow::{anyhow, Context, Result};
use bstr::ByteSlice;
use gitbutler_command_context::ProjectRepository;
use gitbutler_command_context::CommandContext;
use gitbutler_commit::{commit_ext::CommitExt, commit_headers::HasCommitHeaders};
use gitbutler_error::error::Marker;
@ -10,21 +10,19 @@ use crate::{LogUntil, RepoActionsExt, RepositoryExt};
/// this function takes a commit range and generates a Vector of commit oids
/// and then passes them to `cherry_rebase_group` to rebase them onto the target commit
pub fn cherry_rebase(
project_repository: &ProjectRepository,
ctx: &CommandContext,
target_commit_oid: git2::Oid,
start_commit_oid: git2::Oid,
end_commit_oid: git2::Oid,
) -> Result<Option<git2::Oid>> {
// get a list of the commits to rebase
let mut ids_to_rebase =
project_repository.l(end_commit_oid, LogUntil::Commit(start_commit_oid))?;
let mut ids_to_rebase = ctx.l(end_commit_oid, LogUntil::Commit(start_commit_oid))?;
if ids_to_rebase.is_empty() {
return Ok(None);
}
let new_head_id =
cherry_rebase_group(project_repository, target_commit_oid, &mut ids_to_rebase)?;
let new_head_id = cherry_rebase_group(ctx, target_commit_oid, &mut ids_to_rebase)?;
Ok(Some(new_head_id))
}
@ -34,7 +32,7 @@ pub fn cherry_rebase(
/// the difference between this and a libgit2 based rebase is that this will successfully
/// rebase empty commits (two commits with identical trees)
pub fn cherry_rebase_group(
project_repository: &ProjectRepository,
ctx: &CommandContext,
target_commit_oid: git2::Oid,
ids_to_rebase: &mut [git2::Oid],
) -> Result<git2::Oid> {
@ -42,22 +40,21 @@ pub fn cherry_rebase_group(
// now, rebase unchanged commits onto the new commit
let commits_to_rebase = ids_to_rebase
.iter()
.map(|oid| project_repository.repo().find_commit(oid.to_owned()))
.map(|oid| ctx.repository().find_commit(oid.to_owned()))
.collect::<Result<Vec<_>, _>>()
.context("failed to read commits to rebase")?;
let new_head_id = commits_to_rebase
.into_iter()
.fold(
project_repository
.repo()
ctx.repository()
.find_commit(target_commit_oid)
.context("failed to find new commit"),
|head, to_rebase| {
let head = head?;
let mut cherrypick_index = project_repository
.repo()
let mut cherrypick_index = ctx
.repository()
.cherrypick_commit(&to_rebase, &head, 0, None)
.context("failed to cherry pick")?;
@ -66,18 +63,18 @@ pub fn cherry_rebase_group(
}
let merge_tree_oid = cherrypick_index
.write_tree_to(project_repository.repo())
.write_tree_to(ctx.repository())
.context("failed to write merge tree")?;
let merge_tree = project_repository
.repo()
let merge_tree = ctx
.repository()
.find_tree(merge_tree_oid)
.context("failed to find merge tree")?;
let commit_headers = to_rebase.gitbutler_headers();
let commit_oid = project_repository
.repo()
let commit_oid = ctx
.repository()
.commit_with_signature(
None,
&to_rebase.author(),
@ -89,8 +86,7 @@ pub fn cherry_rebase_group(
)
.context("failed to create commit")?;
project_repository
.repo()
ctx.repository()
.find_commit(commit_oid)
.context("failed to find commit")
},

View File

@ -6,7 +6,7 @@ use gitbutler_branch::{
Branch, BranchId, GITBUTLER_INTEGRATION_COMMIT_AUTHOR_EMAIL,
GITBUTLER_INTEGRATION_COMMIT_AUTHOR_NAME,
};
use gitbutler_command_context::ProjectRepository;
use gitbutler_command_context::CommandContext;
use gitbutler_commit::commit_headers::CommitHeadersV2;
use gitbutler_error::error::Code;
use gitbutler_project::AuthKey;
@ -49,7 +49,7 @@ pub trait RepoActionsExt {
fn signatures(&self) -> Result<(git2::Signature, git2::Signature)>;
}
impl RepoActionsExt for ProjectRepository {
impl RepoActionsExt for CommandContext {
fn git_test_push(
&self,
credentials: &Helper,
@ -60,7 +60,7 @@ impl RepoActionsExt for ProjectRepository {
let target_branch_refname =
Refname::from_str(&format!("refs/remotes/{}/{}", remote_name, branch_name))?;
let branch = self
.repo()
.repository()
.find_branch_by_refname(&target_branch_refname)?
.ok_or(anyhow!("failed to find branch {}", target_branch_refname))?;
@ -94,21 +94,23 @@ impl RepoActionsExt for ProjectRepository {
}
fn add_branch_reference(&self, branch: &Branch) -> Result<()> {
let (should_write, with_force) =
match self.repo().find_reference(&branch.refname().to_string()) {
Ok(reference) => match reference.target() {
Some(head_oid) => Ok((head_oid != branch.head, true)),
None => Ok((true, true)),
},
Err(err) => match err.code() {
git2::ErrorCode::NotFound => Ok((true, false)),
_ => Err(err),
},
}
.context("failed to lookup reference")?;
let (should_write, with_force) = match self
.repository()
.find_reference(&branch.refname().to_string())
{
Ok(reference) => match reference.target() {
Some(head_oid) => Ok((head_oid != branch.head, true)),
None => Ok((true, true)),
},
Err(err) => match err.code() {
git2::ErrorCode::NotFound => Ok((true, false)),
_ => Err(err),
},
}
.context("failed to lookup reference")?;
if should_write {
self.repo()
self.repository()
.reference(
&branch.refname().to_string(),
branch.head,
@ -122,7 +124,10 @@ impl RepoActionsExt for ProjectRepository {
}
fn delete_branch_reference(&self, branch: &Branch) -> Result<()> {
match self.repo().find_reference(&branch.refname().to_string()) {
match self
.repository()
.find_reference(&branch.refname().to_string())
{
Ok(mut reference) => {
reference
.delete()
@ -141,7 +146,10 @@ impl RepoActionsExt for ProjectRepository {
fn l(&self, from: git2::Oid, to: LogUntil) -> Result<Vec<git2::Oid>> {
match to {
LogUntil::Commit(oid) => {
let mut revwalk = self.repo().revwalk().context("failed to create revwalk")?;
let mut revwalk = self
.repository()
.revwalk()
.context("failed to create revwalk")?;
revwalk
.push(from)
.context(format!("failed to push {}", from))?;
@ -153,7 +161,10 @@ impl RepoActionsExt for ProjectRepository {
.collect::<Result<Vec<_>, _>>()
}
LogUntil::Take(n) => {
let mut revwalk = self.repo().revwalk().context("failed to create revwalk")?;
let mut revwalk = self
.repository()
.revwalk()
.context("failed to create revwalk")?;
revwalk
.push(from)
.context(format!("failed to push {}", from))?;
@ -163,7 +174,10 @@ impl RepoActionsExt for ProjectRepository {
.collect::<Result<Vec<_>, _>>()
}
LogUntil::When(cond) => {
let mut revwalk = self.repo().revwalk().context("failed to create revwalk")?;
let mut revwalk = self
.repository()
.revwalk()
.context("failed to create revwalk")?;
revwalk
.push(from)
.context(format!("failed to push {}", from))?;
@ -173,7 +187,7 @@ impl RepoActionsExt for ProjectRepository {
oids.push(oid);
let commit = self
.repo()
.repository()
.find_commit(oid)
.context("failed to find commit")?;
@ -184,7 +198,10 @@ impl RepoActionsExt for ProjectRepository {
Ok(oids)
}
LogUntil::End => {
let mut revwalk = self.repo().revwalk().context("failed to create revwalk")?;
let mut revwalk = self
.repository()
.revwalk()
.context("failed to create revwalk")?;
revwalk
.push(from)
.context(format!("failed to push {}", from))?;
@ -205,7 +222,7 @@ impl RepoActionsExt for ProjectRepository {
Ok(self
.list(from, to)?
.into_iter()
.map(|oid| self.repo().find_commit(oid))
.map(|oid| self.repository().find_commit(oid))
.collect::<Result<Vec<_>, _>>()?)
}
@ -213,7 +230,7 @@ impl RepoActionsExt for ProjectRepository {
fn log(&self, from: git2::Oid, to: LogUntil) -> Result<Vec<git2::Commit>> {
self.l(from, to)?
.into_iter()
.map(|oid| self.repo().find_commit(oid))
.map(|oid| self.repository().find_commit(oid))
.collect::<Result<Vec<_>, _>>()
.context("failed to collect commits")
}
@ -232,7 +249,7 @@ impl RepoActionsExt for ProjectRepository {
commit_headers: Option<CommitHeadersV2>,
) -> Result<git2::Oid> {
let (author, committer) = self.signatures().context("failed to get signatures")?;
self.repo()
self.repository()
.commit_with_signature(
None,
&author,
@ -428,7 +445,7 @@ impl RepoActionsExt for ProjectRepository {
}
fn signatures(&self) -> Result<(git2::Signature, git2::Signature)> {
let repo = gix::open(self.repo().path())?;
let repo = gix::open(self.repository().path())?;
let default_actor = gix::actor::SignatureRef {
name: GITBUTLER_INTEGRATION_COMMIT_AUTHOR_NAME.into(),
@ -436,7 +453,7 @@ impl RepoActionsExt for ProjectRepository {
time: Default::default(),
};
let author = repo.author().transpose()?.unwrap_or(default_actor);
let config: Config = self.repo().into();
let config: Config = self.repository().into();
let committer = if config.user_real_comitter()? {
repo.committer().transpose()?.unwrap_or(default_actor)
} else {

View File

@ -1,6 +1,6 @@
use std::{path::PathBuf, str};
use gitbutler_command_context::ProjectRepository;
use gitbutler_command_context::CommandContext;
use gitbutler_project as projects;
use gitbutler_repo::credentials::{Credential, Helper, SshCredential};
use gitbutler_testsupport::{temp_dir, test_repository};
@ -36,9 +36,9 @@ impl TestCase<'_> {
preferred_key: self.preferred_key.clone(),
..Default::default()
};
let project_repository = ProjectRepository::open(&project).unwrap();
let ctx = CommandContext::open(&project).unwrap();
let flow = helper.help(&project_repository, "origin").unwrap();
let flow = helper.help(&ctx, "origin").unwrap();
flow.into_iter()
.map(|(remote, credentials)| (remote.url().as_ref().unwrap().to_string(), credentials))
.collect::<Vec<_>>()

View File

@ -5,7 +5,7 @@ use std::{
use anyhow::{anyhow, Context, Result};
use gitbutler_branch::{Target, VirtualBranchesHandle};
use gitbutler_command_context::ProjectRepository;
use gitbutler_command_context::CommandContext;
use gitbutler_error::error::Code;
use gitbutler_id::id::Id;
use gitbutler_oplog::OplogExt;
@ -17,11 +17,11 @@ use gitbutler_user as users;
use itertools::Itertools;
pub fn sync_with_gitbutler(
project_repository: &ProjectRepository,
ctx: &CommandContext,
user: &users::User,
projects: &projects::Controller,
) -> Result<()> {
let project = project_repository.project();
let project = ctx.project();
let vb_state = VirtualBranchesHandle::new(project.gb_dir());
let default_target = vb_state.get_default_target()?;
let gb_code_last_commit = project
@ -33,7 +33,7 @@ pub fn sync_with_gitbutler(
// Push target
push_target(
projects,
project_repository,
ctx,
&default_target,
gb_code_last_commit,
project.id,
@ -42,16 +42,16 @@ pub fn sync_with_gitbutler(
)?;
// Push all refs
push_all_refs(project_repository, user, project.id)?;
push_all_refs(ctx, user, project.id)?;
// Push Oplog head
let oplog_refspec = project_repository
let oplog_refspec = ctx
.project()
.oplog_head()?
.map(|sha| format!("+{}:refs/gitbutler/oplog/oplog", sha));
if let Some(oplog_refspec) = oplog_refspec {
let x = push_to_gitbutler_server(project_repository, Some(user), &[&oplog_refspec]);
let x = push_to_gitbutler_server(ctx, Some(user), &[&oplog_refspec]);
println!("\n\n\nHERE: {:?}", x?);
}
@ -60,7 +60,7 @@ pub fn sync_with_gitbutler(
fn push_target(
projects: &projects::Controller,
project_repository: &ProjectRepository,
ctx: &CommandContext,
default_target: &Target,
gb_code_last_commit: Option<git2::Oid>,
project_id: Id<Project>,
@ -68,7 +68,7 @@ fn push_target(
batch_size: usize,
) -> Result<()> {
let ids = batch_rev_walk(
project_repository.repo(),
ctx.repository(),
batch_size,
default_target.sha,
gb_code_last_commit,
@ -84,7 +84,7 @@ fn push_target(
for (idx, id) in ids.iter().enumerate().rev() {
let refspec = format!("+{}:refs/push-tmp/{}", id, project_id);
push_to_gitbutler_server(project_repository, Some(user), &[&refspec])?;
push_to_gitbutler_server(ctx, Some(user), &[&refspec])?;
update_project(projects, project_id, *id)?;
tracing::info!(
@ -96,7 +96,7 @@ fn push_target(
}
push_to_gitbutler_server(
project_repository,
ctx,
Some(user),
&[&format!("+{}:refs/{}", default_target.sha, project_id)],
)?;
@ -137,9 +137,9 @@ fn batch_rev_walk(
Ok(oids)
}
fn collect_refs(project_repository: &ProjectRepository) -> anyhow::Result<Vec<Refname>> {
Ok(project_repository
.repo()
fn collect_refs(ctx: &CommandContext) -> anyhow::Result<Vec<Refname>> {
Ok(ctx
.repository()
.references_glob("refs/*")?
.flatten()
.filter_map(|r| {
@ -150,11 +150,11 @@ fn collect_refs(project_repository: &ProjectRepository) -> anyhow::Result<Vec<Re
}
fn push_all_refs(
project_repository: &ProjectRepository,
ctx: &CommandContext,
user: &users::User,
project_id: Id<projects::Project>,
) -> Result<()> {
let gb_references = collect_refs(project_repository)?;
let gb_references = collect_refs(ctx)?;
let all_refs: Vec<_> = gb_references
.iter()
.filter(|r| {
@ -168,7 +168,7 @@ fn push_all_refs(
let all_refs: Vec<_> = all_refs.iter().map(String::as_str).collect();
let anything_pushed = push_to_gitbutler_server(project_repository, Some(user), &all_refs)?;
let anything_pushed = push_to_gitbutler_server(ctx, Some(user), &all_refs)?;
if anything_pushed {
tracing::info!(
%project_id,
@ -196,11 +196,11 @@ fn update_project(
}
fn push_to_gitbutler_server(
project_repo: &ProjectRepository,
ctx: &CommandContext,
user: Option<&users::User>,
ref_specs: &[&str],
) -> Result<bool> {
let project = project_repo.project();
let project = ctx.project();
let url = project
.api
.as_ref()
@ -243,7 +243,7 @@ fn push_to_gitbutler_server(
let headers = &[auth_header.as_str()];
push_options.custom_headers(headers);
let mut remote = project_repo.repo().remote_anonymous(&url.to_string())?;
let mut remote = ctx.repository().remote_anonymous(&url.to_string())?;
remote
.push(ref_specs, Some(&mut push_options))

View File

@ -3,7 +3,7 @@ use std::path::PathBuf;
use anyhow::{Context, Result};
use gitbutler_branch::BranchId;
use gitbutler_branch_actions::conflicts;
use gitbutler_command_context::ProjectRepository;
use gitbutler_command_context::CommandContext;
use gitbutler_project as projects;
use gitbutler_project::ProjectId;
use gitbutler_reference::RemoteRefname;
@ -28,16 +28,16 @@ impl App {
impl App {
pub fn mark_resolved(&self, project_id: ProjectId, path: &str) -> Result<()> {
let project = self.projects().get(project_id)?;
let project_repository = ProjectRepository::open(&project)?;
let ctx = CommandContext::open(&project)?;
// mark file as resolved
conflicts::resolve(&project_repository, path)?;
conflicts::resolve(&ctx, path)?;
Ok(())
}
pub fn git_remote_branches(&self, project_id: ProjectId) -> Result<Vec<RemoteRefname>> {
let project = self.projects().get(project_id)?;
let project_repository = ProjectRepository::open(&project)?;
project_repository.repo().remote_branches()
let ctx = CommandContext::open(&project)?;
ctx.repository().remote_branches()
}
pub fn git_test_push(
@ -49,8 +49,8 @@ impl App {
askpass: Option<Option<BranchId>>,
) -> Result<()> {
let project = self.projects().get(project_id)?;
let project_repository = ProjectRepository::open(&project)?;
project_repository.git_test_push(credentials, remote_name, branch_name, askpass)
let ctx = CommandContext::open(&project)?;
ctx.git_test_push(credentials, remote_name, branch_name, askpass)
}
pub fn git_test_fetch(
@ -61,15 +61,15 @@ impl App {
askpass: Option<String>,
) -> Result<()> {
let project = self.projects().get(project_id)?;
let project_repository = ProjectRepository::open(&project)?;
project_repository.fetch(remote_name, credentials, askpass)
let ctx = CommandContext::open(&project)?;
ctx.fetch(remote_name, credentials, askpass)
}
pub fn git_index_size(&self, project_id: ProjectId) -> Result<usize> {
let project = self.projects().get(project_id)?;
let project_repository = ProjectRepository::open(&project)?;
let size = project_repository
.repo()
let ctx = CommandContext::open(&project)?;
let size = ctx
.repository()
.index()
.context("failed to get index size")?
.len();
@ -78,9 +78,9 @@ impl App {
pub fn git_head(&self, project_id: ProjectId) -> Result<String> {
let project = self.projects().get(project_id)?;
let project_repository = ProjectRepository::open(&project)?;
let head = project_repository
.repo()
let ctx = CommandContext::open(&project)?;
let head = ctx
.repository()
.head()
.context("failed to get repository head")?;
Ok(head.name().unwrap().to_string())

View File

@ -7,7 +7,7 @@ pub mod commands {
BaseBranch, BranchListing, BranchListingDetails, BranchListingFilter, RemoteBranch,
RemoteBranchData, RemoteBranchFile, VirtualBranchActions, VirtualBranches,
};
use gitbutler_command_context::ProjectRepository;
use gitbutler_command_context::CommandContext;
use gitbutler_error::error::Code;
use gitbutler_project as projects;
use gitbutler_project::{FetchResult, ProjectId};
@ -416,7 +416,7 @@ pub mod commands {
project_id: ProjectId,
filter: Option<BranchListingFilter>,
) -> Result<Vec<BranchListing>, Error> {
let ctx = ProjectRepository::open(&projects.get(project_id)?)?;
let ctx = CommandContext::open(&projects.get(project_id)?)?;
let branches = gitbutler_branch_actions::list_branches(&ctx, filter)?;
Ok(branches)
}
@ -428,7 +428,7 @@ pub mod commands {
project_id: ProjectId,
branch_names: Vec<String>,
) -> Result<Vec<BranchListingDetails>, Error> {
let ctx = ProjectRepository::open(&projects.get(project_id)?)?;
let ctx = CommandContext::open(&projects.get(project_id)?)?;
let branches = gitbutler_branch_actions::get_branch_listing_details(&ctx, branch_names)?;
Ok(branches)
}

View File

@ -19,15 +19,15 @@ pub mod paths {
pub mod virtual_branches {
use gitbutler_branch::{Target, VirtualBranchesHandle};
use gitbutler_command_context::ProjectRepository;
use gitbutler_command_context::CommandContext;
use crate::empty_bare_repository;
pub fn set_test_target(project_repository: &ProjectRepository) -> anyhow::Result<()> {
let vb_state = VirtualBranchesHandle::new(project_repository.project().gb_dir());
pub fn set_test_target(ctx: &CommandContext) -> anyhow::Result<()> {
let vb_state = VirtualBranchesHandle::new(ctx.project().gb_dir());
let (remote_repo, _tmp) = empty_bare_repository();
let mut remote = project_repository
.repo()
let mut remote = ctx
.repository()
.remote("origin", remote_repo.path().to_str().unwrap())
.expect("failed to add remote");
remote.push(&["refs/heads/master:refs/heads/master"], None)?;
@ -41,7 +41,7 @@ pub mod virtual_branches {
})
.expect("failed to write target");
gitbutler_branch_actions::update_gitbutler_integration(&vb_state, project_repository)
gitbutler_branch_actions::update_gitbutler_integration(&vb_state, ctx)
.expect("failed to update integration");
Ok(())
@ -66,7 +66,7 @@ pub mod read_only {
path::{Path, PathBuf},
};
use gitbutler_command_context::ProjectRepository;
use gitbutler_command_context::CommandContext;
use gitbutler_project::{Project, ProjectId};
use once_cell::sync::Lazy;
use parking_lot::Mutex;
@ -102,10 +102,7 @@ pub mod read_only {
/// the output of `script_name`.
///
/// Returns the project that is strictly for read-only use.
pub fn fixture(
script_name: &str,
project_directory: &str,
) -> anyhow::Result<ProjectRepository> {
pub fn fixture(script_name: &str, project_directory: &str) -> anyhow::Result<CommandContext> {
static IS_VALID_PROJECT: Lazy<Mutex<BTreeSet<(String, String)>>> =
Lazy::new(|| Mutex::new(Default::default()));
@ -131,7 +128,7 @@ pub mod read_only {
..Default::default()
}
};
ProjectRepository::open(&project)
CommandContext::open(&project)
}
}

View File

@ -4,7 +4,7 @@ use std::{
path::{Path, PathBuf},
};
use gitbutler_command_context::ProjectRepository;
use gitbutler_command_context::CommandContext;
use gitbutler_repo::{credentials::Helper, RepositoryExt};
use tempfile::{tempdir, TempDir};
@ -88,9 +88,9 @@ impl Suite {
pub struct Case {
pub project: gitbutler_project::Project,
pub project_repository: ProjectRepository,
pub ctx: CommandContext,
pub credentials: Helper,
/// The directory containing the `project_repository`
/// The directory containing the `ctx`
project_tmp: Option<TempDir>,
}
@ -108,12 +108,11 @@ impl Drop for Case {
impl Case {
fn new(project: gitbutler_project::Project, project_tmp: TempDir) -> Case {
let project_repository =
ProjectRepository::open(&project).expect("failed to create project repository");
let ctx = CommandContext::open(&project).expect("failed to create project repository");
let credentials = Helper::default();
Case {
project,
project_repository,
ctx,
project_tmp: Some(project_tmp),
credentials,
}
@ -124,12 +123,11 @@ impl Case {
.projects
.get(self.project.id)
.expect("failed to get project");
let project_repository =
ProjectRepository::open(&project).expect("failed to create project repository");
let ctx = CommandContext::open(&project).expect("failed to create project repository");
let credentials = Helper::default();
Self {
credentials,
project_repository,
ctx,
project,
project_tmp: self.project_tmp.take(),
}

View File

@ -2,7 +2,7 @@ use std::{path::PathBuf, sync::Arc};
use anyhow::{Context, Result};
use gitbutler_branch_actions::{VirtualBranchActions, VirtualBranches};
use gitbutler_command_context::ProjectRepository;
use gitbutler_command_context::CommandContext;
use gitbutler_error::error::Marker;
use gitbutler_oplog::{
entry::{OperationKind, SnapshotDetails},
@ -136,7 +136,7 @@ impl Handler {
.get(project_id)
.context("failed to get project")?;
let open_projects_repository = || {
ProjectRepository::open(&project.clone())
CommandContext::open(&project.clone())
.context("failed to open project repository for project")
};
@ -152,14 +152,11 @@ impl Handler {
self.emit_app_event(Change::GitActivity(project.id))?;
}
"HEAD" => {
let project_repository = open_projects_repository()?;
let head_ref = project_repository
.repo()
.head()
.context("failed to get head")?;
let ctx = open_projects_repository()?;
let head_ref = ctx.repository().head().context("failed to get head")?;
let head_ref_name = head_ref.name().context("failed to get head name")?;
if head_ref_name != "refs/heads/gitbutler/integration" {
let mut integration_reference = project_repository.repo().find_reference(
let mut integration_reference = ctx.repository().find_reference(
&Refname::from(LocalRefname::new("gitbutler/integration", None))
.to_string(),
)?;
@ -188,7 +185,7 @@ impl Handler {
if project.is_sync_enabled() && project.has_code_url() {
if let Some(user) = self.users.get_user()? {
let repository = ProjectRepository::open(&project)
let repository = CommandContext::open(&project)
.context("failed to open project repository for project")?;
return sync_with_gitbutler(&repository, &user, &self.projects);
}