module Cabal2Spec ( cabal2spec, createSpecFile, ForceBinary, RunTests, CopyrightYear ) where

import Control.Monad
import Data.Char
import Data.List ( delete, nub, sort, (\\), inits, intersect, isPrefixOf, groupBy )
import Data.Time.Clock
import Data.Time.Format
import Distribution.Compiler
import Distribution.License
import Distribution.Package
import Distribution.PackageDescription
import Distribution.PackageDescription.Configuration
import Distribution.Pretty
import Distribution.Simple.PackageDescription
import Distribution.System
import Distribution.Text
import Distribution.Types.ComponentRequestedSpec
import Distribution.Utils.Path ( getSymbolicPath )
import Distribution.Utils.ShortText ( fromShortText )
import Distribution.Verbosity
import Distribution.Version
import System.FilePath
import System.IO

type ForceBinary = Bool
type RunTests = Bool
type CopyrightYear = Int

cabal2spec :: Platform -> CompilerId -> FlagAssignment -> ForceBinary -> RunTests -> Maybe CopyrightYear
           -> FilePath -> FilePath -> IO ()
cabal2spec :: Platform
-> CompilerId
-> FlagAssignment
-> ForceBinary
-> ForceBinary
-> Maybe CopyrightYear
-> String
-> String
-> IO ()
cabal2spec Platform
platform CompilerId
compilerId FlagAssignment
flags ForceBinary
forceBinary ForceBinary
runTests Maybe CopyrightYear
copyrightYear String
cabalFile String
specFile = do
  GenericPackageDescription
gpd <- Verbosity -> String -> IO GenericPackageDescription
readGenericPackageDescription Verbosity
silent String
cabalFile
  case FlagAssignment
-> ComponentRequestedSpec
-> (Dependency -> ForceBinary)
-> Platform
-> CompilerInfo
-> [PackageVersionConstraint]
-> GenericPackageDescription
-> Either [Dependency] (PackageDescription, FlagAssignment)
finalizePD FlagAssignment
flags ComponentRequestedSpec
requestedComponents (forall a b. a -> b -> a
const ForceBinary
True) Platform
platform (CompilerId -> AbiTag -> CompilerInfo
unknownCompilerInfo CompilerId
compilerId AbiTag
NoAbiTag) [] GenericPackageDescription
gpd of
    Left [Dependency]
missing -> forall (m :: * -> *) a. MonadFail m => String -> m a
fail (String
"finalizePD: " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show [Dependency]
missing)
    Right (PackageDescription
pd,FlagAssignment
_) -> String
-> PackageDescription
-> ForceBinary
-> ForceBinary
-> FlagAssignment
-> Maybe CopyrightYear
-> IO ()
createSpecFile String
specFile PackageDescription
pd ForceBinary
forceBinary ForceBinary
runTests FlagAssignment
flags Maybe CopyrightYear
copyrightYear

requestedComponents :: ComponentRequestedSpec
requestedComponents :: ComponentRequestedSpec
requestedComponents = ComponentRequestedSpec
defaultComponentRequestedSpec

showPkgCfg :: String -> String
showPkgCfg :: String -> String
showPkgCfg String
p = String
"pkgconfig(" forall a. [a] -> [a] -> [a]
++ String
p forall a. [a] -> [a] -> [a]
++ String
")"

mkTools :: [String] -> [String]
mkTools :: [String] -> [String]
mkTools [String]
tools' = forall a. (a -> ForceBinary) -> [a] -> [a]
filter String -> ForceBinary
excludedTools forall a b. (a -> b) -> a -> b
$ forall a. Eq a => [a] -> [a]
nub forall a b. (a -> b) -> a -> b
$ forall a b. (a -> b) -> [a] -> [b]
map String -> String
mapTools [String]
tools'
  where
    excludedTools :: String -> ForceBinary
excludedTools String
n = String
n forall (t :: * -> *) a.
(Foldable t, Eq a) =>
a -> t a -> ForceBinary
`notElem` [String
"ghc", String
"hsc2hs", String
"perl"]
    mapTools :: String -> String
mapTools String
"gtk2hsC2hs" = String
"gtk2hs-buildtools"
    mapTools String
"gtk2hsHookGenerator" = String
"gtk2hs-buildtools"
    mapTools String
"gtk2hsTypeGen" = String
"gtk2hs-buildtools"
    mapTools String
tool = String
tool

createSpecFile :: FilePath -> PackageDescription -> ForceBinary -> RunTests -> FlagAssignment -> Maybe CopyrightYear -> IO ()
createSpecFile :: String
-> PackageDescription
-> ForceBinary
-> ForceBinary
-> FlagAssignment
-> Maybe CopyrightYear
-> IO ()
createSpecFile String
specFile PackageDescription
pkgDesc ForceBinary
forceBinary ForceBinary
runTests FlagAssignment
flagAssignment Maybe CopyrightYear
copyrightYear = do
  let deps :: [String]
      deps :: [String]
deps = forall a b. (a -> b) -> [a] -> [b]
map String -> String
showDevelDep [String]
deps' forall a. [a] -> [a] -> [a]
++ forall a b. (a -> b) -> [a] -> [b]
map String -> String
showProfDep [String]
deps'
      deps' :: [String]
      selfdep :: Bool
      ([String]
deps', ForceBinary
selfdep) = PackageDescription -> String -> ([String], ForceBinary)
buildDependencies PackageDescription
pkgDesc String
name
      pkgcfgs :: [String]
      pkgcfgs :: [String]
pkgcfgs = forall a b. (a -> b) -> [a] -> [b]
map String -> String
showPkgCfg (forall a. Eq a => [a] -> [a]
nub forall a b. (a -> b) -> a -> b
$ forall a b. (a -> b) -> [a] -> [b]
map forall a. IsDependency a => a -> String
depName forall a b. (a -> b) -> a -> b
$ forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap BuildInfo -> [PkgconfigDependency]
pkgconfigDepends [BuildInfo]
buildinfo)
      buildinfo :: [BuildInfo]
      buildinfo :: [BuildInfo]
buildinfo = PackageDescription -> ComponentRequestedSpec -> [BuildInfo]
enabledBuildInfos PackageDescription
pkgDesc ComponentRequestedSpec
requestedComponents
      tools :: [String]
      tools :: [String]
tools = [String] -> [String]
mkTools (forall a. Eq a => [a] -> [a]
nub forall a b. (a -> b) -> a -> b
$ forall a b. (a -> b) -> [a] -> [b]
map forall a. IsDependency a => a -> String
depName (forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap BuildInfo -> [LegacyExeDependency]
buildTools [BuildInfo]
buildinfo)) forall a. [a] -> [a] -> [a]
++ [String]
chrpath
      clibs :: [String]
      clibs :: [String]
clibs = forall a. Eq a => [a] -> [a]
nub (forall a b. (a -> b) -> [a] -> [b]
map String -> String
resolveLib (forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap BuildInfo -> [String]
extraLibs [BuildInfo]
buildinfo))
      chrpath :: [String]
      chrpath :: [String]
chrpath = [String
"chrpath" | ForceBinary
selfdep]

      pkg :: PackageIdentifier
pkg = PackageDescription -> PackageIdentifier
package PackageDescription
pkgDesc
      name :: String
name = PackageName -> String
unPackageName (forall pkg. Package pkg => pkg -> PackageName
packageName PackageIdentifier
pkg)
      hasExec :: ForceBinary
hasExec = PackageDescription -> ForceBinary
hasExes PackageDescription
pkgDesc
      hasLib :: ForceBinary
