1{-# LANGUAGE OverloadedStrings #-}
3 ( Task, Task_, run, throw, mapError
6 , getPackageCacheDirFor
18import Control.Concurrent (forkIO)
19import Control.Concurrent.Chan (Chan, newChan, readChan, writeChan)
20import Control.Monad (forever, join, replicateM_)
21import Control.Monad.Except (ExceptT, runExceptT, throwError, withExceptT)
22import Control.Monad.Reader (ReaderT, runReaderT, ask, asks)
23import Control.Monad.Trans (liftIO)
24import qualified Network.HTTP.Client as Http
25import qualified Network.HTTP.Client.TLS as Http
26import System.Directory (createDirectoryIfMissing)
27import System.FilePath ((</>))
28import qualified System.IO as IO
30import Elm.Package (Name, Version)
31import qualified Elm.Package as Pkg
32import qualified Elm.PerUserCache as PerUserCache
33import qualified Reporting.Exit as Exit
34import qualified Reporting.Progress as Progress
46 ExceptT e (ReaderT Env IO)
51 { _cacheDir :: FilePath
52 , _worker :: IO () -> IO ()
53 , _httpManager :: Http.Manager
54 , _tell :: Progress.Progress -> IO ()
58run :: Progress.Reporter -> Task a -> IO (Maybe a)
59run (Progress.Reporter tell end) task =
60 do root <- PerUserCache.getPackageRoot
62 httpManager <- Http.newManager Http.tlsManagerSettings
63 let env = Env root pool httpManager tell
64 result <- runReaderT (runExceptT task) env
75throw :: e -> Task_ e a
80mapError :: (x -> y) -> Task_ x a -> Task_ y a
89getPackageCacheDir :: Task_ e FilePath
94getPackageCacheDirFor :: Name -> Version -> Task_ e FilePath
95getPackageCacheDirFor name version =
96 do cacheDir <- getPackageCacheDir
97 let dir = cacheDir </> Pkg.toFilePath name </> Pkg.versionToString version
98 liftIO (createDirectoryIfMissing True dir)
106report :: Progress.Progress -> Task_ e ()
108 do tell <- asks _tell
109 liftIO (tell progress)
112getReporter :: Task (Progress.Progress -> IO ())
121withApproval :: Task_ e () -> Task_ e ()
123 do approval <- getApproval
124 if approval then task else return ()
127getApproval :: Task_ e Bool
129 do liftIO $ IO.hFlush IO.stdout
130 input <- liftIO getLine
137 do liftIO $ putStr "Must type 'y' for yes or 'n' for no: "
145silently :: Task_ e a -> Task_ e a
147 do runner <- getSilentRunner
148 result <- liftIO (runner task)
149 either throw return result
152getSilentRunner :: Task_ x (Task_ e a -> IO (Either e a))
155 let silentEnv = env { _tell = \_ -> return () }
156 return $ \task -> runReaderT (runExceptT task) silentEnv
163workerChan :: Chan (Either e a) -> Task_ e a -> Task_ x ()
164workerChan chan task =
167 liftIO $ _worker env $
168 do result <- runReaderT (runExceptT task) env
169 writeChan chan result
172initPool :: Int -> IO (IO () -> IO ())
176 replicateM_ size $ forkIO $ forever $
179 return $ writeChan chan
186runHttp :: (Http.Manager -> (Progress.Progress -> IO ()) -> IO (Either Exit.Exit a)) -> Task a
188 do (Env _ _ manager tell) <- ask
189 result <- liftIO $ fetcher manager tell
190 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