1{-# LANGUAGE OverloadedStrings #-}
10 , getPackageCacheDirFor
22import Control.Concurrent (forkIO)
23import Control.Concurrent.Chan (Chan, newChan, readChan, writeChan)
24import Control.Monad (forever, join, replicateM_)
25import Control.Monad.Except (ExceptT, runExceptT, throwError, withExceptT)
26import Control.Monad.Reader (ReaderT, runReaderT, ask, asks)
27import Control.Monad.Trans (liftIO)
28import qualified Network.HTTP.Client as Http
29import qualified Network.HTTP.Client.TLS as Http
30import qualified System.Directory as Dir
31import qualified System.Exit as Exit
32import System.FilePath ((</>))
33import qualified System.IO as IO
35import Elm.Package (Name, Version)
36import qualified Elm.Package as Pkg
37import qualified Elm.PerUserCache as PerUserCache
38import qualified Reporting.Exit as Exit
39import qualified Reporting.Progress as Progress
51 ExceptT e (ReaderT Env IO)
56 { _cacheDir :: FilePath
57 , _worker :: IO () -> IO ()
58 , _httpManager :: Http.Manager
59 , _tell :: Progress.Progress -> IO ()
63try :: Progress.Reporter -> Task a -> IO (Maybe a)
64try (Progress.Reporter tell end) task =
65 do root <- PerUserCache.getPackageRoot
67 httpManager <- Http.newManager Http.tlsManagerSettings
68 let env = Env root pool httpManager tell
69 result <- runReaderT (runExceptT task) env
80run :: Progress.Reporter -> Task a -> IO ()
82 do maybeAnswer <- try reporter task
84 Nothing -> Exit.exitFailure
88throw :: e -> Task_ e a
93mapError :: (x -> y) -> Task_ x a -> Task_ y a
102getPackageCacheDir :: Task_ e FilePath
107getPackageCacheDirFor :: Name -> Version -> Task_ e FilePath
108getPackageCacheDirFor name version =
109 do cacheDir <- getPackageCacheDir
110 let dir = cacheDir </> Pkg.toFilePath name </> Pkg.versionToString version
111 liftIO (Dir.createDirectoryIfMissing True dir)
119report :: Progress.Progress -> Task_ e ()
121 do tell <- asks _tell
122 liftIO (tell progress)
125getReporter :: Task (Progress.Progress -> IO ())
134withApproval :: Task_ e () -> Task_ e ()
136 do approval <- getApproval
137 if approval then task else return ()
140getApproval :: Task_ e Bool
142 do liftIO $ IO.hFlush IO.stdout
143 input <- liftIO getLine
150 do liftIO $ putStr "Must type 'y' for yes or 'n' for no: "
158silently :: Task_ e a -> Task_ e a
160 do runner <- getSilentRunner
161 result <- liftIO (runner task)
162 either throw return result
165getSilentRunner :: Task_ x (Task_ e a -> IO (Either e a))
168 let silentEnv = env { _tell = \_ -> return () }
169 return $ \task -> runReaderT (runExceptT task) silentEnv
176workerChan :: Chan (Either e a) -> Task_ e a -> Task_ x ()
177workerChan chan task =
180 liftIO $ _worker env $
181 do result <- runReaderT (runExceptT task) env
182 writeChan chan result
185initPool :: Int -> IO (IO () -> IO ())
189 replicateM_ size $ forkIO $ forever $
192 return $ writeChan chan
199runHttp :: (Http.Manager -> (Progress.Progress -> IO ()) -> IO (Either Exit.Exit a)) -> Task a
201 do (Env _ _ manager tell) <- ask
202 result <- liftIO $ fetcher manager tell
203 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