hasLib = PackageDescription -> ForceBinary
hasLibs PackageDescription
pkgDesc
  (String
pkgname, ForceBinary
binlib) <- Maybe String
-> PackageDescription -> ForceBinary -> IO (String, ForceBinary)
getPkgName (forall a. a -> Maybe a
Just String
specFile) PackageDescription
pkgDesc ForceBinary
forceBinary

  let pkg_name :: String
pkg_name = if String
pkgname forall a. Eq a => a -> a -> ForceBinary
== String
name then String
"%{name}" else String
"%{pkg_name}"
      basename :: String
basename | ForceBinary
binlib = String
"%{pkg_name}"
               | ForceBinary
hasExecPkg = String
name
               | ForceBinary
otherwise = String
"ghc-%{pkg_name}"

      hasExecPkg :: ForceBinary
hasExecPkg = ForceBinary
binlib ForceBinary -> ForceBinary -> ForceBinary
|| (ForceBinary
hasExec ForceBinary -> ForceBinary -> ForceBinary
&& ForceBinary -> ForceBinary
not ForceBinary
hasLib)
  -- run commands before opening file to prevent empty file on error
  -- maybe shell commands should be in a monad or something

      testsuiteDeps :: [String]
testsuiteDeps = PackageDescription -> String -> [String]
testsuiteDependencies PackageDescription
pkgDesc String
name

  Handle
h <- String -> IOMode -> IO Handle
openFile String
specFile IOMode
WriteMode
  let putHdr :: String -> String -> IO ()
putHdr String
hdr String
val = Handle -> String -> IO ()
hPutStrLn Handle
h (String
hdr forall a. [a] -> [a] -> [a]
++ String
":" forall a. [a] -> [a] -> [a]
++ forall {t :: * -> *} {a}. Foldable t => t a -> String
padding String
hdr forall a. [a] -> [a] -> [a]
++ String
val)
      padding :: t a -> String
padding t a
hdr = forall a. CopyrightYear -> a -> [a]
replicate (CopyrightYear
14 forall a. Num a => a -> a -> a
- forall (t :: * -> *) a. Foldable t => t a -> CopyrightYear
length t a
hdr) Char
' ' forall a. [a] -> [a] -> [a]
++ String
" "
      putNewline :: IO ()
putNewline = Handle -> String -> IO ()
hPutStrLn Handle
h String
""
      put :: String -> IO ()
put = Handle -> String -> IO ()
hPutStrLn Handle
h
      putDef :: String -> String -> IO ()
putDef String
v String
s = String -> IO ()
put forall a b. (a -> b) -> a -> b
$ [String] -> String
unlines [ String
"%global" String -> String -> String
+-+ String
v String -> String -> String
+-+ String
s
                                 , String
"%global pkgver %{pkg_name}-%{version}"
                                 ]
      ghcPkg :: String
ghcPkg = if ForceBinary
binlib then String
"-n ghc-%{name}" else String
""
      ghcPkgDevel :: String
ghcPkgDevel = if ForceBinary
binlib then String
"-n ghc-%{name}-devel" else String
"devel"

  do
    String
year <- case Maybe CopyrightYear
copyrightYear of
              Just CopyrightYear
y -> forall (m :: * -> *) a. Monad m => a -> m a
return (forall a. Show a => a -> String
show CopyrightYear
y)
              Maybe CopyrightYear
Nothing -> forall t. FormatTime t => TimeLocale -> String -> t -> String
formatTime TimeLocale
defaultTimeLocale String
"%Y" forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IO UTCTime
getCurrentTime
    String -> IO ()
put String
"#"
    String -> IO ()
put forall a b. (a -> b) -> a -> b
$ String
"# spec file for package " forall a. [a] -> [a] -> [a]
++ String
pkgname
    String -> IO ()
put String
"#"
    String -> IO ()
put forall a b. (a -> b) -> a -> b
$ String
"# Copyright (c) " forall a. [a] -> [a] -> [a]
++ String
year forall a. [a] -> [a] -> [a]
++ String
" SUSE LLC"
    String -> IO ()
put String
"#"
    String -> IO ()
put String
"# All modifications and additions to the file contributed by third parties"
    String -> IO ()
put String
"# remain the property of their copyright owners, unless otherwise agreed"
    String -> IO ()
put String
"# upon. The license for this file, and modifications and additions to the"
    String -> IO ()
put String
"# file, is the same license as for the pristine package itself (unless the"
    String -> IO ()
put String
"# license for the pristine package is not an Open Source License, in which"
    String -> IO ()
put String
"# case the license is the MIT License). An \"Open Source License\" is a"
    String -> IO ()
put String
"# license that conforms to the Open Source Definition (Version 1.9)"
    String -> IO ()
put String
"# published by the Open Source Initiative."
    IO ()
putNewline
    String -> IO ()
put String
"# Please submit bugfixes or comments via https://bugs.opensuse.org/"
    String -> IO ()
put String
"#"
  IO ()
putNewline
  IO ()
putNewline

  -- Some packages conflate the synopsis and description fields.  Ugh.
  let syn :: String
syn = ShortText -> String
fromShortText (PackageDescription -> ShortText
synopsis PackageDescription
pkgDesc)
  let initialCapital :: String -> String
initialCapital (Char
c:String
cs) = Char -> Char
toUpper Char
cforall a. a -> [a] -> [a]
:String
cs
      initialCapital [] = []
  let syn' :: String
syn' = if String -> ForceBinary
badDescription String
syn then String
"FIXME" else ([String] -> String
unwords forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> [String]
lines forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> String
initialCapital) String
syn
  let summary :: String
summary = (Char -> ForceBinary) -> String -> String
rstrip (forall a. Eq a => a -> a -> ForceBinary
== Char
'.') forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Char -> ForceBinary) -> String -> String
rstrip Char -> ForceBinary
isSpace forall a b. (a -> b) -> a -> b
$ String
syn'
  let descr :: String
descr = (Char -> ForceBinary) -> String -> String
rstrip Char -> ForceBinary
isSpace (ShortText -> String
fromShortText (PackageDescription -> ShortText
description PackageDescription
pkgDesc))
  let descLines :: [String]
descLines = (String -> [String]
formatParagraphs forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> String
initialCapital forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> String
filterSymbols forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> String
finalPeriod) forall a b. (a -> b) -> a -> b
$ if String -> ForceBinary
badDescription String
descr then String
syn' else String
descr
      finalPeriod :: String -> String
finalPeriod String
cs = if forall a. [a] -> a
last String
cs forall a. Eq a => a -> a -> ForceBinary
== Char
'.' then String
cs else String
cs forall a. [a] -> [a] -> [a]
++ String
"."
      filterSymbols :: String -> String
filterSymbols (Char
c:String
cs) =
        if Char
c forall (t :: * -> *) a.
(Foldable t, Eq a) =>
a -> t a -> ForceBinary
`notElem` String
"@\\" then Char
cforall a. a -> [a] -> [a]
: String -> String
filterSymbols String
cs
        else case Char
c of
          Char
'@' -> Char
'\''forall a. a -> [a] -> [a]
: String -> String
filterSymbols String
cs
          Char
'\\' -> forall a. [a] -> a
head String
csforall a. a -> [a] -> [a]
: String -> String
filterSymbols (forall a. [a] -> [a]
tail String
cs)
          Char
_ -> Char
cforall a. a -> [a] -> [a]
: String -> String
filterSymbols String
cs
      filterSymbols [] = []
  forall (f :: * -> *). Applicative f => ForceBinary -> f () -> f ()
when ForceBinary
hasLib forall a b. (a -> b) -> a -> b
$
    String -> String -> IO ()
putDef String
"pkg_name" String
name

  forall (f :: * -> *). Applicative f => ForceBinary -> f () -> f ()
