Skip to content

Commit

Permalink
fix: add use_stdin option for just reading from stdin
Browse files Browse the repository at this point in the history
  • Loading branch information
mrexox committed Sep 12, 2023
1 parent 3ddec2e commit 14a1d77
Show file tree
Hide file tree
Showing 6 changed files with 54 additions and 24 deletions.
1 change: 1 addition & 0 deletions internal/config/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ type Command struct {

FailText string `mapstructure:"fail_text" yaml:"fail_text,omitempty" json:"fail_text,omitempty" toml:"fail_text,omitempty"`
Interactive bool `mapstructure:"interactive" yaml:",omitempty" json:"interactive,omitempty" toml:"interactive,omitempty"`
UseStdin bool `mapstructure:"use_stdin" yaml:",omitempty" json:"use_stdin,omitempty" toml:"use_stdin,omitempty"`
StageFixed bool `mapstructure:"stage_fixed" yaml:"stage_fixed,omitempty" json:"stage_fixed,omitempty" toml:"stage_fixed,omitempty"`
}

Expand Down
1 change: 1 addition & 0 deletions internal/config/script.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ type Script struct {

FailText string `mapstructure:"fail_text" yaml:"fail_text,omitempty" json:"fail_text,omitempty" toml:"fail_text,omitempty"`
Interactive bool `mapstructure:"interactive" yaml:",omitempty" json:"interactive,omitempty" toml:"interactive,omitempty"`
UseStdin bool `mapstructure:"use_stdin" yaml:",omitempty" json:"use_stdin,omitempty" toml:"use_stdin,omitempty"`
StageFixed bool `mapstructure:"stage_fixed" yaml:"stage_fixed,omitempty" json:"stage_fixed,omitempty" toml:"stage_fixed,omitempty"`
}

