{-|
A library for accessing a Koji hub via its XMLRPC API.
-}

module Distribution.Koji
       ( BuildID(..)
       , BuildInfo(..)
       , buildIDInfo
       , fedoraKojiHub
       , centosKojiHub
       , kojiBuildTags
       , kojiBuildTarget
       , kojiGetBuildID
       , kojiGetBuildState
       , kojiGetBuildTaskID
       , kojiGetCurrentRepo
       , kojiGetRepo
       , kojiGetTaskInfo
       , kojiGetTaskChildren
       , kojiGetTaskState
       , kojiGetUserID
       , kojiLatestBuild
       , kojiLatestBuildRepo
       , kojiListSideTags
       , kojiListTaskIDs
       , kojiUserBuildTasks
       , KojiBuild(..)
       , kojiListTaggedBuilds
       , PackageID(..)
       , TagID(..)
       , TaskID(..)
       , UserID(..)
       , displayID
       , getID
       , readID
       , readID'
       , TaskState(..)
       , getTaskState
       , openTaskStates
       , openTaskValues
       , readTaskState
       , BuildState(..)
       , readBuildState
       , Struct
       , lookupStruct
       , Value (..)
       , getInt
       , getString
       , RepoState(..)
       , readRepoState
       )
where

import qualified Data.List as L
import Data.Maybe
import Network.XmlRpc.Internals

import Distribution.Koji.API

-- | A class for various id's: taskid, tagid, buildid, packageid, etc
class ID a where
  getID :: a -> Int
  mkID :: Int -> a

displayID :: ID a => a -> String
displayID :: forall a. ID a => a -> String
displayID = forall a. Show a => a -> String
show forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. ID a => a -> Int
getID

-- FIXME rename to structID ?
readID :: ID a => Struct -> Maybe a
readID :: forall a. ID a => Struct -> Maybe a
readID Struct
st = forall a b. Eq a => a -> [(a, b)] -> Maybe b
lookup String
"id" Struct
st forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall a. ID a => Int -> a
mkID forall b c a. (b -> c) -> (a -> b) -> a -> c
. Value -> Maybe Int
getInt

readID' :: Struct -> Maybe Int
readID' :: Struct -> Maybe Int
readID' Struct
st = forall a b. Eq a => a -> [(a, b)] -> Maybe b
lookup String
"id" Struct
st forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Value -> Maybe Int
getInt

-- FIXME rename to valueInt ?
getInt :: Value -> Maybe Int
getInt :: Value -> Maybe Int
getInt (ValueInt Int
i) = forall a. a -> Maybe a
Just Int
i
getInt Value
_ = forall a. Maybe a
Nothing

getString :: Value -> Maybe String
getString :: Value -> Maybe String
getString (ValueString String
i) = forall a. a -> Maybe a
Just String
i
getString Value
_ = forall a. Maybe a
Nothing

newtype TaskID = TaskId Int
  deriving Int -> TaskID -> ShowS
[TaskID] -> ShowS
TaskID -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [TaskID] -> ShowS
$cshowList :: [TaskID] -> ShowS
show :: TaskID -> String
$cshow :: TaskID -> String
showsPrec :: Int -> TaskID -> ShowS
$cshowsPrec :: Int -> TaskID -> ShowS
Show

instance ID TaskID where
  getID :: TaskID -> Int
getID (TaskId Int
i) = Int
i
  mkID :: Int -> TaskID
mkID = Int -> TaskID
TaskId

newtype TagID = TagId Int
  deriving Int -> TagID -> ShowS
[TagID] -> ShowS
TagID -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [TagID] -> ShowS
$cshowList :: [TagID] -> ShowS
show :: TagID -> String
$cshow :: TagID -> String
showsPrec :: Int -> TagID -> ShowS
$cshowsPrec :: Int -> TagID -> ShowS
Show

instance ID TagID where
  getID :: TagID -> Int
getID (TagId Int
i) = Int
i
  mkID :: Int -> TagID
mkID = Int -> TagID
TagId

newtype UserID = UserId Int
  deriving Int -> UserID -> ShowS
[UserID] -> ShowS
UserID -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [UserID] -> ShowS
$cshowList :: [UserID] -> ShowS
show :: UserID -> String
$cshow :: UserID -> String
showsPrec :: Int -> UserID -> ShowS
$cshowsPrec :: Int -> UserID -> ShowS
Show

