@@ -5,7 +5,7 @@ module Elm.Install
8−import Control.Monad (filterM, forM, msum, void)
8+import Control.Monad (filterM, foldM, forM, msum, void)
9import Control.Monad.Except (catchError, lift, liftIO)
9import Control.Monad.Except (catchError, lift, liftIO)
10import Data.Map ((!))
10import Data.Map ((!))
11import qualified Data.Map as Map
11import qualified Data.Map as Map
@@ -69,11 +69,31 @@ attemptElmJsonChange root oldProject toString changes =
69 AlreadyInstalled ->
69 AlreadyInstalled ->
70 do liftIO $ putStrLn "It is already installed!"
70 do liftIO $ putStrLn "It is already installed!"
72− PromoteTest newProject ->
73− attempt newProject $ requestPromotion "\"test-dependencies\""
75 PromoteTrans newProject ->
72 PromoteTrans newProject ->
76− attempt newProject $ requestPromotion "\"transitive-dependencies\""
73+ attempt newProject $
76+ ["I","found","it","in","your","elm.json","file,"
77+ ,"but","in","the",D.dullyellow "\"indirect\"","dependencies."
80+ ["Should","I","move","it","into",D.green "\"direct\""
81+ ,"dependencies","for","more","general","use?","[Y/n]: "
85+ PromoteTest newProject ->
89+ ["I","found","it","in","your","elm.json","file,"
90+ ,"but","in","the",D.dullyellow "\"test-dependencies\"","field."
93+ ["Should","I","move","it","into",D.green "\"dependencies\""
94+ ,"for","more","general","use?","[Y/n]: "
78 Changes changeDict newProject ->
98 Changes changeDict newProject ->
@@ -88,20 +108,6 @@ attemptElmJsonChange root oldProject toString changes =
91−requestPromotion :: D.Doc -> D.Doc
92−requestPromotion theWrongPlace =
95− ["I","found","it","in","your","elm.json","file!"
96− ,"In",D.dullyellow theWrongPlace,"though."
99− ["Should","I","move","it","into",D.green "\"dependencies\""
100− ,"for","more","general","use?","[Y/n]: "
106-- MAKE PLANS
112-- MAKE PLANS
@@ -114,31 +120,21 @@ data Changes vsn
116makeAppPlan :: Cache.PackageRegistry -> Pkg.Name -> Project.AppInfo -> Task.Task (Changes Pkg.Version)
122makeAppPlan :: Cache.PackageRegistry -> Pkg.Name -> Project.AppInfo -> Task.Task (Changes Pkg.Version)
117−makeAppPlan registry pkg info@(Project.AppInfo elm srcDirs deps test trans) =
123+makeAppPlan registry pkg info@(Project.AppInfo _ _ depsDirect depsTrans testDirect testTrans) =
118− if Map.member pkg deps then
124+ if Map.member pkg depsDirect then
119 return AlreadyInstalled
125 return AlreadyInstalled
121− case Map.lookup pkg test of
127+ do (AppAnswer old new newInfo) <- toAppAnswer registry pkg info
123− return $ PromoteTest $ Project.App $
124− Project.AppInfo elm srcDirs (Map.insert pkg vsn deps) (Map.delete pkg test) trans
126− Nothing ->
129+ return $
127− case Map.lookup pkg trans of
130+ if Map.member pkg depsTrans then
129− return $ PromoteTrans $ Project.App $
131+ PromoteTrans (Project.App newInfo)
130− Project.AppInfo elm srcDirs (Map.insert pkg vsn deps) test (Map.delete pkg trans)
133− do changes <- addToApp registry pkg info
135− let news = Map.mapMaybe keepNew changes
133+ else if Map.member pkg testDirect || Map.member pkg testTrans then
136− let newDeps = addNews (Just pkg) news deps
134+ PromoteTest (Project.App newInfo)
137− let newTest = addNews Nothing news test
138− let newTrans = Map.union (Map.difference news (Map.union newDeps newTest)) trans
140− return $ Changes changes $ Project.App $
137+ Changes (detectChanges old new) (Project.App newInfo)
141− Project.AppInfo elm srcDirs newDeps newTest newTrans
144makePkgPlan :: Cache.PackageRegistry -> Pkg.Name -> Project.PkgInfo -> Task.Task (Changes Constraint)
140makePkgPlan :: Cache.PackageRegistry -> Pkg.Name -> Project.PkgInfo -> Task.Task (Changes Constraint)
@@ -219,40 +215,83 @@ keepNew change =
219-- ADD TO APP
215-- ADD TO APP
220+ { _old :: Map.Map Pkg.Name Pkg.Version
221+ , _new :: Map.Map Pkg.Name Pkg.Version
222+ , _info :: Project.AppInfo
222−addToApp :: Cache.PackageRegistry -> Pkg.Name -> Project.AppInfo -> Task.Task (Map.Map Pkg.Name (Change Pkg.Version))
226+toAppAnswer :: Cache.PackageRegistry -> Pkg.Name -> Project.AppInfo -> Task.Task AppAnswer
223−addToApp registry pkg info@(Project.AppInfo _ _ deps tests trans) =
227+toAppAnswer registry pkg info@(Project.AppInfo _ _ depsDirect depsTrans testDirect testTrans) =
224 Explorer.run registry $
228 Explorer.run registry $
225 do Explorer.exists pkg
229 do Explorer.exists pkg
226− let old = Map.unions [ deps, tests, trans ]
227− result <- Solver.run (addToAppHelp pkg info)
230+ result <- Solver.run (toAppAnswerHelp pkg info)
228 case result of
231 case result of
229− Just new ->
232+ Just answer ->
230− return $ detectChanges old new
233+ return answer
232 Nothing ->
235 Nothing ->
233− do badNames <- filterM isBadElm (pkg : Map.keys old)
237+ filterM isBadElm $
238+ pkg : Map.keys depsDirect
239+ ++ Map.keys depsTrans
240+ ++ Map.keys testDirect
241+ ++ Map.keys testTrans
234 lift $ Task.throw (Exit.Install (E.NoSolution badNames))
242 lift $ Task.throw (Exit.Install (E.NoSolution badNames))
237−addToAppHelp :: Pkg.Name -> Project.AppInfo -> Solver.Solver (Map.Map Pkg.Name Pkg.Version)
245+toAppAnswerHelp :: Pkg.Name -> Project.AppInfo -> Solver.Solver AppAnswer
238−addToAppHelp pkg (Project.AppInfo _ _ deps tests trans) =
246+toAppAnswerHelp pkg (Project.AppInfo elm srcDirs depsDirect depsTrans testDirect testTrans) =
240 directs =
248 directs =
241− Map.union deps tests
249+ Map.union depsDirect testDirect
252+ Map.union directs (Map.union depsTrans testTrans)
254+ try toConstraint deps =
255+ do solution <- Solver.solve $ Map.insert pkg Con.anything (Map.map toConstraint deps)
256+ let newDepsDirect = Map.intersection solution (Map.insert pkg Pkg.dummyVersion depsDirect)
257+ newDeps <- lift $ foldM (collectTransitive solution) Map.empty (Map.keys newDepsDirect)
260+ { _old = directAndTrans
267+ (Map.difference newDeps newDepsDirect)
268+ (Map.intersection solution testDirect)
269+ (Map.difference (Map.difference solution newDeps) testDirect)
273+ [ try Con.exactly directAndTrans
274+ , try Con.exactly directs
275+ , try Con.untilNextMinor directs
276+ , try Con.untilNextMajor directs
277+ , try (\_ -> Con.anything) directs
282+ :: Map.Map Pkg.Name Pkg.Version
283+ -> Map.Map Pkg.Name Pkg.Version
285+ -> Explorer (Map.Map Pkg.Name Pkg.Version)
286+collectTransitive solution state name =
287+ do let version = solution ! name
288+ (Explorer.Info _ trans) <- Explorer.getConstraints name version
290+ (collectTransitive solution)
291+ (Map.insert name version state)
244− Map.union directs trans
247− Solver.solve $ Map.insert pkg Con.anything constraints
250− [ Map.map Con.exactly everything
251− , Map.map Con.exactly directs
252− , Map.map Con.untilNextMinor directs
253− , Map.map Con.untilNextMajor directs
254− , Map.map (\_ -> Con.anything) directs
@@ -326,7 +365,7 @@ viewNonZero title entries =
328 , D.fromString title
367 , D.fromString title
329− , D.indent 2 (D.vcat (reverse entries))
368+ , D.indent 2 (D.vcat entries)