{-# LANGUAGE DeriveGeneric   #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE CPP #-}

{- |
   A representation of the @meta@ section used in Nix expressions. A
   detailed description can be found in section 4, \"Meta-attributes\",
   of the Nixpkgs manual at <http://nixos.org/nixpkgs/docs.html>.
 -}

module Distribution.Nixpkgs.Meta
  ( Meta, nullMeta
  , homepage, description, license, platforms, hydraPlatforms, maintainers, broken
  , allKnownPlatforms
  ) where

-- Avoid name clash with Prelude.<> exported by post-SMP versions of base.
#if MIN_VERSION_base(4,11,0)
import Prelude hiding ( (<>) )
#endif
import Control.DeepSeq
import Control.Lens
import Data.Set ( Set )
import qualified Data.Set as Set
import Distribution.Nixpkgs.License
import Distribution.System
import GHC.Generics ( Generic )
import Language.Nix.Identifier
import Language.Nix.PrettyPrinting

-- | A representation of the @meta@ section used in Nix expressions.
--
-- >>> :set -XOverloadedStrings
-- >>> :{
--   print (pPrint (Meta "http://example.org" "an example package" (Unknown Nothing)
--                  (Set.singleton (Platform X86_64 Linux))
--                  Set.empty
--                  (Set.fromList ["joe","jane"])
--                  True))
-- :}
-- homepage = "http://example.org";
-- description = "an example package";
-- license = "unknown";
-- platforms = [ "x86_64-linux" ];
-- hydraPlatforms = lib.platforms.none;
-- maintainers = with lib.maintainers; [ jane joe ];
-- broken = true;

data Meta = Meta
  { Meta -> String
_homepage       :: String           -- ^ URL of the package homepage
  , Meta -> String
_description    :: String           -- ^ short description of the package
  , Meta -> License
_license        :: License          -- ^ licensing terms
  , Meta -> Set Platform
_platforms      :: Set Platform     -- ^ We re-use the Cabal type for convenience, but render it to conform to @pkgs\/lib\/platforms.nix@.
  , Meta -> Set Platform
_hydraPlatforms :: Set Platform     -- ^ list of platforms built by Hydra (render to conform to @pkgs\/lib\/platforms.nix@)
  , Meta -> Set Identifier
_maintainers    :: Set Identifier   -- ^ list of maintainers from @pkgs\/lib\/maintainers.nix@
  , Meta -> Bool
_broken         :: Bool             -- ^ set to @true@ if the build is known to fail
  }
  deriving (Int -> Meta -> ShowS
[Meta] -> ShowS
Meta -> String
(Int -> Meta -> ShowS)
-> (Meta -> String) -> ([Meta] -> ShowS) -> Show Meta
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Meta] -> ShowS
$cshowList :: [Meta] -> ShowS
show :: Meta -> String
$cshow :: Meta -> String
showsPrec :: Int -> Meta -> ShowS
$cshowsPrec :: Int -> Meta -> ShowS
Show, Meta -> Meta -> Bool
(Meta -> Meta -> Bool) -> (Meta -> Meta -> Bool) -> Eq Meta
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Meta -> Meta -> Bool
$c/= :: Meta -> Meta -> Bool
== :: Meta -> Meta -> Bool
$c== :: Meta -> Meta -> Bool
Eq, Eq Meta
Eq Meta
-> (Meta -> Meta -> Ordering)
-> (Meta -> Meta -> Bool)
-> (Meta -> Meta -> Bool)
-> (Meta -> Meta -> Bool)
-> (Meta -> Meta -> Bool)
-> (Meta -> Meta -> Meta)
-> (Meta -> Meta -> Meta)
-> Ord Meta
Meta -> Meta -> Bool
Meta -> Meta -> Ordering
Meta -> Meta -> Meta
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: Meta -> Meta -> Meta
$cmin :: Meta -> Meta -> Meta
max :: Meta -> Meta -> Meta
$cmax :: Meta -> Meta -> Meta
>= :: Meta -> Meta -> Bool
$c>= :: Meta -> Meta -> Bool
> :: Meta -> Meta -> Bool
$c> :: Meta -> Meta -> Bool
<= :: Meta -> Meta -> Bool
$c<= :: Meta -> Meta -> Bool
< :: Meta -> Meta -> Bool
$c< :: Meta -> Meta -> Bool
compare :: Meta -> Meta -> Ordering
$ccompare :: Meta -> Meta -> Ordering
$cp1Ord :: Eq Meta
Ord, (forall x. Meta -> Rep Meta x)
-> (forall x. Rep Meta x -> Meta) -> Generic Meta
forall x. Rep Meta x -> Meta
forall x. Meta -> Rep Meta x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep Meta x -> Meta
$cfrom :: forall x. Meta -> Rep Meta x
Generic)

