Find the package category automatically
This commit is contained in:
parent
c8643a2fd4
commit
1094ba7a33
@ -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
|
||||||
|
90
src/Main.hs
90
src/Main.hs
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user