unless (forall (t :: * -> *) a. Foldable t => t a -> ForceBinary
null [String]
testsuiteDeps) forall a b. (a -> b) -> a -> b
$
    if ForceBinary
runTests
       then String -> IO ()
put String
"%bcond_without tests"
       else String -> IO ()
put String
"%bcond_with tests"

  let version :: Version
version = forall pkg. Package pkg => pkg -> Version
packageVersion PackageIdentifier
pkg
      revision :: String
revision = forall a. Show a => a -> String
show forall a b. (a -> b) -> a -> b
$ forall b a. b -> (a -> b) -> Maybe a -> b
maybe (CopyrightYear
0::Int) forall a. Read a => String -> a
read (forall a b. Eq a => a -> [(a, b)] -> Maybe b
lookup String
"x-revision" (PackageDescription -> [(String, String)]
customFieldsPD PackageDescription
pkgDesc))
  String -> String -> IO ()
putHdr String
"Name" (if ForceBinary
binlib then String
"%{pkg_name}" else String
basename)
  String -> String -> IO ()
putHdr String
"Version" (forall a. Pretty a => a -> String
display Version
version)
  String -> String -> IO ()
putHdr String
"Release" String
"0"
  String -> String -> IO ()
putHdr String
"Summary" String
summary
  String -> String -> IO ()
putHdr String
"License" forall a b. (a -> b) -> a -> b
$ forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either (forall a. Show a => a -> String
show forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Pretty a => a -> Doc
pretty) License -> String
showLicense (PackageDescription -> Either License License
licenseRaw PackageDescription
pkgDesc)
  String -> String -> IO ()
putHdr String
"URL" forall a b. (a -> b) -> a -> b
$ String
"https://hackage.haskell.org/package/" forall a. [a] -> [a] -> [a]
++ String
pkg_name
  String -> String -> IO ()
putHdr String
"Source0" forall a b. (a -> b) -> a -> b
$ String
"https://hackage.haskell.org/package/" forall a. [a] -> [a] -> [a]
++ String
pkg_name forall a. [a] -> [a] -> [a]
++ String
"-%{version}/" forall a. [a] -> [a] -> [a]
++ String
pkg_name forall a. [a] -> [a] -> [a]
++ String
"-%{version}.tar.gz"
  forall (f :: * -> *). Applicative f => ForceBinary -> f () -> f ()
when (String
revision forall a. Eq a => a -> a -> ForceBinary
/= String
"0") forall a b. (a -> b) -> a -> b
$
    String -> String -> IO ()
putHdr String
"Source1" forall a b. (a -> b) -> a -> b
$ String
"https://hackage.haskell.org/package/" forall a. [a] -> [a] -> [a]
++ String
pkg_name forall a. [a] -> [a] -> [a]
++ String
"-%{version}/revision/" forall a. [a] -> [a] -> [a]
++ String
revision forall a. [a] -> [a] -> [a]
++ String
".cabal#/" forall a. [a] -> [a] -> [a]
++ String
pkg_name forall a. [a] -> [a] -> [a]
++ String
".cabal"
  String -> String -> IO ()
putHdr String
"ExcludeArch" String
"%{ix86}"

  let fixedDeps :: [String]
fixedDeps = [String
"ghc-Cabal-devel", String
"ghc-rpm-macros"]
  let alldeps :: [String]
alldeps = forall a. Ord a => [a] -> [a]
sort forall a b. (a -> b) -> a -> b
$ forall a. Eq a => [a] -> [a]
nub forall a b. (a -> b) -> a -> b
$ [String]
fixedDeps forall a. [a] -> [a] -> [a]
++ [String]
deps forall a. [a] -> [a] -> [a]
++ [String]
tools forall a. [a] -> [a] -> [a]
++ [String]
clibs forall a. [a] -> [a] -> [a]
++ [String]
pkgcfgs forall a. [a] -> [a] -> [a]
++ [String
"pkgconfig" | ForceBinary -> ForceBinary
not (forall (t :: * -> *) a. Foldable t => t a -> ForceBinary
null [String]
pkgcfgs)]
  let extraTestDeps :: [String]
extraTestDeps = forall a. Ord a => [a] -> [a]
sort forall a b. (a -> b) -> a -> b
$ [String]
testsuiteDeps forall a. Eq a => [a] -> [a] -> [a]
\\ [String]
deps
  forall (f :: * -> *). Applicative f => ForceBinary -> f () -> f ()
unless (forall (t :: * -> *) a. Foldable t => t a -> ForceBinary
null forall a b. (a -> b) -> a -> b
$ [String]
alldeps forall a. [a] -> [a] -> [a]
++ [String]
extraTestDeps) forall a b. (a -> b) -> a -> b
$ do
    forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ (String -> String -> IO ()
putHdr String
"BuildRequires") [String]
alldeps
    forall (f :: * -> *). Applicative f => ForceBinary -> f () -> f ()
unless (forall (t :: * -> *) a. Foldable t => t a -> ForceBinary
null [String]
extraTestDeps) forall a b. (a -> b) -> a -> b
$ do
      String -> IO ()
put String
"%if %{with tests}"
      forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ (String -> String -> IO ()
putHdr String
"BuildRequires") [String]
extraTestDeps
      String -> IO ()
put String
"%endif"

  IO ()
putNewline

  String -> IO ()
put String
"%description"
  forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ String -> IO ()
put [String]
descLines

  let wrapGenDesc :: String -> String
wrapGenDesc = CopyrightYear -> String -> String
wordwrap (CopyrightYear
79 forall a. Num a => a -> a -> a
- forall a. Ord a => a -> a -> a
max CopyrightYear
0 (forall (t :: * -> *) a. Foldable t => t a -> CopyrightYear
length String
pkgname forall a. Num a => a -> a -> a
- forall (t :: * -> *) a. Foldable t => t a -> CopyrightYear
length String
pkg_name))

  forall (f :: * -> *). Applicative f => ForceBinary -> f () -> f ()
when ForceBinary
hasLib forall a b. (a -> b) -> a -> b
$ do
    forall (f :: * -> *). Applicative f => ForceBinary -> f () -> f ()
when ForceBinary
binlib forall a b. (a -> b) -> a -> b
$ do
      String -> IO ()
put forall a b. (a -> b) -> a -> b
$ String
"%package" String -> String -> String
+-+ String
ghcPkg
      String -> String -> IO ()
putHdr String
"Summary" forall a b. (a -> b) -> a -> b
$ String
"Haskell" String -> String -> String
+-+ String
pkg_name String -> String -> String
+-+ String
"library"
      IO ()
putNewline
      String -> IO ()
put forall a b. (a -> b) -> a -> b
$ String
"%description" String -> String -> String
+-+ String
ghcPkg
      String -> IO ()
put forall a b. (a -> b) -> a -> b
$ String -> String
wrapGenDesc forall a b. (a -> b) -> a -> b
$ String
"This package provides the Haskell" String -> String -> String
+-+ String
pkg_name String -> String -> String
+-+ String
"shared library."
    String -> IO ()
put forall a b. (a -> b) -> a -> b
$ String
"%package" String -> String -> String
+-+ String
ghcPkgDevel
    String -> String -> IO ()
putHdr String
"Summary" forall a b. (a -> b) -> a -> b
$ String
"Haskell" String -> String -> String
+-+ String
pkg_name String -> String -> String
+-+ String
"library development files"
    String -> String -> IO ()
putHdr String
"Requires" forall a b. (a -> b) -> a -> b
$ (if ForceBinary
binlib then String
"ghc-%{name}" else String
"%{name}") String -> String -> String
+-+ String
"= %{version}-%{release}"
    String -> String -> IO ()
