hackage-security-0.5.2.2: Hackage security library

Hackage.Security.Client.Repository

Description

Abstract definition of a Repository

Most clients should only need to import this module if they wish to define their own Repository implementations.

Synopsis

Files

data RemoteFile :: * -> * -> * where Source #

RemoteFile is parametrized by the type of the formats that we can accept from the remote repository, as well as with information on whether this file is metadata actual binary content.

Constructors

 RemoteTimestamp :: RemoteFile (FormatUn :- ()) Metadata RemoteRoot :: Maybe (Trusted FileInfo) -> RemoteFile (FormatUn :- ()) Metadata RemoteSnapshot :: Trusted FileInfo -> RemoteFile (FormatUn :- ()) Metadata RemoteMirrors :: Trusted FileInfo -> RemoteFile (FormatUn :- ()) Metadata RemoteIndex :: HasFormat fs FormatGz -> Formats fs (Trusted FileInfo) -> RemoteFile fs Binary RemotePkgTarGz :: PackageIdentifier -> Trusted FileInfo -> RemoteFile (FormatGz :- ()) Binary

Instances

 Show (RemoteFile fs typ) Source # MethodsshowsPrec :: Int -> RemoteFile fs typ -> ShowS #show :: RemoteFile fs typ -> String #showList :: [RemoteFile fs typ] -> ShowS # Pretty (RemoteFile fs typ) Source # Methodspretty :: RemoteFile fs typ -> String Source #

Files that we might request from the local cache

Constructors

 CachedTimestamp Timestamp metadata (timestamp.json) CachedRoot Root metadata (root.json) CachedSnapshot Snapshot metadata (snapshot.json) CachedMirrors Mirrors list (mirrors.json)

Instances

 Source # Methods Source # Methods Source # MethodsshowList :: [CachedFile] -> ShowS # Source # Methods

data IndexFile :: * -> * where Source #

Files that we might request from the index

The type index tells us the type of the decoded file, if any. For files for which the library does not support decoding this will be (). NOTE: Clients should NOT rely on this type index being (), or they might break if we add support for parsing additional file formats in the future.

TODO: If we wanted to support legacy Hackage, we should also have a case for the global preferred-versions file. But supporting legacy Hackage will probably require more work anyway..

Constructors

 IndexPkgMetadata :: PackageIdentifier -> IndexFile (Signed Targets) IndexPkgCabal :: PackageIdentifier -> IndexFile () IndexPkgPrefs :: PackageName -> IndexFile ()

Instances

 Source # Methods Source # Methods Show (IndexFile dec) Source # MethodsshowsPrec :: Int -> IndexFile dec -> ShowS #show :: IndexFile dec -> String #showList :: [IndexFile dec] -> ShowS # Pretty (IndexFile dec) Source # Methodspretty :: IndexFile dec -> String Source #

remoteFileDefaultFormat :: RemoteFile fs typ -> Some (HasFormat fs) Source #

Default format for each file type

For most file types we don't have a choice; for the index the repository is only required to offer the GZip-compressed format so that is the default.

Default file info (see also remoteFileDefaultFormat)

Repository proper

data Repository down Source #

Repository

This is an abstract representation of a repository. It simply provides a way to download metafiles and target files, without specifying how this is done. For instance, for a local repository this could just be doing a file read, whereas for remote repositories this could be using any kind of HTTP client.

Constructors

 DownloadedFile down => Repository FieldsrepGetRemote :: forall fs typ. Throws SomeRemoteError => AttemptNr -> RemoteFile fs typ -> Verify (Some (HasFormat fs), down typ)Get a file from the serverResponsibilies of repGetRemote:Download the file from the repository and make it available at a temporary locationUse the provided file length to protect against endless data attacks. (Repositories such as local repositories that are not suspectible to endless data attacks can safely ignore this argument.)Move the file from its temporary location to its permanent location if verification succeeds.NOTE: Calls to repGetRemote should _always_ be in the scope of repWithMirror.repGetCached :: CachedFile -> IO (Maybe (Path Absolute))Get a cached file (if available)repGetCachedRoot :: IO (Path Absolute)Get the cached rootThis is a separate method only because clients must ALWAYS have root information available.repClearCache :: IO ()Clear all cached dataIn particular, this should remove the snapshot and the timestamp. It would also be okay, but not required, to delete the index.repWithIndex :: forall a. (Handle -> IO a) -> IO aOpen the tarball for readingThis function has this shape so that:We can read multiple files from the tarball without having to open and close the handle each timeWe can close the handle immediately when done.repGetIndexIdx :: IO TarIndexRead the index indexrepLockCache :: IO () -> IO ()Lock the cache (during updates)repWithMirror :: forall a. Maybe [Mirror] -> IO a -> IO aMirror selectionThe purpose of repWithMirror is to scope mirror selection. The idea is that if we haverepWithMirror mirrorList \$ someCallbackthen the repository may pick a mirror before calling someCallback, catch exceptions thrown by someCallback, and potentially try the callback again with a different mirror.The list of mirrors may be Nothing if we haven't yet downloaded the list of mirrors from the repository, or when our cached list of mirrors is invalid. Of course, if we did download it, then the list of mirrors may still be empty. In this case the repository must fall back to its primary download mechanism.Mirrors as currently defined (in terms of a "base URL") are inherently a HTTP (or related) concept, so in repository implementations such as the local-repo repWithMirrors is probably just an identity operation (see ignoreMirrors). Conversely, HTTP implementations of repositories may have other, out-of-band information (for example, coming from a cabal config file) that they may use to influence mirror selection.repLog :: LogMessage -> IO ()LoggingrepLayout :: RepoLayoutLayout of this repositoryrepIndexLayout :: IndexLayoutLayout of the indexSince the repository hosts the index, the layout of the index is not independent of the layout of the repository.repDescription :: StringDescription of the repository (used in the show instance)

