cabal-rpm 0.12 → 0.12.1
raw patch · 13 files changed
+221/−233 lines, 13 files
Files
- ChangeLog +9/−1
- cabal-rpm.cabal +2/−2
- man/cabal-rpm.1 +27/−26
- man/cabal-rpm.1.md +24/−24
- src/Commands/Depends.hs +0/−2
- src/Commands/Diff.hs +1/−1
- src/Commands/Install.hs +13/−15
- src/Commands/RpmBuild.hs +8/−13
- src/Commands/Spec.hs +24/−53
- src/Dependencies.hs +46/−8
- src/Main.hs +21/−25
- src/Options.hs +5/−1
- src/PackageUtils.hs +41/−62
ChangeLog view
@@ -1,3 +1,11 @@+* 0.12.1 (2018-02-20)+- new option --missing: comments out missing dependencies+- put license files in lib subpackage+- no longer append %_isa to C BuildRequires (#54)+- no longer leave leftover tmpdirs (#26)+- change 'cblrpm' to 'cabal-rpm' in documentation+- drop support for SCM snapshot releases+ * 0.12 (2017-11-17) - default to querying stackage.org directly via https - fix stackage-query usage and suggest installing if missing@@ -9,7 +17,7 @@ - allow building with ghc-8.2 and Cabal-2.0 * 0.11.2 (2017-07-31)-- fix cblrpm update --subpackage+- fix cabal-rpm update --subpackage - fix rpm installation when no sudo (#49) - fix handling of no exposed modules (#50) - fix license handling for selfdep binlib (#51)
cabal-rpm.cabal view
@@ -1,10 +1,10 @@ Name: cabal-rpm-Version: 0.12+Version: 0.12.1 Synopsis: RPM packaging tool for Haskell Cabal-based packages Description: This package provides a RPM packaging tool for Haskell Cabal-based packages. .- cblrpm has commands to generate a RPM spec file and srpm for a package.+ 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
man/cabal-rpm.1 view
@@ -1,43 +1,44 @@-.\" Automatically generated by Pandoc 1.19.1+.\" Automatically generated by Pandoc 1.19.2.4 .\"-.TH "CBLRPM" "1" "2013\-01\-21" "" ""+.TH "CABAL\-RPM" "1" "2013\-01\-21" "" "" .hy .SH NAME .PP-cblrpm \- a RPM packaging tool for Haskell Cabal packages+cabal\-rpm \- 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[]] local [\f[I]path\-or\-pkg\f[]] cblrpm-[\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[]] cblrpm-[\f[I]options\f[]] missingdeps [\f[I]path\-or\-pkg\f[]] cblrpm-[\f[I]options\f[]] diff [\f[I]path\-or\-pkg\f[]] cblrpm-[\f[I]options\f[]] update [\f[I]path\-or\-pkg\f[]] cblrpm+cabal\-rpm [\f[I]options\f[]] spec [\f[I]path\-or\-pkg\f[]] cabal\-rpm+[\f[I]options\f[]] local [\f[I]path\-or\-pkg\f[]] cabal\-rpm+[\f[I]options\f[]] srpm [\f[I]path\-or\-pkg\f[]] cabal\-rpm+[\f[I]options\f[]] prep [\f[I]path\-or\-pkg\f[]] cabal\-rpm+[\f[I]options\f[]] builddep [\f[I]path\-or\-pkg\f[]] cabal\-rpm+[\f[I]options\f[]] install [\f[I]path\-or\-pkg\f[]] cabal\-rpm+[\f[I]options\f[]] depends [\f[I]path\-or\-pkg\f[]] cabal\-rpm+[\f[I]options\f[]] requires [\f[I]path\-or\-pkg\f[]] cabal\-rpm+[\f[I]options\f[]] missingdeps [\f[I]path\-or\-pkg\f[]] cabal\-rpm+[\f[I]options\f[]] diff [\f[I]path\-or\-pkg\f[]] cabal\-rpm+[\f[I]options\f[]] update [\f[I]path\-or\-pkg\f[]] cabal\-rpm [\f[I]options\f[]] refresh [\f[I]path\-or\-pkg\f[]] .SH DESCRIPTION .PP-cblrpm generates RPM packages and .spec files from Haskell Cabal+cabal\-rpm 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 .spec or-\&.cabal file in the current directory.+If no \f[I]path\-or\-pkg\f[] is specified, cabal\-rpm looks for a .spec+or .cabal 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 .spec or \&.cabal file. If the argument is a path to a .cabal 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+exist then cabal\-rpm will try to unpack the package and use its .cabal file.-cblrpm uses a temporary directory for unpackaging tarballs or packages.-cblrpm then parses the .cabal file and uses it to generate a .spec file-that can be built.+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. .PP-If a .spec already exists, cblrpm outputs to .spec.cblrpm instead.+If a .spec already exists, cabal\-rpm outputs to .spec.cblrpm instead. .SH OPTIONS .TP .B \-h, \-\-help@@ -78,7 +79,7 @@ .IP .nf \f[C]-cblrpm\ CMD+cabal\-rpm\ CMD \f[] .fi .PP@@ -86,7 +87,7 @@ .IP .nf \f[C]-cblrpm\ CMD\ [package]+cabal\-rpm\ CMD\ [package] \f[] .fi .PP@@ -94,7 +95,7 @@ .IP .nf \f[C]-cblrpm\ CMD\ [package\-version]+cabal\-rpm\ CMD\ [package\-version] \f[] .fi .PP@@ -102,7 +103,7 @@ .IP .nf \f[C]-cblrpm\ CMD\ path/to/some.cabal+cabal\-rpm\ CMD\ path/to/some.cabal \f[] .fi .SH HISTORY
man/cabal-rpm.1.md view
@@ -1,38 +1,38 @@-% CBLRPM(1)+% CABAL-RPM(1) % This manpage was written by Jens Petersen % 2013-01-21 # NAME-cblrpm - a RPM packaging tool for Haskell Cabal packages+cabal-rpm - a RPM packaging tool for Haskell Cabal packages # SYNOPSIS-cblrpm [*options*] spec [*path-or-pkg*]-cblrpm [*options*] local [*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*]-cblrpm [*options*] missingdeps [*path-or-pkg*]-cblrpm [*options*] diff [*path-or-pkg*]-cblrpm [*options*] update [*path-or-pkg*]-cblrpm [*options*] refresh [*path-or-pkg*]+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-cblrpm generates RPM packages and .spec files from Haskell Cabal package.+cabal-rpm generates RPM packages and .spec files from Haskell Cabal package. -If no *path-or-pkg* is specified, cblrpm looks for a .spec or .cabal file+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 cblrpm will try to unpack the package and use its .cabal file.-cblrpm uses a temporary directory for unpackaging tarballs or packages.-cblrpm then parses the .cabal file and uses it to generate a .spec file+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, cblrpm outputs to <PKG>.spec.cblrpm instead.+If a <PKG>.spec already exists, cabal-rpm outputs to <PKG>.spec.cblrpm instead. # OPTIONS -h, --help@@ -60,19 +60,19 @@ Do CMD for the package in current directory: - cblrpm CMD+ cabal-rpm CMD Do CMD for package (directory or package name): - cblrpm CMD [package]+ cabal-rpm CMD [package] Do CMD for package-version (directory or package name): - cblrpm CMD [package-version]+ cabal-rpm CMD [package-version] Do CMD on a .cabal file: - cblrpm CMD path/to/some.cabal+ cabal-rpm CMD path/to/some.cabal # HISTORY Cabal-rpm was originally written by Bryan O'Sullivan in 2007-2008
src/Commands/Depends.hs view
@@ -28,7 +28,6 @@ #endif import Control.Monad (filterM, unless, void) import Data.List (nub, sort, (\\))-import System.Directory (removeDirectoryRecursive) data Depends = Depends | Requires | Missing @@ -69,7 +68,6 @@ missingDepsPkg :: String -> IO [String] missingDepsPkg pkg = do pkgdata <- prepare quiet (Just pkg)- maybe (return ()) removeDirectoryRecursive $ workingDir pkgdata missingPackages (packageDesc pkgdata) >>= filterM notAvail putMissing :: String -> [String] -> [String] -> IO ()
src/Commands/Diff.hs view
@@ -6,7 +6,7 @@ -- Stability : alpha -- Portability : portable ----- Explanation: diff current spec file with cblrpm spec output+-- Explanation: diff current spec file with cabal-rpm spec output -- 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
src/Commands/Install.hs view
@@ -18,9 +18,9 @@ ) where import Commands.RpmBuild (rpmBuild)-import Dependencies (missingPackages, notInstalled)+import Dependencies (missingPackages, notInstalled, pkgInstallMissing) import Options (RpmFlags (..))-import PackageUtils (PackageData (..), pkgInstall, rpmInstall, RpmStage (..), stripPkgDevel)+import PackageUtils (PackageData (..), rpmInstall, RpmStage (..), stripPkgDevel) import SysCmd (cmd, cmd_, (+-+)) #if (defined(MIN_VERSION_base) && MIN_VERSION_base(4,8,2))@@ -34,13 +34,11 @@ install :: PackageData -> RpmFlags -> IO () install pkgdata flags = do let pkgDesc = packageDesc pkgdata- missing <- missingPackages pkgDesc- unless (null missing) $ do- pkgInstall missing False- stillMissing <- missingPackages pkgDesc- unless (null stillMissing) $ do- putStrLn $ "Missing:" +-+ unwords stillMissing- mapM_ installMissing stillMissing+ pkgInstallMissing pkgdata False+ stillMissing <- missingPackages pkgDesc+ unless (null stillMissing) $ do+ putStrLn $ "Missing:" +-+ unwords stillMissing+ mapM_ cblrpmInstallMissing stillMissing spec <- rpmBuild pkgdata flags Binary arch <- cmd "arch" [] rpmdir <- cmd "rpm" ["--eval", "%{_rpmdir}"]@@ -49,10 +47,10 @@ -- metapkgs don't have base package filterM doesFileExist rpms >>= rpmInstall -installMissing :: String -> IO ()-installMissing pkg = do- noInstall <- notInstalled pkg- when noInstall $ do+cblrpmInstallMissing :: String -> IO ()+cblrpmInstallMissing pkg = do+ noPkg <- notInstalled pkg+ when noPkg $ do let dep = stripPkgDevel pkg- putStrLn $ "Running cblrpm install" +-+ dep- cmd_ "cblrpm" ["install", dep]+ putStrLn $ "Running cabal-rpm install" +-+ dep+ cmd_ "cabal-rpm" ["install", dep]
src/Commands/RpmBuild.hs view
@@ -20,21 +20,20 @@ ) where import Commands.Spec (createSpecFile)-import Dependencies (missingPackages)+import Dependencies (pkgInstallMissing) import Options (RpmFlags (..))-import PackageUtils (copyTarball, isScmDir, PackageData (..), packageName,- packageVersion, rpmbuild, pkgInstall, RpmStage (..))+import PackageUtils (copyTarball, PackageData (..), packageName,+ packageVersion, rpmbuild, RpmStage (..)) import SysCmd (cmd, (+-+)) --import Control.Exception (bracket) import Control.Monad (unless, void, when)- import Distribution.PackageDescription (PackageDescription (..)) --import Distribution.Version (VersionRange, foldVersionRange') import System.Directory (doesFileExist)-import System.FilePath (takeDirectory, (</>))+import System.FilePath ((</>)) -- autoreconf :: Verbosity -> PackageDescription -> IO () -- autoreconf verbose pkgDesc = do@@ -53,15 +52,13 @@ -- autoreconf verbose pkgDesc let pkgDesc = packageDesc pkgdata mspec = specFilename pkgdata- cabalPath = cabalFilename pkgdata specFile <- maybe (createSpecFile pkgdata flags Nothing) (\ s -> putStrLn ("Using existing" +-+ s) >> return s) mspec let pkg = package pkgDesc name = packageName pkg- when (stage `elem` [Binary,BuildDep]) $ do- missing <- missingPackages pkgDesc- pkgInstall missing (stage == Binary)+ when (stage `elem` [Binary,BuildDep]) $+ pkgInstallMissing pkgdata (stage == Binary) unless (stage == BuildDep) $ do srcdir <- cmd "rpm" ["--eval", "%{_sourcedir}"]@@ -69,10 +66,8 @@ tarFile = srcdir </> name ++ "-" ++ version ++ ".tar.gz" tarFileExists <- doesFileExist tarFile- unless tarFileExists $ do- scmRepo <- isScmDir $ takeDirectory cabalPath- when scmRepo $- error "No tarball for source repo"+ unless tarFileExists $+ error "No tarball for source repo" copyTarball name version False srcdir
src/Commands/Spec.hs view
@@ -20,11 +20,11 @@ createSpecFile, createSpecFile_ ) where -import Dependencies (notInstalled, packageDependencies, showDep,- subPackages, testsuiteDependencies)+import Dependencies (notInstalled, missingPackages, packageDependencies,+ showDep, subPackages, testsuiteDependencies) import Distro (Distro(..), detectDistro) import Options (RpmFlags (..))-import PackageUtils (copyTarball, getPkgName, isScmDir, latestPackage,+import PackageUtils (copyTarball, getPkgName, latestPackage, nameVersion, PackageData (..), packageName, packageVersion, stripPkgDevel) import SysCmd ((+-+), notNull)@@ -34,9 +34,9 @@ import Control.Applicative ((<$>)) #endif import Control.Monad (filterM, unless, void, when, (>=>))-import Data.Char (toLower, toUpper)-import Data.List (groupBy, intercalate, intersect, isPrefixOf, isSuffixOf,- sort, (\\))+import Data.Char (toUpper)+import Data.List (groupBy, intercalate, intersect, isPrefixOf,+ nub, sort, (\\)) import Data.Maybe (fromMaybe, fromJust) import Data.Time.Clock (getCurrentTime) import Data.Time.Format (formatTime)@@ -64,27 +64,21 @@ --import Distribution.Version (VersionRange, foldVersionRange') -import System.Directory (doesFileExist, getDirectoryContents)+import System.Directory (doesFileExist) import System.IO (IOMode (..), hClose, hPutStrLn, openFile) #if defined(MIN_VERSION_time) && MIN_VERSION_time(1,5,0) import Data.Time.Format (defaultTimeLocale) #else import System.Locale (defaultTimeLocale) #endif-import System.FilePath (dropFileName, takeBaseName, takeDirectory, (</>))+import System.FilePath (takeBaseName, (</>)) import qualified Paths_cabal_rpm (version) -defaultRelease :: FilePath -> Distro -> IO String-defaultRelease cabalPath distro = do- let pkgDir = takeDirectory cabalPath- scmRepo <- isScmDir pkgDir- if scmRepo- then do- now <- getCurrentTime- return $ formatTime defaultTimeLocale "0.%Y%m%d" now- else return $ if distro == SUSE then "0" else "1"+defaultRelease :: Distro -> String+defaultRelease distro =+ if distro == SUSE then "0" else "1" rstrip :: (Char -> Bool) -> String -> String rstrip p = reverse . dropWhile p . reverse@@ -102,7 +96,8 @@ Maybe FilePath -> IO FilePath createSpecFile pkgdata flags mdest = do let mspec = specFilename pkgdata- cabalPath = cabalFilename pkgdata+ docs = docFilenames pkgdata+ licensefiles = licenseFilenames pkgdata pkgDesc = packageDesc pkgdata pkg = package pkgDesc name = packageName pkg@@ -200,11 +195,15 @@ -- FIXME sort by build order -- FIXME recursive missingdeps- missing <- if rpmSubpackage flags then subPackages (if specAlreadyExists then mspec else Nothing) pkgDesc else return []- subpkgs <-+ missing <- do+ subs <- if rpmSubpackage flags then subPackages (if specAlreadyExists then mspec else Nothing) pkgDesc else return []+ miss <- if rpmSubpackage flags || rpmMissing flags then missingPackages pkgDesc else return []+ return $ nub (subs ++ miss)+ subpkgs <- if rpmSubpackage flags then mapM ((getsubpkgMacro flags >=> \(m,pv) -> put ("%global" +-+ m +-+ pv) >> return ("%{" ++ m ++ "}")) . stripPkgDevel) missing+ else return [] let hasSubpkgs = notNull subpkgs when hasSubpkgs $ do put $ "%global subpkgs" +-+ unwords subpkgs@@ -214,15 +213,8 @@ put $ "%bcond_" ++ (if null missTestDeps then "without" else "with") +-+ "tests" putNewline - -- let eCsources = concatMap (cSources . buildInfo) $ executables pkgDesc- -- let lCsources = concatMap (cSources . libBuildInfo) $ maybeToList $ library pkgDesc- -- when (null $ eCsources ++ lCsources) $ do- -- put "# no useful debuginfo for Haskell packages without C sources"- -- put $ "%global debug_package" +-+ "%{nil}"- -- putNewline-- defRelease <- defaultRelease cabalPath distro let version = packageVersion pkg+ defRelease = defaultRelease distro release = fromMaybe defRelease (rpmRelease flags) revision = show $ maybe (0::Int) read (lookup "x-revision" (customFieldsPD pkgDesc)) putHdr "Name" (if binlib then "%{pkg_name}" else basename)@@ -252,8 +244,7 @@ putHdr "BuildRequires" "ghc-Cabal-devel" putHdr "BuildRequires" $ "ghc-rpm-macros" ++ (if hasSubpkgs then "-extra" else "") - let isa = if distro == SUSE then "" else "%{?_isa}"- let alldeps = sort $ deps ++ tools ++ map (++ isa) clibs ++ pkgcfgs+ let alldeps = sort $ deps ++ tools ++ clibs ++ pkgcfgs let extraTestDeps = sort $ testsuiteDeps \\ deps unless (null $ alldeps ++ extraTestDeps) $ do put "# Begin cabal-rpm deps:"@@ -306,6 +297,7 @@ putHdr "Requires(post)" "ghc-compiler = %{ghc_version}" putHdr "Requires(postun)" "ghc-compiler = %{ghc_version}" put "%endif"+ let isa = if distro == SUSE then "" else "%{?_isa}" when exposesModules $ putHdr "Requires" $ (if binlib then "ghc-%{name}" else "%{name}") ++ isa +-+ "= %{version}-%{release}" unless (null $ clibs ++ pkgcfgs) $ do@@ -355,15 +347,6 @@ when selfdep $ put $ "%ghc_fix_rpath" +-+ pkgver - let licensefiles =-#if defined(MIN_VERSION_Cabal) && MIN_VERSION_Cabal(1,20,0)- licenseFiles pkgDesc-#else- if null (licenseFile pkgDesc) then [] else [licenseFile pkgDesc]-#endif-- -- remove docs from datafiles (#38)- docs <- sort <$> findDocs cabalPath licensefiles let datafiles = dataFiles pkgDesc dupdocs = docs `intersect` datafiles datafiles' = datafiles \\ dupdocs@@ -406,7 +389,8 @@ when (distro /= Fedora) $ put "%defattr(-,root,root,-)" -- Add the license file to the main package only if it wouldn't -- otherwise be empty.- mapM_ (\ l -> put $ license_macro +-+ l) licensefiles+ unless (selfdep && binlib) $+ mapM_ (\ l -> put $ license_macro +-+ l) licensefiles unless (null docs) $ put $ "%doc" +-+ unwords docs mapM_ ((\ p -> put $ "%{_bindir}" </> (if p == name then "%{name}" else p)) . unUnqualComponentName) execs@@ -453,19 +437,6 @@ isBuildable :: Executable -> Bool isBuildable exe = buildable $ buildInfo exe--findDocs :: FilePath -> [FilePath] -> IO [FilePath]-findDocs cabalPath licensefiles = do- contents <- getDirectoryContents $ dropFileName cabalPath- let docs = filter likely contents- return $ if null licensefiles- then docs- else filter unlikely $ filter (`notElem` licensefiles) docs- where names = ["author", "changelog", "changes", "contributors", "copying", "doc",- "example", "licence", "license", "news", "readme", "todo"]- likely name = let lowerName = map toLower name- in any (`isPrefixOf` lowerName) names- unlikely name = not $ any (`isSuffixOf` name) ["~", ".cabal"] showLicense :: Distro -> License -> String showLicense SUSE (GPL Nothing) = "GPL-1.0+"
src/Dependencies.hs view
@@ -20,22 +20,23 @@ missingPackages, notInstalled, packageDependencies,+ pkgInstallMissing, showDep, subPackages, testsuiteDependencies ) where -import PackageUtils (packageName, repoquery)-import SysCmd (cmd, cmdBool, (+-+))+import PackageUtils (PackageData(..), packageName, packageManager, repoquery)+import SysCmd (cmd, cmd_, cmdBool, notNull, optionalProgram, trySystem, (+-+)) #if (defined(MIN_VERSION_base) && MIN_VERSION_base(4,8,2)) #else import Control.Applicative ((<$>)) #endif-import Control.Monad (filterM, when)+import Control.Monad (filterM, when, unless) -import Data.List (delete, isSuffixOf, nub)-import Data.Maybe (catMaybes, isNothing)+import Data.List (delete, isSuffixOf, nub, (\\))+import Data.Maybe (catMaybes, fromMaybe, isNothing) import Distribution.Package (Dependency (..), #if defined(MIN_VERSION_Cabal) && MIN_VERSION_Cabal(1,22,0)@@ -65,6 +66,7 @@ ) import System.Directory (doesDirectoryExist, doesFileExist) import System.IO (hPutStrLn, stderr)+import System.Posix.User (getEffectiveUserID) excludedPkgs :: String -> Bool excludedPkgs = flip notElem ["Cabal", "base", "ghc-prim", "integer-gmp"]@@ -134,7 +136,6 @@ -- use repoquery or rpm -q to query which package provides file rpmqueryFile :: QueryBackend -> FilePath -> IO (Maybe String) rpmqueryFile backend file = do- -- FIXME dnf repoquery does not support -f ! let args = ["-q", "--qf=%{name}", "-f"] out <- if backend == Rpm then cmd "rpm" (args ++ [file])@@ -210,6 +211,43 @@ subPackages mspec pkgDesc = do develSubpkgs <- filter ("-devel" `isSuffixOf`) . lines <$> maybe (return "") (\ f -> cmd "rpmspec" ["-q", "--qf", "%{name}\n", f]) mspec let self = packageName $ package pkgDesc- subpkgs = delete (showDep self) develSubpkgs+ return $ delete (showDep self) develSubpkgs++pkgInstallMissing :: PackageData -> Bool -> IO ()+pkgInstallMissing pkgdata hard = do+ let pkgDesc = packageDesc pkgdata+ mspec = specFilename pkgdata missing <- missingPackages pkgDesc- return $ nub (subpkgs ++ missing)+ unless (null missing) $ do+ subpkgs <- subPackages mspec pkgDesc+ let pkgs = missing \\ subpkgs+ pkginstaller <- packageManager+ putStrLn $ "Running repoquery" +-+ unwords pkgs+ repopkgs <- filter (/= "") <$> mapM (repoquery ["--qf", "%{name}"]) pkgs+ let missing' = pkgs \\ repopkgs+ if notNull missing' && hard+ then error $ unwords missing' +-+ "not available."+ else do+ unless (null missing') $ do+ putStrLn "Unavailable dependencies:"+ mapM_ putStrLn missing'+ unless (null repopkgs) $ do+ putStrLn "Uninstalled dependencies:"+ mapM_ putStrLn repopkgs+ uid <- getEffectiveUserID+ maybeSudo <-+ if uid == 0+ then return Nothing+ else do+ havesudo <- optionalProgram "sudo"+ return $ if havesudo then Just "sudo" else Nothing+ let args = map showPkg repopkgs+ putStrLn $ "Running:" +-+ fromMaybe "" maybeSudo +-+ pkginstaller +-+ "install" +-+ unwords args+ let exec = if hard then cmd_ else trySystem+ fedora <- cmd "rpm" ["--eval", "%fedora"]+ let nogpgcheck = ["--nogpgcheck" | fedora `elem` ["22", "23"]]+ exec (fromMaybe pkginstaller maybeSudo) $ maybe [] (const [pkginstaller]) maybeSudo ++ ("install" : args ++ nogpgcheck)+ where+ showPkg :: String -> String+ showPkg p = if '(' `elem` p then show p else p+
src/Main.hs view
@@ -25,34 +25,30 @@ import Commands.Update (update) import Options (parseArgs)-import PackageUtils (prepare, PackageData (..), RpmStage (..))+import PackageUtils (prepare, RpmStage (..)) -import Control.Exception (bracket)-import System.Directory (removeDirectoryRecursive) import System.Environment (getArgs) main :: IO () main = do (opts, cmd, mpkg) <- getArgs >>= parseArgs- bracket (prepare opts mpkg)- (maybe (return ()) removeDirectoryRecursive . workingDir)- (\pkgdata ->- case cmd of- "spec" -> createSpecFile_ pkgdata opts Nothing- "srpm" -> rpmBuild_ pkgdata opts Source- "prep" -> rpmBuild_ pkgdata opts Prep- "local" -> rpmBuild_ pkgdata opts Binary- "build" -> rpmBuild_ pkgdata opts Binary- "builddep" -> rpmBuild_ pkgdata opts BuildDep- "diff" -> diff pkgdata opts mpkg- "install" -> install pkgdata opts- "depends" -> depends pkgdata Depends- "refresh" -> refresh pkgdata opts- "requires" -> depends pkgdata Requires- "missingdeps" -> depends pkgdata Missing- "update" -> update pkgdata opts mpkg- "rpm" -> do- putStrLn "* Warning the 'rpm' command has been renamed to 'local':"- putStrLn "* this alias may be removed in a future release."- rpmBuild_ pkgdata opts Binary- c -> error $ "Unknown cmd: " ++ c)+ pkgdata <- prepare opts mpkg+ case cmd of+ "spec" -> createSpecFile_ pkgdata opts Nothing+ "srpm" -> rpmBuild_ pkgdata opts Source+ "prep" -> rpmBuild_ pkgdata opts Prep+ "local" -> rpmBuild_ pkgdata opts Binary+ "build" -> rpmBuild_ pkgdata opts Binary+ "builddep" -> rpmBuild_ pkgdata opts BuildDep+ "diff" -> diff pkgdata opts mpkg+ "install" -> install pkgdata opts+ "depends" -> depends pkgdata Depends+ "refresh" -> refresh pkgdata opts+ "requires" -> depends pkgdata Requires+ "missingdeps" -> depends pkgdata Missing+ "update" -> update pkgdata opts mpkg+ "rpm" -> do+ putStrLn "* Warning the 'rpm' command has been renamed to 'local':"+ putStrLn "* this alias may be removed in a future release."+ rpmBuild_ pkgdata opts Binary+ c -> error $ "Unknown cmd: " ++ c
src/Options.hs view
@@ -57,6 +57,7 @@ , rpmStrict :: Bool , rpmSubpackage :: Bool , rpmHackage :: Bool+ , rpmMissing :: Bool , rpmRelease :: Maybe String , rpmCompilerId :: Maybe CompilerId , rpmDistribution :: Maybe Distro@@ -74,6 +75,7 @@ , rpmStrict = False , rpmSubpackage = False , rpmHackage = False+ , rpmMissing = False , rpmRelease = Nothing , rpmCompilerId = Nothing , rpmDistribution = Nothing@@ -94,6 +96,8 @@ "Overwrite existing spec file." , Option "" ["hackage"] (NoArg (\x -> x { rpmHackage = True })) "Use Hackage to get package version instead of Stackage."+ , Option "" ["missing"] (NoArg (\x -> x { rpmMissing = True }))+ "Comment out missing BuildRequires packages." , Option "" ["strict"] (NoArg (\x -> x { rpmStrict = True })) "Fail rather than produce an incomplete spec file." , Option "" ["subpackage"] (NoArg (\x -> x { rpmSubpackage = True }))@@ -143,7 +147,7 @@ ++ " missingdeps\t- list missing buildrequires\n" ++ " diff\t\t- diff current spec file\n" ++ " update\t- update spec file package to latest version\n"- ++ " refresh\t- refresh spec file to current cblrpm\n"+ ++ " refresh\t- refresh spec file to current cabal-rpm\n" ++ "\n" ++ "Options:" hPutStrLn h (usageInfo info options)
src/PackageUtils.hs view
@@ -19,14 +19,13 @@ copyTarball, getPkgName, isGitDir,- isScmDir, latestPackage, nameVersion, PackageData (..),+ packageManager, packageName, packageVersion, patchSpec,- pkgInstall, prepare, removePrefix, removeSuffix,@@ -34,7 +33,6 @@ rpmbuild, rpmInstall, RpmStage (..),- simplePackageDescription, stripPkgDevel ) where @@ -42,7 +40,7 @@ getDirectoryContents_, mktempdir) import Options (RpmFlags (..)) import SysCmd (cmd, cmd_, cmdIgnoreErr, cmdSilent, (+-+),- notNull, optionalProgram, requireProgram, sudo, trySystem)+ optionalProgram, requireProgram, sudo) import Stackage (latestStackage) @@ -52,8 +50,8 @@ #endif import Control.Monad (filterM, unless, when) -import Data.Char (isDigit)-import Data.List (isPrefixOf, stripPrefix, (\\))+import Data.Char (isDigit, toLower)+import Data.List (isPrefixOf, isSuffixOf, sort, stripPrefix) import Data.Maybe (fromMaybe, isJust) import Distribution.Compiler@@ -101,12 +99,12 @@ import System.Directory (copyFile, createDirectoryIfMissing,doesDirectoryExist, doesFileExist, getCurrentDirectory,+ getDirectoryContents, removeDirectoryRecursive, setCurrentDirectory) import System.Environment (getEnv)-import System.FilePath ((</>), (<.>), takeBaseName, takeFileName)+import System.FilePath ((</>), (<.>), dropFileName, takeBaseName, takeFileName) import System.Posix.Files (accessTime, fileMode, getFileStatus, modificationTime, setFileMode)-import System.Posix.User (getEffectiveUserID) -- returns path to .cabal file and possibly tmpdir to be removed --findCabalFile :: Verbosity -> FilePath -> IO (FilePath, Maybe FilePath)@@ -120,10 +118,10 @@ hasVer = all (\c -> isDigit c || c == '.') mRev simplePackageDescription :: FilePath -> RpmFlags- -> IO PackageDescription-simplePackageDescription path opts = do+ -> IO (PackageDescription, [FilePath], [FilePath])+simplePackageDescription cabalfile opts = do let verbose = rpmVerbosity opts- genPkgDesc <- readPackageDescription verbose path+ genPkgDesc <- readPackageDescription verbose cabalfile compiler <- case rpmCompilerId opts of Just cid -> return #if defined(MIN_VERSION_Cabal) && MIN_VERSION_Cabal(1,22,0)@@ -148,10 +146,31 @@ compiler [] genPkgDesc of Left e -> die $ "finalize failed: " ++ show e- Right (pd, _) -> return pd+ Right (pd, _) -> do+ (docs, licensefiles) <- findDocsLicenses (dropFileName cabalfile) pd+ return (pd, docs, licensefiles) +findDocsLicenses :: FilePath -> PackageDescription -> IO ([FilePath], [FilePath])+findDocsLicenses dir pkgDesc = do+ contents <- getDirectoryContents dir+ let docs = sort $ filter unlikely $ filter likely contents+ let licenses = #if defined(MIN_VERSION_Cabal) && MIN_VERSION_Cabal(1,20,0)+ licenseFiles pkgDesc #else+ if null (licenseFile pkgDesc) then [] else [licenseFile pkgDesc]+#endif+ docfiles = if null licenses then docs else filter (`notElem` licenses) docs+ return (docfiles, licenses)+ where names = ["author", "changelog", "changes", "contributors", "copying", "doc",+ "example", "licence", "license", "news", "readme", "todo"]+ likely name = let lowerName = map toLower name+ in any (`isPrefixOf` lowerName) names+ unlikely name = not $ any (`isSuffixOf` name) ["~", ".cabal"]+++#if defined(MIN_VERSION_Cabal) && MIN_VERSION_Cabal(1,20,0)+#else tryFindPackageDesc :: FilePath -> IO FilePath tryFindPackageDesc = findPackageDesc #endif@@ -304,15 +323,6 @@ packageVersion :: PackageIdentifier -> String packageVersion = showVersion . pkgVersion -(<||>) :: IO Bool -> IO Bool -> IO Bool-(<||>) f s = do- one <- f- if one then return True else s--isScmDir :: FilePath -> IO Bool-isScmDir dir =- isGitDir dir <||> doesDirectoryExist (dir </> "_darcs")- isGitDir :: FilePath -> IO Bool isGitDir dir = doesDirectoryExist (dir </> ".git") @@ -398,9 +408,9 @@ data PackageData = PackageData { specFilename :: Maybe FilePath- , cabalFilename :: FilePath+ , docFilenames :: [FilePath]+ , licenseFilenames :: [FilePath] , packageDesc :: PackageDescription- , workingDir :: Maybe FilePath } -- Nothing implies existing packaging in cwd@@ -412,8 +422,9 @@ case mspec of Just spec -> do (cabalfile, mtmp) <- cabalFromSpec spec- pkgDesc <- simplePackageDescription cabalfile flags- return $ PackageData mspec cabalfile pkgDesc mtmp+ (pkgDesc, docs, licenses) <- simplePackageDescription cabalfile flags+ maybe (return ()) removeDirectoryRecursive mtmp+ return $ PackageData mspec docs licenses pkgDesc Nothing -> case mpkgver of Nothing -> do@@ -423,15 +434,16 @@ mcabal <- checkForCabalFile pkgmver case mcabal of Just cabalfile -> do- pkgDesc <- simplePackageDescription cabalfile flags- return $ PackageData Nothing cabalfile pkgDesc Nothing+ (pkgDesc, docs, licenses) <- simplePackageDescription cabalfile flags+ return $ PackageData Nothing docs licenses pkgDesc Nothing -> do pkgver <- if stripVersion pkgmver == pkgmver then latestPackage (rpmHackage flags) pkgmver else return pkgmver (cabalfile, mtmp) <- tryUnpack pkgver- pkgDesc <- simplePackageDescription cabalfile flags- return $ PackageData Nothing cabalfile pkgDesc mtmp+ (pkgDesc, docs, licenses) <- simplePackageDescription cabalfile flags+ maybe (return ()) removeDirectoryRecursive mtmp+ return $ PackageData Nothing docs licenses pkgDesc patchSpec :: Maybe FilePath -> FilePath -> FilePath -> IO () patchSpec mdir oldspec newspec = do@@ -454,39 +466,6 @@ havednf <- optionalProgram "dnf" let (prog, subcmd) = if havednf then ("dnf", ["repoquery", "-q"]) else ("repoquery", []) cmd prog (subcmd ++ args ++ [key])--pkgInstall :: [String] -> Bool -> IO ()-pkgInstall [] _ = return ()-pkgInstall pkgs hard = do- pkginstaller <- packageManager- putStrLn $ "Running repoquery" +-+ unwords pkgs- repopkgs <- filter (/= "") <$> mapM (repoquery ["--qf", "%{name}"]) pkgs- let missing = pkgs \\ repopkgs- if notNull missing && hard- then error $ unwords missing +-+ "not available."- else do- unless (null missing) $ do- putStrLn "Unavailable dependencies:"- mapM_ putStrLn missing- unless (null repopkgs) $ do- putStrLn "Uninstalled dependencies:"- mapM_ putStrLn repopkgs- uid <- getEffectiveUserID- maybeSudo <-- if uid == 0- then return Nothing- else do- havesudo <- optionalProgram "sudo"- return $ if havesudo then Just "sudo" else Nothing- let args = map showPkg repopkgs- putStrLn $ "Running:" +-+ fromMaybe "" maybeSudo +-+ pkginstaller +-+ "install" +-+ unwords args- let exec = if hard then cmd_ else trySystem- fedora <- cmd "rpm" ["--eval", "%fedora"]- let nogpgcheck = ["--nogpgcheck" | fedora `elem` ["22", "23"]]- exec (fromMaybe pkginstaller maybeSudo) $ maybe [] (const [pkginstaller]) maybeSudo ++ ("install" : args ++ nogpgcheck)- where- showPkg :: String -> String- showPkg p = if '(' `elem` p then show p else p rpmInstall :: [String] -> IO () rpmInstall rpms = do