# `Git.Commands.Tag`
[🔗](https://github.com/joshrotenberg/git_wrapper_ex/blob/main/lib/git/commands/tag.ex#L1)

Implements the `Git.Command` behaviour for `git tag`.

Supports listing tags (default), creating a lightweight tag, creating an
annotated tag, and deleting a tag.

# `t`

```elixir
@type t() :: %Git.Commands.Tag{
  contains: String.t() | nil,
  create: String.t() | nil,
  delete: String.t() | nil,
  file: String.t() | nil,
  force: boolean(),
  list: boolean(),
  list_glob: String.t() | nil,
  local_user: String.t() | nil,
  message: String.t() | nil,
  points_at: String.t() | nil,
  ref: String.t() | nil,
  sign: boolean(),
  sort: String.t() | nil
}
```

# `args`

```elixir
@spec args(t()) :: [String.t()]
```

Returns the argument list for `git tag`.

- If `:create` is set with `:message`, builds `git tag -a <name> -m <msg>` (annotated).
- If `:create` is set with `:file`, builds `git tag -a <name> -F <path>` (annotated
  message read from a file). `:file` takes precedence over `:message`.
- If `:create` is set without `:message` or `:file`, builds `git tag <name>` (lightweight).
- If `:local_user` is set on annotated creation, replaces `-a` with
  `-u <keyid>` (a signed tag with that key). Otherwise if `:sign` is `true`,
  replaces `-a` with `-s` (a signed tag with the default key). Signing only
  applies to annotated creation, so a message (`:message` or `:file`) is
  always present and git never opens an editor.
- If `:force` is set on creation, adds `-f` so an existing tag is moved/replaced.
- If `:delete` is set, builds `git tag -d <name>`.
- Otherwise, lists tags with detailed format. Listing accepts `:contains`,
  `:points_at`, `:list_glob`, and `:sort` filters.

Both create and delete accept an optional `:ref` to specify the commit.

## Examples

    iex> Git.Commands.Tag.args(%Git.Commands.Tag{})
    ["tag", "-l", "--format=" <> Git.Tag.format_string()]

    iex> Git.Commands.Tag.args(%Git.Commands.Tag{create: "v1.0.0"})
    ["tag", "v1.0.0"]

    iex> Git.Commands.Tag.args(%Git.Commands.Tag{create: "v1.0.0", message: "release 1.0"})
    ["tag", "-a", "v1.0.0", "-m", "release 1.0"]

    iex> Git.Commands.Tag.args(%Git.Commands.Tag{create: "v1.0.0", message: "release 1.0", sign: true})
    ["tag", "-s", "v1.0.0", "-m", "release 1.0"]

    iex> Git.Commands.Tag.args(%Git.Commands.Tag{create: "v1.0.0", message: "release 1.0", local_user: "ABCD1234"})
    ["tag", "-u", "ABCD1234", "v1.0.0", "-m", "release 1.0"]

    iex> Git.Commands.Tag.args(%Git.Commands.Tag{create: "v1.0.0", force: true})
    ["tag", "-f", "v1.0.0"]

    iex> Git.Commands.Tag.args(%Git.Commands.Tag{delete: "v1.0.0"})
    ["tag", "-d", "v1.0.0"]

    iex> Git.Commands.Tag.args(%Git.Commands.Tag{contains: "HEAD"})
    ["tag", "-l", "--contains", "HEAD", "--format=" <> Git.Tag.format_string()]

# `parse_output`

```elixir
@spec parse_output(String.t(), non_neg_integer()) ::
  {:ok, [Git.Tag.t()]}
  | {:ok, :done}
  | {:error, {String.t(), non_neg_integer()}}
```

Parses the output of `git tag`.

For list operations (exit 0), parses each entry into a `Git.Tag` struct.
For create/delete operations (exit 0), returns `{:ok, :done}`.
On failure, returns `{:error, {stdout, exit_code}}`.

---

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