Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 731cee3

Browse files
committed
fix: address clawpatch findings
1 parent 8a14a04 commit 731cee3

160 files changed

Lines changed: 1809 additions & 970 deletions

File tree

Some content is hidden

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

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ go.work.sum
3333

3434
# Local tools
3535
.tools/
36+
.clawpatch/
3637

3738
# Local build output
3839
bin/

Makefile

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ SHELL := /bin/bash
33
# `make` should build the binary by default.
44
.DEFAULT_GOAL := build
55

6-
.PHONY: build build-safe gog gogcli gog-help gogcli-help help fmt fmt-check lint test ci tools docs-commands docs-site docs-check
6+
.PHONY: build build-safe gog gogcli gog-help gogcli-help help fmt fmt-check lint test ci tools pnpm-gate docs-commands docs-site docs-check
77
.PHONY: worker-ci
88

99
BIN_DIR := $(CURDIR)/bin
@@ -81,6 +81,7 @@ tools:
8181
@if [ -x "$(GOFUMPT)" ] && [ -x "$(GOIMPORTS)" ] && [ -x "$(GOLANGCI_LINT)" ] && [ "$$(cat $(TOOLS_STAMP) 2>/dev/null)" = "$(TOOLS_VERSION)" ]; then \
8282
echo "tools up to date"; \
8383
else \
84+
set -e; \
8485
GOBIN=$(TOOLS_DIR) go install mvdan.cc/[email protected]; \
8586
GOBIN=$(TOOLS_DIR) go install golang.org/x/tools/cmd/[email protected]; \
8687
GOBIN=$(TOOLS_DIR) go install github.com/golangci/golangci-lint/v2/cmd/[email protected]; \
@@ -92,9 +93,16 @@ fmt: tools
9293
@$(GOFUMPT) -w .
9394

9495
fmt-check: tools
95-
@$(GOIMPORTS) -local github.com/steipete/gogcli -w .
96-
@$(GOFUMPT) -w .
97-
@git diff --exit-code -- '*.go' go.mod go.sum
96+
@set -e; \
97+
tmp="$$(mktemp)"; \
98+
trap 'rm -f "$$tmp"' EXIT; \
99+
$(GOIMPORTS) -local github.com/steipete/gogcli -l . > "$$tmp"; \
100+
$(GOFUMPT) -l . >> "$$tmp"; \
101+
unformatted="$$(sort -u "$$tmp")"; \
102+
if [ -n "$$unformatted" ]; then \
103+
printf 'formatting needed:\n%s\n' "$$unformatted"; \
104+
exit 1; \
105+
fi
98106

99107
lint: tools
100108
@$(GOLANGCI_LINT) run

internal/backup/async_push.go

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,10 @@ type asyncPushJob struct {
2020
}
2121

2222
type asyncRepoPusher struct {
23-
cfg Config
24-
progress func(format string, args ...any)
23+
cfg Config
24+
25+
progressMu sync.RWMutex
26+
progress func(format string, args ...any)
2527

2628
mu sync.Mutex
2729
cond *sync.Cond
@@ -111,7 +113,7 @@ func asyncPusherFor(ctx context.Context, cfg Config, progress func(format string
111113
defer asyncPushers.mu.Unlock()
112114
if pusher := asyncPushers.m[repo]; pusher != nil {
113115
if progress != nil {
114-
pusher.progress = progress
116+
pusher.setProgress(progress)
115117
}
116118
return pusher
117119
}
@@ -131,7 +133,7 @@ func existingAsyncPusher(repo string, progress func(format string, args ...any))
131133
defer asyncPushers.mu.Unlock()
132134
pusher := asyncPushers.m[strings.TrimSpace(repo)]
133135
if pusher != nil && progress != nil {
134-
pusher.progress = progress
136+
pusher.setProgress(progress)
135137
}
136138
return pusher
137139
}
@@ -184,14 +186,37 @@ func (p *asyncRepoPusher) pushWithRetry(ctx context.Context, job asyncPushJob) e
184186
}
185187
delay := time.Duration(attempt*15) * time.Second
186188
p.progressf("backup git push\tretry\tsha=%s\tattempt=%d\tdelay=%s\terr=%q", shortSHA(job.sha), attempt, delay, err.Error())
187-
time.Sleep(delay)
189+
if err := waitAsyncPushRetry(ctx, delay); err != nil {
190+
return err
191+
}
188192
}
189193
return lastErr
190194
}
191195

