Skip to content

Commit

Permalink
Merge pull request #5 from sevenval/feature/strict-mode
Browse files Browse the repository at this point in the history
Feature/strict mode
  • Loading branch information
malud authored Sep 29, 2017
2 parents 224b1ce + 8749eee commit ad872eb
Show file tree
Hide file tree
Showing 41 changed files with 8,152 additions and 34 deletions.
15 changes: 15 additions & 0 deletions Gopkg.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

26 changes: 26 additions & 0 deletions Gopkg.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@

# Gopkg.toml example
#
# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md
# for detailed Gopkg.toml documentation.
#
# required = ["github.com/user/thing/cmd/thing"]
# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"]
#
# [[constraint]]
# name = "github.com/user/project"
# version = "1.0.0"
#
# [[constraint]]
# name = "github.com/user/project2"
# branch = "dev"
# source = "github.com/myfork/project2"
#
# [[override]]
# name = "github.com/x/y"
# version = "2.4.0"


[[constraint]]
name = "github.com/google/go-cmp"
version = "0.1.0"
9 changes: 6 additions & 3 deletions cli/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (

var envVars = make(temgo.EnvVars)
var inlineFlag = flag.String("i", "", "-i filename")
var strictFlag = flag.Bool("s", false, "-s")

func init() {
for _, e := range os.Environ() {
Expand Down Expand Up @@ -49,8 +50,10 @@ func replace(rw *bufio.ReadWriter, file *os.File) {
must(rw.Flush())
}

if temgo.ContainsVariable(bytes) {
str := envVars.ReplaceVariables(bytes)
tg := temgo.New(envVars, *strictFlag)
if tg.ContainsVariable(bytes) {
str, err := tg.ReplaceVariables(bytes)
must(err)
if file != nil {
truncate(file)
}
Expand All @@ -63,7 +66,7 @@ func replace(rw *bufio.ReadWriter, file *os.File) {
// fatal
func must(err error) {
if err != nil {
println("Err:", err.Error())
println("Error:", err.Error())
os.Exit(1)
}
}
Expand Down
6 changes: 4 additions & 2 deletions cli/cli_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import (
"fmt"
"os"
"testing"

"github.com/google/go-cmp/cmp"
)

func TestReplace(t *testing.T) {
Expand All @@ -26,8 +28,8 @@ func TestReplace(t *testing.T) {
rw := bufio.NewReadWriter(bufio.NewReader(r), bufio.NewWriter(w))
replace(rw, nil)
out := w.Bytes()
if string(out) != testCase.expected {
t.Errorf("\nWant: \t%q\nGot: \t%q", string(testCase.expected), string(out))
if diff := cmp.Diff(string(out), testCase.expected); diff != "" {
t.Errorf("Failed for case: '%v'.\nResult differs:\n%s", string(testCase.in), diff)
}
}
}
53 changes: 39 additions & 14 deletions temgo/temgo.go
Original file line number Diff line number Diff line change
@@ -1,34 +1,59 @@
package temgo

import (
"errors"
"regexp"
"strings"
)

type EnvVars map[string]string

// following the posix standards
var templatePattern = regexp.MustCompile(`\{{2} ([a-zA-Z_]+[a-zA-Z_0-9]*) }{2}`)
type Temgo struct {
envVars EnvVars
pattern *regexp.Regexp
strict bool
}

func New(envs EnvVars, strict bool) *Temgo {
return &Temgo{
envVars: envs,
// following the posix standards
pattern: regexp.MustCompile(`{{2} ([a-zA-Z_]+[a-zA-Z_0-9]*) }{2}`),
strict: strict,
}
}

func ContainsVariable(str []byte) bool {
return templatePattern.Match(str)
func (t *Temgo) ContainsVariable(str []byte) bool {
return t.pattern.Match(str)
}

func replace(e *EnvVars, bytes []byte) []byte {
list := templatePattern.FindAllStringSubmatch(string(bytes), -1)
func (t *Temgo) replace(bytes []byte) (result []byte, errList []string) {
result = bytes
list := t.pattern.FindAllStringSubmatch(string(bytes), -1)
for _, match := range list {
str, ok := (*e)[match[1]]
str, ok := t.envVars[match[1]]
if !ok {
continue // variable not set
if t.strict {
errList = append(errList, "variable "+match[1]+" is not set")
}
continue
}
bytes = []byte(strings.Replace(string(bytes), match[0], str, -1))
result = []byte(strings.Replace(string(result), match[0], str, -1))
}
return bytes
return result, errList
}

func (e *EnvVars) ReplaceVariables(str []byte) []byte {
result := templatePattern.ReplaceAllFunc(str, func(b []byte) []byte {
return replace(e, b)
func (t *Temgo) ReplaceVariables(str []byte) ([]byte, error) {
var errList []string
result := t.pattern.ReplaceAllFunc(str, func(b []byte) []byte {
r, err := t.replace(b)
if err != nil {
errList = append(errList, err...)
}
return r
})
return result
if len(errList) > 0 {
return nil, errors.New(strings.Join(errList, "\n"))
}
return result, nil
}
54 changes: 39 additions & 15 deletions temgo/temgo_test.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
package temgo_test

import (
"github.com/malud/temgo/temgo"
"testing"

"github.com/google/go-cmp/cmp"

"github.com/malud/temgo/temgo"
)

var containsTests = []struct {
Expand All @@ -15,38 +18,59 @@ var containsTests = []struct {
{"This text contains a variable with number {{ AUTH0_DOMAIN }}.", true},
}

var replaceVars = &temgo.EnvVars{
var replaceVars = temgo.EnvVars{
"VAR_A": "/etc/ptc",
"VARIABLE_C": "color:256",
"S": "short",
"AUTH0_DOMAIN": "samples.auth0.com",
}

var replaceTests = []struct {
in string
out string
in string
out string
fail bool
}{
{"This dummy text contains a path to {{ VAR_A }}", "This dummy text contains a path to /etc/ptc"},
{"Some text with a {{ VARIABLE_C }} variable!", "Some text with a color:256 variable!"},
{"This is a {{ S }} text.", "This is a short text."},
{"This is a {{ S }} text with a {{ FAILVAR}} and some vars [\"{{ VAR_A }}\",'{{ VARIABLE_C }}'].", "This is a short text with a {{ FAILVAR}} and some vars [\"/etc/ptc\",'color:256']."},
{"This text contains a variable with number: '{{ AUTH0_DOMAIN }}'.", "This text contains a variable with number: 'samples.auth0.com'."},
{"This dummy text contains a path to {{ VAR_A }}", "This dummy text contains a path to /etc/ptc", false},
{"Some text with a {{ VARIABLE_C }} variable!", "Some text with a color:256 variable!", false},
{"This is a {{ S }} text.", "This is a short text.", false},
{"This is a {{ S }} text with a {{ FAILVAR}} and some vars [\"{{ VAR_A }}\",'{{ VARIABLE_C }}'].", "This is a short text with a {{ FAILVAR}} and some vars [\"/etc/ptc\",'color:256'].", false},
{"This text contains a variable with number: '{{ AUTH0_DOMAIN }}'.", "This text contains a variable with number: 'samples.auth0.com'.", false},
{"This text contains a {{ VAR }} which is {{ NOT_SET }} in environment variables.", "variable VAR is not set\nvariable NOT_SET is not set", true},
}

func TestContainsVariable(t *testing.T) {
tg := temgo.New(nil, false)
for _, test := range containsTests {
r := temgo.ContainsVariable([]byte(test.in))
if r != test.out {
t.Errorf("Failed for case: '%v'. Expected: %v Got: %v", test.in, test.out, r)
r := tg.ContainsVariable([]byte(test.in))
if diff := cmp.Diff(r, test.out); diff != "" {
t.Errorf("Failed for case: '%v'.\nResult differs:\n%s", test.in, diff)
}
}
}

func TestEnvVars_ReplaceVariables(t *testing.T) {
tg := temgo.New(replaceVars, false)
for _, test := range replaceTests {
bytes, err := tg.ReplaceVariables([]byte(test.in))
if !test.fail && err != nil {
t.Fatal(err)
}
if diff := cmp.Diff(string(bytes), test.out); diff != "" && !test.fail {
t.Errorf("Failed for case: '%v'.\nResult differs:\n%s", test.in, diff)
}
}
}

func TestEnvVars_ReplaceVariablesStrict(t *testing.T) {
tg := temgo.New(replaceVars, true)
for _, test := range replaceTests {
bytes := replaceVars.ReplaceVariables([]byte(test.in))
if string(bytes) != test.out {
t.Errorf("Failed for case: '%v'. Expected: %v Got: %v", test.in, test.out, string(bytes))
r, err := tg.ReplaceVariables([]byte(test.in))
if test.fail && err != nil {
if diff := cmp.Diff(err.Error(), test.out); diff != "" {
t.Errorf("Failed for case: '%v'.\nResult differs:\n%s", test.in, diff)
}
} else if diff := cmp.Diff(string(r), test.out); diff != "" {
t.Errorf("Failed for case: '%v'.\nResult differs:\n%s", test.in, diff)
}
}
}
18 changes: 18 additions & 0 deletions vendor/github.com/google/go-cmp/.travis.yml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

23 changes: 23 additions & 0 deletions vendor/github.com/google/go-cmp/CONTRIBUTING.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

27 changes: 27 additions & 0 deletions vendor/github.com/google/go-cmp/LICENSE

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

44 changes: 44 additions & 0 deletions vendor/github.com/google/go-cmp/README.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit ad872eb

Please sign in to comment.