Skip to content

Commit 2da1dfe

Browse files
authored
Merge pull request #5785 from unisonweb/cp/check-and-set-branch-updates
Add check-and-set when running branch updates
2 parents 02aa4b5 + 1bece7c commit 2da1dfe

File tree

4 files changed

+25
-10
lines changed

4 files changed

+25
-10
lines changed

unison-cli/src/Unison/Cli/Monad.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ data Env = Env
189189
--
190190
-- There's an additional pseudo @"currentPath"@ field lens, for convenience.
191191
data LoopState = LoopState
192-
{ -- the current position in the codebase, with the head being the most recent lcoation.
192+
{ -- the current position in the codebase, with the head being the most recent location.
193193
projectPathStack :: List.NonEmpty PP.ProjectPathIds,
194194
-- TBD
195195
-- , _activeEdits :: Set Branch.EditGuid

unison-cli/src/Unison/Cli/MonadUtils.hs

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -423,16 +423,26 @@ updateProjectBranchRoot :: ProjectBranch -> Text -> (Branch IO -> Cli (Branch IO
423423
updateProjectBranchRoot projectBranch reason f = do
424424
env <- ask
425425
Cli.time "updateProjectBranchRoot" do
426-
old <- getProjectBranchRoot projectBranch
427-
(new, result) <- f old
428-
when (old /= new) do
426+
beforeUpdates <- getProjectBranchRoot projectBranch
427+
(new, result) <- f beforeUpdates
428+
when (beforeUpdates /= new) do
429429
liftIO $ Codebase.putBranch env.codebase new
430-
Cli.runTransaction do
431-
-- TODO: If we transactionally check that the project branch hasn't changed while we were computing the new
432-
-- branch, and if it has, abort the transaction and return an error, then we can
433-
-- remove the single UCM per codebase restriction.
434-
causalHashId <- Q.expectCausalHashIdByCausalHash (Branch.headHash new)
435-
Q.setProjectBranchHead reason projectBranch.projectId projectBranch.branchId causalHashId
430+
Cli.runTransactionWithRollback \rollback -> do
431+
causalHashId <- Q.expectProjectBranchHead projectBranch.projectId projectBranch.branchId
432+
currentHeadHash <- Q.expectCausalHash causalHashId
433+
-- Inside the transaction we ensure that the branch from before the updates matches the current head of the
434+
-- project branch, like a check-and-set operation.
435+
-- If it doesn't, then some other process has updated the branch between when we read it and computed the
436+
-- updates. We should abort and ask the user to try again.
437+
if
438+
| (currentHeadHash == Branch.headHash new) -> do
439+
-- Someone else updated the branch, but they set it to what we wanted to anyways.
440+
pure ()
441+
| (currentHeadHash /= Branch.headHash beforeUpdates) -> do
442+
rollback Output.BranchUpdate'BranchChanged
443+
| otherwise -> do
444+
causalHashId <- Q.expectCausalHashIdByCausalHash (Branch.headHash new)
445+
Q.setProjectBranchHead reason projectBranch.projectId projectBranch.branchId causalHashId
436446
-- The input to this function isn't necessarily the *current* project branch, which is what LSP cares about. But
437447
-- it might be! There's no harm in unconditionally notifying the LSP that the current project branch may have
438448
-- changed, but it is slightly more efficient for us to just do the == comparison here (since otherwise the LSP

unison-cli/src/Unison/Codebase/Editor/Output.hs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -452,6 +452,7 @@ data Output
452452
| OpenCodebaseError CodebasePath OpenCodebaseError
453453
| UCMServerNotRunning
454454
| BranchSquashSuccess ({- source -} ProjectAndBranch Project ProjectBranch) ({- dest branch -} ProjectAndBranch Project ProjectBranch)
455+
| BranchUpdate'BranchChanged
455456

456457
data MoreEntriesThanShown = MoreEntriesThanShown | AllEntriesShown
457458
deriving (Eq, Show)
@@ -694,6 +695,7 @@ isFailure o = case o of
694695
OpenCodebaseError {} -> True
695696
UCMServerNotRunning -> True
696697
BranchSquashSuccess {} -> False
698+
BranchUpdate'BranchChanged {} -> True
697699

698700
isNumberedFailure :: NumberedOutput -> Bool
699701
isNumberedFailure = \case

unison-cli/src/Unison/CommandLine/OutputMessages.hs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2346,6 +2346,9 @@ notifyUser dir = \case
23462346
P.lines
23472347
[ P.wrap $ "I squashed " <> sourceName <> " into " <> destName
23482348
]
2349+
BranchUpdate'BranchChanged -> do
2350+
pure $
2351+
P.wrap "Another process updated the codebase while your command was running, so I didn't apply the update. Please run the command again."
23492352

23502353
prettyShareError :: ShareError -> Pretty
23512354
prettyShareError =

0 commit comments

Comments
 (0)