196+
func (p *asyncRepoPusher) setProgress(progress func(format string, args ...any)) {
197+
p.progressMu.Lock()
198+
defer p.progressMu.Unlock()
199+
p.progress = progress
200+
}
201+
192202
func (p *asyncRepoPusher) progressf(format string, args ...any) {
193-
if p.progress != nil {
194-
p.progress(format, args...)
203+
p.progressMu.RLock()
204+
progress := p.progress
205+
p.progressMu.RUnlock()
206+
if progress != nil {
207+
progress(format, args...)
208+
}
209+
}
210+
211+
func waitAsyncPushRetry(ctx context.Context, delay time.Duration) error {
212+
timer := time.NewTimer(delay)
213+
defer timer.Stop()
214+
215+
select {
216+
case <-ctx.Done():
217+
return fmt.Errorf("retry async backup push: %w", ctx.Err())
218+
case <-timer.C:
219+
return nil
195220
}
196221
}
197222

internal/backup/async_push_test.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package backup
2+
3+
import (
4+
"context"
5+
"errors"
6+
"testing"
7+
"time"
8+
)
9+
10+
func TestWaitAsyncPushRetryCanceled(t *testing.T) {
11+
ctx, cancel := context.WithCancel(context.Background())
12+
cancel()
13+
14+
err := waitAsyncPushRetry(ctx, time.Hour)
15+
if !errors.Is(err, context.Canceled) {
16+
t.Fatalf("expected context canceled, got %v", err)
17+
}
18+
}
19+
20+
func TestAsyncPusherProgressCanBeUpdated(t *testing.T) {
21+
var got []string
22+
p := &asyncRepoPusher{
23+
progress: func(format string, _ ...any) {
24+
got = append(got, "old:"+format)
25+
},
26+
}
27+
28+
p.setProgress(func(format string, _ ...any) {
29+
got = append(got, "new:"+format)
30+
})
31+
p.progressf("event")
32+
33+
if len(got) != 1 || got[0] != "new:event" {
34+
t.Fatalf("unexpected progress calls: %#v", got)
35+
}
36+
}

internal/cmd/account.go

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,10 @@ func requireAccount(flags *RootFlags) (string, error) {
2727
// or keyring lookup is needed. We still accept --account/GOG_ACCOUNT as an
2828
// optional label (e.g. for logging), but it is not required.
2929
if googleapi.IsADCMode() {
30-
if v := strings.TrimSpace(flags.Account); v != "" {
30+
if v := flagAccount(flags); v != "" {
31+
if shouldAutoSelectAccount(v) {
32+
return "adc", nil
33+
}
3134
return v, nil
3235
}
3336
if v := strings.TrimSpace(os.Getenv("GOG_ACCOUNT")); v != "" {
@@ -62,14 +65,20 @@ func requireAccount(flags *RootFlags) (string, error) {
6265
}
6366

6467
func configuredAccount(flags *RootFlags) (string, bool, error) {
65-
for _, candidate := range []string{flagAccount(flags), strings.TrimSpace(os.Getenv("GOG_ACCOUNT"))} {
68+
if candidate := flagAccount(flags); candidate != "" {
6669
account, ok, err := selectConfiguredAccount(candidate)
6770
if err != nil {
6871
return "", false, err
6972
}
70-
if ok {
71-
return account, true, nil
73+
return account, ok, nil
74+
}
75+
76+
if candidate := strings.TrimSpace(os.Getenv("GOG_ACCOUNT")); candidate != "" {
77+
account, ok, err := selectConfiguredAccount(candidate)
78+
if err != nil {
79+
return "", false, err
7280
}
81+
return account, ok, nil
7382
}
7483

7584
return "", false, nil

internal/cmd/account_test.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,38 @@ func TestRequireAccount_AutoUsesDefault(t *testing.T) {
118118
}
119119
}
120120

121+
func TestRequireAccount_ExplicitAutoIgnoresEnv(t *testing.T) {
122+
t.Setenv("GOG_ACCOUNT", "[email protected]")
123+
flags := &RootFlags{Account: "auto"}
124+
125+
prev := openSecretsStoreForAccount
126+
t.Cleanup(func() { openSecretsStoreForAccount = prev })
127+
openSecretsStoreForAccount = func() (secrets.Store, error) {
128+
return &fakeSecretsStore{defaultAccount: "[email protected]"}, nil
129+
}
130+
131+
got, err := requireAccount(flags)
132+
if err != nil {
133+
t.Fatalf("err: %v", err)
134+
}
135+
if got != "[email protected]" {
136+
t.Fatalf("got %q", got)
137+
}
138+
}
139+
140+
func TestRequireAccount_ADCNilFlags(t *testing.T) {
141+
t.Setenv("GOG_AUTH_MODE", "adc")
142+
t.Setenv("GOG_ACCOUNT", "")
143+
144+
got, err := requireAccount(nil)
145+
if err != nil {
146+
t.Fatalf("err: %v", err)
147+
}
148+
if got != "adc" {
149+
t.Fatalf("got %q", got)
150+
}
151+
}
152+
121153
func TestRequireAccount_Missing(t *testing.T) {
122154
t.Setenv("GOG_ACCOUNT", "")
123155
flags := &RootFlags{}

internal/cmd/admin_groups.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -275,7 +275,7 @@ func (c *AdminGroupsMembersAddCmd) Run(ctx context.Context, flags *RootFlags) er
275275
})
276276
}
277277

278-
u.Out().Printf("Added %s to %s as %s", created.Email, groupEmail, created.Role)
278+
u.Out().Linef("Added %s to %s as %s", created.Email, groupEmail, created.Role)
279279
return nil
280280
}
281281

@@ -321,6 +321,6 @@ func (c *AdminGroupsMembersRemoveCmd) Run(ctx context.Context, flags *RootFlags)
321321
}
322322

323323
u := ui.FromContext(ctx)
324-
u.Out().Printf("Removed %s from %s", memberEmail, groupEmail)
324+
u.Out().Linef("Removed %s from %s", memberEmail, groupEmail)
325325
return nil
326326
}

internal/cmd/admin_orgunits.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ func (c *AdminOrgunitsCreateCmd) Run(ctx context.Context, flags *RootFlags) erro
165165
if outfmt.IsJSON(ctx) {
166166
return outfmt.WriteJSON(ctx, os.Stdout, created)
167167
}
168-
u.Out().Printf("Created org unit: %s (%s)\n", created.Name, created.OrgUnitPath)
168+
u.Out().Linef("Created org unit: %s (%s)", created.Name, created.OrgUnitPath)
169169
return nil
170170
}
171171

@@ -231,7 +231,7 @@ func (c *AdminOrgunitsUpdateCmd) Run(ctx context.Context, flags *RootFlags) erro
231231
if outfmt.IsJSON(ctx) {
232232
return outfmt.WriteJSON(ctx, os.Stdout, updated)
233233
}
234-
u.Out().Printf("Updated org unit: %s (%s)\n", updated.Name, updated.OrgUnitPath)
234+
u.Out().Linef("Updated org unit: %s (%s)", updated.Name, updated.OrgUnitPath)
235235
return nil
236236
}
237237

