Pass through to gh with a -- separator, delegating to gh --attach when it can do the job - #61
Draft
drogers0 wants to merge 3 commits into
Draft
Pass through to gh with a -- separator, delegating to gh --attach when it can do the job#61drogers0 wants to merge 3 commits into
drogers0 wants to merge 3 commits into
Conversation
drogers0
marked this pull request as draft
September 1, 2026 22:59
…sition Three defects found reviewing #61, each silent: - A body reference spelled differently from the command line never matched, so ./shot.png with a body naming shot.png left the reference dangling and appended a duplicate. Upstream resolves both sides to an absolute path; now so do we, keeping the raw destination bytes for the replacement so escaped and angle-bracket spellings still work. - Rebuilding the argv stripped any token starting with -b, -F, --body or --attach, so a value like `--title -Fix crash` lost its value and left --title to swallow --body. Classify now records the positions its body flags occupy and only those are dropped. It also consumes --title's own value, the one upstream flag whose value plausibly starts with a dash. - --attach right of -- was validated and then dropped on the gh-image route, losing a file without a word. It is refused instead, naming the files-left-of-- form that works on both routes.
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.
Implements the passthrough proposed in #58: everything left of
--is ours, everything right of it is aghinvocation.gh image diagram.pdf -- pr create --title "Design" --body-file design.md gh image shot.png -- issue comment 42 --body-file note.md gh image shot.png -- pr create --fillWhat happens, in plain terms
Two routes exist. You never pick one — the tool works out which can do the job. Either way you type one command and the file ends up in the body.
create, with--body/--body-fileghcreate, without a body flag (--fill, editor)gh --attach--fillmeans gh writes the body, so there is nothing for us to rewritecomment/editghis tried first, refuses the type, gh-image takes overcomment/editghis tried first, refuses, gh-image takes overghtoo old to have--attachghon your machine, per commandcreatewith no body flag and no--attachsupportWhere the file lands in the body:
Path spelling does not matter:
./shot.png,shot.pnganddocs/../shot.pngall match the same file, the wayghmatches it.One case stops rather than guessing: if
ghfails partway through a comment but has already posted it, we do not post a second one — we stop and name the files that may be missing.Routing, precisely
gh <subcommand> --helpis checked for--attachonce per run — per command, not per binary, so a build carrying the flag on only some commands routes correctly.ghresolves viaGH_PATH, thenPATH.UploadAndAttachwrites when at least one asset uploaded) cannot arise: body flag → our route with no--attach; no body flag → delegate verbatim and never fall back; no body flag and no--attachsupport → refuse before uploading.This adopts the refinement discussion on the issue with one change to the second comment's rule: create delegates exactly when fallback is impossible (no body flag), rather than never. Every upstream refusal class — extension, size, token type, permission, host — exits before any side effect, verified against cli/cli trunk, so
-- pr create --fillwith an eligible file keeps working instead of being refused.Fallback rewriter (
internal/passthrough)goldmark walk of inline image and link nodes. Destinations naming an uploaded file are replaced by byte range, preserving titles and angle-bracket wrappers, skipping code spans and fences. Both sides resolve to an absolute path before matching, as upstream's rewriter does. Reference-style links error with a request for an inline link. Files the body never references are appended using the existing per-type markdown — image embed, bare video URL,
[name](url)otherwise. About 280 lines against upstream's ~810, which is an internal package and not importable.Only upstream surface knowledge taken on: the six subcommands plus their cobra aliases (
pr new,issue new), the four body-flag spellings,--repo/-Rfor targeting the fallback upload, and--title(whose value can begin with a dash). User-definedghaliases are refused with a clear message rather than guessed at, as is--attachright of--, which would otherwise be honoured on one route and dropped on the other.Behaviour notes
ghprints, withgh's exit code; route notes and diagnostics go to stderr. The no---mode is unchanged.--body-file -is buffered before delegation so the fallback can replay it.gh image -- -dashed-file.png(escape-dash) is gone —--now always means passthrough. Usegh image ./-dashed-file.png.Testing
Probe, exec and comment-verification are injected boundaries alongside the existing
newUploader/newDownloader, so both routes are exercised with no liveghand no network: routing per kind × probe × body-flag, stdin replay across delegate-then-fallback, argv building, and table-driven rewriter cases covering inline, titled, angle-bracket and escaped destinations, path spellings, code spans and fences, and per-type appends.gofmt,go vet,go build,go test ./...all clean. The lint job is pinned to the module's Go version in a separate commit — golangci-lint v2.12.2 cannot typecheck the Go 1.27 standard library, which failsmaintoday as well.Closes #58