instance ID UserID where
  getID :: UserID -> Int
getID (UserId Int
i) = Int
i
  mkID :: Int -> UserID
mkID = Int -> UserID
UserId

newtype BuildID = BuildId Int

instance ID BuildID where
  getID :: BuildID -> Int
getID (BuildId Int
i) = Int
i
  mkID :: Int -> BuildID
mkID = Int -> BuildID
BuildId

newtype PackageID = PackageId Int

instance ID PackageID where
  getID :: PackageID -> Int
getID (PackageId Int
i) = Int
i
  mkID :: Int -> PackageID
mkID = Int -> PackageID
PackageId

newtype BuildrootID = BuildrootId Int

instance ID BuildrootID where
  getID :: BuildrootID -> Int
getID (BuildrootId Int
i) = Int
i
  mkID :: Int -> BuildrootID
mkID = Int -> BuildrootID
BuildrootId

data BuildInfo = BuildInfoID Int | BuildInfoNVR String

-- | map a BuildInfo into a Info
buildInfo :: BuildInfo -> Info
buildInfo :: BuildInfo -> Info
buildInfo (BuildInfoID Int
bid) = Int -> Info
InfoID Int
bid
buildInfo (BuildInfoNVR String
nvr) = String -> Info
InfoString String
nvr

-- | map a buildid into a buildinfo
buildIDInfo :: BuildID -> BuildInfo
buildIDInfo :: BuildID -> BuildInfo
buildIDInfo (BuildId Int
bid) = Int -> BuildInfo
BuildInfoID Int
bid

-- | main Fedora Koji Hub
fedoraKojiHub :: String
fedoraKojiHub :: String
fedoraKojiHub = String
"https://koji.fedoraproject.org/kojihub"

-- | Centos Koji mbox Hub
centosKojiHub :: String
centosKojiHub :: String
centosKojiHub = String
"https://koji.mbox.centos.org/kojihub"

-- | Get the buildid of an nvr build
kojiGetBuildID :: String -- ^ hub url
               -> String -- ^ NVR
               -> IO (Maybe BuildID)
kojiGetBuildID :: String -> String -> IO (Maybe BuildID)
kojiGetBuildID String
hubUrl String
nvr =
  ((forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Int -> BuildID
BuildId forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. XmlRpcType a => String -> Struct -> Maybe a
lookupStruct String
"id") forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<<) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> String -> Info -> IO (Maybe Struct)
getBuild String
hubUrl (String -> Info
InfoString String
nvr)

-- | Get the task of an nvr build
kojiGetBuildTaskID :: String -- ^ hub url
                   -> String -- ^ NVR
                   -> IO (Maybe TaskID)
kojiGetBuildTaskID :: String -> String -> IO (Maybe TaskID)
kojiGetBuildTaskID String
hubUrl String
nvr =
  ((forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Int -> TaskID
TaskId forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. XmlRpcType a => String -> Struct -> Maybe a
lookupStruct String
"task_id") forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<<) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> String -> Info -> IO (Maybe Struct)
getBuild String
hubUrl (String -> Info
InfoString String
nvr)

-- | List tasks filtered by query options
kojiListTaskIDs :: String -- ^ hub url
                -> Struct -- ^ options
                -> Struct -- ^ query opts
                -> IO [TaskID]
kojiListTaskIDs :: String -> Struct -> Struct -> IO [TaskID]
kojiListTaskIDs String
hubUrl Struct
opts Struct
qopts =
  forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe forall a. ID a => Struct -> Maybe a
readID forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> String -> Struct -> Struct -> IO [Struct]
listTasks String
hubUrl Struct
opts Struct
qopts

-- | List the open tasks of a user (matching source/target)
kojiUserBuildTasks :: String -- ^ hub url
                   -> UserID
                   -> Maybe String -- ^ source
                   -> Maybe String -- ^ target
                   -> IO [TaskID]
kojiUserBuildTasks :: String -> UserID -> Maybe String -> Maybe String -> IO [TaskID]
kojiUserBuildTasks String
hubUrl UserID
userid Maybe String
msource Maybe String
mtarget = do
  [Struct]
