From 44c52165a8b54dd686fb2d735b5568b69c48eecc Mon Sep 17 00:00:00 2001 From: Nicolas Mattia Date: Sun, 8 Sep 2019 19:43:31 +0200 Subject: [PATCH] Prettify logs --- package.yaml | 1 + src/Niv/Cli.hs | 86 ++++++++++++++++++++++++----------------------- src/Niv/Logger.hs | 40 ++++++++++++++++++++++ 3 files changed, 85 insertions(+), 42 deletions(-) create mode 100644 src/Niv/Logger.hs diff --git a/package.yaml b/package.yaml index 479fa29..18c2d4c 100644 --- a/package.yaml +++ b/package.yaml @@ -21,6 +21,7 @@ extra-source-files: dependencies: - aeson - aeson-pretty + - ansi-terminal - base < 5 - bytestring - directory diff --git a/src/Niv/Cli.hs b/src/Niv/Cli.hs index ae61137..5706aad 100644 --- a/src/Niv/Cli.hs +++ b/src/Niv/Cli.hs @@ -17,6 +17,7 @@ import Data.FileEmbed (embedFile) import Data.Hashable (Hashable) import Data.Maybe (fromMaybe) import Data.String.QQ (s) +import Niv.Logger import Niv.GitHub import Niv.Update import System.Exit (exitFailure, ExitCode(ExitSuccess)) @@ -166,34 +167,35 @@ parseCmdInit = Opts.info (pure cmdInit <**> Opts.helper) $ mconcat desc cmdInit :: IO () cmdInit = do + job "initializing" $ do - -- Writes all the default files - -- a path, a "create" function and an update function for each file. - forM_ - [ ( pathNixSourcesNix - , (`createFile` initNixSourcesNixContent) - , \path content -> do - if shouldUpdateNixSourcesNix content - then do - putStrLn "Updating sources.nix" - B.writeFile path initNixSourcesNixContent - else putStrLn "Not updating sources.nix" - ) - , ( pathNixSourcesJson - , \path -> do - createFile path initNixSourcesJsonContent - -- Imports @niv@ and @nixpkgs@ (19.03) - putStrLn "Importing 'niv' ..." - cmdAdd Nothing (PackageName "nmattia/niv", PackageSpec HMS.empty) - putStrLn "Importing 'nixpkgs' ..." - cmdAdd - (Just (PackageName "nixpkgs")) - ( PackageName "NixOS/nixpkgs-channels" - , PackageSpec (HMS.singleton "branch" "nixos-19.03")) - , \path _content -> dontCreateFile path) - ] $ \(path, onCreate, onUpdate) -> do - exists <- Dir.doesFileExist path - if exists then B.readFile path >>= onUpdate path else onCreate path + -- Writes all the default files + -- a path, a "create" function and an update function for each file. + forM_ + [ ( pathNixSourcesNix + , (`createFile` initNixSourcesNixContent) + , \path content -> do + if shouldUpdateNixSourcesNix content + then do + putStrLn "Updating sources.nix" + B.writeFile path initNixSourcesNixContent + else putStrLn "Not updating sources.nix" + ) + , ( pathNixSourcesJson + , \path -> do + createFile path initNixSourcesJsonContent + -- Imports @niv@ and @nixpkgs@ (19.03) + putStrLn "Importing 'niv' ..." + cmdAdd Nothing (PackageName "nmattia/niv", PackageSpec HMS.empty) + putStrLn "Importing 'nixpkgs' ..." + cmdAdd + (Just (PackageName "nixpkgs")) + ( PackageName "NixOS/nixpkgs-channels" + , PackageSpec (HMS.singleton "branch" "nixos-19.03")) + , \path _content -> dontCreateFile path) + ] $ \(path, onCreate, onUpdate) -> do + exists <- Dir.doesFileExist path + if exists then B.readFile path >>= onUpdate path else onCreate path where createFile :: FilePath -> B.ByteString -> IO () createFile path content = do @@ -333,25 +335,25 @@ specToLockedAttrs = fmap (Locked,) . unPackageSpec -- TODO: sexy logging + concurrent updates cmdUpdate :: Maybe (PackageName, PackageSpec) -> IO () cmdUpdate = \case - Just (packageName, cliSpec) -> do - T.putStrLn $ "Updating single package: " <> unPackageName packageName - sources <- unSources <$> getSources + Just (packageName, cliSpec) -> + job ("Update " <> T.unpack (unPackageName packageName)) $ do + sources <- unSources <$> getSources - eFinalSpec <- case HMS.lookup packageName sources of - Just defaultSpec -> do - fmap attrsToSpec <$> tryEvalUpdate - (specToLockedAttrs cliSpec <> specToFreeAttrs defaultSpec) - (githubUpdate nixPrefetchURL githubLatestRev githubRepo) + eFinalSpec <- case HMS.lookup packageName sources of + Just defaultSpec -> do + fmap attrsToSpec <$> tryEvalUpdate + (specToLockedAttrs cliSpec <> specToFreeAttrs defaultSpec) + (githubUpdate nixPrefetchURL githubLatestRev githubRepo) - Nothing -> abortCannotUpdateNoSuchPackage packageName + Nothing -> abortCannotUpdateNoSuchPackage packageName - case eFinalSpec of - Left e -> abortUpdateFailed [(packageName, e)] - Right finalSpec -> - setSources $ Sources $ - HMS.insert packageName finalSpec sources + case eFinalSpec of + Left e -> abortUpdateFailed [(packageName, e)] + Right finalSpec -> + setSources $ Sources $ + HMS.insert packageName finalSpec sources - Nothing -> do + Nothing -> job "Updating all packages" $ do sources <- unSources <$> getSources esources' <- forWithKeyM sources $ diff --git a/src/Niv/Logger.hs b/src/Niv/Logger.hs new file mode 100644 index 0000000..c757e78 --- /dev/null +++ b/src/Niv/Logger.hs @@ -0,0 +1,40 @@ +{-# LANGUAGE DerivingStrategies #-} +{-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE LambdaCase #-} +{-# LANGUAGE GeneralizedNewtypeDeriving #-} + +module Niv.Logger where + +import qualified System.Console.ANSI as ANSI +import Data.String (IsString) +import UnliftIO + +job :: String -> IO () -> IO () +job str act = do + say (bold str) + tryAny act >>= \case + Right () -> say $ green "Done" <> ": " <> Log str + Left e -> say $ red "ERROR" <> ":\n" <> Log (show e) + +newtype Log = Log { unLog :: String } + deriving newtype (Semigroup, Monoid, IsString) + +say :: Log -> IO () +say = putStrLn . unLog + +green :: String -> Log +green str = Log $ + ANSI.setSGRCode [ANSI.SetConsoleIntensity ANSI.BoldIntensity] <> + ANSI.setSGRCode [ANSI.SetColor ANSI.Foreground ANSI.Vivid ANSI.Green] <> + str <> ANSI.setSGRCode [ANSI.Reset] + +red :: String -> Log +red str = Log $ + ANSI.setSGRCode [ANSI.SetColor ANSI.Foreground ANSI.Vivid ANSI.Red] <> + str <> ANSI.setSGRCode [ANSI.Reset] + +bold :: String -> Log +bold str = Log $ + ANSI.setSGRCode [ANSI.SetConsoleIntensity ANSI.BoldIntensity] <> + ANSI.setSGRCode [ANSI.SetColor ANSI.Foreground ANSI.Vivid ANSI.White] <> + str <> ANSI.setSGRCode [ANSI.Reset]