1{-# LANGUAGE OverloadedStrings #-}
24import Prelude hiding (zip)
25import qualified Codec.Archive.Zip as Zip
26import Control.Exception (SomeException, handle)
27import qualified Data.Binary as Binary
28import qualified Data.Binary.Get as Binary
29import qualified Data.ByteString.Char8 as BS
30import qualified Data.Digest.Pure.SHA as SHA
31import qualified Data.String as String
32import Network.HTTP (urlEncodeVars)
33import Network.HTTP.Client
34import Network.HTTP.Client.TLS (tlsManagerSettings)
35import Network.HTTP.Types.Header (Header, hAccept, hAcceptEncoding, hUserAgent)
36import Network.HTTP.Types.Method (Method, methodGet, methodPost)
37import qualified Network.HTTP.Client.MultipartFormData as Multi
39import qualified Elm.Version as V
46getManager :: IO Manager
48 newManager tlsManagerSettings
55toUrl :: String -> [(String,String)] -> String
59 _:_ -> url ++ "?" ++ urlEncodeVars params
66get :: Manager -> String -> [Header] -> (Error -> e) -> (BS.ByteString -> IO (Either e a)) -> IO (Either e a)
71post :: Manager -> String -> [Header] -> (Error -> e) -> (BS.ByteString -> IO (Either e a)) -> IO (Either e a)
76fetch :: Method -> Manager -> String -> [Header] -> (Error -> e) -> (BS.ByteString -> IO (Either e a)) -> IO (Either e a)
77fetch methodVerb manager url headers onError onSuccess =
78 handle (handleSomeException url onError) $
79 handle (handleHttpException url onError) $
80 do req0 <- parseUrlThrow url
84 , requestHeaders = addDefaultHeaders headers
86 withResponse req1 manager $ \response ->
87 do chunks <- brConsume (responseBody response)
88 onSuccess (BS.concat chunks)
91addDefaultHeaders :: [Header] -> [Header]
92addDefaultHeaders headers =
93 (hUserAgent, userAgent) : (hAcceptEncoding, "gzip") : headers
96{-# NOINLINE userAgent #-}
97userAgent :: BS.ByteString
99 BS.pack ("elm/" ++ V.toChars V.compiler)
102accept :: BS.ByteString -> Header
112 = BadUrl String String
113 | BadHttp String HttpExceptionContent
114 | BadMystery String SomeException
117handleHttpException :: String -> (Error -> e) -> HttpException -> IO (Either e a)
118handleHttpException url onError httpException =
119 case httpException of
120 InvalidUrlException _ reason ->
121 return (Left (onError (BadUrl url reason)))
123 HttpExceptionRequest _ content ->
124 return (Left (onError (BadHttp url content)))
127handleSomeException :: String -> (Error -> e) -> SomeException -> IO (Either e a)
128handleSomeException url onError exception =
129 return (Left (onError (BadMystery url exception)))
136type Sha = SHA.Digest SHA.SHA1State
139shaToChars :: Sha -> String
153 -> ((Sha, Zip.Archive) -> IO (Either e a))
155getArchive manager url onError err onSuccess =
156 handle (handleSomeException url onError) $
157 handle (handleHttpException url onError) $
158 do req0 <- parseUrlThrow url
162 , requestHeaders = addDefaultHeaders []
164 withResponse req1 manager $ \response ->
165 do result <- readArchive (responseBody response)
167 Nothing -> return (Left err)
168 Just shaAndArchive -> onSuccess shaAndArchive
171readArchive :: BodyReader -> IO (Maybe (Sha, Zip.Archive))
173 readArchiveHelp body $
174 AS 0 SHA.sha1Incremental (Binary.runGetIncremental Binary.get)
180 , _sha :: !(Binary.Decoder SHA.SHA1State)
181 , _zip :: !(Binary.Decoder Zip.Archive)
185readArchiveHelp :: BodyReader -> ArchiveState -> IO (Maybe (Sha, Zip.Archive))
186readArchiveHelp body (AS len sha zip) =
192 do chunk <- brRead body
193 readArchiveHelp body $
195 { _len = len + BS.length chunk
196 , _sha = Binary.pushChunk sha chunk
197 , _zip = k (if BS.null chunk then Nothing else Just chunk)
200 Binary.Done _ _ archive ->
201 return $ Just ( SHA.completeSha1Incremental sha len, archive )
208upload :: Manager -> String -> [Multi.Part] -> IO (Either Error ())
209upload manager url parts =
210 handle (handleSomeException url id) $
211 handle (handleHttpException url id) $
212 do req0 <- parseUrlThrow url
214 Multi.formDataBody parts $
216 { method = methodPost
217 , requestHeaders = addDefaultHeaders []
218 , responseTimeout = responseTimeoutNone
220 withResponse req1 manager $ \_ ->
224filePart :: String -> FilePath -> Multi.Part
225filePart name filePath =
226 Multi.partFileSource (String.fromString name) filePath
229stringPart :: String -> String -> Multi.Part
230stringPart name string =
231 Multi.partBS (String.fromString name) (BS.pack string)
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