slackbuilder/src/Main.hs

285 lines
11 KiB
Haskell
Raw Normal View History

2023-12-23 22:15:10 +01:00
{- This Source Code Form is subject to the terms of the Mozilla Public License,
v. 2.0. If a copy of the MPL was not distributed with this file, You can
obtain one at https://mozilla.org/MPL/2.0/. -}
module Main
( main
) where
2024-09-08 16:44:57 +02:00
import Control.Exception (Exception(..), handle, SomeException(..))
import Data.Char (isNumber)
2023-12-11 08:14:55 +01:00
import Control.Monad.Catch (MonadThrow(..))
2023-09-03 10:26:43 +02:00
import Control.Monad.IO.Class (MonadIO(..))
import qualified Data.Map as Map
import Options.Applicative (execParser)
import SlackBuilder.CommandLine
2023-08-09 20:59:42 +02:00
import SlackBuilder.Config
2023-08-15 10:33:19 +02:00
import SlackBuilder.Trans
import SlackBuilder.LatestVersionCheck
2024-03-19 11:34:19 +01:00
import SlackBuilder.Update
2023-08-09 20:59:42 +02:00
import qualified Toml
2023-09-03 10:26:43 +02:00
import Data.Text (Text)
2023-08-09 20:59:42 +02:00
import qualified Data.Text as Text
2024-09-08 16:44:57 +02:00
import qualified Data.Text.IO as Text
2024-03-19 11:34:19 +01:00
import Control.Monad.Trans.Reader (ReaderT(..))
import SlackBuilder.Package (PackageDescription(..))
2023-09-03 10:26:43 +02:00
import qualified SlackBuilder.Package as Package
import Text.URI.QQ (uri)
2024-03-19 11:34:19 +01:00
import Data.Foldable (for_, find)
2023-10-08 12:28:46 +02:00
import GHC.Records (HasField(..))
2024-03-19 11:34:19 +01:00
import System.Process (CmdSpec(..))
2024-08-20 22:36:43 +02:00
import System.Console.ANSI
( setSGR
, SGR(..)
, ColorIntensity(..)
, Color(..)
, ConsoleLayer(..)
)
2023-09-03 10:26:43 +02:00
autoUpdatable :: [PackageDescription]
2023-09-03 10:26:43 +02:00
autoUpdatable =
[ PackageDescription
2023-09-03 10:26:43 +02:00
{ latest =
let ghArguments = PackageOwner{ owner = "universal-ctags", name = "ctags" }
2023-09-03 10:26:43 +02:00
template = Package.DownloadTemplate
2024-09-01 17:34:24 +02:00
"https://github.com/universal-ctags/ctags/archive/{version}/ctags-{version}.tar.gz"
2024-01-19 09:57:58 +01:00
in Package.Updater
{ detectLatest = latestGitHub ghArguments "(v)\\."
2024-01-19 09:57:58 +01:00
, getVersion = reuploadWithTemplate template []
, is64 = False
}
2023-09-03 10:26:43 +02:00
, name = "universal-ctags"
, downloaders = mempty
2023-10-01 17:19:06 +02:00
}
, PackageDescription
2023-10-01 17:19:06 +02:00
{ latest =
let packagistArguments = PackageOwner{ owner = "composer", name = "composer" }
2023-10-01 17:19:06 +02:00
template = Package.DownloadTemplate
2024-09-01 17:34:24 +02:00
"https://getcomposer.org/download/{version}/composer.phar"
2024-01-19 09:57:58 +01:00
in Package.Updater
{ detectLatest = latestPackagist packagistArguments
, getVersion = downloadWithTemplate template
, is64 = False
}
2023-10-01 17:19:06 +02:00
, name = "composer"
, downloaders = mempty
2023-09-03 10:26:43 +02:00
}
, PackageDescription
2023-10-03 18:53:41 +02:00
{ latest =
let ghArguments = PackageOwner
2023-10-03 18:53:41 +02:00
{ owner = "jitsi"
, name = "jitsi-meet-electron"
}
template = Package.DownloadTemplate
2024-09-01 17:34:24 +02:00
"https://github.com/jitsi/jitsi-meet-electron/releases/download/v{version}/jitsi-meet-x86_64.AppImage"
2024-01-19 09:57:58 +01:00
in Package.Updater
{ detectLatest = latestGitHub ghArguments "(v)*"
2024-01-19 09:57:58 +01:00
, getVersion = downloadWithTemplate template
, is64 = True
}
2023-10-03 18:53:41 +02:00
, name = "jitsi-meet-desktop"
, downloaders = mempty
2023-10-03 18:53:41 +02:00
}
, PackageDescription
2023-10-04 22:36:19 +02:00
{ latest =
let ghArguments = PackageOwner
2023-10-04 22:36:19 +02:00
{ owner = "php"
, name = "php-src"
}
template = Package.DownloadTemplate
2024-09-01 17:34:24 +02:00
"https://www.php.net/distributions/php-{version}.tar.xz"
2024-01-19 09:57:58 +01:00
in Package.Updater
{ detectLatest = latestGitHub ghArguments "(php-)8.2.\\d"
2024-01-19 09:57:58 +01:00
, getVersion = downloadWithTemplate template
, is64 = False
}
2023-10-04 22:36:19 +02:00
, name = "php82"
, downloaders = mempty
2023-10-08 12:28:46 +02:00
}
, PackageDescription
2023-10-08 12:28:46 +02:00
{ latest =
let ghArguments = PackageOwner
2023-10-08 12:28:46 +02:00
{ owner = "kovidgoyal"
, name = "kitty"
}
template = Package.DownloadTemplate
2024-09-01 17:34:24 +02:00
"https://github.com/kovidgoyal/kitty/releases/download/v{version}/kitty-{version}.tar.xz"
2024-01-19 09:57:58 +01:00
in Package.Updater
{ detectLatest = latestGitHub ghArguments "(v)\\."
2024-01-19 09:57:58 +01:00
, getVersion = reuploadWithTemplate template [RawCommand "go" ["mod", "vendor"]]
, is64 = False
}
2023-10-08 12:28:46 +02:00
, name = "kitty"
, downloaders = mempty
2023-10-04 22:36:19 +02:00
}
, PackageDescription
2023-10-13 19:34:02 +02:00
{ latest =
let ghArguments = PackageOwner
2023-10-13 19:34:02 +02:00
{ owner = "rdiff-backup"
, name = "rdiff-backup"
}
template = Package.DownloadTemplate
2024-09-01 17:34:24 +02:00
"https://github.com/rdiff-backup/rdiff-backup/releases/download/v{version}/rdiff-backup-{version}.tar.gz"
2024-01-19 09:57:58 +01:00
in Package.Updater
{ detectLatest = latestGitHub ghArguments "(v)\\."
2024-01-19 09:57:58 +01:00
, getVersion = reuploadWithTemplate template []
, is64 = False
}
2023-10-13 19:34:02 +02:00
, name = "rdiff-backup"
, downloaders = mempty
2023-10-13 19:34:02 +02:00
}
, PackageDescription
{ latest =
let needle = "Linux—"
textArguments = TextArguments
{ textURL = "https://help.webex.com/en-us/article/mqkve8/Webex-App-%7C-Release-notes"
, versionPicker = Text.takeWhile (liftA2 (||) (== '.') isNumber)
. Text.drop (Text.length needle)
. snd
. Text.breakOn needle
}
2024-09-01 17:34:24 +02:00
template = Package.DownloadTemplate
"https://binaries.webex.com/WebexDesktop-Ubuntu-Official-Package/Webex.deb"
2024-01-19 09:57:58 +01:00
in Package.Updater
{ detectLatest = latestText textArguments
, getVersion = downloadWithTemplate template
, is64 = True
}
, name = "webex"
, downloaders = mempty
}
, PackageDescription
2023-10-20 19:23:21 +02:00
{ latest =
let ghArguments = PackageOwner
2023-10-20 19:23:21 +02:00
{ owner = "librsync"
, name = "librsync"
}
template = Package.DownloadTemplate
2024-09-01 17:34:24 +02:00
"https://github.com/librsync/librsync/archive/v{version}/librsync-{version}.tar.gz"
2024-01-19 09:57:58 +01:00
in Package.Updater
{ detectLatest = latestGitHub ghArguments "(v)\\."
2024-01-19 09:57:58 +01:00
, getVersion = reuploadWithTemplate template []
, is64 = True
}
2023-10-20 19:23:21 +02:00
, name = "librsync"
, downloaders = mempty
2023-10-20 19:23:21 +02:00
}
, PackageDescription
2023-10-20 19:23:21 +02:00
{ latest =
let textArguments = TextArguments
{ textURL = "https://downloads.dlang.org/releases/LATEST"
, versionPicker = Text.strip
}
template = Package.DownloadTemplate
2024-09-01 17:34:24 +02:00
"https://downloads.dlang.org/releases/2.x/{version}/dmd.{version}.linux.tar.xz"
2024-01-19 09:57:58 +01:00
in Package.Updater
{ detectLatest = latestText textArguments
, getVersion = downloadWithTemplate template
, is64 = False
}
2023-10-20 19:23:21 +02:00
, name = "dmd"
, downloaders = mempty
}
, PackageDescription
{ latest =
let textArguments = TextArguments
{ textURL = "https://downloads.dlang.org/releases/LATEST"
, versionPicker = Text.strip
}
2024-09-01 17:34:24 +02:00
template = Package.DownloadTemplate "https://codeload.github.com/dlang/tools/tar.gz/v{version}"
2024-01-19 09:57:58 +01:00
in Package.Updater
{ detectLatest = latestText textArguments
, getVersion = reuploadWithTemplate template []
, is64 = False
}
, name = "d-tools"
, downloaders =
let dubArguments = PackageOwner{ owner = "dlang", name = "dub" }
dscannerArguments = PackageOwner{ owner = "dlang-community", name = "D-Scanner" }
dcdArguments = PackageOwner{ owner = "dlang-community", name = "DCD" }
2024-01-19 09:57:58 +01:00
latestDub = Package.Updater
{ detectLatest = latestGitHub dubArguments "(v)\\."
2024-05-13 18:26:23 +02:00
, getVersion = reuploadWithTemplate dubTemplate []
2024-01-19 09:57:58 +01:00
, is64 = False
}
latestDscanner = Package.Updater
{ detectLatest = latestGitHub dscannerArguments "(v)\\."
2024-01-19 09:57:58 +01:00
, getVersion = cloneFromGit dscannerURI "v"
, is64 = False
}
dcdURI = [uri|https://github.com/dlang-community/DCD.git|]
latestDcd = Package.Updater
{ detectLatest = latestGitHub dcdArguments "(v)\\."
2024-01-19 09:57:58 +01:00
, getVersion = cloneFromGit dcdURI "v"
, is64 = False
}
2024-09-01 17:34:24 +02:00
dubTemplate = Package.DownloadTemplate "https://codeload.github.com/dlang/dub/tar.gz/v{version}"
dscannerURI = [uri|https://github.com/dlang-community/D-Scanner.git|]
in Map.fromList
2024-01-19 09:57:58 +01:00
[ ("DUB", latestDub)
, ("DSCANNER", latestDscanner)
2024-01-19 09:57:58 +01:00
, ("DCD", latestDcd)
]
2023-10-20 19:23:21 +02:00
}
2024-03-26 11:52:16 +01:00
, PackageDescription
{ latest =
let ghArguments = PackageOwner
{ owner = "simd-everywhere"
, name = "simde"
}
template = Package.DownloadTemplate
2024-09-01 17:34:24 +02:00
"https://github.com/simd-everywhere/simde/releases/download/v{version}/simde-amalgamated-{version}.tar.xz"
2024-03-26 11:52:16 +01:00
in Package.Updater
{ detectLatest = latestGitHub ghArguments "(v)\\."
, getVersion = downloadWithTemplate template
, is64 = False
}
, name = "simde"
, downloaders = mempty
}
2023-09-03 10:26:43 +02:00
]
2023-12-11 08:14:55 +01:00
up2Date :: Maybe Text -> SlackBuilderT ()
up2Date = \case
Nothing -> for_ autoUpdatable go
Just packageName
| Just foundPackage <- find ((packageName ==) . getField @"name") autoUpdatable ->
go foundPackage
| otherwise -> throwM $ UpdaterNotFound packageName
2023-09-03 10:26:43 +02:00
where
2023-10-20 19:23:21 +02:00
go package = getAndLogLatest package
>>= mapM_ updatePackageIfRequired
2023-10-20 19:23:21 +02:00
>> liftIO (putStrLn "")
2023-09-03 10:26:43 +02:00
check :: SlackBuilderT ()
check = for_ autoUpdatable go
where
go package = getAndLogLatest package
>>= mapM_ checkUpdateAvailability
>> liftIO (putStrLn "")
main :: IO ()
2024-09-08 16:44:57 +02:00
main = execParser slackBuilderParser
>>= handle handleException . withCommandLine
2023-08-09 20:59:42 +02:00
where
2024-09-08 16:44:57 +02:00
withCommandLine programCommand = do
settingsResult <- Toml.decodeFileEither settingsCodec configurationFile
case settingsResult of
Right settings -> flip runReaderT settings
$ runSlackBuilderT
$ executeCommand programCommand
Left settingsErrors
-> setSGR [SetColor Foreground Dull Red]
>> putStrLn (configurationFile <> " parsing failed.")
>> setSGR [Reset]
>> Text.putStr (Toml.prettyTomlDecodeErrors settingsErrors)
configurationFile = "config/config.toml"
handleException :: SomeException -> IO ()
2024-08-20 22:36:43 +02:00
handleException slackBuilderException
= setSGR [SetColor Foreground Dull Red]
>> putStrLn (displayException slackBuilderException)
>> setSGR [Reset]
2023-08-15 10:33:19 +02:00
executeCommand = \case
2024-08-20 22:36:43 +02:00
CheckCommand -> check
Up2DateCommand packageName -> up2Date packageName