putHdr String
"Requires" String
"ghc-compiler = %{ghc_version}"
    forall (f :: * -> *). Applicative f => ForceBinary -> f () -> f ()
unless (forall (t :: * -> *) a. Foldable t => t a -> ForceBinary
null forall a b. (a -> b) -> a -> b
$ [String]
clibs forall a. [a] -> [a] -> [a]
++ [String]
pkgcfgs) forall a b. (a -> b) -> a -> b
$
      forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ (String -> String -> IO ()
putHdr String
"Requires") forall a b. (a -> b) -> a -> b
$ forall a. Ord a => [a] -> [a]
sort ([String]
clibs forall a. [a] -> [a] -> [a]
++ [String]
pkgcfgs forall a. [a] -> [a] -> [a]
++ [String
"pkgconfig" | ForceBinary -> ForceBinary
not (forall (t :: * -> *) a. Foldable t => t a -> ForceBinary
null [String]
pkgcfgs)])
    String -> String -> IO ()
putHdr String
"Requires(post)" String
"ghc-compiler = %{ghc_version}"
    String -> String -> IO ()
putHdr String
"Requires(postun)" String
"ghc-compiler = %{ghc_version}"
    IO ()
putNewline
    String -> IO ()
put forall a b. (a -> b) -> a -> b
$ String
"%description" String -> String -> String
+-+ String
ghcPkgDevel
    String -> IO ()
put forall a b. (a -> b) -> a -> b
$ String -> String
wrapGenDesc forall a b. (a -> b) -> a -> b
$ String
"This package provides the Haskell" String -> String -> String
+-+ String
pkg_name String -> String -> String
+-+ String
"library development files."
    String -> IO ()
put forall a b. (a -> b) -> a -> b
$ [String] -> String
unlines
        [ String
"%package -n ghc-%{pkg_name}-doc"
        , String
"Summary:        Haskell %{pkg_name} library documentation"
        , String
"BuildArch:      noarch"
        , String
"Requires:       ghc-filesystem"
        , String
""
        , String
"%description -n ghc-%{pkg_name}-doc"
        , String
"This package provides the Haskell %{pkg_name} library documentation."
        , String
""
        , String
""
        , String
"%package -n ghc-%{pkg_name}-prof"
        , String
"Summary:        Haskell %{pkg_name} profiling library"
        , String
"Requires:       ghc-%{pkg_name}-devel = %{version}-%{release}"
        , String
"Supplements:    (ghc-%{pkg_name}-devel and ghc-prof)"
        , String
""
        , String
"%description -n ghc-%{pkg_name}-prof"
        , String
"This package provides the Haskell %{pkg_name} profiling library."
        , String
""
        ]

  String -> IO ()
put String
"%prep"
  String -> IO ()
put forall a b. (a -> b) -> a -> b
$ String
"%autosetup" forall a. [a] -> [a] -> [a]
++ (if String
pkgname forall a. Eq a => a -> a -> ForceBinary
/= String
name then String
" -n %{pkg_name}-%{version}" else String
"")
  forall (f :: * -> *). Applicative f => ForceBinary -> f () -> f ()
when (String
revision forall a. Eq a => a -> a -> ForceBinary
/= String
"0") forall a b. (a -> b) -> a -> b
$
    String -> IO ()
put forall a b. (a -> b) -> a -> b
$ String
"cp -p %{SOURCE1}" String -> String -> String
+-+ String
pkg_name forall a. [a] -> [a] -> [a]
++ String
".cabal"
  IO ()
putNewline

  String -> IO ()
put String
"%build"
  forall (f :: * -> *). Applicative f => ForceBinary -> f () -> f ()
when (FlagAssignment
flagAssignment forall a. Eq a => a -> a -> ForceBinary
/= forall a. Monoid a => a
mempty) forall a b. (a -> b) -> a -> b
$ do
    let cabalFlags :: [String]
cabalFlags = [ String
"-f" forall a. [a] -> [a] -> [a]
++ (if ForceBinary
b then String
"" else String
"-") forall a. [a] -> [a] -> [a]
++ FlagName -> String
unFlagName FlagName
n | (FlagName
n, ForceBinary
b) <- FlagAssignment -> [(FlagName, ForceBinary)]
unFlagAssignment FlagAssignment
flagAssignment ]
    String -> IO ()
put forall a b. (a -> b) -> a -> b
$ String
"%define cabal_configure_options " forall a. [a] -> [a] -> [a]
++ [String] -> String
unwords (forall a. Ord a => [a] -> [a]
sort [String]
cabalFlags)
  let pkgType :: String
pkgType = if ForceBinary
hasLib then String
"lib" else String
"bin"
  String -> IO ()
put forall a b. (a -> b) -> a -> b
$ String
"%ghc_" forall a. [a] -> [a] -> [a]
++ String
pkgType forall a. [a] -> [a] -> [a]
++ String
"_build"
  IO ()
putNewline

  String -> IO ()
put String
"%install"
  String -> IO ()
put forall a b. (a -> b) -> a -> b
$ String
"%ghc_" forall a. [a] -> [a] -> [a]
++ String
pkgType forall a. [a] -> [a] -> [a]
++ String
"_install"

  forall (f :: * -> *). Applicative f => ForceBinary -> f () -> f ()
when ForceBinary
selfdep forall a b. (a -> b) -> a -> b
$
    String -> IO ()
put forall a b. (a -> b) -> a -> b
$ String
"%ghc_fix_rpath" String -> String -> String
+-+ String
"%{pkg_name}-%{version}"

  -- TODO: getSymbolicPath should not be used like this
  let licensefiles :: [String]
