defmodule Mix.Tasks.Hf.Repos do
@shortdoc "List your HuggingFace repositories"
@moduledoc """
Lists repositories for the authenticated user or a specific author.
$ mix hf.repos
$ mix hf.repos --author my-org
$ mix hf.repos --type dataset
$ mix hf.repos --author huggingface --limit 20
## Options
* `--author` / `-a` — list repos for this user/org
* `--type` / `-t` — `model`, `dataset`, `space` (default: all)
* `--limit` / `-n` — max results (default: 20)
* `--sort` / `-s` — sort by: `downloads`, `likes`, `lastModified`
* `--token` — HF API token
"""
use Mix.Task
@impl Mix.Task
def run(args) do
{opts, _, _} =
OptionParser.parse(args,
aliases: [a: :author, t: :type, n: :limit, s: :sort],
strict: [author: :string, type: :string, limit: :integer, sort: :string, token: :string]
)
token = opts[:token] || HuggingfaceClient.Config.token()
limit = opts[:limit] || 20
author = opts[:author]
type = opts[:type]
search_opts = [
access_token: token,
sort: opts[:sort] || "lastModified",
direction: -1,
limit: limit
]
search_opts = if author, do: Keyword.put(search_opts, :author, author), else: search_opts
repos =
case type do
"dataset" -> HuggingfaceClient.Hub.Search.datasets(search_opts) |> Enum.take(limit)
"space" -> HuggingfaceClient.Hub.Search.spaces(search_opts) |> Enum.take(limit)
_ -> HuggingfaceClient.Hub.Search.models(search_opts) |> Enum.take(limit)
end
if repos == [] do
Mix.shell().info("No repositories found.")
else
Mix.shell().info(String.pad_trailing("ID", 50) <> " " <> "Downloads" <> " " <> "Likes")
Mix.shell().info(String.duplicate("─", 70))
Enum.each(repos, fn r ->
id = r["id"] || r["modelId"] || ""
downloads = r["downloads"] || r["downloadsAllTime"] || "-"
likes = r["likes"] || "-"
line =
String.pad_trailing(id, 50) <>
" " <>
String.pad_leading("#{downloads}", 9) <>
" " <>
String.pad_leading("#{likes}", 5)
Mix.shell().info(line)
end)
Mix.shell().info("\n#{length(repos)} repository/ies shown")
end
end
defp print_repo_row(r) do
id = r["id"] || r["modelId"] || ""
downloads = r["downloads"] || r["downloadsAllTime"] || "-"
likes = r["likes"] || "-"
row =
String.pad_trailing(id, 50) <>
" " <>
String.pad_leading("#{downloads}", 9) <>
" " <>
String.pad_leading("#{likes}", 5)
Mix.shell().info(row)
end
end