Skip to content

Commit

Permalink
in delete.namespace, don't worry about endangered definitions in `l…
Browse files Browse the repository at this point in the history
…ib` itself
  • Loading branch information
mitchellwrosen committed Nov 12, 2024
1 parent 78cbe72 commit 5ee4794
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 58 deletions.
13 changes: 7 additions & 6 deletions unison-cli/src/Unison/Codebase/Editor/HandleInput.hs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ import Unison.Codebase.Editor.HandleInput.DebugDefinition qualified as DebugDefi
import Unison.Codebase.Editor.HandleInput.DebugFoldRanges qualified as DebugFoldRanges
import Unison.Codebase.Editor.HandleInput.DebugSynhashTerm (handleDebugSynhashTerm)
import Unison.Codebase.Editor.HandleInput.DeleteBranch (handleDeleteBranch)
import Unison.Codebase.Editor.HandleInput.DeleteNamespace (getEndangeredDependents, handleDeleteNamespace)
import Unison.Codebase.Editor.HandleInput.DeleteProject (handleDeleteProject)
import Unison.Codebase.Editor.HandleInput.EditNamespace (handleEditNamespace)
import Unison.Codebase.Editor.HandleInput.FindAndReplace (handleStructuredFindI, handleStructuredFindReplaceI, handleTextFindI)
Expand Down Expand Up @@ -176,7 +177,6 @@ import Unison.Var (Var)
import Unison.Var qualified as Var
import Unison.WatchKind qualified as WK
import UnliftIO.Directory qualified as Directory
import Unison.Codebase.Editor.HandleInput.DeleteNamespace (handleDeleteNamespace, getEndangeredDependents)

------------------------------------------------------------------------------------------------------------------------
-- Main loop
Expand Down Expand Up @@ -938,7 +938,8 @@ inputDescription input =
UndoI {} -> pure "undo"
ExecuteI s args -> pure ("execute " <> Text.unwords (HQ.toText s : fmap Text.pack args))
IOTestI native hq -> pure (cmd <> HQ.toText hq)
where cmd | native = "io.test.native " | otherwise = "io.test "
where
cmd | native = "io.test.native " | otherwise = "io.test "
IOTestAllI native ->
pure (if native then "io.test.native.all" else "io.test.all")
UpdateBuiltinsI -> pure "builtins.update"
Expand Down Expand Up @@ -1448,17 +1449,17 @@ checkDeletes typesTermsTuples doutput inputs = do
toRel setRef name = R.fromList (fmap (name,) (toList setRef))
let toDelete = fmap (\(_, names, types, terms) -> Names (toRel terms names) (toRel types names)) splitsNames
-- make sure endangered is compeletely contained in paths
projectNames <- Branch.toNames <$> Cli.getCurrentProjectRoot0
currentBranch <- Cli.getCurrentProjectRoot0
let projectNames = Branch.toNames currentBranch
projectNamesSansLib = Branch.toNames (Branch.deleteLibdeps currentBranch)
-- get only once for the entire deletion set
let allTermsToDelete :: Set LabeledDependency
allTermsToDelete = Set.unions (fmap Names.labeledReferences toDelete)
-- get the endangered dependencies for each entity to delete
endangered <-
Cli.runTransaction $
traverse
( \targetToDelete ->
getEndangeredDependents targetToDelete allTermsToDelete projectNames
)
(\targetToDelete -> getEndangeredDependents targetToDelete allTermsToDelete projectNames projectNamesSansLib)
toDelete
-- If the overall dependency map is not completely empty, abort deletion
let endangeredDeletions = List.filter (\m -> not $ null m || Map.foldr (\s b -> null s || b) False m) endangered
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ 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.NamesUtils qualified as Cli
import Unison.Codebase qualified as Codebase
import Unison.Codebase.Branch qualified as Branch
import Unison.Codebase.Branch.Names qualified as Branch
Expand Down Expand Up @@ -52,8 +51,10 @@ handleDeleteNamespace input insistence = \case
(Path.nameFromSplit' $ first (Path.RelativePath' . Path.Relative) p)
(Branch.toNames (Branch.head branch))
afterDelete <- do
names <- Cli.currentNames
endangerments <- Cli.runTransaction (getEndangeredDependents toDelete Set.empty names)
currentBranch <- Cli.getCurrentProjectRoot0
let names = Branch.toNames currentBranch
namesSansLib = Branch.toNames (Branch.deleteLibdeps currentBranch)
endangerments <- Cli.runTransaction (getEndangeredDependents toDelete Set.empty names namesSansLib)
case (null endangerments, insistence) of
(True, _) -> pure (Cli.respond Success)
(False, Force) -> do
Expand Down Expand Up @@ -97,37 +98,37 @@ getEndangeredDependents ::
Set LabeledDependency ->
-- | Names from the current branch
Names ->
-- | Names from the current branch, sans `lib`
Names ->
-- | map from references going extinct to the set of endangered dependents
Sqlite.Transaction (Map LabeledDependency (NESet LabeledDependency))
getEndangeredDependents targetToDelete otherDesiredDeletions rootNames = do
-- names of terms left over after target deletion
let remainingNames :: Names
remainingNames = rootNames `Names.difference` targetToDelete
-- target refs for deletion
let refsToDelete :: Set LabeledDependency
refsToDelete = Names.labeledReferences targetToDelete
-- refs left over after deleting target
let remainingRefs :: Set LabeledDependency
remainingRefs = Names.labeledReferences remainingNames
-- remove the other targets for deletion from the remaining terms
let remainingRefsWithoutOtherTargets :: Set LabeledDependency
remainingRefsWithoutOtherTargets = Set.difference remainingRefs otherDesiredDeletions
getEndangeredDependents targetToDelete otherDesiredDeletions rootNames rootNamesSansLib = do
-- deleting and not left over
let extinct :: Set LabeledDependency
extinct = refsToDelete `Set.difference` remainingRefs
extinct = Names.labeledReferences targetToDelete `Set.difference` refsAfterDeletingTarget rootNames

let accumulateDependents :: LabeledDependency -> Sqlite.Transaction (Map LabeledDependency (Set LabeledDependency))
accumulateDependents ld =
let ref = LD.fold id Referent.toReference ld
in Map.singleton ld . Set.map LD.termRef <$> Codebase.dependents Queries.ExcludeOwnComponent ref

-- All dependents of extinct, including terms which might themselves be in the process of being deleted.
allDependentsOfExtinct :: Map LabeledDependency (Set LabeledDependency) <-
Map.unionsWith (<>) <$> for (Set.toList extinct) accumulateDependents

-- Filtered to only include dependencies which are not being deleted, but depend one which
-- is going extinct.
-- Of all the dependents of things going extinct, we filter down to only those that are not themselves being deleted
-- too (per `otherDesiredDeletion`), and are also somewhere outside `lib`. This allows us to proceed with deleting
-- an entire dependency out of `lib` even if for some reason it contains the only source of names for some other
-- dependency.
let extinctToEndangered :: Map LabeledDependency (NESet LabeledDependency)
extinctToEndangered =
allDependentsOfExtinct & Map.mapMaybe \endangeredDeps ->
let remainingEndangered = endangeredDeps `Set.intersection` remainingRefsWithoutOtherTargets
in NESet.nonEmptySet remainingEndangered
Map.mapMaybe
( NESet.nonEmptySet
. Set.intersection (Set.difference (refsAfterDeletingTarget rootNamesSansLib) otherDesiredDeletions)
)
allDependentsOfExtinct
pure extinctToEndangered
where
refsAfterDeletingTarget :: Names -> Set LabeledDependency
refsAfterDeletingTarget names =
Names.labeledReferences (names `Names.difference` targetToDelete)
2 changes: 1 addition & 1 deletion unison-src/transcripts/fix-5446.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,6 @@ lib.two.bar = foo Nat.+ foo
scratch/main> add
```

```ucm:error
```ucm
scratch/main> delete.namespace lib.one
```
34 changes: 5 additions & 29 deletions unison-src/transcripts/fix-5446.output.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
Previously `delete.namespace` would refuse to delete a namespace if it would leave any nameless references in `lib`.

``` unison
lib.one.foo = 17
lib.two.bar = foo Nat.+ foo
Expand Down Expand Up @@ -25,36 +27,10 @@ scratch/main> add
lib.one.foo : Nat
lib.two.bar : Nat
```
``` ucm
scratch/main> delete.namespace lib.one
⚠️
I didn't delete the namespace because the following
definitions are still in use.
Dependency Referenced In
foo 1. lib.two.bar
If you want to proceed anyways and leave those definitions
without names, use delete.namespace.force
Done.
```



🛑

The transcript failed due to an error in the stanza above. The error is:


⚠️

I didn't delete the namespace because the following
definitions are still in use.

Dependency Referenced In
foo 1. lib.two.bar

If you want to proceed anyways and leave those definitions
without names, use delete.namespace.force

0 comments on commit 5ee4794

Please sign in to comment.