Skip to content

Commit e0d5126

Browse files
committed
refactor: adopt generic methods
Go 1.27 allows methods to declare their own type parameters. Turn the package-level generic functions that took a receiver as first argument into methods: - http.Do[T](r, ...) becomes Request.Do[T](...) - http.OauthResult[T](o, ...) becomes OAuthRequest.Result[T](...) - cache.Get/Set/Delete/DeleteAll/Refresh/Print(store, ...) become methods on Store, e.g. cache.Device.Get[string](key) cache.Store already carried non-generic methods; Get and Set were only package functions because generic methods did not exist. OneOf (options) and the interface-based helpers stay functions, as interface methods cannot have type parameters. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01F4pmtq5zxSxC4VqXipPAmY
1 parent 42b00b9 commit e0d5126

65 files changed

Lines changed: 212 additions & 212 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

src/cache/clear.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ func Clear(force bool, excludedFiles ...string) error {
8383
}
8484

8585
func GetTTL() int {
86-
cacheTTL, OK := Get[int](Device, TTL)
86+
cacheTTL, OK := Device.Get[int](TTL)
8787
if !OK || cacheTTL <= 0 {
8888
cacheTTL = 7
8989
}

src/cache/command.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,14 +86,14 @@ func PersistCommandPath(command, path string, found bool) {
8686
ttl = CommandPathNegativeTTL
8787
}
8888

89-
Set(Session, commandPathKey(command), entry, ttl)
89+
Session.Set(commandPathKey(command), entry, ttl)
9090
}
9191