licensefiles = forall a b. (a -> b) -> [a] -> [b]
map forall from to. SymbolicPath from to -> String
getSymbolicPath (PackageDescription -> [SymbolicPath PackageDir LicenseFile]
licenseFiles PackageDescription
pkgDesc)

  -- remove docs from datafiles (#38)
  [String]
docsUnfiltered <- forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall a. Ord a => [a] -> [a]
sort ([String] -> [String] -> IO [String]
findDocs (PackageDescription -> [String]
extraSrcFiles PackageDescription
pkgDesc forall a. [a] -> [a] -> [a]
++ PackageDescription -> [String]
extraDocFiles PackageDescription
pkgDesc) [String]
licensefiles)
  let datafiles :: [String]
datafiles = PackageDescription -> [String]
dataFiles PackageDescription
pkgDesc
      dupdocs :: [String]
dupdocs   = [String]
docsUnfiltered forall a. Eq a => [a] -> [a] -> [a]
`intersect` [String]
datafiles
      docs :: [String]
docs      = [String]
docsUnfiltered forall a. Eq a => [a] -> [a] -> [a]
\\ [String]
datafiles
  forall (f :: * -> *). Applicative f => ForceBinary -> f () -> f ()
unless (forall (t :: * -> *) a. Foldable t => t a -> ForceBinary
null [String]
dupdocs) forall a b. (a -> b) -> a -> b
$
    -- TODO: What does this warning accomplish?
    String -> IO ()
putStrLn forall a b. (a -> b) -> a -> b
$ String
"*** " forall a. [a] -> [a] -> [a]
++ String
pkgname forall a. [a] -> [a] -> [a]
++ String
": doc files found in datadir:" String -> String -> String
+-+ [String] -> String
unwords (forall a. Ord a => [a] -> [a]
sort [String]
dupdocs)
  IO ()
putNewline

  forall (f :: * -> *). Applicative f => ForceBinary -> f () -> f ()
unless (forall (t :: * -> *) a. Foldable t => t a -> ForceBinary
null [String]
testsuiteDeps) forall a b. (a -> b) -> a -> b
$ do
    String -> IO ()
put String
"%check"
    String -> IO ()
put String
"%cabal_test"
    IO ()
putNewline

  forall (f :: * -> *). Applicative f => ForceBinary -> f () -> f ()
when ForceBinary
hasLib forall a b. (a -> b) -> a -> b
$ do
    let putInstallScript :: IO ()
putInstallScript = do
          String -> IO ()
put String
"%ghc_pkg_recache"
          IO ()
putNewline
    String -> IO ()
put forall a b. (a -> b) -> a -> b
$ String
"%post" String -> String -> String
+-+ String
ghcPkgDevel
    IO ()
putInstallScript
    String -> IO ()
put forall a b. (a -> b) -> a -> b
$ String
"%postun" String -> String -> String
+-+ String
ghcPkgDevel
    IO ()
putInstallScript

  let license_macro :: String
license_macro = String
"%license"
  let execs :: [String]
      execs :: [String]
execs = forall a. Ord a => [a] -> [a]
sort forall a b. (a -> b) -> a -> b
$ forall a b. (a -> b) -> [a] -> [b]
map (UnqualComponentName -> String
unUnqualComponentName forall b c a. (b -> c) -> (a -> b) -> a -> c
. Executable -> UnqualComponentName
exeName) forall a b. (a -> b) -> a -> b
$ forall a. (a -> ForceBinary) -> [a] -> [a]
filter Executable -> ForceBinary
isBuildable forall a b. (a -> b) -> a -> b
$ PackageDescription -> [Executable]
executables PackageDescription
pkgDesc

  let listDataFiles :: IO ()
listDataFiles = forall (f :: * -> *). Applicative f => ForceBinary -> f () -> f ()
unless (forall (t :: * -> *) a. Foldable t => t a -> ForceBinary
null (PackageDescription -> [String]
dataFiles PackageDescription
pkgDesc)) forall a b. (a -> b) -> a -> b
$ do
                        String -> IO ()
put (String
"%dir %{_datadir}/" forall a. [a] -> [a] -> [a]
++ String
pkg_name forall a. [a] -> [a] -> [a]
++ String
"-%{version}")
                        forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ (String -> IO ()
put forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((String
"%dir %{_datadir}/" forall a. [a] -> [a] -> [a]
++ String
pkg_name forall a. [a] -> [a] -> [a]
++ String
"-%{version}/")forall a. [a] -> [a] -> [a]
++) forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> String
avoidSquareBrackets) (forall a. Ord a => [a] -> [a]
sort ([String] -> [String]
listDirs (PackageDescription -> [String]
dataFiles PackageDescription
pkgDesc)))
                        forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ (String -> IO ()
put forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((String
"%{_datadir}/" forall a. [a] -> [a] -> [a]
++ String
pkg_name forall a. [a] -> [a] -> [a]
++ String
"-%{version}/")forall a. [a] -> [a] -> [a]
++) forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> String
avoidSquareBrackets) (forall a. Ord a => [a] -> [a]
sort (PackageDescription -> [String]
dataFiles PackageDescription
pkgDesc))

      listDirs :: [FilePath] -> [FilePath]
      listDirs :: [String] -> [String]
listDirs = forall a. Eq a => [a] -> [a]
nub forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (forall a b. (a -> b) -> [a] -> [b]
map [String] -> String
joinPath forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. [a] -> [a]
tail forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. [a] -> [[a]]
inits) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Eq a => [a] -> [a]
nub forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a -> b) -> [a] -> [b]
map forall a. [a] -> [a]
init forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. (a -> ForceBinary) -> [a] -> [a]
filter (\[String]
p -> forall (t :: * -> *) a. Foldable t => t a -> CopyrightYear
length [String]
p forall a. Ord a => a -> a -> ForceBinary
> CopyrightYear
1) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a -> b) -> [a] -> [b]
map String -> [String]
splitDirectories

  forall (f :: * -> *). Applicative f => ForceBinary -> f () -> f ()
when ForceBinary
hasExecPkg forall a b. (a -> b) -> a -> b
$ do
    String -> IO ()
put String
"%files"
    -- Add the license file to the main package only if it wouldn't
    -- otherwise be empty.
    forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ (\ String
l -> String -> IO ()
put forall a b. (a -> b) -> a -> b
$ String
license_macro String -> String -> String
+-+ String
l) (forall a. Ord a => [a] -> [a]
sort [String]
licensefiles)
    forall (f :: * -> *). Applicative f => ForceBinary -> f () -> f ()
unless (forall (t :: * -> *) a. Foldable t => t a -> ForceBinary
null [String]
docs) forall a b. (a -> b) -> a -> b
$
      String -> IO ()
put forall a b. (a -> b) -> a -> b
$ String
"%doc" String -> String -> String
+-+ [String] -> String
unwords (forall a. Ord a => [a] -> [a]
sort [String]
docs)
    forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ (\ String
p -> String -> IO ()
put forall a b. (a -> b) -> a -> b
$ String
"%{_bindir}/" forall a. [a] -> [a] -> [a]
++ (if String
p forall a. Eq a => a -> a -> ForceBinary
== String
name then String
"%{name}" else String
p)) (forall a. Ord a => [a] -> [a]
sort [String]
execs)
    IO ()
listDataFiles
    IO ()
putNewline

  forall (f :: * -> *). Applicative f => ForceBinary -> f () -> f ()
when ForceBinary
hasLib forall a b. (a -> b) -> a -> b
$ do
    let baseFiles :: String
baseFiles = if ForceBinary
binlib then String
"-f ghc-%{name}.files" else String
"-f %{name}.files"
        develFiles :: String
develFiles = if ForceBinary
binlib then String
"-f ghc-%{name}-devel.files" else String
"-f %{name}-devel.files"
    String -> IO ()
put forall a b. (a -> b) -> a -> b
$ String
"%files" String -> String -> String
+-+ String
ghcPkg String -> String -> String
+-+ String
baseFiles
    forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ (\ String
l -> String -> IO ()
put forall a b. (a -> b) -> a -> b
$ String
license_macro String -> String -> String
+-+ String
l) [String]
licensefiles
    forall (f :: * -> *). Applicative f => ForceBinary -> f () -> f ()
unless ForceBinary
binlib forall a b. (a -> b) -> a -> b
$
      forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ (\ String
p -> String -> IO ()
put forall a b. (a -> b) -> a -> b
$ String
"%{_bindir}/" forall a. [a] -> [a] -> [a]
++ (if String
p forall a. Eq a => a -> a -> ForceBinary
== String
name then String
"%{pkg_name}" else String
p)) (forall a. Ord a => [a] -> [a]
sort [String]
execs)
    forall (f :: * -> *). Applicative f => ForceBinary -> f () -> f ()
unless ForceBinary
hasExecPkg IO ()
listDataFiles
    IO ()
putNewline
    String -> IO ()
put forall a b. (a -> b) -> a -> b
$ String
"%files" String -> String -> String
+-+ String
ghcPkgDevel String -> String -> String
+-+ String
develFiles
    forall (f :: * -> *). Applicative f => ForceBinary -> f () -> f ()
unless (forall (t :: * -> *) a. Foldable t => t a -> ForceBinary
null [String]
docs) forall a b. (a -> b) -> a -> b
$
      String -> IO ()
put forall a b. (a -> b) -> a -> b
$ String
"%doc" String -> String -> String
+-+ [String] -> String
unwords (forall a. Ord a => [a] -> [a]
sort [String]
docs)
    IO ()
putNewline
    String -> IO ()
put String
"%files -n ghc-%{pkg_name}-doc -f ghc-%{pkg_name}-doc.files"
    forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ (\ String
l -> String -> IO ()
put forall a b. (a -> b) -> a -> b
$ String
license_macro String -> String -> String
+-+ String
l) [String]
licensefiles
    IO ()
