fix(git-tools): repair Gitea repo info and issue list author - #173
Open
calcorum wants to merge 1 commit into
Open
fix(git-tools): repair Gitea repo info and issue list author#173calcorum wants to merge 1 commit into
calcorum wants to merge 1 commit into
Conversation
Three defects on the Gitea path of `git-cli`, all the same root cause as St0nefish#133: the code asked `tea` for a shape it does not emit, and the failures were silent rather than loud. `repo info` returned nothing at all on Gitea. It filtered `tea repos list --output json` with `select(.full_name == $slug)`, but that command emits only {owner,name,type,ssh} — the select dropped every row, and the trailing `2>/dev/null || echo "{}"` swallowed the evidence, so it exited 0 with empty output. `tea repos list` is also paginated (30/page) and cannot report `default_branch` under any `--fields` combination, so no jq fix was possible; it now fetches the repo directly via `tea api repos/{owner}/{repo}`, matching the shape St0nefish#133 introduced for `run show`. The slug feeding that call was itself broken. `([^/]+/[^/]+?)(\.git)?$` relies on a lazy quantifier, and POSIX ERE has none — `+?` matched greedily, `(\.git)?` matched empty, and the slug kept its `.git` suffix. Latent before (the result was discarded either way), fatal once it reaches the API. `issue list` always reported `author: ""`. The `--fields` request omitted `author` while the normalizer read `.author`; tea emits only the fields named, so it was always the empty fallback. `issue show` uses a different tea command that emits `user`, which the code already reads — that path was correct and is unchanged. - repo:info (gitea) — fetch via `tea api repos/{owner}/{repo}`; read `.owner.login` (object) rather than `.owner` (string in the old shape) - repo:info (gitea) — strip `.git` in a separate sed expression - issue:list (gitea) — add `author` to the requested `--fields` - add tests/git-cli/test-gitea-repo-info-issue-author.sh (8 cases; all 8 fail against the previous code, covering all four remote URL forms) - bump git-tools 2.2.1 → 2.2.2 and session 4.5.0 → 4.5.1 (both vendor git-cli), and re-run utils/sync.sh Note a deliberate behaviour change: `repo info` on Gitea now reports errors instead of swallowing them, since it routes through `cli_json`. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Three defects on the Gitea path of
git-cli, all the same root cause as #133: the code asksteafor a shape it does not emit. All three fail silently — empty output or an empty string, never an error — which is why they survived.Found while using the
git-toolsplugin against a self-hosted Gitea instance.1.
repo inforeturns nothing on GiteaIt filtered
tea repos list --output jsonwithselect(.full_name == $slug). That command emits only{owner, name, type, ssh}:So the select dropped every row. The trailing
2>/dev/null || echo "{}"then swallowed the evidence, leaving an empty result and exit 0.A jq-only fix isn't possible:
tea repos list --fieldsoffersdescription,forks,id,name,owner,stars,ssh,updated,url,permission,type— nofull_name, nodefault_branch, no visibility — and it is paginated at 30/page, so a filter would miss any repo past the first page regardless.Fixed by fetching the repo directly via
tea api repos/{owner}/{repo}, which returns all the required fields. This is the same shape #133 introduced forrun show.2. The remote slug kept its
.gitsuffixsed -E 's|.*[:/]([^/]+/[^/]+?)(\.git)?$|\1|'This relies on
+?being lazy. POSIX ERE has no lazy quantifiers, so[^/]+matched greedily,(\.git)?matched empty, and the result wasowner/repo.git:Masked before this change rather than latent — the
selectfailed on.full_namefirst, so a wrong slug never got the chance to surface. Two independent bugs hiding each other. Fatal once the slug is interpolated into an API path. Now stripped in its own expression.3.
issue listalways reportsauthor: ""The
--fieldsrequest omittedauthorwhile the normalizer reads.author.teaemits only the fields named, so it was always the empty fallback:issue showis unaffected — it usestea issues <N>, which emitsuser, and the code already reads.user. That path was correct and is unchanged.Testing
New suite
tests/git-cli/test-gitea-repo-info-issue-author.sh, 8 cases, following the mock-PATH pattern fromtest-run-show.sh:repo infoemits a populated normalized object (name, owner, description, default_branch, visibility, url, stars, forks)tea repos listis never invoked (sentinel)repos/owner/repoacross all four remote URL forms —ssh://…:2222/…,git@host:…,https://…/….git, and no-suffixissue listrequestsauthorin--fieldsand reports a non-empty authorThe
teamock honours--fieldsthe way tea does (emitting only the named fields), so case 4 genuinely fails if the field is dropped again.All 8 fail against the pre-change code and pass after.
Also run locally:
bash tests/test.sh— no new failures.permission-manager/test-classifyfails with 9 cases, but it fails identically on a pristineorigin/masterworktree; pre-existing and unrelated.bash .github/scripts/validate-plugins.sh— 300 checks, 0 failures (includes vendored-drift and version-sync)bash .github/scripts/validate-frontmatter.sh— 103 checks, 0 failuresCI's
shellcheck --severity=errorjob covers the changed scripts; no executable line differs from the reviewed diff.Also verified against a live Gitea instance (tea 0.14.1), old code vs new, on real repos with
git@host:owner/repo.gitremotes:repo info— old printed nothing and exited 0; new returns the populated object (name, owner, description,default_branch, visibility, url, stars, forks).issue list— old reportedauthor: ""for every issue; new reports the real login.owner/repo.giton the three.git-suffixed ones, the new one strips it.Notes for the reviewer
utils/git-cliand re-ranutils/sync.sh; vendored copies forgit-toolsandsessionare in the same commit.git-tools2.2.1 → 2.2.2 andsession4.5.0 → 4.5.1 (both vendorgit-cli), claude and copilot manifests together.repo infoon Gitea now surfaces errors instead of swallowing them, because it routes throughcli_jsonrather than… 2>/dev/null || echo "{}". This aligns it with the rest of the file rather than departing from it:cli_json, whichdies on a non-zero exit with the CLI's stderr — all 23 call sites, coveringissue list/show,issue comment,pr list/show,pr comment, andrun list/show.cli_jsoncatches process failure (network, auth, a missingtea). It does not catch API-level errors, becausetea apiprints{"message":"not found",…}and still exits 0 — a 404 therefore yields a null-filled object rather than an error. That is not new here:run showbehaves identically, and has since git-cli:run showbroken on Gitea — tea ignores --output json, jq parse error #133. Worth a follow-up across alltea apicall sites, but out of scope for this fix.repo info's own GitHub arm, three lines above the Gitea arm, already usedcli_json. Before this change the two platform branches of one subcommand disagreed about whether a fetch failure is an error: on GitHub it aborted, on Gitea it printed nothing and exited 0.2>/dev/null || <fallback>sites elsewhere are a different layer — the ship/wait loops, which soften the results of git-cli's own already-cli_json'd subcommands. That's intentional and documented at_ci_status: "Every API call is guarded so a probe failure degrades tononeand never aborts the wait loop." "No CI run yet for this branch" is a legitimate state during a poll, not an error.|| echofallbacks arerepo:default-branch's|| echo "main"(tail of a git-local resolution chain, no API call) and that_ci_statusprobe. The oldrepo infoline was the sole primitive-layer swallow in the file.