Skip to content

Commit

Permalink
Some more Windows fixes (#527)
Browse files Browse the repository at this point in the history
* Some more Windows fixes

Signed-off-by: Dave Henderson <dhenderson@gmail.com>

* Upgrading xignore

Signed-off-by: Dave Henderson <dhenderson@gmail.com>
  • Loading branch information
hairyhenderson committed Mar 30, 2019
1 parent b431586 commit e991f3e
Show file tree
Hide file tree
Showing 27 changed files with 273 additions and 164 deletions.
8 changes: 4 additions & 4 deletions Gopkg.lock

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

2 changes: 1 addition & 1 deletion Gopkg.toml
Expand Up @@ -17,4 +17,4 @@

[[constraint]]
name = "github.com/zealic/xignore"
version = "~0.3.2"
version = "~0.3.3"
9 changes: 7 additions & 2 deletions Makefile
Expand Up @@ -68,7 +68,7 @@ build-release: artifacts.cid

docker-images: gomplate.iid gomplate-slim.iid

$(PREFIX)/bin/$(PKG_NAME)_%: $(shell find $(PREFIX) -type f -name '*.go')
$(PREFIX)/bin/$(PKG_NAME)_%: $(shell find $(PREFIX) -type f -name "*.go")
GOOS=$(shell echo $* | cut -f1 -d-) GOARCH=$(shell echo $* | cut -f2 -d- | cut -f1 -d.) CGO_ENABLED=0 \
$(GO) build \
-ldflags "-w -s $(COMMIT_FLAG) $(VERSION_FLAG) $(BUILD_DATE_FLAG)" \
Expand All @@ -80,10 +80,15 @@ $(PREFIX)/bin/$(PKG_NAME)$(call extension,$(GOOS)): $(PREFIX)/bin/$(PKG_NAME)_$(

build: $(PREFIX)/bin/$(PKG_NAME)$(call extension,$(GOOS))

ifeq ($(OS),Windows_NT)
test:
$(GO) test -v -coverprofile=c.out ./...
else
test:
$(GO) test -v -race -coverprofile=c.out ./...
endif

integration: ./bin/gomplate
integration: build
$(GO) test -v -tags=integration \
./tests/integration -check.v

Expand Down
2 changes: 2 additions & 0 deletions appveyor.yml
@@ -1,3 +1,5 @@
image:
- Visual Studio 2015
version: "{build}"

clone_folder: c:\gopath\src\github.com\hairyhenderson\gomplate
Expand Down
29 changes: 12 additions & 17 deletions data/datasource.go
Expand Up @@ -10,7 +10,6 @@ import (
"os"
"path"
"path/filepath"
"regexp"
"strings"

"github.com/spf13/afero"
Expand Down Expand Up @@ -212,27 +211,19 @@ func parseSource(value string) (source *Source, err error) {
return source, nil
}

func trimLeftChar(s string) string {
for i := range s {
if i > 0 {
return s[i:]
}
}
return s[:0]
}

func parseSourceURL(value string) (*url.URL, error) {
if value == "-" {
value = "stdin://"
}
value = filepath.ToSlash(value)
// handle absolute Windows paths
volName := ""
if volName = filepath.VolumeName(value); volName != "" {
// handle UNCs
if len(volName) > 2 {
value = "file:" + filepath.ToSlash(value)
value = "file:" + value
} else {
value = "file:///" + filepath.ToSlash(value)
value = "file:///" + value
}
}
srcURL, err := url.Parse(value)
Expand All @@ -241,9 +232,8 @@ func parseSourceURL(value string) (*url.URL, error) {
}

if volName != "" {
p := regexp.MustCompile("^/[a-zA-Z]:.*$")
if p.MatchString(srcURL.Path) {
srcURL.Path = trimLeftChar(srcURL.Path)
if strings.HasPrefix(srcURL.Path, "/") && srcURL.Path[2] == ':' {
srcURL.Path = srcURL.Path[1:]
}
}

Expand All @@ -261,15 +251,20 @@ func absURL(value string) (*url.URL, error) {
if err != nil {
return nil, errors.Wrapf(err, "can't get working directory")
}
urlCwd := strings.Replace(cwd, string(os.PathSeparator), "/", -1)
urlCwd := filepath.ToSlash(cwd)
baseURL := &url.URL{
Scheme: "file",
Path: urlCwd + "/",
}
relURL := &url.URL{
Path: value,
}
return baseURL.ResolveReference(relURL), nil
resolved := baseURL.ResolveReference(relURL)
// deal with Windows drive letters
if !strings.HasPrefix(urlCwd, "/") && resolved.Path[2] == ':' {
resolved.Path = resolved.Path[1:]
}
return resolved, nil
}

// DefineDatasource -
Expand Down
2 changes: 0 additions & 2 deletions data/datasource_awssmp_test.go
@@ -1,5 +1,3 @@
// +build !windows

package data

import (
Expand Down
5 changes: 0 additions & 5 deletions data/datasource_env_test.go
Expand Up @@ -3,18 +3,13 @@ package data
import (
"net/url"
"os"
"regexp"
"testing"

"github.com/stretchr/testify/assert"
)

func mustParseURL(in string) *url.URL {
u, _ := url.Parse(in)
p := regexp.MustCompile("^/[a-zA-Z]:.*$")
if p.MatchString(u.Path) {
u.Path = trimLeftChar(u.Path)
}
return u
}

Expand Down
2 changes: 0 additions & 2 deletions data/datasource_file_test.go
@@ -1,5 +1,3 @@
// +build !windows

package data

import (
Expand Down
2 changes: 0 additions & 2 deletions data/datasource_merge_test.go
@@ -1,5 +1,3 @@
//+build !windows

package data

import (
Expand Down
11 changes: 11 additions & 0 deletions data/datasource_test.go
Expand Up @@ -64,6 +64,17 @@ func TestParseSourceWithAlias(t *testing.T) {
assert.Equal(t, "/otherdir/foo.json", s.URL.Path)

if runtime.GOOS == "windows" {
s, err = parseSource("data=foo.json")
assert.NoError(t, err)
assert.Equalf(t, byte(':'), s.URL.Path[1], "Path was %s", s.URL.Path)

s, err = parseSource(`data=\otherdir\foo.json`)
assert.NoError(t, err)
assert.Equal(t, "data", s.Alias)
assert.Equal(t, "file", s.URL.Scheme)
assert.True(t, s.URL.IsAbs())
assert.Equal(t, `/otherdir/foo.json`, s.URL.Path)

s, err = parseSource("data=C:\\windowsdir\\foo.json")
assert.NoError(t, err)
assert.Equal(t, "data", s.Alias)
Expand Down
2 changes: 2 additions & 0 deletions docs/content/usage.md
Expand Up @@ -58,6 +58,8 @@ By default, output files are created with the same file mode (permissions) as in

The value must be an octal integer in the standard UNIX `chmod` format, i.e. `644` to indicate that owner gets read+write, group gets read-only, and others get read-only permissions. See the [`chmod(1)` man page](https://linux.die.net/man/1/chmod) for more details.

**Note:** `--chmod` is not currently supported on Windows. Behaviour is undefined, but will likely not change file permissions at all.

### `--exclude`

To prevent certain files from being processed, you can use `--exclude`. It takes a glob, and any files matching that glob will not be included.
Expand Down
26 changes: 0 additions & 26 deletions template_test.go
@@ -1,5 +1,3 @@
// +build !windows

package gomplate

import (
Expand Down Expand Up @@ -60,30 +58,6 @@ func TestOpenOutFile(t *testing.T) {
assert.Equal(t, Stdout, f)
}

func TestWalkDir(t *testing.T) {
origfs := fs
defer func() { fs = origfs }()
fs = afero.NewMemMapFs()

_, err := walkDir("/indir", "/outdir", nil, 0, false)
assert.Error(t, err)

_ = fs.MkdirAll("/indir/one", 0777)
_ = fs.MkdirAll("/indir/two", 0777)
afero.WriteFile(fs, "/indir/one/foo", []byte("foo"), 0644)
afero.WriteFile(fs, "/indir/one/bar", []byte("bar"), 0644)
afero.WriteFile(fs, "/indir/two/baz", []byte("baz"), 0644)

templates, err := walkDir("/indir", "/outdir", []string{"*/two"}, 0, false)

assert.NoError(t, err)
assert.Equal(t, 2, len(templates))
assert.Equal(t, "/indir/one/bar", templates[0].name)
assert.Equal(t, "/outdir/one/bar", templates[0].targetPath)
assert.Equal(t, "/indir/one/foo", templates[1].name)
assert.Equal(t, "/outdir/one/foo", templates[1].targetPath)
}

func TestLoadContents(t *testing.T) {
origfs := fs
defer func() { fs = origfs }()
Expand Down
43 changes: 43 additions & 0 deletions template_unix_test.go
@@ -0,0 +1,43 @@
// +build !windows

package gomplate

import (
"testing"

"github.com/spf13/afero"

"github.com/stretchr/testify/assert"
)

func TestWalkDir(t *testing.T) {
origfs := fs
defer func() { fs = origfs }()
fs = afero.NewMemMapFs()

_, err := walkDir("/indir", "/outdir", nil, 0, false)
assert.Error(t, err)

_ = fs.MkdirAll("/indir/one", 0777)
_ = fs.MkdirAll("/indir/two", 0777)
afero.WriteFile(fs, "/indir/one/foo", []byte("foo"), 0644)
afero.WriteFile(fs, "/indir/one/bar", []byte("bar"), 0644)
afero.WriteFile(fs, "/indir/two/baz", []byte("baz"), 0644)

templates, err := walkDir("/indir", "/outdir", []string{"*/two"}, 0, false)

assert.NoError(t, err)
expected := []*tplate{
{
name: "/indir/one/bar",
targetPath: "/outdir/one/bar",
mode: 0644,
},
{
name: "/indir/one/foo",
targetPath: "/outdir/one/foo",
mode: 0644,
},
}
assert.EqualValues(t, expected, templates)
}
43 changes: 43 additions & 0 deletions template_windows_test.go
@@ -0,0 +1,43 @@
// +build windows

package gomplate

import (
"testing"

"github.com/spf13/afero"

"github.com/stretchr/testify/assert"
)

func TestWalkDir(t *testing.T) {
origfs := fs
defer func() { fs = origfs }()
fs = afero.NewMemMapFs()

_, err := walkDir(`C:\indir`, `C:\outdir`, nil, 0, false)
assert.Error(t, err)

_ = fs.MkdirAll(`C:\indir\one`, 0777)
_ = fs.MkdirAll(`C:\indir\two`, 0777)
afero.WriteFile(fs, `C:\indir\one\foo`, []byte("foo"), 0644)
afero.WriteFile(fs, `C:\indir\one\bar`, []byte("bar"), 0644)
afero.WriteFile(fs, `C:\indir\two\baz`, []byte("baz"), 0644)

templates, err := walkDir(`C:\indir`, `C:\outdir`, []string{`*\two`}, 0, false)

assert.NoError(t, err)
expected := []*tplate{
{
name: `C:\indir\one\bar`,
targetPath: `C:\outdir\one\bar`,
mode: 0644,
},
{
name: `C:\indir\one\foo`,
targetPath: `C:\outdir\one\foo`,
mode: 0644,
},
}
assert.EqualValues(t, expected, templates)
}
73 changes: 73 additions & 0 deletions tests/integration/basic_nonwindows_test.go
@@ -0,0 +1,73 @@
//+build integration
//+build !windows

package integration

import (
"bytes"
"io/ioutil"
"os"

. "gopkg.in/check.v1"

"github.com/gotestyourself/gotestyourself/assert"
"github.com/gotestyourself/gotestyourself/icmd"
)

func (s *BasicSuite) TestRoutesInputsToProperOutputsWithChmod(c *C) {
oneOut := s.tmpDir.Join("one.out")
twoOut := s.tmpDir.Join("two.out")
result := icmd.RunCmd(icmd.Command(GomplateBin,
"-f", s.tmpDir.Join("one"),
"-f", s.tmpDir.Join("two"),
"-o", oneOut,
"-o", twoOut,
"--chmod", "0600"), func(cmd *icmd.Cmd) {
cmd.Stdin = bytes.NewBufferString("hello world")
})
result.Assert(c, icmd.Success)

testdata := []struct {
path string
mode os.FileMode
content string
}{
{oneOut, 0600, "hi\n"},
{twoOut, 0600, "hello\n"},
}
for _, v := range testdata {
info, err := os.Stat(v.path)
assert.NilError(c, err)
assert.Equal(c, v.mode, info.Mode())
content, err := ioutil.ReadFile(v.path)
assert.NilError(c, err)
assert.Equal(c, v.content, string(content))
}
}

func (s *BasicSuite) TestOverridesOutputModeWithChmod(c *C) {
out := s.tmpDir.Join("two")
result := icmd.RunCmd(icmd.Command(GomplateBin,
"-f", s.tmpDir.Join("one"),
"-o", out,
"--chmod", "0600"), func(cmd *icmd.Cmd) {
cmd.Stdin = bytes.NewBufferString("hello world")
})
result.Assert(c, icmd.Success)

testdata := []struct {
path string
mode os.FileMode
content string
}{
{out, 0600, "hi\n"},
}
for _, v := range testdata {
info, err := os.Stat(v.path)
assert.NilError(c, err)
assert.Equal(c, v.mode, info.Mode())
content, err := ioutil.ReadFile(v.path)
assert.NilError(c, err)
assert.Equal(c, v.content, string(content))
}
}

0 comments on commit e991f3e

Please sign in to comment.