putNewline
    String -> IO ()
put String
"%files -n ghc-%{pkg_name}-prof -f ghc-%{pkg_name}-prof.files"
    IO ()
putNewline

  String -> IO ()
put String
"%changelog"
  Handle -> IO ()
hClose Handle
h


isBuildable :: Executable -> Bool
isBuildable :: Executable -> ForceBinary
isBuildable Executable
exe = BuildInfo -> ForceBinary
buildable forall a b. (a -> b) -> a -> b
$ Executable -> BuildInfo
buildInfo Executable
exe

findDocs :: [FilePath] -> [FilePath] -> IO [FilePath]
findDocs :: [String] -> [String] -> IO [String]
findDocs [String]
contents [String]
licensefiles = do
  let docs :: [String]
docs = forall a. (a -> ForceBinary) -> [a] -> [a]
filter String -> ForceBinary
likely (forall a. Ord a => [a] -> [a]
sort (forall a. Eq a => [a] -> [a]
nub (forall a b. (a -> b) -> [a] -> [b]
map (forall a. [a] -> a
head forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> [String]
splitDirectories) [String]
contents)))
  forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ if forall (t :: * -> *) a. Foldable t => t a -> ForceBinary
null [String]
licensefiles
           then [String]
docs
           else forall a. (a -> ForceBinary) -> [a] -> [a]
filter (forall (t :: * -> *) a.
(Foldable t, Eq a) =>
a -> t a -> ForceBinary
`notElem` [String]
licensefiles) [String]
docs
  where names :: [String]
names = [String
"author", String
"changelog", String
"changes", String
"contributors", String
"copying", String
"doc",
                 String
"example", String
"licence", String
"license", String
"news", String
"readme", String
"todo"]
        likely :: String -> ForceBinary
likely String
name = let lowerName :: String
lowerName = forall a b. (a -> b) -> [a] -> [b]
map Char -> Char
toLower String
name
                      in forall (t :: * -> *) a.
Foldable t =>
(a -> ForceBinary) -> t a -> ForceBinary
any (forall a. Eq a => [a] -> [a] -> ForceBinary
`isPrefixOf` String
lowerName) [String]
names

normalizeVersion :: Version -> Version
normalizeVersion :: Version -> Version
normalizeVersion Version
v = case Version -> [CopyrightYear]
versionNumbers Version
v of
                       [CopyrightYear
i] -> [CopyrightYear] -> Version
mkVersion [CopyrightYear
i,CopyrightYear
0]
                       [CopyrightYear]
_   -> Version
v

showLicense :: License -> String
showLicense :: License -> String
showLicense (GPL Maybe Version
Nothing) = String
"GPL-1.0-or-later"
showLicense (GPL (Just Version
ver)) = String
"GPL-" forall a. [a] -> [a] -> [a]
++ forall a. Pretty a => a -> String
display (Version -> Version
normalizeVersion Version
ver) forall a. [a] -> [a] -> [a]
++ String
"-or-later"
showLicense (LGPL Maybe Version
Nothing) = String
"LGPL-2.0-or-later"
showLicense (LGPL (Just Version
ver)) = String
"LGPL-" forall a. [a] -> [a] -> [a]
++ forall a. Pretty a => a -> String
display (Version -> Version
normalizeVersion Version
ver) forall a. [a] -> [a] -> [a]
++ String
"-or-later"
showLicense License
BSD3 = String
"BSD-3-Clause"
showLicense License
BSD4 = String
"BSD-4-Clause"
showLicense License
MIT = String
"MIT"
showLicense License
PublicDomain = String
"SUSE-Public-Domain"
showLicense License
AllRightsReserved = String
"SUSE-NonFree"
showLicense License
OtherLicense = String
"Unknown"
showLicense (UnknownLicense String
l) = String
"Unknown" String -> String -> String
+-+ String
l
showLicense (Apache Maybe Version
Nothing) = String
"Apache-2.0"
showLicense (Apache (Just Version
ver)) = String
"Apache-" forall a. [a] -> [a] -> [a]
++ forall a. Pretty a => a -> String
display (Version -> Version
normalizeVersion Version
ver)
showLicense (AGPL Maybe Version
Nothing) = String
"AGPL-1.0-or-later"
showLicense (AGPL (Just Version
ver)) = String
"AGPL-" forall a. [a] -> [a] -> [a]
++ forall a. Pretty a => a -> String
display (Version -> Version
normalizeVersion Version
ver) forall a. [a] -> [a] -> [a]
++ String
"-or-later"
showLicense License
BSD2 = String
"BSD-2-Clause"
showLicense (MPL Version
ver) = String
"MPL-" forall a. [a] -> [a] -> [a]
++ forall a. Pretty a => a -> String
display (Version -> Version
normalizeVersion Version
ver)
showLicense License
ISC = String
"ISC"
showLicense License
UnspecifiedLicense = String
"Unspecified license!"

-- http://rosettacode.org/wiki/Word_wrap#Haskell
wordwrap :: Int -> String -> String
wordwrap :: CopyrightYear -> String -> String
wordwrap CopyrightYear
maxlen = CopyrightYear -> ForceBinary -> [String] -> String
wrap_ CopyrightYear
0 ForceBinary
False forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> [String]
words
  where
    wrap_ :: CopyrightYear -> ForceBinary -> [String] -> String
wrap_ CopyrightYear
_ ForceBinary
_ [] = String
"\n"
    wrap_ CopyrightYear
pos ForceBinary
eos (String
w:[String]
ws)
      -- at line start: put down the word no matter what
      | CopyrightYear
pos forall a. Eq a => a -> a -> ForceBinary
== CopyrightYear
0 = String
w forall a. [a] -> [a] -> [a]
++ CopyrightYear -> ForceBinary -> [String] -> String
wrap_ (CopyrightYear
pos forall a. Num a => a -> a -> a
+ CopyrightYear
lw) ForceBinary
endp [String]
ws
      | CopyrightYear
pos forall a. Num a => a -> a -> a
+ CopyrightYear
lw forall a. Num a => a -> a -> a
+ CopyrightYear
1 forall a. Ord a => a -> a -> ForceBinary
> CopyrightYear
maxlen forall a. Num a => a -> a -> a
- CopyrightYear
9 ForceBinary -> ForceBinary -> ForceBinary
&& ForceBinary
eos = Char
'\n'forall a. a -> [a] -> [a]
:CopyrightYear -> ForceBinary -> [String] -> String
wrap_ CopyrightYear
0 ForceBinary
endp (String
wforall a. a -> [a] -> [a]
:[String]
ws)
      | CopyrightYear
pos forall a. Num a => a -> a -> a
+ CopyrightYear
lw forall a. Num a => a -> a -> a
+ CopyrightYear
1 forall a. Ord a => a -> a -> ForceBinary
> CopyrightYear
maxlen = Char
'\n'forall a. a -> [a] -> [a]
:CopyrightYear -> ForceBinary -> [String] -> String
wrap_ CopyrightYear
0 ForceBinary
endp (String
wforall a. a -> [a] -> [a]
:[String]
ws)
      | ForceBinary
otherwise = String
" " forall a. [a] -> [a] -> [a]
++ String
w forall a. [a] -> [a] -> [a]
++ CopyrightYear -> ForceBinary -> [String] -> String
wrap_ (CopyrightYear
pos forall a. Num a => a -> a -> a
+ CopyrightYear
lw forall a. Num a => a -> a -> a
+ CopyrightYear
1) ForceBinary
endp [String]
ws
      where
        lw :: CopyrightYear
lw = forall (t :: * -> *) a. Foldable t => t a -> CopyrightYear
length String
w
        endp :: ForceBinary
