Skip to content

Commit cb15abc

Browse files
author
Bruce Hill
committed
Merge duplicate code for file watching
1 parent 4b01a71 commit cb15abc

File tree

3 files changed

+86
-135
lines changed

3 files changed

+86
-135
lines changed

pkg/cmd/configwatcher.go

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
package cmd
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"os"
7+
"time"
8+
9+
"github.com/urfave/cli/v3"
10+
)
11+
12+
type configChangedEvent struct{}
13+
14+
func waitTillConfigChanges(ctx context.Context, cmd *cli.Command, cc *apiCommandContext) error {
15+
openapiSpecPath := cc.workspaceConfig.OpenAPISpec
16+
if cmd.IsSet("openapi-spec") {
17+
openapiSpecPath = cmd.String("openapi-spec")
18+
}
19+
stainlessConfigPath := cc.workspaceConfig.StainlessConfig
20+
if cmd.IsSet("stainless-config") {
21+
stainlessConfigPath = cmd.String("stainless-config")
22+
}
23+
24+
// Get initial file modification times
25+
openapiSpecInfo, err := os.Stat(openapiSpecPath)
26+
if err != nil {
27+
return fmt.Errorf("failed to get file info for %s: %v", openapiSpecPath, err)
28+
}
29+
openapiSpecModTime := openapiSpecInfo.ModTime()
30+
31+
stainlessConfigInfo, err := os.Stat(stainlessConfigPath)
32+
if err != nil {
33+
return fmt.Errorf("failed to get file info for %s: %v", stainlessConfigPath, err)
34+
}
35+
stainlessConfigModTime := stainlessConfigInfo.ModTime()
36+
37+
// Poll for file changes every 250ms
38+
ticker := time.NewTicker(250 * time.Millisecond)
39+
defer ticker.Stop()
40+
41+
for {
42+
select {
43+
case <-ticker.C:
44+
// Check OpenAPI spec file
45+
if info, err := os.Stat(openapiSpecPath); err == nil {
46+
if info.ModTime().After(openapiSpecModTime) {
47+
return nil
48+
}
49+
}
50+
51+
// Check Stainless config file
52+
if info, err := os.Stat(stainlessConfigPath); err == nil {
53+
if info.ModTime().After(stainlessConfigModTime) {
54+
return nil
55+
}
56+
}
57+
58+
case <-ctx.Done():
59+
return ctx.Err()
60+
}
61+
}
62+
}

pkg/cmd/dev.go

Lines changed: 0 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -402,58 +402,6 @@ func runPreview(ctx context.Context, cmd *cli.Command) error {
402402
return nil
403403
}
404404