Expand Down
35 changes: 26 additions & 9 deletions internal/lefthook/run/exec/execute_unix.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,14 @@ import (

type CommandExecutor struct{}

type executeArgs struct {
in io.Reader
out io.Writer
envs []string
root string
interactive, useStdin bool
}

func (e CommandExecutor) Execute(opts Options, out io.Writer) error {
in := os.Stdin
if opts.Interactive && !isatty.IsTerminal(os.Stdin.Fd()) {
Expand All @@ -40,10 +48,19 @@ func (e CommandExecutor) Execute(opts Options, out io.Writer) error {
)
}

args := &executeArgs{
in: in,
out: out,
envs: envs,
root: root,
interactive: opts.Interactive,
useStdin: opts.UseStdin,
}

// We can have one command split into separate to fit into shell command max length.
// In this case we execute those commands one by one.
for _, command := range opts.Commands {
if err := e.executeOne(command, root, envs, opts.Interactive, in, out); err != nil {
if err := e.execute(command, args); err != nil {
return err
}
}
Expand All @@ -60,14 +77,14 @@ func (e CommandExecutor) RawExecute(command []string, out io.Writer) error {
return cmd.Run()
}

func (e CommandExecutor) executeOne(cmdstr string, root string, envs []string, interactive bool, in io.Reader, out io.Writer) error {
func (e CommandExecutor) execute(cmdstr string, args *executeArgs) error {
command := exec.Command("sh", "-c", cmdstr)
command.Dir = root
command.Env = append(os.Environ(), envs...)
command.Dir = args.root
command.Env = append(os.Environ(), args.envs...)

if interactive {
command.Stdout = out
command.Stdin = in
if args.interactive || args.useStdin {
command.Stdout = args.out
command.Stdin = args.in
command.Stderr = os.Stderr
err := command.Start()
if err != nil {
Expand All @@ -81,9 +98,9 @@ func (e CommandExecutor) executeOne(cmdstr string, root string, envs []string, i

defer func() { _ = p.Close() }()

go func() { _, _ = io.Copy(p, in) }()
go func() { _, _ = io.Copy(p, args.in) }()

_, _ = io.Copy(out, p)
_, _ = io.Copy(args.out, p)
}

defer func() { _ = command.Process.Kill() }()
Expand Down
31 changes: 20 additions & 11 deletions internal/lefthook/run/exec/execute_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@ import (
)

type CommandExecutor struct{}
type executeArgs struct {
in io.Reader
out io.Writer
envs []string
root string
}

func (e CommandExecutor) Execute(opts Options, out io.Writer) error {
root, _ := filepath.Abs(opts.Root)
Expand All @@ -22,8 +28,16 @@ func (e CommandExecutor) Execute(opts Options, out io.Writer) error {
)
}

args:

Check failure on line 31 in internal/lefthook/run/exec/execute_windows.go

View workflow job for this annotation

GitHub Actions / build

label args defined and not used

Check failure on line 31 in internal/lefthook/run/exec/execute_windows.go

View workflow job for this annotation

GitHub Actions / test (1.21.x, windows-latest)

label args defined and not used
&executeArgs{

Check failure on line 32 in internal/lefthook/run/exec/execute_windows.go

View workflow job for this annotation

GitHub Actions / build

&executeArgs{…} (value of type *executeArgs) is not used

Check failure on line 32 in internal/lefthook/run/exec/execute_windows.go

View workflow job for this annotation

GitHub Actions / test (1.21.x, windows-latest)

&executeArgs{…} (value of type *executeArgs) is not used
in: os.Stdin,
out: out,
envs: envs,
root: root,
}

for _, command := range opts.Commands {
if err := e.executeOne(command, root, envs, opts.Interactive, os.Stdin, out); err != nil {
if err := e.execute(command, args); err != nil {

Check failure on line 40 in internal/lefthook/run/exec/execute_windows.go

View workflow job for this annotation

GitHub Actions / build

undefined: args

Check failure on line 40 in internal/lefthook/run/exec/execute_windows.go

View workflow job for this annotation

GitHub Actions / test (1.21.x, windows-latest)

undefined: args
return err
}
}
Expand All @@ -40,22 +54,17 @@ func (e CommandExecutor) RawExecute(command []string, out io.Writer) error {
return cmd.Run()
}

func (e CommandExecutor) executeOne(cmdstr string, root string, envs []string, interactive bool, in io.Reader, out io.Writer) error {
func (e CommandExecutor) execute(cmdstr string, args *executeArgs) error {
cmdargs := strings.Split(cmdstr, " ")
command := exec.Command(cmdargs[0])
command.SysProcAttr = &syscall.SysProcAttr{
CmdLine: strings.Join(cmdargs, " "),
}
command.Dir = root
command.Env = append(os.Environ(), envs...)

if interactive {
command.Stdout = os.Stdout
} else {
command.Stdout = out
}
command.Dir = args.root
command.Env = append(os.Environ(), args.envs...)

command.Stdin = in
command.Stdout = args.out
command.Stdin = args.in
command.Stderr = os.Stderr
err := command.Start()
if err != nil {
Expand Down
8 changes: 4 additions & 4 deletions internal/lefthook/run/exec/executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ import (

// Options contains the data that controls the execution.
type Options struct {
Name, Root, FailText string
Commands []string
Env map[string]string
Interactive bool
Name, Root, FailText string
Commands []string
Env map[string]string
Interactive, UseStdin bool
}

// Executor provides an interface for command execution.
Expand Down
2 changes: 2 additions & 0 deletions internal/lefthook/run/runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,7 @@ func (r *Runner) runScript(script *config.Script, path string, file os.FileInfo)
Commands: []string{command},
FailText: script.FailText,
Interactive: script.Interactive && !r.DisableTTY,
UseStdin: script.UseStdin,
Env: script.Env,
}, r.Hook.Follow)

Expand Down Expand Up @@ -374,6 +375,7 @@ func (r *Runner) runCommand(name string, command *config.Command) {
Commands: run.commands,
FailText: command.FailText,
Interactive: command.Interactive && !r.DisableTTY,
UseStdin: command.UseStdin,
Env: command.Env,
}, r.Hook.Follow)

Expand Down

0 comments on commit 14a1d77

Please sign in to comment.