tasks <- String -> Struct -> Struct -> IO [Struct]
listTasks String
hubUrl [(String
"owner",Int -> Value
ValueInt (forall a. ID a => a -> Int
getID UserID
userid)),(String
"method",String -> Value
ValueString String
"build"),(String
"state",Value
openTaskValues)] []
  forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall a b. (a -> b) -> [a] -> [b]
map Int -> TaskID
TaskId forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe (forall a. XmlRpcType a => String -> Struct -> Maybe a
lookupStruct String
"id") forall a b. (a -> b) -> a -> b
$ forall a. (a -> Bool) -> [a] -> [a]
filter Struct -> Bool
isTheBuild [Struct]
tasks
  where
    isTheBuild :: Struct -> Bool
    isTheBuild :: Struct -> Bool
isTheBuild Struct
st =
      let mreq :: Maybe String
mreq = forall a. XmlRpcType a => String -> Struct -> Maybe a
lookupStruct String
"request" Struct
st in
        case Maybe String
mreq of
          Maybe String
Nothing -> Bool
False
          Just String
req ->
            forall b a. b -> (a -> b) -> Maybe a -> b
maybe Bool
True (forall a. Eq a => [a] -> [a] -> Bool
`L.isInfixOf` String
req) Maybe String
msource Bool -> Bool -> Bool
&&
            forall b a. b -> (a -> b) -> Maybe a -> b
maybe Bool
True (\ String
target -> (String
"<value><string>" forall a. [a] -> [a] -> [a]
++ String
target forall a. [a] -> [a] -> [a]
++ String
"</string></value>") forall a. Eq a => [a] -> [a] -> Bool
`L.isInfixOf` String
req) Maybe String
mtarget

-- getTagID :: String -- ^ tag
--          -> IO TagID
-- getTagID tag =
--   TagId <$> koji "getTagID" tag

-- | Get the userid for the named user
kojiGetUserID :: String -- ^ hub url
              -> String -- ^ user
              -> IO (Maybe UserID)
kojiGetUserID :: String -> String -> IO (Maybe UserID)
kojiGetUserID String
hubUrl String
name = do
  Maybe Struct
res <- String -> Info -> Bool -> IO (Maybe Struct)
getUser String
hubUrl (String -> Info
InfoString String
name) Bool
False
  forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall a. ID a => Struct -> Maybe a
readID forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Maybe Struct
res

-- | Get the tags of a build
kojiBuildTags :: String  -- ^ hub url
              -> BuildInfo
              -> IO [String]
kojiBuildTags :: String -> BuildInfo -> IO [String]
kojiBuildTags String
hubUrl BuildInfo
buildinfo = do
  [Struct]
lst <- String -> Maybe Info -> Maybe Info -> Bool -> IO [Struct]
listTags String
hubUrl (forall a. a -> Maybe a
Just (BuildInfo -> Info
buildInfo BuildInfo
buildinfo)) forall a. Maybe a
Nothing Bool
False
  forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe (forall a. XmlRpcType a => String -> Struct -> Maybe a
lookupStruct String
"name") [Struct]
lst

-- | The state of a build
data BuildState = BuildBuilding
                | BuildComplete
                | BuildDeleted
                | BuildFailed
                | BuildCanceled
  deriving (BuildState -> BuildState -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: BuildState -> BuildState -> Bool
$c/= :: BuildState -> BuildState -> Bool
== :: BuildState -> BuildState -> Bool
$c== :: BuildState -> BuildState -> Bool
Eq, Int -> BuildState
BuildState -> Int
BuildState -> [BuildState]
BuildState -> BuildState
BuildState -> BuildState -> [BuildState]
BuildState -> BuildState -> BuildState -> [BuildState]
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
enumFromThenTo :: BuildState -> BuildState -> BuildState -> [BuildState]
$cenumFromThenTo :: BuildState -> BuildState -> BuildState -> [BuildState]
enumFromTo :: BuildState -> BuildState -> [BuildState]
$cenumFromTo :: BuildState -> BuildState -> [BuildState]
enumFromThen :: BuildState -> BuildState -> [BuildState]
$cenumFromThen :: BuildState -> BuildState -> [BuildState]
enumFrom :: BuildState -> [BuildState]
$cenumFrom :: BuildState -> [BuildState]
fromEnum :: BuildState -> Int
$cfromEnum :: BuildState -> Int
toEnum :: Int -> BuildState
$ctoEnum :: Int -> BuildState
pred :: BuildState -> BuildState
$cpred :: BuildState -> BuildState
succ :: BuildState -> BuildState
$csucc :: BuildState -> BuildState
Enum, Int -> BuildState -> ShowS
[BuildState] -> ShowS
BuildState -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [BuildState] -> ShowS
$cshowList :: [BuildState] -> ShowS
show :: BuildState -> String
$cshow :: BuildState -> String
showsPrec :: Int -> BuildState -> ShowS
$cshowsPrec :: Int -> BuildState -> ShowS
Show)

