-- | @upgrade.commit@ handler.
module Unison.Codebase.Editor.HandleInput.CommitUpgrade
  ( handleCommitUpgrade,
  )
where

import U.Codebase.Sqlite.Project qualified
import U.Codebase.Sqlite.ProjectBranch (ProjectBranch (..))
import U.Codebase.Sqlite.Queries qualified as Queries
import Unison.Cli.Monad (Cli)
import Unison.Cli.Monad qualified as Cli
import Unison.Cli.MonadUtils qualified as Cli
import Unison.Cli.ProjectUtils qualified as ProjectUtils
import Unison.Codebase.Editor.HandleInput.DeleteBranch qualified as DeleteBranch
import Unison.Codebase.Editor.HandleInput.Merge2 qualified as Merge
import Unison.Codebase.Editor.Output qualified as Output
import Unison.Merge.TwoWay (TwoWay (..))
import Unison.Prelude
import Unison.Project (ProjectAndBranch (..))

-- Note: this implementation is similar to `merge.commit`.

handleCommitUpgrade :: Cli ()
handleCommitUpgrade :: Cli ()
handleCommitUpgrade = do
  ProjectAndBranch Project ProjectBranch
upgradeProjectAndBranch <- Cli (ProjectAndBranch Project ProjectBranch)
Cli.getCurrentProjectAndBranch

  -- Assert that this is an "upgrade" branch, get its parent (which is the branch we were on when we ran `upgrade`),
  -- and switch to the parent.

  ProjectBranchId
parentBranchId <-
    ProjectBranch -> Maybe ProjectBranchId
ProjectUtils.getUpgradeBranchParent ProjectAndBranch Project ProjectBranch
upgradeProjectAndBranch.branch
      Maybe ProjectBranchId
-> (Maybe ProjectBranchId -> Cli ProjectBranchId)
-> Cli ProjectBranchId
forall a b. a -> (a -> b) -> b
& Cli ProjectBranchId -> Maybe ProjectBranchId -> Cli ProjectBranchId
forall (m :: * -> *) a. Applicative m => m a -> Maybe a -> m a
onNothing (Output -> Cli ProjectBranchId
forall a. Output -> Cli a
Cli.returnEarly Output
Output.NoUpgradeInProgress)

  ProjectBranch
parentBranch <-
    Transaction ProjectBranch -> Cli ProjectBranch
forall a. Transaction a -> Cli a
Cli.runTransaction do
      ProjectBranch
parentBranch <- ProjectId -> ProjectBranchId -> Transaction ProjectBranch
Queries.expectProjectBranch ProjectAndBranch Project ProjectBranch
upgradeProjectAndBranch.project.projectId ProjectBranchId
parentBranchId
      pure ProjectBranch
parentBranch
  ProjectAndBranch ProjectId ProjectBranchId -> Cli ()
Cli.switchProject (ProjectId
-> ProjectBranchId -> ProjectAndBranch ProjectId ProjectBranchId
forall a b. a -> b -> ProjectAndBranch a b
ProjectAndBranch ProjectBranch
parentBranch.projectId ProjectBranch
parentBranch.branchId)

  -- Merge the upgrade branch into the parent

  TwoWay (ProjectAndBranch Project ProjectBranch) -> Cli ()
Merge.doMergeLocalBranch
    TwoWay
      { $sel:alice:TwoWay :: ProjectAndBranch Project ProjectBranch
alice = Project -> ProjectBranch -> ProjectAndBranch Project ProjectBranch
forall a b. a -> b -> ProjectAndBranch a b
ProjectAndBranch ProjectAndBranch Project ProjectBranch
upgradeProjectAndBranch.project ProjectBranch
parentBranch,
        $sel:bob:TwoWay :: ProjectAndBranch Project ProjectBranch
bob = ProjectAndBranch Project ProjectBranch
upgradeProjectAndBranch
      }

  -- Delete the upgrade branch

  HasCallStack => ProjectAndBranch Project ProjectBranch -> Cli ()
ProjectAndBranch Project ProjectBranch -> Cli ()
DeleteBranch.doDeleteProjectBranch ProjectAndBranch Project ProjectBranch
upgradeProjectAndBranch