From c475c5ee0fd34d80c8198197876c2c629b4991dd Mon Sep 17 00:00:00 2001 From: Tom Payne Date: Mon, 10 Feb 2020 22:52:31 +0100 Subject: [PATCH] Use functional options to construct Configs --- cmd/add_test.go | 45 +++++-------- cmd/apply_test.go | 89 ++++++++++---------------- cmd/archive_test.go | 14 ++-- cmd/chattr_test.go | 103 ++++++++++++++---------------- cmd/cmd_test.go | 35 +++++----- cmd/config.go | 28 ++++++++ cmd/config_test.go | 102 +++++++++++++++++++++++++++-- cmd/diff_posix_test.go | 13 ++-- cmd/dump_test.go | 24 +++---- cmd/import_test.go | 13 ++-- cmd/init_test.go | 47 +++++--------- cmd/root.go | 15 +---- cmd/secretgeneric_posix_test.go | 26 ++++---- cmd/secretgeneric_windows_test.go | 20 +++--- 14 files changed, 297 insertions(+), 277 deletions(-) diff --git a/cmd/add_test.go b/cmd/add_test.go index 4db02bf61ac..3ce6e683382 100644 --- a/cmd/add_test.go +++ b/cmd/add_test.go @@ -1,7 +1,6 @@ package cmd import ( - "os" "path/filepath" "testing" @@ -19,13 +18,10 @@ func TestAddAfterModification(t *testing.T) { }) require.NoError(t, err) defer cleanup() - c := &Config{ - fs: fs, - mutator: chezmoi.NewVerboseMutator(os.Stdout, chezmoi.NewFSMutator(fs), false, 0), - SourceDir: "/home/user/.local/share/chezmoi", - DestDir: "/home/user", - Umask: 022, - } + c := newConfig( + withTestFS(fs), + withTestUser("user"), + ) args := []string{"/home/user/.bashrc"} assert.NoError(t, c.runAddCmd(nil, args)) vfst.RunTests(t, fs, "", @@ -455,22 +451,16 @@ func TestAddCommand(t *testing.T) { fs, cleanup, err := vfst.NewTestFS(tc.root) require.NoError(t, err) defer cleanup() - c := &Config{ - fs: fs, - mutator: chezmoi.NewVerboseMutator(os.Stdout, chezmoi.NewFSMutator(fs), false, 0), - SourceDir: "/home/user/.local/share/chezmoi", - DestDir: "/home/user", - Follow: tc.follow, - Umask: 022, - SourceVCS: sourceVCSConfig{ - Command: "git", - }, - Data: map[string]interface{}{ + c := newConfig( + withTestFS(fs), + withTestUser("user"), + withFollow(tc.follow), + withData(map[string]interface{}{ "name": "John Smith", "email": "john.smith@company.com", - }, - add: tc.add, - } + }), + withAddCmdConfig(tc.add), + ) assert.NoError(t, c.runAddCmd(nil, tc.args)) vfst.RunTests(t, fs, "", tc.tests) }) @@ -495,13 +485,10 @@ func TestIssue192(t *testing.T) { fs, cleanup, err := vfst.NewTestFS(root) require.NoError(t, err) defer cleanup() - c := &Config{ - fs: fs, - mutator: chezmoi.NewVerboseMutator(os.Stdout, chezmoi.NewFSMutator(fs), false, 0), - SourceDir: "/home/offbyone/.local/share/chezmoi", - DestDir: "/home/offbyone", - Umask: 022, - } + c := newConfig( + withTestFS(fs), + withTestUser("offbyone"), + ) assert.NoError(t, c.runAddCmd(nil, []string{"/home/offbyone/snoop/.list"})) vfst.RunTests(t, fs, "", vfst.TestPath("/local/home/offbyone/.local/share/chezmoi/snoop/dot_list", diff --git a/cmd/apply_test.go b/cmd/apply_test.go index 349fd89ad8a..526586c8dc9 100644 --- a/cmd/apply_test.go +++ b/cmd/apply_test.go @@ -8,7 +8,6 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/twpayne/chezmoi/internal/chezmoi" vfs "github.com/twpayne/go-vfs" "github.com/twpayne/go-vfs/vfst" ) @@ -140,14 +139,10 @@ func TestApplyCommand(t *testing.T) { fs, cleanup, err := vfst.NewTestFS(tc.root) require.NoError(t, err) defer cleanup() - c := &Config{ - fs: fs, - mutator: chezmoi.NewVerboseMutator(os.Stdout, chezmoi.NewFSMutator(fs), false, 0), - SourceDir: "/home/user/.local/share/chezmoi", - DestDir: "/home/user", - Umask: 022, - bds: newTestBaseDirectorySpecification("/home/user"), - } + c := newConfig( + withTestFS(fs), + withTestUser("user"), + ) assert.NoError(t, c.runApplyCmd(nil, nil)) vfst.RunTests(t, fs, "", vfst.TestPath("/home/user/dir", @@ -230,15 +225,11 @@ func TestApplyFollow(t *testing.T) { fs, cleanup, err := vfst.NewTestFS(tc.root) require.NoError(t, err) defer cleanup() - c := &Config{ - fs: fs, - mutator: chezmoi.NewVerboseMutator(os.Stdout, chezmoi.NewFSMutator(fs), false, 0), - SourceDir: "/home/user/.local/share/chezmoi", - DestDir: "/home/user", - Follow: tc.follow, - Umask: 022, - bds: newTestBaseDirectorySpecification("/home/user"), - } + c := newConfig( + withTestFS(fs), + withTestUser("user"), + withFollow(tc.follow), + ) assert.NoError(t, c.runApplyCmd(nil, nil)) vfst.RunTests(t, fs, "", tc.tests) }) @@ -350,16 +341,12 @@ func TestApplyRemove(t *testing.T) { fs, cleanup, err := vfst.NewTestFS(tc.root) require.NoError(t, err) defer cleanup() - c := &Config{ - fs: fs, - mutator: chezmoi.NewVerboseMutator(os.Stdout, chezmoi.NewFSMutator(fs), false, 0), - SourceDir: "/home/user/.local/share/chezmoi", - DestDir: "/home/user", - Data: tc.data, - Remove: !tc.noRemove, - Umask: 022, - bds: newTestBaseDirectorySpecification("/home/user"), - } + c := newConfig( + withTestFS(fs), + withTestUser("user"), + withData(tc.data), + withRemove(!tc.noRemove), + ) assert.NoError(t, c.runApplyCmd(nil, nil)) vfst.RunTests(t, fs, "", tc.tests) }) @@ -381,16 +368,12 @@ func TestApplyScript(t *testing.T) { require.NoError(t, os.Mkdir(tempDir, 0700)) }() apply := func() { - c := &Config{ - fs: fs, - mutator: chezmoi.NewVerboseMutator(os.Stdout, chezmoi.NewFSMutator(fs), false, 0), - SourceDir: "/home/user/.local/share/chezmoi", - DestDir: "/", - Umask: 022, - Data: tc.data, - bds: newTestBaseDirectorySpecification("/home/user"), - scriptStateBucket: []byte("script"), - } + c := newConfig( + withTestFS(fs), + withTestUser("user"), + withDestDir("/"), + withData(tc.data), + ) require.NoError(t, c.runApplyCmd(nil, nil)) } // Run apply three times. As chezmoi should be idempotent, the @@ -419,18 +402,14 @@ func TestApplyRunOnce(t *testing.T) { require.NoError(t, err) defer cleanup() - c := &Config{ - fs: fs, - mutator: chezmoi.NewVerboseMutator(os.Stdout, chezmoi.NewFSMutator(fs), false, 0), - SourceDir: "/home/user/.local/share/chezmoi", - DestDir: "/", - Umask: 022, - Data: map[string]interface{}{ + c := newConfig( + withTestFS(fs), + withTestUser("user"), + withDestDir("/"), + withData(map[string]interface{}{ "TempFile": tempFile, - }, - bds: newTestBaseDirectorySpecification("/home/user"), - scriptStateBucket: []byte("script"), - } + }), + ) require.NoError(t, c.runApplyCmd(nil, nil)) vfst.RunTests(t, fs, "", @@ -489,14 +468,10 @@ func TestApplyRemoveEmptySymlink(t *testing.T) { fs, cleanup, err := vfst.NewTestFS(tc.root) require.NoError(t, err) defer cleanup() - c := &Config{ - fs: fs, - mutator: chezmoi.NewVerboseMutator(os.Stdout, chezmoi.NewFSMutator(fs), false, 0), - SourceDir: "/home/user/.local/share/chezmoi", - DestDir: "/home/user", - Umask: 022, - bds: newTestBaseDirectorySpecification("/home/user"), - } + c := newConfig( + withTestFS(fs), + withTestUser("user"), + ) assert.NoError(t, c.runApplyCmd(nil, nil)) vfst.RunTests(t, fs, "", tc.tests) }) diff --git a/cmd/archive_test.go b/cmd/archive_test.go index 8a349c7096f..8cd27c0b1f2 100644 --- a/cmd/archive_test.go +++ b/cmd/archive_test.go @@ -5,13 +5,11 @@ import ( "bytes" "io" "io/ioutil" - "os" "path/filepath" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/twpayne/chezmoi/internal/chezmoi" "github.com/twpayne/go-vfs/vfst" ) @@ -23,13 +21,11 @@ func TestArchiveCmd(t *testing.T) { require.NoError(t, err) defer cleanup() stdout := &bytes.Buffer{} - c := &Config{ - fs: fs, - mutator: chezmoi.NewVerboseMutator(os.Stdout, chezmoi.NewFSMutator(fs), false, 0), - SourceDir: "/home/user/.local/share/chezmoi", - Umask: 022, - stdout: stdout, - } + c := newConfig( + withTestFS(fs), + withTestUser("user"), + withStdout(stdout), + ) assert.NoError(t, c.runArchiveCmd(nil, nil)) r := tar.NewReader(stdout) diff --git a/cmd/chattr_test.go b/cmd/chattr_test.go index 4e09fb290d5..178f3e259c1 100644 --- a/cmd/chattr_test.go +++ b/cmd/chattr_test.go @@ -1,12 +1,10 @@ package cmd import ( - "os" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/twpayne/chezmoi/internal/chezmoi" "github.com/twpayne/go-vfs/vfst" ) @@ -21,15 +19,15 @@ func TestChattrCommand(t *testing.T) { name: "dir_add_exact", args: []string{"+exact", "/home/user/dir"}, root: map[string]interface{}{ - "/home/user/.config/share/chezmoi": map[string]interface{}{ + "/home/user/.local/share/chezmoi": map[string]interface{}{ "dir": &vfst.Dir{Perm: 0755}, }, }, tests: []vfst.Test{ - vfst.TestPath("/home/user/.config/share/chezmoi/dir", + vfst.TestPath("/home/user/.local/share/chezmoi/dir", vfst.TestDoesNotExist, ), - vfst.TestPath("/home/user/.config/share/chezmoi/exact_dir", + vfst.TestPath("/home/user/.local/share/chezmoi/exact_dir", vfst.TestIsDir, ), }, @@ -38,15 +36,15 @@ func TestChattrCommand(t *testing.T) { name: "dir_remove_exact", args: []string{"-exact", "/home/user/dir"}, root: map[string]interface{}{ - "/home/user/.config/share/chezmoi": map[string]interface{}{ + "/home/user/.local/share/chezmoi": map[string]interface{}{ "exact_dir": &vfst.Dir{Perm: 0755}, }, }, tests: []vfst.Test{ - vfst.TestPath("/home/user/.config/share/chezmoi/exact_dir", + vfst.TestPath("/home/user/.local/share/chezmoi/exact_dir", vfst.TestDoesNotExist, ), - vfst.TestPath("/home/user/.config/share/chezmoi/dir", + vfst.TestPath("/home/user/.local/share/chezmoi/dir", vfst.TestIsDir, ), }, @@ -55,15 +53,15 @@ func TestChattrCommand(t *testing.T) { name: "dir_add_private", args: []string{"+private", "/home/user/dir"}, root: map[string]interface{}{ - "/home/user/.config/share/chezmoi": map[string]interface{}{ + "/home/user/.local/share/chezmoi": map[string]interface{}{ "dir": &vfst.Dir{Perm: 0755}, }, }, tests: []vfst.Test{ - vfst.TestPath("/home/user/.config/share/chezmoi/dir", + vfst.TestPath("/home/user/.local/share/chezmoi/dir", vfst.TestDoesNotExist, ), - vfst.TestPath("/home/user/.config/share/chezmoi/private_dir", + vfst.TestPath("/home/user/.local/share/chezmoi/private_dir", vfst.TestIsDir, ), }, @@ -72,15 +70,15 @@ func TestChattrCommand(t *testing.T) { name: "dir_remove_private", args: []string{"-private", "/home/user/dir"}, root: map[string]interface{}{ - "/home/user/.config/share/chezmoi": map[string]interface{}{ + "/home/user/.local/share/chezmoi": map[string]interface{}{ "private_dir": &vfst.Dir{Perm: 0755}, }, }, tests: []vfst.Test{ - vfst.TestPath("/home/user/.config/share/chezmoi/private_dir", + vfst.TestPath("/home/user/.local/share/chezmoi/private_dir", vfst.TestDoesNotExist, ), - vfst.TestPath("/home/user/.config/share/chezmoi/dir", + vfst.TestPath("/home/user/.local/share/chezmoi/dir", vfst.TestIsDir, ), }, @@ -89,15 +87,15 @@ func TestChattrCommand(t *testing.T) { name: "file_add_empty", args: []string{"+empty", "/home/user/foo"}, root: map[string]interface{}{ - "/home/user/.config/share/chezmoi": map[string]interface{}{ + "/home/user/.local/share/chezmoi": map[string]interface{}{ "foo": "# contents of ~/foo\n", }, }, tests: []vfst.Test{ - vfst.TestPath("/home/user/.config/share/chezmoi/foo", + vfst.TestPath("/home/user/.local/share/chezmoi/foo", vfst.TestDoesNotExist, ), - vfst.TestPath("/home/user/.config/share/chezmoi/empty_foo", + vfst.TestPath("/home/user/.local/share/chezmoi/empty_foo", vfst.TestModeIsRegular, vfst.TestContentsString("# contents of ~/foo\n"), ), @@ -107,16 +105,16 @@ func TestChattrCommand(t *testing.T) { name: "file_remove_empty", args: []string{"-empty", "/home/user/foo"}, root: map[string]interface{}{ - "/home/user/.config/share/chezmoi": map[string]interface{}{ + "/home/user/.local/share/chezmoi": map[string]interface{}{ "empty_foo": "# contents of ~/foo\n", }, }, tests: []vfst.Test{ - vfst.TestPath("/home/user/.config/share/chezmoi/foo", + vfst.TestPath("/home/user/.local/share/chezmoi/foo", vfst.TestModeIsRegular, vfst.TestContentsString("# contents of ~/foo\n"), ), - vfst.TestPath("/home/user/.config/share/chezmoi/empty_foo", + vfst.TestPath("/home/user/.local/share/chezmoi/empty_foo", vfst.TestDoesNotExist, ), }, @@ -125,15 +123,15 @@ func TestChattrCommand(t *testing.T) { name: "file_add_executable", args: []string{"+executable", "/home/user/foo"}, root: map[string]interface{}{ - "/home/user/.config/share/chezmoi": map[string]interface{}{ + "/home/user/.local/share/chezmoi": map[string]interface{}{ "foo": "# contents of ~/foo\n", }, }, tests: []vfst.Test{ - vfst.TestPath("/home/user/.config/share/chezmoi/foo", + vfst.TestPath("/home/user/.local/share/chezmoi/foo", vfst.TestDoesNotExist, ), - vfst.TestPath("/home/user/.config/share/chezmoi/executable_foo", + vfst.TestPath("/home/user/.local/share/chezmoi/executable_foo", vfst.TestModeIsRegular, vfst.TestContentsString("# contents of ~/foo\n"), ), @@ -143,16 +141,16 @@ func TestChattrCommand(t *testing.T) { name: "file_remove_executable", args: []string{"-executable", "/home/user/foo"}, root: map[string]interface{}{ - "/home/user/.config/share/chezmoi": map[string]interface{}{ + "/home/user/.local/share/chezmoi": map[string]interface{}{ "executable_foo": "# contents of ~/foo\n", }, }, tests: []vfst.Test{ - vfst.TestPath("/home/user/.config/share/chezmoi/foo", + vfst.TestPath("/home/user/.local/share/chezmoi/foo", vfst.TestModeIsRegular, vfst.TestContentsString("# contents of ~/foo\n"), ), - vfst.TestPath("/home/user/.config/share/chezmoi/executable_foo", + vfst.TestPath("/home/user/.local/share/chezmoi/executable_foo", vfst.TestDoesNotExist, ), }, @@ -161,15 +159,15 @@ func TestChattrCommand(t *testing.T) { name: "file_add_private", args: []string{"+private", "/home/user/foo"}, root: map[string]interface{}{ - "/home/user/.config/share/chezmoi": map[string]interface{}{ + "/home/user/.local/share/chezmoi": map[string]interface{}{ "foo": "# contents of ~/foo\n", }, }, tests: []vfst.Test{ - vfst.TestPath("/home/user/.config/share/chezmoi/foo", + vfst.TestPath("/home/user/.local/share/chezmoi/foo", vfst.TestDoesNotExist, ), - vfst.TestPath("/home/user/.config/share/chezmoi/private_foo", + vfst.TestPath("/home/user/.local/share/chezmoi/private_foo", vfst.TestModeIsRegular, vfst.TestContentsString("# contents of ~/foo\n"), ), @@ -179,16 +177,16 @@ func TestChattrCommand(t *testing.T) { name: "file_remove_private", args: []string{"-private", "/home/user/foo"}, root: map[string]interface{}{ - "/home/user/.config/share/chezmoi": map[string]interface{}{ + "/home/user/.local/share/chezmoi": map[string]interface{}{ "private_foo": "# contents of ~/foo\n", }, }, tests: []vfst.Test{ - vfst.TestPath("/home/user/.config/share/chezmoi/foo", + vfst.TestPath("/home/user/.local/share/chezmoi/foo", vfst.TestModeIsRegular, vfst.TestContentsString("# contents of ~/foo\n"), ), - vfst.TestPath("/home/user/.config/share/chezmoi/private_foo", + vfst.TestPath("/home/user/.local/share/chezmoi/private_foo", vfst.TestDoesNotExist, ), }, @@ -197,15 +195,15 @@ func TestChattrCommand(t *testing.T) { name: "file_add_template", args: []string{"+template", "/home/user/foo"}, root: map[string]interface{}{ - "/home/user/.config/share/chezmoi": map[string]interface{}{ + "/home/user/.local/share/chezmoi": map[string]interface{}{ "foo": "# contents of ~/foo\n", }, }, tests: []vfst.Test{ - vfst.TestPath("/home/user/.config/share/chezmoi/foo", + vfst.TestPath("/home/user/.local/share/chezmoi/foo", vfst.TestDoesNotExist, ), - vfst.TestPath("/home/user/.config/share/chezmoi/foo.tmpl", + vfst.TestPath("/home/user/.local/share/chezmoi/foo.tmpl", vfst.TestModeIsRegular, vfst.TestContentsString("# contents of ~/foo\n"), ), @@ -215,16 +213,16 @@ func TestChattrCommand(t *testing.T) { name: "file_remove_template", args: []string{"-template", "/home/user/foo"}, root: map[string]interface{}{ - "/home/user/.config/share/chezmoi": map[string]interface{}{ + "/home/user/.local/share/chezmoi": map[string]interface{}{ "foo.tmpl": "# contents of ~/foo\n", }, }, tests: []vfst.Test{ - vfst.TestPath("/home/user/.config/share/chezmoi/foo", + vfst.TestPath("/home/user/.local/share/chezmoi/foo", vfst.TestModeIsRegular, vfst.TestContentsString("# contents of ~/foo\n"), ), - vfst.TestPath("/home/user/.config/share/chezmoi/foo.tmpl", + vfst.TestPath("/home/user/.local/share/chezmoi/foo.tmpl", vfst.TestDoesNotExist, ), }, @@ -233,17 +231,17 @@ func TestChattrCommand(t *testing.T) { name: "file_add_template_in_private_dir", args: []string{"+template", "/home/user/.ssh/authorized_keys"}, root: map[string]interface{}{ - "/home/user/.config/share/chezmoi": map[string]interface{}{ + "/home/user/.local/share/chezmoi": map[string]interface{}{ "private_dot_ssh": map[string]interface{}{ "authorized_keys": "# contents of ~/.ssh/authorized_keys\n", }, }, }, tests: []vfst.Test{ - vfst.TestPath("/home/user/.config/share/chezmoi/private_dot_ssh/authorized_keys", + vfst.TestPath("/home/user/.local/share/chezmoi/private_dot_ssh/authorized_keys", vfst.TestDoesNotExist, ), - vfst.TestPath("/home/user/.config/share/chezmoi/private_dot_ssh/authorized_keys.tmpl", + vfst.TestPath("/home/user/.local/share/chezmoi/private_dot_ssh/authorized_keys.tmpl", vfst.TestModeIsRegular, vfst.TestContentsString("# contents of ~/.ssh/authorized_keys\n"), ), @@ -253,15 +251,15 @@ func TestChattrCommand(t *testing.T) { name: "symlink_add_template", args: []string{"+template", "/home/user/foo"}, root: map[string]interface{}{ - "/home/user/.config/share/chezmoi": map[string]interface{}{ + "/home/user/.local/share/chezmoi": map[string]interface{}{ "symlink_foo": "# contents of ~/foo\n", }, }, tests: []vfst.Test{ - vfst.TestPath("/home/user/.config/share/chezmoi/symlink_foo", + vfst.TestPath("/home/user/.local/share/chezmoi/symlink_foo", vfst.TestDoesNotExist, ), - vfst.TestPath("/home/user/.config/share/chezmoi/symlink_foo.tmpl", + vfst.TestPath("/home/user/.local/share/chezmoi/symlink_foo.tmpl", vfst.TestModeIsRegular, vfst.TestContentsString("# contents of ~/foo\n"), ), @@ -271,16 +269,16 @@ func TestChattrCommand(t *testing.T) { name: "symlink_remove_template", args: []string{"-template", "/home/user/foo"}, root: map[string]interface{}{ - "/home/user/.config/share/chezmoi": map[string]interface{}{ + "/home/user/.local/share/chezmoi": map[string]interface{}{ "symlink_foo.tmpl": "# contents of ~/foo\n", }, }, tests: []vfst.Test{ - vfst.TestPath("/home/user/.config/share/chezmoi/symlink_foo", + vfst.TestPath("/home/user/.local/share/chezmoi/symlink_foo", vfst.TestModeIsRegular, vfst.TestContentsString("# contents of ~/foo\n"), ), - vfst.TestPath("/home/user/.config/share/chezmoi/symlink_foo.tmpl", + vfst.TestPath("/home/user/.local/share/chezmoi/symlink_foo.tmpl", vfst.TestDoesNotExist, ), }, @@ -290,13 +288,10 @@ func TestChattrCommand(t *testing.T) { fs, cleanup, err := vfst.NewTestFS(tc.root) require.NoError(t, err) defer cleanup() - c := &Config{ - fs: fs, - mutator: chezmoi.NewVerboseMutator(os.Stdout, chezmoi.NewFSMutator(fs), false, 0), - SourceDir: "/home/user/.config/share/chezmoi", - DestDir: "/home/user", - Umask: 022, - } + c := newConfig( + withTestFS(fs), + withTestUser("user"), + ) assert.NoError(t, c.runChattrCmd(nil, tc.args)) vfst.RunTests(t, fs, "", tc.tests) }) diff --git a/cmd/cmd_test.go b/cmd/cmd_test.go index 42fceb43e57..e5a4c8b87e4 100644 --- a/cmd/cmd_test.go +++ b/cmd/cmd_test.go @@ -7,7 +7,6 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/twpayne/chezmoi/internal/chezmoi" "github.com/twpayne/go-vfs/vfst" ) @@ -19,32 +18,28 @@ func TestExercise(t *testing.T) { require.NoError(t, err) defer cleanup() - c := &Config{ - fs: fs, - mutator: chezmoi.NewVerboseMutator(os.Stdout, chezmoi.NewFSMutator(fs), false, 0), - SourceDir: "/home/user/.chezmoi", - DestDir: "/home/user", - Umask: 022, - Verbose: true, - bds: newTestBaseDirectorySpecification("/home/user"), - remove: removeCmdConfig{ + c := newConfig( + withTestFS(fs), + withTestUser("user"), + withVerbose(true), + withRemoveCmdConfig(removeCmdConfig{ force: true, - }, - } + }), + ) mustWriteFile := func(name, contents string, mode os.FileMode) { - assert.NoError(t, fs.WriteFile(name, []byte(contents), mode)) + require.NoError(t, fs.WriteFile(name, []byte(contents), mode)) } // chezmoi add ~/.bashrc t.Run("chezmoi_add_bashrc", func(t *testing.T) { assert.NoError(t, c.runAddCmd(nil, []string{"/home/user/.bashrc"})) vfst.RunTests(t, fs, "", - vfst.TestPath("/home/user/.chezmoi", + vfst.TestPath("/home/user/.local/share/chezmoi", vfst.TestIsDir, vfst.TestModePerm(0700), ), - vfst.TestPath("/home/user/.chezmoi/dot_bashrc", + vfst.TestPath("/home/user/.local/share/chezmoi/dot_bashrc", vfst.TestModeIsRegular, vfst.TestModePerm(0644), vfst.TestContentsString("# contents of .bashrc\n"), @@ -56,7 +51,7 @@ func TestExercise(t *testing.T) { t.Run("chezmoi_forget_bashrc", func(t *testing.T) { assert.NoError(t, c.runForgetCmd(nil, []string{"/home/user/.bashrc"})) vfst.RunTests(t, fs, "", - vfst.TestPath("/home/user/.chezmoi/dot_bashrc", + vfst.TestPath("/home/user/.local/share/chezmoi/dot_bashrc", vfst.TestDoesNotExist, ), ) @@ -66,10 +61,10 @@ func TestExercise(t *testing.T) { t.Run("chezmoi_add_netrc", func(t *testing.T) { mustWriteFile("/home/user/.netrc", "# contents of .netrc\n", 0600) assert.NoError(t, c.runAddCmd(nil, []string{"/home/user/.netrc"})) - path := "/home/user/.chezmoi/private_dot_netrc" + path := "/home/user/.local/share/chezmoi/private_dot_netrc" // Private files are not supported on Windows. if runtime.GOOS == "windows" { - path = "/home/user/.chezmoi/dot_netrc" + path = "/home/user/.local/share/chezmoi/dot_netrc" } vfst.RunTests(t, fs, "", vfst.TestPath(path, @@ -84,7 +79,7 @@ func TestExercise(t *testing.T) { t.Run("chezmoi_chattr_netrc", func(t *testing.T) { assert.NoError(t, c.runChattrCmd(nil, []string{"-private,+empty", "/home/user/.netrc"})) vfst.RunTests(t, fs, "", - vfst.TestPath("/home/user/.chezmoi/empty_dot_netrc", + vfst.TestPath("/home/user/.local/share/chezmoi/empty_dot_netrc", vfst.TestModeIsRegular, vfst.TestModePerm(0644), vfst.TestContentsString("# contents of .netrc\n"), @@ -111,7 +106,7 @@ func TestExercise(t *testing.T) { vfst.TestPath("/home/user/.netrc", vfst.TestDoesNotExist, ), - vfst.TestPath("/home/user/.chezmoi/empty_dot_netrc", + vfst.TestPath("/home/user/.local/share/chezmoi/empty_dot_netrc", vfst.TestDoesNotExist, ), ) diff --git a/cmd/config.go b/cmd/config.go index e8e1996cf20..1df73684f94 100644 --- a/cmd/config.go +++ b/cmd/config.go @@ -20,6 +20,7 @@ import ( "unicode" "github.com/BurntSushi/toml" + "github.com/Masterminds/sprig" "github.com/spf13/cobra" "github.com/spf13/viper" "github.com/twpayne/chezmoi/internal/chezmoi" @@ -85,6 +86,9 @@ type Config struct { scriptStateBucket []byte } +// A configOption sets an option on a Config. +type configOption func(*Config) + var ( formatMap = map[string]func(io.Writer, interface{}) error{ "json": func(w io.Writer, value interface{}) error { @@ -112,6 +116,30 @@ var ( gzipedAssets = make(map[string][]byte) ) +// newConfig creates a new Config with the given options. +func newConfig(options ...configOption) *Config { + c := &Config{ + Umask: permValue(getUmask()), + Color: "auto", + SourceVCS: sourceVCSConfig{ + Command: "git", + }, + Merge: mergeConfig{ + Command: "vimdiff", + }, + maxDiffDataSize: 1 * 1024 * 1024, // 1MB + templateFuncs: sprig.HermeticTxtFuncMap(), + scriptStateBucket: []byte("script"), + stdin: os.Stdin, + stdout: os.Stdout, + stderr: os.Stderr, + } + for _, option := range options { + option(c) + } + return c +} + // Stderr returns c's stderr. func (c *Config) Stderr() io.Writer { if c.stderr != nil { diff --git a/cmd/config_test.go b/cmd/config_test.go index a708917a15b..b5735124061 100644 --- a/cmd/config_test.go +++ b/cmd/config_test.go @@ -2,6 +2,8 @@ package cmd import ( "bytes" + "io" + "os" "path/filepath" "testing" "text/template" @@ -9,6 +11,8 @@ import ( "github.com/Masterminds/sprig" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/twpayne/chezmoi/internal/chezmoi" + vfs "github.com/twpayne/go-vfs" xdg "github.com/twpayne/go-xdg/v3" ) @@ -129,12 +133,96 @@ func TestValidateKeys(t *testing.T) { } } -//nolint:unparam -func newTestBaseDirectorySpecification(homeDir string) *xdg.BaseDirectorySpecification { - return &xdg.BaseDirectorySpecification{ - ConfigHome: filepath.Join(homeDir, ".config"), - DataHome: filepath.Join(homeDir, ".local"), - CacheHome: filepath.Join(homeDir, ".cache"), - RuntimeDir: filepath.Join(homeDir, ".run"), +func withAddCmdConfig(add addCmdConfig) configOption { + return func(c *Config) { + c.add = add + } +} + +func withData(data map[string]interface{}) configOption { + return func(c *Config) { + c.Data = data + } +} + +func withDestDir(destDir string) configOption { + return func(c *Config) { + c.DestDir = destDir + } +} + +func withDumpCmdConfig(dumpCmdConfig dumpCmdConfig) configOption { + return func(c *Config) { + c.dump = dumpCmdConfig + } +} + +func withFollow(follow bool) configOption { + return func(c *Config) { + c.Follow = follow + } +} + +func withGenericSecretCmdConfig(genericSecretCmdConfig genericSecretCmdConfig) configOption { + return func(c *Config) { + c.GenericSecret = genericSecretCmdConfig + } +} + +func withMutator(mutator chezmoi.Mutator) configOption { + return func(c *Config) { + c.mutator = mutator + } +} + +func withRemove(remove bool) configOption { + return func(c *Config) { + c.Remove = remove + } +} + +func withRemoveCmdConfig(remove removeCmdConfig) configOption { + return func(c *Config) { + c.remove = remove + } +} + +func withStdin(stdin io.Reader) configOption { + return func(c *Config) { + c.stdin = stdin + } +} + +func withStdout(stdout io.Writer) configOption { + return func(c *Config) { + c.stdout = stdout + } +} + +func withTestFS(fs vfs.FS) configOption { + return func(c *Config) { + c.fs = fs + c.mutator = chezmoi.NewVerboseMutator(os.Stdout, chezmoi.NewFSMutator(fs), false, 0) + } +} + +func withVerbose(verbose bool) configOption { + return func(c *Config) { + c.Verbose = verbose + } +} + +func withTestUser(username string) configOption { + return func(c *Config) { + homeDir := filepath.Join("/", "home", username) + c.SourceDir = filepath.Join(homeDir, ".local", "share", "chezmoi") + c.DestDir = homeDir + c.Umask = 022 + c.bds = &xdg.BaseDirectorySpecification{ + ConfigHome: filepath.Join(homeDir, ".config"), + DataHome: filepath.Join(homeDir, ".local"), + CacheHome: filepath.Join(homeDir, ".cache"), + RuntimeDir: filepath.Join(homeDir, ".run"), + } } } diff --git a/cmd/diff_posix_test.go b/cmd/diff_posix_test.go index 54d596db4c2..75af88cdee6 100644 --- a/cmd/diff_posix_test.go +++ b/cmd/diff_posix_test.go @@ -10,7 +10,6 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/twpayne/chezmoi/internal/chezmoi" vfs "github.com/twpayne/go-vfs" "github.com/twpayne/go-vfs/vfst" ) @@ -28,14 +27,10 @@ func TestDiffDoesNotRunScript(t *testing.T) { "/home/user/.local/share/chezmoi/run_true": "#!/bin/sh\necho foo >>" + filepath.Join(tempDir, "evidence") + "\n", }, )) - c := &Config{ - fs: fs, - mutator: chezmoi.NewVerboseMutator(os.Stdout, chezmoi.NewFSMutator(fs), false, 0), - SourceDir: "/home/user/.local/share/chezmoi", - DestDir: "/", - Umask: 022, - bds: newTestBaseDirectorySpecification("/home/user"), - } + c := newConfig( + withTestFS(fs), + withTestUser("user"), + ) assert.NoError(t, c.runDiffCmd(nil, nil)) vfst.RunTests(t, vfs.OSFS, "", vfst.TestPath(filepath.Join(tempDir, "evidence"), diff --git a/cmd/dump_test.go b/cmd/dump_test.go index d518892551f..cc992136146 100644 --- a/cmd/dump_test.go +++ b/cmd/dump_test.go @@ -4,13 +4,11 @@ import ( "bytes" "encoding/json" "fmt" - "os" "path/filepath" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/twpayne/chezmoi/internal/chezmoi" "github.com/twpayne/go-vfs/vfst" ) @@ -22,17 +20,15 @@ func TestDumpCmd(t *testing.T) { require.NoError(t, err) defer cleanup() stdout := &bytes.Buffer{} - c := &Config{ - fs: fs, - mutator: chezmoi.NewVerboseMutator(os.Stdout, chezmoi.NewFSMutator(fs), false, 0), - SourceDir: "/home/user/.local/share/chezmoi", - Umask: 022, - dump: dumpCmdConfig{ + c := newConfig( + withTestFS(fs), + withTestUser("user"), + withDumpCmdConfig(dumpCmdConfig{ format: "json", recursive: true, - }, - stdout: stdout, - } + }), + withStdout(stdout), + ) assert.NoError(t, c.runDumpCmd(nil, nil)) fmt.Println(stdout.String()) var actual interface{} @@ -40,14 +36,14 @@ func TestDumpCmd(t *testing.T) { expected := []interface{}{ map[string]interface{}{ "type": "dir", - "sourcePath": filepath.Join("/home", "user", ".local", "share", "chezmoi", "dir"), + "sourcePath": filepath.Join("/", "home", "user", ".local", "share", "chezmoi", "dir"), "targetPath": "dir", "exact": false, "perm": float64(0755), "entries": []interface{}{ map[string]interface{}{ "type": "file", - "sourcePath": filepath.Join("/home", "user", ".local", "share", "chezmoi", "dir", "file"), + "sourcePath": filepath.Join("/", "home", "user", ".local", "share", "chezmoi", "dir", "file"), "targetPath": filepath.Join("dir", "file"), "empty": false, "encrypted": false, @@ -59,7 +55,7 @@ func TestDumpCmd(t *testing.T) { }, map[string]interface{}{ "type": "symlink", - "sourcePath": filepath.Join("/home", "user", ".local", "share", "chezmoi", "symlink_symlink"), + "sourcePath": filepath.Join("/", "home", "user", ".local", "share", "chezmoi", "symlink_symlink"), "targetPath": "symlink", "template": false, "linkname": "target", diff --git a/cmd/import_test.go b/cmd/import_test.go index f3bb02ec214..47ffe36b9c1 100644 --- a/cmd/import_test.go +++ b/cmd/import_test.go @@ -3,12 +3,10 @@ package cmd import ( "archive/tar" "bytes" - "os" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/twpayne/chezmoi/internal/chezmoi" "github.com/twpayne/go-vfs/vfst" ) @@ -41,12 +39,11 @@ func TestImportCmd(t *testing.T) { require.NoError(t, err) defer cleanup() - c := &Config{ - fs: fs, - mutator: chezmoi.NewVerboseMutator(os.Stdout, chezmoi.NewFSMutator(fs), false, 0), - SourceDir: "/home/user/.local/share/chezmoi", - stdin: b, - } + c := newConfig( + withTestFS(fs), + withTestUser("user"), + withStdin(b), + ) assert.NoError(t, c.runImportCmd(nil, nil)) vfst.RunTests(t, fs, "test", diff --git a/cmd/init_test.go b/cmd/init_test.go index a5fe27ddc81..c0a22e676d5 100644 --- a/cmd/init_test.go +++ b/cmd/init_test.go @@ -8,12 +8,9 @@ import ( "strings" "testing" - "github.com/Masterminds/sprig" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/twpayne/chezmoi/internal/chezmoi" "github.com/twpayne/go-vfs/vfst" - xdg "github.com/twpayne/go-xdg/v3" ) func TestCreateConfigFile(t *testing.T) { @@ -29,17 +26,13 @@ func TestCreateConfigFile(t *testing.T) { require.NoError(t, err) defer cleanup() - conf := &Config{ - fs: fs, - mutator: chezmoi.NewVerboseMutator(os.Stdout, chezmoi.NewFSMutator(fs), false, 0), - SourceDir: "/home/user/.local/share/chezmoi", - templateFuncs: sprig.HermeticTxtFuncMap(), - stdin: bytes.NewBufferString("john.smith@company.com \n"), - stdout: &bytes.Buffer{}, - bds: xdg.NewTestBaseDirectorySpecification("/home/user", nil), - } + c := newConfig( + withTestFS(fs), + withTestUser("user"), + withStdin(bytes.NewBufferString("john.smith@company.com \n")), + ) - require.NoError(t, conf.createConfigFile()) + require.NoError(t, c.createConfigFile()) vfst.RunTests(t, fs, "", vfst.TestPath("/home/user/.config/chezmoi/chezmoi.yaml", @@ -58,7 +51,7 @@ func TestCreateConfigFile(t *testing.T) { "email": "john.smith@company.com", "mailtourl": "mailto:john.smith@company.com", "os": runtime.GOOS, - }, conf.Data) + }, c.Data) } func TestInit(t *testing.T) { @@ -68,15 +61,10 @@ func TestInit(t *testing.T) { require.NoError(t, err) defer cleanup() - c := &Config{ - fs: fs, - mutator: chezmoi.NewVerboseMutator(os.Stdout, chezmoi.NewFSMutator(fs), false, 0), - SourceDir: "/home/user/.local/share/chezmoi", - SourceVCS: sourceVCSConfig{ - Command: "git", - }, - bds: xdg.NewTestBaseDirectorySpecification("/home/user", func(string) string { return "" }), - } + c := newConfig( + withTestFS(fs), + withTestUser("user"), + ) require.NoError(t, c.runInitCmd(nil, nil)) vfst.RunTests(t, fs, "", @@ -99,15 +87,10 @@ func TestInitRepo(t *testing.T) { require.NoError(t, err) defer cleanup() - c := &Config{ - fs: fs, - mutator: chezmoi.NewVerboseMutator(os.Stdout, chezmoi.NewFSMutator(fs), false, 0), - SourceDir: "/home/user/.local/share/chezmoi", - SourceVCS: sourceVCSConfig{ - Command: "git", - }, - bds: xdg.NewTestBaseDirectorySpecification("/home/user", func(string) string { return "" }), - } + c := newConfig( + withTestFS(fs), + withTestUser("user"), + ) wd, err := os.Getwd() require.NoError(t, err) diff --git a/cmd/root.go b/cmd/root.go index ac7a9f34263..a02f82fdc95 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -5,7 +5,6 @@ import ( "os" "strings" - "github.com/Masterminds/sprig" "github.com/coreos/go-semver/semver" "github.com/spf13/cobra" "github.com/spf13/viper" @@ -15,19 +14,7 @@ import ( "golang.org/x/crypto/ssh/terminal" ) -var config = Config{ - Umask: permValue(getUmask()), - Color: "auto", - SourceVCS: sourceVCSConfig{ - Command: "git", - }, - Merge: mergeConfig{ - Command: "vimdiff", - }, - maxDiffDataSize: 1 * 1024 * 1024, // 1MB - templateFuncs: sprig.HermeticTxtFuncMap(), - scriptStateBucket: []byte("script"), -} +var config = newConfig() // Version information. var ( diff --git a/cmd/secretgeneric_posix_test.go b/cmd/secretgeneric_posix_test.go index b49b26cc72f..52d1513f14f 100644 --- a/cmd/secretgeneric_posix_test.go +++ b/cmd/secretgeneric_posix_test.go @@ -5,21 +5,19 @@ package cmd import "github.com/twpayne/chezmoi/internal/chezmoi" func getSecretTestConfig() (*Config, []string) { - return &Config{ - mutator: chezmoi.NullMutator{}, - GenericSecret: genericSecretCmdConfig{ - Command: "date", - }, - }, - []string{"+%Y-%M-%DT%H:%M:%SZ"} + return newConfig( + withMutator(chezmoi.NullMutator{}), + withGenericSecretCmdConfig(genericSecretCmdConfig{ + Command: "date", + }), + ), []string{"+%Y-%M-%DT%H:%M:%SZ"} } func getSecretJSONTestConfig() (*Config, []string) { - return &Config{ - mutator: chezmoi.NullMutator{}, - GenericSecret: genericSecretCmdConfig{ - Command: "date", - }, - }, - []string{`+{"date":"%Y-%M-%DT%H:%M:%SZ"}`} + return newConfig( + withMutator(chezmoi.NullMutator{}), + withGenericSecretCmdConfig(genericSecretCmdConfig{ + Command: "date", + }), + ), []string{`+{"date":"%Y-%M-%DT%H:%M:%SZ"}`} } diff --git a/cmd/secretgeneric_windows_test.go b/cmd/secretgeneric_windows_test.go index 0a7425518d6..ab347137327 100644 --- a/cmd/secretgeneric_windows_test.go +++ b/cmd/secretgeneric_windows_test.go @@ -7,21 +7,21 @@ import "github.com/twpayne/chezmoi/internal/chezmoi" func getSecretTestConfig() (*Config, []string) { // Windows doesn't (usually) have "date", but powershell is included with // all versions of Windows v7 or newer. - return &Config{ - mutator: chezmoi.NullMutator{}, - GenericSecret: genericSecretCmdConfig{ + return newConfig( + withMutator(chezmoi.NullMutator{}), + withGenericSecretCmdConfig(genericSecretCmdConfig{ Command: "powershell.exe", - }, - }, + }), + ), []string{"-NoProfile", "-NonInteractive", "-Command", "Get-Date"} } func getSecretJSONTestConfig() (*Config, []string) { - return &Config{ - mutator: chezmoi.NullMutator{}, - GenericSecret: genericSecretCmdConfig{ + return newConfig( + withMutator(chezmoi.NullMutator{}), + withGenericSecretCmdConfig(genericSecretCmdConfig{ Command: "powershell.exe", - }, - }, + }), + ), []string{"-NoProfile", "-NonInteractive", "-Command", "Get-Date | ConvertTo-Json"} }