Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 6 additions & 20 deletions crates/but-api/src/branch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -857,7 +857,7 @@ pub fn apply_only_with_perm(
perm: &mut RepoExclusive,
) -> anyhow::Result<but_workspace::branch::apply::Outcome> {
let mut meta = ctx.meta()?;
let (repo, mut ws, _db) = ctx.workspace_mut_and_db_with_perm(perm)?;
let (repo, ws, _db) = ctx.workspace_mut_and_db_with_perm(perm)?;
let out = but_workspace::branch::apply(
existing_branch,
ws.clone(),
Expand All @@ -875,9 +875,6 @@ pub fn apply_only_with_perm(
},
)?;

if out.status.persisted_mutation() {
*ws = out.workspace.clone();
}
Ok(out)
}

Expand Down Expand Up @@ -1030,15 +1027,15 @@ pub fn branch_create_with_perm(
DryRun::No,
);
let mut meta = ctx.meta()?;
let (repo, mut ws, _) = ctx.workspace_mut_and_db_with_perm(perm)?;
let (repo, ws, _) = ctx.workspace_mut_and_db_with_perm(perm)?;
let checkout_after_create = checkout_anchor_ref.as_ref().is_some_and(|anchor_ref| {
repo.head_name()
.ok()
.flatten()
.as_ref()
.is_some_and(|head_ref| head_ref == anchor_ref)
});
let new_ws = but_workspace::branch::create_reference(
but_workspace::branch::create_reference(
new_ref.as_ref(),
anchor,
&repo,
Expand All @@ -1047,7 +1044,6 @@ pub fn branch_create_with_perm(
|_| StackId::generate(),
order,
)?;
*ws = new_ws.into_owned();
drop(ws);
drop(repo);
drop(meta);
Expand Down Expand Up @@ -1179,7 +1175,7 @@ pub fn branch_remove_with_perm(
}

let mut meta = ctx.meta()?;
let (mut repo, mut ws, _) = ctx.workspace_mut_and_db_with_perm(perm)?;
let (mut repo, ws, _) = ctx.workspace_mut_and_db_with_perm(perm)?;
let new_ws = if moved_head {
None
} else {
Expand All @@ -1194,8 +1190,7 @@ pub fn branch_remove_with_perm(
},
)?
};
let changed = if let Some(new_ws) = new_ws {
*ws = new_ws;
let changed = if new_ws.is_some() {
true
} else {
// Standalone branches are intentionally absent from the workspace
Expand All @@ -1205,16 +1200,7 @@ pub fn branch_remove_with_perm(
ref_name.as_ref(),
)?;
let deleted_meta = meta.remove(ref_name.as_ref())?;
if deleted_ref || deleted_meta {
let new_ws = ws
.graph
.redo_traversal_with_overlay(&repo, &meta, Default::default())?
.into_workspace()?;
*ws = new_ws;
true
} else {
false
}
deleted_ref || deleted_meta
};
drop(ws);
drop(repo);
Expand Down
1 change: 1 addition & 0 deletions crates/but-api/src/commit/uncommit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -464,6 +464,7 @@ pub fn commit_uncommit_changes_from_commits_only_with_perm(
let context_lines = ctx.settings.context_lines;
let mut meta = ctx.meta()?;
let (repo, mut ws, mut db) = ctx.workspace_mut_and_db_mut_with_perm(perm)?;
let mut ws = &mut ws;

let surfaced =
SurfacedHunks::record_before(assign_to, dry_run, &mut db, &repo, &ws, context_lines)?;
Expand Down
12 changes: 4 additions & 8 deletions crates/but-api/src/legacy/stack.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,15 @@ pub fn create_branch(
ctx.snapshot_create_dependent_branch(&normalized_name, guard.write_permission())
.ok();

let (repo, mut ws, _) = ctx.workspace_mut_and_db_with_perm(guard.write_permission())?;
let (repo, ws, _) = ctx.workspace_mut_and_db_with_perm(guard.write_permission())?;
let stack = ws.try_find_stack_by_id(stack_id)?;
if request.preceding_head.is_some() {
return Err(anyhow!(
"BUG: cannot have preceding head name set - let's use the new API instead"
));
}

let new_ws = but_workspace::branch::create_reference(
but_workspace::branch::create_reference(
new_ref.as_ref(),
{
use but_workspace::branch::create_reference::Position::Above;
Expand Down Expand Up @@ -72,7 +72,6 @@ pub fn create_branch(
None, // order - not used for dependent branches
)?;

*ws = new_ws.into_owned();
Ok(())
}

Expand All @@ -89,8 +88,8 @@ pub fn remove_branch_only(
.to_full_name(branch_name)
.map_err(anyhow::Error::from)?;
let mut meta = ctx.meta()?;
let (mut repo, mut ws, _) = ctx.workspace_mut_and_db_with_perm(perm)?;
let new_ws = but_workspace::branch::remove_reference(
let (mut repo, ws, _) = ctx.workspace_mut_and_db_with_perm(perm)?;
but_workspace::branch::remove_reference(
ref_name.as_ref(),
&mut repo,
&ws,
Expand All @@ -101,9 +100,6 @@ pub fn remove_branch_only(
},
)?;

if let Some(new_ws) = new_ws {
*ws = new_ws;
}
Ok(())
}

Expand Down
16 changes: 7 additions & 9 deletions crates/but-api/src/legacy/virtual_branches.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ pub fn create_virtual_branch(
.map_err(anyhow::Error::from)?;

let mut meta = ctx.meta()?;
let (_guard, repo, mut ws, _) = ctx.workspace_mut_and_db()?;
let (_guard, repo, ws, _) = ctx.workspace_mut_and_db()?;
let new_ws = but_workspace::branch::create_reference(
new_ref.as_ref(),
None,
Expand Down Expand Up @@ -92,7 +92,6 @@ pub fn create_virtual_branch(
is_checked_out: false,
};

*ws = new_ws.into_owned();
out
};
Ok(stack_entry)
Expand Down Expand Up @@ -121,7 +120,7 @@ pub fn delete_local_branch(
bail_precondition!("Cannot delete a branch that is applied in workspace");
}

if let Some(new_ws) = but_workspace::branch::remove_reference(
if but_workspace::branch::remove_reference(
branch_refname.as_ref(),
&mut repo,
&ws,
Expand All @@ -130,9 +129,9 @@ pub fn delete_local_branch(
avoid_anonymous_stacks: false,
keep_metadata: false,
},
)? {
*ws = new_ws;
} else {
)?
.is_none()
{
but_workspace::branch::remove_reference::delete_local_branch(
&mut repo,
branch_refname.as_ref(),
Expand Down Expand Up @@ -558,13 +557,13 @@ fn unapply_stack_v3_with_perm(

let single_branch = ctx.settings.feature_flags.single_branch;
let mut meta = ctx.legacy_meta_mut(perm)?;
let (repo, mut ws, _) = ctx.workspace_mut_and_db_with_perm(perm)?;
let (repo, ws, _) = ctx.workspace_mut_and_db_with_perm(perm)?;
let workspace_disposition = if single_branch {
WorkspaceDisposition::PreventUnnecessaryWorkspaceReferencesKeepWorkspaceCommit
} else {
WorkspaceDisposition::KeepWorkspaceCommit
};
let outcome = but_workspace::branch::unapply(
but_workspace::branch::unapply(
branch_to_unapply.as_ref(),
&ws,
&repo,
Expand All @@ -573,7 +572,6 @@ fn unapply_stack_v3_with_perm(
workspace_disposition,
},
)?;
*ws = outcome.workspace.into_owned();
// Keeping the workspace merge commit can make legacy reconciliation infer the
// removed stack as applied again, so persist the explicit workspace metadata.
meta.write_unreconciled()?;
Expand Down
10 changes: 2 additions & 8 deletions crates/but-api/src/workspace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ pub fn workspace_recreate_with_perm(
Vec::new()
} else {
let mut meta = ctx.meta()?;
let (repo, mut ws, db) = ctx.workspace_mut_and_db_with_perm(perm)?;
let (repo, ws, db) = ctx.workspace_mut_and_db_with_perm(perm)?;

let previously_applied_stack_heads: Vec<gix::refs::FullName> = {
let workspace_ref: gix::refs::FullName = but_core::WORKSPACE_REF_NAME.try_into()?;
Expand Down Expand Up @@ -118,9 +118,7 @@ pub fn workspace_recreate_with_perm(
..Default::default()
},
)?;
if outcome.status.persisted_mutation() {
*ws = outcome.workspace.clone();
} else {
if !outcome.status.persisted_mutation() {
anyhow::bail!(
"BUG: failed to apply head ref ({head_name}). Failed with {:?}",
outcome.status
Expand Down Expand Up @@ -148,10 +146,6 @@ pub fn workspace_recreate_with_perm(
if !apply_outcome.conflicting_stacks.is_empty() {
conflicting_stacks.push(stack_ref);
}

if apply_outcome.status.persisted_mutation() {
*ws = apply_outcome.workspace.clone();
}
}

conflicting_stacks
Expand Down
33 changes: 11 additions & 22 deletions crates/but-ctx/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -546,6 +546,11 @@ impl Context {

/// Trampolines that create new uncached instances of major types.
impl Context {
/// Invalidates the workspace cache, if it is present.
pub fn invalidate_workspace(&mut self, _perm: &mut RepoExclusive) {
self.workspace.take();
}

/// Create a cached workspace as seen from the current HEAD for editing, and return it,
/// along with `(guard, &mut repo, &mut ws, &mut db)`.
/// The guard ensures exclusive process-wide access to the repository.
Expand All @@ -561,7 +566,7 @@ impl Context {
) -> anyhow::Result<(
RepoExclusiveGuard,
cell::RefMut<'_, gix::Repository>,
cell::RefMut<'_, but_graph::Workspace>,
but_graph::Workspace,
cell::RefMut<'_, but_db::DbHandle>,
)> {
let mut guard = self.exclusive_worktree_access();
Expand All @@ -586,21 +591,13 @@ impl Context {
_perm: &mut RepoExclusive,
) -> anyhow::Result<(
cell::RefMut<'_, gix::Repository>,
cell::RefMut<'_, but_graph::Workspace>,
but_graph::Workspace,
cell::RefMut<'_, but_db::DbHandle>,
)> {
if let Ok(cached) =
cell::RefMut::filter_map(self.workspace.try_borrow_mut()?, |opt| opt.as_mut())
{
if let Some(cached) = self.workspace.take() {
return Ok((self.repo.get_mut()?, cached, self.db.get_cache_mut()?));
}
let ws = self.workspace_from_head()?;
{
let mut value = self.workspace.try_borrow_mut()?;
*value = Some(ws);
}
let ws = cell::RefMut::filter_map(self.workspace.borrow_mut(), |opt| opt.as_mut())
.unwrap_or_else(|_| unreachable!("just set the value"));
Ok((self.repo.get_mut()?, ws, self.db.get_cache_mut()?))
}

Expand Down Expand Up @@ -671,7 +668,7 @@ impl Context {
) -> anyhow::Result<(
RepoExclusiveGuard,
cell::RefMut<'_, gix::Repository>,
cell::RefMut<'_, but_graph::Workspace>,
but_graph::Workspace,
cell::Ref<'_, but_db::DbHandle>,
)> {
let mut guard = self.exclusive_worktree_access();
Expand All @@ -695,21 +692,13 @@ impl Context {
_perm: &RepoExclusive,
) -> anyhow::Result<(
cell::RefMut<'_, gix::Repository>,
cell::RefMut<'_, but_graph::Workspace>,
but_graph::Workspace,
cell::Ref<'_, but_db::DbHandle>,
)> {
if let Ok(cached) =
cell::RefMut::filter_map(self.workspace.try_borrow_mut()?, |opt| opt.as_mut())
{
if let Some(cached) = self.workspace.take() {
return Ok((self.repo.get_mut()?, cached, self.db.get_cache()?));
}
let ws = self.workspace_from_head()?;
{
let mut value = self.workspace.try_borrow_mut()?;
*value = Some(ws);
}
let ws = cell::RefMut::filter_map(self.workspace.borrow_mut(), |opt| opt.as_mut())
.unwrap_or_else(|_| unreachable!("just set the value"));
Ok((self.repo.get_mut()?, ws, self.db.get_cache()?))
}

Expand Down
10 changes: 4 additions & 6 deletions crates/but-debug/src/command/workspace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ pub(crate) fn apply(
let mut ctx = but_ctx::Context::discover(&args.current_dir)?;
let mut guard = ctx.exclusive_worktree_access();
let mut meta = ctx.meta()?;
let (repo, mut ws, _) = ctx.workspace_mut_and_db_with_perm(guard.write_permission())?;
let (repo, ws, _) = ctx.workspace_mut_and_db_with_perm(guard.write_permission())?;
let branch = ref_name(&repo, &mutation_args.ref_name)?;

let outcome = but_workspace::branch::apply(
Expand All @@ -39,8 +39,7 @@ pub(crate) fn apply(
)?;

writeln!(out, "{outcome:#?}")?;
*ws = outcome.workspace;
emit_after(&ws, &mutation_args.debug, err)
emit_after(&outcome.workspace, &mutation_args.debug, err)
}

/// Unapply a branch through `but-workspace`, bypassing app/API wiring.
Expand All @@ -53,7 +52,7 @@ pub(crate) fn unapply(
let mut ctx = but_ctx::Context::discover(&args.current_dir)?;
let mut guard = ctx.exclusive_worktree_access();
let mut meta = ctx.meta()?;
let (repo, mut ws, _) = ctx.workspace_mut_and_db_with_perm(guard.write_permission())?;
let (repo, ws, _) = ctx.workspace_mut_and_db_with_perm(guard.write_permission())?;
let branch = ref_name(&repo, &mutation_args.ref_name)?;

let outcome = but_workspace::branch::unapply(
Expand All @@ -67,8 +66,7 @@ pub(crate) fn unapply(
)?;

writeln!(out, "{outcome:#?}")?;
*ws = outcome.workspace.into_owned();
emit_after(&ws, &mutation_args.debug, err)
emit_after(&outcome.workspace, &mutation_args.debug, err)
}

pub(crate) fn emit_after(
Expand Down
6 changes: 2 additions & 4 deletions crates/but/src/command/legacy/branch/new.rs
Original file line number Diff line number Diff line change
Expand Up @@ -353,7 +353,7 @@ impl NewUnstackedBranchOperation {
//
// this also has the effect of entering the workspace with one branch applied
{
let (repo, mut ws, _db) = ctx.workspace_mut_and_db_with_perm(perm)?;
let (repo, ws, _db) = ctx.workspace_mut_and_db_with_perm(perm)?;
let outcome = but_workspace::branch::apply(
head_name.as_ref(),
ws.clone(),
Expand All @@ -364,9 +364,7 @@ impl NewUnstackedBranchOperation {
..Default::default()
},
)?;
if outcome.status.persisted_mutation() {
*ws = outcome.workspace.clone();
} else {
if !outcome.status.persisted_mutation() {
bail!(
"BUG: failed to apply head ref ({head_name}). Failed with {:?}",
outcome.status
Expand Down
8 changes: 1 addition & 7 deletions crates/but/src/command/legacy/status/tui/operations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,7 @@ pub fn reload_legacy(
) -> anyhow::Result<Vec<StatusOutputLine>> {
let mut guard = ctx.exclusive_worktree_access();

{
let meta = ctx.meta()?;
let project_meta = ctx.project_meta()?;
let (repo, mut ws, mut db) =
ctx.workspace_mut_and_db_mut_with_perm(guard.write_permission())?;
ws.refresh_from_head(&repo, &meta, project_meta, &mut db)?;
}
ctx.invalidate_workspace(guard.write_permission());

let mut new_lines = Vec::new();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -705,7 +705,7 @@ mod behind_count {
// Apply C (forks from M2, 1 behind).
let mut guard = ctx.exclusive_worktree_access();
let mut meta = ctx.meta().unwrap();
let (repo, mut workspace, _) = ctx
let (repo, workspace, _) = ctx
.workspace_mut_and_db_with_perm(guard.write_permission())
.unwrap();
let outcome = but_workspace::branch::apply(
Expand All @@ -720,7 +720,6 @@ mod behind_count {
outcome.status.persisted_mutation(),
"branch C must be applied for the multi-stack behind-count scenario"
);
*workspace = outcome.workspace;
drop((repo, workspace));
drop(guard);

Expand Down
Loading