-- |
-- Module      :  FedoraDists
-- Copyright   :  (C) 2014-2018  Jens Petersen
--
-- Maintainer  :  Jens Petersen <petersen@fedoraproject.org>
-- Stability   :  alpha
-- Portability :  portable
--
-- Explanation: Fedora dist metadata

-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.

module FedoraDists
  (Dist(..),
   dists,
   distBranch,
   distContainer,
   distRepo,
   distUpdates,
   distOverride,
   kojicmd,
   mockConfig,
   releaseVersion,
   rawhide,
   rawhideRelease,
   rpkg,
   rpmDistTag) where

import Data.Version
import Text.Read

#if (defined(MIN_VERSION_base) && MIN_VERSION_base(4,8,0))
#else
import Control.Applicative ((<$>), (*>))
import Data.Traversable (traverse)
#endif

-- | The `Dist` datatype specifies the target OS and version.
-- (roughly corresponds to a git branch)
data Dist = Fedora Int -- ^ Fedora release
          | EPEL Int -- ^ EPEL release
          | RHEL Version -- ^ RHEL version
  deriving (Eq)

instance Show Dist where
  show (Fedora n) = "f" ++ show n
  show (EPEL n) = (if n <= 6 then "el" else "epel") ++ show n
  show (RHEL v) = "rhel-" ++ show v

-- | Read from eg "f29", "epel7"
instance Read Dist where
  readPrec = choice [pFedora, pEPEL, pRHEL] where
    pChar c = do
      c' <- get
      if c == c'
        then return c
        else pfail
    pFedora = Fedora <$> (pChar 'f' *> readPrec)
    pEPEL = EPEL <$> (traverse pChar "epel" *> readPrec)
    pRHEL = RHEL <$> (traverse pChar "rhel-" *> readPrec)

  readListPrec = readListPrecDefault

-- | Current maintained distribution releases.
dists :: [Dist]
dists = [rawhide, Fedora 31, Fedora 30, Fedora 29, EPEL 8, EPEL 7, EPEL 6]

-- | The Fedora release number corresponding to current Rawhide
rawhideRelease :: Int
rawhideRelease = 32

-- | The Fedora release corresponding to Rawhide
rawhide :: Dist
rawhide = Fedora rawhideRelease

-- | Maps `Dist` to package distgit branch
distBranch :: Dist -> String
distBranch (Fedora n) | n >= rawhideRelease = "master"
distBranch d = show d

-- | Map `Dist` to DNF/YUM repo name
distRepo :: Dist -> String
distRepo (Fedora n) | n >= rawhideRelease = "rawhide"
                    | otherwise = "fedora"
distRepo (EPEL _) = "epel"
distRepo (RHEL _) = "rhel"

-- | Map `Dist` to Maybe the DNF/YUM updates repo name
distUpdates :: Dist -> Maybe String
distUpdates (Fedora n) | n >= rawhideRelease = Nothing
distUpdates (Fedora _) = Just "updates"
distUpdates _ = Nothing

-- | Whether dist has overrides in Bodhi
distOverride :: Dist -> Bool
distOverride d = d `notElem` [rawhide, Fedora 32 , EPEL 9]

-- | OS release major version for `Dist`
releaseVersion :: Dist -> String
releaseVersion (Fedora n) | n >= rawhideRelease = "rawhide"
releaseVersion (Fedora n) = show n
releaseVersion (EPEL n) = show n
releaseVersion (RHEL n) = show n

-- | `Dist` tag (appended to rpm package release field)
rpmDistTag :: Dist -> String
rpmDistTag (Fedora n) = ".fc" ++ show n
rpmDistTag (RHEL v) = ".el" ++ (show . head . versionBranch) v
rpmDistTag d = '.' : show d

-- | Command line tool for `Dist` (eg "koji")
kojicmd :: Dist -> String
kojicmd (RHEL _) = "brew"
kojicmd _ =  "koji"

-- | rpkg command for `Dist` (eg "fedpkg")
rpkg :: Dist -> String
rpkg (RHEL _) = "rhpkg"
rpkg _ = "fedpkg"

-- | Mock configuration for `Dist` and arch
mockConfig :: Dist -> String -> String
mockConfig dist arch =
  distRepo dist ++ "-" ++ releaseVersion dist ++ "-" ++ arch

-- | Map `Dist` to a container image
distContainer :: Dist -> String
distContainer (Fedora n) = "fedora:" ++ show n
distContainer (EPEL n) = "centos:" ++ show n
distContainer (RHEL n) = "ubi" ++ show n ++ "/ubi"