Separate collectGcroot and printGcroot
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}
-import Control.Exception (IOException, try)
+import Control.Exception (Exception, IOException, try, throwIO)
import Data.Aeson qualified as Aeson
import Data.Aeson (ToJSON(..), FromJSON(..), Value(..), (.:), (.=), object)
import Data.Aeson.Types (prependFailure, typeMismatch)
else
return False
-collectAndPrintGcroot :: FilePath -> IO ()
-collectAndPrintGcroot gcroot = do
+data Gcroot = Gcroot
+ { gcrootPath :: FilePath
+ , gcrootDependencies :: [PathInfo]
+ }
+
+collectGcroot :: FilePath -> IO (Maybe Gcroot)
+collectGcroot gcroot = do
isBroken <- isBrokenLink gcroot
if isBroken
then
- return ()
+ return Nothing
else do
(json, _) <- readProcess_ $ proc "nix" [ "--extra-experimental-features", "nix-command"
, "path-info"
, gcroot
]
let pathInfos_ = Aeson.eitherDecode json :: Either String [PathInfo]
- putStr (gcroot <> ": ")
case pathInfos_ of
Left err ->
- putStrLn ("ERROR: " <> err)
+ throwIO $ PathInfoException err
Right pathInfos ->
- putStrLn $ formatFileSize $ totalSize pathInfos
+ return $ Just $ Gcroot gcroot pathInfos
+
+data PathInfoException =
+ PathInfoException String
+ deriving (Show)
+
+instance Exception PathInfoException
+
+printGcroot :: Gcroot -> IO ()
+printGcroot gcroot = do
+ putStr (gcrootPath gcroot <> ": ")
+ putStrLn $ formatFileSize $ totalSize (gcrootDependencies gcroot)
+
+collectAndPrintGcroot :: FilePath -> IO ()
+collectAndPrintGcroot gcroot =
+ maybe (return ()) printGcroot =<< collectGcroot gcroot
totalSize :: (Foldable f, Functor f) => f PathInfo -> Int
totalSize = sum . fmap pathInfoNarSize