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/. -}
|
|
|
|
|
2023-08-04 21:33:21 +02:00
|
|
|
module Main
|
|
|
|
( main
|
|
|
|
) where
|
|
|
|
|
2023-10-20 15:53:48 +02:00
|
|
|
import Data.Char (isNumber)
|
|
|
|
import Control.Applicative (Applicative(liftA2))
|
2023-09-03 10:26:43 +02:00
|
|
|
import Data.List.NonEmpty (NonEmpty(..))
|
2023-10-01 17:19:06 +02:00
|
|
|
import qualified Data.List.NonEmpty as NonEmpty
|
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(..))
|
2024-03-04 17:28:07 +01:00
|
|
|
import Data.Maybe (fromJust, fromMaybe)
|
2023-11-01 17:05:16 +01:00
|
|
|
import qualified Data.Map as Map
|
2023-08-06 14:25:19 +02:00
|
|
|
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
|
2024-01-01 19:44:45 +01:00
|
|
|
import SlackBuilder.LatestVersionCheck
|
2023-08-09 20:59:42 +02:00
|
|
|
import qualified Toml
|
2023-10-04 22:36:19 +02:00
|
|
|
import qualified Data.ByteString as ByteString
|
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
|
2023-09-03 10:26:43 +02:00
|
|
|
import qualified Data.Text.IO as Text.IO
|
|
|
|
import Control.Monad.Trans.Reader (ReaderT(..), asks)
|
2023-08-15 10:33:19 +02:00
|
|
|
import SlackBuilder.Download
|
2024-02-17 14:15:01 +01:00
|
|
|
import SlackBuilder.Package (PackageDescription(..), PackageUpdateData(..))
|
2023-09-03 10:26:43 +02:00
|
|
|
import qualified SlackBuilder.Package as Package
|
2023-10-24 21:06:37 +02:00
|
|
|
import Text.URI (URI(..), mkURI)
|
2023-10-28 21:24:21 +02:00
|
|
|
import Text.URI.QQ (uri)
|
2024-01-28 13:35:53 +01:00
|
|
|
import Data.Foldable (Foldable(..), for_, find)
|
2023-09-03 10:26:43 +02:00
|
|
|
import qualified Text.URI as URI
|
2024-02-17 14:15:01 +01:00
|
|
|
import System.FilePath
|
|
|
|
( (</>)
|
|
|
|
, (<.>)
|
|
|
|
, dropExtension
|
|
|
|
, takeBaseName
|
|
|
|
, splitFileName
|
|
|
|
, takeDirectory
|
|
|
|
, takeFileName
|
|
|
|
, dropTrailingPathSeparator
|
|
|
|
)
|
2023-10-04 22:36:19 +02:00
|
|
|
import SlackBuilder.Info
|
|
|
|
import Text.Megaparsec (parse, errorBundlePretty)
|
2023-10-08 12:28:46 +02:00
|
|
|
import GHC.Records (HasField(..))
|
|
|
|
import System.Process
|
|
|
|
( CmdSpec(..)
|
|
|
|
, CreateProcess(..)
|
|
|
|
, StdStream(..)
|
|
|
|
, withCreateProcess
|
|
|
|
, waitForProcess
|
|
|
|
)
|
2023-10-20 19:23:21 +02:00
|
|
|
import System.Console.ANSI
|
|
|
|
( setSGR
|
|
|
|
, SGR(..)
|
|
|
|
, ColorIntensity(..)
|
|
|
|
, Color(..)
|
|
|
|
, ConsoleLayer(..)
|
|
|
|
)
|
2024-01-28 13:35:53 +01:00
|
|
|
import System.Directory (listDirectory, doesDirectoryExist, withCurrentDirectory, removeDirectoryRecursive)
|
2024-03-17 11:00:13 +01:00
|
|
|
import Control.Monad (filterM, void)
|
2023-12-12 18:51:44 +01:00
|
|
|
import Data.List (isPrefixOf, isSuffixOf, partition)
|
2024-03-17 11:00:13 +01:00
|
|
|
import Conduit (runConduitRes, (.|), yield)
|
2024-02-17 14:15:01 +01:00
|
|
|
import Data.Functor ((<&>))
|
|
|
|
import Data.Bifunctor (Bifunctor(..))
|
2024-03-17 11:00:13 +01:00
|
|
|
import Data.Conduit.Tar (tarFilePath)
|
|
|
|
import qualified Data.Conduit.Lzma as Lzma
|
2023-09-03 10:26:43 +02:00
|
|
|
|
2024-02-17 14:15:01 +01:00
|
|
|
autoUpdatable :: [PackageDescription]
|
2023-09-03 10:26:43 +02:00
|
|
|
autoUpdatable =
|
2024-02-17 14:15:01 +01:00
|
|
|
[ PackageDescription
|
2023-09-03 10:26:43 +02:00
|
|
|
{ latest =
|
2024-01-01 19:44:45 +01:00
|
|
|
let ghArguments = PackageOwner{ owner = "universal-ctags", name = "ctags" }
|
2023-09-03 10:26:43 +02:00
|
|
|
templateTail =
|
2023-09-25 10:18:00 +02:00
|
|
|
[ Package.VersionPlaceholder
|
|
|
|
, Package.StaticPlaceholder "/ctags-"
|
2023-09-03 10:26:43 +02:00
|
|
|
, Package.VersionPlaceholder
|
|
|
|
, Package.StaticPlaceholder ".tar.gz"
|
|
|
|
]
|
|
|
|
template = Package.DownloadTemplate
|
2023-10-01 17:19:06 +02:00
|
|
|
$ Package.StaticPlaceholder "https://github.com/universal-ctags/ctags/archive/"
|
|
|
|
:| templateTail
|
2024-01-19 09:57:58 +01:00
|
|
|
in Package.Updater
|
|
|
|
{ detectLatest = latestGitHub ghArguments stableTagTransform
|
|
|
|
, getVersion = reuploadWithTemplate template []
|
|
|
|
, is64 = False
|
|
|
|
}
|
2023-09-03 10:26:43 +02:00
|
|
|
, name = "universal-ctags"
|
2023-10-24 21:06:37 +02:00
|
|
|
, downloaders = mempty
|
2023-10-01 17:19:06 +02:00
|
|
|
}
|
2024-02-17 14:15:01 +01:00
|
|
|
, PackageDescription
|
2023-10-01 17:19:06 +02:00
|
|
|
{ latest =
|
2024-01-01 19:44:45 +01:00
|
|
|
let packagistArguments = PackageOwner{ owner = "composer", name = "composer" }
|
2023-10-01 17:19:06 +02:00
|
|
|
template = Package.DownloadTemplate
|
|
|
|
$ Package.StaticPlaceholder "https://getcomposer.org/download/"
|
|
|
|
:| [Package.VersionPlaceholder, Package.StaticPlaceholder "/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"
|
2023-10-24 21:06:37 +02:00
|
|
|
, downloaders = mempty
|
2023-09-03 10:26:43 +02:00
|
|
|
}
|
2024-02-17 14:15:01 +01:00
|
|
|
, PackageDescription
|
2023-10-03 18:53:41 +02:00
|
|
|
{ latest =
|
2024-01-01 19:44:45 +01:00
|
|
|
let ghArguments = PackageOwner
|
2023-10-03 18:53:41 +02:00
|
|
|
{ owner = "jitsi"
|
|
|
|
, name = "jitsi-meet-electron"
|
|
|
|
}
|
|
|
|
template = Package.DownloadTemplate
|
|
|
|
$ Package.StaticPlaceholder "https://github.com/jitsi/jitsi-meet-electron/releases/download/v"
|
|
|
|
:| Package.VersionPlaceholder
|
|
|
|
: [Package.StaticPlaceholder "/jitsi-meet-x86_64.AppImage"]
|
2024-01-19 09:57:58 +01:00
|
|
|
in Package.Updater
|
|
|
|
{ detectLatest = latestGitHub ghArguments $ Text.stripPrefix "v"
|
|
|
|
, getVersion = downloadWithTemplate template
|
|
|
|
, is64 = True
|
|
|
|
}
|
2023-10-03 18:53:41 +02:00
|
|
|
, name = "jitsi-meet-desktop"
|
2023-10-24 21:06:37 +02:00
|
|
|
, downloaders = mempty
|
2023-10-03 18:53:41 +02:00
|
|
|
}
|
2024-02-17 14:15:01 +01:00
|
|
|
, PackageDescription
|
2023-10-04 22:36:19 +02:00
|
|
|
{ latest =
|
2024-01-01 19:44:45 +01:00
|
|
|
let ghArguments = PackageOwner
|
2023-10-04 22:36:19 +02:00
|
|
|
{ owner = "php"
|
|
|
|
, name = "php-src"
|
|
|
|
}
|
|
|
|
checkVersion x
|
2023-10-13 19:34:02 +02:00
|
|
|
| not $ Text.isInfixOf "RC" x
|
|
|
|
, Text.isPrefixOf "php-8.2." x = Text.stripPrefix "php-" x
|
2023-10-04 22:36:19 +02:00
|
|
|
| otherwise = Nothing
|
|
|
|
template = Package.DownloadTemplate
|
|
|
|
$ Package.StaticPlaceholder "https://www.php.net/distributions/php-"
|
|
|
|
:| Package.VersionPlaceholder
|
|
|
|
: [Package.StaticPlaceholder ".tar.xz"]
|
2024-01-19 09:57:58 +01:00
|
|
|
in Package.Updater
|
|
|
|
{ detectLatest = latestGitHub ghArguments checkVersion
|
|
|
|
, getVersion = downloadWithTemplate template
|
|
|
|
, is64 = False
|
|
|
|
}
|
2023-10-04 22:36:19 +02:00
|
|
|
, name = "php82"
|
2023-10-24 21:06:37 +02:00
|
|
|
, downloaders = mempty
|
2023-10-08 12:28:46 +02:00
|
|
|
}
|
2024-02-17 14:15:01 +01:00
|
|
|
, PackageDescription
|
2023-10-08 12:28:46 +02:00
|
|
|
{ latest =
|
2024-01-01 19:44:45 +01:00
|
|
|
let ghArguments = PackageOwner
|
2023-10-08 12:28:46 +02:00
|
|
|
{ owner = "kovidgoyal"
|
|
|
|
, name = "kitty"
|
|
|
|
}
|
|
|
|
templateTail =
|
|
|
|
[ Package.StaticPlaceholder "/kitty-"
|
|
|
|
, Package.VersionPlaceholder
|
|
|
|
, Package.StaticPlaceholder ".tar.xz"
|
|
|
|
]
|
|
|
|
template = Package.DownloadTemplate
|
|
|
|
$ Package.StaticPlaceholder "https://github.com/kovidgoyal/kitty/releases/download/v"
|
|
|
|
:| Package.VersionPlaceholder
|
|
|
|
: templateTail
|
2024-01-19 09:57:58 +01:00
|
|
|
in Package.Updater
|
|
|
|
{ detectLatest = latestGitHub ghArguments stableTagTransform
|
|
|
|
, getVersion = reuploadWithTemplate template [RawCommand "go" ["mod", "vendor"]]
|
|
|
|
, is64 = False
|
|
|
|
}
|
2023-10-08 12:28:46 +02:00
|
|
|
, name = "kitty"
|
2023-10-24 21:06:37 +02:00
|
|
|
, downloaders = mempty
|
2023-10-04 22:36:19 +02:00
|
|
|
}
|
2024-02-17 14:15:01 +01:00
|
|
|
, PackageDescription
|
2023-10-13 19:34:02 +02:00
|
|
|
{ latest =
|
2024-01-01 19:44:45 +01:00
|
|
|
let ghArguments = PackageOwner
|
2023-10-13 19:34:02 +02:00
|
|
|
{ owner = "rdiff-backup"
|
|
|
|
, name = "rdiff-backup"
|
|
|
|
}
|
|
|
|
template = Package.DownloadTemplate
|
|
|
|
$ Package.StaticPlaceholder "https://github.com/rdiff-backup/rdiff-backup/releases/download/v"
|
|
|
|
:| Package.VersionPlaceholder
|
|
|
|
: Package.StaticPlaceholder "/rdiff-backup-"
|
|
|
|
: Package.VersionPlaceholder
|
|
|
|
: [Package.StaticPlaceholder ".tar.gz"]
|
2024-01-19 09:57:58 +01:00
|
|
|
in Package.Updater
|
|
|
|
{ detectLatest = latestGitHub ghArguments $ Text.stripPrefix "v"
|
|
|
|
, getVersion = reuploadWithTemplate template []
|
|
|
|
, is64 = False
|
|
|
|
}
|
2023-10-13 19:34:02 +02:00
|
|
|
, name = "rdiff-backup"
|
2023-10-24 21:06:37 +02:00
|
|
|
, downloaders = mempty
|
2023-10-13 19:34:02 +02:00
|
|
|
}
|
2024-02-17 14:15:01 +01:00
|
|
|
, PackageDescription
|
2023-10-20 15:53:48 +02:00
|
|
|
{ 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
|
|
|
|
}
|
|
|
|
template = Package.DownloadTemplate $ pure
|
|
|
|
$ Package.StaticPlaceholder
|
|
|
|
"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
|
|
|
|
}
|
2023-10-20 15:53:48 +02:00
|
|
|
, name = "webex"
|
2023-10-24 21:06:37 +02:00
|
|
|
, downloaders = mempty
|
2023-10-20 15:53:48 +02:00
|
|
|
}
|
2024-02-17 14:15:01 +01:00
|
|
|
, PackageDescription
|
2023-10-20 19:23:21 +02:00
|
|
|
{ latest =
|
2024-01-01 19:44:45 +01:00
|
|
|
let ghArguments = PackageOwner
|
2023-10-20 19:23:21 +02:00
|
|
|
{ owner = "librsync"
|
|
|
|
, name = "librsync"
|
|
|
|
}
|
|
|
|
template = Package.DownloadTemplate
|
|
|
|
$ Package.StaticPlaceholder "https://github.com/librsync/librsync/archive/v"
|
|
|
|
:| Package.VersionPlaceholder
|
|
|
|
: Package.StaticPlaceholder "/librsync-"
|
|
|
|
: Package.VersionPlaceholder
|
|
|
|
: [Package.StaticPlaceholder ".tar.gz"]
|
2024-01-19 09:57:58 +01:00
|
|
|
in Package.Updater
|
|
|
|
{ detectLatest = latestGitHub ghArguments $ Text.stripPrefix "v"
|
|
|
|
, getVersion = reuploadWithTemplate template []
|
|
|
|
, is64 = True
|
|
|
|
}
|
2023-10-20 19:23:21 +02:00
|
|
|
, name = "librsync"
|
2023-11-01 17:05:16 +01:00
|
|
|
, downloaders = mempty
|
2023-10-20 19:23:21 +02:00
|
|
|
}
|
2024-02-17 14:15:01 +01: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
|
|
|
|
$ Package.StaticPlaceholder "https://downloads.dlang.org/releases/2.x/"
|
|
|
|
:| Package.VersionPlaceholder
|
|
|
|
: Package.StaticPlaceholder "/dmd."
|
|
|
|
: Package.VersionPlaceholder
|
|
|
|
: [Package.StaticPlaceholder ".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"
|
2023-10-24 21:06:37 +02:00
|
|
|
, downloaders = mempty
|
|
|
|
}
|
2024-02-17 14:15:01 +01:00
|
|
|
, PackageDescription
|
2023-10-24 21:06:37 +02:00
|
|
|
{ latest =
|
|
|
|
let textArguments = TextArguments
|
|
|
|
{ textURL = "https://downloads.dlang.org/releases/LATEST"
|
|
|
|
, versionPicker = Text.strip
|
|
|
|
}
|
|
|
|
template = Package.DownloadTemplate
|
|
|
|
$ Package.StaticPlaceholder "https://codeload.github.com/dlang/tools/tar.gz/v"
|
|
|
|
:| [Package.VersionPlaceholder]
|
2024-01-19 09:57:58 +01:00
|
|
|
in Package.Updater
|
|
|
|
{ detectLatest = latestText textArguments
|
|
|
|
, getVersion = reuploadWithTemplate template []
|
|
|
|
, is64 = False
|
|
|
|
}
|
2023-10-24 21:06:37 +02:00
|
|
|
, name = "d-tools"
|
|
|
|
, downloaders =
|
2024-01-01 19:44:45 +01:00
|
|
|
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 stableTagTransform
|
|
|
|
, getVersion = downloadWithTemplate dubTemplate
|
|
|
|
, is64 = False
|
|
|
|
}
|
|
|
|
latestDscanner = Package.Updater
|
|
|
|
{ detectLatest = latestGitHub dscannerArguments stableTagTransform
|
|
|
|
, getVersion = cloneFromGit dscannerURI "v"
|
|
|
|
, is64 = False
|
|
|
|
}
|
|
|
|
dcdURI = [uri|https://github.com/dlang-community/DCD.git|]
|
|
|
|
latestDcd = Package.Updater
|
|
|
|
{ detectLatest = latestGitHub dcdArguments stableTagTransform
|
|
|
|
, getVersion = cloneFromGit dcdURI "v"
|
|
|
|
, is64 = False
|
|
|
|
}
|
2023-10-24 21:06:37 +02:00
|
|
|
dubTemplate = Package.DownloadTemplate
|
|
|
|
$ Package.StaticPlaceholder "https://codeload.github.com/dlang/dub/tar.gz/v"
|
|
|
|
:| [Package.VersionPlaceholder]
|
2023-10-28 21:24:21 +02:00
|
|
|
dscannerURI = [uri|https://github.com/dlang-community/D-Scanner.git|]
|
2023-11-01 17:05:16 +01:00
|
|
|
in Map.fromList
|
2024-01-19 09:57:58 +01:00
|
|
|
[ ("DUB", latestDub)
|
2024-03-04 17:28:07 +01:00
|
|
|
, ("DSCANNER", latestDscanner)
|
2024-01-19 09:57:58 +01:00
|
|
|
, ("DCD", latestDcd)
|
2023-10-28 21:24:21 +02:00
|
|
|
]
|
2023-10-20 19:23:21 +02:00
|
|
|
}
|
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
|
2024-02-17 14:15:01 +01:00
|
|
|
>>= mapM_ updatePackageIfRequired
|
2023-10-20 19:23:21 +02:00
|
|
|
>> liftIO (putStrLn "")
|
2023-09-03 10:26:43 +02:00
|
|
|
|
2023-12-09 21:33:34 +01:00
|
|
|
check :: SlackBuilderT ()
|
|
|
|
check = for_ autoUpdatable go
|
|
|
|
where
|
|
|
|
go package = getAndLogLatest package
|
2024-02-17 14:15:01 +01:00
|
|
|
>>= mapM_ checkUpdateAvailability
|
2023-12-09 21:33:34 +01:00
|
|
|
>> liftIO (putStrLn "")
|
|
|
|
|
2024-02-17 14:15:01 +01:00
|
|
|
getAndLogLatest :: PackageDescription -> SlackBuilderT (Maybe PackageUpdateData)
|
|
|
|
getAndLogLatest description = do
|
|
|
|
let PackageDescription{ latest = Package.Updater{ detectLatest }, name } = description
|
|
|
|
liftIO (putStrLn $ Text.unpack name <> ": Retreiving the latest version.")
|
|
|
|
detectedVersion <- detectLatest
|
|
|
|
category <- fmap Text.pack
|
|
|
|
<$> findCategory (Text.unpack name)
|
|
|
|
pure $ PackageUpdateData description
|
|
|
|
<$> category
|
|
|
|
<*> detectedVersion
|
2023-12-09 21:33:34 +01:00
|
|
|
|
2024-02-17 14:15:01 +01:00
|
|
|
checkUpdateAvailability :: PackageUpdateData -> SlackBuilderT (Maybe PackageInfo)
|
|
|
|
checkUpdateAvailability PackageUpdateData{..} = do
|
|
|
|
let name' = Text.unpack $ getField @"name" description
|
|
|
|
packagePath = Text.unpack category </> name' </> (name' <.> "info")
|
2023-10-04 22:36:19 +02:00
|
|
|
repository' <- SlackBuilderT $ asks repository
|
|
|
|
infoContents <- liftIO $ ByteString.readFile $ repository' </> packagePath
|
|
|
|
|
|
|
|
case parse parseInfoFile packagePath infoContents of
|
2023-10-08 12:28:46 +02:00
|
|
|
Right parsedInfoFile
|
|
|
|
| version == getField @"version" parsedInfoFile ->
|
2023-10-20 19:23:21 +02:00
|
|
|
liftIO $ do
|
|
|
|
setSGR [SetColor Foreground Dull Green]
|
|
|
|
Text.IO.putStrLn
|
2024-02-17 14:15:01 +01:00
|
|
|
$ getField @"name" description <> " is up to date (Version " <> version <> ")."
|
2023-10-20 19:23:21 +02:00
|
|
|
setSGR [Reset]
|
2023-12-09 21:33:34 +01:00
|
|
|
pure Nothing
|
|
|
|
| otherwise ->
|
2023-10-26 19:40:47 +02:00
|
|
|
liftIO $ do
|
|
|
|
setSGR [SetColor Foreground Dull Yellow]
|
2023-12-19 22:53:24 +01:00
|
|
|
Text.IO.putStr
|
2023-10-26 19:40:47 +02:00
|
|
|
$ "A new version of "
|
2024-02-17 14:15:01 +01:00
|
|
|
<> getField @"name" description
|
|
|
|
<> " " <> getField @"version" parsedInfoFile
|
2023-10-26 19:40:47 +02:00
|
|
|
<> " is available (" <> version <> ")."
|
|
|
|
setSGR [Reset]
|
2023-12-19 22:53:24 +01:00
|
|
|
putStrLn ""
|
2023-12-09 21:33:34 +01:00
|
|
|
pure $ Just parsedInfoFile
|
|
|
|
Left errorBundle -> liftIO (putStr $ errorBundlePretty errorBundle)
|
|
|
|
>> pure Nothing
|
|
|
|
|
2024-02-17 14:15:01 +01:00
|
|
|
updatePackageIfRequired :: PackageUpdateData -> SlackBuilderT ()
|
|
|
|
updatePackageIfRequired updateData
|
|
|
|
= checkUpdateAvailability updateData
|
|
|
|
>>= mapM_ (updatePackage updateData)
|
2023-10-04 22:36:19 +02:00
|
|
|
|
2024-01-19 09:57:58 +01:00
|
|
|
data DownloadUpdated = DownloadUpdated
|
|
|
|
{ result :: Package.Download
|
|
|
|
, version :: Text
|
|
|
|
, is64 :: Bool
|
|
|
|
} deriving (Eq, Show)
|
|
|
|
|
|
|
|
updateDownload :: Text -> Package.Updater -> SlackBuilderT DownloadUpdated
|
|
|
|
updateDownload packagePath Package.Updater{..} = do
|
2023-11-01 17:05:16 +01:00
|
|
|
latestDownloadVersion <- fromJust <$> detectLatest
|
2024-01-19 09:57:58 +01:00
|
|
|
result <- getVersion packagePath latestDownloadVersion
|
|
|
|
pure $ DownloadUpdated
|
|
|
|
{ result = result
|
|
|
|
, version = latestDownloadVersion
|
|
|
|
, is64 = is64
|
|
|
|
}
|
2023-10-28 04:04:52 +02:00
|
|
|
|
2023-11-01 17:05:16 +01:00
|
|
|
cloneFromGit :: URI -> Text -> Text -> Text -> SlackBuilderT Package.Download
|
2023-10-28 04:04:52 +02:00
|
|
|
cloneFromGit repo tagPrefix packagePath version = do
|
|
|
|
let downloadFileName = URI.unRText
|
|
|
|
$ NonEmpty.last $ snd $ fromJust $ URI.uriPath repo
|
|
|
|
relativeTarball = Text.unpack packagePath
|
|
|
|
</> (dropExtension (Text.unpack downloadFileName) <> "-" <> Text.unpack version)
|
2024-03-04 17:28:07 +01:00
|
|
|
(uri', checksum) <- cloneAndUpload (URI.render repo) relativeTarball tagPrefix
|
2024-01-04 09:36:11 +01:00
|
|
|
pure $ Package.Download
|
|
|
|
{ md5sum = checksum
|
|
|
|
, download = uri'
|
|
|
|
}
|
2023-09-03 10:26:43 +02:00
|
|
|
|
2024-01-19 09:57:58 +01:00
|
|
|
downloadWithTemplate :: Package.DownloadTemplate -> Text -> Text -> SlackBuilderT Package.Download
|
|
|
|
downloadWithTemplate downloadTemplate packagePath version = do
|
2023-09-27 19:58:16 +02:00
|
|
|
repository' <- SlackBuilderT $ asks repository
|
2023-09-03 10:26:43 +02:00
|
|
|
uri' <- liftIO $ Package.renderDownloadWithVersion downloadTemplate version
|
2024-03-05 23:06:32 +01:00
|
|
|
checksum <- download uri' $ repository' </> Text.unpack packagePath
|
2024-03-04 17:28:07 +01:00
|
|
|
pure $ Package.Download uri' $ snd checksum
|
2023-10-28 03:31:10 +02:00
|
|
|
|
2023-11-01 17:05:16 +01:00
|
|
|
reuploadWithTemplate :: Package.DownloadTemplate -> [CmdSpec] -> Text -> Text -> SlackBuilderT Package.Download
|
2023-10-28 03:31:10 +02:00
|
|
|
reuploadWithTemplate downloadTemplate commands packagePath version = do
|
2024-01-24 14:34:58 +01:00
|
|
|
repository' <- SlackBuilderT $ asks repository
|
|
|
|
uri' <- liftIO $ Package.renderDownloadWithVersion downloadTemplate version
|
2024-03-04 17:28:07 +01:00
|
|
|
let downloadFileName = Text.unpack
|
|
|
|
$ URI.unRText
|
2023-10-28 03:31:10 +02:00
|
|
|
$ NonEmpty.last $ snd $ fromJust $ URI.uriPath uri'
|
2024-03-04 17:28:07 +01:00
|
|
|
packagePathRelativeToCurrent = repository' </> Text.unpack packagePath
|
|
|
|
|
2024-03-17 11:00:13 +01:00
|
|
|
(relativeTarball', checksum) <- case commands of
|
2024-03-04 17:28:07 +01:00
|
|
|
[] -> do
|
2024-03-05 23:06:32 +01:00
|
|
|
(downloadedFileName, checksum) <- download uri' packagePathRelativeToCurrent
|
2024-03-17 11:00:13 +01:00
|
|
|
pure (packagePathRelativeToCurrent </> downloadedFileName, checksum)
|
2024-03-04 17:28:07 +01:00
|
|
|
_ -> do
|
|
|
|
changedArchiveRootName <- extractRemote uri' packagePathRelativeToCurrent
|
|
|
|
let relativeTarball = packagePathRelativeToCurrent
|
|
|
|
</> fromMaybe downloadFileName changedArchiveRootName
|
|
|
|
prepareSource relativeTarball
|
2023-09-03 10:26:43 +02:00
|
|
|
|
2024-03-04 17:28:07 +01:00
|
|
|
download' <- handleReupload relativeTarball' downloadFileName
|
2024-01-19 09:57:58 +01:00
|
|
|
pure $ Package.Download download' checksum
|
2023-10-01 17:19:06 +02:00
|
|
|
where
|
2023-10-28 03:31:10 +02:00
|
|
|
name' = Text.pack $ takeBaseName $ Text.unpack packagePath
|
2024-03-17 11:00:13 +01:00
|
|
|
prepareSource tarballPath =
|
|
|
|
liftIO (traverse (defaultCreateProcess tarballPath) commands)
|
|
|
|
>> liftIO (tarCompress tarballPath)
|
|
|
|
<* liftIO (removeDirectoryRecursive tarballPath)
|
|
|
|
tarCompress tarballPath =
|
|
|
|
let archiveBaseFilename = takeFileName tarballPath
|
|
|
|
appendTarExtension = (<.> "tar.xz")
|
|
|
|
in fmap (appendTarExtension tarballPath,)
|
|
|
|
$ withCurrentDirectory (takeDirectory tarballPath)
|
|
|
|
$ runConduitRes $ yield archiveBaseFilename
|
|
|
|
.| void tarFilePath
|
|
|
|
.| Lzma.compress Nothing
|
|
|
|
.| sinkFileAndHash (appendTarExtension archiveBaseFilename)
|
2023-10-28 03:31:10 +02:00
|
|
|
handleReupload relativeTarball downloadFileName = do
|
2024-01-28 13:35:53 +01:00
|
|
|
downloadURL' <- SlackBuilderT $ asks downloadURL
|
|
|
|
|
|
|
|
liftIO $ putStrLn $ "Upload the source tarball " <> relativeTarball
|
2024-03-04 17:28:07 +01:00
|
|
|
uploadCommand relativeTarball ("/" <> name')
|
|
|
|
liftIO $ mkURI $ downloadURL' <> "/" <> name' <> "/" <> Text.pack downloadFileName
|
2023-10-08 12:28:46 +02:00
|
|
|
defaultCreateProcess cwd' cmdSpec
|
|
|
|
= flip withCreateProcess (const . const . const waitForProcess)
|
|
|
|
$ CreateProcess
|
|
|
|
{ use_process_jobs = False
|
|
|
|
, std_out = Inherit
|
|
|
|
, std_in = NoStream
|
|
|
|
, std_err = Inherit
|
|
|
|
, new_session = False
|
|
|
|
, env = Nothing
|
|
|
|
, detach_console = False
|
|
|
|
, delegate_ctlc = False
|
|
|
|
, cwd = Just cwd'
|
|
|
|
, create_new_console = False
|
|
|
|
, create_group = False
|
|
|
|
, cmdspec = cmdSpec
|
|
|
|
, close_fds = True
|
|
|
|
, child_user = Nothing
|
|
|
|
, child_group = Nothing
|
|
|
|
}
|
2023-10-24 21:06:37 +02:00
|
|
|
|
2024-02-17 14:15:01 +01:00
|
|
|
updatePackage :: PackageUpdateData -> PackageInfo -> SlackBuilderT ()
|
|
|
|
updatePackage PackageUpdateData{..} info = do
|
|
|
|
let packagePath = category <> "/" <> getField @"name" description
|
|
|
|
latest' = getField @"latest" description
|
2023-10-24 21:06:37 +02:00
|
|
|
|
|
|
|
repository' <- SlackBuilderT $ asks repository
|
2024-02-17 14:15:01 +01:00
|
|
|
mainDownload <- (, getField @"is64" latest')
|
|
|
|
<$> getField @"getVersion" latest' packagePath version
|
|
|
|
moreDownloads <- traverse (updateDownload packagePath)
|
|
|
|
$ getField @"downloaders" description
|
2024-01-19 09:57:58 +01:00
|
|
|
let (downloads64, allDownloads) = partition snd
|
|
|
|
$ mainDownload
|
|
|
|
: (liftA2 (,) (getField @"result") (getField @"is64") <$> toList moreDownloads)
|
2023-10-24 21:06:37 +02:00
|
|
|
let infoFilePath = repository' </> Text.unpack packagePath
|
2024-02-17 14:15:01 +01:00
|
|
|
</> (Text.unpack (getField @"name" description) <.> "info")
|
2023-10-24 21:06:37 +02:00
|
|
|
package' = info
|
|
|
|
{ version = version
|
2024-01-19 09:57:58 +01:00
|
|
|
, downloads = getField @"download" . fst <$> allDownloads
|
|
|
|
, checksums = getField @"md5sum" . fst <$> allDownloads
|
|
|
|
, downloadX64 = getField @"download" . fst <$> downloads64
|
|
|
|
, checksumX64 = getField @"md5sum" . fst <$> downloads64
|
2023-10-24 21:06:37 +02:00
|
|
|
}
|
|
|
|
liftIO $ Text.IO.writeFile infoFilePath $ generate package'
|
2024-01-19 09:57:58 +01:00
|
|
|
updateSlackBuildVersion packagePath version
|
|
|
|
$ getField @"version" <$> moreDownloads
|
2023-10-24 21:06:37 +02:00
|
|
|
|
|
|
|
commit packagePath version
|
2023-10-01 17:19:06 +02:00
|
|
|
|
2024-02-17 14:15:01 +01:00
|
|
|
findCategory :: FilePath -> SlackBuilderT (Maybe FilePath)
|
|
|
|
findCategory packageName = do
|
|
|
|
repository' <- SlackBuilderT $ asks repository
|
|
|
|
go repository' [] "" <&> fmap fst . find ((packageName ==) . snd)
|
|
|
|
where
|
|
|
|
go currentDirectory found accumulatedDirectory = do
|
|
|
|
let fullDirectory = currentDirectory </> accumulatedDirectory
|
|
|
|
contents <- liftIO $ listDirectory fullDirectory
|
|
|
|
case find (isSuffixOf ".info") contents of
|
|
|
|
Just _ ->
|
|
|
|
let result = first dropTrailingPathSeparator
|
|
|
|
$ splitFileName accumulatedDirectory
|
|
|
|
in pure $ result : found
|
|
|
|
Nothing ->
|
|
|
|
let accumulatedDirectories = (accumulatedDirectory </>)
|
|
|
|
<$> filter (not . isPrefixOf ".") contents
|
|
|
|
directoryFilter = liftIO . doesDirectoryExist
|
|
|
|
. (currentDirectory </>)
|
|
|
|
in filterM directoryFilter accumulatedDirectories
|
|
|
|
>>= traverse (go currentDirectory found) <&> concat
|
2023-10-20 19:23:21 +02:00
|
|
|
|
2023-08-04 21:33:21 +02:00
|
|
|
main :: IO ()
|
|
|
|
main = do
|
2023-08-06 14:25:19 +02:00
|
|
|
programCommand <- execParser slackBuilderParser
|
2023-08-09 20:59:42 +02:00
|
|
|
settings <- Toml.decodeFile settingsCodec "config/config.toml"
|
2023-08-15 10:33:19 +02:00
|
|
|
latestVersion <- flip runReaderT settings
|
|
|
|
$ runSlackBuilderT
|
|
|
|
$ executeCommand programCommand
|
2023-08-04 21:33:21 +02:00
|
|
|
|
2023-10-20 19:23:21 +02:00
|
|
|
maybe (pure ()) Text.IO.putStrLn latestVersion
|
2023-08-09 20:59:42 +02:00
|
|
|
where
|
2023-08-15 10:33:19 +02:00
|
|
|
executeCommand = \case
|
2023-12-09 21:33:34 +01:00
|
|
|
CheckCommand -> check >> pure Nothing
|
2023-12-11 08:14:55 +01:00
|
|
|
Up2DateCommand packageName -> up2Date packageName >> pure Nothing
|