fix(forge): make client accessors nil-safe
All checks were successful
Security Scan / security (push) Successful in 14s
Test / test (push) Successful in 1m54s

Co-Authored-By: Virgil <virgil@lethean.io>
This commit is contained in:
Virgil 2026-04-02 09:00:15 +00:00
parent d08c875fcf
commit 00a30817f2
4 changed files with 92 additions and 6 deletions

View file

@ -171,6 +171,9 @@ type Client struct {
//
// baseURL := client.BaseURL()
func (c *Client) BaseURL() string {
if c == nil {
return ""
}
return c.baseURL
}
@ -180,6 +183,9 @@ func (c *Client) BaseURL() string {
//
// rl := client.RateLimit()
func (c *Client) RateLimit() RateLimit {
if c == nil {
return RateLimit{}
}
return c.rateLimit
}
@ -189,6 +195,9 @@ func (c *Client) RateLimit() RateLimit {
//
// ua := client.UserAgent()
func (c *Client) UserAgent() string {
if c == nil {
return ""
}
return c.userAgent
}
@ -198,6 +207,9 @@ func (c *Client) UserAgent() string {
//
// hc := client.HTTPClient()
func (c *Client) HTTPClient() *http.Client {
if c == nil {
return nil
}
return c.httpClient
}
@ -232,6 +244,9 @@ func (c *Client) GoString() string { return c.String() }
// _ = "authenticated"
// }
func (c *Client) HasToken() bool {
if c == nil {
return false
}
return c.token != ""
}

View file

@ -215,6 +215,25 @@ func TestClient_HasToken_Bad(t *testing.T) {
}
}
func TestClient_NilSafeAccessors(t *testing.T) {
var c *Client
if got := c.BaseURL(); got != "" {
t.Fatalf("got BaseURL()=%q, want empty string", got)
}
if got := c.RateLimit(); got != (RateLimit{}) {
t.Fatalf("got RateLimit()=%#v, want zero value", got)
}
if got := c.UserAgent(); got != "" {
t.Fatalf("got UserAgent()=%q, want empty string", got)
}
if got := c.HTTPClient(); got != nil {
t.Fatal("expected HTTPClient() to return nil")
}
if got := c.HasToken(); got {
t.Fatal("expected HasToken() to report false")
}
}
func TestClient_WithHTTPClient_Good(t *testing.T) {
custom := &http.Client{}
c := NewClient("https://forge.lthn.ai", "tok", WithHTTPClient(custom))

View file

@ -72,35 +72,60 @@ func NewForge(url, token string, opts ...Option) *Forge {
// Usage:
//
// client := f.Client()
func (f *Forge) Client() *Client { return f.client }
func (f *Forge) Client() *Client {
if f == nil {
return nil
}
return f.client
}
// BaseURL returns the configured Forgejo base URL.
//
// Usage:
//
// baseURL := f.BaseURL()
func (f *Forge) BaseURL() string { return f.client.BaseURL() }
func (f *Forge) BaseURL() string {
if f == nil || f.client == nil {
return ""
}
return f.client.BaseURL()
}
// RateLimit returns the last known rate limit information.
//
// Usage:
//
// rl := f.RateLimit()
func (f *Forge) RateLimit() RateLimit { return f.client.RateLimit() }
func (f *Forge) RateLimit() RateLimit {
if f == nil || f.client == nil {
return RateLimit{}
}
return f.client.RateLimit()
}
// UserAgent returns the configured User-Agent header value.
//
// Usage:
//
// ua := f.UserAgent()
func (f *Forge) UserAgent() string { return f.client.UserAgent() }
func (f *Forge) UserAgent() string {
if f == nil || f.client == nil {
return ""
}
return f.client.UserAgent()
}
// HTTPClient returns the configured underlying HTTP client.
//
// Usage:
//
// hc := f.HTTPClient()
func (f *Forge) HTTPClient() *http.Client { return f.client.HTTPClient() }
func (f *Forge) HTTPClient() *http.Client {
if f == nil || f.client == nil {
return nil
}
return f.client.HTTPClient()
}
// HasToken reports whether the Forge client was configured with an API token.
//
@ -109,7 +134,12 @@ func (f *Forge) HTTPClient() *http.Client { return f.client.HTTPClient() }
// if f.HasToken() {
// _ = "authenticated"
// }
func (f *Forge) HasToken() bool { return f.client.HasToken() }
func (f *Forge) HasToken() bool {
if f == nil || f.client == nil {
return false
}
return f.client.HasToken()
}
// String returns a safe summary of the Forge client.
//

View file

@ -82,6 +82,28 @@ func TestForge_HasToken_Bad(t *testing.T) {
}
}
func TestForge_NilSafeAccessors(t *testing.T) {
var f *Forge
if got := f.Client(); got != nil {
t.Fatal("expected Client() to return nil")
}
if got := f.BaseURL(); got != "" {
t.Fatalf("got BaseURL()=%q, want empty string", got)
}
if got := f.RateLimit(); got != (RateLimit{}) {
t.Fatalf("got RateLimit()=%#v, want zero value", got)
}
if got := f.UserAgent(); got != "" {
t.Fatalf("got UserAgent()=%q, want empty string", got)
}
if got := f.HTTPClient(); got != nil {
t.Fatal("expected HTTPClient() to return nil")
}
if got := f.HasToken(); got {
t.Fatal("expected HasToken() to report false")
}
}
func TestForge_String_Good(t *testing.T) {
f := NewForge("https://forge.lthn.ai", "tok", WithUserAgent("go-forge/1.0"))
got := fmt.Sprint(f)