1{-# OPTIONS_GHC -Wall #-}
2{-# LANGUAGE OverloadedStrings #-}
4 ( Task, Task_, run, throw, mapError
7 , getPackageCacheDirFor
19import Control.Concurrent (forkIO)
20import Control.Concurrent.Chan (Chan, newChan, readChan, writeChan)
21import Control.Monad (forever, join, replicateM_)
22import Control.Monad.Except (ExceptT, runExceptT, throwError, withExceptT)
23import Control.Monad.Reader (ReaderT, runReaderT, ask, asks)
24import Control.Monad.Trans (liftIO)
25import qualified Network.HTTP.Client as Http
26import qualified Network.HTTP.Client.TLS as Http
27import System.Directory (createDirectoryIfMissing)
28import System.FilePath ((</>))
29import qualified System.IO as IO
31import Elm.Package (Name, Version)
32import qualified Elm.Package as Pkg
33import qualified Elm.PerUserCache as PerUserCache
34import qualified Reporting.Error as Error
35import qualified Reporting.Progress as Progress
47 ExceptT e (ReaderT Env IO)
52 { _cacheDir :: FilePath
53 , _worker :: IO () -> IO ()
54 , _httpManager :: Http.Manager
55 , _tell :: Progress.Progress -> IO ()
59run :: Progress.Reporter -> Task a -> IO (Maybe a)
60run (Progress.Reporter tell end) task =
61 do root <- PerUserCache.getPackageRoot
63 httpManager <- Http.newManager Http.tlsManagerSettings
64 let env = Env root pool httpManager tell
65 result <- runReaderT (runExceptT task) env
76throw :: e -> Task_ e a
81mapError :: (x -> y) -> Task_ x a -> Task_ y a
90getPackageCacheDir :: Task_ e FilePath
95getPackageCacheDirFor :: Name -> Version -> Task_ e FilePath
96getPackageCacheDirFor name version =
97 do cacheDir <- getPackageCacheDir
98 let dir = cacheDir </> Pkg.toFilePath name </> Pkg.versionToString version
99 liftIO (createDirectoryIfMissing True dir)
107report :: Progress.Progress -> Task_ e ()
109 do tell <- asks _tell
110 liftIO (tell progress)
113getReporter :: Task (Progress.Progress -> IO ())
122withApproval :: Task_ e () -> Task_ e ()
124 do approval <- getApproval
125 if approval then task else return ()
128getApproval :: Task_ e Bool
130 do liftIO $ IO.hFlush IO.stdout
131 input <- liftIO getLine
138 do liftIO $ putStr "Must type 'y' for yes or 'n' for no: "
146silently :: Task_ e a -> Task_ e a
148 do runner <- getSilentRunner
149 result <- liftIO (runner task)
150 either throw return result
153getSilentRunner :: Task_ x (Task_ e a -> IO (Either e a))
156 let silentEnv = env { _tell = \_ -> return () }
157 return $ \task -> runReaderT (runExceptT task) silentEnv
164workerChan :: Chan (Either e a) -> Task_ e a -> Task_ x ()
165workerChan chan task =
168 liftIO $ _worker env $
169 do result <- runReaderT (runExceptT task) env
170 writeChan chan result
173initPool :: Int -> IO (IO () -> IO ())
177 replicateM_ size $ forkIO $ forever $
180 return $ writeChan chan
187runHttp :: (Http.Manager -> (Progress.Progress -> IO ()) -> IO (Either Error.Error a)) -> Task a
189 do (Env _ _ manager tell) <- ask
190 result <- liftIO $ fetcher manager tell
191 either throwError return result
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