Skip to content

Commit

Permalink
Optimizations for Windows (#74)
Browse files Browse the repository at this point in the history
* Bring myke go run with regular Windows environment on Windows systems
* Add environment variable expansion in the way golang does (very close to sh) that it behaves on every operating system and/or distribution in the same way to be more "cross platform"
* Added appveyor config to also enable tests to run on an Windows
environment.

* * Fixed problem with case insensitve PATH variable under Windows is doubled set - and with a chance of 50% wrong.
* Improved the output .. if a different Shell is used do not output "+ whatever" if a command starts.
  • Loading branch information
blaubaer authored and rdsubhas committed Apr 20, 2017
1 parent 70b9f7a commit b9f7bcf
Show file tree
Hide file tree
Showing 11 changed files with 109 additions and 16 deletions.
25 changes: 25 additions & 0 deletions appveyor.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
version: "{build}"

os: Windows Server 2012 R2

clone_folder: c:\gopath\src\github.com\goeuro\myke

environment:
GOPATH: C:\gopath

# Uncomment following line if you are willing to debug on the build machine.
#init:
#- ps: iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))

install:
- set PATH=%GOPATH%\bin;C:\go\bin;%WINDIR%;%WINDIR%\System32;C:\Program Files\Git\cmd;C:\Program Files\Git\usr\bin
- go version
- go env
- sh c:\gopath\src\github.com\goeuro\myke\bin\init.sh

build_script:
- gofmt -d -s -e . 2>&1 | tee -a fmt.out
- test ! -s fmt.out
- golint -set_exit_status .
- go test -timeout 10s -v ./...

19 changes: 8 additions & 11 deletions core/execution.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,20 +89,26 @@ func (e *Execution) executeCmd(cmd string) error {
return nil
}

env := e.env()
cmd, err := RenderTemplate(cmd, e.Project.Env, e.Query.Params)
if err != nil {
return err
}
cmd = os.Expand(cmd, func(key string) string {
return env[key]
})

shell := []string{"sh", "-exc"}
e.beforeExecuteCmd(cmd, env)

shell := executionShell()
if len(e.Task.Shell) > 0 {
shell = strings.Split(strings.TrimSpace(e.Task.Shell), " ")
}
shell = append(shell, cmd)

proc := exec.Command(shell[0], shell[1:]...)
proc.Dir = e.Project.Cwd
proc.Env = e.envList()
proc.Env = mapToSlice(env)
proc.Stdin = os.Stdin
proc.Stdout = os.Stdout
proc.Stderr = os.Stderr
Expand All @@ -121,12 +127,3 @@ func (e *Execution) env() map[string]string {
env["PATH"] = strings.Join([]string{env["PATH"], os.Getenv("PATH")}, pathSep)
return env
}

func (e *Execution) envList() []string {
env := e.env()
list := make([]string, len(env))
for k, v := range env {
list = append(list, k+"="+v)
}
return list
}
11 changes: 11 additions & 0 deletions core/execution_default.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// +build !windows

package core

func executionShell() []string {
return []string{"sh", "-exc"}
}

func (e *Execution) beforeExecuteCmd(cmd string, env map[string]string) error {
return nil
}
41 changes: 41 additions & 0 deletions core/execution_windows.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// +build windows

package core

import (
"os"
"os/exec"
"path/filepath"
)

var comSpec string

func init() {
comSpec = os.Getenv("ComSpec")
if len(comSpec) > 0 {
return
}
winDir := os.Getenv("windir")
if len(winDir) > 0 {
comSpec = filepath.Join(winDir, "system32", "cmd.exe")
}
comSpec = "C:\\windows\\system32\\cmd.exe"
return
}

func executionShell() []string {
return []string{comSpec, "/C"}
}

func (e *Execution) beforeExecuteCmd(cmd string, env map[string]string) error {
if len(e.Task.Shell) > 0 {
return nil
}
// This will cause the same output like the sh -x on unix like systems.
proc := exec.Command(comSpec, "/C", "echo", "+", cmd)
proc.Dir = e.Project.Cwd
proc.Env = mapToSlice(env)
proc.Stdout = os.Stdout
proc.Stderr = os.Stderr
return proc.Run()
}
13 changes: 12 additions & 1 deletion core/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ func OsEnv() map[string]string {
env := make(map[string]string)
for _, e := range os.Environ() {
pair := strings.SplitN(e, "=", 2)
if pair[0] != "PATH" {
// ToUpper is important here because on Windows this is case insensitive
if strings.ToUpper(pair[0]) != "PATH" {
// PATH is handled as a special case, so lets skip it
env[pair[0]] = pair[1]
}
Expand Down Expand Up @@ -104,3 +105,13 @@ func retry(f func(attempt int) (retry bool, err error)) error {
attempt++
}
}

func mapToSlice(in map[string]string) []string {
list := make([]string, len(in))
i := 0
for k, v := range in {
list[i] = k + "=" + v
i++
}
return list
}
2 changes: 1 addition & 1 deletion examples/env/package_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ var tests = []TestTable{
{Arg: `file_default_local`, Out: `envvar from myke.env.local is value_from_myke.env.local`},
{Arg: `file_custom`, Out: `envvar from test.env is value_from_test.env`},
{Arg: `file_custom_local`, Out: `envvar from test.env.local is value_from_test.env.local`},
{Arg: `path`, Out: `PATH is [^:]+env/path_from_myke.env.local:[^:]+env/path_from_myke.env:[^:]+env/path_from_test.env.local:[^:]+env/path_from_test.env:[^:]+env/path_from_yml:[^:]+env/bin`},
{Arg: `path`, Out: `PATH is [^$PLS$]+env$PS$path_from_myke.env.local$PLS$[^$PLS$]+env$PS$path_from_myke.env$PLS$[^$PLS$]+env$PS$path_from_test.env.local$PLS$[^$PLS$]+env$PS$path_from_test.env$PLS$[^$PLS$]+env$PS$path_from_yml$PLS$[^$PLS$]+env$PS$bin`},
}

func Test(t *testing.T) {
Expand Down
2 changes: 1 addition & 1 deletion examples/mixin/package_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ var tests = []TestTable{
{Arg: `task1`, Out: `parent says value_parent_1`},
{Arg: `task2`, Out: `(?s)parent says value_child_2.*?child says value_child_2`},
{Arg: `task3`, Out: `child says value_child_3`},
{Arg: `path`, Out: `PATH is [^:]+mixin/path_child:[^:]+mixin/bin:[^:]+mixin/parent/path_parent:[^:]+mixin/parent/bin`},
{Arg: `path`, Out: `PATH is [^$PLS$]+mixin$PS$path_child$PLS$[^$PLS$]+mixin$PS$bin$PLS$[^$PLS$]+mixin$PS$parent$PS$path_parent$PLS$[^$PLS$]+mixin$PS$parent$PS$bin`},
}

func Test(t *testing.T) {
Expand Down
2 changes: 1 addition & 1 deletion examples/package_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ var tests = []TestTable{
{Arg: ``, Out: `(?m)^\s*retry\s*\|\s*\|\s*retry\s*$`},
{Arg: ``, Out: `(?m)^\s*tags1\s*\|\s*tagA, tagB\s*\|\s*tag\s*$`},
{Arg: ``, Out: `(?m)^\s*tags2\s*\|\s*tagB, tagC\s*\|\s*tag\s*$`},
{Arg: ``, Out: `(?m)^\s*template\s*\|\s*\|\s*args, file\s*$`},
{Arg: ``, Out: `(?m)^\s*template\s*\|\s*\|\s*args, envs, file\s*$`},
}

func Test(t *testing.T) {
Expand Down
3 changes: 3 additions & 0 deletions examples/template/myke.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ tasks:
args:
cmd: echo from={{.from|required}} to={{.to|default "something_to"}}
desc: run as myke template/args[from=...,to=...]
envs:
cmd: echo PARAM1={{.PARAM2|required}} PARAM2={{.PARAM2|required}}
desc: run as myke template/envs
file:
cmd: myke --template template.tpl
desc: run as myke template/file
1 change: 1 addition & 0 deletions examples/template/package_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ var tests = []TestTable{
{Arg: `args --from=a`, Out: `from=a to=something_to`},
{Arg: `args --from=a --to=b`, Out: `from=a to=b`},
{Arg: `args --from=a args --from=b`, Out: `(?s).*from=a to=something_to.*from=b to=something_to`},
{Arg: `envs`, Out: `(?s).*PARAM1=value2 PARAM2=value2`},
// Cannot invoke myke subcommand in a test
// {Arg:`file`, Out:`(?s)I am a template.*PARAM1=value1.*PARAM2=value2`},
}
Expand Down
6 changes: 5 additions & 1 deletion examples/util/test_util.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ package util

import (
"bytes"
"fmt"
"github.com/goeuro/myke/cmd"
"github.com/stretchr/testify/assert"
"io"
Expand Down Expand Up @@ -36,7 +37,10 @@ func runTest(t *testing.T, tt TestTable) {
return cmd.Exec(args)
})

if tt.Err == (err != nil) && assert.Regexp(t, tt.Out, actual) {
expectedOut := strings.Replace(tt.Out, "$PS$", fmt.Sprintf("\\%c", os.PathSeparator), -1)
expectedOut = strings.Replace(expectedOut, "$PLS$", fmt.Sprintf("\\%c", os.PathListSeparator), -1)

if tt.Err == (err != nil) && assert.Regexp(t, expectedOut, actual) {
t.Logf("myke(%s): passed", tt.Arg)
} else {
t.Errorf("myke(%s): failed %s", tt.Arg, err)
Expand Down

0 comments on commit b9f7bcf

Please sign in to comment.