summaryrefslogtreecommitdiff
path: root/app/SlackBuilder/Download.hs
blob: 83db68779e0da232f53ef2acb42873afd4fff5a1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
module SlackBuilder.Download
    ( commit
    , hostedSources
    , remoteFileExists
    , updateSlackBuildVersion
    ) where

import Data.Text (Text)
import qualified Data.Text as Text
import qualified Data.Text.IO as Text.IO
import SlackBuilder.Config
import SlackBuilder.Trans
import Control.Monad.Trans.Reader (asks)
import Control.Monad.IO.Class (MonadIO(liftIO))
import System.IO (IOMode(..), withFile)
import System.FilePath ((</>), (<.>))
import System.Process (CreateProcess(..), StdStream(..), proc, readCreateProcessWithExitCode, callProcess)
import System.Exit (ExitCode(..))
import Control.Monad (unless)
import Text.URI (URI(..), mkURI)
import Network.HTTP.Req
    ( useHttpsURI
    , HEAD(..)
    , NoReqBody(..)
    , req
    , runReq
    , defaultHttpConfig
    , ignoreResponse
    , responseStatusCode, HttpConfig (..)
    )
import Data.Maybe (fromMaybe)
import Data.Functor ((<&>))

updateSlackBuildVersion :: Text -> Text -> SlackBuilderT ()
updateSlackBuildVersion packagePath version = do
    repository' <- SlackBuilderT $ asks repository
    let name = Text.unpack $ snd $ Text.breakOnEnd "/" packagePath
        slackbuildFilename = repository'
            </> Text.unpack packagePath
            </> (name <.> "SlackBuild")
    slackbuildContents <- liftIO $ Text.IO.readFile slackbuildFilename
    let (contentsHead, contentsTail) = Text.dropWhile (/= '\n')
            <$> Text.breakOn "VERSION=${VERSION:-" slackbuildContents
 
    liftIO $ Text.IO.writeFile slackbuildFilename
        $ contentsHead <> "VERSION=${VERSION:-" <> version <> "}" <> contentsTail

commit :: Text -> Text -> SlackBuilderT ()
commit packagePath version = do
    branch' <- SlackBuilderT $ Text.unpack <$> asks branch
    repository' <- SlackBuilderT $ asks repository
    let message = Text.unpack
            $ packagePath <> ": Updated for version " <> version

    (checkoutExitCode, _, _) <- liftIO
        $ withFile "/dev/null" WriteMode
        $ testCheckout repository' branch'
 
    unless (checkoutExitCode == ExitSuccess)
        $ liftIO
        $ callProcess "git" ["-C", repository', "checkout", "-b", branch', "master"]
    liftIO
        $ callProcess "git" ["-C", repository', "add", Text.unpack packagePath]
        >> callProcess "git" ["-C", repository', "commit", "-S", "-m", message]
  where
    testCheckout repository' branch' nullHandle =
        let createCheckoutProcess = (proc "git" ["-C", repository', "checkout", branch'])
                { std_in = NoStream
                , std_err = UseHandle nullHandle
                }
         in readCreateProcessWithExitCode createCheckoutProcess ""

hostedSources :: Text -> SlackBuilderT URI
hostedSources absoluteURL = SlackBuilderT (asks downloadURL)
    >>= liftIO . mkURI . (<> absoluteURL)

remoteFileExists :: Text -> SlackBuilderT Bool
remoteFileExists url = hostedSources url
    >>= traverse (runReq httpConfig . go . fst) . useHttpsURI
    <&> maybe False ((== 200) . responseStatusCode)
  where
    httpConfig = defaultHttpConfig
        { httpConfigCheckResponse = const $ const $ const Nothing
        }
    go uri = req HEAD uri NoReqBody ignoreResponse mempty