Skip to content

Commit 5ac18a4

Browse files
authored
Fix update ExcludeRegex to empty not work (#308)
* Fix update ExcludeRegex to empty not work #304
1 parent 39482e0 commit 5ac18a4

File tree

4 files changed

+186
-5
lines changed

4 files changed

+186
-5
lines changed

.github/workflows/build.yml

+2
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ jobs:
2222
go-version: ^1.17
2323
- name: build
2424
run: make build
25+
- name: install dependency
26+
run: if [ $(uname) == "Darwin" ]; then brew install gnu-sed ;fi
2527
- name: run Unit tests.
2628
run: go install github.com/go-delve/delve/cmd/dlv@latest && go test ./... -v -covermode=count -coverprofile=coverage.txt
2729
- name: upload Coverage report to CodeCov

runner/config.go

+28-3
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,21 @@ type cfgScreen struct {
8787
ClearOnRebuild bool `toml:"clear_on_rebuild"`
8888
}
8989

90+
type sliceTransformer struct {
91+
}
92+
93+
func (t sliceTransformer) Transformer(typ reflect.Type) func(dst, src reflect.Value) error {
94+
if typ.Kind() == reflect.Slice {
95+
return func(dst, src reflect.Value) error {
96+
if !src.IsZero() {
97+
dst.Set(src)
98+
}
99+
return nil
100+
}
101+
}
102+
return nil
103+
}
104+
90105
// InitConfig initializes the configuration.
91106
func InitConfig(path string) (cfg *Config, err error) {
92107
if path == "" {
@@ -100,12 +115,22 @@ func InitConfig(path string) (cfg *Config, err error) {
100115
return nil, err
101116
}
102117
}
103-
err = mergo.Merge(cfg, defaultConfig())
118+
config := defaultConfig()
119+
// get addr
120+
ret := &config
121+
err = mergo.Merge(ret, cfg, func(config *mergo.Config) {
122+
// mergo.Merge will overwrite the fields if it is Empty
123+
// So need use this to avoid that none-zero slice will be overwritten.
124+
// https://github.com/imdario/mergo#transformers
125+
config.Transformers = sliceTransformer{}
126+
config.Overwrite = true
127+
})
104128
if err != nil {
105129
return nil, err
106130
}
107-
err = cfg.preprocess()
108-
return cfg, err
131+
132+
err = ret.preprocess()
133+
return ret, err
109134
}
110135

111136
func writeDefaultConfig() {

runner/config_test.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ func TestDefaultPathConfig(t *testing.T) {
9393
for _, tt := range tests {
9494
tt := tt
9595
t.Run(tt.name, func(t *testing.T) {
96-
_ = os.Setenv(airWd, tt.path)
96+
t.Setenv(airWd, tt.path)
9797
c, err := defaultPathConfig()
9898
if err != nil {
9999
t.Fatalf("Should not be fail: %s.", err)
@@ -115,7 +115,7 @@ func TestReadConfByName(t *testing.T) {
115115
}
116116

117117
func TestConfPreprocess(t *testing.T) {
118-
_ = os.Setenv(airWd, "_testdata/toml")
118+
t.Setenv(airWd, "_testdata/toml")
119119
df := defaultConfig()
120120
err := df.preprocess()
121121
if err != nil {

runner/engine_test.go

+154
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,12 @@ package runner
33
import (
44
"errors"
55
"fmt"
6+
"io/ioutil"
67
"net"
78
"os"
9+
"os/exec"
810
"os/signal"
11+
"runtime"
912
"strings"
1013
"syscall"
1114
"testing"
@@ -640,3 +643,154 @@ func TestWriteDefaultConfig(t *testing.T) {
640643

641644
assert.Equal(t, expect, *actual)
642645
}
646+
647+
func TestCheckNilSliceShouldBeenOverwrite(t *testing.T) {
648+
port, f := GetPort()
649+
f()
650+
t.Logf("port: %d", port)
651+
652+
tmpDir := initTestEnv(t, port)
653+
654+
// change dir to tmpDir
655+
if err := os.Chdir(tmpDir); err != nil {
656+
t.Fatal(err)
657+
}
658+
659+
// write easy config file
660+
661+
config := `
662+
[build]
663+
cmd = "go build ."
664+
bin = "tmp/main"
665+
exclude_regex = []
666+
exclude_dir = ["test"]
667+
exclude_file = ["main.go"]
668+
669+
`
670+
if err := ioutil.WriteFile(dftTOML, []byte(config), 0644); err != nil {
671+
t.Fatal(err)
672+
}
673+
engine, err := NewEngine(".air.toml", true)
674+
if err != nil {
675+
t.Fatal(err)
676+
}
677+
assert.Equal(t, []string{"go", "tpl", "tmpl", "html"}, engine.config.Build.IncludeExt)
678+
assert.Equal(t, []string{}, engine.config.Build.ExcludeRegex)
679+
assert.Equal(t, []string{"test"}, engine.config.Build.ExcludeDir)
680+
// add new config
681+
assert.Equal(t, []string{"main.go"}, engine.config.Build.ExcludeFile)
682+
assert.Equal(t, "go build .", engine.config.Build.Cmd)
683+
684+
}
685+
686+
func TestShouldIncludeGoTestFile(t *testing.T) {
687+
port, f := GetPort()
688+
f()
689+
t.Logf("port: %d", port)
690+
691+
tmpDir := initTestEnv(t, port)
692+
// change dir to tmpDir
693+
if err := os.Chdir(tmpDir); err != nil {
694+
t.Fatal(err)
695+
}
696+
writeDefaultConfig()
697+
698+
// write go test file
699+
file, err := os.Create("main_test.go")
700+
if err != nil {
701+
t.Fatal(err)
702+
}
703+
_, err = file.WriteString(`package main
704+
705+
import "testing"
706+
707+
func Test(t *testing.T) {
708+
t.Log("testing")
709+
}
710+
`)
711+
// run sed
712+
// check the file is exist
713+
if _, err := os.Stat(dftTOML); err != nil {
714+
t.Fatal(err)
715+
}
716+
// check is MacOS
717+
var cmd *exec.Cmd
718+
if runtime.GOOS == "darwin" {
719+
cmd = exec.Command("gsed", "-i", "s/\"_test.*go\"//g", ".air.toml")
720+
} else {
721+
cmd = exec.Command("sed", "-i", "s/\"_test.*go\"//g", ".air.toml")
722+
}
723+
cmd.Stdout = os.Stdout
724+
cmd.Stderr = os.Stderr
725+
if err := cmd.Run(); err != nil {
726+
t.Fatal(err)
727+
}
728+
729+
time.Sleep(time.Second * 3)
730+
engine, err := NewEngine(".air.toml", false)
731+
if err != nil {
732+
t.Fatal(err)
733+
}
734+
go func() {
735+
engine.Run()
736+
}()
737+
738+
t.Logf("start change main_test.go")
739+
// change file of main_test.go
740+
// just append a new empty line to main_test.go
741+
if err = waitingPortReady(t, port, time.Second*40); err != nil {
742+
t.Fatal(err)
743+
}
744+
go func() {
745+
file, err := os.OpenFile("main_test.go", os.O_APPEND|os.O_WRONLY, 0644)
746+
if err != nil {
747+
t.Fatalf("Should not be fail: %s.", err)
748+
}
749+
defer file.Close()
750+
_, err = file.WriteString("\n")
751+
if err != nil {
752+
t.Fatalf("Should not be fail: %s.", err)
753+
}
754+
}()
755+
// should Have rebuild
756+
if err = waitingPortConnectionRefused(t, port, time.Second*10); err != nil {
757+
t.Fatal(err)
758+
}
759+
}
760+
761+
func TestCreateNewDir(t *testing.T) {
762+
// generate a random port
763+
port, f := GetPort()
764+
f()
765+
t.Logf("port: %d", port)
766+
767+
tmpDir := initTestEnv(t, port)
768+
// change dir to tmpDir
769+
err := os.Chdir(tmpDir)
770+
if err != nil {
771+
t.Fatalf("Should not be fail: %s.", err)
772+
}
773+
engine, err := NewEngine("", true)
774+
if err != nil {
775+
t.Fatalf("Should not be fail: %s.", err)
776+
}
777+
778+
go func() {
779+
engine.Run()
780+
}()
781+
time.Sleep(time.Second * 2)
782+
assert.True(t, checkPortHaveBeenUsed(port))
783+
784+
// create a new dir make dir
785+
if err = os.Mkdir(tmpDir+"/dir", 0644); err != nil {
786+
t.Fatal(err)
787+
}
788+
789+
// no need reload
790+
if err = waitingPortConnectionRefused(t, port, 3*time.Second); err == nil {
791+
t.Fatal("should raise a error")
792+
}
793+
engine.Stop()
794+
time.Sleep(2 * time.Second)
795+
796+
}

0 commit comments

Comments
 (0)