readBuildState :: Value -> BuildState
readBuildState :: Value -> BuildState
readBuildState (ValueInt Int
i) | Int
i forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` forall a b. (a -> b) -> [a] -> [b]
map forall a. Enum a => a -> Int
fromEnum (forall a. Enum a => a -> [a]
enumFrom BuildState
BuildBuilding) = forall a. Enum a => Int -> a
toEnum Int
i
readBuildState Value
_ = forall a. HasCallStack => String -> a
error String
"invalid build state"

-- | Get the state of a build
kojiGetBuildState :: String -- ^ hub url
                  -> BuildInfo
                  -> IO (Maybe BuildState)
kojiGetBuildState :: String -> BuildInfo -> IO (Maybe BuildState)
kojiGetBuildState String
hubUrl BuildInfo
buildinfo =
  ((forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Value -> BuildState
readBuildState forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. XmlRpcType a => String -> Struct -> Maybe a
lookupStruct String
"state") forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<<) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$>
  String -> Info -> IO (Maybe Struct)
getBuild String
hubUrl (BuildInfo -> Info
buildInfo BuildInfo
buildinfo)

-- | The state of a task
data TaskState = TaskFree
               | TaskOpen
               | TaskClosed
               | TaskCanceled
               | TaskAssigned
               | TaskFailed
  deriving (TaskState -> TaskState -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: TaskState -> TaskState -> Bool
$c/= :: TaskState -> TaskState -> Bool
== :: TaskState -> TaskState -> Bool
$c== :: TaskState -> TaskState -> Bool
Eq, Int -> TaskState
TaskState -> Int
TaskState -> [TaskState]
TaskState -> TaskState
TaskState -> TaskState -> [TaskState]
TaskState -> TaskState -> TaskState -> [TaskState]
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
enumFromThenTo :: TaskState -> TaskState -> TaskState -> [TaskState]
$cenumFromThenTo :: TaskState -> TaskState -> TaskState -> [TaskState]
enumFromTo :: TaskState -> TaskState -> [TaskState]
$cenumFromTo :: TaskState -> TaskState -> [TaskState]
enumFromThen :: TaskState -> TaskState -> [TaskState]
$cenumFromThen :: TaskState -> TaskState -> [TaskState]
enumFrom :: TaskState -> [TaskState]
$cenumFrom :: TaskState -> [TaskState]
fromEnum :: TaskState -> Int
$cfromEnum :: TaskState -> Int
toEnum :: Int -> TaskState
$ctoEnum :: Int -> TaskState
pred :: TaskState -> TaskState
$cpred :: TaskState -> TaskState
succ :: TaskState -> TaskState
$csucc :: TaskState -> TaskState
Enum, Int -> TaskState -> ShowS
[TaskState] -> ShowS
TaskState -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [TaskState] -> ShowS
$cshowList :: [TaskState] -> ShowS
show :: TaskState -> String
$cshow :: TaskState -> String
showsPrec :: Int -> TaskState -> ShowS
$cshowsPrec :: Int -> TaskState -> ShowS
Show)

-- | Open task states
openTaskStates :: [TaskState]
openTaskStates :: [TaskState]
openTaskStates = [TaskState
TaskFree, TaskState
TaskOpen, TaskState
TaskAssigned]

openTaskValues :: Value
openTaskValues :: Value
openTaskValues = [Value] -> Value
ValueArray forall a b. (a -> b) -> a -> b
$ forall a b. (a -> b) -> [a] -> [b]
map TaskState -> Value
taskStateToValue [TaskState]
openTaskStates
  where
    taskStateToValue :: TaskState -> Value
    taskStateToValue :: TaskState -> Value
taskStateToValue = Int -> Value
ValueInt forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Enum a => a -> Int
fromEnum

readTaskState :: Value -> TaskState
readTaskState :: Value -> TaskState
readTaskState (ValueInt Int
i) | Int
i forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` forall a b. (a -> b) -> [a] -> [b]
map forall a. Enum a => a -> Int
fromEnum (forall a. Enum a => a -> [a]
enumFrom TaskState
TaskFree) = forall a. Enum a => Int -> a
toEnum Int
i
readTaskState Value
_ = forall a. HasCallStack => String -> a
error String
"invalid task state"

