# `WardrikWorkspace.Files`

Stores trees of files in a `WardrikStore`, each file with its own version.

Every change is made over a version:

  * `nil` - writes only where no file is.
  * a version - writes only if the file is still at that version.

Otherwise it returns `{:error, :conflict}`. This keeps two writers from losing each other's work.

Tree names are opaque: tree `shared/acme` doesn't contain tree `shared/acme/runbooks`.

# `version`

```elixir
@type version() :: String.t()
```

A file's version, as the model is shown it.

# `delete`

```elixir
@spec delete(WardrikStore.t(), String.t(), String.t(), version()) ::
  :ok | {:error, :conflict | term()}
```

Deletes the file at `path` in `tree`. Returns `{:error, :conflict}` unless it's still at `version`.

# `list`

```elixir
@spec list(WardrikStore.t(), String.t()) :: [
  {String.t(), WardrikWorkspace.File.t(), version()}
]
```

Returns every file in `tree`, with its path and version.

# `paths`

```elixir
@spec paths(WardrikStore.t(), String.t()) :: [String.t()]
```

Returns every path in `tree`.

# `read`

```elixir
@spec read(WardrikStore.t(), String.t(), String.t()) ::
  {:ok, WardrikWorkspace.File.t(), version()} | :none
```

Returns the file at `path` in `tree`, with its version, or `:none`.

# `write`

```elixir
@spec write(
  WardrikStore.t(),
  String.t(),
  String.t(),
  WardrikWorkspace.File.t(),
  version() | nil
) ::
  {:ok, version()} | {:error, :conflict | term()}
```

Writes `file` at `path` in `tree`.

With a `nil` version, writes only where no file is. Otherwise writes only over `version`.
Returns `{:error, :conflict}` if that doesn't hold.

---

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