cabal-rpm 2.1.5 → 2.2.0
raw patch · 10 files changed
+115/−136 lines, 10 files
Files
- ChangeLog +10/−0
- README.md +3/−3
- TODO +7/−3
- cabal-rpm.cabal +15/−13
- man/cabal-rpm.1.md +0/−94
- src/Commands/Spec.hs +44/−14
- src/Dependencies.hs +14/−4
- src/Main.hs +3/−2
- src/PackageUtils.hs +18/−2
- src/Stackage/Snapshots.hs +1/−1
ChangeLog view
@@ -1,3 +1,13 @@+# 2.2.0 (2024-03-27)+- Dependencies excludedPkgs: add system-cxx-std-lib+- Dependencies: withGhcProfLibType to respect %with_ghc_prof for builddeps+- PackageUtils dependencySortCabals: do nothing if empty+- Snapshots: update stackage snapshots.json url+- Spec: usesOptparse, maybeGenerateBashCompletion, maybeGenerateManpage+- spec: add %{?haskell_setup}+- spec: define and use %ghc_major for --with-compiler+- spec: do not BR ghcX.Y-prof for standalone+ # 2.1.5 (2023-11-10) - bugfix: --flags should be optional! - PackageUtils pkgSpecPkgData: error displaying an unparsable pkgid
README.md view
@@ -71,15 +71,15 @@ ## Help output `$ cabal-rpm --version` ```-2.1.5+2.2.0 ``` `$ cabal-rpm --help` ```-Cabal-rpm tool+Tool to create RPM packages from Haskell Hackage/Stackage Usage: cabal-rpm [--version] COMMAND - RPM package tool for Haskell Stackage/Hackage packages+ See https://github.com/juhp/cabal-rpm#readme Available options: -h,--help Show this help text
TODO view
@@ -1,3 +1,7 @@+- write the complete spec file atomically+ - with Writer monad to avoid writing empty spec+- respect bounds when querying subpackages+ - 'install' in empty package dir fails (have to local or spec first) - 'install' in a source dir: "package not found for directory" - maybe just run "cabal install" for executable?@@ -79,11 +83,10 @@ - revisions of subpackages - use Set for deps? -write the complete spec file atomically- ## Misc ? run "cabal update" if package-version not found-- use <> instead of +++- add individual command help pages+- use shelly for easy tracing? # Commands - fetch@@ -98,6 +101,7 @@ - --releasever option (for repoquery) - --no-revision - add demo/ & example[s]/ to doc subpackage (gtk2hs)+- replace --flag with --enable/disable? ## version ranges - warn about missing dependencies/versions
cabal-rpm.cabal view
@@ -1,18 +1,21 @@ Cabal-version: 1.18 Name: cabal-rpm-Version: 2.1.5+Version: 2.2.0 Synopsis: RPM packaging tool for Haskell Cabal-based packages Description:- This package provides a RPM packaging tool for Haskell Cabal-based packages.+ This package provides a RPM packaging tool for Haskell Cabal-based+ packages. . cabal-rpm has commands to generate a RPM spec file and srpm for a package.- It can rpmbuild packages, yum/dnf install their dependencies, prep packages,- and install them. There are commands to list package dependencies and- missing dependencies. The diff command compares the current spec file with- a freshly generated one, the update command updates the spec file to latest- version from Stackage or Hackage, and the refresh command updates the spec- file to the current cabal-rpm packaging. It also handles Hackage revisions- of packages. Standalone packages can also be made, built with cabal-install.+ It can rpmbuild packages, dnf/yum install their dependencies,+ prep packages, and install them.+ There are commands to list package dependencies and missing dependencies.+ The diff command compares the current spec file with a freshly generated+ one,+ the update command updates the spec file to latest version from Stackage+ or Hackage, and the refresh command updates the spec file to the current+ cabal-rpm packaging. It also handles Hackage revisions of packages.+ Standalone packages can also be made, built with cabal-install. Homepage: https://github.com/juhp/cabal-rpm Bug-reports: https://github.com/juhp/cabal-rpm/issues License: GPL-3@@ -21,15 +24,14 @@ Bryan O'Sullivan <bos@serpentine.com> Maintainer: Jens Petersen <petersen@fedoraproject.org> Copyright: 2007-2008 Bryan O'Sullivan <bos@serpentine.com>,- 2012-2023 Jens Petersen <juhpetersen@gmail.com>+ 2012-2024 Jens Petersen <juhpetersen@gmail.com> Category: Distribution Build-type: Simple Extra-doc-files: ChangeLog README.md TODO-Extra-source-files: man/cabal-rpm.1.md Tested-with: GHC == 8.0.2, GHC == 8.2.2, GHC == 8.4.4, GHC == 8.6.5, GHC == 8.8.4, GHC == 8.10.7,- GHC == 9.0.2, GHC == 9.2.8, GHC == 9.4.7,- GHC == 9.6.3+ GHC == 9.0.2, GHC == 9.2.8, GHC == 9.4.8,+ GHC == 9.6.4, GHC == 9.8.2 source-repository head type: git
− man/cabal-rpm.1.md
@@ -1,94 +0,0 @@-% CABAL-RPM(1)-% This manpage was written by Jens Petersen-% 2013-01-21--# NAME-cabal-rpm - a RPM packaging tool for Haskell Cabal packages--# SYNOPSIS-cabal-rpm [*options*] spec [*path-or-pkg*]\-cabal-rpm [*options*] local [*path-or-pkg*]\-cabal-rpm [*options*] srpm [*path-or-pkg*]\-cabal-rpm [*options*] prep [*path-or-pkg*]\-cabal-rpm [*options*] builddep [*path-or-pkg*]\-cabal-rpm [*options*] install [*path-or-pkg*]\-cabal-rpm [*options*] depends [*path-or-pkg*]\-cabal-rpm [*options*] requires [*path-or-pkg*]\-cabal-rpm [*options*] missingdeps [*path-or-pkg*]\-cabal-rpm [*options*] diff [*path-or-pkg*]\-cabal-rpm [*options*] update [*path-or-pkg*\]\-cabal-rpm [*options*] refresh [*path-or-pkg*]--# DESCRIPTION-cabal-rpm generates RPM packages and .spec files from Haskell Cabal package.--If no *path-or-pkg* is specified, cabal-rpm looks for a .spec or .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 .spec or .cabal file.-If the argument is a path to a .cabal file then it will use it.-Otherwise if there is no '/' in the argument and it does not exist-then cabal-rpm will try to unpack the package and use its .cabal file.-cabal-rpm uses a temporary directory for unpackaging tarballs or packages.-cabal-rpm then parses the .cabal file and uses it to generate a .spec file-that can be built.--If a <PKG>.spec already exists, cabal-rpm outputs to <PKG>.spec.cblrpm instead.--# OPTIONS--h, --help-: Show the help text.---b, --binary-: Force the base package name to be the Hackage package name.---f *FLAGS*, --flags=*FLAGS*-: Override one or more Cabal build configuration flags.----force-: overwrite existing spec file----missing-: comment out unavailable BuildRequires deps----release=*RELEASE*-: Override the release number in the .spec file.----standalone-: create a standalone package, built using cabal-install---s *STREAM* , --stream=*STREAM*-: Stackage stream (eg lts-13) or 'hackage' used to get package version.---v *N*, --verbose=*N*-: Set verbosity to *N*.----version=*VERSION*-: Override the version number in the .spec file.--# EXAMPLES-Below CMD can be one of:- spec, srpm, prep, local, install, diff, builddep, depends, requires,- missingdeps, update, refresh--Do CMD for the package in current directory:-- cabal-rpm CMD--Do CMD for package (directory or package name):- - cabal-rpm CMD [package]--Do CMD for package-version (directory or package name):-- cabal-rpm CMD [package-version]--Do CMD on a .cabal file:-- cabal-rpm CMD path/to/some.cabal--# HISTORY-Cabal-rpm was originally written by Bryan O'Sullivan in 2007-2008-and resurrected by Jens Petersen in 2012 to replace cabal2spec.--# SEE ALSO-<http://github.com/juhp/cabal-rpm/>
src/Commands/Spec.hs view
@@ -26,7 +26,8 @@ prettyShow, recurseMissing, subPackages, testsuiteDependencies') import Header (headerOption, withSpecHead)-import PackageUtils (dependencySortCabals, PackageData (..), prepare)+import PackageUtils (dependencySortCabals, PackageData (..), prepare,+ packageMacro) import SimpleCabal (buildable, mkPackageName, PackageDescription (..), PackageIdentifier(..)) import SimpleCmd ((+-+), cmd, cmdLines, cmdMaybe, grep, grep_, removePrefix)@@ -204,8 +205,9 @@ put "# https://docs.fedoraproject.org/en-US/packaging-guidelines/Haskell/" putNewline - when (isJust mwithghc) $ do- global "ghc_name" ghcname+ whenJust mwithghc $ \withghc -> do+ global "ghc_major" $ majorVer withghc+ global "ghc_name" "ghc%{ghc_major}" putNewline -- Some packages conflate the synopsis and description fields. Ugh.@@ -261,6 +263,7 @@ when hasLib $ do global "pkg_name" name global "pkgver" "%{pkg_name}-%{version}"+ put "%{?haskell_setup}" putNewline let pkgver = if hasLib then "%{pkgver}" else pkg_name ++ "-%{version}"@@ -276,7 +279,7 @@ subpkgsOrdered <- dependencySortCabals mspec $ map fst missingLibsLicenses --print subpkgs let subpkgs = sort subpkgsOrdered- mkSubpkgMacro = filter (/= '-') . display . pkgName+ mkSubpkgMacro = packageMacro . display . pkgName subpkgMacro pid = "%{" ++ mkSubpkgMacro pid ++ "}" subpkgMacros = map subpkgMacro subpkgs subpkgMacrosOrdered = map subpkgMacro subpkgsOrdered@@ -310,9 +313,11 @@ let local = display pkgid <.> "cabal" have <- doesFileExist local if have then grep_ "x-revision" local else return False- revisedDOS <- if revised then do- filetype <- cmd "file" ["-b", display pkgid <.> "cabal"]- return $ "CRLF" `isInfixOf` filetype+ revisedDOS <-+ if revised+ then do+ filetype <- cmd "file" ["-b", display pkgid <.> "cabal"]+ return $ "CRLF" `isInfixOf` filetype else return False putHdr "Name" (if binlib then "%{pkg_name}" else basename)@@ -350,7 +355,8 @@ when (isJust mwithghc) $ do put "%if %{defined ghc_name}" putHdr "BuildRequires" $ "%{ghc_name}" ++ "-devel"- putHdr "BuildRequires" $ "%{ghc_name}" ++ "-prof"+ unless standalone $+ putHdr "BuildRequires" $ "%{ghc_name}" ++ "-prof" put "%else" let metaPackages = [mkPackageName "haskell-gi-overloading"]@@ -373,7 +379,9 @@ when (isJust mwithghc) $ put "%endif"-+ let usesOptparse = hasExecPkg && any ((`elem` buildDeps pkgdeps) . mkPackageName) ["optparse-applicative","optparse-simple","simple-cmd-args"]+ when usesOptparse $+ putHdr "BuildRequires" "help2man" let common = binlib && datafiles /= [] && not standalone versionRelease = " = %{version}-%{release}" when common $@@ -525,7 +533,7 @@ put "mkdir -p %{buildroot}%{_bindir}" put "%if 0%{?fedora} || 0%{?rhel} >= 9" put "%ghc_set_gcc_flags"- put $ "%cabal_install install" +-+ maybe "" (\v -> "-w ghc-" ++ V.showVersion v) mwithghc +-+ "--install-method=copy --enable-executable-stripping --installdir=%{buildroot}%{_bindir}"+ put $ "%cabal_install install" +-+ (if isJust mwithghc then "-w ghc-%{ghc_major}" else "") +-+ "--install-method=copy --enable-executable-stripping --installdir=%{buildroot}%{_bindir}" put "%else" put "for i in .cabal-sandbox/bin/*; do" put "strip -s -o %{buildroot}%{_bindir}/$(basename $i) $i"@@ -553,11 +561,32 @@ let execs = sort $ map exeName $ filter isBuildable $ executables pkgDesc execNaming p = let pn = unUnqualComponentName p in if pn == name then "%{name}" else pn- bashCompletions = hasExecPkg && any ((`elem` buildDeps pkgdeps) . mkPackageName) ["optparse-applicative","optparse-simple","simple-cmd-args"]+ -- FIXME check for included file+ maybeGenerateBashCompletion exn = do+ put $ "outfile=%{buildroot}%{_datadir}/bash-completion/completions" </> exn+ put "if [ ! -e $outfile ]; then"+ put $ " " ++ "%{buildroot}%{_bindir}" </> exn +-+ "--bash-completion-script" +-+ exn +-+ "| sed s/filenames/default/ > $outfile"+ put "else"+ put " echo \"$outfile exists!\"; exit 1"+ put "fi"+ -- FIXME check for included file+ maybeGenerateManpage exn = do+ put $ "outfile=%{buildroot}%{_mandir}/man1" </> exn <.> "1"+ put "if [ ! -e $outfile ]; then"+ put $ " help2man --no-info %{buildroot}%{_bindir}" </> exn +-+ "> $outfile"+ put "else"+ put " echo \"$outfile exists!\"; exit 1"+ put "fi" - when bashCompletions $ do+ when usesOptparse $ do+ putNewline put "mkdir -p %{buildroot}%{_datadir}/bash-completion/completions/"- mapM_ (\ex -> let exn = execNaming ex in put ("%{buildroot}%{_bindir}" </> exn ++ " --bash-completion-script " ++ exn ++ " | sed s/filenames/default/ > %{buildroot}%{_datadir}/bash-completion/completions" </> exn)) execs+ -- FIXME convert to for loop+ mapM_ (maybeGenerateBashCompletion . execNaming) execs+ putNewline+ put "mkdir -p %{buildroot}%{_mandir}/man1/"+ -- FIXME convert to for loop+ mapM_ (maybeGenerateManpage . execNaming) execs put "# End cabal-rpm install" sectionNewline@@ -583,8 +612,9 @@ mapM_ (put . ("%{_bindir}" </>) . execNaming) execs unless (common || null datafiles) $ put $ "%{_datadir}" </> pkgver- when bashCompletions $+ when usesOptparse $ do mapM_ (put . ("%{_datadir}/bash-completion/completions" </>) . execNaming) execs+ mapM_ (put . (\e -> "%{_mandir}/man1" </> e <.> "1*") . execNaming) execs put "# End cabal-rpm files" sectionNewline
src/Dependencies.hs view
@@ -38,6 +38,7 @@ ) where import PackageUtils (PackageData(..), prepare, repoquery, rpmInstall)+import SysCmd (rpmEval) import Types import SimpleCabal (allLibraries, buildDependencies, mkPackageName,@@ -62,7 +63,7 @@ import Control.Monad (filterM, when, unless) import Data.List (delete, isSuffixOf, nub, (\\))-import Data.Maybe (catMaybes, fromJust, isNothing, mapMaybe)+import Data.Maybe (catMaybes, fromJust, isJust, isNothing, mapMaybe) #if !MIN_VERSION_Cabal(2,2,0) import Distribution.License (License (..))@@ -82,7 +83,7 @@ excludedPkgs :: PackageName -> Bool excludedPkgs =- flip notElem $ map mkPackageName ["ghc-prim", "integer-gmp"]+ flip notElem $ map mkPackageName ["ghc-prim", "integer-gmp", "system-cxx-std-lib"] pkgSuffix :: LibPkgType -> String pkgSuffix lpt =@@ -208,7 +209,10 @@ uninstalledLibraries :: Bool -> PackageDescription -> IO [PackageName] uninstalledLibraries hasLibPkg pkgDesc = do pkgdeps <- packageDependencies pkgDesc- let libType = if hasLibPkg then Prof else Devel+ libType <-+ if hasLibPkg+ then withGhcProfLibType+ else return Devel bdeps <- filterM (notInstalled . RpmHsLib libType) $ buildDeps pkgdeps sdeps <- filterM (notInstalled . RpmHsLib Devel) $ (mkPackageName "Cabal" : setupDeps pkgdeps) \\ buildDeps pkgdeps return $ bdeps ++ sdeps@@ -288,7 +292,8 @@ -- fedora <- rpmEval "%fedora" -- let nogpgcheck = ["--nogpgcheck" | fedora `elem` []] noMacros <- notInstalled (RpmOther "ghc-rpm-macros")- rpmInstall True $ map (showRpm . RpmHsLib Prof) repopkgs ++ ["ghc-rpm-macros" | noMacros]+ libtype <- withGhcProfLibType+ rpmInstall True $ map (showRpm . RpmHsLib libtype) repopkgs ++ ["ghc-rpm-macros" | noMacros] return missing' where repoqueryPackageConf :: String -> PackageName -> IO (Maybe PackageName)@@ -296,6 +301,11 @@ let key = pkgconfd </> display pkg ++ "-[0-9]*.conf" res <- repoquery ["--qf", "%{name}"] key return $ if null res then Nothing else Just pkg++withGhcProfLibType :: IO LibPkgType+withGhcProfLibType = do+ with_ghc_prof <- rpmEval "{?with_ghc_prof}"+ return $ if isJust with_ghc_prof then Prof else Devel showDep :: RpmPackage -> String showDep (RpmHsLib _ n) = display n
src/Main.hs view
@@ -53,8 +53,9 @@ main :: IO () main = do hSetBuffering stdout LineBuffering- simpleCmdArgs (Just version) "Cabal-rpm tool"- "RPM package tool for Haskell Stackage/Hackage packages" $+ simpleCmdArgs (Just version)+ "Tool to create RPM packages from Haskell Hackage/Stackage"+ "See https://github.com/juhp/cabal-rpm#readme" $ subcommands [ Subcommand "spec" "Generate a spec file" $ createSpecFile_
src/PackageUtils.hs view
@@ -33,7 +33,9 @@ repoquery, rpmbuild, rpmInstall,- RpmStage (..)+ RpmStage (..),+ packageMacro,+ readGlobalMacro ) where import FileUtils (assertFileNonEmpty, filesWithExtension, fileWithExtension,@@ -42,7 +44,7 @@ PackageDescription, PackageIdentifier(..), PackageName, showPkgId, tryFindPackageDesc) import SimpleCmd (cmd, cmd_, cmdBool, cmdIgnoreErr, cmdLines,- cmdStderrToStdoutIn, error', grep_,+ cmdStderrToStdoutIn, error', grep, grep_, removePrefix, sudo, sudo_, (+-+)) import SimpleCmd.Git (isGitDir, grepGitConfig) import SimpleCmd.Rpm (rpmspec)@@ -523,6 +525,7 @@ dependencySortCabals :: Maybe FilePath -> [PackageIdentifier] -> IO [PackageIdentifier]+dependencySortCabals _ [] = return [] dependencySortCabals mspec pkgids = do cabalsort <- optionalProgram "cabal-sort" if cabalsort@@ -537,3 +540,16 @@ else do mapM_ (`bringTarball` mspec) pkgids return pkgids++readGlobalMacro :: String -> FilePath -> IO (Maybe String)+readGlobalMacro macro spec = do+ ps <- grep ("%global" +-+ macro ++ " ") spec+ return $+ case ps of+ [] -> Nothing+ [m] -> Just $ last $ words m+ _ -> error' $+ "multiple %" ++ macro +-+ "definitions in" +-+ spec++packageMacro :: String -> String+packageMacro = filter (/= '-')
src/Stackage/Snapshots.hs view
@@ -22,7 +22,7 @@ getSnapshots :: IO Object getSnapshots =- getCachedJSON "stackage-snapshots" "snapshots.json" "http://haddock.stackage.org/snapshots.json" 200+ getCachedJSON "stackage-snapshots" "snapshots.json" "https://www.stackage.org/download/snapshots.json" 200 latestLTS :: IO MajorVer latestLTS = do