internal/cmd/admin_users.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -372,9 +372,9 @@ func (c *AdminUsersCreateCmd) Run(ctx context.Context, flags *RootFlags) error {
372372
}
373373

374374
u := ui.FromContext(ctx)
375-
u.Out().Printf("Created user: %s (ID: %s)\n", created.PrimaryEmail, created.Id)
375+
u.Out().Linef("Created user: %s (ID: %s)", created.PrimaryEmail, created.Id)
376376
if generatedPassword {
377-
u.Out().Printf("Generated password: %s\n", password)
377+
u.Out().Linef("Generated password: %s", password)
378378
}
379379
return nil
380380
}
@@ -439,7 +439,7 @@ func (c *AdminUsersDeleteCmd) Run(ctx context.Context, flags *RootFlags) error {
439439
}
440440

441441
u := ui.FromContext(ctx)
442-
u.Out().Printf("Deleted user: %s\n", userEmail)
442+
u.Out().Linef("Deleted user: %s", userEmail)
443443
return nil
444444
}
445445

@@ -483,6 +483,6 @@ func (c *AdminUsersSuspendCmd) Run(ctx context.Context, flags *RootFlags) error
483483
}
484484

485485
u := ui.FromContext(ctx)
486-
u.Out().Printf("Suspended user: %s", updated.PrimaryEmail)
486+
u.Out().Linef("Suspended user: %s", updated.PrimaryEmail)
487487
return nil
488488
}

internal/cmd/appscript.go

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -53,20 +53,20 @@ func (c *AppScriptGetCmd) Run(ctx context.Context, flags *RootFlags) error {
5353
}
5454

