From a1a43d16f56a8dff1a97f1958d1b995b490eaff3 Mon Sep 17 00:00:00 2001 From: Sibi Prabakaran Date: Fri, 7 Jul 2017 18:13:54 +0530 Subject: [PATCH 01/30] Add ls subcommand --- src/main/Main.hs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/Main.hs b/src/main/Main.hs index 928b5ab645..0cc9563f30 100644 --- a/src/main/Main.hs +++ b/src/main/Main.hs @@ -71,6 +71,7 @@ import Stack.Fetch import Stack.FileWatch import Stack.Ghci import Stack.Hoogle +import Stack.Ls import qualified Stack.IDE as IDE import qualified Stack.Image as Image import Stack.Init @@ -285,6 +286,10 @@ commandLineHandler currentDir progName isInterpreter = complicatedOptions "Print out handy path information" pathCmd Stack.Path.pathParser + addCommand' "ls" + "List latest Stackage snapshots" + lsCmd + lsParser addCommand' "unpack" "Unpack one or more packages locally" unpackCmd From 8bec20e8115f8b63dec16bbaf3af46ad1a4cab6b Mon Sep 17 00:00:00 2001 From: Sibi Prabakaran Date: Fri, 7 Jul 2017 18:14:03 +0530 Subject: [PATCH 02/30] Implement the module implementing the relevant features --- src/Stack/Ls.hs | 181 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 181 insertions(+) create mode 100644 src/Stack/Ls.hs diff --git a/src/Stack/Ls.hs b/src/Stack/Ls.hs new file mode 100644 index 0000000000..0e5bb9e709 --- /dev/null +++ b/src/Stack/Ls.hs @@ -0,0 +1,181 @@ +{-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE ScopedTypeVariables #-} + +module Stack.Ls where + +import Control.Exception (Exception) +import Control.Monad.Catch (MonadThrow) +import Control.Monad.IO.Class (MonadIO, liftIO) +import Control.Monad.Reader (MonadReader) +import Data.Aeson +import qualified Data.Aeson.Types as A +import qualified Data.ByteString.Lazy as BL +import qualified Data.List as L +import Data.Monoid +import Data.Text +import qualified Data.Text.IO as T +import Data.Typeable (Typeable) +import qualified Data.Vector as V +import Network.HTTP.Simple + (Request, Response, addRequestHeader, getResponseBody, httpJSON, + httpJSONEither, httpLbs, parseRequest) +import Network.HTTP.Types.Header (hAccept) +import qualified Options.Applicative as OA +import Path +import Stack.Runners (withBuildConfig) +import Stack.Types.Config +import System.Directory (listDirectory) + +data LsView + = Local + | Remote + deriving (Show, Eq, Ord) + +data SnapshotType + = LtsAndNightly + | Lts + | Nightly + deriving (Show, Eq, Ord) + +data LsCmdOpts = LsCmdOpts + { lsView :: LsView + , lsLtsSnapView :: Bool + , lsNightlySnapView :: Bool + } deriving (Eq, Show, Ord) + +data Snapshot = Snapshot + { snapId :: Text + , snapTitle :: Text + , snapTime :: Text + } deriving (Show, Eq, Ord) + +data SnapshotData = SnapshotData + { snapTotalCounts :: Integer + , snaps :: [[Snapshot]] + } deriving (Show, Eq, Ord) + +toSnapshot :: [Value] -> Snapshot +toSnapshot ((String sid):(String stitle):(String stime):[]) = + Snapshot {snapId = sid, snapTitle = stitle, snapTime = stime} +toSnapshot _ = undefined + +data LsException = + ParseFailure Request + (Response ()) + deriving (Show, Typeable) + +instance Exception LsException + +parseSnapshot :: Value -> A.Parser Snapshot +parseSnapshot = + A.withArray "array of snapshot" (\val -> return $ toSnapshot (V.toList val)) + +instance FromJSON Snapshot where + parseJSON o@(Array _) = parseSnapshot o + parseJSON _ = mempty + +instance FromJSON SnapshotData where + parseJSON (Object s) = + SnapshotData <$> s .: "totalCount" <*> s .: "snapshots" + parseJSON _ = mempty + +displaySnap :: Snapshot -> IO () +displaySnap snapshot = do + T.putStrLn $ "Resolver name: " <> snapId snapshot + T.putStrLn $ snapTitle snapshot + putStrLn "" + putStrLn "" + +displayTime :: Snapshot -> IO () +displayTime snapshot = do + T.putStrLn $ snapTime snapshot + putStrLn "" + +displaySingleSnap :: [Snapshot] -> IO () +displaySingleSnap snapshots = + case snapshots of + [] -> return () + (x:xs) -> do + displayTime x + displaySnap x + mapM_ displaySnap xs + +displaySnapshotData :: SnapshotData -> IO () +displaySnapshotData sdata = + case (L.reverse $ snaps sdata) of + [] -> return () + xs -> mapM_ displaySingleSnap xs + +filterSnapshotData :: SnapshotData -> SnapshotType -> SnapshotData +filterSnapshotData sdata stype = sdata {snaps = filterSnapData} + where + snapdata = snaps sdata + filterSnapData = + case stype of + Lts -> + L.map + (\s -> L.filter (\x -> isPrefixOf "lts" (snapId x)) s) + snapdata + Nightly -> + L.map + (\s -> L.filter (\x -> isPrefixOf "nightly" (snapId x)) s) + snapdata + +displayLocalSnapshot :: [String] -> IO () +displayLocalSnapshot xs = mapM_ putStrLn xs + +handleLocal :: + (MonadIO m, MonadThrow m, MonadReader env m, HasEnvConfig env) + => LsCmdOpts + -> m () +handleLocal lsOpts = do + (instRoot :: Path Abs Dir) <- installationRootDeps + let snapRootDir = parent $ parent $ instRoot + snapData <- liftIO $ listDirectory $ toFilePath snapRootDir + case (lsLtsSnapView lsOpts, lsNightlySnapView lsOpts) of + (True, False) -> + liftIO $ + displayLocalSnapshot $ L.filter (L.isPrefixOf "lts") snapData + (False, True) -> + liftIO $ + displayLocalSnapshot $ L.filter (L.isPrefixOf "night") snapData + _ -> liftIO $ displayLocalSnapshot snapData + +lsCmd :: LsCmdOpts -> GlobalOpts -> IO () +lsCmd lsOpts go = + case (lsView lsOpts) of + Local -> withBuildConfig go (handleLocal lsOpts) + Remote -> do + req <- parseRequest "http://localhost:3000/snapshots" + let req' = addRequestHeader hAccept "application/json" req + result <- httpJSON req' + let snapData = getResponseBody result + case (lsLtsSnapView lsOpts, lsNightlySnapView lsOpts) of + (True, False) -> + liftIO $ + displaySnapshotData $ filterSnapshotData snapData Lts + (False, True) -> + liftIO $ + displaySnapshotData $ filterSnapshotData snapData Nightly + _ -> liftIO $ displaySnapshotData snapData + +lsParser :: OA.Parser LsCmdOpts +lsParser = + LsCmdOpts <$> (OA.hsubparser (lsViewLocalCmd <> lsViewRemoteCmd)) <*> + (OA.switch + ((OA.long "lts") <> (OA.short 'l') <> OA.help ("Just show lts view"))) <*> + (OA.switch + ((OA.long "nightly") <> (OA.short 'n') <> + OA.help ("Just show nightly view"))) + +lsViewLocalCmd :: OA.Mod OA.CommandFields LsView +lsViewLocalCmd = + OA.command + "local" + (OA.info (pure Local) (OA.progDesc "View it in your local system")) + +lsViewRemoteCmd :: OA.Mod OA.CommandFields LsView +lsViewRemoteCmd = + OA.command + "remote" + (OA.info (pure Remote) (OA.progDesc "View remote snapshot")) From 7d87e8726f2e36a4dcae0ffe726d05abf64c3c83 Mon Sep 17 00:00:00 2001 From: Sibi Prabakaran Date: Fri, 7 Jul 2017 18:14:14 +0530 Subject: [PATCH 03/30] Expose the module --- stack.cabal | 1 + 1 file changed, 1 insertion(+) diff --git a/stack.cabal b/stack.cabal index c4ea24f123..b4378a288a 100644 --- a/stack.cabal +++ b/stack.cabal @@ -114,6 +114,7 @@ library Stack.IDE Stack.Image Stack.Init + Stack.Ls Stack.New Stack.Nix Stack.Options.BenchParser From e7910e5e9d67c6847884ef43fe5df50b04ef9a21 Mon Sep 17 00:00:00 2001 From: Sibi Prabakaran Date: Fri, 7 Jul 2017 18:15:16 +0530 Subject: [PATCH 04/30] Code cleanup --- src/Stack/Ls.hs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/Stack/Ls.hs b/src/Stack/Ls.hs index 0e5bb9e709..4533024f7e 100644 --- a/src/Stack/Ls.hs +++ b/src/Stack/Ls.hs @@ -9,7 +9,6 @@ import Control.Monad.IO.Class (MonadIO, liftIO) import Control.Monad.Reader (MonadReader) import Data.Aeson import qualified Data.Aeson.Types as A -import qualified Data.ByteString.Lazy as BL import qualified Data.List as L import Data.Monoid import Data.Text @@ -18,7 +17,7 @@ import Data.Typeable (Typeable) import qualified Data.Vector as V import Network.HTTP.Simple (Request, Response, addRequestHeader, getResponseBody, httpJSON, - httpJSONEither, httpLbs, parseRequest) + parseRequest) import Network.HTTP.Types.Header (hAccept) import qualified Options.Applicative as OA import Path @@ -32,8 +31,7 @@ data LsView deriving (Show, Eq, Ord) data SnapshotType - = LtsAndNightly - | Lts + = Lts | Nightly deriving (Show, Eq, Ord) From c8d4badea3d26cfa2b2b2d0c60970946ecaa2f2a Mon Sep 17 00:00:00 2001 From: Sibi Prabakaran Date: Fri, 7 Jul 2017 18:28:34 +0530 Subject: [PATCH 05/30] More cleanup and some formatting done --- src/Stack/Ls.hs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Stack/Ls.hs b/src/Stack/Ls.hs index 4533024f7e..3e5d175001 100644 --- a/src/Stack/Ls.hs +++ b/src/Stack/Ls.hs @@ -23,6 +23,7 @@ import qualified Options.Applicative as OA import Path import Stack.Runners (withBuildConfig) import Stack.Types.Config +import System.Console.ANSI import System.Directory (listDirectory) data LsView @@ -82,11 +83,12 @@ displaySnap snapshot = do T.putStrLn $ "Resolver name: " <> snapId snapshot T.putStrLn $ snapTitle snapshot putStrLn "" - putStrLn "" displayTime :: Snapshot -> IO () displayTime snapshot = do + setSGR [SetColor Foreground Dull Green] T.putStrLn $ snapTime snapshot + setSGR [Reset] putStrLn "" displaySingleSnap :: [Snapshot] -> IO () @@ -129,7 +131,8 @@ handleLocal :: handleLocal lsOpts = do (instRoot :: Path Abs Dir) <- installationRootDeps let snapRootDir = parent $ parent $ instRoot - snapData <- liftIO $ listDirectory $ toFilePath snapRootDir + snapData' <- liftIO $ listDirectory $ toFilePath snapRootDir + let snapData = L.sort snapData' case (lsLtsSnapView lsOpts, lsNightlySnapView lsOpts) of (True, False) -> liftIO $ From 91b0dab9bf23a0ba82a2a4133500186c1712622e Mon Sep 17 00:00:00 2001 From: Sibi Prabakaran Date: Fri, 7 Jul 2017 18:31:17 +0530 Subject: [PATCH 06/30] Handle exception scenario --- src/Stack/Ls.hs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/Stack/Ls.hs b/src/Stack/Ls.hs index 3e5d175001..ee1049433c 100644 --- a/src/Stack/Ls.hs +++ b/src/Stack/Ls.hs @@ -4,6 +4,7 @@ module Stack.Ls where import Control.Exception (Exception) +import Control.Exception.Safe (impureThrow) import Control.Monad.Catch (MonadThrow) import Control.Monad.IO.Class (MonadIO, liftIO) import Control.Monad.Reader (MonadReader) @@ -16,8 +17,7 @@ import qualified Data.Text.IO as T import Data.Typeable (Typeable) import qualified Data.Vector as V import Network.HTTP.Simple - (Request, Response, addRequestHeader, getResponseBody, httpJSON, - parseRequest) + (addRequestHeader, getResponseBody, httpJSON, parseRequest) import Network.HTTP.Types.Header (hAccept) import qualified Options.Applicative as OA import Path @@ -56,11 +56,10 @@ data SnapshotData = SnapshotData toSnapshot :: [Value] -> Snapshot toSnapshot ((String sid):(String stitle):(String stime):[]) = Snapshot {snapId = sid, snapTitle = stitle, snapTime = stime} -toSnapshot _ = undefined +toSnapshot val = impureThrow $ ParseFailure val data LsException = - ParseFailure Request - (Response ()) + ParseFailure [Value] deriving (Show, Typeable) instance Exception LsException From 3e3ce5fb83d1a839a71630533fbcbb4248664896 Mon Sep 17 00:00:00 2001 From: Sibi Prabakaran Date: Fri, 7 Jul 2017 18:36:30 +0530 Subject: [PATCH 07/30] Update to the stackage server url --- src/Stack/Ls.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Stack/Ls.hs b/src/Stack/Ls.hs index ee1049433c..39b12b16b1 100644 --- a/src/Stack/Ls.hs +++ b/src/Stack/Ls.hs @@ -146,7 +146,7 @@ lsCmd lsOpts go = case (lsView lsOpts) of Local -> withBuildConfig go (handleLocal lsOpts) Remote -> do - req <- parseRequest "http://localhost:3000/snapshots" + req <- parseRequest "https://www.stackage.org/snapshots" let req' = addRequestHeader hAccept "application/json" req result <- httpJSON req' let snapData = getResponseBody result From e4b400cb9c6f630f8254fb640c21c04943f0673e Mon Sep 17 00:00:00 2001 From: Sibi Prabakaran Date: Fri, 7 Jul 2017 19:27:50 +0530 Subject: [PATCH 08/30] Improve help messages --- src/Stack/Ls.hs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Stack/Ls.hs b/src/Stack/Ls.hs index 39b12b16b1..8b52f9a22e 100644 --- a/src/Stack/Ls.hs +++ b/src/Stack/Ls.hs @@ -163,16 +163,17 @@ lsParser :: OA.Parser LsCmdOpts lsParser = LsCmdOpts <$> (OA.hsubparser (lsViewLocalCmd <> lsViewRemoteCmd)) <*> (OA.switch - ((OA.long "lts") <> (OA.short 'l') <> OA.help ("Just show lts view"))) <*> + ((OA.long "lts") <> (OA.short 'l') <> + OA.help ("Only show lts snapshots"))) <*> (OA.switch ((OA.long "nightly") <> (OA.short 'n') <> - OA.help ("Just show nightly view"))) + OA.help ("Only show nightly snapshots"))) lsViewLocalCmd :: OA.Mod OA.CommandFields LsView lsViewLocalCmd = OA.command "local" - (OA.info (pure Local) (OA.progDesc "View it in your local system")) + (OA.info (pure Local) (OA.progDesc "View local snapshot")) lsViewRemoteCmd :: OA.Mod OA.CommandFields LsView lsViewRemoteCmd = From 9e50072f90ad24ce05c3877e3c76ebc749a75d8e Mon Sep 17 00:00:00 2001 From: Sibi Prabakaran Date: Fri, 7 Jul 2017 19:30:26 +0530 Subject: [PATCH 09/30] Update Changelog --- ChangeLog.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ChangeLog.md b/ChangeLog.md index f5415505b9..a2d4829ca6 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -15,6 +15,8 @@ Behavior changes: Other enhancements: +* A new sub command `ls` has been introduced to stack to view + local and remote snapshots present in the system. * `stack setup` allow to control options passed to ghcjs-boot with `--ghcjs-boot-options` (one word at a time) and `--[no-]ghcjs-boot-clean` * Updates to store-0.4.1, which has improved performance and better error From 579828695a468e1ed33e4a30810321c82d51ed34 Mon Sep 17 00:00:00 2001 From: Sibi Prabakaran Date: Fri, 7 Jul 2017 22:44:22 +0530 Subject: [PATCH 10/30] Try fixing build error in stack-7.10 yaml environment --- stack-7.10.yaml | 1 + stack.cabal | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/stack-7.10.yaml b/stack-7.10.yaml index 40b1b8966c..d314a503f8 100644 --- a/stack-7.10.yaml +++ b/stack-7.10.yaml @@ -38,3 +38,4 @@ extra-deps: - hackage-security-0.5.2.2 - echo-0.1.3 - mintty-0.1.1 +- directory-1.3.0.0 diff --git a/stack.cabal b/stack.cabal index b4378a288a..fb3fc8eef0 100644 --- a/stack.cabal +++ b/stack.cabal @@ -207,7 +207,7 @@ library , containers >= 0.5.5.1 , cryptonite >= 0.19 && < 0.22 , cryptonite-conduit >= 0.1 && < 0.3 - , directory >= 1.2.1.0 && < 1.4 + , directory >= 1.2.5.0 && < 1.4 , echo >= 0.1.3 && < 0.2 , either , errors < 2.2 From bcb7f750220fefb5ce74ea0fdef5d1e29631de60 Mon Sep 17 00:00:00 2001 From: Sibi Prabakaran Date: Fri, 7 Jul 2017 22:59:34 +0530 Subject: [PATCH 11/30] Lower constraint because of process dependency See this for more information: https://travis-ci.org/commercialhaskell/stack/jobs/251237747 --- stack-7.10.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stack-7.10.yaml b/stack-7.10.yaml index d314a503f8..c773688813 100644 --- a/stack-7.10.yaml +++ b/stack-7.10.yaml @@ -38,4 +38,4 @@ extra-deps: - hackage-security-0.5.2.2 - echo-0.1.3 - mintty-0.1.1 -- directory-1.3.0.0 +- directory-1.2.5.1 From 0e14de96c9d77c68ffdf08db6ae1ce16ae1808b9 Mon Sep 17 00:00:00 2001 From: Sibi Prabakaran Date: Sat, 8 Jul 2017 02:30:49 +0530 Subject: [PATCH 12/30] Hlint style fixes Have to do this to avoid travis CI failures --- src/Stack/Ls.hs | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/Stack/Ls.hs b/src/Stack/Ls.hs index 8b52f9a22e..3dfe21a566 100644 --- a/src/Stack/Ls.hs +++ b/src/Stack/Ls.hs @@ -54,7 +54,7 @@ data SnapshotData = SnapshotData } deriving (Show, Eq, Ord) toSnapshot :: [Value] -> Snapshot -toSnapshot ((String sid):(String stitle):(String stime):[]) = +toSnapshot [String sid, String stitle, String stime] = Snapshot {snapId = sid, snapTitle = stitle, snapTime = stime} toSnapshot val = impureThrow $ ParseFailure val @@ -101,7 +101,7 @@ displaySingleSnap snapshots = displaySnapshotData :: SnapshotData -> IO () displaySnapshotData sdata = - case (L.reverse $ snaps sdata) of + case L.reverse $ snaps sdata of [] -> return () xs -> mapM_ displaySingleSnap xs @@ -113,11 +113,11 @@ filterSnapshotData sdata stype = sdata {snaps = filterSnapData} case stype of Lts -> L.map - (\s -> L.filter (\x -> isPrefixOf "lts" (snapId x)) s) + (\s -> L.filter (\x -> "lts" `isPrefixOf` snapId x) s) snapdata Nightly -> L.map - (\s -> L.filter (\x -> isPrefixOf "nightly" (snapId x)) s) + (\s -> L.filter (\x -> "nightly" `isPrefixOf` snapId x) s) snapdata displayLocalSnapshot :: [String] -> IO () @@ -129,7 +129,7 @@ handleLocal :: -> m () handleLocal lsOpts = do (instRoot :: Path Abs Dir) <- installationRootDeps - let snapRootDir = parent $ parent $ instRoot + let snapRootDir = parent $ parent instRoot snapData' <- liftIO $ listDirectory $ toFilePath snapRootDir let snapData = L.sort snapData' case (lsLtsSnapView lsOpts, lsNightlySnapView lsOpts) of @@ -143,7 +143,7 @@ handleLocal lsOpts = do lsCmd :: LsCmdOpts -> GlobalOpts -> IO () lsCmd lsOpts go = - case (lsView lsOpts) of + case lsView lsOpts of Local -> withBuildConfig go (handleLocal lsOpts) Remote -> do req <- parseRequest "https://www.stackage.org/snapshots" @@ -161,13 +161,13 @@ lsCmd lsOpts go = lsParser :: OA.Parser LsCmdOpts lsParser = - LsCmdOpts <$> (OA.hsubparser (lsViewLocalCmd <> lsViewRemoteCmd)) <*> - (OA.switch - ((OA.long "lts") <> (OA.short 'l') <> - OA.help ("Only show lts snapshots"))) <*> - (OA.switch - ((OA.long "nightly") <> (OA.short 'n') <> - OA.help ("Only show nightly snapshots"))) + LsCmdOpts <$> OA.hsubparser (lsViewLocalCmd <> lsViewRemoteCmd) <*> + OA.switch + (OA.long "lts" <> OA.short 'l' <> + OA.help "Only show lts snapshots") <*> + OA.switch + (OA.long "nightly" <> OA.short 'n' <> + OA.help "Only show nightly snapshots") lsViewLocalCmd :: OA.Mod OA.CommandFields LsView lsViewLocalCmd = From 9947d9ee49712cbc6a240c82e970c8849115968c Mon Sep 17 00:00:00 2001 From: Sibi Prabakaran Date: Sat, 8 Jul 2017 02:33:49 +0530 Subject: [PATCH 13/30] Only export lsCmd and lsParser --- src/Stack/Ls.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Stack/Ls.hs b/src/Stack/Ls.hs index 3dfe21a566..8de3d8dbbb 100644 --- a/src/Stack/Ls.hs +++ b/src/Stack/Ls.hs @@ -1,7 +1,7 @@ {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE ScopedTypeVariables #-} -module Stack.Ls where +module Stack.Ls (lsCmd, lsParser) where import Control.Exception (Exception) import Control.Exception.Safe (impureThrow) From ef9aa32100775449050c200a7b7297eaeebb3de5 Mon Sep 17 00:00:00 2001 From: Sibi Prabakaran Date: Sat, 8 Jul 2017 02:44:08 +0530 Subject: [PATCH 14/30] Fix another hlint failure https://travis-ci.org/commercialhaskell/stack/jobs/251311494#L251 --- src/Stack/Ls.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Stack/Ls.hs b/src/Stack/Ls.hs index 8de3d8dbbb..4c15920295 100644 --- a/src/Stack/Ls.hs +++ b/src/Stack/Ls.hs @@ -58,7 +58,7 @@ toSnapshot [String sid, String stitle, String stime] = Snapshot {snapId = sid, snapTitle = stitle, snapTime = stime} toSnapshot val = impureThrow $ ParseFailure val -data LsException = +newtype LsException = ParseFailure [Value] deriving (Show, Typeable) From d51783229752b98b0d0cd300a59efb06ed00f876 Mon Sep 17 00:00:00 2001 From: Sibi Prabakaran Date: Sat, 8 Jul 2017 03:41:12 +0530 Subject: [PATCH 15/30] Add no warn for unused-top-binds --- src/Stack/Ls.hs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Stack/Ls.hs b/src/Stack/Ls.hs index 4c15920295..53c8c5d7dd 100644 --- a/src/Stack/Ls.hs +++ b/src/Stack/Ls.hs @@ -1,3 +1,4 @@ +{-# OPTIONS_GHC -fno-warn-unused-top-binds #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE ScopedTypeVariables #-} From fa7fb8b885b83d72abb3f1677f741b57792d3dcd Mon Sep 17 00:00:00 2001 From: Sibi Prabakaran Date: Sat, 8 Jul 2017 04:32:47 +0530 Subject: [PATCH 16/30] Fix warning at the code level itself --- src/Stack/Ls.hs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Stack/Ls.hs b/src/Stack/Ls.hs index 53c8c5d7dd..8471330d61 100644 --- a/src/Stack/Ls.hs +++ b/src/Stack/Ls.hs @@ -1,4 +1,3 @@ -{-# OPTIONS_GHC -fno-warn-unused-top-binds #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE ScopedTypeVariables #-} @@ -50,7 +49,7 @@ data Snapshot = Snapshot } deriving (Show, Eq, Ord) data SnapshotData = SnapshotData - { snapTotalCounts :: Integer + { _snapTotalCounts :: Integer , snaps :: [[Snapshot]] } deriving (Show, Eq, Ord) From 99edd1b44307e9c183f8df19014c7cbd1589680c Mon Sep 17 00:00:00 2001 From: Sibi Prabakaran Date: Sat, 8 Jul 2017 17:55:44 +0530 Subject: [PATCH 17/30] Also add tls setting add stackage is https --- src/Stack/Ls.hs | 55 ++++++++++++++++++++++++++++--------------------- 1 file changed, 31 insertions(+), 24 deletions(-) diff --git a/src/Stack/Ls.hs b/src/Stack/Ls.hs index 8471330d61..633732e826 100644 --- a/src/Stack/Ls.hs +++ b/src/Stack/Ls.hs @@ -1,7 +1,10 @@ {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE ScopedTypeVariables #-} -module Stack.Ls (lsCmd, lsParser) where +module Stack.Ls + ( lsCmd + , lsParser + ) where import Control.Exception (Exception) import Control.Exception.Safe (impureThrow) @@ -17,7 +20,8 @@ import qualified Data.Text.IO as T import Data.Typeable (Typeable) import qualified Data.Vector as V import Network.HTTP.Simple - (addRequestHeader, getResponseBody, httpJSON, parseRequest) + (addRequestHeader, getResponseBody, httpJSON, parseRequest, + setRequestManager) import Network.HTTP.Types.Header (hAccept) import qualified Options.Applicative as OA import Path @@ -25,6 +29,7 @@ import Stack.Runners (withBuildConfig) import Stack.Types.Config import System.Console.ANSI import System.Directory (listDirectory) +import Network.HTTP.Client.TLS (getGlobalManager) data LsView = Local @@ -55,7 +60,11 @@ data SnapshotData = SnapshotData toSnapshot :: [Value] -> Snapshot toSnapshot [String sid, String stitle, String stime] = - Snapshot {snapId = sid, snapTitle = stitle, snapTime = stime} + Snapshot + { snapId = sid + , snapTitle = stitle + , snapTime = stime + } toSnapshot val = impureThrow $ ParseFailure val newtype LsException = @@ -106,15 +115,16 @@ displaySnapshotData sdata = xs -> mapM_ displaySingleSnap xs filterSnapshotData :: SnapshotData -> SnapshotType -> SnapshotData -filterSnapshotData sdata stype = sdata {snaps = filterSnapData} +filterSnapshotData sdata stype = + sdata + { snaps = filterSnapData + } where snapdata = snaps sdata filterSnapData = case stype of Lts -> - L.map - (\s -> L.filter (\x -> "lts" `isPrefixOf` snapId x) s) - snapdata + L.map (\s -> L.filter (\x -> "lts" `isPrefixOf` snapId x) s) snapdata Nightly -> L.map (\s -> L.filter (\x -> "nightly" `isPrefixOf` snapId x) s) @@ -123,10 +133,9 @@ filterSnapshotData sdata stype = sdata {snaps = filterSnapData} displayLocalSnapshot :: [String] -> IO () displayLocalSnapshot xs = mapM_ putStrLn xs -handleLocal :: - (MonadIO m, MonadThrow m, MonadReader env m, HasEnvConfig env) - => LsCmdOpts - -> m () +handleLocal + :: (MonadIO m, MonadThrow m, MonadReader env m, HasEnvConfig env) + => LsCmdOpts -> m () handleLocal lsOpts = do (instRoot :: Path Abs Dir) <- installationRootDeps let snapRootDir = parent $ parent instRoot @@ -134,11 +143,9 @@ handleLocal lsOpts = do let snapData = L.sort snapData' case (lsLtsSnapView lsOpts, lsNightlySnapView lsOpts) of (True, False) -> - liftIO $ - displayLocalSnapshot $ L.filter (L.isPrefixOf "lts") snapData + liftIO $ displayLocalSnapshot $ L.filter (L.isPrefixOf "lts") snapData (False, True) -> - liftIO $ - displayLocalSnapshot $ L.filter (L.isPrefixOf "night") snapData + liftIO $ displayLocalSnapshot $ L.filter (L.isPrefixOf "night") snapData _ -> liftIO $ displayLocalSnapshot snapData lsCmd :: LsCmdOpts -> GlobalOpts -> IO () @@ -147,27 +154,27 @@ lsCmd lsOpts go = Local -> withBuildConfig go (handleLocal lsOpts) Remote -> do req <- parseRequest "https://www.stackage.org/snapshots" - let req' = addRequestHeader hAccept "application/json" req + mgr <- getGlobalManager + let req' = + setRequestManager mgr $ + addRequestHeader hAccept "application/json" req result <- httpJSON req' let snapData = getResponseBody result case (lsLtsSnapView lsOpts, lsNightlySnapView lsOpts) of (True, False) -> - liftIO $ - displaySnapshotData $ filterSnapshotData snapData Lts + liftIO $ displaySnapshotData $ filterSnapshotData snapData Lts (False, True) -> - liftIO $ - displaySnapshotData $ filterSnapshotData snapData Nightly + liftIO $ displaySnapshotData $ filterSnapshotData snapData Nightly _ -> liftIO $ displaySnapshotData snapData lsParser :: OA.Parser LsCmdOpts lsParser = LsCmdOpts <$> OA.hsubparser (lsViewLocalCmd <> lsViewRemoteCmd) <*> OA.switch - (OA.long "lts" <> OA.short 'l' <> - OA.help "Only show lts snapshots") <*> + (OA.long "lts" <> OA.short 'l' <> OA.help "Only show lts snapshots") <*> OA.switch - (OA.long "nightly" <> OA.short 'n' <> - OA.help "Only show nightly snapshots") + (OA.long "nightly" <> OA.short 'n' <> + OA.help "Only show nightly snapshots") lsViewLocalCmd :: OA.Mod OA.CommandFields LsView lsViewLocalCmd = From 1c92ae5906a5be6b8d5f82c7937018e7db31c79d Mon Sep 17 00:00:00 2001 From: Sibi Prabakaran Date: Sun, 12 Nov 2017 20:30:13 +0530 Subject: [PATCH 18/30] Have working code based on the feedback. --- src/Stack/Ls.hs | 131 +++++++++++++++++++++++++++++++++++------------- 1 file changed, 97 insertions(+), 34 deletions(-) diff --git a/src/Stack/Ls.hs b/src/Stack/Ls.hs index 633732e826..6b4225d506 100644 --- a/src/Stack/Ls.hs +++ b/src/Stack/Ls.hs @@ -1,4 +1,5 @@ {-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE RecordWildCards #-} {-# LANGUAGE ScopedTypeVariables #-} module Stack.Ls @@ -6,8 +7,7 @@ module Stack.Ls , lsParser ) where -import Control.Exception (Exception) -import Control.Exception.Safe (impureThrow) +import Control.Exception (Exception, throw) import Control.Monad.Catch (MonadThrow) import Control.Monad.IO.Class (MonadIO, liftIO) import Control.Monad.Reader (MonadReader) @@ -41,12 +41,46 @@ data SnapshotType | Nightly deriving (Show, Eq, Ord) +data LsCmds = LsSnapshot SnapshotOpts deriving (Eq, Show, Ord) + +data SnapshotOpts = SnapshotOpts { + soptViewType :: LsView + , soptLtsSnapView :: Bool + , soptNightlySnapView :: Bool +} deriving (Eq, Show, Ord) + data LsCmdOpts = LsCmdOpts - { lsView :: LsView - , lsLtsSnapView :: Bool - , lsNightlySnapView :: Bool + { lsView :: LsCmds } deriving (Eq, Show, Ord) +lsParser :: OA.Parser LsCmdOpts +lsParser = LsCmdOpts <$> OA.hsubparser lsSnapCmd + +lsCmdOptsParser :: OA.Parser LsCmds +lsCmdOptsParser = fmap LsSnapshot lsViewSnapCmd + +lsViewSnapCmd :: OA.Parser SnapshotOpts +lsViewSnapCmd = SnapshotOpts <$> OA.hsubparser (lsViewRemoteCmd <> lsViewLocalCmd) <*> OA.switch (OA.long "some-flag" <> OA.help "Set the flag") <*> OA.switch (OA.long "ome-flag" <> OA.help "Set the flag") + +lsSnapCmd :: OA.Mod OA.CommandFields LsCmds +lsSnapCmd = OA.command "snapshots" (OA.info lsCmdOptsParser (OA.progDesc "View local snapshot")) + + + +-- <*> +-- OA.switch +-- (OA.long "lts" <> OA.short 'l' <> OA.help "Only show lts snapshots") <*> +-- OA.switch +-- (OA.long "nightly" <> OA.short 'n' <> +-- OA.help "Only show nightly snapshots") <*> +-- OA.option +-- OA.auto +-- (OA.long "package" <> OA.help "Show packages list" <> OA.short 'p' <> +-- OA.value Nothing <> +-- OA.metavar "RESOLVER") + + + data Snapshot = Snapshot { snapId :: Text , snapTitle :: Text @@ -58,6 +92,48 @@ data SnapshotData = SnapshotData , snaps :: [[Snapshot]] } deriving (Show, Eq, Ord) +instance FromJSON Snapshot where + parseJSON o@(Array _) = parseSnapshot o + parseJSON _ = mempty + +instance FromJSON SnapshotData where + parseJSON (Object s) = + SnapshotData <$> s .: "totalCount" <*> s .: "snapshots" + parseJSON _ = mempty + +data Package = Package + { pkgSynopsis :: Text + , pkgVersion :: Text + , pkgName :: Text + , _pkgCore :: Bool + } deriving (Show, Eq, Ord) + +data PackageSnapshot = PackageSnapshot + { pkgSnapName :: Text + , pkgSnapCreated :: Text + , pkgSnapGhc :: Text + } deriving (Show, Eq, Ord) + +instance FromJSON PackageSnapshot where + parseJSON (Object s) = + PackageSnapshot <$> s .: "name" <*> s .: "created" <*> s .: "ghc" + parseJSON _ = mempty + +instance FromJSON Package where + parseJSON (Object s) = + Package <$> s .: "synopsis" <*> s .: "version" <*> s .: "name" <*> + s .: "isCore" + parseJSON _ = mempty + +data Packages = Packages + { pkgPackages :: [Package] + , pkgSnapshot :: PackageSnapshot + } deriving (Show, Eq, Ord) + +instance FromJSON Packages where + parseJSON (Object s) = Packages <$> s .: "packages" <*> s .: "snapshot" + parseJSON _ = mempty + toSnapshot :: [Value] -> Snapshot toSnapshot [String sid, String stitle, String stime] = Snapshot @@ -65,7 +141,7 @@ toSnapshot [String sid, String stitle, String stime] = , snapTitle = stitle , snapTime = stime } -toSnapshot val = impureThrow $ ParseFailure val +toSnapshot val = throw $ ParseFailure val newtype LsException = ParseFailure [Value] @@ -77,15 +153,6 @@ parseSnapshot :: Value -> A.Parser Snapshot parseSnapshot = A.withArray "array of snapshot" (\val -> return $ toSnapshot (V.toList val)) -instance FromJSON Snapshot where - parseJSON o@(Array _) = parseSnapshot o - parseJSON _ = mempty - -instance FromJSON SnapshotData where - parseJSON (Object s) = - SnapshotData <$> s .: "totalCount" <*> s .: "snapshots" - parseJSON _ = mempty - displaySnap :: Snapshot -> IO () displaySnap snapshot = do T.putStrLn $ "Resolver name: " <> snapId snapshot @@ -141,46 +208,42 @@ handleLocal lsOpts = do let snapRootDir = parent $ parent instRoot snapData' <- liftIO $ listDirectory $ toFilePath snapRootDir let snapData = L.sort snapData' - case (lsLtsSnapView lsOpts, lsNightlySnapView lsOpts) of - (True, False) -> - liftIO $ displayLocalSnapshot $ L.filter (L.isPrefixOf "lts") snapData - (False, True) -> - liftIO $ displayLocalSnapshot $ L.filter (L.isPrefixOf "night") snapData - _ -> liftIO $ displayLocalSnapshot snapData + case (lsView lsOpts) of + LsSnapshot SnapshotOpts{..} -> + case (soptLtsSnapView, soptNightlySnapView) of + (True, False) -> + liftIO $ displayLocalSnapshot $ L.filter (L.isPrefixOf "lts") snapData + (False, True) -> + liftIO $ displayLocalSnapshot $ L.filter (L.isPrefixOf "night") snapData + _ -> liftIO $ displayLocalSnapshot snapData lsCmd :: LsCmdOpts -> GlobalOpts -> IO () -lsCmd lsOpts go = +lsCmd lsOpts go = do case lsView lsOpts of + LsSnapshot SnapshotOpts{..} -> case soptViewType of Local -> withBuildConfig go (handleLocal lsOpts) Remote -> do - req <- parseRequest "https://www.stackage.org/snapshots" + req <- parseRequest urlInfo mgr <- getGlobalManager let req' = setRequestManager mgr $ addRequestHeader hAccept "application/json" req result <- httpJSON req' let snapData = getResponseBody result - case (lsLtsSnapView lsOpts, lsNightlySnapView lsOpts) of + case (soptLtsSnapView, soptNightlySnapView) of (True, False) -> liftIO $ displaySnapshotData $ filterSnapshotData snapData Lts (False, True) -> liftIO $ displaySnapshotData $ filterSnapshotData snapData Nightly _ -> liftIO $ displaySnapshotData snapData - -lsParser :: OA.Parser LsCmdOpts -lsParser = - LsCmdOpts <$> OA.hsubparser (lsViewLocalCmd <> lsViewRemoteCmd) <*> - OA.switch - (OA.long "lts" <> OA.short 'l' <> OA.help "Only show lts snapshots") <*> - OA.switch - (OA.long "nightly" <> OA.short 'n' <> - OA.help "Only show nightly snapshots") + where + urlInfo = "https://www.stackage.org/snapshots" lsViewLocalCmd :: OA.Mod OA.CommandFields LsView lsViewLocalCmd = OA.command "local" - (OA.info (pure Local) (OA.progDesc "View local snapshot")) + (OA.info (pure Remote) (OA.progDesc "View local snapshot")) lsViewRemoteCmd :: OA.Mod OA.CommandFields LsView lsViewRemoteCmd = From 7c0e5671fd5cd15f19dfeb84b21e7391f54c3f24 Mon Sep 17 00:00:00 2001 From: Sibi Prabakaran Date: Sun, 12 Nov 2017 20:30:35 +0530 Subject: [PATCH 19/30] Expose Stack.Ls --- package.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/package.yaml b/package.yaml index 207a3104a9..3fee454b2c 100644 --- a/package.yaml +++ b/package.yaml @@ -181,6 +181,7 @@ library: - Stack.IDE - Stack.Image - Stack.Init + - Stack.Ls - Stack.New - Stack.Nix - Stack.Options.BenchParser From 1dea318280d40c5497947711090229b2fde5a7c0 Mon Sep 17 00:00:00 2001 From: Sibi Prabakaran Date: Sun, 12 Nov 2017 20:39:17 +0530 Subject: [PATCH 20/30] Cleanup code --- src/Stack/Ls.hs | 127 ++++++++++++++++++------------------------------ 1 file changed, 47 insertions(+), 80 deletions(-) diff --git a/src/Stack/Ls.hs b/src/Stack/Ls.hs index 6b4225d506..78978d5d49 100644 --- a/src/Stack/Ls.hs +++ b/src/Stack/Ls.hs @@ -41,13 +41,15 @@ data SnapshotType | Nightly deriving (Show, Eq, Ord) -data LsCmds = LsSnapshot SnapshotOpts deriving (Eq, Show, Ord) +data LsCmds = + LsSnapshot SnapshotOpts + deriving (Eq, Show, Ord) -data SnapshotOpts = SnapshotOpts { - soptViewType :: LsView - , soptLtsSnapView :: Bool +data SnapshotOpts = SnapshotOpts + { soptViewType :: LsView + , soptLtsSnapView :: Bool , soptNightlySnapView :: Bool -} deriving (Eq, Show, Ord) + } deriving (Eq, Show, Ord) data LsCmdOpts = LsCmdOpts { lsView :: LsCmds @@ -60,26 +62,19 @@ lsCmdOptsParser :: OA.Parser LsCmds lsCmdOptsParser = fmap LsSnapshot lsViewSnapCmd lsViewSnapCmd :: OA.Parser SnapshotOpts -lsViewSnapCmd = SnapshotOpts <$> OA.hsubparser (lsViewRemoteCmd <> lsViewLocalCmd) <*> OA.switch (OA.long "some-flag" <> OA.help "Set the flag") <*> OA.switch (OA.long "ome-flag" <> OA.help "Set the flag") +lsViewSnapCmd = + SnapshotOpts <$> OA.hsubparser (lsViewRemoteCmd <> lsViewLocalCmd) <*> + OA.switch + (OA.long "lts" <> OA.short 'l' <> OA.help "Only show lts snapshots") <*> + OA.switch + (OA.long "nightly" <> OA.short 'n' <> + OA.help "Only show nightly snapshots") lsSnapCmd :: OA.Mod OA.CommandFields LsCmds -lsSnapCmd = OA.command "snapshots" (OA.info lsCmdOptsParser (OA.progDesc "View local snapshot")) - - - --- <*> --- OA.switch --- (OA.long "lts" <> OA.short 'l' <> OA.help "Only show lts snapshots") <*> --- OA.switch --- (OA.long "nightly" <> OA.short 'n' <> --- OA.help "Only show nightly snapshots") <*> --- OA.option --- OA.auto --- (OA.long "package" <> OA.help "Show packages list" <> OA.short 'p' <> --- OA.value Nothing <> --- OA.metavar "RESOLVER") - - +lsSnapCmd = + OA.command + "snapshots" + (OA.info lsCmdOptsParser (OA.progDesc "View local snapshot")) data Snapshot = Snapshot { snapId :: Text @@ -101,39 +96,6 @@ instance FromJSON SnapshotData where SnapshotData <$> s .: "totalCount" <*> s .: "snapshots" parseJSON _ = mempty -data Package = Package - { pkgSynopsis :: Text - , pkgVersion :: Text - , pkgName :: Text - , _pkgCore :: Bool - } deriving (Show, Eq, Ord) - -data PackageSnapshot = PackageSnapshot - { pkgSnapName :: Text - , pkgSnapCreated :: Text - , pkgSnapGhc :: Text - } deriving (Show, Eq, Ord) - -instance FromJSON PackageSnapshot where - parseJSON (Object s) = - PackageSnapshot <$> s .: "name" <*> s .: "created" <*> s .: "ghc" - parseJSON _ = mempty - -instance FromJSON Package where - parseJSON (Object s) = - Package <$> s .: "synopsis" <*> s .: "version" <*> s .: "name" <*> - s .: "isCore" - parseJSON _ = mempty - -data Packages = Packages - { pkgPackages :: [Package] - , pkgSnapshot :: PackageSnapshot - } deriving (Show, Eq, Ord) - -instance FromJSON Packages where - parseJSON (Object s) = Packages <$> s .: "packages" <*> s .: "snapshot" - parseJSON _ = mempty - toSnapshot :: [Value] -> Snapshot toSnapshot [String sid, String stitle, String stime] = Snapshot @@ -209,33 +171,38 @@ handleLocal lsOpts = do snapData' <- liftIO $ listDirectory $ toFilePath snapRootDir let snapData = L.sort snapData' case (lsView lsOpts) of - LsSnapshot SnapshotOpts{..} -> - case (soptLtsSnapView, soptNightlySnapView) of - (True, False) -> - liftIO $ displayLocalSnapshot $ L.filter (L.isPrefixOf "lts") snapData - (False, True) -> - liftIO $ displayLocalSnapshot $ L.filter (L.isPrefixOf "night") snapData - _ -> liftIO $ displayLocalSnapshot snapData + LsSnapshot SnapshotOpts {..} -> + case (soptLtsSnapView, soptNightlySnapView) of + (True, False) -> + liftIO $ + displayLocalSnapshot $ L.filter (L.isPrefixOf "lts") snapData + (False, True) -> + liftIO $ + displayLocalSnapshot $ L.filter (L.isPrefixOf "night") snapData + _ -> liftIO $ displayLocalSnapshot snapData lsCmd :: LsCmdOpts -> GlobalOpts -> IO () lsCmd lsOpts go = do case lsView lsOpts of - LsSnapshot SnapshotOpts{..} -> case soptViewType of - Local -> withBuildConfig go (handleLocal lsOpts) - Remote -> do - req <- parseRequest urlInfo - mgr <- getGlobalManager - let req' = - setRequestManager mgr $ - addRequestHeader hAccept "application/json" req - result <- httpJSON req' - let snapData = getResponseBody result - case (soptLtsSnapView, soptNightlySnapView) of - (True, False) -> - liftIO $ displaySnapshotData $ filterSnapshotData snapData Lts - (False, True) -> - liftIO $ displaySnapshotData $ filterSnapshotData snapData Nightly - _ -> liftIO $ displaySnapshotData snapData + LsSnapshot SnapshotOpts {..} -> + case soptViewType of + Local -> withBuildConfig go (handleLocal lsOpts) + Remote -> do + req <- parseRequest urlInfo + mgr <- getGlobalManager + let req' = + setRequestManager mgr $ + addRequestHeader hAccept "application/json" req + result <- httpJSON req' + let snapData = getResponseBody result + case (soptLtsSnapView, soptNightlySnapView) of + (True, False) -> + liftIO $ + displaySnapshotData $ filterSnapshotData snapData Lts + (False, True) -> + liftIO $ + displaySnapshotData $ filterSnapshotData snapData Nightly + _ -> liftIO $ displaySnapshotData snapData where urlInfo = "https://www.stackage.org/snapshots" @@ -243,7 +210,7 @@ lsViewLocalCmd :: OA.Mod OA.CommandFields LsView lsViewLocalCmd = OA.command "local" - (OA.info (pure Remote) (OA.progDesc "View local snapshot")) + (OA.info (pure Local) (OA.progDesc "View local snapshot")) lsViewRemoteCmd :: OA.Mod OA.CommandFields LsView lsViewRemoteCmd = From 0eb4078bfd4bc95c65d470cd4f1af5da81487f19 Mon Sep 17 00:00:00 2001 From: Sibi Prabakaran Date: Sun, 12 Nov 2017 21:46:27 +0530 Subject: [PATCH 21/30] Use pager implementation --- src/Stack/Ls.hs | 34 +++++++++++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/src/Stack/Ls.hs b/src/Stack/Ls.hs index 78978d5d49..e7ca9147d5 100644 --- a/src/Stack/Ls.hs +++ b/src/Stack/Ls.hs @@ -12,10 +12,13 @@ import Control.Monad.Catch (MonadThrow) import Control.Monad.IO.Class (MonadIO, liftIO) import Control.Monad.Reader (MonadReader) import Data.Aeson +import Data.ByteString.Lazy.Char8 (ByteString, pack, intercalate) +import qualified Data.ByteString.Lazy.Char8 as BC import qualified Data.Aeson.Types as A import qualified Data.List as L import Data.Monoid -import Data.Text +import Data.Text hiding (pack, intercalate) +import qualified Data.Text as T import qualified Data.Text.IO as T import Data.Typeable (Typeable) import qualified Data.Vector as V @@ -28,6 +31,7 @@ import Path import Stack.Runners (withBuildConfig) import Stack.Types.Config import System.Console.ANSI +import System.Process.PagerEditor import System.Directory (listDirectory) import Network.HTTP.Client.TLS (getGlobalManager) @@ -121,6 +125,15 @@ displaySnap snapshot = do T.putStrLn $ snapTitle snapshot putStrLn "" +displayTime' :: Snapshot -> [ByteString] +displayTime' Snapshot {..} = [pack $ T.unpack snapTime] + +displaySnap' :: Snapshot -> [ByteString] +displaySnap' Snapshot {..} = + [ "Resolver name: " <> (pack $ T.unpack snapId) + , "\n" <> pack (T.unpack snapTitle) <> "\n\n" + ] + displayTime :: Snapshot -> IO () displayTime snapshot = do setSGR [SetColor Foreground Dull Green] @@ -137,11 +150,23 @@ displaySingleSnap snapshots = displaySnap x mapM_ displaySnap xs +displaySingleSnap' :: [Snapshot] -> ByteString +displaySingleSnap' snapshots = + case snapshots of + [] -> mempty + (x:xs) -> + let snaps = + displayTime' x <> ["\n\n"] <> displaySnap' x <> + (L.concatMap displaySnap' xs) + in BC.concat snaps + displaySnapshotData :: SnapshotData -> IO () displaySnapshotData sdata = case L.reverse $ snaps sdata of [] -> return () - xs -> mapM_ displaySingleSnap xs + xs -> + let snaps = BC.concat $ L.map displaySingleSnap' xs + in pageByteString snaps filterSnapshotData :: SnapshotData -> SnapshotType -> SnapshotData filterSnapshotData sdata stype = @@ -160,7 +185,10 @@ filterSnapshotData sdata stype = snapdata displayLocalSnapshot :: [String] -> IO () -displayLocalSnapshot xs = mapM_ putStrLn xs +displayLocalSnapshot xs = pageByteString $ localSnaptoByteString xs + +localSnaptoByteString :: [String] -> ByteString +localSnaptoByteString xs = intercalate "\n" $ L.map pack xs handleLocal :: (MonadIO m, MonadThrow m, MonadReader env m, HasEnvConfig env) From fef24431c21b88be91b6b0a4845189472cafe5c0 Mon Sep 17 00:00:00 2001 From: Sibi Prabakaran Date: Sun, 12 Nov 2017 21:49:18 +0530 Subject: [PATCH 22/30] Remove dead code and do cleanup --- src/Stack/Ls.hs | 40 ++++++++-------------------------------- 1 file changed, 8 insertions(+), 32 deletions(-) diff --git a/src/Stack/Ls.hs b/src/Stack/Ls.hs index e7ca9147d5..6560d5456d 100644 --- a/src/Stack/Ls.hs +++ b/src/Stack/Ls.hs @@ -19,7 +19,6 @@ import qualified Data.List as L import Data.Monoid import Data.Text hiding (pack, intercalate) import qualified Data.Text as T -import qualified Data.Text.IO as T import Data.Typeable (Typeable) import qualified Data.Vector as V import Network.HTTP.Simple @@ -30,7 +29,6 @@ import qualified Options.Applicative as OA import Path import Stack.Runners (withBuildConfig) import Stack.Types.Config -import System.Console.ANSI import System.Process.PagerEditor import System.Directory (listDirectory) import Network.HTTP.Client.TLS (getGlobalManager) @@ -119,45 +117,23 @@ parseSnapshot :: Value -> A.Parser Snapshot parseSnapshot = A.withArray "array of snapshot" (\val -> return $ toSnapshot (V.toList val)) -displaySnap :: Snapshot -> IO () -displaySnap snapshot = do - T.putStrLn $ "Resolver name: " <> snapId snapshot - T.putStrLn $ snapTitle snapshot - putStrLn "" +displayTime :: Snapshot -> [ByteString] +displayTime Snapshot {..} = [pack $ T.unpack snapTime] -displayTime' :: Snapshot -> [ByteString] -displayTime' Snapshot {..} = [pack $ T.unpack snapTime] - -displaySnap' :: Snapshot -> [ByteString] -displaySnap' Snapshot {..} = +displaySnap :: Snapshot -> [ByteString] +displaySnap Snapshot {..} = [ "Resolver name: " <> (pack $ T.unpack snapId) , "\n" <> pack (T.unpack snapTitle) <> "\n\n" ] -displayTime :: Snapshot -> IO () -displayTime snapshot = do - setSGR [SetColor Foreground Dull Green] - T.putStrLn $ snapTime snapshot - setSGR [Reset] - putStrLn "" - -displaySingleSnap :: [Snapshot] -> IO () +displaySingleSnap :: [Snapshot] -> ByteString displaySingleSnap snapshots = - case snapshots of - [] -> return () - (x:xs) -> do - displayTime x - displaySnap x - mapM_ displaySnap xs - -displaySingleSnap' :: [Snapshot] -> ByteString -displaySingleSnap' snapshots = case snapshots of [] -> mempty (x:xs) -> let snaps = - displayTime' x <> ["\n\n"] <> displaySnap' x <> - (L.concatMap displaySnap' xs) + displayTime x <> ["\n\n"] <> displaySnap x <> + (L.concatMap displaySnap xs) in BC.concat snaps displaySnapshotData :: SnapshotData -> IO () @@ -165,7 +141,7 @@ displaySnapshotData sdata = case L.reverse $ snaps sdata of [] -> return () xs -> - let snaps = BC.concat $ L.map displaySingleSnap' xs + let snaps = BC.concat $ L.map displaySingleSnap xs in pageByteString snaps filterSnapshotData :: SnapshotData -> SnapshotType -> SnapshotData From 28f11ffd7820b1eb8bb249dd909d782cccc04523 Mon Sep 17 00:00:00 2001 From: Sibi Prabakaran Date: Sun, 12 Nov 2017 22:20:39 +0530 Subject: [PATCH 23/30] Change help message --- src/main/Main.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/Main.hs b/src/main/Main.hs index 17105c91d9..c1b06201eb 100644 --- a/src/main/Main.hs +++ b/src/main/Main.hs @@ -293,7 +293,7 @@ commandLineHandler currentDir progName isInterpreter = complicatedOptions pathCmd Stack.Path.pathParser addCommand' "ls" - "List latest Stackage snapshots" + "List command. (Supports snapshots)" lsCmd lsParser addCommand' "unpack" From 5cd1db7749ff1f666d943974b63f25a55255f3c3 Mon Sep 17 00:00:00 2001 From: Sibi Prabakaran Date: Sun, 19 Nov 2017 19:26:32 +0530 Subject: [PATCH 24/30] Fix hlint style issues --- src/Stack/Ls.hs | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/src/Stack/Ls.hs b/src/Stack/Ls.hs index 6560d5456d..e0f88d82a2 100644 --- a/src/Stack/Ls.hs +++ b/src/Stack/Ls.hs @@ -114,15 +114,14 @@ newtype LsException = instance Exception LsException parseSnapshot :: Value -> A.Parser Snapshot -parseSnapshot = - A.withArray "array of snapshot" (\val -> return $ toSnapshot (V.toList val)) +parseSnapshot = A.withArray "array of snapshot" (return . toSnapshot . V.toList) displayTime :: Snapshot -> [ByteString] displayTime Snapshot {..} = [pack $ T.unpack snapTime] displaySnap :: Snapshot -> [ByteString] displaySnap Snapshot {..} = - [ "Resolver name: " <> (pack $ T.unpack snapId) + [ "Resolver name: " <> pack (T.unpack snapId) , "\n" <> pack (T.unpack snapTitle) <> "\n\n" ] @@ -133,7 +132,7 @@ displaySingleSnap snapshots = (x:xs) -> let snaps = displayTime x <> ["\n\n"] <> displaySnap x <> - (L.concatMap displaySnap xs) + L.concatMap displaySnap xs in BC.concat snaps displaySnapshotData :: SnapshotData -> IO () @@ -153,12 +152,9 @@ filterSnapshotData sdata stype = snapdata = snaps sdata filterSnapData = case stype of - Lts -> - L.map (\s -> L.filter (\x -> "lts" `isPrefixOf` snapId x) s) snapdata + Lts -> L.map (L.filter (\x -> "lts" `isPrefixOf` snapId x)) snapdata Nightly -> - L.map - (\s -> L.filter (\x -> "nightly" `isPrefixOf` snapId x) s) - snapdata + L.map (L.filter (\x -> "nightly" `isPrefixOf` snapId x)) snapdata displayLocalSnapshot :: [String] -> IO () displayLocalSnapshot xs = pageByteString $ localSnaptoByteString xs @@ -174,7 +170,7 @@ handleLocal lsOpts = do let snapRootDir = parent $ parent instRoot snapData' <- liftIO $ listDirectory $ toFilePath snapRootDir let snapData = L.sort snapData' - case (lsView lsOpts) of + case lsView lsOpts of LsSnapshot SnapshotOpts {..} -> case (soptLtsSnapView, soptNightlySnapView) of (True, False) -> @@ -186,7 +182,7 @@ handleLocal lsOpts = do _ -> liftIO $ displayLocalSnapshot snapData lsCmd :: LsCmdOpts -> GlobalOpts -> IO () -lsCmd lsOpts go = do +lsCmd lsOpts go = case lsView lsOpts of LsSnapshot SnapshotOpts {..} -> case soptViewType of From d412dbb05f5356a25431c340aec47c49adc03d18 Mon Sep 17 00:00:00 2001 From: Sibi Prabakaran Date: Mon, 18 Dec 2017 00:20:12 +0530 Subject: [PATCH 25/30] By default, use Local snapshot if none specified --- src/Stack/Ls.hs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Stack/Ls.hs b/src/Stack/Ls.hs index e0f88d82a2..90f51e9b72 100644 --- a/src/Stack/Ls.hs +++ b/src/Stack/Ls.hs @@ -26,6 +26,7 @@ import Network.HTTP.Simple setRequestManager) import Network.HTTP.Types.Header (hAccept) import qualified Options.Applicative as OA +import Options.Applicative ((<|>)) import Path import Stack.Runners (withBuildConfig) import Stack.Types.Config @@ -58,14 +59,15 @@ data LsCmdOpts = LsCmdOpts } deriving (Eq, Show, Ord) lsParser :: OA.Parser LsCmdOpts -lsParser = LsCmdOpts <$> OA.hsubparser lsSnapCmd +lsParser = LsCmdOpts <$> (OA.hsubparser lsSnapCmd) lsCmdOptsParser :: OA.Parser LsCmds lsCmdOptsParser = fmap LsSnapshot lsViewSnapCmd lsViewSnapCmd :: OA.Parser SnapshotOpts lsViewSnapCmd = - SnapshotOpts <$> OA.hsubparser (lsViewRemoteCmd <> lsViewLocalCmd) <*> + SnapshotOpts <$> + (OA.hsubparser (lsViewRemoteCmd <> lsViewLocalCmd) <|> pure Local) <*> OA.switch (OA.long "lts" <> OA.short 'l' <> OA.help "Only show lts snapshots") <*> OA.switch From 19d880b23898060c3564daf08c456751fceced20 Mon Sep 17 00:00:00 2001 From: Sibi Prabakaran Date: Mon, 18 Dec 2017 01:39:58 +0530 Subject: [PATCH 26/30] Add pageText to stream Text via pager --- src/System/Process/PagerEditor.hs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/System/Process/PagerEditor.hs b/src/System/Process/PagerEditor.hs index 37f2bb515e..f3031bd068 100644 --- a/src/System/Process/PagerEditor.hs +++ b/src/System/Process/PagerEditor.hs @@ -7,6 +7,7 @@ module System.Process.PagerEditor (-- * Pager pageWriter ,pageByteString + ,pageText ,pageBuilder ,pageFile ,pageString @@ -29,6 +30,7 @@ import System.FilePath (()) import System.Process (createProcess,shell,proc,waitForProcess,StdStream (CreatePipe) ,CreateProcess(std_in, close_fds, delegate_ctlc)) import System.IO (hClose,hPutStr,readFile,stdout) +import qualified Data.Text.IO as T -- | Run pager, providing a function that writes to the pager's input. pageWriter :: (Handle -> IO ()) -> IO () @@ -55,6 +57,10 @@ pageWriter writer = pageByteString :: ByteString -> IO () pageByteString = pageWriter . flip hPut +-- | Run pager to display a 'Text' +pageText :: Text -> IO () +pageText = pageWriter . flip T.hPutStr + -- | Run pager to display a ByteString-Builder. pageBuilder :: Builder -> IO () pageBuilder = pageWriter . flip hPutBuilder From 1f8d99b706273196a1c94285a1aad66087dc74ac Mon Sep 17 00:00:00 2001 From: Sibi Prabakaran Date: Mon, 18 Dec 2017 01:40:28 +0530 Subject: [PATCH 27/30] More changes to ls sub-command Now the interface is similar to previous commands but we have done some minor changes: If a user gives just `stack ls snapshots`, then by default we show the local snapshots available. Also based on @mgsloan's input, I don't always use pager now. Also a new convienence API has been added to `PagerEditor.hs` which exports a function `pageText`. We use that in our module to pass `Text` content to pager. (We were using ByteString previously). --- src/Stack/Ls.hs | 99 +++++++++++++++++++++++++++++-------------------- 1 file changed, 58 insertions(+), 41 deletions(-) diff --git a/src/Stack/Ls.hs b/src/Stack/Ls.hs index 90f51e9b72..5da6a06fc5 100644 --- a/src/Stack/Ls.hs +++ b/src/Stack/Ls.hs @@ -12,13 +12,13 @@ import Control.Monad.Catch (MonadThrow) import Control.Monad.IO.Class (MonadIO, liftIO) import Control.Monad.Reader (MonadReader) import Data.Aeson -import Data.ByteString.Lazy.Char8 (ByteString, pack, intercalate) -import qualified Data.ByteString.Lazy.Char8 as BC +import Stack.Types.Runner import qualified Data.Aeson.Types as A import qualified Data.List as L import Data.Monoid import Data.Text hiding (pack, intercalate) import qualified Data.Text as T +import qualified Data.Text.IO as T import Data.Typeable (Typeable) import qualified Data.Vector as V import Network.HTTP.Simple @@ -30,7 +30,7 @@ import Options.Applicative ((<|>)) import Path import Stack.Runners (withBuildConfig) import Stack.Types.Config -import System.Process.PagerEditor +import System.Process.PagerEditor (pageText) import System.Directory (listDirectory) import Network.HTTP.Client.TLS (getGlobalManager) @@ -78,7 +78,9 @@ lsSnapCmd :: OA.Mod OA.CommandFields LsCmds lsSnapCmd = OA.command "snapshots" - (OA.info lsCmdOptsParser (OA.progDesc "View local snapshot")) + (OA.info + lsCmdOptsParser + (OA.progDesc "View local snapshot (default option)")) data Snapshot = Snapshot { snapId :: Text @@ -118,16 +120,14 @@ instance Exception LsException parseSnapshot :: Value -> A.Parser Snapshot parseSnapshot = A.withArray "array of snapshot" (return . toSnapshot . V.toList) -displayTime :: Snapshot -> [ByteString] -displayTime Snapshot {..} = [pack $ T.unpack snapTime] +displayTime :: Snapshot -> [Text] +displayTime Snapshot {..} = [snapTime] -displaySnap :: Snapshot -> [ByteString] +displaySnap :: Snapshot -> [Text] displaySnap Snapshot {..} = - [ "Resolver name: " <> pack (T.unpack snapId) - , "\n" <> pack (T.unpack snapTitle) <> "\n\n" - ] + ["Resolver name: " <> snapId, "\n" <> snapTitle <> "\n\n"] -displaySingleSnap :: [Snapshot] -> ByteString +displaySingleSnap :: [Snapshot] -> Text displaySingleSnap snapshots = case snapshots of [] -> mempty @@ -135,15 +135,19 @@ displaySingleSnap snapshots = let snaps = displayTime x <> ["\n\n"] <> displaySnap x <> L.concatMap displaySnap xs - in BC.concat snaps + in T.concat snaps -displaySnapshotData :: SnapshotData -> IO () -displaySnapshotData sdata = +renderData :: Bool -> Text -> IO () +renderData True content = pageText content +renderData False content = T.putStr content + +displaySnapshotData :: Bool -> SnapshotData -> IO () +displaySnapshotData term sdata = case L.reverse $ snaps sdata of [] -> return () xs -> - let snaps = BC.concat $ L.map displaySingleSnap xs - in pageByteString snaps + let snaps = T.concat $ L.map displaySingleSnap xs + in renderData term snaps filterSnapshotData :: SnapshotData -> SnapshotType -> SnapshotData filterSnapshotData sdata stype = @@ -158,17 +162,18 @@ filterSnapshotData sdata stype = Nightly -> L.map (L.filter (\x -> "nightly" `isPrefixOf` snapId x)) snapdata -displayLocalSnapshot :: [String] -> IO () -displayLocalSnapshot xs = pageByteString $ localSnaptoByteString xs +displayLocalSnapshot :: Bool -> [String] -> IO () +displayLocalSnapshot term xs = renderData term (localSnaptoText xs) -localSnaptoByteString :: [String] -> ByteString -localSnaptoByteString xs = intercalate "\n" $ L.map pack xs +localSnaptoText :: [String] -> Text +localSnaptoText xs = T.intercalate "\n" $ L.map T.pack xs handleLocal :: (MonadIO m, MonadThrow m, MonadReader env m, HasEnvConfig env) => LsCmdOpts -> m () handleLocal lsOpts = do (instRoot :: Path Abs Dir) <- installationRootDeps + isStdoutTerminal <- view terminalL let snapRootDir = parent $ parent instRoot snapData' <- liftIO $ listDirectory $ toFilePath snapRootDir let snapData = L.sort snapData' @@ -177,11 +182,40 @@ handleLocal lsOpts = do case (soptLtsSnapView, soptNightlySnapView) of (True, False) -> liftIO $ - displayLocalSnapshot $ L.filter (L.isPrefixOf "lts") snapData + displayLocalSnapshot isStdoutTerminal $ + L.filter (L.isPrefixOf "lts") snapData (False, True) -> liftIO $ - displayLocalSnapshot $ L.filter (L.isPrefixOf "night") snapData - _ -> liftIO $ displayLocalSnapshot snapData + displayLocalSnapshot isStdoutTerminal $ + L.filter (L.isPrefixOf "night") snapData + _ -> liftIO $ displayLocalSnapshot isStdoutTerminal snapData + +handleRemote + :: (MonadIO m, MonadThrow m, MonadReader env m, HasEnvConfig env) + => LsCmdOpts -> m () +handleRemote lsOpts = do + req <- liftIO $ parseRequest urlInfo + mgr <- liftIO $ getGlobalManager + isStdoutTerminal <- view terminalL + let req' = + setRequestManager mgr $ + addRequestHeader hAccept "application/json" req + result <- httpJSON req' + let snapData = getResponseBody result + case lsView lsOpts of + LsSnapshot SnapshotOpts {..} -> + case (soptLtsSnapView, soptNightlySnapView) of + (True, False) -> + liftIO $ + displaySnapshotData isStdoutTerminal $ + filterSnapshotData snapData Lts + (False, True) -> + liftIO $ + displaySnapshotData isStdoutTerminal $ + filterSnapshotData snapData Nightly + _ -> liftIO $ displaySnapshotData isStdoutTerminal snapData + where + urlInfo = "https://www.stackage.org/snapshots" lsCmd :: LsCmdOpts -> GlobalOpts -> IO () lsCmd lsOpts go = @@ -189,24 +223,7 @@ lsCmd lsOpts go = LsSnapshot SnapshotOpts {..} -> case soptViewType of Local -> withBuildConfig go (handleLocal lsOpts) - Remote -> do - req <- parseRequest urlInfo - mgr <- getGlobalManager - let req' = - setRequestManager mgr $ - addRequestHeader hAccept "application/json" req - result <- httpJSON req' - let snapData = getResponseBody result - case (soptLtsSnapView, soptNightlySnapView) of - (True, False) -> - liftIO $ - displaySnapshotData $ filterSnapshotData snapData Lts - (False, True) -> - liftIO $ - displaySnapshotData $ filterSnapshotData snapData Nightly - _ -> liftIO $ displaySnapshotData snapData - where - urlInfo = "https://www.stackage.org/snapshots" + Remote -> withBuildConfig go (handleRemote lsOpts) lsViewLocalCmd :: OA.Mod OA.CommandFields LsView lsViewLocalCmd = From b29dbed842e4871a3d39e023d08c4eda133c815a Mon Sep 17 00:00:00 2001 From: Sibi Prabakaran Date: Mon, 18 Dec 2017 02:58:11 +0530 Subject: [PATCH 28/30] Update changelog --- ChangeLog.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/ChangeLog.md b/ChangeLog.md index fb6d019713..f69cac9623 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -10,6 +10,12 @@ Behaviour changes: Other enhancements: +* A new sub command `ls` has been introduced to stack to view + local and remote snapshots present in the system. Use `stack ls + snapshots --help` to get more details about it. +* `pageText` function introduced in `System.Process.PagerEditor` + module. + Bug fixes: * For versions of Cabal before 1.24, ensure that the dependencies of @@ -252,8 +258,6 @@ Behavior changes: Other enhancements: -* A new sub command `ls` has been introduced to stack to view - local and remote snapshots present in the system. * `stack setup` allow to control options passed to ghcjs-boot with `--ghcjs-boot-options` (one word at a time) and `--[no-]ghcjs-boot-clean` * `stack setup` now accepts a `--install-cabal VERSION` option which From 16e5b253c5896843ad72699a799f725308784e98 Mon Sep 17 00:00:00 2001 From: Sibi Prabakaran Date: Mon, 18 Dec 2017 02:58:24 +0530 Subject: [PATCH 29/30] Fix hlint style issues --- src/Stack/Ls.hs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Stack/Ls.hs b/src/Stack/Ls.hs index 5da6a06fc5..024f0ae06a 100644 --- a/src/Stack/Ls.hs +++ b/src/Stack/Ls.hs @@ -44,7 +44,7 @@ data SnapshotType | Nightly deriving (Show, Eq, Ord) -data LsCmds = +newtype LsCmds = LsSnapshot SnapshotOpts deriving (Eq, Show, Ord) @@ -54,12 +54,12 @@ data SnapshotOpts = SnapshotOpts , soptNightlySnapView :: Bool } deriving (Eq, Show, Ord) -data LsCmdOpts = LsCmdOpts +newtype LsCmdOpts = LsCmdOpts { lsView :: LsCmds } deriving (Eq, Show, Ord) lsParser :: OA.Parser LsCmdOpts -lsParser = LsCmdOpts <$> (OA.hsubparser lsSnapCmd) +lsParser = LsCmdOpts <$> OA.hsubparser lsSnapCmd lsCmdOptsParser :: OA.Parser LsCmds lsCmdOptsParser = fmap LsSnapshot lsViewSnapCmd @@ -195,7 +195,7 @@ handleRemote => LsCmdOpts -> m () handleRemote lsOpts = do req <- liftIO $ parseRequest urlInfo - mgr <- liftIO $ getGlobalManager + mgr <- liftIO getGlobalManager isStdoutTerminal <- view terminalL let req' = setRequestManager mgr $ From 947cbc8e647f169cd65dbd50d945960883f335c6 Mon Sep 17 00:00:00 2001 From: Sibi Prabakaran Date: Mon, 18 Dec 2017 05:54:33 +0530 Subject: [PATCH 30/30] Remove API change from changelog --- ChangeLog.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/ChangeLog.md b/ChangeLog.md index f69cac9623..3224a2927f 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -13,8 +13,6 @@ Other enhancements: * A new sub command `ls` has been introduced to stack to view local and remote snapshots present in the system. Use `stack ls snapshots --help` to get more details about it. -* `pageText` function introduced in `System.Process.PagerEditor` - module. Bug fixes: