From f8ef93fde7dd5e9da499514c4ba6b782e5ec35b2 Mon Sep 17 00:00:00 2001 From: Eugen Wissner Date: Sat, 11 May 2024 19:01:41 +0200 Subject: [PATCH] Support a custom upload command --- config/config.toml.example | 14 +++++++------- lib/SlackBuilder/Config.hs | 5 +++-- lib/SlackBuilder/Download.hs | 26 ++++++++++++++------------ src/SlackBuilder/Update.hs | 6 +++--- 4 files changed, 27 insertions(+), 24 deletions(-) diff --git a/config/config.toml.example b/config/config.toml.example index 2c9b4d4..476c71c 100644 --- a/config/config.toml.example +++ b/config/config.toml.example @@ -19,13 +19,13 @@ branch = "user/nick/updates" # be configured consistently with the remote_path. download_url = "https://example.com/some/path" -# If a package updater generates a source tarball, the tarball is uploaded to -# a remote destination with scp. remote_path specifies the remote server and -# a local path on the server where the source tarballs are hosted. When -# uploading the remote_path is followed by the package name and source file -# name. To specify a public URL where the sources can be downloaded, see -# download_url. -remote_path = "example.com:/srv/httpd/some/path" +# If a package updater generates a source tarball, the tarball is uploaded with +# a command given in this parameter. The parameter is a array where the first +# element is the command with the following elements being the command +# arguments. The command supports 2 placeholders: +# %s - Path to the source archive. +# %c - Package category. +upload_command = ["scp", "%s", "example.com:/srv/httpd/some/path/%c"] ## Maintainer specific options [maintainer] diff --git a/lib/SlackBuilder/Config.hs b/lib/SlackBuilder/Config.hs index 39fabd9..8e627e3 100644 --- a/lib/SlackBuilder/Config.hs +++ b/lib/SlackBuilder/Config.hs @@ -9,6 +9,7 @@ module SlackBuilder.Config , settingsCodec ) where +import Data.List.NonEmpty (NonEmpty(..)) import Data.Text (Text) import Toml ((.=)) import qualified Toml @@ -18,7 +19,7 @@ data Settings = Settings , repository :: !FilePath , branch :: Text , downloadURL :: Text - , remotePath :: Text + , uploadCommand :: NonEmpty Text , maintainer :: MaintainerSettings } deriving (Eq, Show) @@ -32,7 +33,7 @@ settingsCodec = Settings <*> Toml.string "repository" .= repository <*> Toml.text "branch" .= branch <*> Toml.text "download_url" .= downloadURL - <*> Toml.text "remote_path" .= remotePath + <*> Toml.arrayNonEmptyOf Toml._Text "upload_command" .= uploadCommand <*> Toml.table maintainerSettingsCodec "maintainer" .= maintainer maintainerSettingsCodec :: Toml.TomlCodec MaintainerSettings diff --git a/lib/SlackBuilder/Download.hs b/lib/SlackBuilder/Download.hs index b3723e0..096ede8 100644 --- a/lib/SlackBuilder/Download.hs +++ b/lib/SlackBuilder/Download.hs @@ -14,12 +14,13 @@ module SlackBuilder.Download , sinkFileAndHash , sinkHash , updateSlackBuildVersion - , uploadCommand + , uploadSource ) where import Data.ByteString (ByteString) import qualified Data.ByteString as ByteString import qualified Data.ByteString.Char8 as Char8 +import Data.List.NonEmpty (NonEmpty(..)) import qualified Data.List.NonEmpty as NonEmpty import Data.Foldable (find) import Data.Map.Strict (Map) @@ -195,10 +196,10 @@ cloneAndUpload :: Text -> FilePath -> Text -> SlackBuilderT (URI, Digest MD5) cloneAndUpload repo tarballPath tagPrefix = do localPath <- relativeToRepository $ tarballPath <.> "tar.xz" let packageName = takeFileName $ takeDirectory tarballPath - remoteArchivePath = Text.cons '/' $ Text.pack + remoteArchivePath = Text.pack $ packageName takeFileName tarballPath <.> "tar.xz" - remoteResultURI <- hostedSources remoteArchivePath - remoteFileExists' <- remoteFileExists remoteArchivePath + remoteResultURI <- hostedSources $ Text.cons '/' remoteArchivePath + remoteFileExists' <- remoteFileExists $ Text.cons '/' remoteArchivePath if remoteFileExists' then (remoteResultURI,) . snd @@ -206,21 +207,22 @@ cloneAndUpload repo tarballPath tagPrefix = do else let go = sourceFile localPath .| sinkHash in cloneAndArchive repo tarballPath tagPrefix - >> uploadCommand localPath remoteArchivePath + >> uploadSource localPath remoteArchivePath >> liftIO (runConduitRes go) <&> (remoteResultURI,) -- | Given a path to a local file and a remote path uploads the file using -- the settings given in the configuration file. -- -- The remote path is given relative to the path in the configuration. -uploadCommand :: FilePath -> Text -> SlackBuilderT () -uploadCommand localPath remotePath' = do - remoteRoot <- SlackBuilderT $ asks remotePath +uploadSource :: FilePath -> Text -> SlackBuilderT () +uploadSource localPath remotePath' = do + uploadCommand' :| uploadArguments <- SlackBuilderT $ asks uploadCommand + let uploadArguments' = Text.unpack + . Text.replace "%s" (Text.pack localPath) + . Text.replace "%c" remotePath' + <$> uploadArguments - liftIO $ callProcess "scp" - [ localPath - , Text.unpack $ remoteRoot <> remotePath' - ] + liftIO $ callProcess (Text.unpack uploadCommand') uploadArguments' -- | Downlaods a file into the directory. Returns name of the downloaded file -- and checksum. diff --git a/src/SlackBuilder/Update.hs b/src/SlackBuilder/Update.hs index 008b63d..a23ee48 100644 --- a/src/SlackBuilder/Update.hs +++ b/src/SlackBuilder/Update.hs @@ -172,7 +172,7 @@ reuploadWithTemplate downloadTemplate commands packagePath version = do download' <- handleReupload relativeTarball' downloadFileName pure $ Package.Download download' checksum where - name' = Text.pack $ takeBaseName $ Text.unpack packagePath + category' = Text.pack $ takeBaseName $ Text.unpack packagePath prepareSource tarballPath = liftIO (traverse (defaultCreateProcess tarballPath) commands) >> liftIO (tarCompress tarballPath) @@ -190,8 +190,8 @@ reuploadWithTemplate downloadTemplate commands packagePath version = do downloadURL' <- SlackBuilderT $ asks downloadURL liftIO $ putStrLn $ "Upload the source tarball " <> relativeTarball - uploadCommand relativeTarball ("/" <> name') - liftIO $ mkURI $ downloadURL' <> "/" <> name' <> "/" <> Text.pack downloadFileName + uploadSource relativeTarball category' + liftIO $ mkURI $ downloadURL' <> "/" <> category' <> "/" <> Text.pack downloadFileName defaultCreateProcess cwd' cmdSpec = flip withCreateProcess (const . const . const waitForProcess) $ CreateProcess