Instances

 Show (Repository down) Source # MethodsshowsPrec :: Int -> Repository down -> ShowS #show :: Repository down -> String #showList :: [Repository down] -> ShowS #

newtype AttemptNr Source #

Are we requesting this information because of a previous validation error?

Clients can take advantage of this to tell caches to revalidate files.

Constructors

 AttemptNr Int

Instances

 Source # Methods Source # Methods Source # Methods

Log messages

We use a RemoteFile rather than a RepoPath here because we might not have a RepoPath for the file that we were trying to download (that is, for example if the server does not provide an uncompressed tarball, it doesn't make much sense to list the path to that non-existing uncompressed tarball).

Constructors

 LogRootUpdated Root information was updatedThis message is issued when the root information is updated as part of the normal check for updates procedure. If the root information is updated because of a verification error WarningVerificationError is issued instead. LogVerificationError VerificationError A verification errorVerification errors can be temporary, and may be resolved later; hence these are just warnings. (Verification errors that cannot be resolved are thrown as exceptions.) LogDownloading (RemoteFile fs typ) Download a file from a repository LogUpdating (RemoteFile fs Binary) Incrementally updating a file from a repository LogSelectedMirror MirrorDescription Selected a particular mirror LogCannotUpdate (RemoteFile fs Binary) UpdateFailure Updating a file failed (we will instead download it whole) LogMirrorFailed MirrorDescription SomeException We got an exception with a particular mirror (we will try with a different mirror if any are available)

Instances

 Source # Methods

Constructors

 UpdateImpossibleUnsupported Server does not support incremental downloads UpdateImpossibleNoLocalCopy We don't have a local copy of the file to update UpdateFailedTwice Update failed twiceIf we attempt an incremental update the first time, and it fails, we let it go round the loop, update local security information, and try again. But if an incremental update then fails _again_, we instead attempt a regular download. UpdateFailed SomeException Update failed (for example: perhaps the local file got corrupted)

Instances

 Source # Methods

data SomeRemoteError :: * where Source #

Repository-specific exceptions

For instance, for repositories using HTTP this might correspond to a 404; for local repositories this might correspond to file-not-found, etc.

Constructors

 SomeRemoteError :: Exception e => e -> SomeRemoteError

Instances

 Source # MethodsshowList :: [SomeRemoteError] -> ShowS # Source # Methods Source # Methods

Minimal complete definition

Methods

downloadedVerify :: down a -> Trusted FileInfo -> IO Bool Source #

downloadedCopyTo :: down a -> Path Absolute -> IO () Source #

Instances

 Source # Methods Source # Methods

Helpers

mirrorsUnsupported :: Maybe [Mirror] -> IO a -> IO a Source #

Helper function to implement repWithMirrors.

Utility

data IsCached :: * -> * where Source #

Is a particular remote file cached?

Constructors

 CacheAs :: CachedFile -> IsCached Metadata DontCache :: IsCached Binary CacheIndex :: IsCached Binary

Instances

 Eq (IsCached typ) Source # Methods(==) :: IsCached typ -> IsCached typ -> Bool #(/=) :: IsCached typ -> IsCached typ -> Bool # Show (IsCached typ) Source # MethodsshowsPrec :: Int -> IsCached typ -> ShowS #show :: IsCached typ -> String #showList :: [IsCached typ] -> ShowS #

mustCache :: RemoteFile fs typ -> IsCached typ Source #

Which remote files should we cache locally?