cabal-rpm 0.8.6 → 0.8.7
raw patch · 18 files changed
+509/−386 lines, 18 filessetup-changed
Files
- ChangeLog +122/−0
- NEWS +0/−113
- README.md +21/−10
- Setup.hs +8/−0
- Setup.lhs +0/−8
- cabal-rpm.cabal +6/−20
- cblrpm-diff +11/−4
- man/cblrpm.1 +2/−1
- man/cblrpm.1.md +14/−11
- src/Commands/Build.hs +0/−109
- src/Commands/Install.hs +47/−0
- src/Commands/RpmBuild.hs +120/−0
- src/Commands/Spec.hs +38/−60
- src/Depends.hs +68/−0
- src/Main.hs +12/−10
- src/PackageUtils.hs +14/−18
- src/Setup.hs +4/−4
- src/SysCmd.hs +22/−18
+ ChangeLog view
@@ -0,0 +1,122 @@+* 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)+- hlint cleanup+- support AGPL license in Cabal-1.18++* 0.8.6 (2013-10-04)+- check for _darcs or .git dir in package topdir not pwd++* 0.8.5 (2013-09-29)+- fix repoquery when a package update exists for C lib+- make cblrpm-diff quieter++* 0.8.4 (2013-09-28)+- use repoquery to determine extra C library dependencies+- quote "pkgconfig(foo)" for rpm query and yum install+- show sudo command before sudo password prompt appears+- exclude hsc2hs from build tool deps+- devel provides ghc-<pkg>-static+- drop release from initial changelog entry for packager to add an entry+- do not try to fetch tarball for a darcs or git source dir++* 0.8.3 (2013-07-12)+- only try to install missing dependencies+- for executables depending on own lib add BR chrpath and %ghc_fix_dynamic_rpath+- word-wrap generic descriptions+- map ffi to libffi+- move modules to toplevel+- Rpm module split into Spec and Build in Commands/++* 0.8.2 (2013-07-02)+- handle pkg-ver arg, and check cabal list is non-empty+- sort all generated deps+- use yum-builddep again to install deps+- copy tarball into cwd for rpmbuild+- warn about long synopsis rather than multiline+- wrap after end of sentence near end of line+- use _isa in requires ghc-<pkg>+- --version now outputs to stdout+- new --force flag to overwrite existing .spec file++* 0.8.1 (2013-06-14)+- word wrapping of descriptions+- use generic description for shared subpackage+- simplify logic for summary and description processing++* 0.8.0 (2013-05-31)+- new simplier revision to Fedora Packaging+ - drop %common_summary and %common_description+ - drop %ghc_package, %ghc_description, %ghc_devel_package,+ %ghc_devel_description, %ghc_devel_post_postun, %ghc_files,+ and %ghc_devel_requires+- check external programs available before use+- tweaks for ghc-7.6.3 and Cabal-1.16++* 0.7.1 (2013-03-22)+- add final full-stop to description if missing+- add ver-rel to initial changelog entry+- fix use of cblrpm-diff force lib option+- output warning when .spec already exists+- fix handling of package names that end in a digit+- output when trying a path+- map curl C dep to libcurl++* 0.7.0 (2013-01-22)+- cabal-rpm command renamed to cblrpm, and cabal-rpm-diff to cblrpm-diff+- cblrpm now has commands for spec, srpm, and build+- cblrpm will try to install packaged uninstalled depends with sudo yum install+- add %ghc_arches_with_ghci for hamlet dep+- cblrpm-diff supports -l+- cblrpm --version+- sort extralibs depends+- cleanup of unused options and help output++* 0.6.6 (2012-11-21)+- generate BRs and Req's for C libraries (extra-libraries)+- initial map for some C libs: libglut, libiw, libz, libX*+- generate BRs and Req's for pkgconfig-depends+- generate BRs for build-tools+- initial map for build-tools: gtk2hs-buildtools+- map LGPL-2.1 license to LGPLv2+ tag+- backup suffix changed from .cabal-rpm to .cblrpm+- don't mistake non-existent file in cwd for a package++* 0.6.5 (2012-11-01)+- drop hscolour BuildRequires+- simplify generated BuildRequires: drop version ranges for now,+ exclude pkg self, base libs, and Cabal+- use ExclusiveArch ghc_arches_with_ghci for template-haskell dep+- replace --name option with --library to force Lib++* 0.6.4 (2012-09-25)+- add cabal-rpm-diff+- fix manpage generation++* 0.6.3 (2012-09-24)+- support tarball path argument+- use a temporary working dir for opening tarball or cabal unpack+- add a manpage++* 0.6.2 (2012-09-10)+- fix output of L/GPL version++* 0.6.1 (2012-07-25)+bugfixes:+- fix "cabal-rpm pkg" when other *pkg* packages exist in hackage+- always generate the extra docs list from the pkg src dir!+- now no backslash at end of common_description++* 0.6.0 (2012-07-24)+- updated to work with Cabal >= 1.10 and current cabal2spec style packaging+ using currently actively used ghc-rpm-macros+- should generate haskell dependencies correctly and also summary and+ description text+- some of the generic compiler supported was dropped for simplicity+- rpmbuild support will be re-introduced in a future version++* 0.5.1 and earlier (2007-2008) released by Bryan O'Sullivan+- should work with ghc-6.8
− NEWS
@@ -1,113 +0,0 @@-* 0.8.6 (2013-10-04)-- check for _darcs or .git dir in package topdir not pwd--* 0.8.5 (2013-09-29)-- fix repoquery when a package update exists for C lib-- make cblrpm-diff quieter--* 0.8.4 (2013-09-28)-- use repoquery to determine extra C library dependencies-- quote "pkgconfig(foo)" for rpm query and yum install-- show sudo command before sudo password prompt appears-- exclude hsc2hs from build tool deps-- devel provides ghc-<pkg>-static-- drop release from initial changelog entry for packager to add an entry-- do not try to fetch tarball for a darcs or git source dir--* 0.8.3 (2013-07-12)-- only try to install missing dependencies-- for executables depending on own lib add BR chrpath and %ghc_fix_dynamic_rpath-- word-wrap generic descriptions-- map ffi to libffi-- move modules to toplevel-- Rpm module split into Spec and Build in Commands/--* 0.8.2 (2013-07-02)-- handle pkg-ver arg, and check cabal list is non-empty-- sort all generated deps-- use yum-builddep again to install deps-- copy tarball into cwd for rpmbuild-- warn about long synopsis rather than multiline-- wrap after end of sentence near end of line-- use _isa in requires ghc-<pkg>-- --version now outputs to stdout-- new --force flag to overwrite existing .spec file--* 0.8.1 (2013-06-14)-- word wrapping of descriptions-- use generic description for shared subpackage-- simplify logic for summary and description processing--* 0.8.0 (2013-05-31)-- new simplier revision to Fedora Packaging- - drop %common_summary and %common_description- - drop %ghc_package, %ghc_description, %ghc_devel_package,- %ghc_devel_description, %ghc_devel_post_postun, %ghc_files,- and %ghc_devel_requires-- check external programs available before use-- tweaks for ghc-7.6.3 and Cabal-1.16--* 0.7.1 (2013-03-22)-- add final full-stop to description if missing-- add ver-rel to initial changelog entry-- fix use of cblrpm-diff force lib option-- output warning when .spec already exists-- fix handling of package names that end in a digit-- output when trying a path-- map curl C dep to libcurl--* 0.7.0 (2013-01-22)-- cabal-rpm command renamed to cblrpm, and cabal-rpm-diff to cblrpm-diff-- cblrpm now has commands for spec, srpm, and build-- cblrpm will try to install packaged uninstalled depends with sudo yum install-- add %ghc_arches_with_ghci for hamlet dep-- cblrpm-diff supports -l-- cblrpm --version-- sort extralibs depends-- cleanup of unused options and help output--* 0.6.6 (2012-11-21)-- generate BRs and Req's for C libraries (extra-libraries)-- initial map for some C libs: libglut, libiw, libz, libX*-- generate BRs and Req's for pkgconfig-depends-- generate BRs for build-tools-- initial map for build-tools: gtk2hs-buildtools-- map LGPL-2.1 license to LGPLv2+ tag-- backup suffix changed from .cabal-rpm to .cblrpm-- don't mistake non-existent file in cwd for a package--* 0.6.5 (2012-11-01)-- drop hscolour BuildRequires-- simplify generated BuildRequires: drop version ranges for now,- exclude pkg self, base libs, and Cabal-- use ExclusiveArch ghc_arches_with_ghci for template-haskell dep-- replace --name option with --library to force Lib--* 0.6.4 (2012-09-25)-- add cabal-rpm-diff-- fix manpage generation--* 0.6.3 (2012-09-24)-- support tarball path argument-- use a temporary working dir for opening tarball or cabal unpack-- add a manpage--* 0.6.2 (2012-09-10)-- fix output of L/GPL version--* 0.6.1 (2012-07-25)-bugfixes:-- fix "cabal-rpm pkg" when other *pkg* packages exist in hackage-- always generate the extra docs list from the pkg src dir!-- now no backslash at end of common_description--* 0.6.0 (2012-07-24)-- updated to work with Cabal >= 1.10 and current cabal2spec style packaging- using currently actively used ghc-rpm-macros-- should generate haskell dependencies correctly and also summary and- description text-- some of the generic compiler supported was dropped for simplicity-- rpmbuild support will be re-introduced in a future version--* 0.5.1 and earlier (2007-2008) released by Bryan O'Sullivan-- should work with ghc-6.8
README.md view
@@ -3,13 +3,13 @@ # cabal-rpm cabal-rpm creates RPM spec files for packaging Haskell Cabal-based packages.+It can also act as a cabal-install wrapper which installs dependencies+packaged in Fedora before running "cabal install". -This version updates the older cabal-rpm-0.5.1 package by Bryan O'Sullivan-(see README.orig) to work with current Cabal and also updated to current RPM-packaging conventions defined until now by cabal2spec which is used by Fedora-and also OpenSuSE. It is licensed under the terms of the GPL version 3-(see the COPYING file). It is designed to replace the simple cabal2spec tool-shell script made by the maintainer.+Cabal-rpm was originally created by Bryan O'Sullivan (see README.orig)+but has since been updated to work with current Cabal and Fedora Packaging+Guidelines replacing cabal2spec. It is used by Fedora and (patched) OpenSuSE. +It is licensed under the terms of the GPL version 3 (see the COPYING file). You can build from source as normal by running `cabal install` or via Hackage with `cabal install cabal-rpm`.@@ -19,6 +19,12 @@ It currently needs Cabal 1.10 or later to build (ie ghc7), but it should not be hard to patch it to build at least for ghc-6.12. +## Installation+The package is on Hackage. If you have cabal-install (part of Haskell Platform)+you can install simply with++ $ cabal install cabal-rpm+ ## Usage To create a `.spec` file for a Haskell src package in the current dir: @@ -38,23 +44,28 @@ You can also package directly from hackage: - $ cblrpm build somepkg+ $ cblrpm srpm somepkg or - $ cblrpm build somepkg-0.1+ $ cblrpm rpm somepkg-0.1 will unpack the (latest) 'somepkg' package from hackage (if the dir does not exist, otherwise it uses the existing dir), create a spec file for it, and build it. -cblrpm always creates `.spec` files in the current dir+cblrpm creates `.spec` files in the current dir and if a `.spec` file already exists it will append `.cblrpm` to the generated filename to avoid overwriting an existing file. + $ cblrpm install [pkg][-ver]++will yum install available missing dependencies and+run "cabal install" to build the package.+ ## Development The latest source code is available from: https://github.com/juhp/cabal-rpm ## Plans-More features are planned and patches welcome, including recursive packaging.+More features are planned and patches welcome. See the TODO file for more details.
+ Setup.hs view
@@ -0,0 +1,8 @@+#!/usr/bin/env runghc++module Main where++import Distribution.Simple++main :: IO ()+main = defaultMain
− Setup.lhs
@@ -1,8 +0,0 @@-#!/usr/bin/env runghc--> module Main where--> import Distribution.Simple--> main :: IO ()-> main = defaultMain
cabal-rpm.cabal view
@@ -1,26 +1,10 @@ Name: cabal-rpm-Version: 0.8.6+Version: 0.8.7 Synopsis: RPM package creator for Haskell Cabal-based packages Description: This package generates RPM packages from Haskell Cabal packages. .- Recent changes:- .- * 0.8.6: check for _darcs or .git dir in package topdir not pwd- .- * 0.8.5: fix repoquery when a package update exists for C lib; make cblrpm-diff quieter- .- * 0.8.4: use repoquery for C deps, pkgconfig quoting, devel provides static- .- * 0.8.3: only install missing dependencies, word-wrap generic descriptions- .- * 0.8.2: wrap after sentences near end of line, handle pkg-ver arg, sort deps- .- * 0.8.1: word wrapping of descriptions- .- * 0.8.0: new simpler revised Fedora packaging; check external commands available- .- See <https://github.com/juhp/cabal-rpm/blob/master/NEWS> for more history and details.+ See <https://github.com/juhp/cabal-rpm/blob/master/ChangeLog> for history details. Homepage: https://github.com/juhp/cabal-rpm Bug-reports: https://github.com/juhp/cabal-rpm/issues License: GPL-3@@ -31,7 +15,7 @@ 2012-2013 Jens Petersen <petersen@fedoraproject.org> Category: Distribution Build-type: Simple-Extra-source-files: README.md NEWS man/cblrpm.1.md man/cblrpm.1 cblrpm-diff+Extra-source-files: README.md ChangeLog man/cblrpm.1.md man/cblrpm.1 cblrpm-diff Cabal-version: >=1.6 source-repository head@@ -50,8 +34,10 @@ time, unix Other-modules:- Commands.Build,+ Commands.Install,+ Commands.RpmBuild, Commands.Spec,+ Depends, PackageUtils, Setup, SysCmd
cblrpm-diff view
@@ -27,19 +27,26 @@ esac fi -if [ $# -ne 1 -o ! -r "$1" ]; then+if [ $# -ne 1 ]; then echo "Usage: $(basename $0) [-l] [hackage|hackage.tar.gz|hackage.cabal]" echo " -l assume BinLib package is Lib" exit 1 fi -FILE=$1+case $0 in+ /*) CBLRPM=$(dirname $0)/cblrpm ;;+ *) CBLRPM=cblrpm ;;+esac +PKG=$1+ WORKDIR=$(mktemp --tmpdir=. -d) cd $WORKDIR -if ! cblrpm -v0 $FORCE_LIB spec ../$FILE; then+if [ ! -r ../$PKG ]; then+ $CBLRPM -v0 $FORCE_LIB spec $PKG+elif ! $CBLRPM -v0 $FORCE_LIB spec ../$PKG; then cd .. rm -r $WORKDIR exit 1@@ -50,7 +57,7 @@ cd .. if [ ! -r "$SPECFILE" ]; then- echo No $SPECFILE file found for $FILE+ echo "No $SPECFILE file found in current directory" rm -r $WORKDIR exit 1 fi
man/cblrpm.1 view
@@ -5,8 +5,9 @@ .SH SYNOPSIS .PP cblrpm [\f[I]options\f[]] spec [\f[I]path\-or\-pkg\f[]] cblrpm-[\f[I]options\f[]] build [\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[]] .SH DESCRIPTION .PP cblrpm generates RPM .spec files from Haskell Cabal package.
man/cblrpm.1.md view
@@ -7,8 +7,9 @@ # SYNOPSIS cblrpm [*options*] spec [*path-or-pkg*]-cblrpm [*options*] build [*path-or-pkg*]+cblrpm [*options*] rpm [*path-or-pkg*] cblrpm [*options*] srpm [*path-or-pkg*]+cblrpm [*options*] install [*path-or-pkg*] # DESCRIPTION cblrpm generates RPM .spec files from Haskell Cabal package.@@ -49,25 +50,27 @@ : Override the version number in the .spec file. # EXAMPLES-Create a .spec file for the Cabal src package in current directory:+Below CMD can be one of: spec, srpm, rpm, and install. - cblrpm spec+Do CMD for the Cabal src package in current directory: -Create a .spec file for package (directory or package name):+ cblrpm CMD++Do CMD for package (directory or package name): - cblrpm spec [package]+ cblrpm CMD [package] -Create a .spec file for package-version (directory or package name):+Do CMD for package-version (directory or package name): - cblrpm spec [package-version]+ cblrpm CMD [package-version] -Create a .spec file for a .cabal file:+Do CMD on a .cabal file: - cblrpm spec path/to/some.cabal+ cblrpm CMD path/to/some.cabal -Create a .spec file from a tarball:+Do CMD for a tarball: - cblrpm spec path/to/pkg-ver.tar.gz+ cblrpm CMD path/to/pkg-ver.tar.gz # HISTORY Cabal-rpm was originally written by Bryan O'Sullivan in 2007-2008
− src/Commands/Build.hs
@@ -1,109 +0,0 @@--- |--- Module : Commands.Build--- Copyright : Bryan O'Sullivan 2007, 2008--- Jens Petersen 2012-2013------ Maintainer : Jens Petersen <petersen@fedoraproject.org>--- Stability : alpha--- Portability : portable------ 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.--module Commands.Build (- rpmBuild- ) where--import Commands.Spec (createSpecFile)-import PackageUtils (packageName, packageVersion,- simplePackageDescription)-import Setup (RpmFlags (..))-import SysCmd (tryReadProcess, trySystem, optionalSudo, systemBool, (+-+))----import Control.Exception (bracket)-import Control.Monad (filterM, liftM, unless, when)--import Distribution.PackageDescription (GenericPackageDescription (..),- PackageDescription (..),- hasExes)----import Distribution.Version (VersionRange, foldVersionRange')--import System.Directory (copyFile, doesFileExist, doesDirectoryExist,- getCurrentDirectory)-import System.Environment (getEnv)-import System.FilePath.Posix (takeDirectory, (</>))---- autoreconf :: Verbosity -> PackageDescription -> IO ()--- autoreconf verbose pkgDesc = do--- ac <- doesFileExist "configure.ac"--- when ac $ do--- c <- doesFileExist "configure"--- when (not c) $ do--- setupMessage verbose "Running autoreconf" pkgDesc--- trySystem "autoreconf"--rpmBuild :: FilePath -> GenericPackageDescription -> RpmFlags -> Bool -> IO ()-rpmBuild cabalPath genPkgDesc flags binary = do--- let verbose = rpmVerbosity flags- pkgDesc <- simplePackageDescription genPkgDesc flags--- bracket (setFileCreationMask 0o022) setFileCreationMask $ \ _ -> do--- autoreconf verbose pkgDesc- specFile <- specFileName pkgDesc flags- specFileExists <- doesFileExist specFile- if specFileExists- then putStrLn $ "Using existing" +-+ specFile- else createSpecFile cabalPath genPkgDesc flags- let pkg = package pkgDesc- name = packageName pkg- when binary $ do- br_out <- tryReadProcess "rpmspec" ["-q", "--buildrequires", specFile]- missing <- filterM notInstalled $ lines br_out- unless (null missing) $ do- putStrLn $ "Installing dependencies:"- mapM_ putStrLn missing- optionalSudo $ "yum install" +-+ (unwords $ map show missing)-- cwd <- getCurrentDirectory- home <- getEnv "HOME"- let version = packageVersion pkg- cachedir = home </> ".cabal/packages/hackage.haskell.org" </> name </> version- tarFile = name ++ "-" ++ version ++ ".tar.gz"- rpmCmd = if binary then "a" else "s"- tarFileExists <- doesFileExist tarFile- unless tarFileExists $ do- let pkgDir = takeDirectory cabalPath- darcsRepo <- doesDirectoryExist $ pkgDir </> "_darcs"- unless darcsRepo $ do- gitRepo <- doesDirectoryExist $ pkgDir </> ".git"- unless (darcsRepo || gitRepo) $ do- trySystem ("cabal fetch -v0 --no-dependencies" +-+ name ++ "-" ++ version)- copyFile (cachedir </> tarFile) (cwd </> tarFile)- tarFileExists' <- doesFileExist tarFile- if tarFileExists'- then trySystem ("rpmbuild -b" ++ rpmCmd +-+- "--define \"_rpmdir" +-+ cwd ++ "\"" +-+- "--define \"_srcrpmdir" +-+ cwd ++ "\"" +-+- "--define \"_sourcedir" +-+ cwd ++ "\"" +-+- specFile)- else error $ "No" +-+ tarFile +-+ "found"- where- notInstalled :: String -> IO Bool- notInstalled br = do- liftM not $ systemBool $ "rpm -q --whatprovides" +-+ (shellQuote br)- shellQuote :: String -> String- shellQuote (c:cs) = (if (elem c "()") then (['\\', c] ++) else (c:)) (shellQuote cs)- shellQuote "" = ""--specFileName :: PackageDescription -- ^pkg description- -> RpmFlags -- ^rpm flags- -> IO FilePath-specFileName pkgDesc flags = do- let pkg = package pkgDesc- name = packageName pkg- pkgname = if isExec then name else "ghc-" ++ name- isExec = if (rpmLibrary flags) then False else hasExes pkgDesc- return $ pkgname ++ ".spec"
+ src/Commands/Install.hs view
@@ -0,0 +1,47 @@+-- |+-- Module : Commands.Install+-- Copyright : Jens Petersen 2012-2013+--+-- Maintainer : Jens Petersen <petersen@fedoraproject.org>+-- Stability : alpha+-- Portability : portable+--+-- 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.++module Commands.Install (+ install+ ) where++import Depends (dependencies)+import PackageUtils (packageName, simplePackageDescription)+import Setup (RpmFlags (..))+import SysCmd (trySystem, systemBool, yumInstall, (+-+))++import Control.Monad (filterM, liftM)++import Distribution.PackageDescription (GenericPackageDescription (..),+ PackageDescription (..))+import System.Directory (setCurrentDirectory)+import System.FilePath.Posix (takeDirectory)++install :: FilePath -> GenericPackageDescription -> RpmFlags -> IO ()+install cabalPath genPkgDesc flags = do+ pkgDesc <- simplePackageDescription genPkgDesc flags+ let pkg = package pkgDesc+ name = packageName pkg+ (deps, tools, clibs, pkgcfgs, _) <- dependencies pkgDesc name+ missing <- filterM notInstalled $ deps ++ tools ++ clibs ++ pkgcfgs+ yumInstall missing+ let pkgDir = takeDirectory cabalPath+ setCurrentDirectory pkgDir+ trySystem "cabal install"+ where+ notInstalled :: String -> IO Bool+ notInstalled br =+ liftM not $ systemBool $ "rpm -q --whatprovides" +-+ shellQuote br+ shellQuote :: String -> String+ shellQuote (c:cs) = (if c `elem` "()" then (['\\', c] ++) else (c:)) (shellQuote cs)+ shellQuote "" = ""
+ src/Commands/RpmBuild.hs view
@@ -0,0 +1,120 @@+-- |+-- Module : Commands.RpmBuild+-- Copyright : Bryan O'Sullivan 2007, 2008+-- Jens Petersen 2012-2013+--+-- Maintainer : Jens Petersen <petersen@fedoraproject.org>+-- Stability : alpha+-- Portability : portable+--+-- 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.++module Commands.RpmBuild (+ rpmBuild+ ) where++import Commands.Spec (createSpecFile)+import PackageUtils (isScmDir, packageName, packageVersion,+ simplePackageDescription)+import Setup (RpmFlags (..))+import SysCmd (tryReadProcess, trySystem, systemBool, yumInstall, (+-+))++--import Control.Exception (bracket)+import Control.Applicative ((<$>))+import Control.Monad (filterM, liftM, unless, when)++import Data.List (isPrefixOf)++import Distribution.PackageDescription (GenericPackageDescription (..),+ PackageDescription (..),+ hasExes)++--import Distribution.Version (VersionRange, foldVersionRange')++import System.Directory (copyFile, doesFileExist,+ getCurrentDirectory, getDirectoryContents)+import System.Environment (getEnv)+import System.FilePath.Posix (takeDirectory, (</>))++-- autoreconf :: Verbosity -> PackageDescription -> IO ()+-- autoreconf verbose pkgDesc = do+-- ac <- doesFileExist "configure.ac"+-- when ac $ do+-- c <- doesFileExist "configure"+-- when (not c) $ do+-- setupMessage verbose "Running autoreconf" pkgDesc+-- trySystem "autoreconf"++rpmBuild :: FilePath -> GenericPackageDescription -> RpmFlags -> Bool -> IO ()+rpmBuild cabalPath genPkgDesc flags binary = do+-- let verbose = rpmVerbosity flags+ pkgDesc <- simplePackageDescription genPkgDesc flags+-- bracket (setFileCreationMask 0o022) setFileCreationMask $ \ _ -> do+-- autoreconf verbose pkgDesc+ specFile <- specFileName pkgDesc flags+ specFileExists <- doesFileExist specFile+ if specFileExists+ then putStrLn $ "Using existing" +-+ specFile+ else createSpecFile cabalPath genPkgDesc flags+ let pkg = package pkgDesc+ name = packageName pkg+ when binary $ do+ br_out <- tryReadProcess "rpmspec" ["-q", "--buildrequires", specFile]+ missing <- filterM notInstalled $ lines br_out+ yumInstall missing++ let version = packageVersion pkg+ tarFile = name ++ "-" ++ version ++ ".tar.gz"+ rpmCmd = if binary then "a" else "s"++ 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)+ where+ notInstalled :: String -> IO Bool+ notInstalled br =+ liftM not $ systemBool $ "rpm -q --whatprovides" +-+ shellQuote br+ shellQuote :: String -> String+ shellQuote (c:cs) = (if c `elem` "()" then (['\\', c] ++) else (c:)) (shellQuote cs)+ 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)++specFileName :: PackageDescription -- ^pkg description+ -> RpmFlags -- ^rpm flags+ -> IO FilePath+specFileName pkgDesc flags = do+ let pkg = package pkgDesc+ name = packageName pkg+ pkgname = if isExec then name else "ghc-" ++ name+ isExec = not (rpmLibrary flags) && hasExes pkgDesc+ return $ pkgname ++ ".spec"
src/Commands/Spec.hs view
@@ -18,16 +18,16 @@ createSpecFile ) where -import PackageUtils (buildDependencies,- depName, packageName, packageVersion,- simplePackageDescription, showDep)+import Depends (dependencies, showDep)+import PackageUtils (isScmDir, packageName, packageVersion,+ simplePackageDescription) import Setup (RpmFlags (..))-import SysCmd ((+-+), tryReadProcess)+import SysCmd ((+-+)) --import Control.Exception (bracket) import Control.Monad (unless, when) import Data.Char (toLower)-import Data.List (groupBy, isPrefixOf, isSuffixOf, nub, sort)+import Data.List (groupBy, isPrefixOf, isSuffixOf, sort) import Data.Maybe (fromMaybe) import Data.Time.Clock (UTCTime, getCurrentTime) import Data.Time.Format (formatTime)@@ -38,18 +38,16 @@ import Distribution.Simple.Utils (warn) import Distribution.PackageDescription (PackageDescription (..), exeName,- hasExes, hasLibs, withExe, allBuildInfo,- BuildInfo (..))+ hasExes, hasLibs, withExe,+ GenericPackageDescription (..)) --import Distribution.Version (VersionRange, foldVersionRange') -import Distribution.PackageDescription (GenericPackageDescription (..)) -import System.Directory (doesDirectoryExist, doesFileExist,- getDirectoryContents)+import System.Directory (doesFileExist, getDirectoryContents) import System.IO (IOMode (..), hClose, hPutStrLn, openFile) import System.Locale (defaultTimeLocale)-import System.FilePath (dropFileName, takeDirectory, (</>))+import System.FilePath (dropFileName, takeDirectory) import qualified Paths_cabal_rpm (version) @@ -57,9 +55,8 @@ defaultRelease :: FilePath -> UTCTime -> IO String defaultRelease cabalPath now = do let pkgDir = takeDirectory cabalPath- darcsRepo <- doesDirectoryExist $ pkgDir </> "_darcs"- gitRepo <- doesDirectoryExist $ pkgDir </> ".git"- return $ if (darcsRepo || gitRepo)+ scmRepo <- isScmDir pkgDir+ return $ if scmRepo then formatTime defaultTimeLocale "0.%Y%m%d" now else "1" @@ -89,11 +86,11 @@ version = packageVersion pkg release = fromMaybe defRelease (rpmRelease flags) specFile = pkgname ++ ".spec"- isExec = if (rpmLibrary flags) then False else hasExes pkgDesc+ isExec = not (rpmLibrary flags) && hasExes pkgDesc isLib = hasLibs pkgDesc isBinLib = isExec && isLib specAlreadyExists <- doesFileExist specFile- let specFilename = specFile ++ if (not $ rpmForce flags) && specAlreadyExists then ".cblrpm" else ""+ let specFilename = specFile ++ if not (rpmForce flags) && specAlreadyExists then ".cblrpm" else "" when specAlreadyExists $ putStrLn $ specFile +-+ "exists:" +-+ "creating" +-+ specFilename h <- openFile specFilename WriteMode let putHdr hdr val = hPutStrLn h (hdr ++ ":" ++ padding hdr ++ val)@@ -111,19 +108,19 @@ let syn = synopsis pkgDesc when (null syn) $ warn verbose "this package has no synopsis."- let syn' = if (null syn)- then ("Haskell" +-+ name +-+ "package")- else (unwords $ lines syn)+ let syn' = if null syn+ then "Haskell" +-+ name +-+ "package"+ else unwords $ lines syn let summary = rstrip (== '.') syn'- when ((length $ "Summary : " ++ syn') > 79) $+ when (length ("Summary : " ++ syn') > 79) $ warn verbose "this package has a long synopsis." let descr = description pkgDesc when (null descr) $ warn verbose "this package has no description." let descLines = (formatParagraphs . lines . finalPeriod) $- if (null descr) then syn' else descr- finalPeriod cs = if (last cs == '.') then cs else cs ++ "."+ if null descr then syn' else descr+ finalPeriod cs = if last cs == '.' then cs else cs ++ "." when isLib $ do putDef "pkg_name" name@@ -139,26 +136,14 @@ putHdr "Source0" $ "http://hackage.haskell.org/packages/archive/" ++ pkg_name ++ "/%{version}/" ++ pkg_name ++ "-%{version}.tar.gz" putNewline putHdr "BuildRequires" "ghc-Cabal-devel"- putHdr "BuildRequires" $ "ghc-rpm-macros"-- let (deps, selfdep) = buildDependencies pkgDesc name- buildinfo = allBuildInfo pkgDesc- excludedTools n = notElem n ["ghc", "hsc2hs", "perl"]- mapTools "gtk2hsC2hs" = "gtk2hs-buildtools"- mapTools "gtk2hsHookGenerator" = "gtk2hs-buildtools"- mapTools "gtk2hsTypeGen" = "gtk2hs-buildtools"- mapTools tool = tool- chrpath = if selfdep then ["chrpath"] else []- tools = filter excludedTools $ nub $ (map (mapTools . depName) $ concat (map buildTools buildinfo)) ++ chrpath- pkgcfgs = nub $ map depName $ concat (map pkgconfigDepends buildinfo)- showPkgCfg p = "pkgconfig(" ++ p ++ ")"+ putHdr "BuildRequires" "ghc-rpm-macros" - clibs <- mapM repoqueryLib $ concat (map extraLibs buildinfo)- when (not . null $ deps ++ tools ++ clibs ++ pkgcfgs) $ do+ (deps, tools, clibs, pkgcfgs, selfdep) <- dependencies pkgDesc name+ unless (null $ deps ++ tools ++ clibs ++ pkgcfgs) $ do put "# Begin cabal-rpm deps:"- let pkgdeps = sort $ map showDep deps ++ tools ++ map (++ "%{?_isa}") clibs ++ map showPkgCfg pkgcfgs+ let pkgdeps = sort $ deps ++ tools ++ clibs ++ pkgcfgs mapM_ (putHdr "BuildRequires") pkgdeps- when (any (\ d -> elem d ["template-haskell", "hamlet"]) deps) $+ when (any (\ d -> d `elem` map showDep ["template-haskell", "hamlet"]) deps) $ putHdr "ExclusiveArch" "%{ghc_arches_with_ghci}" put "# End cabal-rpm deps" @@ -185,10 +170,9 @@ putHdr "Requires(post)" "ghc-compiler = %{ghc_version}" putHdr "Requires(postun)" "ghc-compiler = %{ghc_version}" putHdr "Requires" $ (if isExec then "ghc-%{name}" else "%{name}") ++ "%{?_isa} = %{version}-%{release}"- when (not . null $ clibs ++ pkgcfgs) $ do+ unless (null $ clibs ++ pkgcfgs) $ do put "# Begin cabal-rpm deps:"- mapM_ (putHdr "Requires") $ map (++ "%{?_isa}") clibs- mapM_ (putHdr "Requires") $ map showPkgCfg pkgcfgs+ mapM_ (putHdr "Requires") $ sort $ clibs ++ pkgcfgs put "# End cabal-rpm deps" putNewline put $ "%description" +-+ ghcPkgDevel@@ -215,14 +199,14 @@ putNewline when isLib $ do+ let putInstallScript = do+ put "%ghc_pkg_recache"+ putNewline+ putNewline put $ "%post" +-+ ghcPkgDevel- put "%ghc_pkg_recache"- putNewline- putNewline+ putInstallScript put $ "%postun" +-+ ghcPkgDevel- put "%ghc_pkg_recache"- putNewline- putNewline+ putInstallScript docs <- findDocs cabalPath pkgDesc @@ -293,15 +277,19 @@ showLicense (Apache Nothing) = "ASL ?" showLicense (Apache (Just ver)) = "ASL" +-+ showVersion ver #endif+#if MIN_VERSION_Cabal(1,18,0)+showLicense (AGPL Nothing) = "AGPLv?"+showLicense (AGPL (Just ver)) = "AGPLv" ++ showVersion ver+#endif -- from http://stackoverflow.com/questions/930675/functional-paragraphs -- using split would be: map unlines . (Data.List.Split.splitWhen null) paragraphs :: [String] -> [String]-paragraphs = map unlines . map (filter $ not . null) . groupBy (const $ not . null)+paragraphs = map (unlines . filter (not . null)) . groupBy (const $ not . null) -- http://rosettacode.org/wiki/Word_wrap#Haskell wordwrap :: Int -> String -> String-wordwrap maxlen = (wrap_ 0 False) . words where+wordwrap maxlen = wrap_ 0 False . words where wrap_ _ _ [] = "\n" wrap_ pos eos (w:ws) -- at line start: put down the word no matter what@@ -314,13 +302,3 @@ formatParagraphs :: [String] -> [String] formatParagraphs = map (wordwrap 79) . paragraphs--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 view
@@ -0,0 +1,68 @@+-- |+-- 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
@@ -14,7 +14,8 @@ module Main where -import Commands.Build (rpmBuild)+import Commands.Install (install)+import Commands.RpmBuild (rpmBuild) import Commands.Spec (createSpecFile) import Setup (RpmFlags (..), parseArgs) import SysCmd (tryReadProcess, trySystem)@@ -45,9 +46,11 @@ case cmd of "spec" -> createSpecFile cabalPath genPkgDesc opts "srpm" -> rpmBuild cabalPath genPkgDesc opts False- "build" -> rpmBuild cabalPath genPkgDesc opts True+ "rpm" -> rpmBuild cabalPath genPkgDesc opts True+ "install" -> install cabalPath genPkgDesc opts+-- "builddep" -> +-- "depends" -> -- "install" ->--- "builddep" -> -- "showdeps" -> c -> error $ "Unknown cmd: " ++ c maybe (return ()) removeDirectoryRecursive mtmp@@ -77,13 +80,12 @@ else do isfile <- doesFileExist path if not isfile- then if (isJust $ matchRegex pkg_re path)- then do- tryUnpack path+ then if isJust $ matchRegex pkg_re path+ then tryUnpack path else error $ path ++ ": No such file or directory" else if takeExtension path == ".cabal" then return (path, Nothing)- else if isSuffixOf ".tar.gz" path+ else if ".tar.gz" `isSuffixOf` path then do tmpdir <- mktempdir trySystem $ "tar zxf " ++ path ++ " -C " ++ tmpdir ++ " *.cabal"@@ -95,11 +97,11 @@ tryUnpack :: String -> IO (FilePath, Maybe FilePath) tryUnpack pkg = do- pkgver <- if elem '.' pkg then return pkg+ pkgver <- if '.' `elem` pkg then return pkg else do contains_pkg <- tryReadProcess "cabal" ["list", "--simple-output", pkg]- let pkgs = filter ((== pkg) . fst . break (== ' ')) $ lines contains_pkg- if (null pkgs)+ let pkgs = filter ((== pkg) . takeWhile (not . (== ' '))) $ lines contains_pkg+ if null pkgs then error $ pkg ++ " hackage not found" else return $ map (\c -> if c == ' ' then '-' else c) $ last pkgs isdir <- doesDirectoryExist pkgver
src/PackageUtils.hs view
@@ -12,22 +12,19 @@ -- the GNU General Public License, incorporated herein by reference. module PackageUtils (- buildDependencies,- depName,+ isScmDir, packageName, packageVersion,- simplePackageDescription,- showDep+ simplePackageDescription ) where import Setup (RpmFlags (..)) -import Data.List (nub) import Data.Version (showVersion) import Distribution.Compiler (CompilerFlavor (..)) -import Distribution.Package (Dependency (..), PackageIdentifier (..),+import Distribution.Package (PackageIdentifier (..), PackageName (..)) import Distribution.PackageDescription (GenericPackageDescription (..), PackageDescription (..))@@ -41,6 +38,9 @@ import Distribution.System (Platform (..), buildArch, buildOS) +import System.Directory (doesDirectoryExist)+import System.FilePath.Posix ((</>))+ simplePackageDescription :: GenericPackageDescription -> RpmFlags -> IO PackageDescription simplePackageDescription genPkgDesc flags = do@@ -58,17 +58,13 @@ where PackageName name = pkgName pkg packageVersion :: PackageIdentifier -> String-packageVersion pkg = (showVersion . pkgVersion) pkg---- 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, elem self deps)+packageVersion = showVersion . pkgVersion -depName :: Dependency -> String-depName (Dependency (PackageName n) _) = n+(<||>) :: IO Bool -> IO Bool -> IO Bool+(<||>) f s = do+ one <- f+ if one then return True else s -showDep :: String -> String-showDep p = "ghc-" ++ p ++ "-devel"+isScmDir :: FilePath -> IO Bool+isScmDir dir =+ doesDirectoryExist (dir </> ".git") <||> doesDirectoryExist (dir </> "_darcs")
src/Setup.hs view
@@ -91,8 +91,8 @@ ++ "Commands:\n" ++ " spec\t generate a spec file\n" ++ " srpm\t generate a src rpm file\n"- ++ " build\t build rpm package\n"--- ++ " install\t install rpm package\n"+ ++ " rpm\t build rpm package\n"+ ++ " install user install package\n" -- ++ " mock\t mock build package\n" ++ "\n" ++ "Options:"@@ -106,7 +106,7 @@ printHelp stdout exitSuccess when (rpmVersion opts) $ do- hPutStrLn stdout $ showVersion version+ putStrLn $ showVersion version exitSuccess unless (null errs) $ do hPutStrLn stderr "Error:"@@ -116,7 +116,7 @@ hPutStr stderr "Unrecognised options: " hPutStrLn stderr $ unwords unknown exitWith (ExitFailure 1)- when ((null args') || (notElem (head args') ["spec", "srpm", "build", "install"])) $ do+ when (null args' || notElem (head args') ["spec", "srpm", "rpm", "install"]) $ do printHelp stderr exitWith (ExitFailure 1) when (length args' > 2) $ do
src/SysCmd.hs view
@@ -16,16 +16,17 @@ requireProgram, trySystem, tryReadProcess,- optionalSudo, systemBool,+ yumInstall, (+-+)) where -import Control.Monad (when)+import Control.Monad (when, unless) import Data.Maybe (isJust, isNothing) import Distribution.Simple.Utils (die, warn, findProgramLocation) import Distribution.Verbosity (normal) +import System.Posix.User (getEffectiveUserID) import System.Process (readProcess, system) import System.Exit (ExitCode(..)) @@ -40,22 +41,6 @@ when (isNothing mavail) $ warn normal (cmd ++ ": command not found") return $ isJust mavail -optionalSudo :: String -> IO ()-optionalSudo cmd = do- havesudo <- optionalProgram "sudo"- when havesudo $ do- let argv = words cmd- cmd0 = head argv - mavail <- findProgramLocation normal cmd0- case mavail of- Nothing -> warn normal $ cmd0 ++ ": command not found"- Just _ -> do- putStrLn $ "Running:" +-+ "sudo" +-+ cmd- ret <- system $ "sudo" +-+ cmd- case ret of- ExitSuccess -> return ()- ExitFailure n -> warn normal ("\"" ++ cmd ++ "\"" +-+ "failed with status" +-+ show n)- trySystem :: String -> IO () trySystem cmd = do requireProgram $ head $ words cmd@@ -82,3 +67,22 @@ s +-+ "" = s s +-+ t = s ++ " " ++ t +yumInstall :: [String] -> IO ()+yumInstall pkgs =+ unless (null pkgs) $ do+ putStrLn "Uninstalled dependencies:"+ mapM_ putStrLn pkgs+ uid <- getEffectiveUserID+ cmdprefix <-+ if uid == 0+ then return ""+ else do+ havesudo <- optionalProgram "sudo"+ return $ if havesudo then "sudo" else ""+ requireProgram "yum"+ let args = unwords $ map showPkg pkgs+ putStrLn $ "Running:" +-+ cmdprefix +-+ "yum install" +-+ args+ trySystem $ cmdprefix +-+ "yum install" +-+ args++showPkg :: String -> String+showPkg p = if '(' `elem` p then show p else p