makeLenses ''Meta

instance NFData Meta

instance Pretty Meta where
  pPrint :: Meta -> Doc
pPrint Meta {Bool
String
Set Platform
Set Identifier
License
_broken :: Bool
_maintainers :: Set Identifier
_hydraPlatforms :: Set Platform
_platforms :: Set Platform
_license :: License
_description :: String
_homepage :: String
_broken :: Meta -> Bool
_maintainers :: Meta -> Set Identifier
_hydraPlatforms :: Meta -> Set Platform
_platforms :: Meta -> Set Platform
_license :: Meta -> License
_description :: Meta -> String
_homepage :: Meta -> String
..} = [Doc] -> Doc
vcat
    [ Bool -> Doc -> Doc
onlyIf (Bool -> Bool
not (String -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null String
_homepage)) (Doc -> Doc) -> Doc -> Doc
forall a b. (a -> b) -> a -> b
$ String -> Doc -> Doc
attr String
"homepage" (Doc -> Doc) -> Doc -> Doc
forall a b. (a -> b) -> a -> b
$ String -> Doc
string String
_homepage
    , Bool -> Doc -> Doc
onlyIf (Bool -> Bool
not (String -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null String
_description)) (Doc -> Doc) -> Doc -> Doc
forall a b. (a -> b) -> a -> b
$ String -> Doc -> Doc
attr String
"description" (Doc -> Doc) -> Doc -> Doc
forall a b. (a -> b) -> a -> b
$ String -> Doc
string String
_description
    , String -> Doc -> Doc
attr String
"license" (Doc -> Doc) -> Doc -> Doc
forall a b. (a -> b) -> a -> b
$ License -> Doc
forall a. Pretty a => a -> Doc
pPrint License
_license
    , Bool -> Doc -> Doc
onlyIf (Set Platform
_platforms Set Platform -> Set Platform -> Bool
forall a. Eq a => a -> a -> Bool
/= Set Platform
allKnownPlatforms) (Doc -> Doc) -> Doc -> Doc
forall a b. (a -> b) -> a -> b
$ String -> Set Platform -> Doc
renderPlatforms String
"platforms" Set Platform
_platforms
    , Bool -> Doc -> Doc
onlyIf (Set Platform
_hydraPlatforms Set Platform -> Set Platform -> Bool
forall a. Eq a => a -> a -> Bool
/= Set Platform
_platforms) (Doc -> Doc) -> Doc -> Doc
forall a b. (a -> b) -> a -> b
$ String -> Set Platform -> Doc
renderPlatforms String
"hydraPlatforms" Set Platform
_hydraPlatforms
    , String -> Doc -> Set String -> Doc
setattr String
"maintainers" (String -> Doc
text String
"with lib.maintainers;") ((Identifier -> String) -> Set Identifier -> Set String
forall b a. Ord b => (a -> b) -> Set a -> Set b
Set.map (Getting String Identifier String -> Identifier -> String
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting String Identifier String
Iso' Identifier String
ident) Set Identifier
_maintainers)
    , String -> Bool -> Bool -> Doc
boolattr String
"broken" Bool
_broken Bool
_broken
    ]