405-
func waitTillConfigChanges(ctx context.Context, cmd *cli.Command, cc *apiCommandContext) error {
406-
openapiSpecPath := cc.workspaceConfig.OpenAPISpec
407-
if cmd.IsSet("openapi-spec") {
408-
openapiSpecPath = cmd.String("openapi-spec")
409-
}
410-
stainlessConfigPath := cc.workspaceConfig.StainlessConfig
411-
if cmd.IsSet("stainless-config") {
412-
stainlessConfigPath = cmd.String("stainless-config")
413-
}
414-
415-
// Get initial file modification times
416-
openapiSpecInfo, err := os.Stat(openapiSpecPath)
417-
if err != nil {
418-
return fmt.Errorf("failed to get file info for %s: %v", openapiSpecPath, err)
419-
}
420-
openapiSpecModTime := openapiSpecInfo.ModTime()
421-
422-
stainlessConfigInfo, err := os.Stat(stainlessConfigPath)
423-
if err != nil {
424-
return fmt.Errorf("failed to get file info for %s: %v", stainlessConfigPath, err)
425-
}
426-
stainlessConfigModTime := stainlessConfigInfo.ModTime()
427-
428-
fmt.Println("Waiting for file changes...")
429-
430-
// Poll for file changes every 250ms
431-
ticker := time.NewTicker(250 * time.Millisecond)
432-
defer ticker.Stop()
433-
434-
for {
435-
select {
436-
case <-ticker.C:
437-
// Check OpenAPI spec file
438-
if info, err := os.Stat(openapiSpecPath); err == nil {
439-
if info.ModTime().After(openapiSpecModTime) {
440-
return nil
441-
}
442-
}
443-
444-
// Check Stainless config file
445-
if info, err := os.Stat(stainlessConfigPath); err == nil {
446-
if info.ModTime().After(stainlessConfigModTime) {
447-
return nil
448-
}
449-
}
450-
451-
case <-ctx.Done():
452-
return ctx.Err()
453-
}
454-
}
455-
}
456-
457405
func runDevBuild(ctx context.Context, cc *apiCommandContext, cmd *cli.Command, branch string, languages []stainless.Target) error {
458406
// Handle file flags by reading files and mutating JSON body
459407
if err := applyFileFlag(cmd, "openapi-spec", "revision.openapi\\.yml.content"); err != nil {

pkg/cmd/lint.go

Lines changed: 24 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package cmd
33
import (
44
"context"
55
"fmt"
6+
"log"
67
"os"
78
"time"
89

@@ -46,51 +47,22 @@ var helpStyle = lipgloss.NewStyle().
4647
Margin(1, 0, 0, 0)
4748

4849
type lintModel struct {
49-
spinner spinner.Model
50-
diagnostics []stainless.BuildDiagnostic
51-
error error
52-
watching bool
53-
watchedFiles map[string]time.Time
54-
ctx context.Context
55-
cmd *cli.Command
56-
cc *apiCommandContext
57-
stopPolling chan struct{}
58-
help helpModel
50+
spinner spinner.Model
51+
diagnostics []stainless.BuildDiagnostic
52+
error error
53+
watching bool
54+
ctx context.Context
55+
cmd *cli.Command
56+
cc *apiCommandContext
57+
stopPolling chan struct{}
58+
help helpModel
5959
}
6060

6161
type helpModel struct {
6262
width int
6363
height int
6464
}
6565

66-
type fileChangedEvent struct{}
67-
68-
func waitForFileChanges(m lintModel) tea.Cmd {
69-
return func() tea.Msg {
70-
ticker := time.NewTicker(250 * time.Millisecond)
71-
defer ticker.Stop()
72-
73-
for {
74-
select {
75-
case <-ticker.C:
76-
for file, lastModTime := range m.watchedFiles {
77-
stat, err := os.Stat(file)
78-
if err != nil {
79-
continue
80-
}
81-
82-
if stat.ModTime().After(lastModTime) {
83-
m.watchedFiles[file] = stat.ModTime()
84-
return fileChangedEvent{}
85-
}
86-
}
87-
case <-m.stopPolling:
88-
return nil
89-
}
90-
}
91-
}
92-
}
93-
9466
func (m lintModel) Init() tea.Cmd {
9567
if m.watching {
9668
// Clear the screen and move the cursor to the top
@@ -116,11 +88,16 @@ func (m lintModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
11688
m.cc = msg.cc
11789

11890
if m.watching {
119-
return m, waitForFileChanges(m)
91+
return m, func() tea.Msg {
92+
if err := waitTillConfigChanges(m.ctx, m.cmd, m.cc); err != nil {
93+
log.Fatal(err)
94+
}
95+
return configChangedEvent{}
96+
}
12097
}
12198
return m, tea.Quit
12299

123-
case fileChangedEvent:
100+
case configChangedEvent:
124101
m.diagnostics = nil // Clear diagnostics while linting
125102
return m, getDiagnosticsCmd(m.ctx, m.cmd, m.cc)
126103

@@ -186,20 +163,13 @@ func runLinter(ctx context.Context, cmd *cli.Command) error {
186163
s.Style = lipgloss.NewStyle().Foreground(lipgloss.Color("208"))
187164

188165
m := lintModel{
189-
spinner: s,
190-
watching: cmd.Bool("watch"),
191-
ctx: ctx,
192-
cmd: cmd,
193-
cc: cc,
194-
watchedFiles: make(map[string]time.Time),
195-
stopPolling: make(chan struct{}),
196-
help: helpModel{},
197-
}
198-
199-
if m.watching {
200-
if err := setupFileWatcher(&m, cmd, cc); err != nil {
201-
return err
202-
}
166+
spinner: s,
167+
watching: cmd.Bool("watch"),
168+
ctx: ctx,
169+
cmd: cmd,
170+
cc: cc,
171+
stopPolling: make(chan struct{}),
172+
help: helpModel{},
203173
}
204174

205175
p := tea.NewProgram(m, tea.WithContext(ctx))
@@ -231,32 +201,3 @@ func runLinter(ctx context.Context, cmd *cli.Command) error {
231201

232202
return nil
233203
}
234-
235-
func setupFileWatcher(m *lintModel, cmd *cli.Command, cc *apiCommandContext) error {
236-
// Watch OpenAPI spec file
237-
openapiSpecPath := cc.workspaceConfig.OpenAPISpec
238-
if cmd.IsSet("openapi-spec") {
239-
openapiSpecPath = cmd.String("openapi-spec")
240-
}
241-
242-
if err := addFileToWatch(m, openapiSpecPath); err != nil {
243-
return err
244-
}
245-
246-
// Watch Stainless config file
247-
stainlessConfigPath := cc.workspaceConfig.StainlessConfig
248-
if cmd.IsSet("stainless-config") {
249-
stainlessConfigPath = cmd.String("stainless-config")
250-
}
251-
252-
return addFileToWatch(m, stainlessConfigPath)
253-
}
254-
255-
func addFileToWatch(m *lintModel, path string) error {
256-
stat, err := os.Stat(path)
257-
if err != nil {
258-
return fmt.Errorf("failed to get file info for %s: %v", path, err)
259-
}
260-
m.watchedFiles[path] = stat.ModTime()
261-
return nil
262-
}

0 commit comments

Comments
 (0)