1{-# LANGUAGE OverloadedStrings #-}
23import Prelude hiding (zip)
24import qualified Codec.Archive.Zip as Zip
25import Control.Exception (SomeException, handle)
26import qualified Data.Binary as Binary
27import qualified Data.Binary.Get as Binary
28import qualified Data.ByteString.Char8 as BS
29import qualified Data.Digest.Pure.SHA as SHA
30import qualified Data.String as String
31import Network.HTTP (urlEncodeVars)
32import Network.HTTP.Client
33import Network.HTTP.Client.TLS (tlsManagerSettings)
34import Network.HTTP.Types.Header (Header, hAccept, hAcceptEncoding, hUserAgent)
35import Network.HTTP.Types.Method (methodPost)
36import qualified Network.HTTP.Client.MultipartFormData as Multi
38import qualified Elm.Version as V
45getManager :: IO Manager
47 newManager tlsManagerSettings
54toUrl :: String -> [(String,String)] -> String
58 _:_ -> url ++ "?" ++ urlEncodeVars params
65post :: Manager -> String -> [Header] -> (Error -> e) -> (BS.ByteString -> IO (Either e a)) -> IO (Either e a)
66post manager url headers onError onSuccess =
67 handle (handleSomeException url onError) $
68 handle (handleHttpException url onError) $
69 do req0 <- parseUrlThrow url
73 , requestHeaders = addDefaultHeaders headers
75 withResponse req1 manager $ \response ->
76 do chunks <- brConsume (responseBody response)
77 onSuccess (BS.concat chunks)
80addDefaultHeaders :: [Header] -> [Header]
81addDefaultHeaders headers =
82 (hUserAgent, userAgent) : (hAcceptEncoding, "gzip") : headers
85{-# NOINLINE userAgent #-}
86userAgent :: BS.ByteString
88 BS.pack ("elm/" ++ V.toChars V.compiler)
91accept :: BS.ByteString -> Header
101 = BadUrl String String
102 | BadHttp String HttpExceptionContent
103 | BadMystery String SomeException
106handleHttpException :: String -> (Error -> e) -> HttpException -> IO (Either e a)
107handleHttpException url onError httpException =
108 case httpException of
109 InvalidUrlException _ reason ->
110 return (Left (onError (BadUrl url reason)))
112 HttpExceptionRequest _ content ->
113 return (Left (onError (BadHttp url content)))
116handleSomeException :: String -> (Error -> e) -> SomeException -> IO (Either e a)
117handleSomeException url onError exception =
118 return (Left (onError (BadMystery url exception)))
125type Sha = SHA.Digest SHA.SHA1State
128shaToChars :: Sha -> String
142 -> ((Sha, Zip.Archive) -> IO (Either e a))
144fetchArchive manager url onError err onSuccess =
145 handle (handleSomeException url onError) $
146 handle (handleHttpException url onError) $
147 do req0 <- parseUrlThrow url
150 { method = methodPost
151 , requestHeaders = addDefaultHeaders []
153 withResponse req1 manager $ \response ->
154 do result <- readArchive (responseBody response)
156 Nothing -> return (Left err)
157 Just shaAndArchive -> onSuccess shaAndArchive
160readArchive :: BodyReader -> IO (Maybe (Sha, Zip.Archive))
162 readArchiveHelp body $
163 AS 0 SHA.sha1Incremental (Binary.runGetIncremental Binary.get)
169 , _sha :: !(Binary.Decoder SHA.SHA1State)
170 , _zip :: !(Binary.Decoder Zip.Archive)
174readArchiveHelp :: BodyReader -> ArchiveState -> IO (Maybe (Sha, Zip.Archive))
175readArchiveHelp body (AS len sha zip) =
181 do chunk <- brRead body
182 readArchiveHelp body $
184 { _len = len + BS.length chunk
185 , _sha = Binary.pushChunk sha chunk
186 , _zip = k (if BS.null chunk then Nothing else Just chunk)
189 Binary.Done _ _ archive ->
190 return $ Just ( SHA.completeSha1Incremental sha len, archive )
197upload :: Manager -> String -> [Multi.Part] -> IO (Either Error ())
198upload manager url parts =
199 handle (handleSomeException url id) $
200 handle (handleHttpException url id) $
201 do req0 <- parseUrlThrow url
203 Multi.formDataBody parts $
205 { method = methodPost
206 , requestHeaders = addDefaultHeaders []
207 , responseTimeout = responseTimeoutNone
209 withResponse req1 manager $ \_ ->
213filePart :: String -> FilePath -> Multi.Part
214filePart name filePath =
215 Multi.partFileSource (String.fromString name) filePath
218stringPart :: String -> String -> Multi.Part
219stringPart name string =
220 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