on master help sign in
Show the "package not found" error on bad installs
988c63cEvan Czaplicki
builder/src/Deps/Explorer.hs+17−1
@@ -4,6 +4,7 @@ module Deps.Explorer
4 , Metadata
4 , Metadata
5 , Info(..)
5 , Info(..)
6 , run
6 , run
7+ , exists
7 , getVersions
8 , getVersions
8 , getConstraints
9 , getConstraints
9 )
10 )
@@ -62,6 +63,21 @@ run explorer =
62
63
63
64
64
65
66+-- EXISTS
67+
68+
69+exists :: Name -> Explorer ()
70+exists name =
71+ do pkgs <- gets _vsns
72+ case Get.versions name pkgs of
73+ Right _ ->
74+ return ()
75+
76+ Left allPkgs ->
77+ throwError (Exit.Deps (E.PackageNotFound name allPkgs))
78+
79+
80+
65-- VERSIONS
81-- VERSIONS
66
82
67
83
@@ -72,7 +88,7 @@ getVersions name =
72 Right versions ->
88 Right versions ->
73 return versions
89 return versions
74
90
75− Left _suggestions ->
91+ Left _allPkgs ->
76 throwError (Exit.Deps (E.CorruptVersionCache name))
92 throwError (Exit.Deps (E.CorruptVersionCache name))
77
93
78
94
builder/src/Deps/Get.hs+7−8
@@ -10,6 +10,7 @@ module Deps.Get
10 )
10 )
11 where
11 where
12
12
13+
13import Prelude hiding (all)
14import Prelude hiding (all)
14import Control.Monad.Except (catchError, liftIO)
15import Control.Monad.Except (catchError, liftIO)
15import qualified Data.ByteString as BS
16import qualified Data.ByteString as BS
@@ -22,11 +23,9 @@ import qualified Text.PrettyPrint.ANSI.Leijen as P
22
23
23import qualified Elm.Docs as Docs
24import qualified Elm.Docs as Docs
24import qualified Elm.Package as Pkg
25import qualified Elm.Package as Pkg
25−import Elm.Package (Name, Version)
26
26
27import qualified Deps.Website as Website
27import qualified Deps.Website as Website
28import qualified Elm.Project.Json as Project
28import qualified Elm.Project.Json as Project
29−import qualified Elm.Utils as Utils
30import qualified File.IO as IO
29import qualified File.IO as IO
31import qualified Reporting.Exit as Exit
30import qualified Reporting.Exit as Exit
32import qualified Reporting.Exit.Assets as E
31import qualified Reporting.Exit.Assets as E
@@ -42,7 +41,7 @@ import qualified Json.Decode as Decode
42data Mode = RequireLatest | AllowOffline
41data Mode = RequireLatest | AllowOffline
43
42
44
43
45−newtype AllPackages = AllPackages (Map Name [Version])
44+newtype AllPackages = AllPackages (Map Pkg.Name [Pkg.Version])
46
45
47
46
48all :: Mode -> Task.Task AllPackages
47all :: Mode -> Task.Task AllPackages
@@ -85,7 +84,7 @@ fetchNew versionsFile mode =
85 return (AllPackages newAllPkgs)
84 return (AllPackages newAllPkgs)
86
85
87
86
88−addNew :: Map Name [Version] -> (Name, Version) -> Map Name [Version]
87+addNew :: Map Pkg.Name [Pkg.Version] -> (Pkg.Name, Pkg.Version) -> Map Pkg.Name [Pkg.Version]
89addNew packages (name, version) =
88addNew packages (name, version) =
90 Map.insertWith (++) name [version] packages
89 Map.insertWith (++) name [version] packages
91
90
@@ -94,21 +93,21 @@ addNew packages (name, version) =
94-- VERSIONS
93-- VERSIONS
95
94
96
95
97−versions :: Name -> AllPackages -> Either [Name] [Version]
96+versions :: Pkg.Name -> AllPackages -> Either [Pkg.Name] [Pkg.Version]
98versions name (AllPackages pkgs) =
97versions name (AllPackages pkgs) =
99 case Map.lookup name pkgs of
98 case Map.lookup name pkgs of
100 Just vsns ->
99 Just vsns ->
101 Right vsns
100 Right vsns
102
101
103 Nothing ->
102 Nothing ->
104− Left (Utils.nearbyNames Pkg.toString name (Map.keys pkgs))
103+ Left (Map.keys pkgs)
105
104
106
105
107
106
108-- PACKAGE INFO
107-- PACKAGE INFO
109
108
110
109
111−info :: Name -> Version -> Task.Task Project.PkgInfo
110+info :: Pkg.Name -> Pkg.Version -> Task.Task Project.PkgInfo
112info name version =
111info name version =
113 do dir <- Task.getPackageCacheDirFor name version
112 do dir <- Task.getPackageCacheDirFor name version
114 let elmJson = dir </> "elm.json"
113 let elmJson = dir </> "elm.json"
@@ -136,7 +135,7 @@ info name version =
136-- DOCS
135-- DOCS
137
136
138
137
139−docs :: Name -> Version -> Task.Task Docs.Documentation
138+docs :: Pkg.Name -> Pkg.Version -> Task.Task Docs.Documentation
140docs name version =
139docs name version =
141 do dir <- Task.getPackageCacheDirFor name version
140 do dir <- Task.getPackageCacheDirFor name version
142 let docsJson = dir </> "docs.json"
141 let docsJson = dir </> "docs.json"
builder/src/Elm/Install.hs+4−2
@@ -138,7 +138,8 @@ keepNew change =
138addToApp :: Name -> Project.AppInfo -> Task.Task (Map Name (Change Version))
138addToApp :: Name -> Project.AppInfo -> Task.Task (Map Name (Change Version))
139addToApp pkg info@(Project.AppInfo _ _ deps tests trans) =
139addToApp pkg info@(Project.AppInfo _ _ deps tests trans) =
140 Explorer.run $
140 Explorer.run $
141+ do Explorer.exists pkg
141− do let old = Map.unions [ deps, tests, trans ]
142+ let old = Map.unions [ deps, tests, trans ]
142 result <- Solver.run (addToAppHelp pkg info)
143 result <- Solver.run (addToAppHelp pkg info)
143 case result of
144 case result of
144 Just new ->
145 Just new ->
@@ -177,7 +178,8 @@ addToAppHelp pkg (Project.AppInfo _ _ deps tests trans) =
177addToPkg :: Name -> Project.PkgInfo -> Task.Task (Map Name (Change Constraint))
178addToPkg :: Name -> Project.PkgInfo -> Task.Task (Map Name (Change Constraint))
178addToPkg pkg info@(Project.PkgInfo _ _ _ _ _ deps tests _) =
179addToPkg pkg info@(Project.PkgInfo _ _ _ _ _ deps tests _) =
179 Explorer.run $
180 Explorer.run $
181+ do Explorer.exists pkg
180− do let old = Map.union deps tests
182+ let old = Map.union deps tests
181 result <- Solver.run (addToPkgHelp pkg info)
183 result <- Solver.run (addToPkgHelp pkg info)
182 case result of
184 case result of
183 Just new ->
185 Just new ->
builder/src/Reporting/Exit/Deps.hs+50−5
@@ -5,12 +5,17 @@ module Reporting.Exit.Deps
5 )
5 )
6 where
6 where
7
7
8+
9+import Data.Function (on)
10+import qualified Data.List as List
11+import qualified Data.Text as Text
8import Text.PrettyPrint.ANSI.Leijen ((<>))
12import Text.PrettyPrint.ANSI.Leijen ((<>))
9import qualified Text.PrettyPrint.ANSI.Leijen as P
13import qualified Text.PrettyPrint.ANSI.Leijen as P
10
14
11import qualified Elm.Compiler as Compiler
15import qualified Elm.Compiler as Compiler
12import qualified Elm.Package as Pkg
16import qualified Elm.Package as Pkg
13import qualified Elm.Project.Constraint as Con
17import qualified Elm.Project.Constraint as Con
18+import qualified Elm.Utils as Utils
14import qualified Reporting.Exit.Help as Help
19import qualified Reporting.Exit.Help as Help
15
20
16
21
@@ -46,12 +51,21 @@ toReport exit =
46 \ so you can delete it and see if that fixes the issue."
51 \ so you can delete it and see if that fixes the issue."
47 ]
52 ]
48
53
49− PackageNotFound package suggestions ->
54+ PackageNotFound package allPackages ->
55+ let
56+ suggestions =
57+ nearbyNames package allPackages
58+ in
50− Help.report "PACKAGE NOT FOUND" Nothing
59+ Help.docReport "PACKAGE NOT FOUND" Nothing
60+ ( P.fillSep
61+ ["I","cannot","find","a"
51− ( "Could not find any packages named " ++ Pkg.toString package
62+ ,P.red (P.text (Pkg.toString package))
63+ ,"package","on","the","package","website."
64+ ]
52 )
65 )
53− [ P.text $ "Maybe you want one of these instead?"
66+ [ "Maybe you want one of these instead?"
54− , P.indent 4 $ P.vcat $ map (P.text . Pkg.toString) suggestions
67+ , P.indent 4 $ P.dullyellow $ P.vcat $ map (P.text . Pkg.toString) suggestions
68+ , "But check <https://package.elm-lang.org> to see all possibilities!"
55 ]
69 ]
56
70
57 AppBadElm version ->
71 AppBadElm version ->
@@ -97,3 +111,34 @@ toReport exit =
97 "This probably means the downloaded files got corrupted somehow.\
111 "This probably means the downloaded files got corrupted somehow.\
98 \ Maybe try deleting your ELM_HOME and see if that resolves the issue?"
112 \ Maybe try deleting your ELM_HOME and see if that resolves the issue?"
99 ]
113 ]
114+
115+
116+
117+-- NEARBY NAMES
118+
119+
120+nearbyNames :: Pkg.Name -> [Pkg.Name] -> [Pkg.Name]
121+nearbyNames (Pkg.Name author1 project1) possibleNames =
122+ let
123+ authorDist = authorDistance (Text.unpack author1)
124+ projectDist = projectDistance (Text.unpack project1)
125+
126+ addDistance name@(Pkg.Name author2 project2) =
127+ ( authorDist author2 + projectDist project2, name )
128+ in
129+ map snd $ take 4 $
130+ List.sortBy (compare `on` fst) $
131+ map addDistance possibleNames
132+
133+
134+authorDistance :: String -> Text.Text -> Int
135+authorDistance bad possibility =
136+ abs (Utils.distance bad (Text.unpack possibility))
137+
138+
139+projectDistance :: String -> Text.Text -> Int
140+projectDistance bad possibility =
141+ if possibility == "elm-lang" || possibility == "elm-explorations" then
142+ 0
143+ else
144+ abs (Utils.distance bad (Text.unpack possibility))