withRepoContext' :: Verbosity -> [RemoteRepo] -> [FilePath]
                 -> FilePath  -> Maybe String -> Maybe Bool
                 -> (RepoContext -> IO a)
                 -> IO a
withRepoContext' verbosity remoteRepos localRepos
                 sharedCacheDir httpTransport ignoreExpiry = \callback -> do
    transportRef <- newMVar Nothing
    let httpLib = Sec.HTTP.transportAdapter
                    verbosity
                    (getTransport transportRef)
    initSecureRepos verbosity httpLib secureRemoteRepos $ \secureRepos' ->
      callback RepoContext {
          repoContextRepos          = allRemoteRepos
                                   ++ map RepoLocal localRepos
        , repoContextGetTransport   = getTransport transportRef
        , repoContextWithSecureRepo = withSecureRepo secureRepos'
        , repoContextIgnoreExpiry   = fromMaybe False ignoreExpiry
        }
  where
    secureRemoteRepos =
      [ (remote, cacheDir) | RepoSecure remote cacheDir <- allRemoteRepos ]
    allRemoteRepos =
      [ (if isSecure then RepoSecure else RepoRemote) remote cacheDir
      | remote <- remoteRepos
      , let cacheDir = sharedCacheDir </> remoteRepoName remote
            isSecure = remoteRepoSecure remote == Just True
      ]

    getTransport :: MVar (Maybe HttpTransport) -> IO HttpTransport
    getTransport transportRef =
      modifyMVar transportRef $ \mTransport -> do
        transport <- case mTransport of
          Just tr -> return tr
          Nothing -> configureTransport verbosity httpTransport
        return (Just transport, transport)

    withSecureRepo :: Map Repo SecureRepo
                   -> Repo
                   -> (forall down. Sec.Repository down -> IO a)
                   -> IO a
    withSecureRepo secureRepos repo callback =
      case Map.lookup repo secureRepos of
        Just (SecureRepo secureRepo) -> callback secureRepo
        Nothing -> throwIO $ userError "repoContextWithSecureRepo: unknown repo"

-- | Initialize the provided secure repositories
--
-- Assumed invariant: `remoteRepoSecure` should be set for all these repos.
withRepoContext' :: Verbosity -> [RemoteRepo] -> [FilePath]
                 -> FilePath  -> Maybe String -> Maybe Bool
                 -> (RepoContext -> IO a)
                 -> IO a
withRepoContext' verbosity remoteRepos localRepos
                 sharedCacheDir httpTransport ignoreExpiry = \callback -> do
    transportRef <- newMVar Nothing
    let httpLib = Sec.HTTP.transportAdapter
                    verbosity
                    (getTransport transportRef)
    initSecureRepos verbosity httpLib secureRemoteRepos $ \secureRepos' ->
      callback RepoContext {
          repoContextRepos          = allRemoteRepos
                                   ++ map RepoLocal localRepos
        , repoContextGetTransport   = getTransport transportRef
        , repoContextWithSecureRepo = withSecureRepo secureRepos'
        , repoContextIgnoreExpiry   = fromMaybe False ignoreExpiry
        }
  where
    secureRemoteRepos =
      [ (remote, cacheDir) | RepoSecure remote cacheDir <- allRemoteRepos ]
    allRemoteRepos =
      [ (if isSecure then RepoSecure else RepoRemote) remote cacheDir
      | remote <- remoteRepos
      , let cacheDir = sharedCacheDir </> remoteRepoName remote
            isSecure = remoteRepoSecure remote == Just True
      ]

    getTransport :: MVar (Maybe HttpTransport) -> IO HttpTransport
    getTransport transportRef =
      modifyMVar transportRef $ \mTransport -> do
        transport <- case mTransport of
          Just tr -> return tr
          Nothing -> configureTransport verbosity httpTransport
        return (Just transport, transport)

    withSecureRepo :: Map Repo SecureRepo
                   -> Repo
                   -> (forall down. Sec.Repository down -> IO a)
                   -> IO a
    withSecureRepo secureRepos repo callback =
      case Map.lookup repo secureRepos of
        Just (SecureRepo secureRepo) -> callback secureRepo
        Nothing -> throwIO $ userError "repoContextWithSecureRepo: unknown repo"

-- | Initialize the provided secure repositories
--
-- Assumed invariant: `remoteRepoSecure` should be set for all these repos.
withRepoContext' verbosity remoteRepos localRepos
                 sharedCacheDir httpTransport ignoreExpiry = \callback -> do
    transportRef <- newMVar Nothing
    let httpLib = Sec.HTTP.transportAdapter
                    verbosity
                    (getTransport transportRef)
    initSecureRepos verbosity httpLib secureRemoteRepos $ \secureRepos' ->
      callback RepoContext {
          repoContextRepos          = allRemoteRepos
                                   ++ map RepoLocal localRepos
        , repoContextGetTransport   = getTransport transportRef
        , repoContextWithSecureRepo = withSecureRepo secureRepos'
        , repoContextIgnoreExpiry   = fromMaybe False ignoreExpiry
        }
  where
    secureRemoteRepos =
      [ (remote, cacheDir) | RepoSecure remote cacheDir <- allRemoteRepos ]
    allRemoteRepos =
      [ (if isSecure then RepoSecure else RepoRemote) remote cacheDir
      | remote <- remoteRepos
      , let cacheDir = sharedCacheDir </> remoteRepoName remote
            isSecure = remoteRepoSecure remote == Just True
      ]

    getTransport :: MVar (Maybe HttpTransport) -> IO HttpTransport
    getTransport transportRef =
      modifyMVar transportRef $ \mTransport -> do
        transport <- case mTransport of
          Just tr -> return tr
          Nothing -> configureTransport verbosity httpTransport
        return (Just transport, transport)

    withSecureRepo :: Map Repo SecureRepo
                   -> Repo
                   -> (forall down. Sec.Repository down -> IO a)
                   -> IO a
    withSecureRepo secureRepos repo callback =
      case Map.lookup repo secureRepos of
        Just (SecureRepo secureRepo) -> callback secureRepo
        Nothing -> throwIO $ userError "repoContextWithSecureRepo: unknown repo"

-- | Initialize the provided secure repositories
--
-- Assumed invariant: `remoteRepoSecure` should be set for all these repos.