getTaskState :: Struct -> Maybe TaskState
getTaskState :: Struct -> Maybe TaskState
getTaskState Struct
st = Value -> TaskState
readTaskState forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a b. Eq a => a -> [(a, b)] -> Maybe b
lookup String
"state" Struct
st

-- | Get the state of a taskid
kojiGetTaskState :: String -- ^ hub url
                 -> TaskID
                 -> IO (Maybe TaskState)
kojiGetTaskState :: String -> TaskID -> IO (Maybe TaskState)
kojiGetTaskState String
hubUrl TaskID
tid = do
  Maybe Struct
mti <- String -> Int -> Bool -> IO (Maybe Struct)
getTaskInfo String
hubUrl (forall a. ID a => a -> Int
getID TaskID
tid) Bool
False
  forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ case Maybe Struct
mti of
             Maybe Struct
Nothing -> forall a. Maybe a
Nothing
             Just Struct
ti -> Value -> TaskState
readTaskState forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. XmlRpcType a => String -> Struct -> Maybe a
lookupStruct String
"state" Struct
ti

-- | Get info about a task
kojiGetTaskInfo :: String -- ^ hub url
                -> TaskID
                -> IO (Maybe Struct)
kojiGetTaskInfo :: String -> TaskID -> IO (Maybe Struct)
kojiGetTaskInfo String
hubUrl TaskID
tid = String -> Int -> Bool -> IO (Maybe Struct)
getTaskInfo String
hubUrl (forall a. ID a => a -> Int
getID TaskID
tid) Bool
True
  -- res <- kojiCall "getTaskInfo" [show taskid]
  -- let state = res ^? key "state" % _Integer <&> (toEnum . fromInteger)
  --     arch = res ^? key "arch" % _String
  -- return $ TaskInfo arch state

-- | Get the children tasks of a task
kojiGetTaskChildren :: String -- ^ hub url
                    -> TaskID
                    -> Bool
                    -> IO [Struct]
kojiGetTaskChildren :: String -> TaskID -> Bool -> IO [Struct]
kojiGetTaskChildren String
hubUrl TaskID
tid =
  String -> Int -> Bool -> IO [Struct]
getTaskChildren String
hubUrl (forall a. ID a => a -> Int
getID TaskID
tid)

-- | Get the latest build of a package in a tag
kojiLatestBuild :: String -- ^ hub
                -> String -- ^ tag
                -> String -- ^ pkg
                -> IO (Maybe Struct)
kojiLatestBuild :: String -> String -> String -> IO (Maybe Struct)
kojiLatestBuild String
hubUrl String
tag String
pkg =
  forall a. [a] -> Maybe a
listToMaybe forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> String
-> Info -> Maybe Int -> Maybe String -> Maybe String -> IO [Struct]
getLatestBuilds String
hubUrl (String -> Info
InfoString String
tag) forall a. Maybe a
Nothing (forall a. a -> Maybe a
Just String
pkg) forall a. Maybe a
Nothing

-- | Get latest build in a tag for package at a time event.
--
-- Used for example to implement waitrepo
kojiLatestBuildRepo :: String -- ^ hub
                    -> String -- ^ tag
                    -> Int    -- ^ event
                    -> String -- ^ pkg
                    -> IO (Maybe Struct)
kojiLatestBuildRepo :: String -> String -> Int -> String -> IO (Maybe Struct)
kojiLatestBuildRepo String
hubUrl String
tag Int
event String
pkg =
  forall a. [a] -> Maybe a