endp = forall a. [a] -> a
last String
w forall a. Eq a => a -> a -> ForceBinary
== Char
'.'

formatParagraphs :: String -> [String]
formatParagraphs :: String -> [String]
formatParagraphs = forall a b. (a -> b) -> [a] -> [b]
map (CopyrightYear -> String -> String
wordwrap CopyrightYear
79) forall b c a. (b -> c) -> (a -> b) -> a -> c
. [String] -> [String]
paragraphs forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> [String]
lines
  where
    -- from http://stackoverflow.com/questions/930675/functional-paragraphs
    -- using split would be: map unlines . (Data.List.Split.splitWhen null)
    paragraphs :: [String] -> [String]
    paragraphs :: [String] -> [String]
paragraphs = forall a b. (a -> b) -> [a] -> [b]
map ([String] -> String
unlines forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. (a -> ForceBinary) -> [a] -> [a]
filter (ForceBinary -> ForceBinary
not forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (t :: * -> *) a. Foldable t => t a -> ForceBinary
null)) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. (a -> a -> ForceBinary) -> [a] -> [[a]]
groupBy (forall a b. a -> b -> a
const forall a b. (a -> b) -> a -> b
$ ForceBinary -> ForceBinary
not forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (t :: * -> *) a. Foldable t => t a -> ForceBinary
null)

rstrip :: (Char -> Bool) -> String -> String
rstrip :: (Char -> ForceBinary) -> String -> String
rstrip Char -> ForceBinary
p = forall a. [a] -> [a]
reverse forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. (a -> ForceBinary) -> [a] -> [a]
dropWhile Char -> ForceBinary
p forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. [a] -> [a]
reverse

getPkgName :: Maybe FilePath -> PackageDescription -> Bool -> IO (String, Bool)
getPkgName :: Maybe String
-> PackageDescription -> ForceBinary -> IO (String, ForceBinary)
getPkgName (Just String
spec) PackageDescription
pkgDesc ForceBinary
binary = do
  let name :: String
name = PackageName -> String
unPackageName (forall pkg. Package pkg => pkg -> PackageName
packageName (PackageDescription -> PackageIdentifier
package PackageDescription
pkgDesc))
      pkgname :: String
pkgname = String -> String
takeBaseName String
spec
      hasLib :: ForceBinary
hasLib = PackageDescription -> ForceBinary
hasLibs PackageDescription
pkgDesc
  forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ if String
name forall a. Eq a => a -> a -> ForceBinary
== String
pkgname ForceBinary -> ForceBinary -> ForceBinary
|| ForceBinary
binary then (String
name, ForceBinary
hasLib) else (String
pkgname, ForceBinary
False)
getPkgName Maybe String
Nothing PackageDescription
pkgDesc ForceBinary
binary = do
  let name :: String
name = PackageName -> String
unPackageName (forall pkg. Package pkg => pkg -> PackageName
packageName (PackageDescription -> PackageIdentifier
package PackageDescription
pkgDesc))
      hasExec :: ForceBinary
hasExec = PackageDescription -> ForceBinary
hasExes PackageDescription
pkgDesc
      hasLib :: ForceBinary
hasLib = PackageDescription -> ForceBinary
hasLibs PackageDescription
pkgDesc
  forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ if ForceBinary
binary ForceBinary -> ForceBinary -> ForceBinary
|| ForceBinary
hasExec ForceBinary -> ForceBinary -> ForceBinary
&& ForceBinary -> ForceBinary
not ForceBinary
hasLib then (String
name, ForceBinary
hasLib) else (String
"ghc-" forall a. [a] -> [a] -> [a]
++ String
name, ForceBinary
False)

infixr 4 +-+
(+-+) :: String -> String -> String
String
"" +-+ :: String -> String -> String
+-+ String
s = String
s
String
s +-+ String
"" = String
s
String
s +-+ String
t = String
s forall a. [a] -> [a] -> [a]
++ String
" " forall a. [a] -> [a] -> [a]
++ String
t

excludedPkgs :: PackageDescription -> String -> Bool
excludedPkgs :: PackageDescription -> String -> ForceBinary
excludedPkgs PackageDescription
pkgDesc = forall a b c. (a -> b -> c) -> b -> a -> c
flip forall (t :: * -> *) a.
(Foldable t, Eq a) =>
a -> t a -> ForceBinary
notElem ([String]
subLibs forall a. [a] -> [a] -> [a]
++ [String
"ghc-prim", String
"integer-gmp", String
"ghc-bignum"])
  where
    subLibs :: [String]
    subLibs :: [String]
subLibs = [ UnqualComponentName -> String
unUnqualComponentName UnqualComponentName
ln | Library
l <- PackageDescription -> [Library]
subLibraries PackageDescription
pkgDesc, LSubLibName UnqualComponentName
ln <- [Library -> LibraryName
libName Library
l] ]

-- returns list of deps and whether package is self-dependent
buildDependencies :: PackageDescription -> String -> ([String], Bool)
buildDependencies :: PackageDescription -> String -> ([String], ForceBinary)
buildDependencies PackageDescription
pkgDesc String
self =
  let bis :: [BuildInfo]
bis   = forall a b. (a -> b) -> [a] -> [b]
map Library -> BuildInfo
libBuildInfo (PackageDescription -> [Library]
allLibraries PackageDescription
pkgDesc) forall a. [a] -> [a] -> [a]
++ forall a b. (a -> b) -> [a] -> [b]
map Executable -> BuildInfo
buildInfo (PackageDescription -> [Executable]
executables PackageDescription
pkgDesc)
      bdeps :: [String]
bdeps = forall a b. (a -> b) -> [a] -> [b]
map forall a. IsDependency a => a -> String
depName (forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap BuildInfo -> [Dependency]
targetBuildDepends (forall a. (a -> ForceBinary) -> [a] -> [a]
filter BuildInfo -> ForceBinary
buildable [BuildInfo]
bis))
      sdeps :: [String]
sdeps = forall b a. b -> (a -> b) -> Maybe a -> b
maybe [] (forall a b. (a -> b) -> [a] -> [b]
map forall a. IsDependency a => a -> String
depName forall b c a. (b -> c) -> (a -> b) -> a -> c
. SetupBuildInfo -> [Dependency]
setupDepends) (PackageDescription -> Maybe SetupBuildInfo
setupBuildInfo PackageDescription
pkgDesc)
      deps :: [String]
deps  = forall a. Eq a => [a] -> [a]
nub forall a b. (a -> b) -> a -> b
$ [String]
bdeps forall a. [a] -> [a] -> [a]
++ [String]
sdeps
  in
    (forall a. (a -> ForceBinary) -> [a] -> [a]
filter (PackageDescription -> String -> ForceBinary
excludedPkgs PackageDescription
pkgDesc) (forall a. Eq a => a -> [a] -> [a]
delete String
self [String]
deps), String
self forall (t :: * -> *) a.
(Foldable t, Eq a) =>
a -> t a -> ForceBinary
`elem` [String]
deps ForceBinary -> ForceBinary -> ForceBinary
&& PackageDescription -> ForceBinary
hasExes PackageDescription
pkgDesc)

class IsDependency a where
  depName :: a -> String

instance IsDependency Dependency where
  depName :: Dependency -> String
depName (Dependency PackageName
n VersionRange
_ NonEmptySet LibraryName
_) = PackageName -> String
unPackageName PackageName
n

instance IsDependency PkgconfigDependency where
  depName :: PkgconfigDependency -> String
depName (PkgconfigDependency PkgconfigName
n PkgconfigVersionRange
_) = PkgconfigName -> String
unPkgconfigName PkgconfigName
n

instance IsDependency LegacyExeDependency where
  depName :: LegacyExeDependency -> String
