packages feed

indigo-0.6.0: app/Upgrade.hs

-- SPDX-FileCopyrightText: 2022 Oxhead Alpha
-- SPDX-License-Identifier: LicenseRef-MIT-OA

-- | Upgrade command implementation
module Upgrade
  ( run
  ) where

import Data.Text qualified as T
import Data.Version
import Network.HTTP.Req
  (GET(GET), HttpException, MonadHttp, NoReqBody(..), Scheme(Https), Url, bsResponse,
  defaultHttpConfig, queryParam, req, responseBody, runReq, (/:))
import Shelly qualified as S
import System.Directory (createDirectoryIfMissing)
import System.FilePath ((</>))
import Text.ParserCombinators.ReadP (eof, readP_to_S)
import Universum.Lifted.File (writeFile)

import FileGen.Files (DependenceSnapshotVersion(..), indigoDependenceSnapshotYaml)
import Helper (repo)
import Paths_indigo (version)

run :: Maybe Text -> Bool -> IO ()
run mrevision bforce = do
  S.shelly $ S.escaping False $ S.withTmpDir $ \tempDir -> do
    let revision = fromMaybe "production" mrevision
    remoteVer <- runReq defaultHttpConfig $ do
      eresp <- try @_ @HttpException $ req GET
        (repo revision /: "package.yaml")
        NoReqBody
        bsResponse
        (queryParam @_ @Text "inline" (Just "false"))
      liftIO $ case eresp of
        Left err -> do
          putTextLn "Failed get new indigo version:"
          putStrLn $ displayException err
          exitFailure
        Right resp -> maybe (fail "Invalid package.yaml") (pure . fst) $
          responseBody resp
            & decodeUtf8
            & lines
            & find ("version:" `T.isPrefixOf`)
            >>= listToMaybe . drop 1 . words
            >>= listToMaybe . readP_to_S (parseVersion <* eof) . toString
    if remoteVer <= version && not bforce
    then putStrLn $ "Executable version " <> showVersion version <> " already up to date"
    else do
      runReq defaultHttpConfig $ getFile revision tempDir "indigo-snapshot.yaml"
      writeFile (tempDir </> "indigo-dependence-snapshot.yaml") $
        indigoDependenceSnapshotYaml $
          maybe (DSVPublishedVersion remoteVer) DSVGitCommitSha mrevision
      S.run_ "stack"
        ["install", "indigo", "--resolver"
        , toText $ tempDir </> "indigo-dependence-snapshot.yaml"]

getFile :: (MonadCatch m, MonadHttp m) => Text -> FilePath -> Text -> m ()
getFile revision configDir fn = do
  eresp <- try @_ @HttpException $ req GET
    (url revision fn)
    NoReqBody
    bsResponse
    (queryParam @_ @Text "inline" (Just "false"))
  case eresp of
    Left err -> do
      putStrLn $ "Failed to get " <> fn <> ":"
      putStrLn $ displayException err
    Right resp -> do
      let fp = configDir </> toString fn
          dep = decodeUtf8 $ responseBody resp
      liftIO $ createDirectoryIfMissing True configDir
      writeFile fp dep

url :: Text -> Text -> Url 'Https
url revision fn = repo revision /: "snapshots" /: fn