5555
u := ui.FromContext(ctx)
56-
u.Out().Printf("script_id\t%s", project.ScriptId)
56+
u.Out().Linef("script_id\t%s", project.ScriptId)
5757
if project.Title != "" {
58-
u.Out().Printf("title\t%s", project.Title)
58+
u.Out().Linef("title\t%s", project.Title)
5959
}
6060
if project.ParentId != "" {
61-
u.Out().Printf("parent_id\t%s", project.ParentId)
61+
u.Out().Linef("parent_id\t%s", project.ParentId)
6262
}
6363
if project.CreateTime != "" {
64-
u.Out().Printf("created\t%s", project.CreateTime)
64+
u.Out().Linef("created\t%s", project.CreateTime)
6565
}
6666
if project.UpdateTime != "" {
67-
u.Out().Printf("updated\t%s", project.UpdateTime)
67+
u.Out().Linef("updated\t%s", project.UpdateTime)
6868
}
69-
u.Out().Printf("editor_url\t%s", appScriptEditURL(scriptID))
69+
u.Out().Linef("editor_url\t%s", appScriptEditURL(scriptID))
7070
return nil
7171
}
7272

@@ -100,13 +100,13 @@ func (c *AppScriptContentCmd) Run(ctx context.Context, flags *RootFlags) error {
100100
}
101101

102102
u := ui.FromContext(ctx)
103-
u.Out().Printf("script_id\t%s", content.ScriptId)
104-
u.Out().Printf("files\t%d", len(content.Files))
103+
u.Out().Linef("script_id\t%s", content.ScriptId)
104+
u.Out().Linef("files\t%d", len(content.Files))
105105
for _, file := range content.Files {
106106
if file == nil {
107107
continue
108108
}
109-
u.Out().Printf("file\t%s\t%s", file.Name, file.Type)
109+
u.Out().Linef("file\t%s\t%s", file.Name, file.Type)
110110
}
111111
return nil
112112
}
@@ -157,21 +157,21 @@ func (c *AppScriptRunCmd) Run(ctx context.Context, flags *RootFlags) error {
157157
}
158158

159159
u := ui.FromContext(ctx)
160-
u.Out().Printf("done\t%t", op.Done)
160+
u.Out().Linef("done\t%t", op.Done)
161161

162162
if op.Error != nil {
163163
if op.Error.Code != 0 {
164-
u.Out().Printf("error_code\t%d", op.Error.Code)
164+
u.Out().Linef("error_code\t%d", op.Error.Code)
165165
}
166166
if op.Error.Message != "" {
167-
u.Out().Printf("error\t%s", op.Error.Message)
167+
u.Out().Linef("error\t%s", op.Error.Message)
168168
}
169169
if detail := parseExecutionError(op.Error); detail != nil {
170170
if detail.ErrorType != "" {
171-
u.Out().Printf("error_type\t%s", detail.ErrorType)
171+
u.Out().Linef("error_type\t%s", detail.ErrorType)
172172
}
173173
if detail.ErrorMessage != "" {
174-
u.Out().Printf("error_message\t%s", detail.ErrorMessage)
174+
u.Out().Linef("error_message\t%s", detail.ErrorMessage)
175175
}
176176
}
177177
return nil
@@ -181,7 +181,7 @@ func (c *AppScriptRunCmd) Run(ctx context.Context, flags *RootFlags) error {
181181
var execResp scriptapi.ExecutionResponse
182182
if err := json.Unmarshal(op.Response, &execResp); err == nil && execResp.Result != nil {
183183
if b, marshalErr := json.Marshal(execResp.Result); marshalErr == nil {
184-
u.Out().Printf("result\t%s", string(b))
184+
u.Out().Linef("result\t%s", string(b))
185185
}
186186
}
187187
}
@@ -233,15 +233,15 @@ func (c *AppScriptCreateCmd) Run(ctx context.Context, flags *RootFlags) error {
233233
}
234234

235235
u := ui.FromContext(ctx)
236-
u.Out().Printf("created\ttrue")
237-
u.Out().Printf("script_id\t%s", project.ScriptId)
236+
u.Out().Linef("created\ttrue")
237+
u.Out().Linef("script_id\t%s", project.ScriptId)
238238
if project.Title != "" {
239-
u.Out().Printf("title\t%s", project.Title)
239+
u.Out().Linef("title\t%s", project.Title)
240240
}
241241
if project.ParentId != "" {
242-
u.Out().Printf("parent_id\t%s", project.ParentId)
242+
u.Out().Linef("parent_id\t%s", project.ParentId)
243243
}
244-
u.Out().Printf("editor_url\t%s", appScriptEditURL(project.ScriptId))
244+
u.Out().Linef("editor_url\t%s", appScriptEditURL(project.ScriptId))
245245
return nil
246246
}
247247

0 commit comments

Comments
 (0)