packages feed

rpm-nvr-0.1.2: src/Data/RPM/NVRA.hs

{-# LANGUAGE CPP #-}

-- 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 2 of the License, or
-- (at your option) any later version.

-- | A type for a (binary) RPM package.
module Data.RPM.NVRA (
  NVRA(..),
  readNVRA,
  eitherNVRA,
  maybeNVRA,
  showNVRA,
  showPkgIdent,
  showPkgVerRel,
  )
where

import Data.Either.Extra
import Data.List.Extra
#if !MIN_VERSION_extra(1,6,4)
import Data.Maybe (fromMaybe)
#endif
#if !MIN_VERSION_base(4,11,0)
import Data.Monoid ((<>))
#endif
import Data.RPM.NVR
import Data.RPM.VerRel
import System.FilePath (takeFileName)

-- | RPM package with name, version-release, and architecture
--
-- If arch is not needed use NVR instead.
--
-- FIXME: add epoch field
data NVRA = NVRA {rpmName :: String,
                  rpmVerRel :: VerRel,
                  rpmArch :: String}
  deriving (Eq, Ord)

-- | Render an RpmPackage
showNVRA :: NVRA -> String
showNVRA (NVRA n vr a) = n <> "-" <> showVerRel vr <> "." <> a

-- | Either read a name-version-release.arch or return a failure string
--
-- Strips off ".rpm" extension and any directory path prefix.
eitherNVRA :: String -> Either String NVRA
eitherNVRA "" = Left "NVRA string cannot be empty"
eitherNVRA s@('-':_) = Left $ "NVRA cannot start with '-': " ++ s
eitherNVRA s =
  let nvra = dropSuffix ".rpm" $ takeFileName s
  in
    case reverse (splitOn "-" nvra) of
      relarch:ver:emaN ->
        if null relarch || null ver || null emaN
        then Left $ "Bad NVRA string: " ++ s
        else
          case breakOnEnd "." relarch of
            ("",_) -> Left $ "No arch suffix for " ++ s
            (_,"") -> Left $ "Package release should not end in '.' " ++ s
            (reldot,arch) ->
              Right $ NVRA (intercalate "-" $ reverse emaN) (VerRel ver (dropEnd 1 reldot)) arch
      _ -> Left $ "NVRA string must have form 'name-version-release.arch': " ++ s

-- | Maybe read an NVRA
maybeNVRA :: String -> Maybe NVRA
maybeNVRA = eitherToMaybe . eitherNVRA

-- | Parse an NVRA with arch suffix
--
-- Errors if not of the form "name-version-release[.arch]"
readNVRA :: String -> NVRA
readNVRA = either error id . eitherNVRA

-- | Render the version-release of an NVRA
showPkgVerRel :: NVRA -> String
showPkgVerRel = showVerRel . rpmVerRel

-- | Identifier for an RPM package identified by name and arch
showPkgIdent :: NVRA -> String
showPkgIdent p = rpmName p <> "." <> rpmArch p

#if !MIN_VERSION_extra(1,6,4)
dropSuffix :: Eq a => [a] -> [a] -> [a]
dropSuffix a b = fromMaybe b $ stripSuffix a b
#endif