renderPlatforms :: String -> Set Platform -> Doc
renderPlatforms :: String -> Set Platform -> Doc
renderPlatforms String
field Set Platform
ps
  | Set Platform -> Bool
forall a. Set a -> Bool
Set.null Set Platform
ps = [Doc] -> Doc
sep [ String -> Doc
text String
field Doc -> Doc -> Doc
<+> Doc
equals Doc -> Doc -> Doc
<+> String -> Doc
text String
"lib.platforms.none" Doc -> Doc -> Doc
<> Doc
semi ]
  | Bool
otherwise   = String -> Doc -> Set String -> Doc
setattr String
field Doc
forall a. Monoid a => a
mempty (Set String -> Doc) -> Set String -> Doc
forall a b. (a -> b) -> a -> b
$ (Platform -> String) -> Set Platform -> Set String
forall b a. Ord b => (a -> b) -> Set a -> Set b
Set.map Platform -> String
fromCabalPlatform Set Platform
ps

nullMeta :: Meta
nullMeta :: Meta
nullMeta = Meta :: String
-> String
-> License
-> Set Platform
-> Set Platform
-> Set Identifier
-> Bool
-> Meta
Meta
  { _homepage :: String
_homepage = ShowS
forall a. HasCallStack => String -> a
error String
"undefined Meta.homepage"
  , _description :: String
_description = ShowS
forall a. HasCallStack => String -> a
error String
"undefined Meta.description"
  , _license :: License
_license = String -> License
forall a. HasCallStack => String -> a
error String
"undefined Meta.license"
  , _platforms :: Set Platform
_platforms = String -> Set Platform
forall a. HasCallStack => String -> a
error String
"undefined Meta.platforms"
  , _hydraPlatforms :: Set Platform
_hydraPlatforms = String -> Set Platform
forall a. HasCallStack => String -> a
error String
"undefined Meta.hydraPlatforms"
  , _maintainers :: Set Identifier
_maintainers = String -> Set Identifier
forall a. HasCallStack => String -> a
error String
"undefined Meta.maintainers"
  , _broken :: Bool
_broken = String -> Bool
forall a. HasCallStack => String -> a
error String
"undefined Meta.broken"
  }

allKnownPlatforms :: Set Platform
allKnownPlatforms :: Set Platform
allKnownPlatforms = [Platform] -> Set Platform
forall a. Ord a => [a] -> Set a
Set.fromList [ Arch -> OS -> Platform
Platform Arch
I386 OS
Linux, Arch -> OS -> Platform
Platform Arch
X86_64 OS
Linux
                                 , Arch -> OS -> Platform
Platform Arch
X86_64 OS
OSX, Arch -> OS -> Platform
Platform (String -> Arch
OtherArch String
"armv7l") OS
Linux
                                 , Arch -> OS -> Platform
Platform Arch
AArch64 OS
Linux, Arch -> OS -> Platform
Platform Arch
AArch64 OS
OSX
                                 ]

fromCabalPlatform :: Platform -> String
fromCabalPlatform :: Platform -> String
fromCabalPlatform (Platform Arch
I386 OS
Linux)                 = String
"\"i686-linux\""
fromCabalPlatform (Platform Arch
X86_64 OS
Linux)               = String
"\"x86_64-linux\""
fromCabalPlatform (Platform Arch
X86_64 OS
OSX)                 = String
"\"x86_64-darwin\""
fromCabalPlatform (Platform (OtherArch String
"armv7l") OS
Linux) = String
"\"armv7l-linux\""
fromCabalPlatform (Platform Arch
AArch64 OS
Linux)              = String
"\"aarch64-linux\""
fromCabalPlatform (Platform Arch
AArch64 OS
OSX)                = String
"\"aarch64-darwin\""
fromCabalPlatform Platform
p                                     = ShowS
forall a. HasCallStack => String -> a
error (String
"fromCabalPlatform: invalid Nix platform" String -> ShowS
forall a. [a] -> [a] -> [a]
++ Platform -> String
forall a. Show a => a -> String
show Platform
p)