Browse Source

allow using special characters in external commands (#1652) (#1868)

on Windows, when using cmd.exe or a bat file as external command.
pull/1869/head
Alessandro Ros 3 years ago committed by GitHub
parent
commit
a0b973963d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 18
      internal/externalcmd/cmd.go
  2. 6
      internal/externalcmd/cmd_unix.go
  3. 28
      internal/externalcmd/cmd_win.go

18
internal/externalcmd/cmd.go

@ -33,6 +33,8 @@ func NewCmd(
env Environment, env Environment,
onExit func(int), onExit func(int),
) *Cmd { ) *Cmd {
// replace variables in both Linux and Windows, in order to allow using the
// same commands on both of them.
for key, val := range env { for key, val := range env {
cmdstr = strings.ReplaceAll(cmdstr, "$"+key, val) cmdstr = strings.ReplaceAll(cmdstr, "$"+key, val)
} }
@ -62,8 +64,15 @@ func (e *Cmd) run() {
defer e.pool.wg.Done() defer e.pool.wg.Done()
for { for {
ok := func() bool { ok := e.runInner()
c, ok := e.runInner() if !ok {
break
}
}
}
func (e *Cmd) runInner() bool {
c, ok := e.runOSSpecific()
if !ok { if !ok {
return false return false
} }
@ -81,9 +90,4 @@ func (e *Cmd) run() {
case <-e.terminate: case <-e.terminate:
return false return false
} }
}()
if !ok {
break
}
}
} }

6
internal/externalcmd/cmd_unix.go

@ -11,13 +11,13 @@ import (
"github.com/kballard/go-shellquote" "github.com/kballard/go-shellquote"
) )
func (e *Cmd) runInner() (int, bool) { func (e *Cmd) runOSSpecific() (int, bool) {
cmdparts, err := shellquote.Split(e.cmdstr) cmdParts, err := shellquote.Split(e.cmdstr)
if err != nil { if err != nil {
return 0, true return 0, true
} }
cmd := exec.Command(cmdparts[0], cmdparts[1:]...) cmd := exec.Command(cmdParts[0], cmdParts[1:]...)
cmd.Env = append([]string(nil), os.Environ()...) cmd.Env = append([]string(nil), os.Environ()...)
for key, val := range e.env { for key, val := range e.env {

28
internal/externalcmd/cmd_win.go

@ -6,17 +6,37 @@ package externalcmd
import ( import (
"os" "os"
"os/exec" "os/exec"
"strings"
"syscall"
"github.com/kballard/go-shellquote" "github.com/kballard/go-shellquote"
) )
func (e *Cmd) runInner() (int, bool) { func (e *Cmd) runOSSpecific() (int, bool) {
cmdparts, err := shellquote.Split(e.cmdstr) var cmd *exec.Cmd
// from Golang documentation:
// On Windows, processes receive the whole command line as a single string and do their own parsing.
// Command combines and quotes Args into a command line string with an algorithm compatible with
// applications using CommandLineToArgvW (which is the most common way). Notable exceptions are
// msiexec.exe and cmd.exe (and thus, all batch files), which have a different unquoting algorithm.
// In these or other similar cases, you can do the quoting yourself and provide the full command
// line in SysProcAttr.CmdLine, leaving Args empty.
if strings.HasPrefix(e.cmdstr, "cmd ") || strings.HasPrefix(e.cmdstr, "cmd.exe ") {
args := strings.TrimPrefix(strings.TrimPrefix(e.cmdstr, "cmd "), "cmd.exe ")
cmd = exec.Command("cmd.exe")
cmd.SysProcAttr = &syscall.SysProcAttr{
CmdLine: args,
}
} else {
cmdParts, err := shellquote.Split(e.cmdstr)
if err != nil { if err != nil {
return 0, true return 0, true
} }
cmd := exec.Command(cmdparts[0], cmdparts[1:]...) cmd = exec.Command(cmdParts[0], cmdParts[1:]...)
}
cmd.Env = append([]string(nil), os.Environ()...) cmd.Env = append([]string(nil), os.Environ()...)
for key, val := range e.env { for key, val := range e.env {
@ -26,7 +46,7 @@ func (e *Cmd) runInner() (int, bool) {
cmd.Stdout = os.Stdout cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr cmd.Stderr = os.Stderr
err = cmd.Start() err := cmd.Start()
if err != nil { if err != nil {
return 0, true return 0, true
} }

Loading…
Cancel
Save