Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve Windows support. #381

Merged
merged 20 commits into from
Jul 7, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
e11a0ff
Improve Windows compatibility. Everything in the quickstart guide wo…
zb140 Jul 2, 2019
23614d4
Fix some tests to run on Windows.
zb140 Jul 2, 2019
a1876d5
Fix several more tests on Windows. All but 4 test cases pass now on …
zb140 May 27, 2019
8fa3dae
Fix the permissions related problems in the tests. The only remainin…
zb140 Jul 2, 2019
f2ff742
Don't turn DestDir into an absolute path if it's an empty string.
zb140 May 28, 2019
0586ab4
Implement an actual privateness check in `root.go`
zb140 May 28, 2019
6d1eee7
Reformat files to meet standards
zb140 Jun 7, 2019
eef846a
Fix incorrect boolean check
zb140 Jun 29, 2019
c094eba
Fix Windows tests for symlink following and remove functionality. Al…
zb140 Jun 30, 2019
5c3aed8
Fix apply script tests on Windows:
zb140 Jun 30, 2019
2e23916
Fix tests on non-Windows platforms.
zb140 Jun 30, 2019
aaccef5
Remove unneeded `getOwner` abstraction in upgrade since the command i…
zb140 Jul 1, 2019
8c6bca4
Disable lint checking for runtime.GOOS == "windows" It suggests
zb140 Jul 2, 2019
a703fad
Remove (nearly) all new uses of `runtime.GOOS` by refactoring to use …
zb140 Jul 3, 2019
a56f6b9
Fix build on non-Windows platforms.
zb140 Jul 3, 2019
4bdbb4a
Move IsPrivate out of Mutator to a top-level method. Also rename a f…
zb140 Jul 7, 2019
fa6b866
Fix lint -- the posix implementation of IsPrivate can get away with a…
zb140 Jul 7, 2019
d974593
Fix prompting on Windows
zb140 Jul 7, 2019
10171d8
Remove redundant hash characters from script filenames in the Windows…
zb140 Jul 7, 2019
1d3d743
Restore an accidentally-removed `filepath.Base` call when computing t…
zb140 Jul 7, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion cmd/add.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ func (c *Config) runAddCmd(fs vfs.FS, args []string) (err error) {
if err := c.ensureSourceDirectory(fs, mutator); err != nil {
return err
}
destDirPrefix := ts.DestDir + "/"
destDirPrefix := filepath.FromSlash(ts.DestDir + "/")
var quit int // quit is an int with a unique address
defer func() {
if r := recover(); r != nil {
Expand Down
30 changes: 19 additions & 11 deletions cmd/add_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -336,10 +336,14 @@ func TestAddCommand(t *testing.T) {
{
name: "dest_dir_is_symlink",
args: []string{"/home/user/foo"},
root: map[string]interface{}{
"/home/user": &vfst.Symlink{Target: "../local/home/user"},
"/local/home/user/.chezmoi": &vfst.Dir{Perm: 0700},
"/local/home/user/foo": "bar",
root: []interface{}{
map[string]interface{}{
"/local/home/user/.chezmoi": &vfst.Dir{Perm: 0700},
"/local/home/user/foo": "bar",
},
map[string]interface{}{
"/home/user": &vfst.Symlink{Target: "../local/home/user"},
},
},
tests: []vfst.Test{
vfst.TestPath("/home/user/.chezmoi",
Expand Down Expand Up @@ -385,15 +389,19 @@ func TestAddCommand(t *testing.T) {
}

func TestIssue192(t *testing.T) {
root := map[string]interface{}{
"/local/home/offbyone": &vfst.Dir{
Perm: 0750,
Entries: map[string]interface{}{
".local/share/chezmoi": &vfst.Dir{Perm: 0700},
"snoop/.list": "# contents of .list\n",
root := []interface{}{
map[string]interface{}{
"/local/home/offbyone": &vfst.Dir{
Perm: 0750,
Entries: map[string]interface{}{
".local/share/chezmoi": &vfst.Dir{Perm: 0700},
"snoop/.list": "# contents of .list\n",
},
},
},
"/home/offbyone": &vfst.Symlink{Target: "/local/home/offbyone/"},
map[string]interface{}{
"/home/offbyone": &vfst.Symlink{Target: "/local/home/offbyone/"},
},
}
c := &Config{
SourceDir: "/home/offbyone/.local/share/chezmoi",
Expand Down
92 changes: 14 additions & 78 deletions cmd/apply_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"io/ioutil"
"os"
"path/filepath"
"strings"
"testing"

"github.com/stretchr/testify/assert"
Expand Down Expand Up @@ -245,85 +244,17 @@ func TestApplyScript(t *testing.T) {
defer func() {
require.NoError(t, os.RemoveAll(tempDir))
}()
for _, tc := range []struct {
name string
root interface{}
data map[string]interface{}
tests []vfst.Test
}{
{
name: "simple",
root: map[string]interface{}{
"/home/user/.local/share/chezmoi/run_true": "#!/bin/sh\necho foo >>" + filepath.Join(tempDir, "evidence") + "\n",
},
tests: []vfst.Test{
vfst.TestPath(filepath.Join(tempDir, "evidence"),
vfst.TestModeIsRegular,
vfst.TestContentsString("foo\nfoo\nfoo\n"),
),
},
},
{
name: "simple_once",
root: map[string]interface{}{
"/home/user/.local/share/chezmoi/run_once_true": "#!/bin/sh\necho foo >>" + filepath.Join(tempDir, "evidence") + "\n",
},
tests: []vfst.Test{
vfst.TestPath(filepath.Join(tempDir, "evidence"),
vfst.TestModeIsRegular,
vfst.TestContentsString("foo\n"),
),
},
},
{
name: "template",
root: map[string]interface{}{
"/home/user/.local/share/chezmoi/run_true.tmpl": "#!/bin/sh\necho {{ .Foo }} >>" + filepath.Join(tempDir, "evidence") + "\n",
},
data: map[string]interface{}{
"Foo": "foo",
},
tests: []vfst.Test{
vfst.TestPath(filepath.Join(tempDir, "evidence"),
vfst.TestModeIsRegular,
vfst.TestContentsString("foo\nfoo\nfoo\n"),
),
},
},
{
name: "issue_353",
root: map[string]interface{}{
"/home/user/.local/share/chezmoi": map[string]interface{}{
"run_050_giraffe": "#!/usr/bin/env bash\necho giraffe >>" + filepath.Join(tempDir, "evidence") + "\n",
"run_150_elephant": "#!/usr/bin/env bash\necho elephant >>" + filepath.Join(tempDir, "evidence") + "\n",
"run_once_100_miauw.sh": "#!/usr/bin/env bash\necho miauw >>" + filepath.Join(tempDir, "evidence") + "\n",
},
},
tests: []vfst.Test{
vfst.TestPath(filepath.Join(tempDir, "evidence"),
vfst.TestModeIsRegular,
vfst.TestContentsString(strings.Join([]string{
"giraffe\n",
"miauw\n",
"elephant\n",
"giraffe\n",
"elephant\n",
"giraffe\n",
"elephant\n",
}, "")),
),
},
},
} {
for _, tc := range getApplyScriptTestCases(tempDir) {
t.Run(tc.name, func(t *testing.T) {
fs := vfs.NewPathFS(vfs.OSFS, tempDir)
require.NoError(t, vfst.NewBuilder().Build(fs, tc.root))
persistentState, err := chezmoi.NewBoltPersistentState(fs, "/home/user/.config/chezmoi/chezmoistate.boltdb")
require.NoError(t, err)
defer func() {
require.NoError(t, persistentState.Close())
require.NoError(t, os.RemoveAll(tempDir))
require.NoError(t, os.Mkdir(tempDir, 0700))
}()
require.NoError(t, vfst.NewBuilder().Build(fs, tc.root))
persistentState, err := chezmoi.NewBoltPersistentState(fs, "/home/user/.config/chezmoi/chezmoistate.boltdb")
require.NoError(t, err)
c := &Config{
SourceDir: "/home/user/.local/share/chezmoi",
DestDir: "/",
Expand Down Expand Up @@ -352,10 +283,14 @@ func TestApplyRunOnce(t *testing.T) {
}()
tempFile := filepath.Join(tempDir, "foo")

fs, cleanup, err := vfst.NewTestFS(map[string]interface{}{
filepath.Dir(statePath): &vfst.Dir{Perm: 0755},
"/home/user/.local/share/chezmoi/run_once_foo.tmpl": "#!/bin/sh\necho bar >> {{ .TempFile }}\n",
})
fs, cleanup, err := vfst.NewTestFS(
[]interface{}{
map[string]interface{}{
filepath.Dir(statePath): &vfst.Dir{Perm: 0755},
},
getRunOnceFiles(),
},
)
require.NoError(t, err)
defer cleanup()

Expand All @@ -379,6 +314,7 @@ func TestApplyRunOnce(t *testing.T) {
vfst.TestModeIsRegular,
),
)

actualData, err := ioutil.ReadFile(tempFile)
require.NoError(t, err)
assert.Equal(t, []byte("bar\n"), actualData)
Expand Down
91 changes: 91 additions & 0 deletions cmd/apply_test_posix.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
// +build !windows

package cmd

import (
"path/filepath"
"strings"

"github.com/twpayne/go-vfs/vfst"
)

type scriptTestCase struct {
name string
root interface{}
data map[string]interface{}
tests []vfst.Test
}

func getApplyScriptTestCases(tempDir string) []scriptTestCase {
return []scriptTestCase{
{
name: "simple",
root: map[string]interface{}{
"/home/user/.local/share/chezmoi/run_true": "#!/bin/sh\necho foo >>" + filepath.Join(tempDir, "evidence") + "\n",
},
tests: []vfst.Test{
vfst.TestPath(filepath.Join(tempDir, "evidence"),
vfst.TestModeIsRegular,
vfst.TestContentsString("foo\nfoo\nfoo\n"),
),
},
},
{
name: "simple_once",
root: map[string]interface{}{
"/home/user/.local/share/chezmoi/run_once_true": "#!/bin/sh\necho foo >>" + filepath.Join(tempDir, "evidence") + "\n",
},
tests: []vfst.Test{
vfst.TestPath(filepath.Join(tempDir, "evidence"),
vfst.TestModeIsRegular,
vfst.TestContentsString("foo\n"),
),
},
},
{
name: "template",
root: map[string]interface{}{
"/home/user/.local/share/chezmoi/run_true.tmpl": "#!/bin/sh\necho {{ .Foo }} >>" + filepath.Join(tempDir, "evidence") + "\n",
},
data: map[string]interface{}{
"Foo": "foo",
},
tests: []vfst.Test{
vfst.TestPath(filepath.Join(tempDir, "evidence"),
vfst.TestModeIsRegular,
vfst.TestContentsString("foo\nfoo\nfoo\n"),
),
},
},
{
name: "issue_353",
root: map[string]interface{}{
"/home/user/.local/share/chezmoi": map[string]interface{}{
"run_050_giraffe": "#!/usr/bin/env bash\necho giraffe >>" + filepath.Join(tempDir, "evidence") + "\n",
"run_150_elephant": "#!/usr/bin/env bash\necho elephant >>" + filepath.Join(tempDir, "evidence") + "\n",
"run_once_100_miauw.sh": "#!/usr/bin/env bash\necho miauw >>" + filepath.Join(tempDir, "evidence") + "\n",
},
},
tests: []vfst.Test{
vfst.TestPath(filepath.Join(tempDir, "evidence"),
vfst.TestModeIsRegular,
vfst.TestContentsString(strings.Join([]string{
"giraffe\n",
"miauw\n",
"elephant\n",
"giraffe\n",
"elephant\n",
"giraffe\n",
"elephant\n",
}, "")),
),
},
},
}
}

func getRunOnceFiles() map[string]interface{} {
return map[string]interface{}{
"/home/user/.local/share/chezmoi/run_once_foo.tmpl": "#!/bin/sh\necho bar >> {{ .TempFile }}\n",
}
}
95 changes: 95 additions & 0 deletions cmd/apply_test_windows.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
// +build windows

package cmd

import (
"path/filepath"
"strings"

"github.com/twpayne/go-vfs/vfst"
)

type scriptTestCase struct {
name string
root interface{}
data map[string]interface{}
tests []vfst.Test
}

func getApplyScriptTestCases(tempDir string) []scriptTestCase {
return []scriptTestCase{
{
name: "simple",
root: map[string]interface{}{
"/home/user/.local/share/chezmoi/run_true.bat": "@echo foo>>" + filepath.Join(tempDir, "evidence") + "\n",
},
tests: []vfst.Test{
vfst.TestPath(filepath.Join(tempDir, "evidence"),
vfst.TestModeIsRegular,
vfst.TestContentsString("foo\r\nfoo\r\nfoo\r\n"),
),
},
},
{
name: "simple_once",
root: map[string]interface{}{
"/home/user/.local/share/chezmoi/run_once_true.bat": "@echo foo>>" + filepath.Join(tempDir, "evidence") + "\n",
},
tests: []vfst.Test{
vfst.TestPath(filepath.Join(tempDir, "evidence"),
vfst.TestModeIsRegular,
vfst.TestContentsString("foo\r\n"),
),
},
},
{
name: "template",
root: map[string]interface{}{
"/home/user/.local/share/chezmoi/run_true.bat.tmpl": "@echo {{ .Foo }}>>" + filepath.Join(tempDir, "evidence") + "\n",
},
data: map[string]interface{}{
"Foo": "foo",
},
tests: []vfst.Test{
vfst.TestPath(filepath.Join(tempDir, "evidence"),
vfst.TestModeIsRegular,
vfst.TestContentsString("foo\r\nfoo\r\nfoo\r\n"),
),
},
},
{
name: "issue_353",
root: map[string]interface{}{
"/home/user/.local/share/chezmoi": map[string]interface{}{
"run_050_giraffe.bat": "@echo giraffe>>" + filepath.Join(tempDir, "evidence") + "\n",
"run_150_elephant.bat": "@echo elephant>>" + filepath.Join(tempDir, "evidence") + "\n",
"run_once_100_miauw.bat": "@echo miauw>>" + filepath.Join(tempDir, "evidence") + "\n",
},
},
tests: []vfst.Test{
vfst.TestPath(filepath.Join(tempDir, "evidence"),
vfst.TestModeIsRegular,
vfst.TestContentsString(strings.Join([]string{
"giraffe\r\n",
"miauw\r\n",
"elephant\r\n",
"giraffe\r\n",
"elephant\r\n",
"giraffe\r\n",
"elephant\r\n",
}, "")),
),
},
},
}
}

func getRunOnceFiles() map[string]interface{} {
return map[string]interface{}{
// Windows batch script does not include any way to print a string to the console with only a linefeed (0x0A)
// and no carriage return (0x0D), but it can be done with Powershell. The default action for Powershell script
// files on Windows is to open them in the default text editor rather than to execute them (for security
// reasons). The easiest solution is to make a batch file that calls Powershell.
"/home/user/.local/share/chezmoi/run_once_foo.bat.tmpl": "@powershell.exe -NoProfile -NonInteractive -c \"Write-Host -NoNewLine ('bar{0}' -f (0x0A -as [char]))\">> {{ .TempFile }}\n",
}
}
3 changes: 2 additions & 1 deletion cmd/archive_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"bytes"
"io"
"io/ioutil"
"path/filepath"
"testing"

"github.com/stretchr/testify/assert"
Expand Down Expand Up @@ -34,7 +35,7 @@ func TestArchiveCmd(t *testing.T) {

h, err = r.Next()
assert.NoError(t, err)
assert.Equal(t, "dir/file", h.Name)
assert.Equal(t, filepath.Join("dir", "file"), h.Name)
data, err := ioutil.ReadAll(r)
assert.NoError(t, err)
assert.Equal(t, []byte("contents"), data)
Expand Down
Loading