cabal-rpm 0.8.7 → 0.8.8
raw patch · 15 files changed
+381/−221 lines, 15 files
Files
- ChangeLog +14/−1
- cabal-rpm.cabal +12/−4
- cblrpm-diff +1/−1
- man/cblrpm.1 +28/−21
- man/cblrpm.1.md +13/−9
- src/Commands/Depends.hs +42/−0
- src/Commands/Install.hs +9/−7
- src/Commands/RpmBuild.hs +53/−41
- src/Commands/Spec.hs +29/−18
- src/Dependencies.hs +80/−0
- src/Depends.hs +0/−68
- src/Main.hs +66/−33
- src/PackageUtils.hs +5/−3
- src/Setup.hs +11/−5
- src/SysCmd.hs +18/−10
ChangeLog view
@@ -1,9 +1,22 @@+* 0.8.8 (2014-02-07)+- updated GPLv3 license headers+- use .spec file to determine package if no .cabal file (works with+ or without arg)+- bugfix: install command now works even if some dependencies not packaged+- bugfix: do not re-copy cached tarball each time+- use new shorter hackage2 URL for packages+- filter @ and \ quotes in descriptions+- new prep command (like "rpmbuild -bp" or "fedpkg prep")+- new depends and requires commands list package depends or buildrequires+- new builddep command (like yum-buildep, but allows missing packages)+- notice for overwriting existing spec file with force option+ * 0.8.7 (2013-12-31) - new "install" command wrapping "cabal install" - "build" command renamed to "rpm" - sort devel Requires - cblrpm-diff: allow package arg-- support copying tarball fetched from another remote-repo (CodeBlock)+- support copying tarball fetched from another remote-repo (Ricky Elrod) - hlint cleanup - support AGPL license in Cabal-1.18
cabal-rpm.cabal view
@@ -1,10 +1,17 @@ Name: cabal-rpm-Version: 0.8.7+Version: 0.8.8 Synopsis: RPM package creator for Haskell Cabal-based packages Description: This package generates RPM packages from Haskell Cabal packages. .- See <https://github.com/juhp/cabal-rpm/blob/master/ChangeLog> for history details.+ * cblrpm spec: creates a .spec file from a hackage+ * cblrpm srpm: creates an source rpm package+ * cblrpm rpm: build a binary rpm package, installing depends with yum+ * cblrpm prep: unpacks package source+ * cblrpm builddep: yum install depends+ * cblrpm install: yum install depends and then cabal install+ * cblrpm depends: list hackage dependencies+ * cblrpm requires: list package dependencies Homepage: https://github.com/juhp/cabal-rpm Bug-reports: https://github.com/juhp/cabal-rpm/issues License: GPL-3@@ -12,7 +19,7 @@ Author: Bryan O'Sullivan <bos@serpentine.com>, Jens Petersen <juhp@community.haskell.org> Maintainer: Jens Petersen <petersen@fedoraproject.org> Copyright: 2007-2008 Bryan O'Sullivan <bos@serpentine.com>,- 2012-2013 Jens Petersen <petersen@fedoraproject.org>+ 2012-2014 Jens Petersen <petersen@fedoraproject.org> Category: Distribution Build-type: Simple Extra-source-files: README.md ChangeLog man/cblrpm.1.md man/cblrpm.1 cblrpm-diff@@ -34,10 +41,11 @@ time, unix Other-modules:+ Commands.Depends, Commands.Install, Commands.RpmBuild, Commands.Spec,- Depends,+ Dependencies, PackageUtils, Setup, SysCmd
cblrpm-diff view
@@ -1,6 +1,6 @@ #!/bin/sh -# Copyright (C) 2008-2012 Red Hat, Inc+# Copyright (C) 2008-2013 Red Hat, Inc # Author: Jens Petersen <petersen@redhat.com> # # This program is free software: you can redistribute it and/or modify
man/cblrpm.1 view
@@ -1,24 +1,29 @@-.TH CBLRPM 1 "2013\-01\-21" +.TH "CBLRPM" "1" "2013\-01\-21" "" "" .SH NAME .PP-cblrpm \- generates RPM .spec files from Cabal packages+cblrpm \- a RPM packaging tool for Haskell Cabal packages .SH SYNOPSIS .PP cblrpm [\f[I]options\f[]] spec [\f[I]path\-or\-pkg\f[]] cblrpm [\f[I]options\f[]] rpm [\f[I]path\-or\-pkg\f[]] cblrpm-[\f[I]options\f[]] srpm [\f[I]path\-or\-pkg\f[]]-[\f[I]options\f[]] install [\f[I]path\-or\-pkg\f[]]+[\f[I]options\f[]] srpm [\f[I]path\-or\-pkg\f[]] cblrpm+[\f[I]options\f[]] prep [\f[I]path\-or\-pkg\f[]] cblrpm+[\f[I]options\f[]] builddep [\f[I]path\-or\-pkg\f[]] cblrpm+[\f[I]options\f[]] install [\f[I]path\-or\-pkg\f[]] cblrpm+[\f[I]options\f[]] depends [\f[I]path\-or\-pkg\f[]] cblrpm+[\f[I]options\f[]] requires [\f[I]path\-or\-pkg\f[]] .SH DESCRIPTION .PP-cblrpm generates RPM .spec files from Haskell Cabal package.+cblrpm generates RPM packages and .spec files from Haskell Cabal+package. .PP-If no \f[I]path\-or\-pkg\f[] is specified, cblrpm looks for a .cabal-file in the current directory.+If no \f[I]path\-or\-pkg\f[] is specified, cblrpm looks for a .cabal or+.spec file in the current directory. Otherwise, it will look for \f[I]path\-or\-pkg\f[].-If the argument is a directory then it will look there for a .cabal-file.-If the argument is a path to a .cabal or .tar.gz file then it will use-it.+If the argument is a directory then it will look there for a .cabal or+.spec file.+If the argument is a path to a .cabal, .spec, or .tar.gz file then it+will use it. Otherwise if there is no \[aq]/\[aq] in the argument and it does not exist then cblrpm will try to unpack the package and use its .cabal file.@@ -56,43 +61,45 @@ file. .SH EXAMPLES .PP-Create a .spec file for the Cabal src package in current directory:+Below CMD can be one of: spec, srpm, rpm, install, and depends.+.PP+Do CMD for the package in current directory: .IP .nf \f[C]-cblrpm\ spec+cblrpm\ CMD \f[] .fi .PP-Create a .spec file for package (directory or package name):+Do CMD for package (directory or package name): .IP .nf \f[C]-cblrpm\ spec\ [package]+cblrpm\ CMD\ [package] \f[] .fi .PP-Create a .spec file for package\-version (directory or package name):+Do CMD for package\-version (directory or package name): .IP .nf \f[C]-cblrpm\ spec\ [package\-version]+cblrpm\ CMD\ [package\-version] \f[] .fi .PP-Create a .spec file for a .cabal file:+Do CMD on a .cabal file: .IP .nf \f[C]-cblrpm\ spec\ path/to/some.cabal+cblrpm\ CMD\ path/to/some.cabal \f[] .fi .PP-Create a .spec file from a tarball:+Do CMD for a tarball: .IP .nf \f[C]-cblrpm\ spec\ path/to/pkg\-ver.tar.gz+cblrpm\ CMD\ path/to/pkg\-ver.tar.gz \f[] .fi .SH HISTORY
man/cblrpm.1.md view
@@ -3,22 +3,26 @@ % 2013-01-21 # NAME-cblrpm - generates RPM .spec files from Cabal packages+cblrpm - a RPM packaging tool for Haskell Cabal packages # SYNOPSIS cblrpm [*options*] spec [*path-or-pkg*] cblrpm [*options*] rpm [*path-or-pkg*] cblrpm [*options*] srpm [*path-or-pkg*]+cblrpm [*options*] prep [*path-or-pkg*]+cblrpm [*options*] builddep [*path-or-pkg*] cblrpm [*options*] install [*path-or-pkg*]+cblrpm [*options*] depends [*path-or-pkg*]+cblrpm [*options*] requires [*path-or-pkg*] # DESCRIPTION-cblrpm generates RPM .spec files from Haskell Cabal package.+cblrpm generates RPM packages and .spec files from Haskell Cabal package. -If no *path-or-pkg* is specified, cblrpm looks for a .cabal file-in the current directory. Otherwise, it will look for *path-or-pkg*.-If the argument is a directory then it will look there for a .cabal file.-If the argument is a path to a .cabal or .tar.gz file then it will use it.-Otherwise if there is no '/' in the argument and it does not exist+If no *path-or-pkg* is specified, cblrpm looks for a .cabal or .spec file+in the current directory. Otherwise, it will look for *path-or-pkg*. If+the argument is a directory then it will look there for a .cabal or .spec file.+If the argument is a path to a .cabal, .spec, or .tar.gz file then it will+use it. Otherwise if there is no '/' in the argument and it does not exist then cblrpm will try to unpack the package and use its .cabal file. cblrpm uses a temporary directory for unpackaging tarballs or packages. @@ -50,9 +54,9 @@ : Override the version number in the .spec file. # EXAMPLES-Below CMD can be one of: spec, srpm, rpm, and install.+Below CMD can be one of: spec, srpm, rpm, install, and depends. -Do CMD for the Cabal src package in current directory:+Do CMD for the package in current directory: cblrpm CMD
+ src/Commands/Depends.hs view
@@ -0,0 +1,42 @@+-- |+-- Module : Commands.Depends+-- Copyright : (C) 2014 Jens Petersen+--+-- Maintainer : Jens Petersen <petersen@fedoraproject.org>+-- Stability : alpha+--+-- Explanation: cabal wrapper which yum installs dependencies++-- 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 Commands.Depends (+ depends,+ requires+ ) where++import Dependencies (dependencies, packageDependencies )+import PackageUtils (packageName, simplePackageDescription)+import Setup (RpmFlags (..))++import Data.List (sort)+import Distribution.PackageDescription (GenericPackageDescription (..),+ PackageDescription (..))++depends :: GenericPackageDescription -> RpmFlags -> IO ()+depends genPkgDesc flags = do+ pkgDesc <- simplePackageDescription genPkgDesc flags+ let pkg = package pkgDesc+ name = packageName pkg+ (deps, tools, clibs, pkgcfgs, _) <- dependencies pkgDesc name+ mapM_ putStrLn $ deps ++ tools ++ clibs ++ pkgcfgs++requires :: GenericPackageDescription -> RpmFlags -> IO ()+requires genPkgDesc flags = do+ pkgDesc <- simplePackageDescription genPkgDesc flags+ let pkg = package pkgDesc+ name = packageName pkg+ (deps, tools, clibs, pkgcfgs, _) <- packageDependencies pkgDesc name+ mapM_ putStrLn $ sort $ deps ++ tools ++ clibs ++ pkgcfgs
src/Commands/Install.hs view
@@ -1,6 +1,6 @@ -- | -- Module : Commands.Install--- Copyright : Jens Petersen 2012-2013+-- Copyright : (C) 2012-2014 Jens Petersen -- -- Maintainer : Jens Petersen <petersen@fedoraproject.org> -- Stability : alpha@@ -8,17 +8,19 @@ -- -- Explanation: cabal wrapper which yum installs dependencies --- This software may be used and distributed according to the terms of--- the GNU General Public License, incorporated herein by reference.+-- 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 Commands.Install ( install ) where -import Depends (dependencies)+import Dependencies (dependencies) import PackageUtils (packageName, simplePackageDescription) import Setup (RpmFlags (..))-import SysCmd (trySystem, systemBool, yumInstall, (+-+))+import SysCmd (runSystem, systemBool, yumInstall, (+-+)) import Control.Monad (filterM, liftM) @@ -34,10 +36,10 @@ name = packageName pkg (deps, tools, clibs, pkgcfgs, _) <- dependencies pkgDesc name missing <- filterM notInstalled $ deps ++ tools ++ clibs ++ pkgcfgs- yumInstall missing+ yumInstall missing False let pkgDir = takeDirectory cabalPath setCurrentDirectory pkgDir- trySystem "cabal install"+ runSystem "cabal install" where notInstalled :: String -> IO Bool notInstalled br =
src/Commands/RpmBuild.hs view
@@ -1,7 +1,7 @@ -- | -- Module : Commands.RpmBuild--- Copyright : Bryan O'Sullivan 2007, 2008--- Jens Petersen 2012-2013+-- Copyright : (C) 2007-2008 Bryan O'Sullivan+-- (C) 2012-2014 Jens Petersen -- -- Maintainer : Jens Petersen <petersen@fedoraproject.org> -- Stability : alpha@@ -10,18 +10,20 @@ -- Explanation: Support for building RPM packages. Can also generate -- an RPM spec file if you need a basic one to hand-customize. --- This software may be used and distributed according to the terms of--- the GNU General Public License, incorporated herein by reference.+-- 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 Commands.RpmBuild (- rpmBuild+ rpmBuild, RpmStage (..) ) where import Commands.Spec (createSpecFile) import PackageUtils (isScmDir, packageName, packageVersion, simplePackageDescription) import Setup (RpmFlags (..))-import SysCmd (tryReadProcess, trySystem, systemBool, yumInstall, (+-+))+import SysCmd (runSystem, systemBool, tryReadProcess, yumInstall, (+-+)) --import Control.Exception (bracket) import Control.Applicative ((<$>))@@ -47,10 +49,12 @@ -- c <- doesFileExist "configure" -- when (not c) $ do -- setupMessage verbose "Running autoreconf" pkgDesc--- trySystem "autoreconf"+-- runSystem "autoreconf" -rpmBuild :: FilePath -> GenericPackageDescription -> RpmFlags -> Bool -> IO ()-rpmBuild cabalPath genPkgDesc flags binary = do+data RpmStage = Binary | Source | Prep | BuildDep deriving Eq++rpmBuild :: FilePath -> GenericPackageDescription -> RpmFlags -> RpmStage -> IO ()+rpmBuild cabalPath genPkgDesc flags stage = do -- let verbose = rpmVerbosity flags pkgDesc <- simplePackageDescription genPkgDesc flags -- bracket (setFileCreationMask 0o022) setFileCreationMask $ \ _ -> do@@ -62,28 +66,34 @@ else createSpecFile cabalPath genPkgDesc flags let pkg = package pkgDesc name = packageName pkg- when binary $ do+ when (stage `elem` [Binary,BuildDep]) $ do br_out <- tryReadProcess "rpmspec" ["-q", "--buildrequires", specFile] missing <- filterM notInstalled $ lines br_out- yumInstall missing+ yumInstall missing True - let version = packageVersion pkg- tarFile = name ++ "-" ++ version ++ ".tar.gz"- rpmCmd = if binary then "a" else "s"+ unless (stage == BuildDep) $ do+ let version = packageVersion pkg+ tarFile = name ++ "-" ++ version ++ ".tar.gz"+ rpmCmd = case stage of+ Binary -> "a"+ Source -> "s"+ Prep -> "p"+ BuildDep -> "_" - tarFileExists <- doesFileExist tarFile- unless tarFileExists $ do- scmRepo <- isScmDir $ takeDirectory cabalPath- when scmRepo $- error "No tarball for source repo"+ tarFileExists <- doesFileExist tarFile+ unless tarFileExists $ do+ scmRepo <- isScmDir $ takeDirectory cabalPath+ when scmRepo $+ error "No tarball for source repo" - cwd <- getCurrentDirectory- copyTarball name version False cwd- trySystem ("rpmbuild -b" ++ rpmCmd +-+- "--define \"_rpmdir" +-+ cwd ++ "\"" +-+- "--define \"_srcrpmdir" +-+ cwd ++ "\"" +-+- "--define \"_sourcedir" +-+ cwd ++ "\"" +-+- specFile)+ cwd <- getCurrentDirectory+ copyTarball name version False cwd+ runSystem ("rpmbuild -b" ++ rpmCmd +-++ (if stage == Prep then "--nodeps" else "") +-++ "--define \"_rpmdir" +-+ cwd ++ "\"" +-++ "--define \"_srcrpmdir" +-+ cwd ++ "\"" +-++ "--define \"_sourcedir" +-+ cwd ++ "\"" +-++ specFile) where notInstalled :: String -> IO Bool notInstalled br =@@ -93,21 +103,23 @@ shellQuote "" = "" copyTarball :: String -> String -> Bool -> FilePath -> IO () copyTarball n v ranFetch dest = do- home <- getEnv "HOME"- let cacheparent = home </> ".cabal" </> "packages"- tarfile = n ++ "-" ++ v ++ ".tar.gz"- tarpath = n </> v </> tarfile- remotes <- filter (not . isPrefixOf ".") <$> getDirectoryContents cacheparent- let paths = map (\ repo -> cacheparent </> repo </> tarpath) remotes- -- if more than one tarball, should maybe warn if they are different- tarballs <- filterM doesFileExist paths- if null tarballs- then if ranFetch- then error $ "No" +-+ tarfile +-+ "found"- else do- trySystem ("cabal fetch -v0 --no-dependencies" +-+ n ++ "-" ++ v)- copyTarball n v True dest- else copyFile (head tarballs) (dest </> tarfile)+ let tarfile = n ++ "-" ++ v ++ ".tar.gz"+ already <- doesFileExist tarfile+ unless already $ do+ home <- getEnv "HOME"+ let cacheparent = home </> ".cabal" </> "packages"+ tarpath = n </> v </> tarfile+ remotes <- filter (not . isPrefixOf ".") <$> getDirectoryContents cacheparent+ let paths = map (\ repo -> cacheparent </> repo </> tarpath) remotes+ -- if more than one tarball, should maybe warn if they are different+ tarballs <- filterM doesFileExist paths+ if null tarballs+ then if ranFetch+ then error $ "No" +-+ tarfile +-+ "found"+ else do+ runSystem ("cabal fetch -v0 --no-dependencies" +-+ n ++ "-" ++ v)+ copyTarball n v True dest+ else copyFile (head tarballs) (dest </> tarfile) specFileName :: PackageDescription -- ^pkg description -> RpmFlags -- ^rpm flags
src/Commands/Spec.hs view
@@ -2,8 +2,8 @@ -- | -- Module : Commands.Spec--- Copyright : Bryan O'Sullivan 2007, 2008--- Jens Petersen 2012-2013+-- Copyright : (C) 2007-2008 Bryan O'Sullivan+-- (C) 2012-2014 Jens Petersen -- -- Maintainer : Jens Petersen <petersen@fedoraproject.org> -- Stability : alpha@@ -11,14 +11,16 @@ -- -- Explanation: Generates an RPM spec file from a .cabal file. --- This software may be used and distributed according to the terms of--- the GNU General Public License, incorporated herein by reference.+-- 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 Commands.Spec ( createSpecFile ) where -import Depends (dependencies, showDep)+import Dependencies (packageDependencies, showDep) import PackageUtils (isScmDir, packageName, packageVersion, simplePackageDescription) import Setup (RpmFlags (..))@@ -26,7 +28,7 @@ --import Control.Exception (bracket) import Control.Monad (unless, when)-import Data.Char (toLower)+import Data.Char (toLower, toUpper) import Data.List (groupBy, isPrefixOf, isSuffixOf, sort) import Data.Maybe (fromMaybe) import Data.Time.Clock (UTCTime, getCurrentTime)@@ -35,7 +37,7 @@ import Distribution.License (License (..)) -import Distribution.Simple.Utils (warn)+import Distribution.Simple.Utils (notice, warn) import Distribution.PackageDescription (PackageDescription (..), exeName, hasExes, hasLibs, withExe,@@ -91,7 +93,8 @@ isBinLib = isExec && isLib specAlreadyExists <- doesFileExist specFile let specFilename = specFile ++ if not (rpmForce flags) && specAlreadyExists then ".cblrpm" else ""- when specAlreadyExists $ putStrLn $ specFile +-+ "exists:" +-+ "creating" +-+ specFilename+ when specAlreadyExists $+ notice verbose $ specFile +-+ "exists:" +-+ if rpmForce flags then "forcing overwrite" else "creating" +-+ specFilename h <- openFile specFilename WriteMode let putHdr hdr val = hPutStrLn h (hdr ++ ":" ++ padding hdr ++ val) padding hdr = replicate (14 - length hdr) ' ' ++ " "@@ -108,9 +111,11 @@ let syn = synopsis pkgDesc when (null syn) $ warn verbose "this package has no synopsis."+ let initialCapital (c:cs) = toUpper c:cs+ initialCapital [] = [] let syn' = if null syn then "Haskell" +-+ name +-+ "package"- else unwords $ lines syn+ else (unwords . lines . initialCapital) syn let summary = rstrip (== '.') syn' when (length ("Summary : " ++ syn') > 79) $ warn verbose "this package has a long synopsis."@@ -118,10 +123,16 @@ let descr = description pkgDesc when (null descr) $ warn verbose "this package has no description."- let descLines = (formatParagraphs . lines . finalPeriod) $+ let descLines = (formatParagraphs . initialCapital . filterSymbols . finalPeriod) $ if null descr then syn' else descr finalPeriod cs = if last cs == '.' then cs else cs ++ "."-+ filterSymbols (c:cs) =+ if c `notElem` "@\\" then c: filterSymbols cs+ else case c of+ '@' -> '\'': filterSymbols cs+ '\\' -> head cs: filterSymbols (tail cs)+ _ -> c: filterSymbols cs+ filterSymbols [] = [] when isLib $ do putDef "pkg_name" name putNewline@@ -133,16 +144,16 @@ putNewline putHdr "License" $ (showLicense . license) pkgDesc putHdr "URL" $ "http://hackage.haskell.org/package/" ++ pkg_name- putHdr "Source0" $ "http://hackage.haskell.org/packages/archive/" ++ pkg_name ++ "/%{version}/" ++ pkg_name ++ "-%{version}.tar.gz"+ putHdr "Source0" $ "http://hackage.haskell.org/package/" ++ pkg_name ++ "-%{version}/" ++ pkg_name ++ "-%{version}.tar.gz" putNewline putHdr "BuildRequires" "ghc-Cabal-devel" putHdr "BuildRequires" "ghc-rpm-macros" - (deps, tools, clibs, pkgcfgs, selfdep) <- dependencies pkgDesc name- unless (null $ deps ++ tools ++ clibs ++ pkgcfgs) $ do+ (deps, tools, clibs, pkgcfgs, selfdep) <- packageDependencies pkgDesc name+ let alldeps = sort $ deps ++ tools ++ clibs ++ pkgcfgs+ unless (null alldeps) $ do put "# Begin cabal-rpm deps:"- let pkgdeps = sort $ deps ++ tools ++ clibs ++ pkgcfgs- mapM_ (putHdr "BuildRequires") pkgdeps+ mapM_ (putHdr "BuildRequires") alldeps when (any (\ d -> d `elem` map showDep ["template-haskell", "hamlet"]) deps) $ putHdr "ExclusiveArch" "%{ghc_arches_with_ghci}" put "# End cabal-rpm deps"@@ -300,5 +311,5 @@ where lw = length w endp = last w == '.' -formatParagraphs :: [String] -> [String]-formatParagraphs = map (wordwrap 79) . paragraphs+formatParagraphs :: String -> [String]+formatParagraphs = map (wordwrap 79) . paragraphs . lines
+ src/Dependencies.hs view
@@ -0,0 +1,80 @@+-- |+-- Module : Dependencies+-- Copyright : (C) 2012-2014 Jens Petersen+--+-- Maintainer : Jens Petersen <petersen@fedoraproject.org>+-- Stability : alpha+-- Portability : portable+--+-- Explanation: Dependency info++-- 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 Dependencies (+ dependencies, packageDependencies, showDep+ ) where++import SysCmd (tryReadProcess)++import Data.List (nub)++import Distribution.Package (Dependency (..), PackageName (..))+import Distribution.PackageDescription (PackageDescription (..),+ allBuildInfo,+ BuildInfo (..))++-- returns list of deps and whether package is self-dependent+buildDependencies :: PackageDescription -> String -> ([String], Bool)+buildDependencies pkgDesc self =+ let deps = nub $ map depName (buildDepends pkgDesc)+ excludedPkgs n = notElem n [self, "Cabal", "base", "ghc-prim", "integer-gmp"] in+ (filter excludedPkgs deps, self `elem` deps)++depName :: Dependency -> String+depName (Dependency (PackageName n) _) = n++showDep :: String -> String+showDep p = "ghc-" ++ p ++ "-devel"++dependencies :: PackageDescription -- ^pkg description+ -> String -- ^pkg name+ -> IO ([String], [String], [String], [String], Bool)+ -- ^depends, tools, c-libs, pkgcfg, selfdep+dependencies pkgDesc self = do+ let (deps, selfdep) = buildDependencies pkgDesc self+ buildinfo = allBuildInfo pkgDesc+ tools = nub $ map depName (concatMap buildTools buildinfo)+ pkgcfgs = nub $ map depName $ concatMap pkgconfigDepends buildinfo++ clibs <- mapM repoqueryLib $ concatMap extraLibs buildinfo+ return (deps, tools, clibs, pkgcfgs, selfdep)++packageDependencies :: PackageDescription -- ^pkg description+ -> String -- ^pkg name+ -> IO ([String], [String], [String], [String], Bool)+ -- ^depends, tools, c-libs, pkgcfg, selfdep+packageDependencies pkgDesc self = do+ (deps, tools', clibs, pkgcfgs, selfdep) <- dependencies pkgDesc self+ let excludedTools n = n `notElem` ["ghc", "hsc2hs", "perl"]+ mapTools "gtk2hsC2hs" = "gtk2hs-buildtools"+ mapTools "gtk2hsHookGenerator" = "gtk2hs-buildtools"+ mapTools "gtk2hsTypeGen" = "gtk2hs-buildtools"+ mapTools tool = tool+ chrpath = ["chrpath" | selfdep]+ tools = filter excludedTools $ nub $ map mapTools tools' ++ chrpath++ let showPkgCfg p = "pkgconfig(" ++ p ++ ")"+ return (map showDep deps, tools, map (++ "%{?_isa}") clibs, map showPkgCfg pkgcfgs, selfdep)++repoqueryLib :: String -> IO String+repoqueryLib lib = do+ let lib_path = "/usr/lib/lib" ++ lib ++ ".so"+ out <- tryReadProcess "repoquery" ["--qf=%{name}", "-qf", lib_path]+ let pkgs = nub $ words out+ case pkgs of+ [pkg] -> return pkg+ [] -> error $ "Could not resolve package that provides lib" ++ lib_path+ _ -> error $ "More than one package seems to provide lib" ++ lib_path ++ ": " ++ show pkgs
− src/Depends.hs
@@ -1,68 +0,0 @@--- |--- Module : Depends--- Copyright : Jens Petersen 2012-2013------ Maintainer : Jens Petersen <petersen@fedoraproject.org>--- Stability : alpha--- Portability : portable------ Explanation: Dependency info---- This software may be used and distributed according to the terms of--- the GNU General Public License, incorporated herein by reference.--module Depends (- dependencies, showDep- ) where--import SysCmd (tryReadProcess)--import Data.List (nub)--import Distribution.Package (Dependency (..), PackageName (..))-import Distribution.PackageDescription (PackageDescription (..),- allBuildInfo,- BuildInfo (..))---- returns list of deps and whether package is self-dependent-buildDependencies :: PackageDescription -> String -> ([String], Bool)-buildDependencies pkgDesc self =- let deps = nub $ map depName (buildDepends pkgDesc)- excludedPkgs n = notElem n [self, "Cabal", "base", "ghc-prim", "integer-gmp"] in- (filter excludedPkgs deps, self `elem` deps)--depName :: Dependency -> String-depName (Dependency (PackageName n) _) = n--showDep :: String -> String-showDep p = "ghc-" ++ p ++ "-devel"--dependencies :: PackageDescription -- ^pkg description- -> String -- ^pkg name- -> IO ([String], [String], [String], [String], Bool)- -- ^depends, tools, c-libs, pkgcfg, selfdep-dependencies pkgDesc self = do- let (deps, selfdep) = buildDependencies pkgDesc self- buildinfo = allBuildInfo pkgDesc- excludedTools n = n `notElem` ["ghc", "hsc2hs", "perl"]- mapTools "gtk2hsC2hs" = "gtk2hs-buildtools"- mapTools "gtk2hsHookGenerator" = "gtk2hs-buildtools"- mapTools "gtk2hsTypeGen" = "gtk2hs-buildtools"- mapTools tool = tool- chrpath = ["chrpath" | selfdep]- tools = filter excludedTools $ nub $ map (mapTools . depName) (concatMap buildTools buildinfo) ++ chrpath- pkgcfgs = nub $ map depName $ concatMap pkgconfigDepends buildinfo-- clibs <- mapM repoqueryLib $ concatMap extraLibs buildinfo- let showPkgCfg p = "pkgconfig(" ++ p ++ ")"- return (map showDep deps, tools, map (++ "%{?_isa}") clibs, map showPkgCfg pkgcfgs, selfdep)- -repoqueryLib :: String -> IO String-repoqueryLib lib = do- let lib_path = "/usr/lib/lib" ++ lib ++ ".so"- out <- tryReadProcess "repoquery" ["--qf=%{name}", "-qf", lib_path]- let pkgs = nub $ words out- case pkgs of- [pkg] -> return pkg- [] -> error $ "Could not resolve package that provides lib" ++ lib_path- _ -> error $ "More than one package seems to provide lib" ++ lib_path ++ ": " ++ show pkgs
src/Main.hs view
@@ -1,7 +1,7 @@ -- | -- Module : Main--- Copyright : Bryan O'Sullivan 2007--- Jens Petersen 2012-2013+-- Copyright : (C) 2007 Bryan O'Sullivan+-- (C) 2012-2014 Jens Petersen -- -- Maintainer : Jens Petersen <petersen@fedoraproject.org> -- Stability : alpha@@ -9,25 +9,30 @@ -- -- Explanation: Main entry point for building RPM packages. --- This software may be used and distributed according to the terms of--- the GNU General Public License, incorporated herein by reference.+-- 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 Main where +import Commands.Depends (depends, requires) import Commands.Install (install)-import Commands.RpmBuild (rpmBuild)+import Commands.RpmBuild (rpmBuild, RpmStage (..)) import Commands.Spec (createSpecFile) import Setup (RpmFlags (..), parseArgs)-import SysCmd (tryReadProcess, trySystem)+import SysCmd (runSystem, tryReadProcess) +import Control.Applicative ((<$>)) import Control.Monad (unless)-import Data.List (isSuffixOf)-import Data.Maybe (isJust)+import Data.List (isSuffixOf, stripPrefix)+import Data.Maybe (isJust, listToMaybe, fromMaybe) import Distribution.PackageDescription.Parse (readPackageDescription)-import Distribution.Simple.Utils (defaultPackageDesc, findPackageDesc)+import Distribution.Simple.Utils (die, findPackageDesc) import Distribution.Verbosity (Verbosity, silent) import System.Directory (doesDirectoryExist, doesFileExist, getCurrentDirectory,- removeDirectoryRecursive, setCurrentDirectory)+ getDirectoryContents, removeDirectoryRecursive,+ setCurrentDirectory) import System.Environment (getArgs) import System.FilePath.Posix (takeExtension) @@ -37,21 +42,17 @@ main = do (opts, args) <- getArgs >>= parseArgs let verbose = rpmVerbosity opts (cmd:args') = args- (cabalPath, mtmp) <- if null args'- then do- pth <- defaultPackageDesc verbose- return (pth, Nothing)- else findCabalFile verbose $ head args'+ (cabalPath, mtmp) <- findCabalFile verbose $ fromMaybe "." $ listToMaybe args' genPkgDesc <- readPackageDescription verbose cabalPath case cmd of "spec" -> createSpecFile cabalPath genPkgDesc opts- "srpm" -> rpmBuild cabalPath genPkgDesc opts False- "rpm" -> rpmBuild cabalPath genPkgDesc opts True+ "srpm" -> rpmBuild cabalPath genPkgDesc opts Source+ "prep" -> rpmBuild cabalPath genPkgDesc opts Prep+ "rpm" -> rpmBuild cabalPath genPkgDesc opts Binary+ "builddep" -> rpmBuild cabalPath genPkgDesc opts BuildDep "install" -> install cabalPath genPkgDesc opts--- "builddep" -> --- "depends" -> --- "install" ->--- "showdeps" ->+ "depends" -> depends genPkgDesc opts+ "requires" -> requires genPkgDesc opts c -> error $ "Unknown cmd: " ++ c maybe (return ()) removeDirectoryRecursive mtmp @@ -74,9 +75,16 @@ isdir <- doesDirectoryExist path if isdir then do- unless (vb == silent) $ putStrLn $ "Using " ++ path ++ "/"- file <- findPackageDesc path- return (file, Nothing)+ cblfile <- fileWithExtension_ path ".cabal"+ if cblfile+ then do+ unless (vb == silent) $ putStrLn $ "trying " ++ path ++ "/"+ file <- findPackageDesc path+ return (file, Nothing)+ else do+ spcfile <- fileWithExtension path ".spec"+ maybe (die "Cannot determine package in dir.")+ (cabalFromSpec vb) spcfile else do isfile <- doesFileExist path if not isfile@@ -85,16 +93,41 @@ else error $ path ++ ": No such file or directory" else if takeExtension path == ".cabal" then return (path, Nothing)- else if ".tar.gz" `isSuffixOf` path- then do- tmpdir <- mktempdir- trySystem $ "tar zxf " ++ path ++ " -C " ++ tmpdir ++ " *.cabal"- subdir <- tryReadProcess "ls" [tmpdir]- file <- findPackageDesc $ tmpdir ++ "/" ++ init subdir- return (file, Just tmpdir)- else error $ path ++ ": file should be a .cabal or .tar.gz file."+ else if takeExtension path == ".spec"+ then cabalFromSpec vb path+ else if ".tar.gz" `isSuffixOf` path+ then do+ tmpdir <- mktempdir+ runSystem $ "tar zxf " ++ path ++ " -C " ++ tmpdir ++ " *.cabal"+ subdir <- tryReadProcess "ls" [tmpdir]+ file <- findPackageDesc $ tmpdir ++ "/" ++ init subdir+ return (file, Just tmpdir)+ else error $ path ++ ": file should be a .cabal, .spec or .tar.gz file." where pkg_re = mkRegex "^([A-Za-z0-9-]+)(-([0-9.]+))?$" +-- looks in current dir for a unique file with given extension+fileWithExtension :: FilePath -> String -> IO (Maybe FilePath)+fileWithExtension dir ext = do+ files <- filter (\ f -> takeExtension f == ext) <$> getDirectoryContents dir+ case files of+ [file] -> return $ Just file+ [] -> return Nothing+ _ -> putStrLn ("More than one " ++ ext ++ " file found!") >> return Nothing++-- looks in current dir for a unique file with given extension+fileWithExtension_ :: FilePath -> String -> IO Bool+fileWithExtension_ dir ext =+ isJust <$> fileWithExtension dir ext++cabalFromSpec :: Verbosity -> FilePath -> IO (FilePath, Maybe FilePath)+cabalFromSpec vrb spcfile = do+ namever <- removePrefix "ghc-" <$> tryReadProcess "rpmspec" ["-q", "--srpm", "--qf", "%{name}-%{version}", spcfile]+ findCabalFile vrb namever++removePrefix :: String -> String-> String+removePrefix pref str =+ fromMaybe str (stripPrefix pref str)+ tryUnpack :: String -> IO (FilePath, Maybe FilePath) tryUnpack pkg = do pkgver <- if '.' `elem` pkg then return pkg@@ -113,7 +146,7 @@ cwd <- getCurrentDirectory tmpdir <- mktempdir setCurrentDirectory tmpdir- trySystem $ "cabal unpack -v0 " ++ pkgver+ runSystem $ "cabal unpack -v0 " ++ pkgver pth <- findPackageDesc pkgver setCurrentDirectory cwd return (tmpdir ++ "/" ++ pth, Just tmpdir)
src/PackageUtils.hs view
@@ -1,6 +1,6 @@ -- | -- Module : PackageUtils--- Copyright : Jens Petersen 2013+-- Copyright : (C) 2013-2014 Jens Petersen -- -- Maintainer : Jens Petersen <petersen@fedoraproject.org> -- Stability : alpha@@ -8,8 +8,10 @@ -- -- Explanation: functions related to Cabal dependency generation. --- This software may be used and distributed according to the terms of--- the GNU General Public License, incorporated herein by reference.+-- 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 PackageUtils ( isScmDir,
src/Setup.hs view
@@ -1,7 +1,7 @@ -- | -- Module : Setup--- Copyright : Bryan O'Sullivan 2007, 2008--- Jens Petersen 2012-2013+-- Copyright : (C) 2007-2008 Bryan O'Sullivan+-- (C) 2012-2014 Jens Petersen -- -- Maintainer : Jens Petersen <petersen@fedoraproject.org> -- Stability : alpha@@ -10,8 +10,10 @@ -- Explanation: Command line option processing for building RPM -- packages. --- This software may be used and distributed according to the terms of--- the GNU General Public License, incorporated herein by reference.+-- 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 Setup ( RpmFlags(..)@@ -91,8 +93,12 @@ ++ "Commands:\n" ++ " spec\t generate a spec file\n" ++ " srpm\t generate a src rpm file\n"+ ++ " prep\t unpack source\n" ++ " rpm\t build rpm package\n"+ ++ " builddep install dependencies\n" ++ " install user install package\n"+ ++ " depends list Cabal depends\n"+ ++ " requires list package buildrequires\n" -- ++ " mock\t mock build package\n" ++ "\n" ++ "Options:"@@ -116,7 +122,7 @@ hPutStr stderr "Unrecognised options: " hPutStrLn stderr $ unwords unknown exitWith (ExitFailure 1)- when (null args' || notElem (head args') ["spec", "srpm", "rpm", "install"]) $ do+ when (null args' || notElem (head args') ["builddep", "depends", "install", "prep", "requires", "spec", "srpm", "rpm"]) $ do printHelp stderr exitWith (ExitFailure 1) when (length args' > 2) $ do
src/SysCmd.hs view
@@ -1,6 +1,6 @@ -- | -- Module : SysCmd--- Copyright : Jens Petersen 2013+-- Copyright : (C) 2013-2014 Jens Petersen -- -- Maintainer : Jens Petersen <petersen@fedoraproject.org> -- Stability : alpha@@ -9,18 +9,20 @@ -- Explanation: Command line option processing for building RPM -- packages. --- This software may be used and distributed according to the terms of--- the GNU General Public License, incorporated herein by reference.+-- 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 SysCmd ( requireProgram,- trySystem,+ runSystem, tryReadProcess, systemBool, yumInstall, (+-+)) where -import Control.Monad (when, unless)+import Control.Monad (unless, void, when) import Data.Maybe (isJust, isNothing) import Distribution.Simple.Utils (die, warn, findProgramLocation)@@ -41,14 +43,19 @@ when (isNothing mavail) $ warn normal (cmd ++ ": command not found") return $ isJust mavail -trySystem :: String -> IO ()-trySystem cmd = do+runSystem :: String -> IO ()+runSystem cmd = do requireProgram $ head $ words cmd ret <- system cmd case ret of ExitSuccess -> return () ExitFailure n -> die ("\"" ++ cmd ++ "\"" +-+ "failed with status" +-+ show n) +trySystem :: String -> IO ()+trySystem cmd = do+ requireProgram $ head $ words cmd+ void $ system cmd+ systemBool :: String -> IO Bool systemBool cmd = do requireProgram $ head $ words cmd@@ -67,8 +74,8 @@ s +-+ "" = s s +-+ t = s ++ " " ++ t -yumInstall :: [String] -> IO ()-yumInstall pkgs =+yumInstall :: [String] -> Bool -> IO ()+yumInstall pkgs hard = unless (null pkgs) $ do putStrLn "Uninstalled dependencies:" mapM_ putStrLn pkgs@@ -82,7 +89,8 @@ requireProgram "yum" let args = unwords $ map showPkg pkgs putStrLn $ "Running:" +-+ cmdprefix +-+ "yum install" +-+ args- trySystem $ cmdprefix +-+ "yum install" +-+ args+ let exec = if hard then runSystem else trySystem+ exec $ cmdprefix +-+ "yum install" +-+ args showPkg :: String -> String showPkg p = if '(' `elem` p then show p else p