isAllowed :: PackageInstallInfo pii
          => GetInstalledOpts
          -> Maybe InstalledCache
          -> Map PackageName pii
          -> Maybe InstalledPackageLocation
          -> DumpPackage Bool Bool
          -> Maybe LoadHelper
isAllowed opts mcache sourceMap mloc dp
    -- Check that it can do profiling if necessary
    | getInstalledProfiling opts && isJust mcache && not (dpProfiling dp) = Nothing
    -- Check that it has haddocks if necessary
    | getInstalledHaddock opts && isJust mcache && not (dpHaddock dp) = Nothing
    | toInclude = Just LoadHelper
        { lhId = gid
        , lhDeps =
            -- We always want to consider the wired in packages as having all
            -- of their dependencies installed, since we have no ability to
            -- reinstall them. This is especially important for using different
            -- minor versions of GHC, where the dependencies of wired-in
            -- packages may change slightly and therefore not match the
            -- snapshot.
            if name `HashSet.member` wiredInPackages
                then []
                else dpDepends dp
        , lhPair = (name, (version, toPackageLocation mloc, Library ident gid))
        }
    | otherwise = Nothing
  where
    toPackageLocation :: Maybe InstalledPackageLocation -> InstallLocation
    toPackageLocation Nothing = Snap
    toPackageLocation (Just ExtraGlobal) = Snap
    toPackageLocation (Just (InstalledTo loc)) = loc

    toInclude =
        case Map.lookup name sourceMap of
            Nothing ->
                case mloc of
                    -- The sourceMap has nothing to say about this global
                    -- package, so we can use it
                    Nothing -> True
                    Just ExtraGlobal -> True
                    -- For non-global packages, don't include unknown packages.
                    -- See:
                    -- https://github.com/commercialhaskell/stack/issues/292
                    Just _ -> False

            Just pii ->
                version == piiVersion pii -- only accept the desired version
                && checkLocation (piiLocation pii)

    -- Ensure that the installed location matches where the sourceMap says it
    -- should be installed
    checkLocation Snap = mloc /= Just (InstalledTo Local) -- we can allow either global or snap
    checkLocation Local = mloc == Just (InstalledTo Local) || mloc == Just ExtraGlobal -- 'locally' installed snapshot packages can come from extra dbs

    gid = dpGhcPkgId dp
    ident@(PackageIdentifier name version) = dpPackageIdent dp
isAllowed :: PackageInstallInfo pii
          => GetInstalledOpts
          -> Maybe InstalledCache
          -> Map PackageName pii
          -> Maybe InstalledPackageLocation
          -> DumpPackage Bool Bool
          -> Maybe LoadHelper
isAllowed opts mcache sourceMap mloc dp
    -- Check that it can do profiling if necessary
    | getInstalledProfiling opts && isJust mcache && not (dpProfiling dp) = Nothing
    -- Check that it has haddocks if necessary
    | getInstalledHaddock opts && isJust mcache && not (dpHaddock dp) = Nothing
    | toInclude = Just LoadHelper
        { lhId = gid
        , lhDeps =
            -- We always want to consider the wired in packages as having all
            -- of their dependencies installed, since we have no ability to
            -- reinstall them. This is especially important for using different
            -- minor versions of GHC, where the dependencies of wired-in
            -- packages may change slightly and therefore not match the
            -- snapshot.
            if name `HashSet.member` wiredInPackages
                then []
                else dpDepends dp
        , lhPair = (name, (version, toPackageLocation mloc, Library ident gid))
        }
    | otherwise = Nothing
  where
    toPackageLocation :: Maybe InstalledPackageLocation -> InstallLocation
    toPackageLocation Nothing = Snap
    toPackageLocation (Just ExtraGlobal) = Snap
    toPackageLocation (Just (InstalledTo loc)) = loc

    toInclude =
        case Map.lookup name sourceMap of
            Nothing ->
                case mloc of
                    -- The sourceMap has nothing to say about this global
                    -- package, so we can use it
                    Nothing -> True
                    Just ExtraGlobal -> True
                    -- For non-global packages, don't include unknown packages.
                    -- See:
                    -- https://github.com/commercialhaskell/stack/issues/292
                    Just _ -> False

            Just pii ->
                version == piiVersion pii -- only accept the desired version
                && checkLocation (piiLocation pii)

    -- Ensure that the installed location matches where the sourceMap says it
    -- should be installed
    checkLocation Snap = mloc /= Just (InstalledTo Local) -- we can allow either global or snap
    checkLocation Local = mloc == Just (InstalledTo Local) || mloc == Just ExtraGlobal -- 'locally' installed snapshot packages can come from extra dbs

    gid = dpGhcPkgId dp
    ident@(PackageIdentifier name version) = dpPackageIdent dp
isAllowed opts mcache sourceMap mloc dp
    -- Check that it can do profiling if necessary
    | getInstalledProfiling opts && isJust mcache && not (dpProfiling dp) = Nothing
    -- Check that it has haddocks if necessary
    | getInstalledHaddock opts && isJust mcache && not (dpHaddock dp) = Nothing
    | toInclude = Just LoadHelper
        { lhId = gid
        , lhDeps =
            -- We always want to consider the wired in packages as having all
            -- of their dependencies installed, since we have no ability to
            -- reinstall them. This is especially important for using different
            -- minor versions of GHC, where the dependencies of wired-in
            -- packages may change slightly and therefore not match the
            -- snapshot.
            if name `HashSet.member` wiredInPackages
                then []
                else dpDepends dp
        , lhPair = (name, (version, toPackageLocation mloc, Library ident gid))
        }
    | otherwise = Nothing
  where
    toPackageLocation :: Maybe InstalledPackageLocation -> InstallLocation
    toPackageLocation Nothing = Snap
    toPackageLocation (Just ExtraGlobal) = Snap
    toPackageLocation (Just (InstalledTo loc)) = loc

    toInclude =
        case Map.lookup name sourceMap of
            Nothing ->
                case mloc of
                    -- The sourceMap has nothing to say about this global
                    -- package, so we can use it
                    Nothing -> True
                    Just ExtraGlobal -> True
                    -- For non-global packages, don't include unknown packages.
                    -- See:
                    -- https://github.com/commercialhaskell/stack/issues/292
                    Just _ -> False

            Just pii ->
                version == piiVersion pii -- only accept the desired version
                && checkLocation (piiLocation pii)

    -- Ensure that the installed location matches where the sourceMap says it
    -- should be installed
    checkLocation Snap = mloc /= Just (InstalledTo Local) -- we can allow either global or snap
    checkLocation Local = mloc == Just (InstalledTo Local) || mloc == Just ExtraGlobal -- 'locally' installed snapshot packages can come from extra dbs

    gid = dpGhcPkgId dp
    ident@(PackageIdentifier name version) = dpPackageIdent dp