feat(forge): support Gitea (and Forgejo) in the repository panel
Adds a third `ForgeProvider` and the `/api/v1` client behind it, so the repository panel, the trigger flow and the delivery path work against a Gitea or Forgejo instance the same way they do against GitHub and GitLab. Gitea models a repository the way GitHub does — a pull request IS an issue, one comment collection serves both — so the new client follows `github.rs` rather than `gitlab.rs`. Where it cannot, each difference is a silent wrong answer if assumed away: - The issue list takes no `sort` (Gitea hard-codes newest-first), so the order is ignored and the panel HIDES the control rather than showing a choice the server discards. - A new issue's labels are IDs, not names, so they are resolved against the repository's vocabulary first — exact match before loose. - The file list carries no patch, so the change's own `.diff` is streamed under a 2 MiB cap and split per file, keyed off `+++ b/<path>` (the path AFTER a rename, which is the one the file list reports). - The comment collection is unpaginated, so the page is cut client-side. - `status`, not `state`, on a commit status; `deleted`, not `removed`, on a changed file; `pulls`, not `pull`, in the web URL. - Gitea's three "join it as it is" merge styles all map to one method, with the difference carried by the existing merge strategy, so a repository that permits only `rebase-merge` or `fast-forward-only` merges instead of taking a 405 on every press. Host detection asks the public, unauthenticated `/api/v1/version` FIRST and concludes from its body, so a self-hosted instance whose name says nothing identifies itself before a credential is spent. Probe bodies are now read to a 4 KiB cap instead of whole. `find_pulls` is the one place this client can be incomplete: Gitea's `/pulls` has no head filter and its base/head lookup answers with an arbitrary row when a branch has both a closed and an open change, so the match is local over a bounded scan. It fails safe — an unseen pull request reads as no match, and the create that follows is refused by Gitea itself rather than duplicating anything. Settings gain a Gitea accounts section with its own token validation (`validate_gitea_token`, Tauri command plus HTTP route), and the unsupported-host explanation now names three forges across all ten locales.
X
xintaofei committed
221d54404feed7709ca261aae304f54723d0b161
Parent: ccc420c