Skip to content

Commit afcd333

Browse files
committed
fix: fixes watch behaviour, now watches all the commands in a task
instead of, just the last command
1 parent 4cee317 commit afcd333

File tree

6 files changed

+162
-97
lines changed

6 files changed

+162
-97
lines changed

go.mod

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ require (
77
github.com/charmbracelet/lipgloss v1.0.0
88
github.com/joho/godotenv v1.5.1
99
github.com/muesli/termenv v0.15.2
10-
github.com/nxtcoder17/fwatcher v1.0.3
10+
github.com/nxtcoder17/fwatcher v1.0.4-0.20241218102704-76d04c526fb0
1111
github.com/phuslu/log v1.0.112
1212
github.com/urfave/cli/v3 v3.0.0-beta1
1313
golang.org/x/sync v0.10.0
@@ -16,20 +16,13 @@ require (
1616

1717
require (
1818
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
19-
github.com/charmbracelet/log v0.4.0 // indirect
2019
github.com/charmbracelet/x/ansi v0.6.0 // indirect
21-
github.com/cpuguy83/go-md2man/v2 v2.0.5 // indirect
2220
github.com/dlclark/regexp2 v1.11.4 // indirect
2321
github.com/fsnotify/fsnotify v1.8.0 // indirect
24-
github.com/go-logfmt/logfmt v0.6.0 // indirect
2522
github.com/google/go-cmp v0.6.0 // indirect
2623
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
2724
github.com/mattn/go-isatty v0.0.20 // indirect
2825
github.com/mattn/go-runewidth v0.0.16 // indirect
2926
github.com/rivo/uniseg v0.4.7 // indirect
30-
github.com/russross/blackfriday/v2 v2.1.0 // indirect
31-
github.com/urfave/cli/v2 v2.27.5 // indirect
32-
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect
33-
golang.org/x/exp v0.0.0-20241210194714-1829a127f884 // indirect
3427
golang.org/x/sys v0.28.0 // indirect
3528
)

go.sum

Lines changed: 2 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,14 @@ github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiE
88
github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8=
99
github.com/charmbracelet/lipgloss v1.0.0 h1:O7VkGDvqEdGi93X+DeqsQ7PKHDgtQfF8j8/O2qFMQNg=
1010
github.com/charmbracelet/lipgloss v1.0.0/go.mod h1:U5fy9Z+C38obMs+T+tJqst9VGzlOYGj4ri9reL3qUlo=
11-
github.com/charmbracelet/log v0.4.0 h1:G9bQAcx8rWA2T3pWvx7YtPTPwgqpk7D68BX21IRW8ZM=
12-
github.com/charmbracelet/log v0.4.0/go.mod h1:63bXt/djrizTec0l11H20t8FDSvA4CRZJ1KH22MdptM=
1311
github.com/charmbracelet/x/ansi v0.6.0 h1:qOznutrb93gx9oMiGf7caF7bqqubh6YIM0SWKyA08pA=
1412
github.com/charmbracelet/x/ansi v0.6.0/go.mod h1:KBUFw1la39nl0dLl10l5ORDAqGXaeurTQmwyyVKse/Q=
15-
github.com/cpuguy83/go-md2man/v2 v2.0.5 h1:ZtcqGrnekaHpVLArFSe4HK5DoKx1T0rq2DwVB0alcyc=
16-
github.com/cpuguy83/go-md2man/v2 v2.0.5/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
1713
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
1814
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
1915
github.com/dlclark/regexp2 v1.11.4 h1:rPYF9/LECdNymJufQKmri9gV604RvvABwgOA8un7yAo=
2016
github.com/dlclark/regexp2 v1.11.4/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
2117
github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M=
2218
github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
23-
github.com/go-logfmt/logfmt v0.6.0 h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi4=
24-
github.com/go-logfmt/logfmt v0.6.0/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
2519
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
2620
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
2721
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
@@ -37,29 +31,19 @@ github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6T
3731
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
3832
github.com/muesli/termenv v0.15.2 h1:GohcuySI0QmI3wN8Ok9PtKGkgkFIk7y6Vpb5PvrY+Wo=
3933
github.com/muesli/termenv v0.15.2/go.mod h1:Epx+iuz8sNs7mNKhxzH4fWXGNpZwUaJKRS1noLXviQ8=
40-
github.com/nxtcoder17/fwatcher v1.0.3-0.20241212071621-beb84ec5b061 h1:bNRVjvghGLiCJ9EOTS/qkrSAyKvz4e2S6CMzL8GnxgI=
41-
github.com/nxtcoder17/fwatcher v1.0.3-0.20241212071621-beb84ec5b061/go.mod h1:MNmSwXYOrqp7U1pUxh0GWB5skpjFTWTQXhAA0+sPJcU=
42-
github.com/nxtcoder17/fwatcher v1.0.3 h1:6oCdh9uMzSSeJLyA6iezc/8WBIZPbD9lx50nxC7cMyQ=
43-
github.com/nxtcoder17/fwatcher v1.0.3/go.mod h1:MNmSwXYOrqp7U1pUxh0GWB5skpjFTWTQXhAA0+sPJcU=
34+
github.com/nxtcoder17/fwatcher v1.0.4-0.20241218102704-76d04c526fb0 h1:k09TYswdqCsFz0fBnO3AjGT5MHfvjPRyBtHbBWuiJLM=
35+
github.com/nxtcoder17/fwatcher v1.0.4-0.20241218102704-76d04c526fb0/go.mod h1:MNmSwXYOrqp7U1pUxh0GWB5skpjFTWTQXhAA0+sPJcU=
4436
github.com/phuslu/log v1.0.112 h1:vQ0ZFd5O+in/0IQAcjuEl6wRkHiQPw7T0sqwmOjpL0U=
4537
github.com/phuslu/log v1.0.112/go.mod h1:F8osGJADo5qLK/0F88djWwdyoZZ9xDJQL1HYRHFEkS0=
4638
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
4739
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
4840
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
4941
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
5042
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
51-
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
52-
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
5343
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
5444
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
55-
github.com/urfave/cli/v2 v2.27.5 h1:WoHEJLdsXr6dDWoJgMq/CboDmyY/8HMMH1fTECbih+w=
56-
github.com/urfave/cli/v2 v2.27.5/go.mod h1:3Sevf16NykTbInEnD0yKkjDAeZDS0A6bzhBH5hrMvTQ=
5745
github.com/urfave/cli/v3 v3.0.0-beta1 h1:6DTaaUarcM0wX7qj5Hcvs+5Dm3dyUTBbEwIWAjcw9Zg=
5846
github.com/urfave/cli/v3 v3.0.0-beta1/go.mod h1:FnIeEMYu+ko8zP1F9Ypr3xkZMIDqW3DR92yUtY39q1Y=
59-
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGCjxCBTO/36wtF6j2nSip77qHd4x4=
60-
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM=
61-
golang.org/x/exp v0.0.0-20241210194714-1829a127f884 h1:Y/Mj/94zIQQGHVSv1tTtQBDaQaJe62U9bkDZKKyhPCU=
62-
golang.org/x/exp v0.0.0-20241210194714-1829a127f884/go.mod h1:qj5a5QZpwLU2NLQudwIN5koi3beDhSAlJwa67PuM98c=
6347
golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
6448
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
6549
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=

parser/parse-task.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,5 +94,6 @@ func ParseTask(ctx context.Context, prf *types.ParsedRunfile, task types.Task) (
9494
Interactive: task.Interactive,
9595
Env: taskEnv,
9696
Commands: commands,
97+
Watch: task.Watch,
9798
}, nil
9899
}

runner/run-task.go

Lines changed: 155 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"os/exec"
99
"path/filepath"
1010
"strings"
11+
"sync"
1112
"time"
1213

1314
"github.com/alecthomas/chroma/v2/quick"
@@ -17,6 +18,7 @@ import (
1718
"github.com/nxtcoder17/fwatcher/pkg/watcher"
1819
"github.com/nxtcoder17/runfile/errors"
1920
fn "github.com/nxtcoder17/runfile/functions"
21+
"github.com/nxtcoder17/runfile/logging"
2022
"github.com/nxtcoder17/runfile/parser"
2123
"github.com/nxtcoder17/runfile/types"
2224
)
@@ -53,45 +55,27 @@ func isTTY() bool {
5355
return ((stdout.Mode() & os.ModeCharDevice) == os.ModeCharDevice) && ((stderr.Mode() & os.ModeCharDevice) == os.ModeCharDevice)
5456
}
5557

56-
func runTask(ctx Context, prf *types.ParsedRunfile, args runTaskArgs) error {
57-
runfilePath := prf.Metadata.RunfilePath
58-
task := prf.Tasks[args.taskName]
59-
60-
if task.Metadata.RunfilePath != nil {
61-
runfilePath = *task.Metadata.RunfilePath
62-
}
63-
64-
trail := append(args.taskTrail, args.taskName)
65-
66-
logger := ctx.With("task", args.taskName, "runfile", runfilePath)
67-
logger.Debug("running task")
68-
69-
task, ok := prf.Tasks[args.taskName]
70-
if !ok {
71-
return errors.ErrTaskNotFound
72-
}
73-
74-
task.Name = args.taskName
75-
76-
pt, err := parser.ParseTask(ctx, prf, task)
77-
if err != nil {
78-
return errors.WithErr(err)
79-
}
80-
58+
func runCommand(ctx Context, prf *types.ParsedRunfile, pt *types.ParsedTask, args runTaskArgs) error {
8159
for _, command := range pt.Commands {
82-
logger.Debug("running command task", "command.run", command.Run, "parent.task", args.taskName)
60+
ctx.Debug("running command task", "command.run", command.Run, "parent.task", args.taskName)
8361

8462
if command.If != nil && !*command.If {
85-
logger.Debug("skipping execution for failed `if`", "command", command.Run)
63+
ctx.Debug("skipping execution for failed `if`", "command", command.Run)
8664
continue
8765
}
8866

8967
if command.Run != "" {
90-
if err := runTask(ctx, prf, runTaskArgs{
91-
taskTrail: trail,
92-
taskName: command.Run,
93-
envOverrides: pt.Env,
94-
}); err != nil {
68+
rt, ok := prf.Tasks[command.Run]
69+
if !ok {
70+
return fmt.Errorf("invalid run target")
71+
}
72+
73+
rtp, err := parser.ParseTask(ctx, prf, rt)
74+
if err != nil {
75+
return errors.WithErr(err).KV("env-vars", prf.Env)
76+
}
77+
78+
if err := runCommand(ctx, prf, rtp, args); err != nil {
9579
return errors.WithErr(err).KV("env-vars", prf.Env)
9680
}
9781
continue
@@ -172,8 +156,14 @@ func runTask(ctx Context, prf *types.ParsedRunfile, args runTaskArgs) error {
172156
fmt.Printf("%s\n", s.Render(padString(hlCode.String(), args.taskName)))
173157
}
174158

159+
logger2 := logging.New(logging.Options{
160+
Prefix: "[runfile]",
161+
Writer: os.Stderr,
162+
SlogKeyAsPrefix: "task",
163+
})
164+
175165
ex := executor.NewExecutor(executor.ExecutorArgs{
176-
Logger: logger,
166+
Logger: logger2,
177167
IsInteractive: pt.Interactive,
178168
Command: func(c context.Context) *exec.Cmd {
179169
return CreateCommand(c, CmdArgs{
@@ -188,47 +178,144 @@ func runTask(ctx Context, prf *types.ParsedRunfile, args runTaskArgs) error {
188178
},
189179
})
190180

191-
if task.Watch.Enable {
192-
watch, err := watcher.NewWatcher(ctx, watcher.WatcherArgs{
193-
Logger: logger,
194-
WatchDirs: append(task.Watch.Dirs, pt.WorkingDir),
195-
OnlySuffixes: pt.Watch.OnlySuffixes,
196-
IgnoreSuffixes: pt.Watch.IgnoreSuffixes,
197-
ExcludeDirs: pt.Watch.ExcludeDirs,
198-
UseDefaultIgnoreList: true,
199-
})
181+
// if task.Watch != nil && (task.Watch.Enable == nil || *task.Watch.Enable) {
182+
// watch, err := watcher.NewWatcher(ctx, watcher.WatcherArgs{
183+
// Logger: logger,
184+
// WatchDirs: append(task.Watch.Dirs, pt.WorkingDir),
185+
// OnlySuffixes: pt.Watch.OnlySuffixes,
186+
// IgnoreSuffixes: pt.Watch.IgnoreSuffixes,
187+
// ExcludeDirs: pt.Watch.ExcludeDirs,
188+
// UseDefaultIgnoreList: true,
189+
// // CooldownDuration: fn.New(1 * time.Second),
190+
// })
191+
// if err != nil {
192+
// return errors.WithErr(err)
193+
// }
194+
//
195+
// go ex.Exec()
196+
//
197+
// go func() {
198+
// <-ctx.Done()
199+
// logger.Debug("fwatcher is closing ...")
200+
// watch.Close()
201+
// <-time.After(200 * time.Millisecond)
202+
// logger.Info("CLOSING..................")
203+
// os.Exit(0)
204+
// }()
205+
//
206+
// watch.WatchEvents(func(event watcher.Event, fp string) error {
207+
// relPath, err := filepath.Rel(fn.Must(os.Getwd()), fp)
208+
// if err != nil {
209+
// return err
210+
// }
211+
// logger.Info(fmt.Sprintf("[RELOADING] due changes in %s", relPath))
212+
// ex.Kill()
213+
// select {
214+
// case <-time.After(100 * time.Millisecond):
215+
// go ex.Exec()
216+
// return nil
217+
// case <-ctx.Done():
218+
// logger.Info("close signal received")
219+
// watch.Close()
220+
// return nil
221+
// }
222+
// })
223+
//
224+
// return nil
225+
// }
226+
227+
if err := ex.Exec(); err != nil {
228+
return errors.ErrTaskFailed.Wrap(err).KV("task", args.taskName)
229+
}
230+
}
231+
232+
return nil
233+
}
234+
235+
func runTask(ctx Context, prf *types.ParsedRunfile, args runTaskArgs) error {
236+
runfilePath := prf.Metadata.RunfilePath
237+
task := prf.Tasks[args.taskName]
238+
239+
if task.Metadata.RunfilePath != nil {
240+
runfilePath = *task.Metadata.RunfilePath
241+
}
242+
243+
args.taskTrail = append(args.taskTrail, args.taskName)
244+
245+
logger := ctx.With("task", args.taskName, "runfile", runfilePath)
246+
logger.Debug("running task")
247+
248+
task, ok := prf.Tasks[args.taskName]
249+
if !ok {
250+
return errors.ErrTaskNotFound
251+
}
252+
253+
task.Name = args.taskName
254+
255+
pt, err := parser.ParseTask(ctx, prf, task)
256+
if err != nil {
257+
return errors.WithErr(err)
258+
}
259+
260+
nctx, cf := context.WithCancel(ctx)
261+
defer cf()
262+
263+
var wg sync.WaitGroup
264+
265+
wg.Add(1)
266+
go func() {
267+
defer wg.Done()
268+
runCommand(NewContext(nctx, ctx.Logger), prf, pt, args)
269+
}()
270+
271+
if pt.Watch != nil && (pt.Watch.Enable == nil || *pt.Watch.Enable) {
272+
watch, err := watcher.NewWatcher(ctx, watcher.WatcherArgs{
273+
Logger: logger,
274+
WatchDirs: append(task.Watch.Dirs, pt.WorkingDir),
275+
OnlySuffixes: pt.Watch.OnlySuffixes,
276+
IgnoreSuffixes: pt.Watch.IgnoreSuffixes,
277+
ExcludeDirs: pt.Watch.ExcludeDirs,
278+
UseDefaultIgnoreList: true,
279+
// CooldownDuration: fn.New(1 * time.Second),
280+
})
281+
if err != nil {
282+
return errors.WithErr(err)
283+
}
284+
285+
go func() {
286+
<-ctx.Done()
287+
logger.Debug("fwatcher is closing ...")
288+
watch.Close()
289+
<-time.After(200 * time.Millisecond)
290+
logger.Info("CLOSING..................")
291+
os.Exit(0)
292+
}()
293+
294+
watch.WatchEvents(func(event watcher.Event, fp string) error {
295+
relPath, err := filepath.Rel(fn.Must(os.Getwd()), fp)
200296
if err != nil {
201-
return errors.WithErr(err)
297+
return err
202298
}
299+
logger.Info(fmt.Sprintf("[RELOADING] due changes in %s", relPath))
300+
select {
301+
case <-time.After(100 * time.Millisecond):
302+
cf()
203303

204-
go ex.Exec()
205-
206-
go func() {
207-
<-ctx.Done()
208-
logger.Info("fwatcher is closing ...")
209-
<-time.After(200 * time.Millisecond)
210-
os.Exit(0)
211-
}()
212-
213-
watch.WatchEvents(func(event watcher.Event, fp string) error {
214-
relPath, err := filepath.Rel(fn.Must(os.Getwd()), fp)
215-
if err != nil {
216-
return err
217-
}
218-
logger.Info(fmt.Sprintf("[RELOADING] due changes in %s", relPath))
219-
ex.Kill()
220-
<-time.After(100 * time.Millisecond)
221-
go ex.Exec()
222-
return nil
223-
})
304+
nctx, cf = context.WithCancel(ctx)
305+
go runCommand(NewContext(nctx, ctx.Logger), prf, pt, args)
224306

225-
return nil
226-
}
307+
return nil
308+
case <-ctx.Done():
309+
logger.Info("close signal received")
310+
watch.Close()
311+
return nil
312+
}
313+
})
227314

228-
if err := ex.Exec(); err != nil {
229-
return errors.ErrTaskFailed.Wrap(err).KV("task", args.taskName)
230-
}
315+
return nil
231316
}
232317

318+
wg.Wait()
319+
233320
return nil
234321
}

types/parsed-types.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ type ParsedRunfile struct {
1212
type ParsedTask struct {
1313
Shell []string `json:"shell"`
1414
WorkingDir string `json:"workingDir"`
15-
Watch TaskWatch `json:"watch"`
15+
Watch *TaskWatch `json:"watch,omitempty"`
1616
Env map[string]string `json:"environ"`
1717
Interactive bool `json:"interactive,omitempty"`
1818
Commands []ParsedCommandJson `json:"commands"`

types/types.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ type TaskMetadata struct {
3636
}
3737

3838
type TaskWatch struct {
39-
Enable bool `json:"enable"`
39+
Enable *bool `json:"enable,omitempty"`
4040
Dirs []string `json:"dirs"`
4141
OnlySuffixes []string `json:"onlySuffixes"`
4242
IgnoreSuffixes []string `json:"ignoreSuffixes"`
@@ -66,7 +66,7 @@ type Task struct {
6666

6767
Env EnvVar `json:"env,omitempty"`
6868

69-
Watch TaskWatch `json:"watch"`
69+
Watch *TaskWatch `json:"watch"`
7070

7171
Requires []*Requires `json:"requires,omitempty"`
7272

0 commit comments

Comments
 (0)