Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

passes stdin from CompileDaemon to the built command #62

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 45 additions & 3 deletions daemon.go
Original file line number Diff line number Diff line change
Expand Up @@ -232,14 +232,19 @@ func logger(pipeChan <-chan io.ReadCloser) {
}

// Start the supplied command and return stdout and stderr pipes for logging.
func startCommand(command string) (cmd *exec.Cmd, stdout io.ReadCloser, stderr io.ReadCloser, err error) {
func startCommand(command string) (cmd *exec.Cmd, stdin io.WriteCloser, stdout io.ReadCloser, stderr io.ReadCloser, err error) {
args := strings.Split(command, " ")
cmd = exec.Command(args[0], args[1:]...)

if *flagRunDir != "" {
cmd.Dir = *flagRunDir
}

if stdin, err = cmd.StdinPipe(); err != nil {
err = fmt.Errorf("can't get stdin pipe for command: %s", err)
return
}

if stdout, err = cmd.StdoutPipe(); err != nil {
err = fmt.Errorf("can't get stdout pipe for command: %s", err)
return
Expand All @@ -263,7 +268,6 @@ func startCommand(command string) (cmd *exec.Cmd, stdout io.ReadCloser, stderr i
func runner(commandTemplate string, buildStarted <-chan string, buildSuccess <-chan bool) {
var currentProcess *os.Process
pipeChan := make(chan io.ReadCloser)

go logger(pipeChan)

// Launch concurrent process watching for signals from outside that
Expand All @@ -281,9 +285,32 @@ func runner(commandTemplate string, buildStarted <-chan string, buildSuccess <-c
os.Exit(0)
}()



// These 2 channels are used for passing stdin to the launched command
restarted := make(chan struct{}) // signal for to writer goroutine to end
msg := make(chan string) // contains the lines read from stdin

// read lines from stdin and write the result to msg, allowing the input
// to be passed to the currently active command
go func() {
reader := bufio.NewReader(os.Stdin)
for {
s, err := reader.ReadString('\n')
if err == nil {
msg <- s
}
}
}()

for {
eventPath := <-buildStarted

// close + recreate this channel to ensure the goroutine writing
// to commands stdin is closed when it is restarted
close(restarted)
restarted = make(chan struct{})

// prepend %0.s (which adds nothing) to prevent warning about missing
// format specifier if the user did not supply one.
command := fmt.Sprintf("%0.s"+commandTemplate, eventPath)
Expand All @@ -306,12 +333,27 @@ func runner(commandTemplate string, buildStarted <-chan string, buildSuccess <-c
}

log.Println(okColor("Restarting the given command."))
cmd, stdoutPipe, stderrPipe, err := startCommand(command)
cmd, stdinPipe, stdoutPipe, stderrPipe, err := startCommand(command)
defer stdinPipe.Close()

if err != nil {
log.Fatal(failColor("Could not start command: %s", err))
}

// This goroutine will write the contents of the msg channel to
// the stdin of the currently launched command
go func() {
for {
select {
case input := <-msg:
io.WriteString(stdinPipe, input)
case <-restarted:
return
}
}
}()


pipeChan <- stdoutPipe
pipeChan <- stderrPipe

Expand Down