1module Elm.Package where
5import qualified Data.Char as Char
6import Data.Function (on)
7import qualified Data.List as List
8import qualified Data.Text as T
9import System.FilePath ((</>))
18 deriving (Eq, Ord, Show)
21type Package = (Name, Version)
31 Name "elm-lang" "core"
36 Name "elm-lang" "virtual-dom"
41 Name "elm-lang" "html"
44toString :: Name -> String
46 user name ++ "/" ++ project name
49toUrl :: Name -> String
51 user name ++ "/" ++ project name
54toFilePath :: Name -> FilePath
56 user name </> project name
59fromString :: String -> Either String Name
61 case break (=='/') string of
62 ( user, '/' : project ) ->
64 Left "You did not provide a user name (user/project)"
66 else if null project then
67 Left "You did not provide a project name (user/project)"
69 else if all (/='/') project then
70 Name user <$> validateProjectName project
73 Left "Expecting only one slash, separating the user and project name (user/project)"
76 Left "There should be a slash separating the user and project name (user/project)"
79whitelistedUppercaseName :: String -> Bool
80whitelistedUppercaseName name =
81 -- These packages were uploaded to package.elm-lang.org before version 0.16,
82 -- when uppercase letters were disallowed in package names.
83 -- They should be considered deprecated and removed from this list once users
84 -- migrate to using the lowercase versions of the names.
95 , "Elm-Align-Distribute"
98 , "Elm-Random-Sampling"
105validateProjectName :: String -> Either String String
106validateProjectName str =
107 if elem ('-','-') (zip str (tail str)) then
108 Left "There is a double dash -- in your package name. It must be a single dash."
110 else if elem '_' str then
111 Left "Underscores are not allowed in package names."
113 else if any Char.isUpper str && not (whitelistedUppercaseName str) then
114 Left "Upper case characters are not allowed in package names."
116 else if not (Char.isLetter (head str)) then
117 Left "Package names must start with a letter."
123instance Binary Name where
124 get = Name <$> get <*> get
125 put (Name user project) =
130instance FromJSON Name where
131 parseJSON (String text) =
133 string = T.unpack text
135 case fromString string of
137 fail ("Ran into an invalid package name: " ++ string ++ "\n\n" ++ msg)
143 fail "Project name must be a string."
146instance ToJSON Name where
148 toJSON (toString name)
153data Version = Version
161initialVersion :: Version
165dummyVersion :: Version
170bumpPatch :: Version -> Version
171bumpPatch (Version major minor patch) =
172 Version major minor (patch + 1)
174bumpMinor :: Version -> Version
175bumpMinor (Version major minor _patch) =
176 Version major (minor + 1) 0
178bumpMajor :: Version -> Version
179bumpMajor (Version major _minor _patch) =
180 Version (major + 1) 0 0
185filterLatest :: (Ord a) => (Version -> a) -> [Version] -> [Version]
186filterLatest characteristic versions =
187 map last (List.groupBy ((==) `on` characteristic) (List.sort versions))
190majorAndMinor :: Version -> (Int,Int)
191majorAndMinor (Version major minor _patch) =
197versionToString :: Version -> String
198versionToString (Version major minor patch) =
199 show major ++ "." ++ show minor ++ "." ++ show patch
202versionFromString :: String -> Either String Version
203versionFromString string =
204 case splitNumbers string of
205 Just [major, minor, patch] ->
206 Right (Version major minor patch)
208 Left "Must have format MAJOR.MINOR.PATCH (e.g. 1.0.2)"
210 splitNumbers :: String -> Maybe [Int]
212 case span Char.isDigit ns of
217 Just [ read numbers ]
219 (numbers, '.':rest) ->
220 (read numbers :) <$> splitNumbers rest
226instance Binary Version where
227 get = Version <$> get <*> get <*> get
228 put (Version major minor patch) =
234instance FromJSON Version where
235 parseJSON (String text) =
236 let string = T.unpack text in
237 case versionFromString string of
243 [ "Ran into an invalid version number: " ++ string
248 fail "Version number must be stored as a string."
251instance ToJSON Version where
253 toJSON (versionToString version)
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list