listToMaybe forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> String
-> Info -> Maybe Int -> Maybe String -> Maybe String -> IO [Struct]
getLatestBuilds String
hubUrl (String -> Info
InfoString String
tag) (forall a. a -> Maybe a
Just Int
event) (forall a. a -> Maybe a
Just String
pkg) forall a. Maybe a
Nothing

-- | Build metadata
data KojiBuild
  = KojiBuild
      { KojiBuild -> Int
kbBuildId :: Int
      , KojiBuild -> Int
kbPackageId :: Int
      , KojiBuild -> String
kbOwnerName :: String
      , KojiBuild -> String
kbNvr :: String
      }
  deriving (Int -> KojiBuild -> ShowS
[KojiBuild] -> ShowS
KojiBuild -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [KojiBuild] -> ShowS
$cshowList :: [KojiBuild] -> ShowS
show :: KojiBuild -> String
$cshow :: KojiBuild -> String
showsPrec :: Int -> KojiBuild -> ShowS
$cshowsPrec :: Int -> KojiBuild -> ShowS
Show)

-- | List builds in a tag
kojiListTaggedBuilds :: String -- ^ hub url
                     -> Bool -- ^ latest
                     -> String -- ^ tag
                     -> IO [KojiBuild]
kojiListTaggedBuilds :: String -> Bool -> String -> IO [KojiBuild]
kojiListTaggedBuilds String
hubUrl Bool
latest String
tag =
  forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe Struct -> Maybe KojiBuild
readKojiBuild forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> String
-> String
-> Maybe Int
-> Bool
-> Maybe String
-> Bool
-> Maybe String
-> Maybe String
-> Maybe String
-> IO [Struct]
listTagged String
hubUrl String
tag forall a. Maybe a
Nothing Bool
False forall a. Maybe a
Nothing Bool
latest forall a. Maybe a
Nothing forall a. Maybe a
Nothing forall a. Maybe a
Nothing
  where
    readKojiBuild :: Struct -> Maybe KojiBuild
    readKojiBuild :: Struct -> Maybe KojiBuild
readKojiBuild Struct
values = do
      Int
buildId <- forall a. XmlRpcType a => String -> Struct -> Maybe a
lookupStruct String
"build_id" Struct
values
      Int
packageId <- forall a. XmlRpcType a => String -> Struct -> Maybe a
lookupStruct String
"package_id" Struct
values
      String
owner <- forall a. XmlRpcType a => String -> Struct -> Maybe a
lookupStruct String
"owner_name" Struct
values
      String
nvr <- forall a. XmlRpcType a => String -> Struct -> Maybe a
lookupStruct String
"nvr" Struct
values
      forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ Int -> Int -> String -> String -> KojiBuild
KojiBuild Int
buildId Int
packageId String
owner String
nvr

-- | Get the build and dest tags for a target.
kojiBuildTarget :: String -- ^ hubUrl
                -> String -- ^ target
                -> IO (Maybe (String, String)) -- ^ (build-tag,dest-tag)
kojiBuildTarget :: String -> String -> IO (Maybe (String, String))
kojiBuildTarget String
hub String
target = do
  Maybe Struct
mres <- Value -> Maybe Struct
maybeStruct forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> String -> String -> IO Value
getBuildTarget String
hub String
target
  case Maybe Struct
mres of
    Maybe Struct
Nothing -> forall (m :: * -> *) a. Monad m => a -> m a
return forall a. Maybe a
Nothing
    Just Struct
res -> forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall {a} {b}.
(XmlRpcType a, XmlRpcType b) =>
Struct -> Maybe (a, b)
readTarget Struct
res
  where
  readTarget :: Struct -> Maybe (a, b)
readTarget Struct
res = do
    a
buildtag <- forall a. XmlRpcType a => String -> Struct -> Maybe a
lookupStruct String
"build_tag_name" Struct
res
    b
desttag <- forall a. XmlRpcType a => String -> Struct -> Maybe a
lookupStruct String
"dest_tag_name" Struct
res
    forall (m :: * -> *) a. Monad m => a -> m a
return (a
buildtag, b
desttag)

-- | List sidetags (preferably for user and/or basetag)
kojiListSideTags :: String -- ^ hubUrl
                 -> Maybe String -- ^ basetag
                 -> Maybe String -- ^ user
                 -> IO [String] -- ^ list of sidetags
