FetchBlob retrieves the content of a blob by SHA. The blob is base64-encoded inside the JSON response and decoded here, so it is returned as iostreams.Untrusted and callers must choose sanitized display or raw round-tripping.
(client *api.Client, host, owner, repo, sha string)
| 916 | // iostreams.Untrusted and callers must choose sanitized display or raw |
| 917 | // round-tripping. |
| 918 | func FetchBlob(client *api.Client, host, owner, repo, sha string) (iostreams.Untrusted, error) { |
| 919 | apiPath, err := safeurl.JoinPath("repos", owner, repo, "git", "blobs", sha) |
| 920 | if err != nil { |
| 921 | return iostreams.Untrusted{}, err |
| 922 | } |
| 923 | var resp struct { |
| 924 | SHA string `json:"sha"` |
| 925 | Content string `json:"content"` |
| 926 | Encoding string `json:"encoding"` |
| 927 | } |
| 928 | if err := client.REST(host, "GET", apiPath.String(), nil, &resp); err != nil { |
| 929 | return iostreams.Untrusted{}, fmt.Errorf("could not fetch blob: %w", err) |
| 930 | } |
| 931 | |
| 932 | if resp.Encoding != "base64" { |
| 933 | return iostreams.Untrusted{}, fmt.Errorf("unexpected blob encoding: %s", resp.Encoding) |
| 934 | } |
| 935 | |
| 936 | // GitHub API returns base64 with embedded newlines; use the StdEncoding |
| 937 | // decoder via a reader to handle them transparently. |
| 938 | decoded, err := io.ReadAll(base64.NewDecoder(base64.StdEncoding, strings.NewReader(resp.Content))) |
| 939 | if err != nil { |
| 940 | return iostreams.Untrusted{}, fmt.Errorf("could not decode blob content: %w", err) |
| 941 | } |
| 942 | |
| 943 | return iostreams.NewUntrustedBytes(decoded), nil |
| 944 | } |
| 945 | |
| 946 | // DiscoverLocalSkills finds non-hidden-dir skills in a local directory using |
| 947 | // the same conventions as remote discovery. Hidden-dir skills are excluded; use |