Find the package category automatically
Some checks failed
Build / audit (push) Successful in 14m43s
Build / test (push) Failing after 5m37s

This commit is contained in:
Eugen Wissner 2024-02-17 14:15:01 +01:00
parent c8643a2fd4
commit 1094ba7a33
Signed by: belka
GPG Key ID: A27FDC1E8EE902C0
2 changed files with 54 additions and 48 deletions

View File

@ -6,7 +6,8 @@ module SlackBuilder.Package
( DownloadPlaceholder(..) ( DownloadPlaceholder(..)
, Download(..) , Download(..)
, DownloadTemplate(..) , DownloadTemplate(..)
, Package(..) , PackageDescription(..)
, PackageUpdateData(..)
, Maintainer(..) , Maintainer(..)
, Updater(..) , Updater(..)
, renderDownloadWithVersion , renderDownloadWithVersion
@ -23,13 +24,18 @@ import Control.Monad.Catch (MonadThrow)
import Data.Map (Map) import Data.Map (Map)
-- | Contains information how a package can be updated. -- | Contains information how a package can be updated.
data Package = Package data PackageDescription = PackageDescription
{ latest :: Updater { latest :: Updater
, downloaders :: Map Text Updater , downloaders :: Map Text Updater
, category :: Text
, name :: Text , name :: Text
} }
data PackageUpdateData = PackageUpdateData
{ description :: PackageDescription
, category :: Text
, version :: Text
}
-- | Download URI with the MD5 checksum of the target. -- | Download URI with the MD5 checksum of the target.
data Download = Download data Download = Download
{ download :: URI { download :: URI

View File

@ -12,7 +12,7 @@ import Data.List.NonEmpty (NonEmpty(..))
import qualified Data.List.NonEmpty as NonEmpty import qualified Data.List.NonEmpty as NonEmpty
import Control.Monad.Catch (MonadThrow(..)) import Control.Monad.Catch (MonadThrow(..))
import Control.Monad.IO.Class (MonadIO(..)) import Control.Monad.IO.Class (MonadIO(..))
import Data.Maybe (fromJust) import Data.Maybe (fromJust, listToMaybe)
import qualified Data.Map as Map import qualified Data.Map as Map
import Options.Applicative (execParser) import Options.Applicative (execParser)
import SlackBuilder.CommandLine import SlackBuilder.CommandLine
@ -26,7 +26,7 @@ import qualified Data.Text as Text
import qualified Data.Text.IO as Text.IO import qualified Data.Text.IO as Text.IO
import Control.Monad.Trans.Reader (ReaderT(..), asks) import Control.Monad.Trans.Reader (ReaderT(..), asks)
import SlackBuilder.Download import SlackBuilder.Download
import SlackBuilder.Package (Package(..)) import SlackBuilder.Package (PackageDescription(..), PackageUpdateData(..))
import qualified SlackBuilder.Package as Package import qualified SlackBuilder.Package as Package
import Text.URI (URI(..), mkURI) import Text.URI (URI(..), mkURI)
import Text.URI.QQ (uri) import Text.URI.QQ (uri)
@ -56,9 +56,9 @@ import Control.Monad (filterM)
import Data.List (isPrefixOf, isSuffixOf, partition) import Data.List (isPrefixOf, isSuffixOf, partition)
import Conduit (runConduitRes, (.|), sourceFile) import Conduit (runConduitRes, (.|), sourceFile)
autoUpdatable :: [Package] autoUpdatable :: [PackageDescription]
autoUpdatable = autoUpdatable =
[ Package [ PackageDescription
{ latest = { latest =
let ghArguments = PackageOwner{ owner = "universal-ctags", name = "ctags" } let ghArguments = PackageOwner{ owner = "universal-ctags", name = "ctags" }
templateTail = templateTail =
@ -75,11 +75,10 @@ autoUpdatable =
, getVersion = reuploadWithTemplate template [] , getVersion = reuploadWithTemplate template []
, is64 = False , is64 = False
} }
, category = "development"
, name = "universal-ctags" , name = "universal-ctags"
, downloaders = mempty , downloaders = mempty
} }
, Package , PackageDescription
{ latest = { latest =
let packagistArguments = PackageOwner{ owner = "composer", name = "composer" } let packagistArguments = PackageOwner{ owner = "composer", name = "composer" }
template = Package.DownloadTemplate template = Package.DownloadTemplate
@ -90,11 +89,10 @@ autoUpdatable =
, getVersion = downloadWithTemplate template , getVersion = downloadWithTemplate template
, is64 = False , is64 = False
} }
, category = "development"
, name = "composer" , name = "composer"
, downloaders = mempty , downloaders = mempty
} }
, Package , PackageDescription
{ latest = { latest =
let ghArguments = PackageOwner let ghArguments = PackageOwner
{ owner = "jitsi" { owner = "jitsi"
@ -109,11 +107,10 @@ autoUpdatable =
, getVersion = downloadWithTemplate template , getVersion = downloadWithTemplate template
, is64 = True , is64 = True
} }
, category = "network"
, name = "jitsi-meet-desktop" , name = "jitsi-meet-desktop"
, downloaders = mempty , downloaders = mempty
} }
, Package , PackageDescription
{ latest = { latest =
let ghArguments = PackageOwner let ghArguments = PackageOwner
{ owner = "php" { owner = "php"
@ -132,11 +129,10 @@ autoUpdatable =
, getVersion = downloadWithTemplate template , getVersion = downloadWithTemplate template
, is64 = False , is64 = False
} }
, category = "development"
, name = "php82" , name = "php82"
, downloaders = mempty , downloaders = mempty
} }
, Package , PackageDescription
{ latest = { latest =
let ghArguments = PackageOwner let ghArguments = PackageOwner
{ owner = "kovidgoyal" { owner = "kovidgoyal"
@ -156,11 +152,10 @@ autoUpdatable =
, getVersion = reuploadWithTemplate template [RawCommand "go" ["mod", "vendor"]] , getVersion = reuploadWithTemplate template [RawCommand "go" ["mod", "vendor"]]
, is64 = False , is64 = False
} }
, category = "system"
, name = "kitty" , name = "kitty"
, downloaders = mempty , downloaders = mempty
} }
, Package , PackageDescription
{ latest = { latest =
let ghArguments = PackageOwner let ghArguments = PackageOwner
{ owner = "rdiff-backup" { owner = "rdiff-backup"
@ -177,11 +172,10 @@ autoUpdatable =
, getVersion = reuploadWithTemplate template [] , getVersion = reuploadWithTemplate template []
, is64 = False , is64 = False
} }
, category = "system"
, name = "rdiff-backup" , name = "rdiff-backup"
, downloaders = mempty , downloaders = mempty
} }
, Package , PackageDescription
{ latest = { latest =
let needle = "Linux—" let needle = "Linux—"
textArguments = TextArguments textArguments = TextArguments
@ -199,11 +193,10 @@ autoUpdatable =
, getVersion = downloadWithTemplate template , getVersion = downloadWithTemplate template
, is64 = True , is64 = True
} }
, category = "network"
, name = "webex" , name = "webex"
, downloaders = mempty , downloaders = mempty
} }
, Package , PackageDescription
{ latest = { latest =
let ghArguments = PackageOwner let ghArguments = PackageOwner
{ owner = "librsync" { owner = "librsync"
@ -220,11 +213,10 @@ autoUpdatable =
, getVersion = reuploadWithTemplate template [] , getVersion = reuploadWithTemplate template []
, is64 = True , is64 = True
} }
, category = "libraries"
, name = "librsync" , name = "librsync"
, downloaders = mempty , downloaders = mempty
} }
, Package , PackageDescription
{ latest = { latest =
let textArguments = TextArguments let textArguments = TextArguments
{ textURL = "https://downloads.dlang.org/releases/LATEST" { textURL = "https://downloads.dlang.org/releases/LATEST"
@ -241,11 +233,10 @@ autoUpdatable =
, getVersion = downloadWithTemplate template , getVersion = downloadWithTemplate template
, is64 = False , is64 = False
} }
, category = "development"
, name = "dmd" , name = "dmd"
, downloaders = mempty , downloaders = mempty
} }
, Package , PackageDescription
{ latest = { latest =
let textArguments = TextArguments let textArguments = TextArguments
{ textURL = "https://downloads.dlang.org/releases/LATEST" { textURL = "https://downloads.dlang.org/releases/LATEST"
@ -259,7 +250,6 @@ autoUpdatable =
, getVersion = reuploadWithTemplate template [] , getVersion = reuploadWithTemplate template []
, is64 = False , is64 = False
} }
, category = "development"
, name = "d-tools" , name = "d-tools"
, downloaders = , downloaders =
let dubArguments = PackageOwner{ owner = "dlang", name = "dub" } let dubArguments = PackageOwner{ owner = "dlang", name = "dub" }
@ -302,24 +292,31 @@ up2Date = \case
| otherwise -> throwM $ UpdaterNotFound packageName | otherwise -> throwM $ UpdaterNotFound packageName
where where
go package = getAndLogLatest package go package = getAndLogLatest package
>>= mapM_ (updatePackageIfRequired package) >>= mapM_ updatePackageIfRequired
>> liftIO (putStrLn "") >> liftIO (putStrLn "")
check :: SlackBuilderT () check :: SlackBuilderT ()
check = for_ autoUpdatable go check = for_ autoUpdatable go
where where
go package = getAndLogLatest package go package = getAndLogLatest package
>>= mapM_ (checkUpdateAvailability package) >>= mapM_ checkUpdateAvailability
>> liftIO (putStrLn "") >> liftIO (putStrLn "")
getAndLogLatest :: Package -> SlackBuilderT (Maybe Text) getAndLogLatest :: PackageDescription -> SlackBuilderT (Maybe PackageUpdateData)
getAndLogLatest Package{ latest = Package.Updater{ detectLatest }, name } getAndLogLatest description = do
= liftIO (putStrLn $ Text.unpack name <> ": Retreiving the latest version.") let PackageDescription{ latest = Package.Updater{ detectLatest }, name } = description
>> detectLatest liftIO (putStrLn $ Text.unpack name <> ": Retreiving the latest version.")
detectedVersion <- detectLatest
category <- liftIO $ fmap Text.pack . listToMaybe
<$> findCategory (Text.unpack name)
pure $ PackageUpdateData description
<$> category
<*> detectedVersion
checkUpdateAvailability :: Package -> Text -> SlackBuilderT (Maybe PackageInfo) checkUpdateAvailability :: PackageUpdateData -> SlackBuilderT (Maybe PackageInfo)
checkUpdateAvailability Package{..} version = do checkUpdateAvailability PackageUpdateData{..} = do
let packagePath = Text.unpack category </> Text.unpack name </> (Text.unpack name <.> "info") let name' = Text.unpack $ getField @"name" description
packagePath = Text.unpack category </> name' </> (name' <.> "info")
repository' <- SlackBuilderT $ asks repository repository' <- SlackBuilderT $ asks repository
infoContents <- liftIO $ ByteString.readFile $ repository' </> packagePath infoContents <- liftIO $ ByteString.readFile $ repository' </> packagePath
@ -329,7 +326,7 @@ checkUpdateAvailability Package{..} version = do
liftIO $ do liftIO $ do
setSGR [SetColor Foreground Dull Green] setSGR [SetColor Foreground Dull Green]
Text.IO.putStrLn Text.IO.putStrLn
$ name <> " is up to date (Version " <> version <> ")." $ getField @"name" description <> " is up to date (Version " <> version <> ")."
setSGR [Reset] setSGR [Reset]
pure Nothing pure Nothing
| otherwise -> | otherwise ->
@ -337,7 +334,8 @@ checkUpdateAvailability Package{..} version = do
setSGR [SetColor Foreground Dull Yellow] setSGR [SetColor Foreground Dull Yellow]
Text.IO.putStr Text.IO.putStr
$ "A new version of " $ "A new version of "
<> name <> " " <> getField @"version" parsedInfoFile <> getField @"name" description
<> " " <> getField @"version" parsedInfoFile
<> " is available (" <> version <> ")." <> " is available (" <> version <> ")."
setSGR [Reset] setSGR [Reset]
putStrLn "" putStrLn ""
@ -345,10 +343,10 @@ checkUpdateAvailability Package{..} version = do
Left errorBundle -> liftIO (putStr $ errorBundlePretty errorBundle) Left errorBundle -> liftIO (putStr $ errorBundlePretty errorBundle)
>> pure Nothing >> pure Nothing
updatePackageIfRequired :: Package -> Text -> SlackBuilderT () updatePackageIfRequired :: PackageUpdateData -> SlackBuilderT ()
updatePackageIfRequired package version updatePackageIfRequired updateData
= checkUpdateAvailability package version = checkUpdateAvailability updateData
>>= mapM_ (updatePackage package version) >>= mapM_ (updatePackage updateData)
data DownloadUpdated = DownloadUpdated data DownloadUpdated = DownloadUpdated
{ result :: Package.Download { result :: Package.Download
@ -443,19 +441,21 @@ reuploadWithTemplate downloadTemplate commands packagePath version = do
, child_group = Nothing , child_group = Nothing
} }
updatePackage :: Package -> Text -> PackageInfo -> SlackBuilderT () updatePackage :: PackageUpdateData -> PackageInfo -> SlackBuilderT ()
updatePackage Package{..} version info = do updatePackage PackageUpdateData{..} info = do
let packagePath = category <> "/" <> name let packagePath = category <> "/" <> getField @"name" description
latest' = getField @"latest" description
repository' <- SlackBuilderT $ asks repository repository' <- SlackBuilderT $ asks repository
mainDownload <- (, getField @"is64" latest) mainDownload <- (, getField @"is64" latest')
<$> getField @"getVersion" latest packagePath version <$> getField @"getVersion" latest' packagePath version
moreDownloads <- traverse (updateDownload packagePath) downloaders moreDownloads <- traverse (updateDownload packagePath)
$ getField @"downloaders" description
let (downloads64, allDownloads) = partition snd let (downloads64, allDownloads) = partition snd
$ mainDownload $ mainDownload
: (liftA2 (,) (getField @"result") (getField @"is64") <$> toList moreDownloads) : (liftA2 (,) (getField @"result") (getField @"is64") <$> toList moreDownloads)
let infoFilePath = repository' </> Text.unpack packagePath let infoFilePath = repository' </> Text.unpack packagePath
</> (Text.unpack name <.> "info") </> (Text.unpack (getField @"name" description) <.> "info")
package' = info package' = info
{ version = version { version = version
, downloads = getField @"download" . fst <$> allDownloads , downloads = getField @"download" . fst <$> allDownloads