# `Stevedore.Transport`
[🔗](https://github.com/oshlabs/stevedore/blob/v0.2.0/lib/stevedore/transport.ex#L1)

The seam describing **where images live**, behind one uniform interface.

A transport instance is a struct (carrying its own config — a registry repository, a layout
path, a `Store`, …) whose module implements this behaviour. The functions in this module
dispatch to that module based on the struct, so callers (notably `Stevedore.copy/3`) work
against any transport interchangeably:

    Stevedore.Transport.get_manifest(transport, "3.20")

Implementations: `Stevedore.Transport.Registry` (`docker://`), `Transport.OCILayout` (`oci:`),
`Transport.Dir` (`dir:`), `Transport.Archive` (`docker-archive:`), and `Transport.Static`.

Spec: [containers-transports(5)](https://github.com/containers/image/blob/main/docs/containers-transports.5.md).

# `fetched`

```elixir
@type fetched() :: %{
  media_type: String.t(),
  digest: Stevedore.Digest.t(),
  raw: binary(),
  json: map()
}
```

# `ref`

```elixir
@type ref() :: String.t() | Stevedore.Digest.t() | nil
```

# `t`

```elixir
@type t() :: struct()
```

# `delete`
*optional* 

```elixir
@callback delete(t(), ref()) :: :ok | {:error, term()}
```

Delete a manifest by tag or digest.

# `finalize`
*optional* 

```elixir
@callback finalize(t()) :: :ok | {:error, term()}
```

Flush any buffered state (e.g. emit a tar). Called once at the end of a copy.

# `get_blob`

```elixir
@callback get_blob(t(), Stevedore.Digest.t()) :: {:ok, binary()} | {:error, term()}
```

Fetch a blob by digest.

# `get_manifest`

```elixir
@callback get_manifest(t(), ref()) :: {:ok, fetched()} | {:error, term()}
```

Fetch a manifest (or index) by tag or digest.

# `has_blob?`

```elixir
@callback has_blob?(t(), Stevedore.Digest.t()) :: boolean()
```

Whether the blob is already present (lets `copy` skip it).

# `list_tags`
*optional* 

```elixir
@callback list_tags(t()) :: {:ok, [String.t()]} | {:error, term()}
```

List tags held by this transport.

# `put_blob`

```elixir
@callback put_blob(t(), Stevedore.Digest.t(), iodata()) :: :ok | {:error, term()}
```

Store a blob (the implementation verifies it against `digest`).

# `put_manifest`

```elixir
@callback put_manifest(t(), ref(), raw :: binary(), media_type :: String.t()) ::
  {:ok, Stevedore.Digest.t()} | {:error, term()}
```

Store raw manifest bytes, optionally tagged as `ref`. Returns the manifest digest.

# `delete`

```elixir
@spec delete(t(), ref()) :: :ok | {:error, term()}
```

Dispatch `delete/2`.

# `finalize`

```elixir
@spec finalize(t()) :: :ok | {:error, term()}
```

Dispatch `finalize/1`, or `:ok` for transports that don't define it.

# `get_blob`

```elixir
@spec get_blob(t(), Stevedore.Digest.t()) :: {:ok, binary()} | {:error, term()}
```

Dispatch `get_blob/2`.

# `get_manifest`

```elixir
@spec get_manifest(t(), ref()) :: {:ok, fetched()} | {:error, term()}
```

Dispatch `get_manifest/2` to `transport`'s implementation.

# `has_blob?`

```elixir
@spec has_blob?(t(), Stevedore.Digest.t()) :: boolean()
```

Dispatch `has_blob?/2`.

# `list_tags`

```elixir
@spec list_tags(t()) :: {:ok, [String.t()]} | {:error, term()}
```

Dispatch `list_tags/1`.

# `put_blob`

```elixir
@spec put_blob(t(), Stevedore.Digest.t(), iodata()) :: :ok | {:error, term()}
```

Dispatch `put_blob/3`.

# `put_manifest`

```elixir
@spec put_manifest(t(), ref(), binary(), String.t()) ::
  {:ok, Stevedore.Digest.t()} | {:error, term()}
```

Dispatch `put_manifest/4`.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
