move ProjectRepo into its own crate

This type currently acts more or less like a command context that lives for the duration of the request. Regardless of if we wanna keep this pattern or not, separating it out helps us split up core
This commit is contained in:
Kiril Videlov 2024-07-08 13:23:03 +02:00
parent 306ab0bea9
commit e258710502
No known key found for this signature in database
GPG Key ID: A4C733025427C471
28 changed files with 153 additions and 133 deletions

16
Cargo.lock generated
View File

@ -2113,6 +2113,7 @@ dependencies = [
"git2",
"git2-hooks",
"gitbutler-branchstate",
"gitbutler-command-context",
"gitbutler-core",
"gitbutler-git",
"gitbutler-oplog",
@ -2156,6 +2157,16 @@ dependencies = [
"pager",
]
[[package]]
name = "gitbutler-command-context"
version = "0.0.0"
dependencies = [
"anyhow",
"git2",
"gitbutler-core",
"tracing",
]
[[package]]
name = "gitbutler-core"
version = "0.0.0"
@ -2267,6 +2278,7 @@ dependencies = [
"anyhow",
"bstr",
"git2",
"gitbutler-command-context",
"gitbutler-core",
"gitbutler-git",
"gitbutler-testsupport",
@ -2285,6 +2297,7 @@ dependencies = [
"anyhow",
"git2",
"gitbutler-branchstate",
"gitbutler-command-context",
"gitbutler-core",
"gitbutler-oplog",
"itertools 0.13.0",
@ -2303,6 +2316,7 @@ dependencies = [
"futures",
"git2",
"gitbutler-branch",
"gitbutler-command-context",
"gitbutler-core",
"gitbutler-oplog",
"gitbutler-repo",
@ -2339,6 +2353,7 @@ dependencies = [
"git2",
"gitbutler-branch",
"gitbutler-branchstate",
"gitbutler-command-context",
"gitbutler-core",
"gitbutler-repo",
"keyring",
@ -2356,6 +2371,7 @@ dependencies = [
"backoff",
"futures",
"gitbutler-branch",
"gitbutler-command-context",
"gitbutler-core",
"gitbutler-notify-debouncer",
"gitbutler-oplog",

View File

@ -12,6 +12,7 @@ members = [
"crates/gitbutler-oplog",
"crates/gitbutler-branchstate",
"crates/gitbutler-repo",
"crates/gitbutler-command-context",
]
resolver = "2"
@ -35,6 +36,7 @@ gitbutler-sync = { path = "crates/gitbutler-sync" }
gitbutler-oplog = { path = "crates/gitbutler-oplog" }
gitbutler-branchstate = { path = "crates/gitbutler-branchstate" }
gitbutler-repo = { path = "crates/gitbutler-repo" }
gitbutler-command-context = { path = "crates/gitbutler-command-context" }
[profile.release]
codegen-units = 1 # Compile crates one after another so the compiler can optimize better

View File

@ -24,6 +24,7 @@ url = { version = "2.5.2", features = ["serde"] }
md5 = "0.7.0"
futures = "0.3"
itertools = "0.13"
gitbutler-command-context.workspace = true
[[test]]
name="branches"

View File

@ -3,6 +3,7 @@ use std::{path::Path, time};
use anyhow::{anyhow, Context, Result};
use git2::Index;
use gitbutler_branchstate::{VirtualBranchesAccess, VirtualBranchesHandle};
use gitbutler_command_context::ProjectRepo;
use gitbutler_repo::{LogUntil, RepoActions, RepositoryExt};
use serde::Serialize;
@ -16,7 +17,6 @@ use gitbutler_core::error::Marker;
use gitbutler_core::virtual_branches::{branch, target, BranchId, GITBUTLER_INTEGRATION_REFERENCE};
use gitbutler_core::{
git::{self, diff},
project_repository,
projects::FetchResult,
virtual_branches::branch::BranchOwnershipClaims,
};
@ -40,16 +40,14 @@ pub struct BaseBranch {
pub last_fetched_ms: Option<u128>,
}
pub fn get_base_branch_data(
project_repository: &project_repository::ProjectRepo,
) -> Result<BaseBranch> {
pub fn get_base_branch_data(project_repository: &ProjectRepo) -> Result<BaseBranch> {
let target = default_target(&project_repository.project().gb_dir())?;
let base = target_to_base_branch(project_repository, &target)?;
Ok(base)
}
fn go_back_to_integration(
project_repository: &project_repository::ProjectRepo,
project_repository: &ProjectRepo,
default_target: &target::Target,
) -> Result<BaseBranch> {
let statuses = project_repository
@ -120,7 +118,7 @@ fn go_back_to_integration(
}
pub fn set_base_branch(
project_repository: &project_repository::ProjectRepo,
project_repository: &ProjectRepo,
target_branch_ref: &git::RemoteRefname,
) -> Result<BaseBranch> {
let repo = project_repository.repo();
@ -273,7 +271,7 @@ pub fn set_base_branch(
}
pub fn set_target_push_remote(
project_repository: &project_repository::ProjectRepo,
project_repository: &ProjectRepo,
push_remote_name: &str,
) -> Result<()> {
let remote = project_repository
@ -294,7 +292,7 @@ pub fn set_target_push_remote(
Ok(())
}
fn set_exclude_decoration(project_repository: &project_repository::ProjectRepo) -> Result<()> {
fn set_exclude_decoration(project_repository: &ProjectRepo) -> Result<()> {
let repo = project_repository.repo();
let mut config = repo.config()?;
config
@ -330,7 +328,7 @@ fn _print_tree(repo: &git2::Repository, tree: &git2::Tree) -> Result<()> {
// merge the target branch into our current working directory
// update the target sha
pub fn update_base_branch(
project_repository: &project_repository::ProjectRepo,
project_repository: &ProjectRepo,
) -> anyhow::Result<Vec<git2::Branch<'_>>> {
project_repository.assure_resolved()?;
@ -576,7 +574,7 @@ pub fn update_base_branch(
}
pub fn target_to_base_branch(
project_repository: &project_repository::ProjectRepo,
project_repository: &ProjectRepo,
target: &target::Target,
) -> Result<BaseBranch> {
let repo = project_repository.repo();

View File

@ -11,9 +11,10 @@ use std::{
};
use anyhow::{anyhow, Context, Result};
use gitbutler_command_context::ProjectRepo;
use itertools::Itertools;
use gitbutler_core::{error::Marker, project_repository::ProjectRepo};
use gitbutler_core::error::Marker;
pub fn mark<P: AsRef<Path>, A: AsRef<[P]>>(
repository: &ProjectRepo,

View File

@ -1,8 +1,7 @@
use anyhow::Result;
use gitbutler_branchstate::{VirtualBranchesAccess, VirtualBranchesHandle};
use gitbutler_core::{
git::BranchExt, project_repository::ProjectRepo, projects::FetchResult, types::ReferenceName,
};
use gitbutler_command_context::ProjectRepo;
use gitbutler_core::{git::BranchExt, projects::FetchResult, types::ReferenceName};
use gitbutler_oplog::{
entry::{OperationKind, SnapshotDetails},
oplog::Oplog,

View File

@ -4,14 +4,13 @@ use anyhow::{anyhow, bail, Context, Result};
use bstr::ByteSlice;
use gitbutler_branchstate::{VirtualBranchesAccess, VirtualBranchesHandle};
use gitbutler_command_context::ProjectRepo;
use gitbutler_core::error::Marker;
use gitbutler_core::virtual_branches::{
GITBUTLER_INTEGRATION_COMMIT_AUTHOR_EMAIL, GITBUTLER_INTEGRATION_COMMIT_AUTHOR_NAME,
GITBUTLER_INTEGRATION_REFERENCE,
};
use gitbutler_core::{
git::CommitExt, project_repository, virtual_branches::branch::BranchCreateRequest,
};
use gitbutler_core::{git::CommitExt, virtual_branches::branch::BranchCreateRequest};
use gitbutler_repo::{LogUntil, RepoActions, RepositoryExt};
use crate::conflicts;
@ -31,7 +30,7 @@ pub fn get_integration_commiter<'a>() -> Result<git2::Signature<'a>> {
// what files have been modified.
pub fn get_workspace_head(
vb_state: &VirtualBranchesHandle,
project_repo: &project_repository::ProjectRepo,
project_repo: &ProjectRepo,
) -> Result<git2::Oid> {
let target = vb_state
.get_default_target()
@ -139,7 +138,7 @@ fn write_integration_file(head: &git2::Reference, path: PathBuf) -> Result<()> {
}
pub fn update_gitbutler_integration(
vb_state: &VirtualBranchesHandle,
project_repository: &project_repository::ProjectRepo,
project_repository: &ProjectRepo,
) -> Result<git2::Oid> {
let target = vb_state
.get_default_target()
@ -289,7 +288,7 @@ pub fn update_gitbutler_integration(
Ok(final_commit)
}
pub fn verify_branch(project_repository: &project_repository::ProjectRepo) -> Result<()> {
pub fn verify_branch(project_repository: &ProjectRepo) -> Result<()> {
project_repository
.verify_current_branch_name()
.and_then(|me| me.verify_head_is_set())
@ -304,7 +303,7 @@ pub trait Verify {
fn verify_head_is_clean(&self) -> Result<&Self>;
}
impl Verify for project_repository::ProjectRepo {
impl Verify for ProjectRepo {
fn verify_head_is_set(&self) -> Result<&Self> {
match self.repo().head().context("failed to get head")?.name() {
Some(refname) if *refname == GITBUTLER_INTEGRATION_REFERENCE.to_string() => Ok(self),

View File

@ -3,14 +3,12 @@ use std::path::Path;
use anyhow::{Context, Result};
use bstr::BString;
use gitbutler_branchstate::VirtualBranchesHandle;
use gitbutler_command_context::ProjectRepo;
use gitbutler_repo::{LogUntil, RepoActions, RepositoryExt};
use serde::Serialize;
use gitbutler_core::git::{self, CommitExt};
use gitbutler_core::virtual_branches::{target, Author};
use gitbutler_core::{
git::{self, CommitExt},
project_repository,
};
// this struct is a mapping to the view `RemoteBranch` type in Typescript
// found in src-tauri/src/routes/repo/[project_id]/types.ts
@ -60,9 +58,7 @@ 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: &project_repository::ProjectRepo,
) -> Result<Vec<RemoteBranch>> {
pub fn list_remote_branches(project_repository: &ProjectRepo) -> Result<Vec<RemoteBranch>> {
let default_target = default_target(&project_repository.project().gb_dir())?;
let mut remote_branches = vec![];
@ -90,7 +86,7 @@ pub fn list_remote_branches(
}
pub fn get_branch_data(
project_repository: &project_repository::ProjectRepo,
project_repository: &ProjectRepo,
refname: &git::Refname,
) -> Result<RemoteBranchData> {
let default_target = default_target(&project_repository.project().gb_dir())?;
@ -148,7 +144,7 @@ pub fn branch_to_remote_branch(branch: &git2::Branch) -> Result<Option<RemoteBra
}
pub fn branch_to_remote_branch_data(
project_repository: &project_repository::ProjectRepo,
project_repository: &ProjectRepo,
branch: &git2::Branch,
base: git2::Oid,
) -> Result<Option<RemoteBranchData>> {

View File

@ -1,4 +1,5 @@
use gitbutler_branchstate::{VirtualBranchesAccess, VirtualBranchesHandle};
use gitbutler_command_context::ProjectRepo;
use gitbutler_oplog::snapshot::Snapshot;
use gitbutler_repo::credentials::Helper;
use gitbutler_repo::{LogUntil, RepoActions, RepositoryExt};
@ -41,7 +42,6 @@ use gitbutler_core::virtual_branches::{
use gitbutler_core::{
dedup::{dedup, dedup_fmt},
git::{self, diff, Refname, RemoteRefname},
project_repository,
};
use gitbutler_repo::rebase::{cherry_rebase, cherry_rebase_group};
@ -205,7 +205,7 @@ pub enum NameConflitResolution {
}
pub fn unapply_ownership(
project_repository: &project_repository::ProjectRepo,
project_repository: &ProjectRepo,
ownership: &BranchOwnershipClaims,
) -> Result<()> {
project_repository.assure_resolved()?;
@ -305,10 +305,7 @@ pub fn unapply_ownership(
}
// reset a file in the project to the index state
pub fn reset_files(
project_repository: &project_repository::ProjectRepo,
files: &Vec<String>,
) -> Result<()> {
pub fn reset_files(project_repository: &ProjectRepo, files: &Vec<String>) -> Result<()> {
project_repository.assure_resolved()?;
// for each tree, we need to checkout the entry from the index at that path
@ -335,12 +332,12 @@ pub fn reset_files(
// to unapply a branch, we need to write the current tree out, then remove those file changes from the wd
pub fn convert_to_real_branch(
project_repository: &project_repository::ProjectRepo,
project_repository: &ProjectRepo,
branch_id: BranchId,
name_conflict_resolution: NameConflitResolution,
) -> Result<git2::Branch<'_>> {
fn build_real_branch<'l>(
project_repository: &'l project_repository::ProjectRepo,
project_repository: &'l ProjectRepo,
vbranch: &branch::Branch,
name_conflict_resolution: NameConflitResolution,
) -> Result<git2::Branch<'l>> {
@ -391,7 +388,7 @@ pub fn convert_to_real_branch(
Ok(branch)
}
fn build_metadata_commit<'l>(
project_repository: &'l project_repository::ProjectRepo,
project_repository: &'l ProjectRepo,
vbranch: &branch::Branch,
branch: &git2::Branch<'l>,
) -> Result<git2::Oid> {
@ -474,7 +471,7 @@ fn find_base_tree<'a>(
}
pub fn list_virtual_branches(
project_repository: &project_repository::ProjectRepo,
project_repository: &ProjectRepo,
) -> Result<(Vec<VirtualBranch>, Vec<diff::FileDiff>)> {
let mut branches: Vec<VirtualBranch> = Vec::new();
@ -655,10 +652,7 @@ fn joined(start_a: u32, end_a: u32, start_b: u32, end_b: u32) -> bool {
|| ((start_b >= start_a && start_b <= end_a) || (end_b >= start_a && end_b <= end_a))
}
fn is_requires_force(
project_repository: &project_repository::ProjectRepo,
branch: &branch::Branch,
) -> Result<bool> {
fn is_requires_force(project_repository: &ProjectRepo, branch: &branch::Branch) -> Result<bool> {
let upstream = if let Some(upstream) = &branch.upstream {
upstream
} else {
@ -687,7 +681,7 @@ fn is_requires_force(
}
fn list_virtual_commit_files(
project_repository: &project_repository::ProjectRepo,
project_repository: &ProjectRepo,
commit: &git2::Commit,
) -> Result<Vec<VirtualBranchFile>> {
if commit.parent_count() == 0 {
@ -705,7 +699,7 @@ fn list_virtual_commit_files(
}
fn commit_to_vbranch_commit(
repository: &project_repository::ProjectRepo,
repository: &ProjectRepo,
branch: &branch::Branch,
commit: &git2::Commit,
is_integrated: bool,
@ -743,7 +737,7 @@ fn commit_to_vbranch_commit(
}
pub fn create_virtual_branch(
project_repository: &project_repository::ProjectRepo,
project_repository: &ProjectRepo,
create: &BranchCreateRequest,
) -> Result<branch::Branch> {
let vb_state = project_repository.project().virtual_branches();
@ -867,7 +861,7 @@ pub fn create_virtual_branch(
/// end since there will only be one parent commit.
///
pub fn integrate_upstream_commits(
project_repository: &project_repository::ProjectRepo,
project_repository: &ProjectRepo,
branch_id: BranchId,
) -> Result<()> {
conflicts::is_conflicting(project_repository, None)?;
@ -997,7 +991,7 @@ pub fn integrate_upstream_commits(
}
pub fn integrate_with_rebase(
project_repository: &project_repository::ProjectRepo,
project_repository: &ProjectRepo,
branch: &mut Branch,
unknown_commits: &mut Vec<git2::Oid>,
) -> Result<git2::Oid> {
@ -1009,7 +1003,7 @@ pub fn integrate_with_rebase(
}
pub fn integrate_with_merge(
project_repository: &project_repository::ProjectRepo,
project_repository: &ProjectRepo,
branch: &mut Branch,
upstream_commit: &git2::Commit,
merge_base: git2::Oid,
@ -1063,7 +1057,7 @@ pub fn integrate_with_merge(
}
pub fn update_branch(
project_repository: &project_repository::ProjectRepo,
project_repository: &ProjectRepo,
branch_update: &branch::BranchUpdateRequest,
) -> Result<branch::Branch> {
let vb_state = project_repository.project().virtual_branches();
@ -1141,10 +1135,7 @@ pub fn update_branch(
Ok(branch)
}
pub fn delete_branch(
project_repository: &project_repository::ProjectRepo,
branch_id: BranchId,
) -> Result<()> {
pub fn delete_branch(project_repository: &ProjectRepo, branch_id: BranchId) -> Result<()> {
let vb_state = project_repository.project().virtual_branches();
let Some(branch) = vb_state.try_branch(branch_id)? else {
return Ok(());
@ -1332,7 +1323,7 @@ pub type VirtualBranchHunksByPathMap = HashMap<PathBuf, Vec<VirtualBranchHunk>>;
// list the virtual branches and their file statuses (statusi?)
#[allow(clippy::type_complexity)]
pub fn get_status_by_branch(
project_repository: &project_repository::ProjectRepo,
project_repository: &ProjectRepo,
integration_commit: Option<&git2::Oid>,
) -> Result<(AppliedStatuses, Vec<diff::FileDiff>)> {
let vb_state = project_repository.project().virtual_branches();
@ -1379,7 +1370,7 @@ pub fn get_status_by_branch(
//
// ownerships are not taken into account here, as they are not relevant for non applied branches
fn get_non_applied_status(
project_repository: &project_repository::ProjectRepo,
project_repository: &ProjectRepo,
virtual_branches: Vec<branch::Branch>,
) -> Result<Vec<(branch::Branch, BranchStatus)>> {
virtual_branches
@ -1482,7 +1473,7 @@ fn new_compute_locks(
}
fn compute_merge_base(
project_repository: &project_repository::ProjectRepo,
project_repository: &ProjectRepo,
target_sha: &git2::Oid,
virtual_branches: &Vec<branch::Branch>,
) -> Result<git2::Oid> {
@ -1503,7 +1494,7 @@ fn compute_merge_base(
}
fn compute_locks(
project_repository: &project_repository::ProjectRepo,
project_repository: &ProjectRepo,
integration_commit: &git2::Oid,
target_sha: &git2::Oid,
base_diffs: &BranchStatus,
@ -1567,7 +1558,7 @@ fn compute_locks(
// Returns branches and their associated file changes, in addition to a list
// of skipped files.
fn get_applied_status(
project_repository: &project_repository::ProjectRepo,
project_repository: &ProjectRepo,
integration_commit: &git2::Oid,
target_sha: &git2::Oid,
mut virtual_branches: Vec<branch::Branch>,
@ -1757,7 +1748,7 @@ fn get_applied_status(
/// NOTE: There is no use returning an iterator here as this acts like the final product.
fn virtual_hunks_into_virtual_files(
project_repository: &project_repository::ProjectRepo,
project_repository: &ProjectRepo,
hunks: impl IntoIterator<Item = (PathBuf, Vec<VirtualBranchHunk>)>,
) -> Vec<VirtualBranchFile> {
hunks
@ -1784,7 +1775,7 @@ fn virtual_hunks_into_virtual_files(
// reset virtual branch to a specific commit
pub fn reset_branch(
project_repository: &project_repository::ProjectRepo,
project_repository: &ProjectRepo,
branch_id: BranchId,
target_commit_id: git2::Oid,
) -> Result<()> {
@ -1855,7 +1846,7 @@ pub fn reset_branch(
}
fn diffs_into_virtual_files(
project_repository: &project_repository::ProjectRepo,
project_repository: &ProjectRepo,
diffs: BranchStatus,
) -> Vec<VirtualBranchFile> {
let hunks_by_filepath = virtual_hunks_by_git_hunks(&project_repository.project().path, diffs);
@ -1866,7 +1857,7 @@ fn diffs_into_virtual_files(
// constructs a tree from those changes on top of the target
// and writes it as a new tree for storage
pub fn write_tree(
project_repository: &project_repository::ProjectRepo,
project_repository: &ProjectRepo,
target: &git2::Oid,
files: impl IntoIterator<Item = (impl Borrow<PathBuf>, impl Borrow<Vec<diff::GitHunk>>)>,
) -> Result<git2::Oid> {
@ -1874,7 +1865,7 @@ pub fn write_tree(
}
pub fn write_tree_onto_commit(
project_repository: &project_repository::ProjectRepo,
project_repository: &ProjectRepo,
commit_oid: git2::Oid,
files: impl IntoIterator<Item = (impl Borrow<PathBuf>, impl Borrow<Vec<diff::GitHunk>>)>,
) -> Result<git2::Oid> {
@ -1888,7 +1879,7 @@ pub fn write_tree_onto_commit(
}
pub fn write_tree_onto_tree(
project_repository: &project_repository::ProjectRepo,
project_repository: &ProjectRepo,
base_tree: &git2::Tree,
files: impl IntoIterator<Item = (impl Borrow<PathBuf>, impl Borrow<Vec<diff::GitHunk>>)>,
) -> Result<git2::Oid> {
@ -2036,7 +2027,7 @@ pub fn write_tree_onto_tree(
#[allow(clippy::too_many_arguments)]
pub fn commit(
project_repository: &project_repository::ProjectRepo,
project_repository: &ProjectRepo,
branch_id: BranchId,
message: &str,
ownership: Option<&branch::BranchOwnershipClaims>,
@ -2157,7 +2148,7 @@ pub fn commit(
}
pub fn push(
project_repository: &project_repository::ProjectRepo,
project_repository: &ProjectRepo,
branch_id: BranchId,
with_force: bool,
credentials: &Helper,
@ -2224,7 +2215,7 @@ pub fn push(
}
fn is_commit_integrated(
project_repository: &project_repository::ProjectRepo,
project_repository: &ProjectRepo,
target: &target::Target,
commit: &git2::Commit,
) -> Result<bool> {
@ -2288,7 +2279,7 @@ fn is_commit_integrated(
}
pub fn is_remote_branch_mergeable(
project_repository: &project_repository::ProjectRepo,
project_repository: &ProjectRepo,
branch_name: &git::RemoteRefname,
) -> Result<bool> {
let vb_state = project_repository.project().virtual_branches();
@ -2331,7 +2322,7 @@ pub fn is_remote_branch_mergeable(
// the changes need to be removed from the "from" commit, everything rebased,
// then added to the "to" commit and everything above that rebased again.
pub fn move_commit_file(
project_repository: &project_repository::ProjectRepo,
project_repository: &ProjectRepo,
branch_id: BranchId,
from_commit_id: git2::Oid,
to_commit_id: git2::Oid,
@ -2568,7 +2559,7 @@ pub fn move_commit_file(
// add the file changes. The branch is then rebased onto the new commit
// and the respective branch head is updated
pub fn amend(
project_repository: &project_repository::ProjectRepo,
project_repository: &ProjectRepo,
branch_id: BranchId,
commit_oid: git2::Oid,
target_ownership: &BranchOwnershipClaims,
@ -2715,7 +2706,7 @@ pub fn amend(
// if the offset is negative, move the commit up one
// rewrites the branch head to the new head commit
pub fn reorder_commit(
project_repository: &project_repository::ProjectRepo,
project_repository: &ProjectRepo,
branch_id: BranchId,
commit_oid: git2::Oid,
offset: i32,
@ -2800,7 +2791,7 @@ pub fn reorder_commit(
// if offset is positive, insert below, if negative, insert above
// return the oid of the new head commit of the branch with the inserted blank commit
pub fn insert_blank_commit(
project_repository: &project_repository::ProjectRepo,
project_repository: &ProjectRepo,
branch_id: BranchId,
commit_oid: git2::Oid,
offset: i32,
@ -2854,7 +2845,7 @@ pub fn insert_blank_commit(
// remove a commit in a branch by rebasing all commits _except_ for it onto it's parent
// if successful, it will update the branch head to the new head commit
pub fn undo_commit(
project_repository: &project_repository::ProjectRepo,
project_repository: &ProjectRepo,
branch_id: BranchId,
commit_oid: git2::Oid,
) -> Result<()> {
@ -2905,7 +2896,7 @@ pub fn undo_commit(
/// squashes a commit from a virtual branch into its parent.
pub fn squash(
project_repository: &project_repository::ProjectRepo,
project_repository: &ProjectRepo,
branch_id: BranchId,
commit_id: git2::Oid,
) -> Result<()> {
@ -2994,7 +2985,7 @@ pub fn squash(
// changes a commit message for commit_oid, rebases everything above it, updates branch head if successful
pub fn update_commit_message(
project_repository: &project_repository::ProjectRepo,
project_repository: &ProjectRepo,
branch_id: BranchId,
commit_id: git2::Oid,
message: &str,
@ -3068,7 +3059,7 @@ pub fn update_commit_message(
/// moves commit from the branch it's in to the top of the target branch
pub fn move_commit(
project_repository: &project_repository::ProjectRepo,
project_repository: &ProjectRepo,
target_branch_id: BranchId,
commit_id: git2::Oid,
) -> Result<()> {
@ -3208,13 +3199,10 @@ pub fn move_commit(
}
pub fn create_virtual_branch_from_branch(
project_repository: &project_repository::ProjectRepo,
project_repository: &ProjectRepo,
upstream: &git::Refname,
) -> Result<BranchId> {
fn apply_branch(
project_repository: &project_repository::ProjectRepo,
branch_id: BranchId,
) -> Result<String> {
fn apply_branch(project_repository: &ProjectRepo, branch_id: BranchId) -> Result<String> {
project_repository.assure_resolved()?;
let repo = project_repository.repo();
@ -3633,7 +3621,7 @@ pub fn apply<S: AsRef<[u8]>>(base_image: S, patch: &Patch<'_, [u8]>) -> Result<B
// are present in a file it will be resolved, meaning it will be removed from the
// conflicts file.
fn update_conflict_markers(
project_repository: &project_repository::ProjectRepo,
project_repository: &ProjectRepo,
files: &HashMap<PathBuf, Vec<GitHunk>>,
) -> Result<()> {
let conflicting_files = conflicts::conflicting_files(project_repository)?;

View File

@ -0,0 +1,12 @@
[package]
name = "gitbutler-command-context"
version = "0.0.0"
edition = "2021"
authors = ["GitButler <gitbutler@gitbutler.com>"]
publish = false
[dependencies]
gitbutler-core.workspace = true
anyhow = "1.0.86"
git2.workspace = true
tracing = "0.1.40"

View File

@ -0,0 +1,2 @@
mod repository;
pub use repository::ProjectRepo;

View File

@ -1,6 +1,6 @@
use anyhow::Result;
use crate::projects;
use gitbutler_core::projects;
pub struct ProjectRepo {
git_repository: git2::Repository,

View File

@ -1,5 +1,3 @@
mod config;
mod repository;
pub use config::Config;
pub use repository::ProjectRepo;

View File

@ -16,6 +16,7 @@ tracing = "0.1.40"
tempfile = "3.10"
thiserror.workspace = true
resolve-path = "0.1.0"
gitbutler-command-context.workspace = true
[[test]]
name="repo"

View File

@ -1,9 +1,7 @@
use anyhow::Result;
use bstr::BString;
use gitbutler_core::{
project_repository::{self, Config},
projects::Project,
};
use gitbutler_command_context::ProjectRepo;
use gitbutler_core::{project_repository::Config, projects::Project};
use crate::RepositoryExt;
@ -17,19 +15,19 @@ pub trait RepoCommands {
impl RepoCommands for Project {
fn get_local_config(&self, key: &str) -> Result<Option<String>> {
let project_repo = project_repository::ProjectRepo::open(self)?;
let project_repo = ProjectRepo::open(self)?;
let config: Config = project_repo.repo().into();
config.get_local(key)
}
fn set_local_config(&self, key: &str, value: &str) -> Result<()> {
let project_repo = project_repository::ProjectRepo::open(self)?;
let project_repo = ProjectRepo::open(self)?;
let config: Config = project_repo.repo().into();
config.set_local(key, value)
}
fn check_signing_settings(&self) -> Result<bool> {
let repo = project_repository::ProjectRepo::open(self)?;
let repo = ProjectRepo::open(self)?;
let signed = repo.repo().sign_buffer(&BString::new("test".into()).into());
match signed {
Ok(_) => Ok(true),
@ -38,12 +36,12 @@ impl RepoCommands for Project {
}
fn remotes(&self) -> Result<Vec<String>> {
let project_repository = project_repository::ProjectRepo::open(self)?;
let project_repository = ProjectRepo::open(self)?;
project_repository.repo().remotes_as_string()
}
fn add_remote(&self, name: &str, url: &str) -> Result<()> {
let project_repository = project_repository::ProjectRepo::open(self)?;
let project_repository = ProjectRepo::open(self)?;
project_repository.repo().remote(name, url)?;
Ok(())
}

View File

@ -3,7 +3,8 @@ use std::{path::PathBuf, vec};
use anyhow::Context;
use gitbutler_core::{keys, project_repository, projects};
use gitbutler_command_context::ProjectRepo;
use gitbutler_core::{keys, projects};
use gitbutler_core::git::Url;
@ -90,7 +91,7 @@ pub enum HelpError {
impl Helper {
pub fn help<'a>(
&'a self,
project_repository: &'a project_repository::ProjectRepo,
project_repository: &'a ProjectRepo,
remote_name: &str,
) -> Result<Vec<(git2::Remote, Vec<Credential>)>, HelpError> {
let remote = project_repository.repo().find_remote(remote_name)?;
@ -142,7 +143,7 @@ impl Helper {
}
fn https_flow(
project_repository: &project_repository::ProjectRepo,
project_repository: &ProjectRepo,
remote_url: &gitbutler_core::git::Url,
) -> Result<Vec<HttpsCredential>, HelpError> {
let mut flow = vec![];

View File

@ -1,7 +1,8 @@
use anyhow::{anyhow, Context, Result};
use bstr::ByteSlice;
use gitbutler_command_context::ProjectRepo;
use gitbutler_core::git::HasCommitHeaders;
use gitbutler_core::{error::Marker, git::CommitExt, project_repository};
use gitbutler_core::{error::Marker, git::CommitExt};
use crate::{LogUntil, RepoActions, RepositoryExt};
@ -9,7 +10,7 @@ use crate::{LogUntil, RepoActions, 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: &project_repository::ProjectRepo,
project_repository: &ProjectRepo,
target_commit_oid: git2::Oid,
start_commit_oid: git2::Oid,
end_commit_oid: git2::Oid,
@ -33,7 +34,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: &project_repository::ProjectRepo,
project_repository: &ProjectRepo,
target_commit_oid: git2::Oid,
ids_to_rebase: &mut [git2::Oid],
) -> Result<git2::Oid> {

View File

@ -2,6 +2,7 @@ use std::str::FromStr;
use anyhow::{anyhow, Context, Result};
use gitbutler_command_context::ProjectRepo;
use gitbutler_core::{
askpass,
error::Code,
@ -11,7 +12,7 @@ use gitbutler_core::{
virtual_branches::{Branch, BranchId},
};
use gitbutler_core::project_repository::{Config, ProjectRepo};
use gitbutler_core::project_repository::Config;
use crate::{credentials::Helper, RepositoryExt};
pub trait RepoActions {

View File

@ -1,7 +1,8 @@
use std::path::PathBuf;
use std::str;
use gitbutler_core::{project_repository, projects, users};
use gitbutler_command_context::ProjectRepo;
use gitbutler_core::{projects, users};
use gitbutler_repo::credentials::{Credential, Helper, SshCredential};
use gitbutler_testsupport::{temp_dir, test_repository};
@ -36,7 +37,7 @@ impl TestCase<'_> {
preferred_key: self.preferred_key.clone(),
..Default::default()
};
let project_repository = project_repository::ProjectRepo::open(&project).unwrap();
let project_repository = ProjectRepo::open(&project).unwrap();
let flow = helper.help(&project_repository, "origin").unwrap();
flow.into_iter()

View File

@ -13,3 +13,4 @@ git2.workspace = true
gitbutler-core.workspace = true
gitbutler-oplog.workspace = true
gitbutler-branchstate.workspace = true
gitbutler-command-context.workspace = true

View File

@ -4,12 +4,12 @@ use std::time;
use anyhow::{anyhow, Context, Result};
use gitbutler_branchstate::VirtualBranchesAccess;
use gitbutler_command_context::ProjectRepo;
use gitbutler_core::error::Code;
use gitbutler_core::git::Url;
use gitbutler_core::id::Id;
use gitbutler_core::{
git::{self},
project_repository,
git,
projects::{self, CodePushState},
users,
};
@ -17,7 +17,7 @@ use gitbutler_oplog::oplog::Oplog;
use itertools::Itertools;
pub async fn sync_with_gitbutler(
project_repository: &project_repository::ProjectRepo,
project_repository: &ProjectRepo,
user: &users::User,
projects: &projects::Controller,
) -> Result<()> {
@ -61,7 +61,7 @@ pub async fn sync_with_gitbutler(
async fn push_target(
projects: &projects::Controller,
project_repository: &project_repository::ProjectRepo,
project_repository: &ProjectRepo,
default_target: &gitbutler_core::virtual_branches::target::Target,
gb_code_last_commit: Option<git2::Oid>,
project_id: Id<projects::Project>,
@ -138,9 +138,7 @@ fn batch_rev_walk(
Ok(oids)
}
fn collect_refs(
project_repository: &project_repository::ProjectRepo,
) -> anyhow::Result<Vec<git::Refname>> {
fn collect_refs(project_repository: &ProjectRepo) -> anyhow::Result<Vec<git::Refname>> {
Ok(project_repository
.repo()
.references_glob("refs/*")?
@ -153,7 +151,7 @@ fn collect_refs(
}
fn push_all_refs(
project_repository: &project_repository::ProjectRepo,
project_repository: &ProjectRepo,
user: &users::User,
project_id: Id<projects::Project>,
) -> Result<()> {
@ -200,7 +198,7 @@ async fn update_project(
}
fn push_to_gitbutler_server(
project_repo: &project_repository::ProjectRepo,
project_repo: &ProjectRepo,
user: Option<&users::User>,
ref_specs: &[&str],
) -> Result<bool> {

View File

@ -51,6 +51,7 @@ gitbutler-watcher.workspace = true
gitbutler-branch.workspace = true
gitbutler-oplog.workspace = true
gitbutler-repo.workspace = true
gitbutler-command-context.workspace = true
open = "5"
[dependencies.tauri]

View File

@ -1,7 +1,8 @@
use anyhow::{Context, Result};
use gitbutler_branch::conflicts;
use gitbutler_command_context::ProjectRepo;
use gitbutler_core::{
git, project_repository,
git,
projects::{self, ProjectId},
virtual_branches::BranchId,
};
@ -19,7 +20,7 @@ impl App {
pub fn mark_resolved(&self, project_id: ProjectId, path: &str) -> Result<()> {
let project = self.projects.get(project_id)?;
let project_repository = project_repository::ProjectRepo::open(&project)?;
let project_repository = ProjectRepo::open(&project)?;
// mark file as resolved
conflicts::resolve(&project_repository, path)?;
Ok(())
@ -27,7 +28,7 @@ impl App {
pub fn git_remote_branches(&self, project_id: ProjectId) -> Result<Vec<git::RemoteRefname>> {
let project = self.projects.get(project_id)?;
let project_repository = project_repository::ProjectRepo::open(&project)?;
let project_repository = ProjectRepo::open(&project)?;
project_repository.repo().remote_branches()
}
@ -40,7 +41,7 @@ impl App {
askpass: Option<Option<BranchId>>,
) -> Result<()> {
let project = self.projects.get(project_id)?;
let project_repository = project_repository::ProjectRepo::open(&project)?;
let project_repository = ProjectRepo::open(&project)?;
project_repository.git_test_push(credentials, remote_name, branch_name, askpass)
}
@ -52,13 +53,13 @@ impl App {
askpass: Option<String>,
) -> Result<()> {
let project = self.projects.get(project_id)?;
let project_repository = project_repository::ProjectRepo::open(&project)?;
let project_repository = ProjectRepo::open(&project)?;
project_repository.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 = project_repository::ProjectRepo::open(&project)?;
let project_repository = ProjectRepo::open(&project)?;
let size = project_repository
.repo()
.index()
@ -69,7 +70,7 @@ impl App {
pub fn git_head(&self, project_id: ProjectId) -> Result<String> {
let project = self.projects.get(project_id)?;
let project_repository = project_repository::ProjectRepo::open(&project)?;
let project_repository = ProjectRepo::open(&project)?;
let head = project_repository
.repo()
.head()

View File

@ -21,3 +21,4 @@ gitbutler-core = { path = "../gitbutler-core" }
gitbutler-branch = { path = "../gitbutler-branch" }
gitbutler-repo = { path = "../gitbutler-repo" }
gitbutler-branchstate = { path = "../gitbutler-branchstate" }
gitbutler-command-context.workspace = true

View File

@ -19,13 +19,12 @@ pub mod paths {
pub mod virtual_branches {
use gitbutler_branchstate::VirtualBranchesAccess;
use gitbutler_core::{project_repository, virtual_branches};
use gitbutler_command_context::ProjectRepo;
use gitbutler_core::virtual_branches;
use crate::empty_bare_repository;
pub fn set_test_target(
project_repository: &project_repository::ProjectRepo,
) -> anyhow::Result<()> {
pub fn set_test_target(project_repository: &ProjectRepo) -> anyhow::Result<()> {
let vb_state = project_repository.project().virtual_branches();
let (remote_repo, _tmp) = empty_bare_repository();
let mut remote = project_repository

View File

@ -4,6 +4,7 @@ use std::{
path::{Path, PathBuf},
};
use gitbutler_command_context::ProjectRepo;
use gitbutler_core::project_repository;
use gitbutler_repo::{credentials::Helper, RepositoryExt};
use tempfile::{tempdir, TempDir};
@ -91,7 +92,7 @@ impl Suite {
pub struct Case {
pub project: gitbutler_core::projects::Project,
pub project_repository: gitbutler_core::project_repository::ProjectRepo,
pub project_repository: ProjectRepo,
pub credentials: Helper,
/// The directory containing the `project_repository`
project_tmp: Option<TempDir>,
@ -111,8 +112,8 @@ impl Drop for Case {
impl Case {
fn new(project: gitbutler_core::projects::Project, project_tmp: TempDir) -> Case {
let project_repository = gitbutler_core::project_repository::ProjectRepo::open(&project)
.expect("failed to create project repository");
let project_repository =
ProjectRepo::open(&project).expect("failed to create project repository");
let credentials = Helper::default();
Case {
project,
@ -127,8 +128,8 @@ impl Case {
.projects
.get(self.project.id)
.expect("failed to get project");
let project_repository = gitbutler_core::project_repository::ProjectRepo::open(&project)
.expect("failed to create project repository");
let project_repository =
ProjectRepo::open(&project).expect("failed to create project repository");
let credentials = Helper::default();
Self {
credentials,

View File

@ -20,6 +20,8 @@ tokio = { workspace = true, features = [ "macros" ] }
tokio-util = "0.7.11"
tracing = "0.1.40"
gix = { workspace = true, features = ["excludes"] }
gitbutler-command-context.workspace = true
backoff = "0.4.0"
notify = { version = "6.0.1" }

View File

@ -3,9 +3,10 @@ use std::sync::Arc;
use anyhow::{Context, Result};
use gitbutler_branch::VirtualBranches;
use gitbutler_command_context::ProjectRepo;
use gitbutler_core::error::Marker;
use gitbutler_core::projects::ProjectId;
use gitbutler_core::{assets, git, project_repository, projects, users};
use gitbutler_core::{assets, git, projects, users};
use gitbutler_oplog::{
entry::{OperationKind, SnapshotDetails},
oplog::Oplog,
@ -155,7 +156,7 @@ impl Handler {
.get(project_id)
.context("failed to get project")?;
let open_projects_repository = || {
project_repository::ProjectRepo::open(&project.clone())
ProjectRepo::open(&project.clone())
.context("failed to open project repository for project")
};
@ -211,7 +212,7 @@ impl Handler {
if project.is_sync_enabled() && project.has_code_url() {
if let Some(user) = self.users.get_user()? {
let repository = project_repository::ProjectRepo::open(&project)
let repository = ProjectRepo::open(&project)
.context("failed to open project repository for project")?;
return sync_with_gitbutler(&repository, &user, &self.projects).await;
}