getCabalLbs :: M env m => PvpBounds -> FilePath -> m L.ByteString
getCabalLbs pvpBounds fp = do
    bs <- liftIO $ S.readFile fp
    (_warnings, gpd) <- readPackageUnresolvedBS Nothing bs
    (_, _, _, _, sourceMap) <- loadSourceMap AllowNoTargets defaultBuildOpts
    menv <- getMinimalEnvOverride
    (installedMap, _, _, _) <- getInstalled menv GetInstalledOpts
                                { getInstalledProfiling = False
                                , getInstalledHaddock = False
                                }
                                sourceMap
    let gpd' = gtraverseT (addBounds sourceMap installedMap) gpd
    return $ TLE.encodeUtf8 $ TL.pack $ showGenericPackageDescription gpd'
  where
    addBounds :: SourceMap -> InstalledMap -> Dependency -> Dependency
    addBounds sourceMap installedMap dep@(Dependency cname range) =
      case lookupVersion (fromCabalPackageName cname) of
        Nothing -> dep
        Just version -> Dependency cname $ simplifyVersionRange
          $ (if toAddUpper && not (hasUpper range) then addUpper version else id)
          $ (if toAddLower && not (hasLower range) then addLower version else id)
            range
      where
        lookupVersion name =
          case Map.lookup name sourceMap of
              Just (PSLocal lp) -> Just $ packageVersion $ lpPackage lp
              Just (PSUpstream version _ _) -> Just version
              Nothing ->
                  case Map.lookup name installedMap of
                      Just (_, installed) -> Just (installedVersion installed)
                      Nothing -> Nothing

    addUpper version = intersectVersionRanges
        (earlierVersion $ toCabalVersion $ nextMajorVersion version)
    addLower version = intersectVersionRanges
        (orLaterVersion (toCabalVersion version))

    (toAddLower, toAddUpper) =
      case pvpBounds of
        PvpBoundsNone  -> (False, False)
        PvpBoundsUpper -> (False, True)
        PvpBoundsLower -> (True,  False)
        PvpBoundsBoth  -> (True,  True)

-- | Traverse a data type.
getCabalLbs :: M env m => PvpBounds -> FilePath -> m L.ByteString
getCabalLbs pvpBounds fp = do
    bs <- liftIO $ S.readFile fp
    (_warnings, gpd) <- readPackageUnresolvedBS Nothing bs
    (_, _, _, _, sourceMap) <- loadSourceMap AllowNoTargets defaultBuildOpts
    menv <- getMinimalEnvOverride
    (installedMap, _, _, _) <- getInstalled menv GetInstalledOpts
                                { getInstalledProfiling = False
                                , getInstalledHaddock = False
                                }
                                sourceMap
    let gpd' = gtraverseT (addBounds sourceMap installedMap) gpd
    return $ TLE.encodeUtf8 $ TL.pack $ showGenericPackageDescription gpd'
  where
    addBounds :: SourceMap -> InstalledMap -> Dependency -> Dependency
    addBounds sourceMap installedMap dep@(Dependency cname range) =
      case lookupVersion (fromCabalPackageName cname) of
        Nothing -> dep
        Just version -> Dependency cname $ simplifyVersionRange
          $ (if toAddUpper && not (hasUpper range) then addUpper version else id)
          $ (if toAddLower && not (hasLower range) then addLower version else id)
            range
      where
        lookupVersion name =
          case Map.lookup name sourceMap of
              Just (PSLocal lp) -> Just $ packageVersion $ lpPackage lp
              Just (PSUpstream version _ _) -> Just version
              Nothing ->
                  case Map.lookup name installedMap of
                      Just (_, installed) -> Just (installedVersion installed)
                      Nothing -> Nothing

    addUpper version = intersectVersionRanges
        (earlierVersion $ toCabalVersion $ nextMajorVersion version)
    addLower version = intersectVersionRanges
        (orLaterVersion (toCabalVersion version))

    (toAddLower, toAddUpper) =
      case pvpBounds of
        PvpBoundsNone  -> (False, False)
        PvpBoundsUpper -> (False, True)
        PvpBoundsLower -> (True,  False)
        PvpBoundsBoth  -> (True,  True)

-- | Traverse a data type.
getCabalLbs pvpBounds fp = do
    bs <- liftIO $ S.readFile fp
    (_warnings, gpd) <- readPackageUnresolvedBS Nothing bs
    (_, _, _, _, sourceMap) <- loadSourceMap AllowNoTargets defaultBuildOpts
    menv <- getMinimalEnvOverride
    (installedMap, _, _, _) <- getInstalled menv GetInstalledOpts
                                { getInstalledProfiling = False
                                , getInstalledHaddock = False
                                }
                                sourceMap
    let gpd' = gtraverseT (addBounds sourceMap installedMap) gpd
    return $ TLE.encodeUtf8 $ TL.pack $ showGenericPackageDescription gpd'
  where
    addBounds :: SourceMap -> InstalledMap -> Dependency -> Dependency
    addBounds sourceMap installedMap dep@(Dependency cname range) =
      case lookupVersion (fromCabalPackageName cname) of
        Nothing -> dep
        Just version -> Dependency cname $ simplifyVersionRange
          $ (if toAddUpper && not (hasUpper range) then addUpper version else id)
          $ (if toAddLower && not (hasLower range) then addLower version else id)
            range
      where
        lookupVersion name =
          case Map.lookup name sourceMap of
              Just (PSLocal lp) -> Just $ packageVersion $ lpPackage lp
              Just (PSUpstream version _ _) -> Just version
              Nothing ->
                  case Map.lookup name installedMap of
                      Just (_, installed) -> Just (installedVersion installed)
                      Nothing -> Nothing

    addUpper version = intersectVersionRanges
        (earlierVersion $ toCabalVersion $ nextMajorVersion version)
    addLower version = intersectVersionRanges
        (orLaterVersion (toCabalVersion version))

    (toAddLower, toAddUpper) =
      case pvpBounds of
        PvpBoundsNone  -> (False, False)
        PvpBoundsUpper -> (False, True)
        PvpBoundsLower -> (True,  False)
        PvpBoundsBoth  -> (True,  True)

-- | Traverse a data type.