9292
// An entry persisted under a different PATH(+PATHEXT) environment is treated
9393
// as a miss, so the caller falls through to a fresh exec.LookPath (which
9494
// overwrites the entry with the current environment's hash).
9595
func GetPersistedCommandPath(command string) (path string, found, ok bool) {
96-
entry, exists := Get[commandPathEntry](Session, commandPathKey(command))
96+
entry, exists := Session.Get[commandPathEntry](commandPathKey(command))
9797
if !exists {
9898
return "", false, false
9999
}

src/cache/command_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ func TestGetPersistedCommandPathStalePathHashIsAMiss(t *testing.T) {
4242
// Simulate an entry persisted under a different PATH environment (or a
4343
// pre-PathHash entry, which decodes with PathHash == 0).
4444
entry := commandPathEntry{Path: "/usr/bin/git", PathHash: pathEnvHash() + 1, Found: true}
45-
Set(Session, commandPathKey("git"), entry, CommandPathTTL)
45+
Session.Set(commandPathKey("git"), entry, CommandPathTTL)
4646

4747
_, _, ok := GetPersistedCommandPath("git")
4848
assert.False(t, ok, "entry persisted under a different PATH must be treated as a miss")

src/cache/store.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ func touchSessionFile(filePath string) {
148148
// process (serve) that keeps its cache in memory for the session: without
149149
// it, a write from another process (e.g. `toggle`, `enable`/`disable`)
150150
// would stay invisible until the daemon exits.
151-
func Refresh(s Store) {
151+
func (s Store) Refresh() {
152152
defer log.Trace(time.Now(), string(s))
153153

154154
store := s.get()
@@ -202,7 +202,7 @@ func (s Store) close() {
202202
// (e.g. right before the shell exits) isn't clobbered by this store's
203203
// own, possibly stale, in-memory copy.
204204
if store != nil && !store.locked && store.persist && store.dirty {
205-
Refresh(s)
205+
s.Refresh()
206206
}
207207

208208
if store == nil || store.locked || !store.persist || !store.dirty {
@@ -250,7 +250,7 @@ func (s Store) close() {
250250
}
251251
}
252252

253-
func Get[T any](s Store, key string) (T, bool) {
253+
func (s Store) Get[T any](key string) (T, bool) {
254254
var zero T
255255
defer log.Trace(time.Now(), string(s), key)
256256

@@ -293,7 +293,7 @@ func Get[T any](s Store, key string) (T, bool) {
293293
return zero, false
294294
}
295295

296-
func Set[T any](s Store, key string, value T, duration Duration) {
296+
func (s Store) Set[T any](key string, value T, duration Duration) {
297297
defer log.Trace(time.Now(), string(s), key)
298298

299299
store := s.get()
@@ -318,7 +318,7 @@ func Set[T any](s Store, key string, value T, duration Duration) {
318318
store.dirty = true
319319
}
320320

321-
func Delete(s Store, key string) {
321+
func (s Store) Delete(key string) {
322322
defer log.Trace(time.Now(), string(s), key)
323323

324324
store := s.get()
@@ -332,7 +332,7 @@ func Delete(s Store, key string) {
332332
store.dirty = true
333333
}
334334

335-
func DeleteAll(s Store) {
335+
func (s Store) DeleteAll() {
336336
defer log.Trace(time.Now(), string(s))
337337

338338
store := s.get()
@@ -345,7 +345,7 @@ func DeleteAll(s Store) {
345345
store.dirty = true
346346
}
347347

348-
func Print(s Store) string {
348+
func (s Store) Print() string {
349349
defer log.Trace(time.Now(), string(s))
350350

351351
store := s.get()

src/cache/store_test.go

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ func TestStore(t *testing.T) {
4343
return testStore
4444
},
4545
testFunc: func(t *testing.T) {
46-
result := Print(Session)
46+
result := Session.Print()
4747
assert.Contains(t, result, "Key: test_key1")
4848
assert.Contains(t, result, `Value: "test_value1"`) // Note: quotes are included in output
4949
assert.Contains(t, result, "Type: string")
@@ -67,7 +67,7 @@ func TestStore(t *testing.T) {
6767
return testStore
6868
},
6969
testFunc: func(t *testing.T) {
70-
result := Print(Session)
70+
result := Session.Print()
7171
assert.Contains(t, result, "Store session is empty")
7272
},
7373
},
@@ -80,7 +80,7 @@ func TestStore(t *testing.T) {
8080
},
8181
testFunc: func(t *testing.T) {
8282
// Since get() always creates a store, we test empty store behavior
83-
result := Print(Session)
83+
result := Session.Print()
8484
assert.Contains(t, result, "Store session is empty")
8585
},
8686
},
@@ -154,15 +154,15 @@ func TestGetSurvivesGobPointerRegistration(t *testing.T) {
154154
writer.persist = true
155155
device = writer
156156

157-
Set(Device, "test_key", storeGobPointerType{Name: "value"}, Duration("1h"))
157+
Device.Set("test_key", storeGobPointerType{Name: "value"}, Duration("1h"))
158158
Device.close()
159159

160160
// Second process: fresh store, loaded from disk. This is the gob decode
161161
// that flips the interface-typed value from T to *T.
162162
device = nil
163163
Device.init(fileName, true)
164164

165-
got, ok := Get[storeGobPointerType](Device, "test_key")
165+
got, ok := Device.Get[storeGobPointerType]("test_key")
166166
require.True(t, ok, "expected a cache hit after a gob round-trip of a pointer-registered type")
167167
assert.Equal(t, "value", got.Name)
168168
}
@@ -212,15 +212,15 @@ func TestRefreshMergesExternalWriteByTimestamp(t *testing.T) {
212212
// Back to the daemon's perspective: refresh should pick up the new
213213
// toggle_cache key from disk...
214214
session = daemon
215-
Refresh(Session)
215+
Session.Refresh()
216216

217-
toggled, found := Get[map[string]bool](Session, TOGGLECACHE)
217+
toggled, found := Session.Get[map[string]bool](TOGGLECACHE)
218218
require.True(t, found, "toggle_cache written externally should be visible after Refresh")
219219
assert.True(t, toggled["shell"])
220220

221221
// ...without clobbering the daemon's own newer value for a key both
222222
// sides touched.
223-
shared, found := Get[string](Session, "shared_key")
223+
shared, found := Session.Get[string]("shared_key")
224224
require.True(t, found)
225225
assert.Equal(t, "daemon-value", shared, "a newer in-memory value must win over an older on-disk one")
226226
}
@@ -272,11 +272,11 @@ func TestCloseRefreshesBeforePersistingToAvoidClobber(t *testing.T) {
272272

273273
session = &store{cache: onDisk.ToConcurrent()}
274274

275-
toggled, found := Get[map[string]bool](Session, TOGGLECACHE)
275+
toggled, found := Session.Get[map[string]bool](TOGGLECACHE)
276276
require.True(t, found, "the external write must survive the daemon's own shutdown flush")
277277
assert.True(t, toggled["shell"])
278278

279-
count, found := Get[int](Session, "prompt_count_cache")
279+
count, found := Session.Get[int]("prompt_count_cache")
280280
require.True(t, found)
281281
assert.Equal(t, 3, count)
282282
}
@@ -310,9 +310,9 @@ func TestRefreshPicksUpDeviceStoreWrite(t *testing.T) {
310310
Device.close()
311311

312312
device = daemon
313-
Refresh(Device)
313+
Device.Refresh()
314314

315-
reload, found := Get[bool](Device, "reload")
315+
reload, found := Device.Get[bool]("reload")
316316
require.True(t, found, "`enable reload` written externally should be visible after Refresh")
317317
assert.True(t, reload)
318318
}

src/cli/auth/tui/copilot.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ func (c *CopilotAuth) Authenticate() {
8888
return
8989
}
9090

91-
cache.Set(cache.Device, auth.CopilotTokenKey, token, cache.TWOYEARS)
91+
cache.Device.Set(auth.CopilotTokenKey, token, cache.TWOYEARS)
9292

9393
setState(done)
9494
}

src/cli/auth/tui/ytmda.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ func (y *Ytmda) Authenticate() {
6363
return
6464
}
6565

66-
cache.Set(cache.Device, auth.YTMDATOKEN, token, cache.INFINITE)
66+
cache.Device.Set(auth.YTMDATOKEN, token, cache.INFINITE)
6767

6868
setState(done)
6969
}

src/cli/auth/tui/ytmda_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,12 +95,12 @@ func TestYtdma_Authenticate(t *testing.T) {
9595
}
9696

9797
if tc.shouldSetToken {
98-
token, ok := cache.Get[string](cache.Device, auth.YTMDATOKEN)
98+
token, ok := cache.Device.Get[string](auth.YTMDATOKEN)
9999
require.True(t, ok)
100100
assert.Equal(t, tc.expectedToken, token)
101101
}
102102

103-
cache.DeleteAll(cache.Device)
103+
cache.Device.DeleteAll()
104104
})
105105
}
106106
}

src/cli/cache.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ You can do the following:
6565
}
6666

6767
cache.Init(os.Getenv("POSH_SHELL"), cache.Persist)
68-
cache.Set(cache.Device, cache.TTL, ttl, cache.INFINITE)
68+
cache.Device.Set(cache.TTL, ttl, cache.INFINITE)
6969
cache.Close()
7070
case "show":
7171
cache.Init(os.Getenv("POSH_SHELL"))
@@ -74,7 +74,7 @@ You can do the following:
7474
store = cache.Session
7575
}
7676

77-
fmt.Println(cache.Print(store))
77+
fmt.Println(store.Print())
7878
}
7979
},
8080
}

src/cli/config.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ You can export or edit the config (via the editor specified in the environment v
3030
switch args[0] {
3131
case "edit":
3232
cache.Init(os.Getenv("POSH_SHELL"))
33-
if configPath, OK := cache.Get[string](cache.Session, config.SourceKey); OK {
33+
if configPath, OK := cache.Session.Get[string](config.SourceKey); OK {
3434
exitcode = editFileWithEditor(configPath)
3535
return
3636
}

0 commit comments

Comments
 (0)