-- SPDX-License-Identifier: BSD-3-Clause module Main (main) where import Control.Monad.Extra (unless, void, when, whenJust) import Data.List (isInfixOf) import SimpleCmd import System.Directory (createDirectoryIfMissing, doesFileExist, renameFile, removeFile) import System.Environment.XDG.BaseDir (getUserCacheDir) import System.FilePath (()) import System.IO (BufferMode(..), hSetBuffering, stdout) rpmostree :: String rpmostree = "/usr/bin/rpm-ostree" data Mode = Update | Changelog instance Show Mode where show Update = "update" show Changelog = "changelog" modeArgs :: Mode -> [String] modeArgs Update = ["update", "--preview"] modeArgs Changelog = ["db", "diff", "-c"] main :: IO () main = do hSetBuffering stdout NoBuffering exists <- doesFileExist rpmostree unless exists $ error' $ rpmostree +-+ ": not found" cachedir <- getUserCacheDir "rpmostree-updates" createDirectoryIfMissing True cachedir -- whether latest is a staged deployment staged <- ("true" `isInfixOf`) <$> cmd rpmostree ["status", "-J", "$.deployments[0].staged"] putStrLn "Preview:" changed <- cachedRpmOstree staged cachedir Update when changed $ do prompt "to update" cmd_ rpmostree ["update"] prompt "for changelog" void $ cachedRpmOstree staged cachedir Changelog cachedRpmOstree :: Bool -> FilePath -> Mode -> IO Bool cachedRpmOstree staged cachedir mode = do (latest, mprevious) <- cacheFiles ok <- pipeBool (rpmostree, modeArgs mode) ("tee", [latest]) if not ok then do whenJust mprevious $ \previous -> renameFile previous latest return False else case mprevious of Just previous -> do (diff,_err) <- cmdStdErr "diff" ["-u0", previous, latest] let diffs = lines diff if length diffs <= 5 -- FIXME print old timestamp then do putStrLn "no new changes" return False else do putStrLn $ "\nChanges since last rpm-ostree update:\n" ++ unlines diffs return True Nothing -> return False where cacheFiles :: IO (FilePath, Maybe FilePath) cacheFiles = do let latestCache = cachedir "latest-" ++ show mode previousCache = cachedir "previous-" ++ show mode haveLatest <- doesFileExist latestCache mprevious <- if haveLatest then do useCache <- case mode of Update -> return staged Changelog -> do -- ostree diff commit from: booted deployment (81ad560ed850559259e46d5739e8d9ac8714fbcbbd0d24257a8934db7730edab) cachedBootedDeployment <- init . tail . last . words <$> cmd "head" ["-1", latestCache] bootedChecksum <- cmd rpmostree ["status", "-b", "-J", "$.deployments[0].checksum"] return $ cachedBootedDeployment `isInfixOf` bootedChecksum if useCache then do renameFile latestCache previousCache return $ Just previousCache else do removeFile latestCache return Nothing else return Nothing return (latestCache,mprevious) prompt :: String -> IO () prompt txt = do putStr $ "Press Enter" +-+ txt ++ ":" void getLine