kojiListSideTags :: String -> Maybe String -> Maybe String -> IO [String]
kojiListSideTags String
hub Maybe String
mbasetag Maybe String
muser =
  forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe (forall a. XmlRpcType a => String -> Struct -> Maybe a
lookupStruct String
"name") forall b c a. (b -> c) -> (a -> b) -> a -> c
. Value -> [Struct]
structArray forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> String -> Maybe Info -> Maybe Info -> IO Value
listSideTags String
hub (String -> Info
InfoString forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe String
mbasetag) (String -> Info
InfoString forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe String
muser)

-- | Repo state
data RepoState = RepoInit
               | RepoReady
               | RepoExpired
               | RepoDeleted
               | RepoProblem
  deriving (RepoState -> RepoState -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: RepoState -> RepoState -> Bool
$c/= :: RepoState -> RepoState -> Bool
== :: RepoState -> RepoState -> Bool
$c== :: RepoState -> RepoState -> Bool
Eq, Int -> RepoState
RepoState -> Int
RepoState -> [RepoState]
RepoState -> RepoState
RepoState -> RepoState -> [RepoState]
RepoState -> RepoState -> RepoState -> [RepoState]
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
enumFromThenTo :: RepoState -> RepoState -> RepoState -> [RepoState]
$cenumFromThenTo :: RepoState -> RepoState -> RepoState -> [RepoState]
enumFromTo :: RepoState -> RepoState -> [RepoState]
$cenumFromTo :: RepoState -> RepoState -> [RepoState]
enumFromThen :: RepoState -> RepoState -> [RepoState]
$cenumFromThen :: RepoState -> RepoState -> [RepoState]
enumFrom :: RepoState -> [RepoState]
$cenumFrom :: RepoState -> [RepoState]
fromEnum :: RepoState -> Int
$cfromEnum :: RepoState -> Int
toEnum :: Int -> RepoState
$ctoEnum :: Int -> RepoState
pred :: RepoState -> RepoState
$cpred :: RepoState -> RepoState
succ :: RepoState -> RepoState
$csucc :: RepoState -> RepoState
Enum, Int -> RepoState -> ShowS
[RepoState] -> ShowS
RepoState -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [RepoState] -> ShowS
$cshowList :: [RepoState] -> ShowS
show :: RepoState -> String
$cshow :: RepoState -> String
showsPrec :: Int -> RepoState -> ShowS
$cshowsPrec :: Int -> RepoState -> ShowS
Show)

readRepoState :: Value -> RepoState
readRepoState :: Value -> RepoState
readRepoState (ValueInt Int
i) | Int
i forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` forall a b. (a -> b) -> [a] -> [b]
map forall a. Enum a => a -> Int
fromEnum (forall a. Enum a => a -> [a]
enumFrom RepoState
RepoInit) = forall a. Enum a => Int -> a
toEnum Int
i
readRepoState Value
_ = forall a. HasCallStack => String -> a
error String
"invalid repo state"

-- getRepoState :: Struct -> Maybe RepoState
-- getRepoState st = readRepoState <$> lookup "state" st

-- | Get repo info for tag
kojiGetRepo :: String -- ^ hub url
            -> String -- ^ tag
            -> Maybe RepoState
            -> Maybe Int -- ^ event
            -> IO (Maybe Struct) -- ^ result
kojiGetRepo :: String
-> String -> Maybe RepoState -> Maybe Int -> IO (Maybe Struct)
kojiGetRepo String
hub String
tag Maybe RepoState
mstate Maybe Int
mevent =
  Value -> Maybe Struct
maybeStruct forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> String -> String -> Maybe Int -> Maybe Int -> Bool -> IO Value
getRepo String
hub String
tag (forall a. Enum a => a -> Int
fromEnum forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe RepoState
mstate) Maybe Int
mevent Bool
False

-- | Get current repo info for tag
kojiGetCurrentRepo :: String -> String -> IO (Maybe Struct)
kojiGetCurrentRepo :: String -> String -> IO (Maybe Struct)
kojiGetCurrentRepo String
hub String
tag =
  Value -> Maybe Struct
maybeStruct forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> String -> String -> Maybe Int -> Maybe Int -> Bool -> IO Value
getRepo String
hub String
tag forall a. Maybe a
Nothing forall a. Maybe a
Nothing Bool
False