mirror of
https://github.com/gitbutlerapp/gitbutler.git
synced 2024-12-02 07:53:55 +03:00
Merge pull request #4528 from gitbutlerapp/more-accuratly-define-operating-modes
Introduce operating modes
This commit is contained in:
commit
16400aa4f0
12
Cargo.lock
generated
12
Cargo.lock
generated
@ -2024,6 +2024,7 @@ dependencies = [
|
|||||||
"gitbutler-fs",
|
"gitbutler-fs",
|
||||||
"gitbutler-git",
|
"gitbutler-git",
|
||||||
"gitbutler-id",
|
"gitbutler-id",
|
||||||
|
"gitbutler-operating-modes",
|
||||||
"gitbutler-oplog",
|
"gitbutler-oplog",
|
||||||
"gitbutler-project",
|
"gitbutler-project",
|
||||||
"gitbutler-reference",
|
"gitbutler-reference",
|
||||||
@ -2188,6 +2189,16 @@ dependencies = [
|
|||||||
"walkdir",
|
"walkdir",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "gitbutler-operating-modes"
|
||||||
|
version = "0.0.0"
|
||||||
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
|
"git2",
|
||||||
|
"gitbutler-command-context",
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gitbutler-oplog"
|
name = "gitbutler-oplog"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
@ -2442,6 +2453,7 @@ dependencies = [
|
|||||||
"gitbutler-command-context",
|
"gitbutler-command-context",
|
||||||
"gitbutler-error",
|
"gitbutler-error",
|
||||||
"gitbutler-notify-debouncer",
|
"gitbutler-notify-debouncer",
|
||||||
|
"gitbutler-operating-modes",
|
||||||
"gitbutler-oplog",
|
"gitbutler-oplog",
|
||||||
"gitbutler-project",
|
"gitbutler-project",
|
||||||
"gitbutler-reference",
|
"gitbutler-reference",
|
||||||
|
@ -28,13 +28,13 @@ members = [
|
|||||||
"crates/gitbutler-tagged-string",
|
"crates/gitbutler-tagged-string",
|
||||||
"crates/gitbutler-url",
|
"crates/gitbutler-url",
|
||||||
"crates/gitbutler-diff",
|
"crates/gitbutler-diff",
|
||||||
|
"crates/gitbutler-operating-modes",
|
||||||
]
|
]
|
||||||
resolver = "2"
|
resolver = "2"
|
||||||
|
|
||||||
[workspace.dependencies]
|
[workspace.dependencies]
|
||||||
# Add the `tracing` or `tracing-detail` features to see more of gitoxide in the logs. Useful to see which programs it invokes.
|
# Add the `tracing` or `tracing-detail` features to see more of gitoxide in the logs. Useful to see which programs it invokes.
|
||||||
gix = { version = "0.64", default-features = false, features = [
|
gix = { version = "0.64", default-features = false, features = [] }
|
||||||
] }
|
|
||||||
git2 = { version = "0.18.3", features = [
|
git2 = { version = "0.18.3", features = [
|
||||||
"vendored-openssl",
|
"vendored-openssl",
|
||||||
"vendored-libgit2",
|
"vendored-libgit2",
|
||||||
@ -75,6 +75,7 @@ gitbutler-commit = { path = "crates/gitbutler-commit" }
|
|||||||
gitbutler-tagged-string = { path = "crates/gitbutler-tagged-string" }
|
gitbutler-tagged-string = { path = "crates/gitbutler-tagged-string" }
|
||||||
gitbutler-url = { path = "crates/gitbutler-url" }
|
gitbutler-url = { path = "crates/gitbutler-url" }
|
||||||
gitbutler-diff = { path = "crates/gitbutler-diff" }
|
gitbutler-diff = { path = "crates/gitbutler-diff" }
|
||||||
|
gitbutler-operating-modes = { path = "crates/gitbutler-operating-modes" }
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
codegen-units = 1 # Compile crates one after another so the compiler can optimize better
|
codegen-units = 1 # Compile crates one after another so the compiler can optimize better
|
||||||
|
@ -24,6 +24,7 @@ gitbutler-commit.workspace = true
|
|||||||
gitbutler-url.workspace = true
|
gitbutler-url.workspace = true
|
||||||
gitbutler-fs.workspace = true
|
gitbutler-fs.workspace = true
|
||||||
gitbutler-diff.workspace = true
|
gitbutler-diff.workspace = true
|
||||||
|
gitbutler-operating-modes.workspace = true
|
||||||
serde = { workspace = true, features = ["std"] }
|
serde = { workspace = true, features = ["std"] }
|
||||||
bstr = "1.9.1"
|
bstr = "1.9.1"
|
||||||
diffy = "0.4.0"
|
diffy = "0.4.0"
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
use anyhow::Result;
|
use anyhow::{Context, Result};
|
||||||
use gitbutler_branch::{BranchCreateRequest, BranchId, BranchOwnershipClaims, BranchUpdateRequest};
|
use gitbutler_branch::{BranchCreateRequest, BranchId, BranchOwnershipClaims, BranchUpdateRequest};
|
||||||
use gitbutler_command_context::CommandContext;
|
use gitbutler_command_context::CommandContext;
|
||||||
|
use gitbutler_operating_modes::assure_open_workspace_mode;
|
||||||
use gitbutler_oplog::{
|
use gitbutler_oplog::{
|
||||||
entry::{OperationKind, SnapshotDetails},
|
entry::{OperationKind, SnapshotDetails},
|
||||||
OplogExt, SnapshotExt,
|
OplogExt, SnapshotExt,
|
||||||
@ -35,6 +36,8 @@ impl VirtualBranchActions {
|
|||||||
run_hooks: bool,
|
run_hooks: bool,
|
||||||
) -> Result<git2::Oid> {
|
) -> Result<git2::Oid> {
|
||||||
let ctx = open_with_verify(project)?;
|
let ctx = open_with_verify(project)?;
|
||||||
|
assure_open_workspace_mode(&ctx)
|
||||||
|
.context("Creating a commit requires open workspace mode")?;
|
||||||
let mut guard = project.exclusive_worktree_access();
|
let mut guard = project.exclusive_worktree_access();
|
||||||
let snapshot_tree = ctx.project().prepare_snapshot(guard.read_permission());
|
let snapshot_tree = ctx.project().prepare_snapshot(guard.read_permission());
|
||||||
let result =
|
let result =
|
||||||
@ -57,6 +60,8 @@ impl VirtualBranchActions {
|
|||||||
branch_name: &RemoteRefname,
|
branch_name: &RemoteRefname,
|
||||||
) -> Result<bool> {
|
) -> Result<bool> {
|
||||||
let ctx = CommandContext::open(project)?;
|
let ctx = CommandContext::open(project)?;
|
||||||
|
assure_open_workspace_mode(&ctx)
|
||||||
|
.context("Testing branch mergability requires open workspace mode")?;
|
||||||
branch::is_remote_branch_mergeable(&ctx, branch_name).map_err(Into::into)
|
branch::is_remote_branch_mergeable(&ctx, branch_name).map_err(Into::into)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,10 +69,12 @@ impl VirtualBranchActions {
|
|||||||
&self,
|
&self,
|
||||||
project: &Project,
|
project: &Project,
|
||||||
) -> Result<(Vec<branch::VirtualBranch>, Vec<gitbutler_diff::FileDiff>)> {
|
) -> Result<(Vec<branch::VirtualBranch>, Vec<gitbutler_diff::FileDiff>)> {
|
||||||
branch::list_virtual_branches(
|
let ctx = open_with_verify(project)?;
|
||||||
&open_with_verify(project)?,
|
|
||||||
project.exclusive_worktree_access().write_permission(),
|
assure_open_workspace_mode(&ctx)
|
||||||
)
|
.context("Listing virtual branches requires open workspace mode")?;
|
||||||
|
|
||||||
|
branch::list_virtual_branches(&ctx, project.exclusive_worktree_access().write_permission())
|
||||||
.map_err(Into::into)
|
.map_err(Into::into)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -77,6 +84,8 @@ impl VirtualBranchActions {
|
|||||||
create: &BranchCreateRequest,
|
create: &BranchCreateRequest,
|
||||||
) -> Result<BranchId> {
|
) -> Result<BranchId> {
|
||||||
let ctx = open_with_verify(project)?;
|
let ctx = open_with_verify(project)?;
|
||||||
|
assure_open_workspace_mode(&ctx)
|
||||||
|
.context("Creating a branch requires open workspace mode")?;
|
||||||
let mut guard = project.exclusive_worktree_access();
|
let mut guard = project.exclusive_worktree_access();
|
||||||
let branch_manager = ctx.branch_manager();
|
let branch_manager = ctx.branch_manager();
|
||||||
let branch_id = branch_manager
|
let branch_id = branch_manager
|
||||||
@ -121,6 +130,8 @@ impl VirtualBranchActions {
|
|||||||
|
|
||||||
pub fn integrate_upstream_commits(&self, project: &Project, branch_id: BranchId) -> Result<()> {
|
pub fn integrate_upstream_commits(&self, project: &Project, branch_id: BranchId) -> Result<()> {
|
||||||
let ctx = open_with_verify(project)?;
|
let ctx = open_with_verify(project)?;
|
||||||
|
assure_open_workspace_mode(&ctx)
|
||||||
|
.context("Integrating upstream commits requires open workspace mode")?;
|
||||||
let mut guard = project.exclusive_worktree_access();
|
let mut guard = project.exclusive_worktree_access();
|
||||||
let _ = ctx.project().create_snapshot(
|
let _ = ctx.project().create_snapshot(
|
||||||
SnapshotDetails::new(OperationKind::MergeUpstream),
|
SnapshotDetails::new(OperationKind::MergeUpstream),
|
||||||
@ -131,6 +142,8 @@ impl VirtualBranchActions {
|
|||||||
|
|
||||||
pub fn update_base_branch(&self, project: &Project) -> Result<Vec<ReferenceName>> {
|
pub fn update_base_branch(&self, project: &Project) -> Result<Vec<ReferenceName>> {
|
||||||
let ctx = open_with_verify(project)?;
|
let ctx = open_with_verify(project)?;
|
||||||
|
assure_open_workspace_mode(&ctx)
|
||||||
|
.context("Updating base branch requires open workspace mode")?;
|
||||||
let mut guard = project.exclusive_worktree_access();
|
let mut guard = project.exclusive_worktree_access();
|
||||||
let _ = ctx.project().create_snapshot(
|
let _ = ctx.project().create_snapshot(
|
||||||
SnapshotDetails::new(OperationKind::UpdateWorkspaceBase),
|
SnapshotDetails::new(OperationKind::UpdateWorkspaceBase),
|
||||||
@ -145,6 +158,8 @@ impl VirtualBranchActions {
|
|||||||
branch_update: BranchUpdateRequest,
|
branch_update: BranchUpdateRequest,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let ctx = open_with_verify(project)?;
|
let ctx = open_with_verify(project)?;
|
||||||
|
assure_open_workspace_mode(&ctx)
|
||||||
|
.context("Updating a branch requires open workspace mode")?;
|
||||||
let mut guard = project.exclusive_worktree_access();
|
let mut guard = project.exclusive_worktree_access();
|
||||||
let snapshot_tree = ctx.project().prepare_snapshot(guard.read_permission());
|
let snapshot_tree = ctx.project().prepare_snapshot(guard.read_permission());
|
||||||
let old_branch = ctx
|
let old_branch = ctx
|
||||||
@ -171,6 +186,8 @@ impl VirtualBranchActions {
|
|||||||
branch_updates: Vec<BranchUpdateRequest>,
|
branch_updates: Vec<BranchUpdateRequest>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let ctx = open_with_verify(project)?;
|
let ctx = open_with_verify(project)?;
|
||||||
|
assure_open_workspace_mode(&ctx)
|
||||||
|
.context("Updating branch order requires open workspace mode")?;
|
||||||
for branch_update in branch_updates {
|
for branch_update in branch_updates {
|
||||||
let branch = ctx
|
let branch = ctx
|
||||||
.project()
|
.project()
|
||||||
@ -185,6 +202,8 @@ impl VirtualBranchActions {
|
|||||||
|
|
||||||
pub fn delete_virtual_branch(&self, project: &Project, branch_id: BranchId) -> Result<()> {
|
pub fn delete_virtual_branch(&self, project: &Project, branch_id: BranchId) -> Result<()> {
|
||||||
let ctx = open_with_verify(project)?;
|
let ctx = open_with_verify(project)?;
|
||||||
|
assure_open_workspace_mode(&ctx)
|
||||||
|
.context("Deleting a branch order requires open workspace mode")?;
|
||||||
let branch_manager = ctx.branch_manager();
|
let branch_manager = ctx.branch_manager();
|
||||||
let mut guard = project.exclusive_worktree_access();
|
let mut guard = project.exclusive_worktree_access();
|
||||||
branch_manager.delete_branch(branch_id, guard.write_permission())
|
branch_manager.delete_branch(branch_id, guard.write_permission())
|
||||||
@ -196,6 +215,7 @@ impl VirtualBranchActions {
|
|||||||
ownership: &BranchOwnershipClaims,
|
ownership: &BranchOwnershipClaims,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let ctx = open_with_verify(project)?;
|
let ctx = open_with_verify(project)?;
|
||||||
|
assure_open_workspace_mode(&ctx).context("Unapply a patch requires open workspace mode")?;
|
||||||
let mut guard = project.exclusive_worktree_access();
|
let mut guard = project.exclusive_worktree_access();
|
||||||
let _ = ctx.project().create_snapshot(
|
let _ = ctx.project().create_snapshot(
|
||||||
SnapshotDetails::new(OperationKind::DiscardHunk),
|
SnapshotDetails::new(OperationKind::DiscardHunk),
|
||||||
@ -206,6 +226,8 @@ impl VirtualBranchActions {
|
|||||||
|
|
||||||
pub fn reset_files(&self, project: &Project, files: &Vec<String>) -> Result<()> {
|
pub fn reset_files(&self, project: &Project, files: &Vec<String>) -> Result<()> {
|
||||||
let ctx = open_with_verify(project)?;
|
let ctx = open_with_verify(project)?;
|
||||||
|
assure_open_workspace_mode(&ctx)
|
||||||
|
.context("Resetting a file requires open workspace mode")?;
|
||||||
let mut guard = project.exclusive_worktree_access();
|
let mut guard = project.exclusive_worktree_access();
|
||||||
let _ = ctx.project().create_snapshot(
|
let _ = ctx.project().create_snapshot(
|
||||||
SnapshotDetails::new(OperationKind::DiscardFile),
|
SnapshotDetails::new(OperationKind::DiscardFile),
|
||||||
@ -222,6 +244,8 @@ impl VirtualBranchActions {
|
|||||||
ownership: &BranchOwnershipClaims,
|
ownership: &BranchOwnershipClaims,
|
||||||
) -> Result<git2::Oid> {
|
) -> Result<git2::Oid> {
|
||||||
let ctx = open_with_verify(project)?;
|
let ctx = open_with_verify(project)?;
|
||||||
|
assure_open_workspace_mode(&ctx)
|
||||||
|
.context("Amending a commit requires open workspace mode")?;
|
||||||
let mut guard = project.exclusive_worktree_access();
|
let mut guard = project.exclusive_worktree_access();
|
||||||
let _ = ctx.project().create_snapshot(
|
let _ = ctx.project().create_snapshot(
|
||||||
SnapshotDetails::new(OperationKind::AmendCommit),
|
SnapshotDetails::new(OperationKind::AmendCommit),
|
||||||
@ -239,6 +263,8 @@ impl VirtualBranchActions {
|
|||||||
ownership: &BranchOwnershipClaims,
|
ownership: &BranchOwnershipClaims,
|
||||||
) -> Result<git2::Oid> {
|
) -> Result<git2::Oid> {
|
||||||
let ctx = open_with_verify(project)?;
|
let ctx = open_with_verify(project)?;
|
||||||
|
assure_open_workspace_mode(&ctx)
|
||||||
|
.context("Amending a commit requires open workspace mode")?;
|
||||||
let mut guard = project.exclusive_worktree_access();
|
let mut guard = project.exclusive_worktree_access();
|
||||||
let _ = ctx.project().create_snapshot(
|
let _ = ctx.project().create_snapshot(
|
||||||
SnapshotDetails::new(OperationKind::MoveCommitFile),
|
SnapshotDetails::new(OperationKind::MoveCommitFile),
|
||||||
@ -255,6 +281,8 @@ impl VirtualBranchActions {
|
|||||||
commit_oid: git2::Oid,
|
commit_oid: git2::Oid,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let ctx = open_with_verify(project)?;
|
let ctx = open_with_verify(project)?;
|
||||||
|
assure_open_workspace_mode(&ctx)
|
||||||
|
.context("Undoing a commit requires open workspace mode")?;
|
||||||
let mut guard = project.exclusive_worktree_access();
|
let mut guard = project.exclusive_worktree_access();
|
||||||
let snapshot_tree = ctx.project().prepare_snapshot(guard.read_permission());
|
let snapshot_tree = ctx.project().prepare_snapshot(guard.read_permission());
|
||||||
let result: Result<()> =
|
let result: Result<()> =
|
||||||
@ -278,6 +306,8 @@ impl VirtualBranchActions {
|
|||||||
offset: i32,
|
offset: i32,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let ctx = open_with_verify(project)?;
|
let ctx = open_with_verify(project)?;
|
||||||
|
assure_open_workspace_mode(&ctx)
|
||||||
|
.context("Inserting a blank commit requires open workspace mode")?;
|
||||||
let mut guard = project.exclusive_worktree_access();
|
let mut guard = project.exclusive_worktree_access();
|
||||||
let _ = ctx.project().create_snapshot(
|
let _ = ctx.project().create_snapshot(
|
||||||
SnapshotDetails::new(OperationKind::InsertBlankCommit),
|
SnapshotDetails::new(OperationKind::InsertBlankCommit),
|
||||||
@ -294,6 +324,8 @@ impl VirtualBranchActions {
|
|||||||
offset: i32,
|
offset: i32,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let ctx = open_with_verify(project)?;
|
let ctx = open_with_verify(project)?;
|
||||||
|
assure_open_workspace_mode(&ctx)
|
||||||
|
.context("Reordering a commit requires open workspace mode")?;
|
||||||
let mut guard = project.exclusive_worktree_access();
|
let mut guard = project.exclusive_worktree_access();
|
||||||
let _ = ctx.project().create_snapshot(
|
let _ = ctx.project().create_snapshot(
|
||||||
SnapshotDetails::new(OperationKind::ReorderCommit),
|
SnapshotDetails::new(OperationKind::ReorderCommit),
|
||||||
@ -309,6 +341,8 @@ impl VirtualBranchActions {
|
|||||||
target_commit_oid: git2::Oid,
|
target_commit_oid: git2::Oid,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let ctx = open_with_verify(project)?;
|
let ctx = open_with_verify(project)?;
|
||||||
|
assure_open_workspace_mode(&ctx)
|
||||||
|
.context("Resetting a branch requires open workspace mode")?;
|
||||||
let mut guard = project.exclusive_worktree_access();
|
let mut guard = project.exclusive_worktree_access();
|
||||||
let _ = ctx.project().create_snapshot(
|
let _ = ctx.project().create_snapshot(
|
||||||
SnapshotDetails::new(OperationKind::UndoCommit),
|
SnapshotDetails::new(OperationKind::UndoCommit),
|
||||||
@ -323,6 +357,8 @@ impl VirtualBranchActions {
|
|||||||
branch_id: BranchId,
|
branch_id: BranchId,
|
||||||
) -> Result<ReferenceName> {
|
) -> Result<ReferenceName> {
|
||||||
let ctx = open_with_verify(project)?;
|
let ctx = open_with_verify(project)?;
|
||||||
|
assure_open_workspace_mode(&ctx)
|
||||||
|
.context("Converting branch to a real branch requires open workspace mode")?;
|
||||||
let mut guard = project.exclusive_worktree_access();
|
let mut guard = project.exclusive_worktree_access();
|
||||||
let snapshot_tree = ctx.project().prepare_snapshot(guard.read_permission());
|
let snapshot_tree = ctx.project().prepare_snapshot(guard.read_permission());
|
||||||
let branch_manager = ctx.branch_manager();
|
let branch_manager = ctx.branch_manager();
|
||||||
@ -348,6 +384,8 @@ impl VirtualBranchActions {
|
|||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let helper = Helper::default();
|
let helper = Helper::default();
|
||||||
let ctx = open_with_verify(project)?;
|
let ctx = open_with_verify(project)?;
|
||||||
|
assure_open_workspace_mode(&ctx)
|
||||||
|
.context("Pushing a branch requires open workspace mode")?;
|
||||||
branch::push(&ctx, branch_id, with_force, &helper, askpass)
|
branch::push(&ctx, branch_id, with_force, &helper, askpass)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -372,6 +410,8 @@ impl VirtualBranchActions {
|
|||||||
commit_oid: git2::Oid,
|
commit_oid: git2::Oid,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let ctx = open_with_verify(project)?;
|
let ctx = open_with_verify(project)?;
|
||||||
|
assure_open_workspace_mode(&ctx)
|
||||||
|
.context("Squashing a commit requires open workspace mode")?;
|
||||||
let mut guard = project.exclusive_worktree_access();
|
let mut guard = project.exclusive_worktree_access();
|
||||||
let _ = ctx.project().create_snapshot(
|
let _ = ctx.project().create_snapshot(
|
||||||
SnapshotDetails::new(OperationKind::SquashCommit),
|
SnapshotDetails::new(OperationKind::SquashCommit),
|
||||||
@ -388,6 +428,8 @@ impl VirtualBranchActions {
|
|||||||
message: &str,
|
message: &str,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let ctx = open_with_verify(project)?;
|
let ctx = open_with_verify(project)?;
|
||||||
|
assure_open_workspace_mode(&ctx)
|
||||||
|
.context("Updating a commit message requires open workspace mode")?;
|
||||||
let mut guard = project.exclusive_worktree_access();
|
let mut guard = project.exclusive_worktree_access();
|
||||||
let _ = ctx.project().create_snapshot(
|
let _ = ctx.project().create_snapshot(
|
||||||
SnapshotDetails::new(OperationKind::UpdateCommitMessage),
|
SnapshotDetails::new(OperationKind::UpdateCommitMessage),
|
||||||
@ -434,6 +476,7 @@ impl VirtualBranchActions {
|
|||||||
commit_oid: git2::Oid,
|
commit_oid: git2::Oid,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let ctx = open_with_verify(project)?;
|
let ctx = open_with_verify(project)?;
|
||||||
|
assure_open_workspace_mode(&ctx).context("Moving a commit requires open workspace mode")?;
|
||||||
let mut guard = project.exclusive_worktree_access();
|
let mut guard = project.exclusive_worktree_access();
|
||||||
let _ = ctx.project().create_snapshot(
|
let _ = ctx.project().create_snapshot(
|
||||||
SnapshotDetails::new(OperationKind::MoveCommit),
|
SnapshotDetails::new(OperationKind::MoveCommit),
|
||||||
@ -449,6 +492,8 @@ impl VirtualBranchActions {
|
|||||||
remote: Option<RemoteRefname>,
|
remote: Option<RemoteRefname>,
|
||||||
) -> Result<BranchId> {
|
) -> Result<BranchId> {
|
||||||
let ctx = open_with_verify(project)?;
|
let ctx = open_with_verify(project)?;
|
||||||
|
assure_open_workspace_mode(&ctx)
|
||||||
|
.context("Creating a virtual branch from a branch open workspace mode")?;
|
||||||
let branch_manager = ctx.branch_manager();
|
let branch_manager = ctx.branch_manager();
|
||||||
let mut guard = project.exclusive_worktree_access();
|
let mut guard = project.exclusive_worktree_access();
|
||||||
branch_manager
|
branch_manager
|
||||||
|
@ -6,6 +6,7 @@ use gitbutler_branch::{
|
|||||||
};
|
};
|
||||||
use gitbutler_command_context::CommandContext;
|
use gitbutler_command_context::CommandContext;
|
||||||
use gitbutler_diff::{diff_files_into_hunks, GitHunk, Hunk, HunkHash};
|
use gitbutler_diff::{diff_files_into_hunks, GitHunk, Hunk, HunkHash};
|
||||||
|
use gitbutler_operating_modes::assure_open_workspace_mode;
|
||||||
use gitbutler_project::access::WorktreeWritePermission;
|
use gitbutler_project::access::WorktreeWritePermission;
|
||||||
use gitbutler_repo::RepositoryExt;
|
use gitbutler_repo::RepositoryExt;
|
||||||
|
|
||||||
@ -32,6 +33,8 @@ pub fn get_applied_status(
|
|||||||
ctx: &CommandContext,
|
ctx: &CommandContext,
|
||||||
perm: Option<&mut WorktreeWritePermission>,
|
perm: Option<&mut WorktreeWritePermission>,
|
||||||
) -> Result<VirtualBranchesStatus> {
|
) -> Result<VirtualBranchesStatus> {
|
||||||
|
assure_open_workspace_mode(ctx)
|
||||||
|
.context("Getting applied status requires open workspace mode")?;
|
||||||
let integration_commit = get_workspace_head(ctx)?;
|
let integration_commit = get_workspace_head(ctx)?;
|
||||||
let mut virtual_branches = ctx
|
let mut virtual_branches = ctx
|
||||||
.project()
|
.project()
|
||||||
|
@ -16,6 +16,7 @@ use gitbutler_command_context::CommandContext;
|
|||||||
use gitbutler_commit::{commit_ext::CommitExt, commit_headers::HasCommitHeaders};
|
use gitbutler_commit::{commit_ext::CommitExt, commit_headers::HasCommitHeaders};
|
||||||
use gitbutler_diff::{trees, GitHunk, Hunk};
|
use gitbutler_diff::{trees, GitHunk, Hunk};
|
||||||
use gitbutler_error::error::{Code, Marker};
|
use gitbutler_error::error::{Code, Marker};
|
||||||
|
use gitbutler_operating_modes::assure_open_workspace_mode;
|
||||||
use gitbutler_project::access::WorktreeWritePermission;
|
use gitbutler_project::access::WorktreeWritePermission;
|
||||||
use gitbutler_reference::{normalize_branch_name, Refname, RemoteRefname};
|
use gitbutler_reference::{normalize_branch_name, Refname, RemoteRefname};
|
||||||
use gitbutler_repo::{
|
use gitbutler_repo::{
|
||||||
@ -258,6 +259,8 @@ pub fn list_virtual_branches(
|
|||||||
// that conditionally write things.
|
// that conditionally write things.
|
||||||
perm: &mut WorktreeWritePermission,
|
perm: &mut WorktreeWritePermission,
|
||||||
) -> Result<(Vec<VirtualBranch>, Vec<gitbutler_diff::FileDiff>)> {
|
) -> Result<(Vec<VirtualBranch>, Vec<gitbutler_diff::FileDiff>)> {
|
||||||
|
assure_open_workspace_mode(ctx)
|
||||||
|
.context("Listing virtual branches requires open workspace mode")?;
|
||||||
let mut branches: Vec<VirtualBranch> = Vec::new();
|
let mut branches: Vec<VirtualBranch> = Vec::new();
|
||||||
|
|
||||||
let vb_state = ctx.project().virtual_branches();
|
let vb_state = ctx.project().virtual_branches();
|
||||||
|
12
crates/gitbutler-operating-modes/Cargo.toml
Normal file
12
crates/gitbutler-operating-modes/Cargo.toml
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
[package]
|
||||||
|
name = "gitbutler-operating-modes"
|
||||||
|
version = "0.0.0"
|
||||||
|
edition = "2021"
|
||||||
|
authors = ["GitButler <gitbutler@gitbutler.com>"]
|
||||||
|
publish = false
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
serde = { workspace = true, features = ["std"] }
|
||||||
|
git2.workspace = true
|
||||||
|
anyhow.workspace = true
|
||||||
|
gitbutler-command-context.workspace = true
|
38
crates/gitbutler-operating-modes/src/lib.rs
Normal file
38
crates/gitbutler-operating-modes/src/lib.rs
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
use anyhow::{bail, Context, Result};
|
||||||
|
use gitbutler_command_context::CommandContext;
|
||||||
|
|
||||||
|
/// Operating Modes:
|
||||||
|
/// Gitbutler currently has two main operating modes:
|
||||||
|
/// - `in workspace mode`: When the app is on the gitbutler/integration branch.
|
||||||
|
/// This is when normal operations can be performed.
|
||||||
|
/// - `outside workspace mode`: When the user has left the gitbutler/integration
|
||||||
|
/// branch to perform regular git commands.
|
||||||
|
|
||||||
|
const INTEGRATION_BRANCH_REF: &str = "refs/heads/gitbutler/integration";
|
||||||
|
|
||||||
|
pub fn in_open_workspace_mode(ctx: &CommandContext) -> Result<bool> {
|
||||||
|
let head_ref = ctx.repository().head().context("failed to get head")?;
|
||||||
|
let head_ref_name = head_ref.name().context("failed to get head name")?;
|
||||||
|
|
||||||
|
Ok(head_ref_name == INTEGRATION_BRANCH_REF)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn assure_open_workspace_mode(ctx: &CommandContext) -> Result<()> {
|
||||||
|
if in_open_workspace_mode(ctx)? {
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
bail!("Unexpected state: cannot perform operation on non-integration branch")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn in_outside_workspace_mode(ctx: &CommandContext) -> Result<bool> {
|
||||||
|
in_open_workspace_mode(ctx).map(|open_mode| !open_mode)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn assure_outside_workspace_mode(ctx: &CommandContext) -> Result<()> {
|
||||||
|
if in_open_workspace_mode(ctx)? {
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
bail!("Unexpected state: cannot perform operation on non-integration branch")
|
||||||
|
}
|
||||||
|
}
|
@ -24,6 +24,7 @@ gitbutler-project.workspace = true
|
|||||||
gitbutler-user.workspace = true
|
gitbutler-user.workspace = true
|
||||||
gitbutler-reference.workspace = true
|
gitbutler-reference.workspace = true
|
||||||
gitbutler-error.workspace = true
|
gitbutler-error.workspace = true
|
||||||
|
gitbutler-operating-modes.workspace = true
|
||||||
|
|
||||||
backoff = "0.4.0"
|
backoff = "0.4.0"
|
||||||
notify = { version = "6.0.1" }
|
notify = { version = "6.0.1" }
|
||||||
|
@ -4,6 +4,7 @@ use anyhow::{Context, Result};
|
|||||||
use gitbutler_branch_actions::{VirtualBranchActions, VirtualBranches};
|
use gitbutler_branch_actions::{VirtualBranchActions, VirtualBranches};
|
||||||
use gitbutler_command_context::CommandContext;
|
use gitbutler_command_context::CommandContext;
|
||||||
use gitbutler_error::error::Marker;
|
use gitbutler_error::error::Marker;
|
||||||
|
use gitbutler_operating_modes::in_open_workspace_mode;
|
||||||
use gitbutler_oplog::{
|
use gitbutler_oplog::{
|
||||||
entry::{OperationKind, SnapshotDetails},
|
entry::{OperationKind, SnapshotDetails},
|
||||||
OplogExt,
|
OplogExt,
|
||||||
@ -79,8 +80,22 @@ impl Handler {
|
|||||||
(self.send_event)(event).context("failed to send event")
|
(self.send_event)(event).context("failed to send event")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn open_command_context(&self, project_id: ProjectId) -> Result<CommandContext> {
|
||||||
|
let project = self
|
||||||
|
.projects
|
||||||
|
.get(project_id)
|
||||||
|
.context("failed to get project")?;
|
||||||
|
CommandContext::open(&project).context("Failed to create a command context")
|
||||||
|
}
|
||||||
|
|
||||||
#[instrument(skip(self, project_id))]
|
#[instrument(skip(self, project_id))]
|
||||||
fn calculate_virtual_branches(&self, project_id: ProjectId) -> Result<()> {
|
fn calculate_virtual_branches(&self, project_id: ProjectId) -> Result<()> {
|
||||||
|
let ctx = self.open_command_context(project_id)?;
|
||||||
|
// Skip if we're not on the open workspace mode
|
||||||
|
if !in_open_workspace_mode(&ctx)? {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
let project = self
|
let project = self
|
||||||
.projects
|
.projects
|
||||||
.get(project_id)
|
.get(project_id)
|
||||||
@ -107,6 +122,12 @@ impl Handler {
|
|||||||
|
|
||||||
#[instrument(skip(self, paths, project_id), fields(paths = paths.len()))]
|
#[instrument(skip(self, paths, project_id), fields(paths = paths.len()))]
|
||||||
fn recalculate_everything(&self, paths: Vec<PathBuf>, project_id: ProjectId) -> Result<()> {
|
fn recalculate_everything(&self, paths: Vec<PathBuf>, project_id: ProjectId) -> Result<()> {
|
||||||
|
let ctx = self.open_command_context(project_id)?;
|
||||||
|
// Skip if we're not on the open workspace mode
|
||||||
|
if !in_open_workspace_mode(&ctx)? {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
self.maybe_create_snapshot(project_id).ok();
|
self.maybe_create_snapshot(project_id).ok();
|
||||||
self.calculate_virtual_branches(project_id)?;
|
self.calculate_virtual_branches(project_id)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -135,10 +156,6 @@ impl Handler {
|
|||||||
.projects
|
.projects
|
||||||
.get(project_id)
|
.get(project_id)
|
||||||
.context("failed to get project")?;
|
.context("failed to get project")?;
|
||||||
let open_projects_repository = || {
|
|
||||||
CommandContext::open(&project.clone())
|
|
||||||
.context("failed to open project repository for project")
|
|
||||||
};
|
|
||||||
|
|
||||||
for path in paths {
|
for path in paths {
|
||||||
let Some(file_name) = path.to_str() else {
|
let Some(file_name) = path.to_str() else {
|
||||||
@ -152,16 +169,17 @@ impl Handler {
|
|||||||
self.emit_app_event(Change::GitActivity(project.id))?;
|
self.emit_app_event(Change::GitActivity(project.id))?;
|
||||||
}
|
}
|
||||||
"HEAD" => {
|
"HEAD" => {
|
||||||
let ctx = open_projects_repository()?;
|
let ctx = CommandContext::open(&project)
|
||||||
let head_ref = ctx.repository().head().context("failed to get head")?;
|
.context("Failed to create a command context")?;
|
||||||
let head_ref_name = head_ref.name().context("failed to get head name")?;
|
if in_open_workspace_mode(&ctx)? {
|
||||||
if head_ref_name != "refs/heads/gitbutler/integration" {
|
|
||||||
let mut integration_reference = ctx.repository().find_reference(
|
let mut integration_reference = ctx.repository().find_reference(
|
||||||
&Refname::from(LocalRefname::new("gitbutler/integration", None))
|
&Refname::from(LocalRefname::new("gitbutler/integration", None))
|
||||||
.to_string(),
|
.to_string(),
|
||||||
)?;
|
)?;
|
||||||
integration_reference.delete()?;
|
integration_reference.delete()?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let head_ref = ctx.repository().head().context("failed to get head")?;
|
||||||
if let Some(head) = head_ref.name() {
|
if let Some(head) = head_ref.name() {
|
||||||
self.emit_app_event(Change::GitHead {
|
self.emit_app_event(Change::GitHead {
|
||||||
project_id,
|
project_id,
|
||||||
|
Loading…
Reference in New Issue
Block a user