updated MergeLocalBranchI to use two updates, and not print todo

implement added Lens.Cons and Lens.Snoc instances (closes #1200):

instance Cons Path Path NameSegment NameSegment
instance Snoc Relative Relative NameSegment NameSegment
instance Snoc Absolute Absolute NameSegment NameSegment
instance Snoc Path Path NameSegment NameSegment
instance Snoc Path' Path' NameSegment NameSegment

and class Path.Resolve l r where
  resolve :: l -> r -> l
with
instance Resolve Path Path
instance Resolve Relative Relative
instance Resolve Absolute Relative
instance Resolve Path' Path'
instance Resolve Path' Split'
instance Resolve Absolute Path'
This commit is contained in:
Arya Irani 2020-02-06 00:04:34 -05:00
parent 5cd19d3eef
commit 72832815eb
13 changed files with 200 additions and 129 deletions

View File

@ -191,7 +191,7 @@ loop = do
resolveSplit' :: (Path', a) -> (Path, a)
resolveSplit' = Path.fromAbsoluteSplit . Path.toAbsoluteSplit currentPath'
resolveToAbsolute :: Path' -> Path.Absolute
resolveToAbsolute = Path.toAbsolutePath currentPath'
resolveToAbsolute = Path.resolve currentPath'
getAtSplit :: Path.Split -> Maybe (Branch m)
getAtSplit p = BranchUtil.getBranch p root0
getAtSplit' :: Path.Split' -> Maybe (Branch m)
@ -490,17 +490,17 @@ loop = do
else do
destb <- getAt dest
merged <- eval . Eval $ Branch.merge srcb destb
let merged0 = Branch.head merged
patch <- getPatchAt' defaultPatchPath merged0
if (merged /= destb) then do
let (applyPatch, printMsg) = propagatePatch' @m @v patch dest
merged' <-
-- fromJust is safe as long as Branch.merge doesn't produce a Causal.One!
fromJust <$> Branch.adjustHeadMN applyPatch (eval . Eval) merged
updateAtM dest $ const (pure merged')
diffHelper (Branch.head destb) (Branch.head merged') >>=
respondNumbered . uncurry (ShowDiffAfterMerge dest0 dest)
when (merged' /= merged) printMsg
diffHelper (Branch.head destb) (Branch.head merged) >>=
respondNumbered . uncurry (ShowDiffAfterMerge dest0 dest)
mergeDidChange <- updateAtM dest $ const (pure merged)
if mergeDidChange then do
patch <- getPatchAt' defaultPatchPath (Branch.head merged)
patchDidChange <- propagatePatch inputDescription patch dest
when patchDidChange $ do
patched <- getAt dest
let patchPath = Path.resolve dest0 defaultPatchPath
diffHelper (Branch.head destb) (Branch.head patched) >>=
respondNumbered . uncurry (ShowDiffAfterMergePropagate dest0 dest patchPath)
else respond (NothingTodo input)
PreviewMergeLocalBranchI src0 dest0 -> do
@ -638,7 +638,7 @@ loop = do
respond $ CantDelete ppe failed failedDependents
SwitchBranchI path' -> do
path <- use $ currentPath . to (`Path.toAbsolutePath` path')
let path = resolveToAbsolute path'
currentPath .= path
branch' <- getAt path
when (Branch.isEmpty branch') (respond $ CreatedNewBranch path)
@ -649,7 +649,7 @@ loop = do
Right b -> do
doHistory 0 b []
Right path' -> do
path <- use $ currentPath . to (`Path.toAbsolutePath` path')
let path = resolveToAbsolute path'
branch' <- getAt path
if Branch.isEmpty branch' then respond $ CreatedNewBranch path
else do
@ -752,7 +752,7 @@ loop = do
case mdType of
Nothing -> respond $ LinkFailure input
Just ty -> do
let parent = Path.toAbsolutePath currentPath' (fst src)
let parent = resolveToAbsolute (fst src)
let get = Branch.head <$> getAt parent
before <- get
stepAt (Path.unabsolute parent, step (Type.toReference ty))
@ -929,7 +929,7 @@ loop = do
FindShallowI pathArg -> do
prettyPrintNames0 <- basicPrettyPrintNames0
ppe <- fmap PPE.suffixifiedPPE . prettyPrintEnvDecl $ Names prettyPrintNames0 mempty
let pathArgAbs = Path.toAbsolutePath currentPath' pathArg
let pathArgAbs = resolveToAbsolute pathArg
b0 <- Branch.head <$> getAt pathArgAbs
let
hqTerm b0 ns r =
@ -1266,7 +1266,7 @@ loop = do
TodoI patchPath branchPath' -> do
patch <- getPatchAt (fromMaybe defaultPatchPath patchPath)
branch <- getAt $ Path.toAbsolutePath currentPath' branchPath'
branch <- getAt $ resolveToAbsolute branchPath'
let names0 = Branch.toNames0 (Branch.head branch)
-- showTodoOutput only needs the local references
-- to check for obsolete defs
@ -1357,7 +1357,7 @@ loop = do
<> UF.typecheckedToNames0 IOSource.typecheckedFile
let b0 = BranchUtil.addFromNames0 names0 Branch.empty0
let srcb = Branch.one b0
_ <- updateAtM (Path.snocAbsolute currentPath' "builtin") $ \destb ->
_ <- updateAtM (currentPath' `snoc` "builtin") $ \destb ->
eval . Eval $ Branch.merge srcb destb
success
@ -1372,13 +1372,13 @@ loop = do
respond $ ListEdits patch ppe
PullRemoteBranchI mayRepo path -> do
let destAbs = Path.toAbsolutePath currentPath' path
let destAbs = resolveToAbsolute path
resolveConfiguredGitUrl Pull path mayRepo >>= \case
Left e -> eval . Notify $ e
Right ns -> pullRemoteBranchAt (Just path) input inputDescription ns destAbs
PushRemoteBranchI mayRepo path -> do
let srcAbs = Path.toAbsolutePath currentPath' path
let srcAbs = resolveToAbsolute path
srcb <- getAt srcAbs
let expandRepo (r, rp) = (r, Nothing, rp)
resolveConfiguredGitUrl Push path (fmap expandRepo mayRepo) >>= \case
@ -1424,7 +1424,7 @@ loop = do
resolveConfiguredGitUrl pushPull destPath' = \case
Just ns -> pure $ Right ns
Nothing -> do
let destPath = Path.toAbsolutePath currentPath' destPath'
let destPath = resolveToAbsolute destPath'
let configKey = gitUrlKey destPath
(eval . ConfigLookup) configKey >>= \case
Just url ->
@ -1544,34 +1544,27 @@ resolveShortBranchHash hash = do
-- Returns True if the operation changed the namespace, False otherwise.
propagatePatch :: (Monad m, Var v) =>
Text -> Patch -> Path.Absolute -> Action' m v Bool
propagatePatch inputDescription patch scopePath = do
let (f, msg) = propagatePatch' patch scopePath
changed <- stepAtM' (inputDescription <> " (patch propagation)")
(Path.unabsolute scopePath, f)
when changed msg
pure changed
propagatePatch inputDescription patch scopePath =
stepAtM' (inputDescription <> " (applying patch)")
(Path.unabsolute scopePath, applyPatch' patch)
-- Returns a function that updates a Branch0 according to the patch,
-- and a an action that prints todo output, suitable for running if the branch
-- was updated
propagatePatch' :: forall m v. (Monad m, Var v)
=> Patch
-> Path.Absolute
-> ( Branch0 m -> Action' m v (Branch0 m)
, Action' m v () )
propagatePatch' patch scopePath =
let applyPatch :: Branch0 m -> Action' m v (Branch0 m)
applyPatch = lift . lift . Propagate.propagateAndApply patch in
( applyPatch
, do
scope <- getAt scopePath
let names0 = Branch.toNames0 (Branch.head scope)
-- this will be different AFTER the update succeeds
let getPpe = do
names <- makePrintNamesFromLabeled' (Patch.labeledDependencies patch)
prettyPrintEnvDecl names
showTodoOutput getPpe patch names0
)
applyPatch' :: forall m v. (Monad m, Var v)
=> Patch -> Branch0 m -> Action' m v (Branch0 m)
applyPatch' patch = lift . lift . Propagate.propagateAndApply patch
-- | Create the args needed for showTodoOutput and call it
doShowTodoOutput :: Monad m => Patch -> Path.Absolute -> Action' m v ()
doShowTodoOutput patch scopePath = do
scope <- getAt scopePath
let names0 = Branch.toNames0 (Branch.head scope)
-- this will be different AFTER the update succeeds
let getPpe = do
names <- makePrintNamesFromLabeled' (Patch.labeledDependencies patch)
prettyPrintEnvDecl names
showTodoOutput getPpe patch names0
-- | Show todo output if there are any conflicts or edits.
showTodoOutput

View File

@ -75,6 +75,7 @@ data NumberedOutput v
| ShowDiffAfterDeleteDefinitions PPE.PrettyPrintEnv (BranchDiffOutput v Ann)
| ShowDiffAfterDeleteBranch Path.Absolute PPE.PrettyPrintEnv (BranchDiffOutput v Ann)
| ShowDiffAfterMerge Path.Path' Path.Absolute PPE.PrettyPrintEnv (BranchDiffOutput v Ann)
| ShowDiffAfterMergePropagate Path.Path' Path.Absolute Path.Path' PPE.PrettyPrintEnv (BranchDiffOutput v Ann)
| ShowDiffAfterMergePreview Path.Path' Path.Absolute PPE.PrettyPrintEnv (BranchDiffOutput v Ann)
| ShowDiffAfterPull Path.Path' Path.Absolute PPE.PrettyPrintEnv (BranchDiffOutput v Ann)
| ShowDiffAfterCreatePR RemoteNamespace RemoteNamespace PPE.PrettyPrintEnv (BranchDiffOutput v Ann)
@ -318,6 +319,7 @@ isNumberedFailure = \case
ShowDiffAfterDeleteDefinitions{} -> False
ShowDiffAfterDeleteBranch{} -> False
ShowDiffAfterMerge{} -> False
ShowDiffAfterMergePropagate{} -> False
ShowDiffAfterMergePreview{} -> False
ShowDiffAfterUndo{} -> False
ShowDiffAfterPull{} -> False

View File

@ -203,7 +203,7 @@ parseHQSplit' s =
shError s = "couldn't parse shorthash from " <> s
toAbsoluteSplit :: Absolute -> (Path', a) -> (Absolute, a)
toAbsoluteSplit a (p, s) = (toAbsolutePath a p, s)
toAbsoluteSplit a (p, s) = (resolve a p, s)
fromSplit' :: (Path', a) -> (Path, a)
fromSplit' (Path' (Left (Absolute p)), a) = (p, a)
@ -221,13 +221,6 @@ relativeEmpty' = Path' (Right (Relative empty))
relativeSingleton :: NameSegment -> Relative
relativeSingleton = Relative . Path . Seq.singleton
toAbsolutePath :: Absolute -> Path' -> Absolute
toAbsolutePath cur (Path' p) = either id (relativeToAbsolutePath cur) p
relativeToAbsolutePath :: Absolute -> Relative -> Absolute
relativeToAbsolutePath (Absolute cur) (Relative rel) =
Absolute (Path $ toSeq cur <> toSeq rel)
toPath' :: Path -> Path'
toPath' = \case
Path (NameSegment "" :<| tail) -> Path' . Left . Absolute . Path $ tail
@ -251,23 +244,20 @@ prefixName p = toName . prefix p . fromName'
singleton :: NameSegment -> Path
singleton n = fromList [n]
cons :: NameSegment -> Path -> Path
cons = Lens.cons
snoc :: Path -> NameSegment -> Path
snoc (Path p) ns = Path (p <> pure ns)
snoc = Lens.snoc
snoc' :: Path' -> NameSegment -> Path'
snoc' (Path' e) n = case e of
Left abs -> Path' (Left . Absolute $ snoc (unabsolute abs) n)
Right rel -> Path' (Right . Relative $ snoc (unrelative rel) n)
snoc' = Lens.snoc
unsnoc :: Path -> Maybe (Path, NameSegment)
unsnoc p = case p of
Path (init :|> last) -> Just (Path init, last)
_ -> Nothing
unsnoc = Lens.unsnoc
uncons :: Path -> Maybe (NameSegment, Path)
uncons p = case p of
Path (hd :<| tl) -> Just (hd, Path tl)
_ -> Nothing
uncons = Lens.uncons
--asDirectory :: Path -> Text
--asDirectory p = case toList p of
@ -318,15 +308,6 @@ pattern Parent h t = Path (NameSegment h :<| t)
empty :: Path
empty = Path mempty
cons :: NameSegment -> Path -> Path
cons ns (Path p) = Path (ns :<| p)
snocAbsolute :: Absolute -> NameSegment -> Absolute
snocAbsolute a n = Absolute . (`snoc` n) $ unabsolute a
snocRelative :: Relative -> NameSegment -> Relative
snocRelative r n = Relative . (`snoc` n) $ unrelative r
instance Show Path where
show = Text.unpack . toText
@ -337,3 +318,74 @@ toText' :: Path' -> Text
toText' = \case
Path' (Left (Absolute path)) -> Text.cons '.' (toText path)
Path' (Right (Relative path)) -> toText path
instance Cons Path Path NameSegment NameSegment where
_Cons = prism (uncurry cons) uncons where
cons :: NameSegment -> Path -> Path
cons ns (Path p) = Path (ns :<| p)
uncons :: Path -> Either Path (NameSegment, Path)
uncons p = case p of
Path (hd :<| tl) -> Right (hd, Path tl)
_ -> Left p
instance Snoc Relative Relative NameSegment NameSegment where
_Snoc = prism (uncurry snocRelative) $ \case
Relative (Lens.unsnoc -> Just (s,a)) -> Right (Relative s,a)
e -> Left e
where
snocRelative :: Relative -> NameSegment -> Relative
snocRelative r n = Relative . (`Lens.snoc` n) $ unrelative r
instance Snoc Absolute Absolute NameSegment NameSegment where
_Snoc = prism (uncurry snocAbsolute) $ \case
Absolute (Lens.unsnoc -> Just (s,a)) -> Right (Absolute s, a)
e -> Left e
where
snocAbsolute :: Absolute -> NameSegment -> Absolute
snocAbsolute a n = Absolute . (`Lens.snoc` n) $ unabsolute a
instance Snoc Path Path NameSegment NameSegment where
_Snoc = prism (uncurry snoc) unsnoc
where
unsnoc :: Path -> Either Path (Path, NameSegment)
unsnoc = \case
Path (s Seq.:|> a) -> Right (Path s, a)
e -> Left e
snoc :: Path -> NameSegment -> Path
snoc (Path p) ns = Path (p <> pure ns)
instance Snoc Path' Path' NameSegment NameSegment where
_Snoc = prism (uncurry snoc') $ \case
Path' (Left (Lens.unsnoc -> Just (s,a))) -> Right (Path' (Left s), a)
Path' (Right (Lens.unsnoc -> Just (s,a))) -> Right (Path' (Right s), a)
e -> Left e
where
snoc' :: Path' -> NameSegment -> Path'
snoc' (Path' e) n = case e of
Left abs -> Path' (Left . Absolute $ Lens.snoc (unabsolute abs) n)
Right rel -> Path' (Right . Relative $ Lens.snoc (unrelative rel) n)
class Resolve l r where
resolve :: l -> r -> l
instance Resolve Path Path where
resolve (Path l) (Path r) = Path (l <> r)
instance Resolve Relative Relative where
resolve (Relative (Path l)) (Relative (Path r)) = Relative (Path (l <> r))
instance Resolve Absolute Relative where
resolve (Absolute l) (Relative r) = Absolute (resolve l r)
instance Resolve Path' Path' where
resolve _ a@(Path' Left{}) = a
resolve (Path' (Left a)) (Path' (Right r)) = Path' (Left (resolve a r))
resolve (Path' (Right r1)) (Path' (Right r2)) = Path' (Right (resolve r1 r2))
instance Resolve Path' Split' where
resolve l r = resolve l (unsplit' r)
instance Resolve Absolute Path' where
resolve _ (Path' (Left a)) = a
resolve a (Path' (Right r)) = resolve a r

View File

@ -144,6 +144,8 @@ notifyNumbered o = case o of
, undoTip
]) (showDiffNamespace ppe bAbs bAbs diff)
ShowDiffAfterMerge _ _ _ (OBD.isEmpty -> True) ->
(P.wrap $ "Nothing changed as a result of the merge.", mempty)
ShowDiffAfterMerge dest' destAbs ppe diffOutput ->
first (\p -> P.lines [
P.wrap $ "Here's what's changed in " <> prettyPath' dest' <> "after the merge:"
@ -157,6 +159,21 @@ notifyNumbered o = case o of
<> IP.makeExample' IP.viewReflog <> " to undo the results of this merge."
]) (showDiffNamespace ppe destAbs destAbs diffOutput)
ShowDiffAfterMergePropagate dest' destAbs patchPath' ppe diffOutput ->
first (\p -> P.lines [
P.wrap $ "Here's what's changed in " <> prettyPath' dest'
<> "after applying the patch at " <> P.group (prettyPath' patchPath' <> ":")
, ""
, p
, ""
, tip $ "You can use "
<> IP.makeExample IP.todo [prettyPath' patchPath', prettyPath' dest']
<> "to see if this generated any work to do in this namespace"
<> "and " <> IP.makeExample' IP.test <> "to run the tests."
<> "Or you can use" <> IP.makeExample' IP.undo <> " or"
<> IP.makeExample' IP.viewReflog <> " to undo the results of this merge."
]) (showDiffNamespace ppe destAbs destAbs diffOutput)
ShowDiffAfterMergePreview dest' destAbs ppe diffOutput ->
first (\p -> P.lines [
P.wrap $ "Here's what would change in " <> prettyPath' dest' <> "after the merge:"
@ -244,7 +261,7 @@ notifyUser dir o = case o of
<> "to see what's been updated."
, P.wrap $ "Use" <>
IP.makeExample IP.todo
[ prettyRelative (Path.snocRelative mergedPath "patch")
[ prettyRelative (snoc mergedPath "patch")
, prettyRelative mergedPath ]
<> "to see what work is remaining for the merge."
, P.wrap $ "Use" <>
@ -845,13 +862,11 @@ notifyUser dir o = case o of
NothingTodo input -> pure . P.callout "😶" $ case input of
Input.MergeLocalBranchI src dest ->
P.wrap $ "The merge had no effect, since the destination"
<> P.shown dest <> "is at or ahead of the source"
<> P.group (P.shown src <> ".")
P.wrap $ prettyPath' dest <> "was already up-to-date with"
<> P.group (prettyPath' src <> ".")
Input.PreviewMergeLocalBranchI src dest ->
P.wrap $ "The merge will have no effect, since the destination"
<> P.shown dest <> "is at or ahead of the source"
<> P.group (P.shown src <> ".")
P.wrap $ prettyPath' dest <> "is already up-to-date with"
<> P.group (prettyPath' src <> ".")
_ -> "Nothing to do."
DumpNumberedArgs args -> pure . P.numberedList $ fmap P.string args
NoConflictsOrEdits ->

View File

@ -1,5 +1,7 @@
{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ViewPatterns #-}
{-# LANGUAGE MultiParamTypeClasses #-}
module Unison.Codebase.NameSegment where
@ -9,6 +11,8 @@ import qualified Unison.Name as Name
import qualified Data.Text as Text
import qualified Unison.Hashable as H
import qualified Unison.HashQualified' as HQ'
import qualified Control.Lens as Lens
import Unison.Name (Name(Name))
-- Represents the parts of a name between the `.`s
newtype NameSegment = NameSegment { toText :: Text } deriving (Eq, Ord)
@ -37,3 +41,14 @@ instance Show NameSegment where
instance IsString NameSegment where
fromString = NameSegment . Text.pack
instance Lens.Snoc Name Name NameSegment NameSegment where
_Snoc = Lens.prism snoc unsnoc
where
snoc :: (Name, NameSegment) -> Name
snoc (n,s) = Name.joinDot n (toName s)
unsnoc :: Name -> Either Name (Name, NameSegment)
unsnoc n@(Name (Text.splitOn "." -> ns)) = case Lens.unsnoc ns of
Nothing -> Left n
Just ([],_) -> Left n
Just (init, last) -> Right $ (Name (Text.intercalate "." init), NameSegment last)

View File

@ -1,7 +1,7 @@
{-# LANGUAGE OverloadedStrings #-}
module Unison.Name
( Name
( Name(Name)
, fromString
, isPrefixOf
, joinDot

View File

@ -177,10 +177,10 @@ type Foo = Foo Boolean
3. └ type Foo#gq9inhvg9h
4. Foo.Foo#d97e0jhkmd#0 : Nat -> Foo#d97e0jhkmd
4. Foo.Foo#d97e0jhkmd#0 : Nat -> Foo
5. ┌ Foo.Foo#d97e0jhkmd#0 : Nat -> Foo#d97e0jhkmd
6. └ Foo.Foo#gq9inhvg9h#0 : Boolean -> Foo#gq9inhvg9h
5. ┌ Foo.Foo#d97e0jhkmd#0 : Nat -> Foo
6. └ Foo.Foo#gq9inhvg9h#0 : Boolean -> b.Foo
Added definitions:

View File

@ -126,7 +126,11 @@ a = 555
```ucm
.nsz> update
.> merge nsy nsw
```
```ucm:error
.> merge nsz nsw
```
```ucm
.> diff.namespace nsx nsw
.nsw> view a b
```
@ -134,9 +138,9 @@ a = 555
a = 777
```
```-ucm
```ucm:error
.nsw> update
nsw> view a b
.nsw> view a b
```
##

View File

@ -211,10 +211,6 @@ unique type Y a b = Y a b
b : .builtin.Text
fromJust : .builtin.Nat
No conflicts or edits in progress.
.ns2> links fromJust
1. .ns1.b : Nat
@ -469,10 +465,6 @@ bdependent = "banana"
bdependent : .builtin.Text
No conflicts or edits in progress.
.> diff.namespace ns2 ns3
Updates:
@ -528,10 +520,6 @@ a = 444
a : .builtin.Nat
No conflicts or edits in progress.
```
```unison
a = 555
@ -544,10 +532,6 @@ a = 555
a : .builtin.Nat
No conflicts or edits in progress.
.> merge nsy nsw
Here's what's changed in nsw after the merge:
@ -564,6 +548,8 @@ a = 555
can use `undo` or `reflog` to undo the results of this
merge.
```
```ucm
.> merge nsz nsw
Here's what's changed in nsw after the merge:
@ -588,6 +574,10 @@ a = 555
can use `undo` or `reflog` to undo the results of this
merge.
A patch needs to be conflict-free.
```
```ucm
.> diff.namespace nsx nsw
New name conflicts:
@ -645,13 +635,37 @@ a = 777
`>`)... Ctrl+C cancels.
```
```
-ucm
```ucm
.nsw> update
nsw> view a b
x These definitions failed:
Reason
conflicted a : .builtin.Nat
Tip: Use `help filestatus` to learn more.
A patch needs to be conflict-free.
.nsw> view a b
a#5f8uodgrtf : Nat
a#5f8uodgrtf = 555
a#ekguc9h648 : Nat
a#ekguc9h648 = 444
b#be9a2abbbg : Nat
b#be9a2abbbg =
use Nat +
a#ekguc9h648 + 1
b#kut4vstim7 : Nat
b#kut4vstim7 =
use Nat +
a#5f8uodgrtf + 1
```
##
Updates: -- 1 to 1

View File

@ -64,10 +64,6 @@ Update
hey : builtin.Text
No conflicts or edits in progress.
.> find.patch
1. patch

View File

@ -60,10 +60,6 @@ x = 7
x : builtin.Nat
No conflicts or edits in progress.
.> view x y z
x : Nat

View File

@ -244,10 +244,6 @@ master.frobnicate n = n + 1
master.y : builtin.Text
No conflicts or edits in progress.
.> view master.y
feature2.y : Text

View File

@ -87,10 +87,6 @@ and update the codebase to use the new type `Foo`...
unique type Foo
No conflicts or edits in progress.
```
... it should automatically propagate the type to `fooToInt`.
@ -177,10 +173,6 @@ Update...
someTerm : .builtin.Optional x -> .builtin.Optional x
No conflicts or edits in progress.
```
Now the type of `someTerm` should be `Optional x -> Optional x` and the
type of `otherTerm` should remain the same.
@ -294,10 +286,6 @@ someTerm _ = None
someTerm : .builtin.Optional x -> .builtin.Optional x
No conflicts or edits in progress.
```
The other namespace should be left alone.