depName (LegacyExeDependency String
n VersionRange
_) = String
n

showDevelDep :: String -> String
showDevelDep :: String -> String
showDevelDep String
p = String
"ghc-" forall a. [a] -> [a] -> [a]
++ String
p forall a. [a] -> [a] -> [a]
++ String
"-devel"

showProfDep :: String -> String
showProfDep :: String -> String
showProfDep String
p = String
"ghc-" forall a. [a] -> [a] -> [a]
++ String
p forall a. [a] -> [a] -> [a]
++ String
"-prof"

resolveLib :: String -> String
resolveLib :: String -> String
resolveLib String
"alut" = String
"freealut-devel"
resolveLib String
"asound" = String
"alsa-devel"
resolveLib String
"blas" = String
"blas-devel"
resolveLib String
"bluetooth" = String
"bluez-devel"
resolveLib String
"clang" = String
"clang-devel"
resolveLib String
"crypt" = String
"glibc-devel"
resolveLib String
"crypto" = String
"libopenssl-devel"
resolveLib String
"fftw3" = String
"fftw3-devel"
resolveLib String
"FLAC" = String
"flac-devel"
resolveLib String
"fontconfig" = String
"fontconfig-devel"
resolveLib String
"freetype" = String
"freetype2-devel"
resolveLib String
"gd" = String
"gd-devel"
resolveLib String
"GL" = String
"Mesa-libGL-devel"
resolveLib String
"glib-2.0" = String
"glib2-devel"
resolveLib String
"GLU" = String
"glu-devel"
resolveLib String
"gmp" = String
"gmp-devel"
resolveLib String
"gsl" = String
"gsl-devel"
resolveLib String
"icudata" = String
"libicu-devel"
resolveLib String
"icui18n" = String
"libicu-devel"
resolveLib String
"icuuc" = String
"libicu-devel"
resolveLib String
"IL" = String
"DevIL-devel"
resolveLib String
"Imlib2" = String
"imlib2-devel"
resolveLib String
"lapack" = String
"lapack-devel"
resolveLib String
"leveldb" = String
"leveldb-devel"
resolveLib String
"lmdb" = String
"lmdb-devel"
resolveLib String
"lua" = String
"lua-devel"
resolveLib String
"luajit" = String
"luajit-devel"
resolveLib String
"lzma" = String
"xz-devel"
resolveLib String
"m" = String
"glibc-devel"
resolveLib String
"magic" = String
"file-devel"
resolveLib String
"mpfr" = String
"mpfr-devel"
resolveLib String
"odbc" = String
"unixODBC-devel"
resolveLib String
"openal" = String
"openal-soft-devel"
resolveLib String
"pcre" = String
"pcre-devel"
resolveLib String
"png" = String
"libpng16-compat-devel"
resolveLib String
"pq" = String
"postgresql-server-devel"
resolveLib String
"pthread" = String
"glibc-devel"
resolveLib String
"re2" = String
"re2-devel"
resolveLib String
"resolv" = String
"glibc-devel"
resolveLib String
"ruby" = String
"ruby-devel"
resolveLib String
"snappy" = String
"snappy-devel"
resolveLib String
"sqlite3" = String
"sqlite3-devel"
resolveLib String
"ssl" = String
"libopenssl-devel"
resolveLib String
"tag_c" = String
"libtag-devel"
resolveLib String
"z" = String
"zlib-devel"
resolveLib String
name | String
"lib" forall a. Eq a => [a] -> [a] -> ForceBinary
`isPrefixOf` String
name = String
name forall a. [a] -> [a] -> [a]
++ String
"-devel"
                | ForceBinary
otherwise               = String
"lib" forall a. [a] -> [a] -> [a]
++ String
name forall a. [a] -> [a] -> [a]
++ String
"-devel"

testsuiteDependencies :: PackageDescription -- ^pkg description
                      -> String             -- ^self
                      -> [String]           -- ^depends
testsuiteDependencies :: PackageDescription -> String -> [String]
testsuiteDependencies PackageDescription
pkgDesc String
self = forall a b. (a -> b) -> [a] -> [b]
map String -> String
showDevelDep [String]
deps forall a. [a] -> [a] -> [a]
++ forall a b. (a -> b) -> [a] -> [b]
map String -> String
showProfDep [String]
deps
  where deps :: [String]
deps = forall a. Eq a => a -> [a] -> [a]
delete String
self forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. (a -> ForceBinary) -> [a] -> [a]
filter (PackageDescription -> String -> ForceBinary
excludedPkgs PackageDescription
pkgDesc) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Eq a => [a] -> [a]
nub forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a -> b) -> [a] -> [b]
map forall a. IsDependency a => a -> String
depName forall a b. (a -> b) -> a -> b
$
                 forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap BuildInfo -> [Dependency]
targetBuildDepends (forall a. (a -> ForceBinary) -> [a] -> [a]
filter BuildInfo -> ForceBinary
buildable (forall a b. (a -> b) -> [a] -> [b]
map TestSuite -> BuildInfo
testBuildInfo (PackageDescription -> [TestSuite]
testSuites PackageDescription
pkgDesc)))

badDescription :: String -> Bool
badDescription :: String -> ForceBinary
badDescription String
s = forall (t :: * -> *) a. Foldable t => t a -> ForceBinary
null String
s
                ForceBinary -> ForceBinary -> ForceBinary
|| String
"please see readme" forall a. Eq a => [a] -> [a] -> ForceBinary
`isPrefixOf` forall a b. (a -> b) -> [a] -> [b]
map Char -> Char
toLower String
s
                ForceBinary -> ForceBinary -> ForceBinary
|| String
"please see the readme" forall a. Eq a => [a] -> [a] -> ForceBinary
`isPrefixOf` forall a b. (a -> b) -> [a] -> [b]
map Char -> Char
toLower String
s
                ForceBinary -> ForceBinary -> ForceBinary
|| String
"see readme" forall a. Eq a => [a] -> [a] -> ForceBinary
`isPrefixOf` forall a b. (a -> b) -> [a] -> [b]
map Char -> Char
toLower String
s
                ForceBinary -> ForceBinary -> ForceBinary
|| String
"cf readme" forall a. Eq a => [a] -> [a] -> ForceBinary
`isPrefixOf` forall a b. (a -> b) -> [a] -> [b]
map Char -> Char
toLower String
s
                ForceBinary -> ForceBinary -> ForceBinary
|| String
"please refer to readme" forall a. Eq a => [a] -> [a] -> ForceBinary
`isPrefixOf` forall a b. (a -> b) -> [a] -> [b]
map Char -> Char
toLower String
s
                ForceBinary -> ForceBinary -> ForceBinary
|| String
"initial project template" forall a. Eq a => [a] -> [a] -> ForceBinary
`isPrefixOf` forall a b. (a -> b) -> [a] -> [b]
map Char -> Char
toLower String
s

-- | @pandoc-2.2.1@ installs a file with square brackets in its name, and that
-- confuses RPM because it thinks those are shell specials.
--
-- TODO: Figure out how this code is supposed to interact with legitimate shell
-- globs, like '*'.

avoidSquareBrackets :: String -> String
avoidSquareBrackets :: String -> String
avoidSquareBrackets []     = []
avoidSquareBrackets (Char
x:String
xs)
  | Char
x forall (t :: * -> *) a.
(Foldable t, Eq a) =>
a -> t a -> ForceBinary
`elem` String
"[]"       = Char
'?' forall a. a -> [a] -> [a]
: String -> String
avoidSquareBrackets String
xs
  | ForceBinary
otherwise           = Char
x forall a. a -> [a] -> [a]
: String -> String
avoidSquareBrackets String
xs