diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,5 +1,11 @@
 # Revision history for staversion
 
+## 0.1.3.0  -- 2016-12-29
+
+* Now staversion shows the exact resolver for a partial resolver (e.g. "lts-4" -> "lts-4.2")
+* Now staversion reads .cabal files, and uses their `build-depends` fields as query.
+* Fix minor error in ordering the result.
+
 ## 0.1.2.0  -- 2016-11-10
 
 * New option `--hackage`, which searches hackage for the latest version number.
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -2,8 +2,14 @@
 
 ![travis status](https://api.travis-ci.org/debug-ito/staversion.png)
 
-staversion is a command-line tool to look for version numbers of Haskell packages. It mainly focuses on package versions in stackage, i.e. it answers to questions like "What version is the package X in stackage lts-Y.ZZ?" It aims to make it easier to write `build-depends` section in YOUR_PACKAGE.cabal.
+staversion is a command-line tool to look for version numbers of Haskell packages.
 
+See `--help` message for detailed usage.
+
+## Package version in Stackage
+
+staversion mainly focuses on package versions in stackage, i.e. it answers to questions like "What version is the package X in stackage lts-Y.ZZ?" It aims to make it easier to write `build-depends` section in YOUR_PACKAGE.cabal.
+
     $ staversion --resolver lts-4.2 conduit
     ------ lts-4.2
     conduit ==1.2.6.1
@@ -26,6 +32,8 @@
 
 staversion first reads build plan YAML files that are stored locally in your computer, then it tries to fetch them over network.
 
+## Package version in Hackage
+
 You can also look up the latest version numbers hosted on hackage.
 
     $ staversion --hackage conduit base
@@ -33,12 +41,35 @@
     conduit ==1.2.8,
     base ==4.9.0.0
 
-See `--help` message for detail.
+## Package version for build-depends
 
+You can also specify .cabal files in the query. In that case, staversion reads `build-depends` fields in all sections of those .cabal files, and shows versions of the dependency packages.
 
+    $ staversion --hackage staversion.cabal 
+    ------ latest in hackage
+    -- staversion.cabal - library
+    base ==4.9.0.0,
+    unordered-containers ==0.2.7.2,
+    aeson ==1.0.2.1,
+    text ==1.2.2.1,
+    bytestring ==0.10.8.1,
+    yaml ==0.8.21.1,
+    filepath ==1.4.1.1,
+    directory ==1.3.0.0,
+    optparse-applicative ==0.13.0.0,
+    containers ==0.5.9.1,
+    http-client ==0.5.5,
+    http-client-tls ==0.3.3,
+    http-types ==0.9.1,
+    transformers ==0.5.2.0,
+    transformers-compat ==0.5.1.4,
+    megaparsec ==5.1.2
+    
+    (snip)
+
+
 ## TODO
 
-- Read `build-depends` sections .cabal files for package name queries.
 - Show version number ranges supported by the given resolvers.
 - Cache build plans in some local storage (SQLite?)
 
diff --git a/src/Staversion/Internal/BuildPlan.hs b/src/Staversion/Internal/BuildPlan.hs
--- a/src/Staversion/Internal/BuildPlan.hs
+++ b/src/Staversion/Internal/BuildPlan.hs
@@ -4,18 +4,20 @@
 -- Maintainer: Toshio Ito <debug.ito@gmail.com>
 --
 -- __This is an internal module. End-users should not use it.__
-{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving, TupleSections #-}
 module Staversion.Internal.BuildPlan
        ( -- * Entry APIs
+         HasVersions(..),
          BuildPlan,
-         packageVersion,
+         buildPlanSource,
          BuildPlanManager,
          newBuildPlanManager,
          loadBuildPlan,
          -- * Low-level APIs
-         loadBuildPlanYAML,
+         BuildPlanMap,
+         loadBuildPlanMapYAML,
          -- * For tests
-         _setDisambiguator
+         _setLTSDisambiguator
        ) where
 
 import Control.Applicative (empty, (<$>), (<*>))
@@ -33,6 +35,7 @@
 import Data.Text (Text, unpack)
 import Data.Traversable (Traversable(traverse))
 import Data.Version (Version)
+import Data.Word (Word)
 import qualified Data.Yaml as Yaml
 import System.FilePath ((</>), (<.>))
 import qualified System.IO.Error as IOE
@@ -54,18 +57,18 @@
   ( Disambiguator,
     fetchDisambiguator,
     parseResolverString,
-    formatResolverString,
-    PartialResolver(..), ExactResolver,
+    formatExactResolverString,
+    PartialResolver(..), ExactResolver(..),
     fetchBuildPlanYAML
   )
 import Staversion.Internal.BuildPlan.Version (unVersionJSON)
 
 -- | A data structure that keeps a map between package names and their
 -- versions.
-newtype BuildPlan = BuildPlan (HM.HashMap PackageName Version) deriving (Monoid)
+newtype BuildPlanMap = BuildPlanMap (HM.HashMap PackageName Version) deriving (Monoid)
 
-instance FromJSON BuildPlan where
-  parseJSON (Object object) = (\p1 p2 -> BuildPlan $ p1 <> p2) <$> core_packages <*> other_packages where
+instance FromJSON BuildPlanMap where
+  parseJSON (Object object) = (\p1 p2 -> BuildPlanMap $ p1 <> p2) <$> core_packages <*> other_packages where
     core_packages = parseSysInfo =<< (object .: "system-info")
     parseSysInfo (Object o) = parseCorePackages =<< (o .: "core-packages")
     parseSysInfo _ = empty
@@ -79,6 +82,22 @@
     parsePackageObject _ = empty
   parseJSON _ = empty
 
+-- | A 'BuildPlanMap' associated with its 'PackageSource'.
+data BuildPlan = BuildPlan { buildPlanMap :: BuildPlanMap,
+                             buildPlanSource :: PackageSource
+                           }
+
+-- | Types that have mapping between 'PackageName' and 'Version'.
+class HasVersions t where
+  packageVersion :: t -> PackageName -> Maybe Version
+
+instance HasVersions BuildPlanMap where
+  packageVersion (BuildPlanMap bp_map) name = HM.lookup name bp_map
+
+instance HasVersions BuildPlan where
+  packageVersion bp = packageVersion (buildPlanMap bp)
+
+
 -- | Stateful manager for 'BuildPlan's.
 data BuildPlanManager =
   BuildPlanManager { manBuildPlanDir :: FilePath,
@@ -129,18 +148,22 @@
   handler e = return $ Left (context ++ ": " ++ show e)
 
 loadBuildPlan :: BuildPlanManager
-              -> [PackageName] -- ^ package names whose versions the user is interested in.
-              -> PackageSource -> IO (Either ErrorMsg BuildPlan)
+              -> [PackageName]
+              -- ^ package names whose versions the user is interested in.
+              -> PackageSource
+              -> IO (Either ErrorMsg BuildPlan)
+              -- ^ the second result is the real (disambiguated) PackageSource.
 loadBuildPlan man _ (SourceStackage resolver) = runExceptT impl where
   impl = loadBuildPlan_stackageLocalFile man resolver `loggedElse'` do
     e_resolver <- tryDisambiguate man =<< getPresolver
-    loadBuildPlan_stackageLocalFile man (formatResolverString $ PartialExact e_resolver) `loggedElse'` loadBuildPlan_stackageNetwork man e_resolver
+    loadBuildPlan_stackageLocalFile man (formatExactResolverString e_resolver) `loggedElse'` loadBuildPlan_stackageNetwork man e_resolver
   getPresolver = maybeToLoadM ("Invalid resolver format for stackage.org: " ++ resolver) $ parseResolverString resolver
   loggedElse' = loggedElse $ manLogger man
 loadBuildPlan man names SourceHackage = runExceptT impl where
   impl = do
     http_man <- httpManagerM man
-    (mconcat . zipWith registeredVersionToBuildPlan names) <$> mapM (doFetch http_man) names
+    build_plan_map <- (mconcat . zipWith registeredVersionToBuildPlanMap names) <$> mapM (doFetch http_man) names
+    return $ BuildPlan { buildPlanMap = build_plan_map, buildPlanSource = SourceHackage }
   logDebug' msg = liftIO $ logDebug (manLogger man) msg
   doFetch http_man name = do
     logDebug' ("Ask hackage for the latest version of " ++ unpack name)
@@ -151,7 +174,9 @@
   yaml_file = manBuildPlanDir man </> resolver <.> "yaml"
   doLoad = do
     logDebug (manLogger man) ("Read " ++ yaml_file ++ " for build plan.")
-    loadBuildPlanYAML yaml_file
+    e_build_plan_map <- loadBuildPlanMapYAML yaml_file
+    return $ makeBuildPlan <$> e_build_plan_map
+  makeBuildPlan bp_map = BuildPlan { buildPlanMap = bp_map, buildPlanSource = SourceStackage resolver }
   handleIOError :: IOException -> Maybe ErrorMsg
   handleIOError e | IOE.isDoesNotExistError e = Just $ makeErrorMsg e (yaml_file ++ " not found.")
                   | IOE.isPermissionError e = Just $ makeErrorMsg e ("you cannot open " ++ yaml_file ++ ".")
@@ -182,24 +207,33 @@
   http_man <- httpManagerM man
   liftIO $ logDebug (manLogger man) ("Fetch build plan from network: resolver = " ++ show e_resolver)
   yaml_data <- httpExceptionToLoadM ("Downloading build plan failed: " ++ show e_resolver) $ liftIO $ fetchBuildPlanYAML http_man e_resolver
-  ExceptT $ return $ parseBuildPlanYAML $ BSL.toStrict yaml_data
+  makeBuildPlan <$> (ExceptT $ return $ parseBuildPlanMapYAML $ BSL.toStrict yaml_data)
+  where
+    makeBuildPlan bp_map = BuildPlan { buildPlanMap = bp_map,
+                                       buildPlanSource = SourceStackage $ formatExactResolverString e_resolver
+                                     }
 
-parseBuildPlanYAML :: BS.ByteString -> Either ErrorMsg BuildPlan
-parseBuildPlanYAML = either (Left . toErrorMsg) Right  . Yaml.decodeEither' where
-  toErrorMsg parse_exception = "Error while parsing BuildPlan YAML: " ++ show parse_exception
+parseBuildPlanMapYAML :: BS.ByteString -> Either ErrorMsg BuildPlanMap
+parseBuildPlanMapYAML = either (Left . toErrorMsg) Right  . Yaml.decodeEither' where
+  toErrorMsg parse_exception = "Error while parsing BuildPlanMap YAML: " ++ show parse_exception
 
--- | Load a 'BuildPlan' from a file.
-loadBuildPlanYAML :: FilePath -> IO (Either ErrorMsg BuildPlan)
-loadBuildPlanYAML yaml_file = parseBuildPlanYAML <$> BS.readFile yaml_file where -- TODO: make it memory-efficient!
+-- | Load a 'BuildPlanMap' from a file.
+loadBuildPlanMapYAML :: FilePath -> IO (Either ErrorMsg BuildPlanMap)
+loadBuildPlanMapYAML yaml_file = parseBuildPlanMapYAML <$> BS.readFile yaml_file where -- TODO: make it memory-efficient!
 
-packageVersion :: BuildPlan -> PackageName -> Maybe Version
-packageVersion (BuildPlan bp_map) name = HM.lookup name bp_map
+registeredVersionToBuildPlanMap :: PackageName -> RegisteredVersions -> BuildPlanMap
+registeredVersionToBuildPlanMap name rvers = BuildPlanMap $ HM.fromList $ pairs where
+  pairs = case latestVersion rvers of
+    Nothing -> []
+    Just v -> [(name, v)]
 
 _setDisambiguator :: BuildPlanManager -> Maybe Disambiguator -> IO ()
 _setDisambiguator bp_man = writeIORef (manDisambiguator bp_man)
 
-registeredVersionToBuildPlan :: PackageName -> RegisteredVersions -> BuildPlan
-registeredVersionToBuildPlan name rvers = BuildPlan $ HM.fromList $ pairs where
-  pairs = case latestVersion rvers of
-    Nothing -> []
-    Just v -> [(name, v)]
+_setLTSDisambiguator :: BuildPlanManager
+                     -> Word -- ^ disambiguated LTS major version
+                     -> Word -- ^ disambiguated LTS minor version
+                     -> IO ()
+_setLTSDisambiguator bp_man lts_major lts_minor = _setDisambiguator bp_man $ Just disam where
+  disam PartialLTSLatest = Just $ ExactLTS lts_major lts_minor
+  disam _ = Nothing
diff --git a/src/Staversion/Internal/BuildPlan/Stackage.hs b/src/Staversion/Internal/BuildPlan/Stackage.hs
--- a/src/Staversion/Internal/BuildPlan/Stackage.hs
+++ b/src/Staversion/Internal/BuildPlan/Stackage.hs
@@ -13,6 +13,7 @@
          PartialResolver(..),
          parseResolverString,
          formatResolverString,
+         formatExactResolverString,
          Disambiguator,
          fetchDisambiguator,
          fetchBuildPlanYAML,
@@ -84,6 +85,9 @@
   PartialLTSLatest -> "lts"
   PartialLTSMajor major -> "lts-" ++ show major
   PartialNightlyLatest -> "nightly"
+
+formatExactResolverString :: ExactResolver -> Resolver
+formatExactResolverString er = formatResolverString $ PartialExact er
 
 type Disambiguator = PartialResolver -> Maybe ExactResolver
 
diff --git a/src/Staversion/Internal/Cabal.hs b/src/Staversion/Internal/Cabal.hs
new file mode 100644
--- /dev/null
+++ b/src/Staversion/Internal/Cabal.hs
@@ -0,0 +1,137 @@
+-- |
+-- Module: Staversion.Internal.Cabal
+-- Description: functions dealing with .cabal files.
+-- Maintainer: Toshio Ito <debug.ito@gmail.com>
+--
+-- __This is an internal module. End-users should not use it.__
+module Staversion.Internal.Cabal
+       ( loadCabalFile,
+         Target(..),
+         BuildDepends(..)
+       ) where
+
+import Control.Applicative ((<*), (*>), (<|>), (<*>), many, some)
+import Control.Monad (void, mzero, forM)
+import Data.Bifunctor (first)
+import Data.Char (isAlpha, isDigit, toLower, isSpace)
+import Data.List (intercalate, nub)
+import Data.Monoid (mconcat)
+import Data.Text (pack, Text)
+import qualified Data.Text as T
+import qualified Data.Text.IO as TIO
+import qualified Text.Megaparsec as P
+import qualified Text.Megaparsec.Text as P
+
+import Staversion.Internal.Query
+  ( PackageName, ErrorMsg
+  )
+
+-- | Build target type.
+data Target = TargetLibrary -- ^ the @library@ target.
+            | TargetExecutable Text -- ^ the @executable NAME@ target.
+            | TargetTestSuite Text -- ^ the @test-suite NAME@ target.
+            | TargetBenchmark Text -- ^ the @benchmark NAME@ target.
+            deriving (Show,Eq,Ord)
+
+-- | A block of @build-depends:@.
+data BuildDepends =
+  BuildDepends { depsTarget :: Target,
+                 depsPackages :: [PackageName]
+               } deriving (Show,Eq,Ord)
+
+loadCabalFile :: FilePath -> IO (Either ErrorMsg [BuildDepends])
+loadCabalFile cabal_filepath = first show <$> P.runParser (cabalParser <* P.eof) cabal_filepath <$> TIO.readFile cabal_filepath
+
+isLineSpace :: Char -> Bool
+isLineSpace ' ' = True
+isLineSpace '\t' = True
+isLineSpace _ = False
+
+indent :: P.Parser Int
+indent = length <$> (many $ P.satisfy isLineSpace)
+
+finishLine :: P.Parser ()
+finishLine = P.eof <|> void P.eol
+
+emptyLine :: P.Parser ()
+emptyLine = indent *> (P.try finishLine <|> comment_line) where
+  comment_line = P.string "--" *> P.manyTill P.anyChar finishLine *> pure ()
+
+blockHeadLine :: P.Parser Target
+blockHeadLine = target <* trail <* finishLine where
+  trail = indent
+  target = target_lib <|> target_exe <|> target_test <|> target_bench
+  target_lib = P.try (P.string' "library") *> pure TargetLibrary
+  target_exe = TargetExecutable <$> targetNamed "executable"
+  target_test = TargetTestSuite <$> targetNamed "test-suite"
+  target_bench = TargetBenchmark <$> targetNamed "benchmark"
+  targetNamed :: String -> P.Parser Text
+  targetNamed target_type = P.try (P.string' target_type)
+                            *> (some $ P.satisfy isLineSpace)
+                            *> (fmap pack $ some $ P.satisfy (not . isSpace))
+
+fieldStart :: Maybe String -- ^ expected field name. If Nothing, it just don't care.
+           -> P.Parser (String, Int) -- ^ (lower-case field name, indent level)
+fieldStart mexp_name = do
+  level <- indent
+  name <- nameParser <* indent <* P.char ':'
+  return (map toLower name, level)
+  where
+    nameParser = case mexp_name of
+      Nothing -> some $ P.satisfy $ \c -> not (isLineSpace c || c == ':')
+      Just exp_name -> P.string' exp_name
+
+fieldBlock :: P.Parser (String, Text) -- ^ (lower-case field name, block content)
+fieldBlock = impl where
+  impl = do
+    _ <- many $ P.try conditionalLine
+    (field_name, level) <- P.try $ fieldStart Nothing
+    field_trail <- P.manyTill P.anyChar finishLine
+    rest <- remainingLines level
+    let text_block = T.intercalate "\n" $ map pack (field_trail : rest)
+    return (field_name, text_block)
+  remainingLines field_indent_level = reverse <$> go [] where
+    go cur_lines = (P.eof *> pure cur_lines) <|> foundSomething cur_lines
+    foundSomething cur_lines = do
+      void $ many $ P.try emptyLine
+      this_level <- P.lookAhead indent
+      if this_level <= field_indent_level
+        then pure cur_lines
+        else do
+        _ <- indent
+        this_line <- P.manyTill P.anyChar finishLine
+        go (this_line : cur_lines)
+
+buildDependsLine :: P.Parser [PackageName]
+buildDependsLine = P.space *> (pname `P.endBy` ignored) where
+  pname = pack <$> (some $ P.satisfy allowedChar)
+  allowedChar '-' = True
+  allowedChar '_' = True
+  allowedChar c = isAlpha c || isDigit c
+  ignored = P.manyTill P.anyChar finishItem *> P.space
+  finishItem = P.eof <|> (void $ P.char ',')
+
+conditionalLine :: P.Parser ()
+conditionalLine = void $ indent *> (term "if" <|> term "else") *> P.manyTill P.anyChar finishLine where
+  term :: String -> P.Parser ()
+  term t = P.try (P.string' t *> P.lookAhead P.space)
+
+targetBlock :: P.Parser BuildDepends
+targetBlock = do
+  target <- P.try blockHeadLine
+  _ <- many $ P.try emptyLine
+  fields <- some fieldBlock
+  let build_deps_blocks = map snd $ filter (("build-depends" ==) . fst) $ fields
+  packages <- fmap (nub . concat) $ forM build_deps_blocks $ \block -> do
+    either (fail . show) return $ P.runParser (buildDependsLine <* P.space <* P.eof) "build-depends" block
+  return $ BuildDepends { depsTarget = target,
+                          depsPackages = packages
+                        }
+
+cabalParser :: P.Parser [BuildDepends]
+cabalParser = reverse <$> go [] where
+  go cur_deps = targetBlockParsed cur_deps <|> (P.eof *> pure cur_deps) <|> ignoreLine cur_deps
+  targetBlockParsed cur_deps = do
+    new_dep <- targetBlock
+    go (new_dep : cur_deps)
+  ignoreLine cur_deps = P.manyTill P.anyChar finishLine *> go cur_deps
diff --git a/src/Staversion/Internal/Command.hs b/src/Staversion/Internal/Command.hs
--- a/src/Staversion/Internal/Command.hs
+++ b/src/Staversion/Internal/Command.hs
@@ -25,6 +25,7 @@
   ( Resolver,
     PackageName,
     Query(..),
+    parseQuery,
     PackageSource(..)
   )
 
@@ -81,11 +82,15 @@
                         Opt.short 'H',
                         Opt.help "Search hackage.org for the latest version."
                       ]
-  queries = some $ QueryName <$> package
-  package = fmap pack $ Opt.strArgument
-            $ mconcat [ Opt.help "Name of package whose version you want to check.",
-                        Opt.metavar "PACKAGE_NAME"
-                      ]
+  queries = some $ parseQuery <$> (query_package <|> query_cabal)
+  query_package = Opt.strArgument
+                  $ mconcat [ Opt.help "Name of package whose version you want to check.",
+                              Opt.metavar "PACKAGE_NAME"
+                            ]
+  query_cabal = Opt.strArgument
+                $ mconcat [ Opt.help "(EXPERIMENTAL) .cabal file name. It checks versions of packages in build-deps lists.",
+                            Opt.metavar "CABAL_FILEPATH"
+                          ]
   network = not <$> no_network
   no_network = Opt.switch $ mconcat [ Opt.long "no-network",
                                       Opt.help "Forbid network access."
diff --git a/src/Staversion/Internal/Exec.hs b/src/Staversion/Internal/Exec.hs
--- a/src/Staversion/Internal/Exec.hs
+++ b/src/Staversion/Internal/Exec.hs
@@ -6,7 +6,9 @@
 -- __This is an internal module. End-users should not use it.__
 module Staversion.Internal.Exec
        ( main,
-         processCommand
+         processCommand,
+         -- * Only for testing
+         _processCommandWithCustomBuildPlanManager
        ) where
 
 import Control.Applicative ((<$>))
@@ -16,48 +18,84 @@
 import qualified Data.Text.Lazy.IO as TLIO
 
 import Staversion.Internal.BuildPlan
-  ( BuildPlan, packageVersion, newBuildPlanManager, loadBuildPlan
+  ( BuildPlan, packageVersion, buildPlanSource,
+    newBuildPlanManager, loadBuildPlan,
+    BuildPlanManager
   )
 import Staversion.Internal.Command
   ( parseCommandArgs,
     Command(..)
   )
 import Staversion.Internal.Format (formatResultsCabal)
-import Staversion.Internal.Log (logDebug, logError)
+import Staversion.Internal.Log (logDebug, logError, Logger)
 import Staversion.Internal.Query
-  ( Query(..), Result(..), PackageSource(..), PackageName,
-    resultVersionsFromList, ResultVersions,
-    ErrorMsg
+  ( Query(..), PackageSource(..), PackageName, ErrorMsg
   )
+import Staversion.Internal.Result (Result(..), ResultBody(..))
+import Staversion.Internal.Cabal (BuildDepends(..), loadCabalFile)
 
 main :: IO ()
 main = do
   comm <- parseCommandArgs
   (TLIO.putStr . formatResultsCabal) =<< (processCommand comm)
 
+data ResolvedQuery = RQueryOne Query PackageName
+                   | RQueryCabal Query FilePath BuildDepends
+                   deriving (Show, Eq, Ord)
+
 processCommand :: Command -> IO [Result]
-processCommand comm = impl where
+processCommand = _processCommandWithCustomBuildPlanManager return
+
+_processCommandWithCustomBuildPlanManager :: (BuildPlanManager -> IO BuildPlanManager) -> Command -> IO [Result]
+_processCommandWithCustomBuildPlanManager customBPM comm = impl where
   impl = do
-    bp_man <- newBuildPlanManager (commBuildPlanDir comm) (commLogger comm) (commAllowNetwork comm)
-    fmap concat $ mapM (processQueriesIn bp_man) $ commSources comm
+    bp_man <- customBPM =<< newBuildPlanManager (commBuildPlanDir comm) (commLogger comm) (commAllowNetwork comm)
+    rqueries <- resolveQueries' logger $ commQueries comm
+    fmap concat $ mapM (processQueriesIn bp_man rqueries) $ commSources comm
   logger = commLogger comm
-  processQueriesIn bp_man source = do
-    queried_names <- fmap (nub . concat) $ mapM getQueriedPackageNames $ commQueries comm
+  processQueriesIn bp_man rqueries source = do
+    let queried_names = nub $ concat $ map getQueriedPackageNames $ rqueries
     logDebug logger ("Retrieve package source " ++ show source)
     e_build_plan <- loadBuildPlan bp_man queried_names source
     logBuildPlanResult e_build_plan
-    return $ map (makeResult source e_build_plan) $ commQueries comm
-  makeResult source e_build_plan query = case e_build_plan of
-    Left error_msg -> Result { resultIn = source, resultFor = query, resultVersions = Left error_msg }
-    Right build_plan -> Result { resultIn = source, resultFor = query,
-                                 resultVersions = Right $ searchVersions build_plan query
+    return $ map (makeResult source e_build_plan) $ rqueries
+  makeResult source e_build_plan rquery = case e_build_plan of
+    Left error_msg -> Result { resultIn = source, resultReallyIn = Nothing,
+                               resultFor = originalQuery rquery, resultBody = Left error_msg
+                             }
+    Right build_plan -> Result { resultIn = source,
+                                 resultReallyIn = if source == real_source then Nothing else Just real_source,
+                                 resultFor = originalQuery rquery,
+                                 resultBody = Right $ searchVersions build_plan rquery
                                }
+      where real_source = buildPlanSource build_plan
   logBuildPlanResult (Right _) = logDebug logger ("Successfully retrieved build plan.")
   logBuildPlanResult (Left error_msg) = logError logger ("Failed to load build plan: " ++ error_msg)
 
-searchVersions :: BuildPlan -> Query -> ResultVersions
-searchVersions build_plan (QueryName package_name) =
-  resultVersionsFromList [(package_name, packageVersion build_plan package_name)]
+resolveQueries' :: Logger -> [Query] -> IO [ResolvedQuery]
+resolveQueries' logger = fmap concat . mapM resolveQ where
+  resolveQ query = reportAndFilterError =<< resolveQuery logger query
+  reportAndFilterError (Left err) = logError logger err >> return []
+  reportAndFilterError (Right ret) = return ret
 
-getQueriedPackageNames :: Query -> IO [PackageName]
-getQueriedPackageNames (QueryName n) = return [n]
+resolveQuery :: Logger -> Query -> IO (Either ErrorMsg [ResolvedQuery])
+resolveQuery _ q@(QueryName name) = return $ Right $ [RQueryOne q name]
+resolveQuery logger q@(QueryCabalFile file) = do
+  logDebug logger ("Load " ++ file ++ " for build-depends fields.")
+  (fmap . fmap) processBuildDependsList $ loadCabalFile file
+  where
+    processBuildDependsList = map (RQueryCabal q file) . filter ((0 <) . length . depsPackages)
+
+originalQuery :: ResolvedQuery -> Query
+originalQuery (RQueryOne q _) = q
+originalQuery (RQueryCabal q _ _) = q
+
+searchVersions :: BuildPlan -> ResolvedQuery -> ResultBody
+searchVersions build_plan (RQueryOne _ package_name) = SimpleResultBody package_name $ packageVersion build_plan package_name
+searchVersions build_plan (RQueryCabal _ cabal_file build_deps) = CabalResultBody cabal_file target ret_list where
+  target = depsTarget build_deps
+  ret_list = map (\pname -> (pname, packageVersion build_plan pname)) $ depsPackages build_deps
+
+getQueriedPackageNames :: ResolvedQuery -> [PackageName]
+getQueriedPackageNames (RQueryOne _ n) = [n]
+getQueriedPackageNames (RQueryCabal _ _ bd) = depsPackages bd
diff --git a/src/Staversion/Internal/Format.hs b/src/Staversion/Internal/Format.hs
--- a/src/Staversion/Internal/Format.hs
+++ b/src/Staversion/Internal/Format.hs
@@ -13,18 +13,19 @@
 import Data.Monoid (mempty, mconcat, (<>))
 import qualified Data.Text.Lazy as TL
 import Data.Text.Lazy.Builder (Builder, toLazyText, fromText, fromString)
-import Data.Version (showVersion)
+import Data.Version (showVersion, Version)
 
 import Staversion.Internal.Query
-  ( Result(..), Query(..),
+  ( Query(..),
     sourceDesc,
-    ResultVersions,
-    resultVersionsToList
+    PackageName
   )
+import Staversion.Internal.Result (Result(..), ResultBody(..))
+import Staversion.Internal.Cabal (Target(..))
 
 -- | format 'Result's like it's in build-depends in .cabal files.
 formatResultsCabal :: [Result] -> TL.Text
-formatResultsCabal = toLazyText . mconcat . map formatGroupedResultsCabal . groupAllPreservingOrderBy ((==) `on` resultIn)
+formatResultsCabal = toLazyText . mconcat . map formatResultBlock . makeSourceBlocks
 
 groupAllPreservingOrderBy :: (a -> a -> Bool) -> [a] -> [[a]]
 groupAllPreservingOrderBy sameGroup = map snd  . foldr f [] where
@@ -32,31 +33,63 @@
     update heads [] = (item, [item]) : heads
     update heads (cur@(cur_item, cur_list) : rest) =
       if sameGroup item cur_item
-      then heads ++ ( (cur_item, item : cur_list) : rest )
+      then ((cur_item, item : cur_list) : heads) ++ rest 
       else update (heads ++ [cur]) rest
 
-formatGroupedResultsCabal :: [Result] -> Builder
-formatGroupedResultsCabal [] = mempty
-formatGroupedResultsCabal results@(head_ret : _) = header <> (concatLines $ single_result_output =<< results) where
-  header = "------ " <> (fromText $ sourceDesc $ resultIn head_ret) <> "\n"
-  single_result_output ret = case resultVersions ret of
-    Left _ -> [Left $ error_result ret]
-    Right versions -> formatVersionsCabal (resultFor ret) versions
-  error_result ret = case resultFor ret of
-    QueryName query_name -> "-- " <> fromText query_name <> " ERROR"
-  concatLines ebuilder_lines = (mconcat $ intersperse "\n" $ map (either id id) $ tailCommas ebuilder_lines) <> "\n\n"
-  tailCommas = fst . foldr f ([], False) where
-    -- flag: True if it has already encountered the last Right element in the list.
-    f eb (ret, flag) = let (next_e, next_flag) = getNext ret flag eb
-                       in (next_e:ret, next_flag)
-    getNext [] flag e@(Left _) = (e, flag)
-    getNext _ flag (Left b) = (Left (b <> ","), flag)
-    getNext _ False e@(Right _) = (e, True)
-    getNext _ True (Right b) = (Right (b <> ","), True)
+-- | 'Left' lines and 'Right' lines are handled differently by
+-- 'formatResultBlock'. It puts commas at the right places assuming
+-- 'Left' lines are commented out.
+type ResultLine = Either Builder Builder
 
-formatVersionsCabal :: Query -> ResultVersions -> [Either Builder Builder]
-formatVersionsCabal (QueryName _) rvers = map format $ resultVersionsToList rvers where
-  format (name, mver) = case mver of
-    Nothing -> Left $ "-- " <> fromText name <> " N/A"
-    Just ver -> Right $ fromText name <> " ==" <> (fromString $ showVersion ver)
+data ResultBlock = RBHead Builder [ResultBlock] -- ^ header and child blocks
+                 | RBLines [ResultLine] -- ^ a block, which consists of some lines.
 
+makeSourceBlocks :: [Result] -> [ResultBlock]
+makeSourceBlocks = map sourceBlock . groupAllPreservingOrderBy ((==) `on` resultIn) where
+  sourceBlock [] = RBLines []
+  sourceBlock results@(head_ret : _) = RBHead header $ makeQueryBlocks results where
+    header = "------ " <> (fromText $ sourceDesc $ resultIn head_ret) <> header_real_source
+    header_real_source = maybe "" fromText $ resultReallyIn head_ret >>= \real_source -> do
+      return (" (" <> sourceDesc real_source <> ")")
+
+makeQueryBlocks :: [Result] -> [ResultBlock]
+makeQueryBlocks = uncurry prependLines . foldr f ([], []) where
+  prependLines blocks [] = blocks
+  prependLines blocks rlines = (RBLines rlines) : blocks
+  f ret (blocks, rlines) = case (resultFor ret, resultBody ret) of
+    (_, Right (SimpleResultBody name mver)) -> (blocks, (versionLine name mver) : rlines)
+    (_, Right (CabalResultBody file target pairs)) -> (cabalFileSuccessBlock file target pairs : prependLines blocks rlines, [])
+    ((QueryName name), Left _) -> (blocks, (packageErrorLine name) : rlines)
+    ((QueryCabalFile file), Left _) -> (cabalFileErrorBlock file : prependLines blocks rlines, [])
+
+versionLine :: PackageName -> Maybe Version -> ResultLine
+versionLine name Nothing = Left $ "-- " <> fromText name <> " N/A"
+versionLine name (Just ver) = Right $ fromText name <> " ==" <> (fromString $ showVersion ver)
+
+packageErrorLine :: PackageName -> ResultLine
+packageErrorLine name = Left $ "-- " <> fromText name <> " ERROR"
+
+cabalFileErrorBlock :: FilePath -> ResultBlock
+cabalFileErrorBlock file = RBLines [Left line] where
+  line = "-- " <> fromString file <> " ERROR"
+
+cabalFileSuccessBlock :: FilePath -> Target -> [(PackageName, Maybe Version)] -> ResultBlock
+cabalFileSuccessBlock file target pairs = RBHead header [RBLines $ map (uncurry versionLine) pairs] where
+  header = "-- " <> fromString file <> " - " <> target_text
+  target_text = case target of
+    TargetLibrary -> "library"
+    TargetExecutable n -> "executable " <> fromText n
+    TargetTestSuite n -> "test-suite " <> fromText n
+    TargetBenchmark n -> "benchmark " <> fromText n
+
+formatResultBlock :: ResultBlock -> Builder
+formatResultBlock (RBHead header blocks) = header <> "\n" <> mconcat (map formatResultBlock blocks)
+formatResultBlock (RBLines rlines) = (mconcat $ map ((<> "\n") . either id id) $ tailCommas rlines) <> "\n" where
+  tailCommas = fst . foldr f ([], False)
+               -- flag: True if it has already encountered the last Right element in the list.
+  f eb (ret, flag) = let (next_e, next_flag) = getNext ret flag eb
+                     in (next_e:ret, next_flag)
+  getNext [] flag e@(Left _) = (e, flag)
+  getNext _ flag (Left b) = (Left (b <> ","), flag)
+  getNext _ False e@(Right _) = (e, True)
+  getNext _ True (Right b) = (Right (b <> ","), True)
diff --git a/src/Staversion/Internal/Query.hs b/src/Staversion/Internal/Query.hs
--- a/src/Staversion/Internal/Query.hs
+++ b/src/Staversion/Internal/Query.hs
@@ -8,18 +8,14 @@
        ( PackageName,
          Resolver,
          PackageSource(..),
+         sourceDesc,
          Query(..),
-         ErrorMsg,
-         Result(..),
-         ResultVersions,
-         resultVersionsFromList,
-         resultVersionsToList,
-         sourceDesc
+         parseQuery,
+         ErrorMsg
        ) where
 
-import qualified Data.HashMap.Strict as HM
+import Data.List (isSuffixOf)
 import Data.Text (Text, pack)
-import Data.Version (Version)
 
 type PackageName = Text
 
@@ -33,28 +29,17 @@
 
 -- | Query for package version(s).
 data Query = QueryName PackageName
+           | QueryCabalFile FilePath
            deriving (Show,Eq,Ord)
 
 type ErrorMsg = String
 
--- | Result for a query.
-data Result = Result { resultIn :: PackageSource,
-                       resultFor :: Query,
-                       resultVersions :: Either ErrorMsg ResultVersions
-                     } deriving (Show,Eq)
-
-
--- | The obtained version map.
-newtype ResultVersions = ResultVersions (HM.HashMap PackageName (Maybe Version))
-                       deriving (Show,Eq)
-
-resultVersionsFromList :: [(PackageName, Maybe Version)] -> ResultVersions
-resultVersionsFromList = ResultVersions . HM.fromList
-
-resultVersionsToList :: ResultVersions -> [(PackageName, Maybe Version)]
-resultVersionsToList (ResultVersions m) = HM.toList m
-
 -- | description of a 'PackageSource'.
 sourceDesc :: PackageSource -> Text
 sourceDesc (SourceStackage r) = pack r
 sourceDesc SourceHackage = "latest in hackage"
+
+parseQuery :: String -> Query
+parseQuery s = if ".cabal" `isSuffixOf` s
+               then QueryCabalFile s
+               else QueryName $ pack s
diff --git a/src/Staversion/Internal/Result.hs b/src/Staversion/Internal/Result.hs
new file mode 100644
--- /dev/null
+++ b/src/Staversion/Internal/Result.hs
@@ -0,0 +1,28 @@
+-- |
+-- Module: Staversion.Internal.Result
+-- Description: Result data type and its utilities
+-- Maintainer: Toshio Ito <debug.ito@gmail.com>
+--
+-- __This is an internal module. End-users should not use it.__
+module Staversion.Internal.Result
+       ( Result(..),
+         ResultBody(..)
+       ) where
+
+import Data.Version (Version)
+import Staversion.Internal.Query
+  ( Query, PackageSource, ErrorMsg, PackageName
+  )
+import Staversion.Internal.Cabal (Target)
+
+-- | Result for a query.
+data Result = Result { resultIn :: PackageSource,
+                       resultFor :: Query,
+                       resultReallyIn :: Maybe PackageSource,
+                       -- ^ the true PackageSource resolved (or redirected) from 'resultIn', if any.
+                       resultBody :: Either ErrorMsg ResultBody
+                     } deriving (Show,Eq)
+
+data ResultBody = SimpleResultBody PackageName (Maybe Version)
+                | CabalResultBody FilePath Target [(PackageName, (Maybe Version))]
+                deriving (Show,Eq)
diff --git a/staversion.cabal b/staversion.cabal
--- a/staversion.cabal
+++ b/staversion.cabal
@@ -1,5 +1,5 @@
 name:                   staversion
-version:                0.1.2.0
+version:                0.1.3.0
 author:                 Toshio Ito <debug.ito@gmail.com>
 maintainer:             Toshio Ito <debug.ito@gmail.com>
 license:                BSD3
@@ -16,7 +16,10 @@
                         test/data/lts-4.2.yaml,
                         test/data/lts-2.22_conpact.yaml,
                         test/data/snapshots.json,
-                        test/data/aeson_preferred.json
+                        test/data/aeson_preferred.json,
+                        test/data/doctest.cabal_test,
+                        test/data/conduit.cabal_test,
+                        test/data/foobar.cabal_test
                         
 homepage:               https://github.com/debug-ito/staversion
 bug-reports:            https://github.com/debug-ito/staversion/issues
@@ -26,12 +29,14 @@
   hs-source-dirs:       src
   ghc-options:          -Wall -fno-warn-unused-imports
   default-extensions:   OverloadedStrings
-  other-extensions:     CPP, DeriveDataTypeable, GeneralizedNewtypeDeriving
+  other-extensions:     CPP, DeriveDataTypeable, TupleSections
   exposed-modules:      Staversion.Internal.BuildPlan,
                         Staversion.Internal.BuildPlan.Stackage,
                         Staversion.Internal.BuildPlan.Hackage,
                         Staversion.Internal.BuildPlan.Version,
                         Staversion.Internal.Query,
+                        Staversion.Internal.Result,
+                        Staversion.Internal.Cabal,
                         Staversion.Internal.Command,
                         Staversion.Internal.Log,
                         Staversion.Internal.Exec,
@@ -45,14 +50,15 @@
                         bytestring >=0.10.0 && <0.11,
                         yaml >=0.8.3 && <0.9,
                         filepath >=1.3.0 && <1.5,
-                        directory >=1.2.0 && <1.3,
+                        directory >=1.2.0 && <1.4,
                         optparse-applicative >=0.11.0 && <0.14,
                         containers >=0.5.5 && <0.6,
                         http-client >=0.4.18 && <0.6,
                         http-client-tls >=0.2.2 && <0.4,
                         http-types >=0.8.6 && <0.10,
                         transformers >=0.3.0 && <0.6,
-                        transformers-compat >=0.4.0 && <0.6
+                        transformers-compat >=0.4.0 && <0.6,
+                        megaparsec >=4.2.0 && <5.2
 
 executable staversion
   default-language:     Haskell2010
@@ -78,10 +84,11 @@
                         Staversion.Internal.BuildPlan.VersionSpec,
                         Staversion.Internal.ExecSpec,
                         Staversion.Internal.FormatSpec,
+                        Staversion.Internal.CabalSpec,
                         Staversion.Internal.TestUtil
   build-depends:        base, staversion, text, filepath, bytestring,
                         hspec >=2.1.7 && <2.4,
-                        QuickCheck
+                        QuickCheck >=2.8.1 && <2.10
 
 flag network-test
   description: Enable network tests.
diff --git a/test/NetworkTest.hs b/test/NetworkTest.hs
--- a/test/NetworkTest.hs
+++ b/test/NetworkTest.hs
@@ -1,7 +1,9 @@
 module Main (main,spec) where
 
 import Control.Applicative ((<$>))
+import Control.Monad (forM_)
 import qualified Data.ByteString.Lazy as BSL
+import Data.Word (Word)
 import Network.HTTP.Client (newManager, Manager)
 import Network.HTTP.Client.TLS (tlsManagerSettings)
 import Test.Hspec
@@ -12,21 +14,23 @@
 import Staversion.Internal.BuildPlan
   ( newBuildPlanManager,
     loadBuildPlan,
-    packageVersion
+    packageVersion,
+    buildPlanSource
   )
 import Staversion.Internal.BuildPlan.Hackage (fetchPreferredVersions, latestVersion)
 import Staversion.Internal.BuildPlan.Stackage
   ( fetchDisambiguator,
     fetchBuildPlanYAML,
-    PartialResolver(..), ExactResolver(..)
+    PartialResolver(..), ExactResolver(..),
+    parseResolverString
   )
 import Staversion.Internal.Command (Command(..))
 import Staversion.Internal.Exec (processCommand)
 import Staversion.Internal.Log (defaultLogger, Logger(loggerThreshold))
 import Staversion.Internal.Query
- ( PackageSource(..), ErrorMsg, Query(..), Result(..),
-   resultVersionsToList
+ ( PackageSource(..), ErrorMsg, Query(..)
  )
+import Staversion.Internal.Result (Result(..), ResultBody(..))
 
 main :: IO ()
 main = hspec spec
@@ -45,7 +49,10 @@
       e_dis <- fetchDisambiguator man
       case e_dis of
        Left err -> expectationFailure ("should not be Left: " ++ err)
-       Right dis -> dis (PartialLTSMajor 2) `shouldBe` Just (ExactLTS 2 22)
+       Right dis -> forM_ [(0,7), (1,15), (2,22), (3,22), (4,2), (5,18), (6,24), (7,8)] $ \(major, minor_min) -> do
+         case dis (PartialLTSMajor major) of
+          Just eresolver -> (PartialExact eresolver) `shouldBeAboveLTSMinorResolver` (major,minor_min)
+          Nothing -> expectationFailure "Unexpected disambiguation error."
   describe "fetchBuildPlanYAML" $ do
     it "fetches a LTS build plan" $ \man -> do
       raw_yaml <- fetchBuildPlanYAML man (ExactLTS 2 22)
@@ -66,19 +73,34 @@
 isJustAnd :: Maybe a -> (a -> Bool) -> Bool
 isJustAnd m p = maybe False p m
 
+shouldBeAboveLTSMinorResolver :: PartialResolver -> (Word,Word) -> IO ()
+shouldBeAboveLTSMinorResolver (PartialExact (ExactLTS got_major got_minor)) (lts_major, lts_minor_min) = do
+  got_major `shouldBe` lts_major
+  got_minor `shouldSatisfy` (>= lts_minor_min)
+shouldBeAboveLTSMinorResolver pr _ = expectationFailure ("Unexpected PartialResolver: " ++ show pr)
+
+shouldBeAboveLTSMinor :: PackageSource -> (Word, Word) -> IO ()
+shouldBeAboveLTSMinor (SourceStackage resolver) expected_lts =
+  case parseResolverString resolver of
+   Just presolver -> presolver `shouldBeAboveLTSMinorResolver` expected_lts
+   ret_parse -> expectationFailure ("Unexpected parse result: " ++ show ret_parse)
+shouldBeAboveLTSMinor source _ = expectationFailure ("Unexpected PackageSource: " ++ show source)
+
 spec_BuildPlan :: Spec
 spec_BuildPlan = describe "BuildPlan" $ do
   describe "loadBuildPlan from Stackage" $ do
     it "disambiguates LTS version and fetches a valid BuildPlan" $ do
       bp_man <- newBuildPlanManager "." quietLogger True
       bp <- expectRight "loadBuildPlan failed: " =<< loadBuildPlan bp_man [] (SourceStackage "lts-5")
-      packageVersion bp "base" `shouldBe` Just (ver [4,8,2,0])
-      packageVersion bp "bytestring" `shouldBe` Just (ver [0,10,6,0])
-      packageVersion bp "conduit" `shouldBe` Just (ver [1,2,6,6])
+      buildPlanSource bp `shouldBeAboveLTSMinor` (5,18)
+      packageVersion bp "base" `shouldSatisfy` (`isJustAnd` (>= ver [4,8,2,0]))
+      packageVersion bp "bytestring" `shouldSatisfy` (`isJustAnd` (>= ver [0,10,6,0]))
+      packageVersion bp "conduit" `shouldSatisfy` (`isJustAnd` (>= ver [1,2,6,6]))
   describe "loadBuildPlan from Hackage" $ do
     it "fetches BuildPlan for queried packages" $ do
       bp_man <- newBuildPlanManager "." quietLogger True
       bp <- expectRight "loadBuildPlan failed: " =<< loadBuildPlan bp_man ["base", "lens", "transformers"] SourceHackage
+      buildPlanSource bp `shouldBe` SourceHackage
       packageVersion bp "base" `shouldSatisfy` (`isJustAnd` (>= ver [4,9,0,0]))
       packageVersion bp "lens" `shouldSatisfy` (`isJustAnd` (>= ver [4,15,1]))
       packageVersion bp "transformers" `shouldSatisfy` (`isJustAnd` (>= ver [0,5,2,0]))
@@ -95,9 +117,28 @@
 
 spec_Exec :: Spec
 spec_Exec = describe "Exec" $ describe "processCommand" $ do
-  specify "search hackage" $ do
+  it "should fill resultReallyIn field if necesssary" $ do
     let comm = Command { commBuildPlanDir = ".",
                          commLogger = quietLogger,
+                         commSources = [SourceStackage "lts-3"],
+                         commQueries = [QueryName "base"],
+                         commAllowNetwork = True
+                       }
+    [ret] <- processCommand comm
+    resultIn ret `shouldBe` SourceStackage "lts-3"
+    resultFor ret `shouldBe` QueryName "base"
+    case resultBody ret of
+     Right (SimpleResultBody got_name (Just got_version)) -> do
+       got_name `shouldBe` "base"
+       got_version `shouldSatisfy` (>= ver [4,8,1,0])
+     body -> expectationFailure ("Unexpected body: " ++ show body)
+    case resultReallyIn ret of
+     Just source -> source `shouldBeAboveLTSMinor` (3,22)
+     ret_really_in -> expectationFailure ("Unexpected resultReallyIn: " ++ show ret_really_in)
+
+  it "should search hackage" $ do
+    let comm = Command { commBuildPlanDir = ".",
+                         commLogger = quietLogger,
                          commSources = [SourceHackage],
                          commQueries = [QueryName "base"],
                          commAllowNetwork = True
@@ -105,8 +146,13 @@
     [ret] <- processCommand comm
     resultIn ret `shouldBe` SourceHackage
     resultFor ret `shouldBe` QueryName "base"
-    [(got_name, Just got_version)] <- resultVersionsToList <$> expectRight "processCommand error" (resultVersions ret)
-    got_name `shouldBe` "base"
-    got_version `shouldSatisfy` (>= ver [4,9,0,0]) 
+    resultReallyIn ret `shouldBe` Nothing
+    case resultBody ret of
+     Right (SimpleResultBody got_name (Just got_version)) -> do
+       got_name `shouldBe` "base"
+       got_version `shouldSatisfy` (>= ver [4,9,0,0])
+     body -> expectationFailure ("Unexpected body: " ++ show body)
+    
+    
     
     
diff --git a/test/Staversion/Internal/BuildPlanSpec.hs b/test/Staversion/Internal/BuildPlanSpec.hs
--- a/test/Staversion/Internal/BuildPlanSpec.hs
+++ b/test/Staversion/Internal/BuildPlanSpec.hs
@@ -2,23 +2,21 @@
 
 import Data.Text (Text, pack)
 import Data.Version (Version(..))
+import Data.Word (Word)
 import System.FilePath ((</>), (<.>))
 import Test.Hspec
 
 import Staversion.Internal.Log (defaultLogger, loggerThreshold)
 import Staversion.Internal.Query (PackageName, PackageSource(..))
 import Staversion.Internal.BuildPlan
-  ( BuildPlan, 
-    loadBuildPlanYAML, 
+  ( BuildPlanMap, 
+    loadBuildPlanMapYAML, 
     packageVersion,
     BuildPlanManager,
     newBuildPlanManager,
-    _setDisambiguator,
-    loadBuildPlan
-  )
-import Staversion.Internal.BuildPlan.Stackage
-  ( Disambiguator,
-    PartialResolver(..), ExactResolver(..)
+    _setLTSDisambiguator,
+    loadBuildPlan,
+    buildPlanSource
   )
 
 main :: IO ()
@@ -31,7 +29,7 @@
 
 packageVersion_spec :: Spec
 packageVersion_spec = describe "packageVersion" $ do
-  forBuildPlan "conpact_build_plan" $ \loader -> do
+  forBuildPlanMap "conpact_build_plan" $ \loader -> do
     specify "drawille -> 0.1.0.6" $ do
       loadVersion "drawille" loader `shouldReturn` Just (Version [0,1,0,6] [])
     specify "unknown -> Nothing" $ do
@@ -41,27 +39,27 @@
     specify "base -> 4.8.2.0" $ do
       loadVersion "base" loader `shouldReturn` Just (Version [4,8,2,0] [])
 
-  forBuildPlan "lts-4.2" $ \loader -> do
+  forBuildPlanMap "lts-4.2" $ \loader -> do
     specify "conduit -> 1.2.6.1" $ do
       loadVersion "conduit" loader `shouldReturn` Just (Version [1,2,6,1] [])
     specify "transformers -> 0.4.2.0" $ do
       loadVersion "transformers" loader `shouldReturn` Just (Version [0,4,2,0] [])
 
 
-forBuildPlan :: String -> (IO BuildPlan -> Spec) -> Spec
-forBuildPlan build_plan_base testWith = describe build_plan_base (testWith loader) where
-  loader = either error return =<< loadBuildPlanYAML ("test" </> "data" </> build_plan_base <.> "yaml")
+forBuildPlanMap :: String -> (IO BuildPlanMap -> Spec) -> Spec
+forBuildPlanMap build_plan_base testWith = describe build_plan_base (testWith loader) where
+  loader = either error return =<< loadBuildPlanMapYAML ("test" </> "data" </> build_plan_base <.> "yaml")
 
-loadVersion :: PackageName -> IO BuildPlan -> IO (Maybe Version)
+loadVersion :: PackageName -> IO BuildPlanMap -> IO (Maybe Version)
 loadVersion package_name loader = do
   plan <- loader
   return $ packageVersion plan package_name
 
 
-mockBuildPlanManager :: Disambiguator -> IO BuildPlanManager
-mockBuildPlanManager disam = do
+mockBuildPlanManager :: Word -> Word -> IO BuildPlanManager
+mockBuildPlanManager lts_major lts_minor = do
   bp_man <- newBuildPlanManager build_plan_dir logger False
-  _setDisambiguator bp_man (Just disam)
+  _setLTSDisambiguator bp_man lts_major lts_minor
   return bp_man
   where
     build_plan_dir = "test" </> "data"
@@ -70,8 +68,7 @@
 loadBuildPlan_spec :: Spec
 loadBuildPlan_spec = describe "loadBuildPlan" $ do
   it "reads local file after disambiguation" $ do
-    let disam (PartialLTSLatest) = Just $ ExactLTS 4 2
-        disam _ = Nothing
-    bp_man <- mockBuildPlanManager disam
+    bp_man <- mockBuildPlanManager 4 2
     bp <- either (\e -> error ("Error: " ++ e)) return =<< loadBuildPlan bp_man [] (SourceStackage "lts")
     packageVersion bp "base" `shouldBe` (Just $ Version [4,8,2,0] [])
+    buildPlanSource bp `shouldBe` SourceStackage "lts-4.2"
diff --git a/test/Staversion/Internal/CabalSpec.hs b/test/Staversion/Internal/CabalSpec.hs
new file mode 100644
--- /dev/null
+++ b/test/Staversion/Internal/CabalSpec.hs
@@ -0,0 +1,112 @@
+module Staversion.Internal.CabalSpec (main,spec) where
+
+import System.FilePath ((</>), (<.>))
+import Test.Hspec
+
+import Staversion.Internal.Cabal (loadCabalFile, BuildDepends(..), Target(..))
+
+main :: IO ()
+main = hspec spec
+
+shouldBeParsedTo :: FilePath -> [BuildDepends] -> IO ()
+shouldBeParsedTo cabal_file expectation = do
+  got_deps <- either error return  =<< loadCabalFile ("test" </> "data" </> cabal_file)
+  got_deps `shouldBe` expectation
+
+spec :: Spec
+spec = describe "loadCabalFile" $ do
+  it "should load library, executable and test-suite targets" $ do
+    "doctest.cabal_test" `shouldBeParsedTo`
+      [ BuildDepends { depsTarget = TargetLibrary,
+                       depsPackages = [ "base",
+                                        "base-compat",
+                                        "ghc",
+                                        "syb",
+                                        "deepseq",
+                                        "directory",
+                                        "filepath",
+                                        "process",
+                                        "ghc-paths",
+                                        "transformers"
+                                      ]
+                     },
+        BuildDepends { depsTarget = TargetExecutable "doctest",
+                       depsPackages = [ "base",
+                                        "doctest"
+                                      ]
+                     },
+        BuildDepends { depsTarget = TargetTestSuite "spec",
+                       depsPackages = [ "base",
+                                        "ghc",
+                                        "syb",
+                                        "deepseq",
+                                        "directory",
+                                        "filepath",
+                                        "process",
+                                        "ghc-paths",
+                                        "transformers",
+                                        "base-compat",
+                                        "HUnit",
+                                        "hspec",
+                                        "QuickCheck",
+                                        "stringbuilder",
+                                        "silently",
+                                        "setenv",
+                                        "with-location"
+                                      ]
+                     },
+        BuildDepends { depsTarget = TargetTestSuite "doctests",
+                       depsPackages = [ "base", "doctest"
+                                      ]
+                     }
+      ]
+  it "should merge conditional build-depends" $ do
+    "conduit.cabal_test" `shouldBeParsedTo`
+      [ BuildDepends { depsTarget = TargetLibrary,
+                       depsPackages = [ "base",
+                                        "resourcet",
+                                        "exceptions",
+                                        "lifted-base",
+                                        "transformers-base",
+                                        "transformers",
+                                        "mtl",
+                                        "mmorph",
+                                        "monad-control",
+                                        "void"
+                                      ]
+                     },
+        BuildDepends { depsTarget = TargetTestSuite "test",
+                       depsPackages = [ "conduit",
+                                        "base",
+                                        "hspec",
+                                        "QuickCheck",
+                                        "transformers",
+                                        "mtl",
+                                        "resourcet",
+                                        "containers",
+                                        "exceptions",
+                                        "safe",
+                                        "void"
+                                      ]
+                     },
+        BuildDepends { depsTarget = TargetBenchmark "optimize-201408",
+                       depsPackages = [ "base",
+                                        "conduit",
+                                        "vector",
+                                        "deepseq",
+                                        "containers",
+                                        "transformers",
+                                        "hspec",
+                                        "mwc-random",
+                                        "criterion",
+                                        "kan-extensions"
+                                      ]
+                     },
+        BuildDepends { depsTarget = TargetBenchmark "unfused",
+                       depsPackages = [ "base",
+                                        "conduit",
+                                        "criterion",
+                                        "transformers"
+                                      ]
+                     }
+      ]
diff --git a/test/Staversion/Internal/ExecSpec.hs b/test/Staversion/Internal/ExecSpec.hs
--- a/test/Staversion/Internal/ExecSpec.hs
+++ b/test/Staversion/Internal/ExecSpec.hs
@@ -6,32 +6,43 @@
 import System.FilePath ((</>))
 import Test.Hspec
 
+import Staversion.Internal.BuildPlan (_setLTSDisambiguator)
 import Staversion.Internal.Command (Command(..))
-import Staversion.Internal.Exec (processCommand)
+import Staversion.Internal.Exec
+  ( processCommand,
+    _processCommandWithCustomBuildPlanManager
+  )
 import Staversion.Internal.Query
   ( PackageName,
     Query(..),
     PackageSource(..),
-    Result(..),
-    ResultVersions,
-    resultVersionsFromList,
     ErrorMsg
   )
+import Staversion.Internal.Result
+  ( Result(..),
+    ResultBody(..)
+  )
 import Staversion.Internal.Log (defaultLogger, _mockLogger, Logger(loggerThreshold), LogLevel(..))
+import Staversion.Internal.Cabal (Target(..))
 
-import Staversion.Internal.TestUtil (ver, rvers)
+import Staversion.Internal.TestUtil (ver, simpleResultBody, verPairs)
 
 main :: IO ()
 main = hspec spec
 
 spec :: Spec
-spec = describe "processCommand" $ do
+spec = do
+  spec_processCommand_basic
+  spec_processCommand_disambiguates
+
+spec_processCommand_basic :: Spec
+spec_processCommand_basic = describe "processCommand" $ do
   specify "QueryName, SourceStackage, hit" $ do
     singleCase (SourceStackage "conpact_build_plan") (QueryName "drawille")
-      (Right $ rvers [("drawille", Just $ ver [0,1,0,6])])
+      (Right $ simpleResultBody "drawille" [0,1,0,6])
   specify "QueryName, SourceStackage, miss" $ do
     singleCase (SourceStackage "conpact_build_plan") (QueryName "unknown")
-      (Right $ rvers [("unknown", Nothing)])
+      (Right $ SimpleResultBody "unknown" Nothing)
   specify "QueryName, SourceStackage, source not found" $ do
     (logger, logs) <- _mockLogger
     let src = SourceStackage "unknown"
@@ -43,7 +54,7 @@
     [got_ret] <- processCommand comm
     resultIn got_ret `shouldBe` src
     resultFor got_ret `shouldBe` query
-    case resultVersions got_ret of
+    case resultBody got_ret of
       Right _ -> expectationFailure "it should fail"
       Left _ -> return ()
     got_logs <- readIORef logs
@@ -58,32 +69,55 @@
         qc = QueryName "conduit"
         qa = QueryName "aeson"
         comm = baseCommand { commSources = [src2, src7], commQueries = [qc, qa] }
-        expected = [ Result { resultIn = src2, resultFor = qc,
-                              resultVersions = Right $ rvers [("conduit", Just $ ver [1,2,5])]
+        expected = [ Result { resultIn = src2, resultReallyIn = Nothing, resultFor = qc,
+                              resultBody = Right $ simpleResultBody "conduit" [1,2,5]
                             },
-                     Result { resultIn = src2, resultFor = qa,
-                              resultVersions = Right $ rvers [("aeson", Just $ ver [0,8,0,2])]
+                     Result { resultIn = src2, resultReallyIn = Nothing, resultFor = qa,
+                              resultBody = Right $ simpleResultBody "aeson" [0,8,0,2]
                             },
-                     Result { resultIn = src7, resultFor = qc,
-                              resultVersions = Right $ rvers [("conduit", Just $ ver [1,2,7])]
+                     Result { resultIn = src7, resultReallyIn = Nothing, resultFor = qc,
+                              resultBody = Right $ simpleResultBody "conduit" [1,2,7]
                             },
-                     Result { resultIn = src7, resultFor = qa,
-                              resultVersions = Right $ rvers [("aeson", Just $ ver [0,11,2,1])]
+                     Result { resultIn = src7, resultReallyIn = Nothing, resultFor = qa,
+                              resultBody = Right $ simpleResultBody "aeson" [0,11,2,1]
                             }
                    ]
-    got <- processCommand comm
-    got `shouldBe` expected
+    processCommand comm `shouldReturn` expected
+  specify "QueryCabalfile, SourceStackage" $ do
+    let src = SourceStackage "lts-4.2"
+        cabal_file = ("test" </> "data" </> "foobar.cabal_test")
+        query = QueryCabalFile cabal_file
+        comm = baseCommand { commSources = [src], commQueries = [query] }
+        ret t vps = Result { resultIn = src, resultReallyIn = Nothing, resultFor = query,
+                             resultBody = Right $ CabalResultBody cabal_file t vps
+                           }
+        expected = [ ret TargetLibrary $ verPairs [ ("base", [4,8,2,0]),
+                                                    ("unordered-containers", [0,2,5,1])
+                                                  ],
+                     -- no result for "executable" section because it has no build-depends field.
+                     ret (TargetTestSuite "spec") $ verPairs [ ("base", [4,8,2,0]),
+                                                               ("staversion", []),
+                                                               ("text", [1,2,2,0]),
+                                                               ("filepath", [1,4,0,0]),
+                                                               ("bytestring", [0,10,6,0])
+                                                             ],
+                     ret (TargetTestSuite "network-test") $ verPairs [ ("base", [4,8,2,0]),
+                                                                       ("http-client", [0,4,26,2])
+                                                                     ]
+                   ]
+    processCommand comm `shouldReturn` expected
         
 
-singleCase :: PackageSource -> Query -> Either ErrorMsg ResultVersions -> IO ()
+singleCase :: PackageSource -> Query -> Either ErrorMsg ResultBody -> IO ()
 singleCase src query exp_ret_vers = singleCase' src query (`shouldBe` exp_ret_vers)
 
-singleCase' :: PackageSource -> Query -> (Either ErrorMsg ResultVersions -> IO a) -> IO a
+singleCase' :: PackageSource -> Query -> (Either ErrorMsg ResultBody -> IO a) -> IO a
 singleCase' src query checker = do
   [got_ret] <- processCommand comm
   resultIn got_ret `shouldBe` src
+  resultReallyIn got_ret `shouldBe` Nothing
   resultFor got_ret `shouldBe` query
-  checker $ resultVersions got_ret
+  checker $ resultBody got_ret
   where
     comm =  baseCommand { commSources = [src],
                           commQueries = [query]
@@ -96,3 +130,18 @@
                         commQueries = [],
                         commAllowNetwork = False
                       }
+
+spec_processCommand_disambiguates :: Spec
+spec_processCommand_disambiguates = describe "processCommand" $ do
+  it "disambiguates a partial resolver and sets resultReallyIn field" $ do
+    let comm = baseCommand { commSources = [SourceStackage "lts"],
+                             commQueries = [QueryName "conduit"]
+                           }
+        withMockDisam bp_man = do
+          _setLTSDisambiguator bp_man 4 2
+          return bp_man
+    [got_ret] <- _processCommandWithCustomBuildPlanManager withMockDisam comm
+    resultIn got_ret `shouldBe` SourceStackage "lts"
+    resultReallyIn got_ret `shouldBe` (Just $ SourceStackage "lts-4.2")
+    resultFor got_ret `shouldBe` QueryName "conduit"
+    resultBody got_ret `shouldBe` Right (simpleResultBody "conduit" [1,2,6,1])
diff --git a/test/Staversion/Internal/FormatSpec.hs b/test/Staversion/Internal/FormatSpec.hs
--- a/test/Staversion/Internal/FormatSpec.hs
+++ b/test/Staversion/Internal/FormatSpec.hs
@@ -5,11 +5,13 @@
 
 import Staversion.Internal.Format (formatResultsCabal)
 import Staversion.Internal.Query
-  ( Result(..), PackageSource(..), Query(..),
+  ( PackageSource(..), Query(..),
     Resolver, PackageName
   )
+import Staversion.Internal.Result (Result(..), ResultBody(..))
+import Staversion.Internal.Cabal (Target(..))
 
-import Staversion.Internal.TestUtil (ver, rvers)
+import Staversion.Internal.TestUtil (ver, simpleResultBody, verPairs)
        
 
 
@@ -21,9 +23,9 @@
   it "should return empty text for empty list" $ do
     formatResultsCabal [] `shouldBe` ""
   it "should format a Result in a Cabal way" $ do
-    let input = [ Result { resultIn = SourceStackage "lts-6.10",
+    let input = [ Result { resultIn = SourceStackage "lts-6.10", resultReallyIn = Nothing,
                            resultFor = QueryName "hoge",
-                           resultVersions = Right $ rvers [("hoge", Just $ ver [3,4,5])]
+                           resultBody = Right $ simpleResultBody "hoge" [3,4,5]
                          }
                 ]
         expected = ( "------ lts-6.10\n"
@@ -56,6 +58,30 @@
                      <> "\n"
                    )
     formatResultsCabal input `shouldBe` expected
+  it "should group Results by PackageSource with preserved order (2)" $ do
+    let input = [ simpleResult "lts-5.0" "pack-A" [1,0],
+                  simpleResult "lts-5.0" "pack-A" [2,0],
+                  simpleResult "lts-6.6" "pack-A" [3,0],
+                  simpleResult "lts-6.6" "pack-A" [4,0],
+                  simpleResult "lts-8.0" "pack-A" [5,0],
+                  simpleResult "lts-6.6" "pack-A" [6,0],
+                  simpleResult "lts-6.6" "pack-A" [7,0]
+                ]
+        expected = ( "------ lts-5.0\n"
+                     <> "pack-A ==1.0,\n"
+                     <> "pack-A ==2.0\n"
+                     <> "\n"
+                     <> "------ lts-6.6\n"
+                     <> "pack-A ==3.0,\n"
+                     <> "pack-A ==4.0,\n"
+                     <> "pack-A ==6.0,\n"
+                     <> "pack-A ==7.0\n"
+                     <> "\n"
+                     <> "------ lts-8.0\n"
+                     <> "pack-A ==5.0\n"
+                     <> "\n"
+                   )
+    formatResultsCabal input `shouldBe` expected
   it "should not put comma at the last non-N/A entry even if it is followed by N/A entries"  $ do
     let input = [ simpleResult "s" "hoge" [1,0,0],
                   simpleResult "s" "not-found-1" [],
@@ -72,13 +98,129 @@
                      <> "\n"
                    )
     formatResultsCabal input `shouldBe` expected
+  it "should output resultReallyIn field" $ do
+    let input = [ Result { resultIn = SourceStackage "lts",
+                           resultReallyIn = Just $ SourceStackage "lts-7.4",
+                           resultFor = QueryName "foobar",
+                           resultBody = Right $ simpleResultBody "foobar" [3,4,5]
+                         } ]
+        expected = ( "------ lts (lts-7.4)\n"
+                     <> "foobar ==3.4.5\n"
+                     <> "\n"
+                   )
+    formatResultsCabal input `shouldBe` expected
+  it "should show ERROR if resultBody is Left, resultFor is QueryName" $ do
+    let input = [ Result { resultIn = SourceStackage "lts-4.2", resultReallyIn = Nothing,
+                           resultFor = QueryName "hogehoge",
+                           resultBody = Left "some error"
+                         } ]
+        expected = ( "------ lts-4.2\n"
+                     <> "-- hogehoge ERROR\n"
+                     <> "\n"
+                   )
+    formatResultsCabal input `shouldBe` expected
+  it "should show ERROR if resultBody is Left, resultFor is QueryCabalFile" $ do
+    let input = [ Result { resultIn = SourceStackage "lts-5.3", resultReallyIn = Nothing,
+                           resultFor = QueryCabalFile "foobar.cabal",
+                           resultBody = Left "some error"
+                         },
+                  Result { resultIn = SourceStackage "lts-5.3", resultReallyIn = Nothing,
+                           resultFor = QueryName "hoge",
+                           resultBody = Right $ simpleResultBody "hoge" [5,5]
+                         }
+                ]
+        expected = ( "------ lts-5.3\n"
+                     <> "-- foobar.cabal ERROR\n"
+                     <> "\n"
+                     <> "hoge ==5.5\n"
+                     <> "\n"
+                   )
+    formatResultsCabal input `shouldBe` expected
+  it "should show build-depends blocks for CabalResultBody" $ do
+    let mkRet = cabalResult "lts-7.0" "hoge.cabal"
+        input = [ mkRet TargetLibrary [ ("base", [4,6,0,0]),
+                                        ("foobar", [5,7])
+                                      ],
+                  mkRet (TargetExecutable "hoge-exe") [ ("bytestring", [1,9]) ],
+                  mkRet (TargetTestSuite "hoge-test") [ ("hspec", [10,8,9]),
+                                                        ("QuickCheck", [5,4,2]),
+                                                        ("unknown", [])
+                                                      ],
+                  mkRet (TargetBenchmark "hoge-bench") [ ("base", [4,8,0,4]),
+                                                         ("quux", []),
+                                                         ("parsec", [3,0,2])
+                                                       ]
+                ]
+        expected = ( "------ lts-7.0\n"
+                     <> "-- hoge.cabal - library\n"
+                     <> "base ==4.6.0.0,\n"
+                     <> "foobar ==5.7\n"
+                     <> "\n"
+                     <> "-- hoge.cabal - executable hoge-exe\n"
+                     <> "bytestring ==1.9\n"
+                     <> "\n"
+                     <> "-- hoge.cabal - test-suite hoge-test\n"
+                     <> "hspec ==10.8.9,\n"
+                     <> "QuickCheck ==5.4.2\n"
+                     <> "-- unknown N/A\n"
+                     <> "\n"
+                     <> "-- hoge.cabal - benchmark hoge-bench\n"
+                     <> "base ==4.8.0.4,\n"
+                     <> "-- quux N/A,\n"
+                     <> "parsec ==3.0.2\n"
+                     <> "\n"
+                   )
+    formatResultsCabal input `shouldBe` expected
+  it "should show mixed blocks and lines" $ do
+    let input = [ simpleResult "lts-5.0" "pack-A" [4,5],
+                  simpleResult "lts-5.0" "pack-B" [7,7],
+                  cabalResult "lts-5.0" "X.cabal" TargetLibrary [("pack-A", [4,5,1]), ("pack-B", [6,0])],
+                  cabalResult "lts-5.0" "X.cabal" (TargetExecutable "X-exe") [("pack-A", []), ("pack-B", [6,6]), ("pack-C", [0,10])],
+                  cabalResult "lts-6.6" "Y.cabal" TargetLibrary [("pack-C", [9,99,0])],
+                  simpleResult "lts-6.6" "pack-A" [],
+                  simpleResult "lts-7.2" "pack-B" [8,4],
+                  cabalResult "lts-6.6" "Y.cabal" (TargetTestSuite "X-test") [("pack-D", [1,0]), ("pack-A", [5,0]), ("pack-C", []), ("pack-B", [6,5])]
+                ]
+        expected = ( "------ lts-5.0\n"
+                     <> "pack-A ==4.5,\n"
+                     <> "pack-B ==7.7\n"
+                     <> "\n"
+                     <> "-- X.cabal - library\n"
+                     <> "pack-A ==4.5.1,\n"
+                     <> "pack-B ==6.0\n"
+                     <> "\n"
+                     <> "-- X.cabal - executable X-exe\n"
+                     <> "-- pack-A N/A,\n"
+                     <> "pack-B ==6.6,\n"
+                     <> "pack-C ==0.10\n"
+                     <> "\n"
+                     <> "------ lts-6.6\n"
+                     <> "-- Y.cabal - library\n"
+                     <> "pack-C ==9.99.0\n"
+                     <> "\n"
+                     <> "-- pack-A N/A\n"
+                     <> "\n"
+                     <> "-- Y.cabal - test-suite X-test\n"
+                     <> "pack-D ==1.0,\n"
+                     <> "pack-A ==5.0,\n"
+                     <> "-- pack-C N/A,\n"
+                     <> "pack-B ==6.5\n"
+                     <> "\n"
+                     <> "------ lts-7.2\n"
+                     <> "pack-B ==8.4\n"
+                     <> "\n"
+                   )
+    formatResultsCabal input `shouldBe` expected
 
 simpleResult :: Resolver -> PackageName -> [Int] -> Result
-simpleResult res name vs = Result { resultIn = SourceStackage res,
+simpleResult res name vs = Result { resultIn = SourceStackage res, resultReallyIn = Nothing,
                                     resultFor = QueryName name,
-                                    resultVersions = Right $ rvers [(name, mversion)]
+                                    resultBody = Right $ simpleResultBody name vs
                                   }
-  where
-    mversion = case vs of
-      [] -> Nothing
-      _ -> Just $ ver vs
+
+cabalResult :: Resolver -> FilePath -> Target -> [(PackageName, [Int])] -> Result
+cabalResult res file target vps =
+  Result { resultIn = SourceStackage res, resultReallyIn = Nothing,
+           resultFor = QueryCabalFile file,
+           resultBody = Right $ CabalResultBody file target $ verPairs vps
+         }
diff --git a/test/Staversion/Internal/TestUtil.hs b/test/Staversion/Internal/TestUtil.hs
--- a/test/Staversion/Internal/TestUtil.hs
+++ b/test/Staversion/Internal/TestUtil.hs
@@ -1,13 +1,23 @@
 module Staversion.Internal.TestUtil
-       ( ver, rvers
+       ( ver, simpleResultBody,
+         verPairs
        ) where
 
 import Data.Version (Version(..))
-import Staversion.Internal.Query (PackageName, ResultVersions, resultVersionsFromList)
+import Staversion.Internal.Query ( PackageName
+                                 )
+import Staversion.Internal.Result (ResultBody(..))
 
 ver :: [Int] -> Version
 ver vs = Version vs []
 
-rvers :: [(PackageName, Maybe Version)] -> ResultVersions
-rvers = resultVersionsFromList
+verMaybe :: [Int] -> Maybe Version
+verMaybe [] = Nothing
+verMaybe vs = Just $ ver vs
 
+verPairs :: [(PackageName, [Int])] -> [(PackageName, Maybe Version)]
+verPairs = map f where
+  f (pname, vs) = (pname, verMaybe vs)
+
+simpleResultBody :: PackageName -> [Int] -> ResultBody
+simpleResultBody name vs = SimpleResultBody name $ verMaybe vs
diff --git a/test/data/conduit.cabal_test b/test/data/conduit.cabal_test
new file mode 100644
--- /dev/null
+++ b/test/data/conduit.cabal_test
@@ -0,0 +1,111 @@
+Name:                conduit
+Version:             1.2.8
+Synopsis:            Streaming data processing library.
+description:
+    Hackage documentation generation is not reliable. For up to date documentation, please see: <http://www.stackage.org/package/conduit>.
+    .
+    @conduit@ is a solution to the streaming data problem, allowing for production, transformation, and consumption of streams of data in constant memory. It is an alternative to lazy I\/O which guarantees deterministic resource handling, and fits in the same general solution space as @enumerator@\/@iteratee@ and @pipes@. For a tutorial, please visit <https://www.fpcomplete.com/user/snoyberg/library-documentation/conduit-overview>.
+License:             MIT
+License-file:        LICENSE
+Author:              Michael Snoyman
+Maintainer:          michael@snoyman.com
+Category:            Data, Conduit
+Build-type:          Simple
+Cabal-version:       >=1.8
+Homepage:            http://github.com/snoyberg/conduit
+extra-source-files:  test/main.hs
+                   , README.md
+                   , ChangeLog.md
+                   , fusion-macros.h
+
+Library
+  Exposed-modules:     Data.Conduit
+                       Data.Conduit.List
+                       Data.Conduit.Internal
+                       Data.Conduit.Lift
+                       Data.Conduit.Internal.Fusion
+                       Data.Conduit.Internal.List.Stream
+  other-modules:       Data.Conduit.Internal.Pipe
+                       Data.Conduit.Internal.Conduit
+  Build-depends:       base                     >= 4.5          && < 5
+                     , resourcet                >= 1.1          && < 1.2
+                     , exceptions               >= 0.6
+                     , lifted-base              >= 0.1
+                     , transformers-base        >= 0.4.1        && < 0.5
+                     , transformers             >= 0.2.2
+                     , mtl
+                     , mmorph
+                     , monad-control
+  if !impl(ghc>=7.9)
+    build-depends:   void                     >= 0.5.5
+  ghc-options:         -Wall
+  include-dirs:        .
+
+test-suite test
+    hs-source-dirs: test
+    main-is: main.hs
+    other-modules: Data.Conduit.Extra.ZipConduitSpec
+                 , Data.Conduit.StreamSpec
+    type: exitcode-stdio-1.0
+    cpp-options:   -DTEST
+    build-depends:   conduit
+                   , base
+                   , hspec >= 1.3
+                   , QuickCheck >= 2.7
+                   , transformers
+                   , mtl
+                   , resourcet
+                   , containers
+                   , exceptions >= 0.6
+                   , safe
+    if !impl(ghc>=7.9)
+        build-depends: void
+    ghc-options:     -Wall
+
+--test-suite doctests
+--    hs-source-dirs: test
+--    main-is: doctests.hs
+--    type: exitcode-stdio-1.0
+--    ghc-options: -threaded
+--    build-depends: base, directory, doctest >= 0.8
+
+-- benchmark utf8-memory-usage
+--     type: exitcode-stdio-1.0
+--     hs-source-dirs: benchmarks
+--     build-depends:  base
+--                   , text-stream-decode
+--                   , bytestring
+--                   , text
+--                   , conduit
+--     main-is:        utf8-memory-usage.hs
+--     ghc-options:    -Wall -O2 -with-rtsopts=-s
+
+benchmark optimize-201408
+    type: exitcode-stdio-1.0
+    hs-source-dirs: benchmarks
+    build-depends:  base
+                  , conduit
+                  , vector
+                  , deepseq
+                  , containers
+                  , transformers
+                  , hspec
+                  , mwc-random
+                  , criterion
+                  , kan-extensions
+    main-is:        optimize-201408.hs
+    ghc-options:    -Wall -O2 -rtsopts
+
+benchmark unfused
+    type: exitcode-stdio-1.0
+    hs-source-dirs: benchmarks
+    build-depends:  base
+                  , conduit
+                  , criterion
+                  , transformers
+    main-is:        unfused.hs
+    ghc-options:    -Wall -O2 -rtsopts
+
+source-repository head
+  type:     git
+  location: git://github.com/snoyberg/conduit.git
diff --git a/test/data/doctest.cabal_test b/test/data/doctest.cabal_test
new file mode 100644
--- /dev/null
+++ b/test/data/doctest.cabal_test
@@ -0,0 +1,118 @@
+name:             doctest
+version:          0.11.0
+synopsis:         Test interactive Haskell examples
+description:      The doctest program checks examples in source code comments.
+                  It is modeled after doctest for Python
+                  (<http://docs.python.org/library/doctest.html>).
+                  .
+                  Documentation is at
+                  <https://github.com/sol/doctest#readme>.
+category:         Testing
+bug-reports:      https://github.com/sol/doctest/issues
+homepage:         https://github.com/sol/doctest#readme
+license:          MIT
+license-file:     LICENSE
+copyright:        (c) 2009-2015 Simon Hengel
+author:           Simon Hengel <sol@typeful.net>
+maintainer:       Simon Hengel <sol@typeful.net>
+build-type:       Simple
+cabal-version:    >= 1.8
+extra-source-files: example/example.cabal
+                  , example/src/Example.hs
+                  , example/test/doctests.hs
+
+source-repository head
+  type: git
+  location: https://github.com/sol/doctest
+
+library
+  exposed-modules:
+      Test.DocTest
+  ghc-options:
+      -Wall
+  hs-source-dirs:
+      src, ghci-wrapper/src
+  other-modules:
+      Extract
+    , GhcUtil
+    , Interpreter
+    , Location
+    , Help
+    , PackageDBs
+    , Parse
+    , Paths_doctest
+    , Property
+    , Runner
+    , Runner.Example
+    , Run
+    , Util
+    , Sandbox
+    , Language.Haskell.GhciWrapper
+  build-depends:
+      base          == 4.*
+    , base-compat   >= 0.4.2
+    , ghc           >= 7.0 && < 8.2
+    , syb           >= 0.3
+    , deepseq
+    , directory
+    , filepath
+    , process
+    , ghc-paths     >= 0.1.0.9
+    , transformers
+
+executable doctest
+  main-is:
+      Main.hs
+  ghc-options:
+      -Wall -threaded
+  hs-source-dirs:
+      driver
+  build-depends:
+      base          == 4.*
+    , doctest
+
+test-suite spec
+  main-is:
+      Spec.hs
+  type:
+      exitcode-stdio-1.0
+  ghc-options:
+      -Wall -threaded
+  cpp-options:
+      -DTEST
+  hs-source-dirs:
+      test, src, ghci-wrapper/src
+  c-sources:
+      test/integration/with-cbits/foo.c
+  build-depends:
+      base
+    , ghc
+    , syb
+    , deepseq
+    , directory
+    , filepath
+    , process
+    , ghc-paths
+    , transformers
+
+    , base-compat
+    , HUnit
+    , hspec         >= 1.5.1
+    , QuickCheck    >= 2.8.2
+    , stringbuilder >= 0.4
+    , silently      >= 1.2.4
+    , setenv
+    , with-location
+
+test-suite doctests
+  main-is:
+      doctests.hs
+  type:
+      exitcode-stdio-1.0
+  ghc-options:
+      -Wall -threaded
+  hs-source-dirs:
+      test
+  build-depends:
+      base
+    , doctest
diff --git a/test/data/foobar.cabal_test b/test/data/foobar.cabal_test
new file mode 100644
--- /dev/null
+++ b/test/data/foobar.cabal_test
@@ -0,0 +1,61 @@
+name:                   foobar
+version:                0.1.2.0
+author:                 Toshio Ito <debug.ito@gmail.com>
+maintainer:             Toshio Ito <debug.ito@gmail.com>
+license:                BSD3
+license-file:           LICENSE
+synopsis:               foo
+description:            bar
+category:               Example
+cabal-version:          >= 1.10
+build-type:             Simple
+-- extra-source-files:     README.md, ChangeLog.md,
+                        
+library
+  default-language:     Haskell2010
+  hs-source-dirs:       src
+  ghc-options:          -Wall -fno-warn-unused-imports
+  default-extensions:   OverloadedStrings
+  other-extensions:     CPP, DeriveDataTypeable, TupleSections
+  other-modules:        Paths_staversion,
+                        Staversion.Internal.HTTP
+  build-depends:        base >=4.6 && <4.10,
+                        unordered-containers >=0.2.3 && <0.3,
+
+executable foobar
+  default-language:     Haskell2010
+  hs-source-dirs:       app
+  main-is:              Main.hs
+  ghc-options:          -Wall -fno-warn-unused-imports -rtsopts -threaded "-with-rtsopts=-N"
+  -- other-modules:        
+  -- default-extensions:   
+  -- other-extensions:     
+  -- build-depends:        base, staversion
+  -- -- (no build-depends case (quite unlikely, though..))
+
+test-suite spec
+  type:                 exitcode-stdio-1.0
+  default-language:     Haskell2010
+  hs-source-dirs:       test
+  ghc-options:          -Wall -fno-warn-unused-imports -fno-warn-orphans "-with-rtsopts=-M512m"
+  main-is:              Spec.hs
+  default-extensions:   OverloadedStrings
+  build-depends:        base, staversion, text, filepath, bytestring,
+
+
+flag network-test
+  description: Enable network tests.
+  default: False
+
+test-suite network-test
+  type:                 exitcode-stdio-1.0
+  default-language:     Haskell2010
+  hs-source-dirs:       test
+  ghc-options:          -Wall -fno-warn-unused-imports -fno-warn-orphans "-with-rtsopts=-M512m"
+  main-is:              NetworkTest.hs
+  default-extensions:   OverloadedStrings
+  if !flag(network-test)
+    buildable:          False
+  -- other-extensions:     
+  other-modules:        Staversion.Internal.TestUtil
+  build-depends:        base, http-client
