Skip to content

Commit eeedbf5

Browse files
committed
fix: adds killing previous command, when watcher starts new command
1 parent afcd333 commit eeedbf5

File tree

1 file changed

+179
-162
lines changed

1 file changed

+179
-162
lines changed

runner/run-task.go

Lines changed: 179 additions & 162 deletions
Original file line numberDiff line numberDiff line change
@@ -55,177 +55,193 @@ func isTTY() bool {
5555
return ((stdout.Mode() & os.ModeCharDevice) == os.ModeCharDevice) && ((stderr.Mode() & os.ModeCharDevice) == os.ModeCharDevice)
5656
}
5757

58-
func runCommand(ctx Context, prf *types.ParsedRunfile, pt *types.ParsedTask, args runTaskArgs) error {
59-
for _, command := range pt.Commands {
60-
ctx.Debug("running command task", "command.run", command.Run, "parent.task", args.taskName)
58+
func runCommand(ctx Context, prf *types.ParsedRunfile, pt *types.ParsedTask, args runTaskArgs, command types.ParsedCommandJson) error {
59+
ctx.Debug("running command task", "command.run", command.Run, "parent.task", args.taskName)
60+
var wg sync.WaitGroup
6161

62-
if command.If != nil && !*command.If {
63-
ctx.Debug("skipping execution for failed `if`", "command", command.Run)
64-
continue
62+
if command.If != nil && !*command.If {
63+
ctx.Debug("skipping execution for failed `if`", "command", command.Run)
64+
return nil
65+
}
66+
67+
if command.Run != "" {
68+
rt, ok := prf.Tasks[command.Run]
69+
if !ok {
70+
return fmt.Errorf("invalid run target")
6571
}
6672

67-
if command.Run != "" {
68-
rt, ok := prf.Tasks[command.Run]
69-
if !ok {
70-
return fmt.Errorf("invalid run target")
71-
}
73+
rtp, err := parser.ParseTask(ctx, prf, rt)
74+
if err != nil {
75+
return errors.WithErr(err).KV("env-vars", prf.Env)
76+
}
7277

73-
rtp, err := parser.ParseTask(ctx, prf, rt)
74-
if err != nil {
75-
return errors.WithErr(err).KV("env-vars", prf.Env)
76-
}
78+
if err := runTaskCommands(ctx, prf, rtp, args); err != nil {
79+
return errors.WithErr(err).KV("env-vars", prf.Env)
80+
}
81+
return nil
82+
}
7783

78-
if err := runCommand(ctx, prf, rtp, args); err != nil {
79-
return errors.WithErr(err).KV("env-vars", prf.Env)
80-
}
81-
continue
84+
// stdoutR, stdoutW := io.Pipe()
85+
// stderrR, stderrW := io.Pipe()
86+
87+
// wg := sync.WaitGroup{}
88+
89+
// [snippet source](https://rderik.com/blog/identify-if-output-goes-to-the-terminal-or-is-being-redirected-in-golang/)
90+
// stdout, _ := os.Stdout.Stat()
91+
// stderr, _ := os.Stderr.Stat()
92+
// isTTY := ((stdout.Mode() & os.ModeCharDevice) == os.ModeCharDevice) && ((stderr.Mode() & os.ModeCharDevice) == os.ModeCharDevice)
93+
//
94+
// if isTTY {
95+
// go func() {
96+
// defer wg.Done()
97+
// logPrefix := fmt.Sprintf("%s ", ctx.theme.TaskPrefixStyle.Render(fmt.Sprintf("[%s]", strings.Join(trail, "/"))))
98+
// processOutput(os.Stdout, stdoutR, &logPrefix)
99+
//
100+
// stderrPrefix := fmt.Sprintf("%s ", ctx.theme.TaskPrefixStyle.Render(fmt.Sprintf("[%s/stderr]", strings.Join(trail, "/"))))
101+
// processOutput(os.Stderr, stderrR, &stderrPrefix)
102+
// }()
103+
// } else {
104+
// wg.Add(1)
105+
// go func() {
106+
// defer wg.Done()
107+
// logPrefix := fmt.Sprintf("%s ", ctx.theme.TaskPrefixStyle.Render(fmt.Sprintf("[%s]", strings.Join(trail, "/"))))
108+
// processOutput(os.Stdout, stdoutR, &logPrefix)
109+
// // if pt.Interactive {
110+
// // processOutput(os.Stdout, stdoutR, &logPrefix)
111+
// // return
112+
// // }
113+
// // processOutputLineByLine(os.Stdout, stdoutR, &logPrefix)
114+
// }()
115+
//
116+
// wg.Add(1)
117+
// go func() {
118+
// defer wg.Done()
119+
// logPrefix := fmt.Sprintf("%s ", ctx.theme.TaskPrefixStyle.Render(fmt.Sprintf("[%s/stderr]", strings.Join(trail, "/"))))
120+
// processOutput(os.Stderr, stderrR, &logPrefix)
121+
// // if pt.Interactive {
122+
// // processOutput(os.Stderr, stderrR, &logPrefix)
123+
// // return
124+
// // }
125+
// // processOutputLineByLine(os.Stderr, stderrR, &logPrefix)
126+
// }()
127+
// }
128+
129+
if isTTY() {
130+
borderColor := "#4388cc"
131+
if !isDarkTheme() {
132+
borderColor = "#3d5485"
82133
}
134+
s := lipgloss.NewStyle().BorderForeground(lipgloss.Color(borderColor)).PaddingLeft(1).PaddingRight(1).Border(lipgloss.RoundedBorder(), true, true, true, true)
135+
// labelStyle := lipgloss.NewStyle().Foreground(lipgloss.Color(borderColor)).Blink(true)
83136

84-
// stdoutR, stdoutW := io.Pipe()
85-
// stderrR, stderrW := io.Pipe()
86-
87-
// wg := sync.WaitGroup{}
88-
89-
// [snippet source](https://rderik.com/blog/identify-if-output-goes-to-the-terminal-or-is-being-redirected-in-golang/)
90-
// stdout, _ := os.Stdout.Stat()
91-
// stderr, _ := os.Stderr.Stat()
92-
// isTTY := ((stdout.Mode() & os.ModeCharDevice) == os.ModeCharDevice) && ((stderr.Mode() & os.ModeCharDevice) == os.ModeCharDevice)
93-
//
94-
// if isTTY {
95-
// go func() {
96-
// defer wg.Done()
97-
// logPrefix := fmt.Sprintf("%s ", ctx.theme.TaskPrefixStyle.Render(fmt.Sprintf("[%s]", strings.Join(trail, "/"))))
98-
// processOutput(os.Stdout, stdoutR, &logPrefix)
99-
//
100-
// stderrPrefix := fmt.Sprintf("%s ", ctx.theme.TaskPrefixStyle.Render(fmt.Sprintf("[%s/stderr]", strings.Join(trail, "/"))))
101-
// processOutput(os.Stderr, stderrR, &stderrPrefix)
102-
// }()
103-
// } else {
104-
// wg.Add(1)
105-
// go func() {
106-
// defer wg.Done()
107-
// logPrefix := fmt.Sprintf("%s ", ctx.theme.TaskPrefixStyle.Render(fmt.Sprintf("[%s]", strings.Join(trail, "/"))))
108-
// processOutput(os.Stdout, stdoutR, &logPrefix)
109-
// // if pt.Interactive {
110-
// // processOutput(os.Stdout, stdoutR, &logPrefix)
111-
// // return
112-
// // }
113-
// // processOutputLineByLine(os.Stdout, stdoutR, &logPrefix)
114-
// }()
115-
//
116-
// wg.Add(1)
117-
// go func() {
118-
// defer wg.Done()
119-
// logPrefix := fmt.Sprintf("%s ", ctx.theme.TaskPrefixStyle.Render(fmt.Sprintf("[%s/stderr]", strings.Join(trail, "/"))))
120-
// processOutput(os.Stderr, stderrR, &logPrefix)
121-
// // if pt.Interactive {
122-
// // processOutput(os.Stderr, stderrR, &logPrefix)
123-
// // return
124-
// // }
125-
// // processOutputLineByLine(os.Stderr, stderrR, &logPrefix)
126-
// }()
127-
// }
128-
129-
if isTTY() {
130-
borderColor := "#4388cc"
131-
if !isDarkTheme() {
132-
borderColor = "#3d5485"
133-
}
134-
s := lipgloss.NewStyle().BorderForeground(lipgloss.Color(borderColor)).PaddingLeft(1).PaddingRight(1).Border(lipgloss.RoundedBorder(), true, true, true, true)
135-
// labelStyle := lipgloss.NewStyle().Foreground(lipgloss.Color(borderColor)).Blink(true)
137+
if args.DebugEnv {
138+
fmt.Printf("%s\n", s.Render(padString(fmt.Sprintf("%+v", prf.Env), "DEBUG: env")))
139+
}
136140

137-
if args.DebugEnv {
138-
fmt.Printf("%s\n", s.Render(padString(fmt.Sprintf("%+v", prf.Env), "DEBUG: env")))
139-
}
141+
hlCode := new(bytes.Buffer)
142+
// choose colorschemes from `https://swapoff.org/chroma/playground/`
143+
colorscheme := "catppuccin-macchiato"
144+
if !isDarkTheme() {
145+
colorscheme = "monokailight"
146+
}
147+
// quick.Highlight(hlCode, strings.TrimSpace(command.Command), "bash", "terminal16m", colorscheme)
140148

141-
hlCode := new(bytes.Buffer)
142-
// choose colorschemes from `https://swapoff.org/chroma/playground/`
143-
colorscheme := "catppuccin-macchiato"
144-
if !isDarkTheme() {
145-
colorscheme = "monokailight"
146-
}
147-
// quick.Highlight(hlCode, strings.TrimSpace(command.Command), "bash", "terminal16m", colorscheme)
149+
cmdStr := strings.TrimSpace(command.Command)
148150

149-
cmdStr := strings.TrimSpace(command.Command)
151+
quick.Highlight(hlCode, cmdStr, "bash", "terminal16m", colorscheme)
152+
// cst := styles.Get("gruvbox")
153+
// fmt.Println("cst: ", cst.Name, styles.Fallback.Name, styles.Names())
150154

151-
quick.Highlight(hlCode, cmdStr, "bash", "terminal16m", colorscheme)
152-
// cst := styles.Get("gruvbox")
153-
// fmt.Println("cst: ", cst.Name, styles.Fallback.Name, styles.Names())
155+
// fmt.Printf("%s\n", s.Render(args.taskName+" | "+hlCode.String()))
156+
fmt.Printf("%s\n", s.Render(padString(hlCode.String(), args.taskName)))
157+
}
154158

155-
// fmt.Printf("%s\n", s.Render(args.taskName+" | "+hlCode.String()))
156-
fmt.Printf("%s\n", s.Render(padString(hlCode.String(), args.taskName)))
157-
}
159+
logger2 := logging.New(logging.Options{
160+
Prefix: "[runfile]",
161+
Writer: os.Stderr,
162+
SlogKeyAsPrefix: "task",
163+
})
164+
165+
ex := executor.NewExecutor(executor.ExecutorArgs{
166+
Logger: logger2,
167+
IsInteractive: pt.Interactive,
168+
Command: func(c context.Context) *exec.Cmd {
169+
return CreateCommand(c, CmdArgs{
170+
Shell: pt.Shell,
171+
Env: fn.ToEnviron(pt.Env),
172+
Cmd: command.Command,
173+
WorkingDir: pt.WorkingDir,
174+
interactive: pt.Interactive,
175+
Stdout: os.Stdout,
176+
Stderr: os.Stderr,
177+
})
178+
},
179+
})
158180

159-
logger2 := logging.New(logging.Options{
160-
Prefix: "[runfile]",
161-
Writer: os.Stderr,
162-
SlogKeyAsPrefix: "task",
163-
})
181+
wg.Add(1)
182+
go func() {
183+
defer wg.Done()
184+
<-ctx.Done()
185+
ex.Kill()
186+
}()
164187

165-
ex := executor.NewExecutor(executor.ExecutorArgs{
166-
Logger: logger2,
167-
IsInteractive: pt.Interactive,
168-
Command: func(c context.Context) *exec.Cmd {
169-
return CreateCommand(c, CmdArgs{
170-
Shell: pt.Shell,
171-
Env: fn.ToEnviron(pt.Env),
172-
Cmd: command.Command,
173-
WorkingDir: pt.WorkingDir,
174-
interactive: pt.Interactive,
175-
Stdout: os.Stdout,
176-
Stderr: os.Stderr,
177-
})
178-
},
179-
})
188+
// if task.Watch != nil && (task.Watch.Enable == nil || *task.Watch.Enable) {
189+
// watch, err := watcher.NewWatcher(ctx, watcher.WatcherArgs{
190+
// Logger: logger,
191+
// WatchDirs: append(task.Watch.Dirs, pt.WorkingDir),
192+
// OnlySuffixes: pt.Watch.OnlySuffixes,
193+
// IgnoreSuffixes: pt.Watch.IgnoreSuffixes,
194+
// ExcludeDirs: pt.Watch.ExcludeDirs,
195+
// UseDefaultIgnoreList: true,
196+
// // CooldownDuration: fn.New(1 * time.Second),
197+
// })
198+
// if err != nil {
199+
// return errors.WithErr(err)
200+
// }
201+
//
202+
// go ex.Exec()
203+
//
204+
// go func() {
205+
// <-ctx.Done()
206+
// logger.Debug("fwatcher is closing ...")
207+
// watch.Close()
208+
// <-time.After(200 * time.Millisecond)
209+
// logger.Info("CLOSING..................")
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+
// select {
221+
// case <-time.After(100 * time.Millisecond):
222+
// go ex.Exec()
223+
// return nil
224+
// case <-ctx.Done():
225+
// logger.Info("close signal received")
226+
// watch.Close()
227+
// return nil
228+
// }
229+
// })
230+
//
231+
// return nil
232+
// }
233+
234+
if err := ex.Exec(); err != nil {
235+
return errors.ErrTaskFailed.Wrap(err).KV("task", args.taskName)
236+
}
180237

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)
238+
return nil
239+
}
240+
241+
func runTaskCommands(ctx Context, prf *types.ParsedRunfile, pt *types.ParsedTask, args runTaskArgs) error {
242+
for _, command := range pt.Commands {
243+
if err := runCommand(ctx, prf, pt, args, command); err != nil {
244+
return err
229245
}
230246
}
231247

@@ -265,7 +281,7 @@ func runTask(ctx Context, prf *types.ParsedRunfile, args runTaskArgs) error {
265281
wg.Add(1)
266282
go func() {
267283
defer wg.Done()
268-
runCommand(NewContext(nctx, ctx.Logger), prf, pt, args)
284+
runTaskCommands(NewContext(nctx, ctx.Logger), prf, pt, args)
269285
}()
270286

271287
if pt.Watch != nil && (pt.Watch.Enable == nil || *pt.Watch.Enable) {
@@ -276,7 +292,7 @@ func runTask(ctx Context, prf *types.ParsedRunfile, args runTaskArgs) error {
276292
IgnoreSuffixes: pt.Watch.IgnoreSuffixes,
277293
ExcludeDirs: pt.Watch.ExcludeDirs,
278294
UseDefaultIgnoreList: true,
279-
// CooldownDuration: fn.New(1 * time.Second),
295+
CooldownDuration: fn.New(1 * time.Second),
280296
})
281297
if err != nil {
282298
return errors.WithErr(err)
@@ -286,9 +302,6 @@ func runTask(ctx Context, prf *types.ParsedRunfile, args runTaskArgs) error {
286302
<-ctx.Done()
287303
logger.Debug("fwatcher is closing ...")
288304
watch.Close()
289-
<-time.After(200 * time.Millisecond)
290-
logger.Info("CLOSING..................")
291-
os.Exit(0)
292305
}()
293306

294307
watch.WatchEvents(func(event watcher.Event, fp string) error {
@@ -302,7 +315,11 @@ func runTask(ctx Context, prf *types.ParsedRunfile, args runTaskArgs) error {
302315
cf()
303316

304317
nctx, cf = context.WithCancel(ctx)
305-
go runCommand(NewContext(nctx, ctx.Logger), prf, pt, args)
318+
wg.Add(1)
319+
go func() {
320+
defer wg.Done()
321+
runTaskCommands(NewContext(nctx, ctx.Logger), prf, pt, args)
322+
}()
306323

307324
return nil
308325
case <-ctx.Done():

0 commit comments

Comments
 (0)