diff --git a/ChangeLog b/ChangeLog
--- a/ChangeLog
+++ b/ChangeLog
@@ -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
 
diff --git a/cabal-rpm.cabal b/cabal-rpm.cabal
--- a/cabal-rpm.cabal
+++ b/cabal-rpm.cabal
@@ -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
diff --git a/cblrpm-diff b/cblrpm-diff
--- a/cblrpm-diff
+++ b/cblrpm-diff
@@ -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
diff --git a/man/cblrpm.1 b/man/cblrpm.1
--- a/man/cblrpm.1
+++ b/man/cblrpm.1
@@ -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
diff --git a/man/cblrpm.1.md b/man/cblrpm.1.md
--- a/man/cblrpm.1.md
+++ b/man/cblrpm.1.md
@@ -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
 
diff --git a/src/Commands/Depends.hs b/src/Commands/Depends.hs
new file mode 100644
--- /dev/null
+++ b/src/Commands/Depends.hs
@@ -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
diff --git a/src/Commands/Install.hs b/src/Commands/Install.hs
--- a/src/Commands/Install.hs
+++ b/src/Commands/Install.hs
@@ -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 =
diff --git a/src/Commands/RpmBuild.hs b/src/Commands/RpmBuild.hs
--- a/src/Commands/RpmBuild.hs
+++ b/src/Commands/RpmBuild.hs
@@ -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
diff --git a/src/Commands/Spec.hs b/src/Commands/Spec.hs
--- a/src/Commands/Spec.hs
+++ b/src/Commands/Spec.hs
@@ -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
diff --git a/src/Dependencies.hs b/src/Dependencies.hs
new file mode 100644
--- /dev/null
+++ b/src/Dependencies.hs
@@ -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
diff --git a/src/Depends.hs b/src/Depends.hs
deleted file mode 100644
--- a/src/Depends.hs
+++ /dev/null
@@ -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
diff --git a/src/Main.hs b/src/Main.hs
--- a/src/Main.hs
+++ b/src/Main.hs
@@ -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)
diff --git a/src/PackageUtils.hs b/src/PackageUtils.hs
--- a/src/PackageUtils.hs
+++ b/src/PackageUtils.hs
@@ -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,
diff --git a/src/Setup.hs b/src/Setup.hs
--- a/src/Setup.hs
+++ b/src/Setup.hs
@@ -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
diff --git a/src/SysCmd.hs b/src/SysCmd.hs
--- a/src/SysCmd.hs
+++ b/src/SysCmd.hs
@@ -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
