From 7203d6bfce13edea2dd5d7e24face022ef0bf461 Mon Sep 17 00:00:00 2001 From: Tom Payne Date: Tue, 10 Oct 2023 18:28:32 +0200 Subject: [PATCH] feat: Set CHEZMOI_ and scriptEnv env vars for all invoked commands --- .../configuration-file/variables.md.yaml | 2 +- internal/chezmoi/archivereadersystem.go | 5 ----- internal/chezmoi/debugsystem.go | 5 ----- internal/chezmoi/dryrunsystem.go | 5 ----- internal/chezmoi/dumpsystem.go | 5 ----- internal/chezmoi/erroronwritesystem.go | 5 ----- internal/chezmoi/externaldiffsystem.go | 5 ----- internal/chezmoi/gitdiffsystem.go | 5 ----- internal/chezmoi/nullsystem.go | 5 ----- internal/chezmoi/readonlysystem.go | 5 ----- internal/chezmoi/realsystem.go | 11 ---------- internal/chezmoi/realsystem_unix.go | 1 - internal/chezmoi/sourcestate.go | 9 -------- internal/chezmoi/system.go | 1 - internal/chezmoi/tarwritersystem.go | 5 ----- internal/chezmoi/zipwritersystem.go | 5 ----- internal/cmd/cdcmd.go | 3 ++- internal/cmd/config.go | 22 ++++++------------- internal/cmd/testdata/scripts/issue3268.txtar | 12 ++++++++++ 19 files changed, 22 insertions(+), 94 deletions(-) create mode 100644 internal/cmd/testdata/scripts/issue3268.txtar diff --git a/assets/chezmoi.io/docs/reference/configuration-file/variables.md.yaml b/assets/chezmoi.io/docs/reference/configuration-file/variables.md.yaml index 5e3875ad4ce..3ad788ae3f0 100644 --- a/assets/chezmoi.io/docs/reference/configuration-file/variables.md.yaml +++ b/assets/chezmoi.io/docs/reference/configuration-file/variables.md.yaml @@ -39,7 +39,7 @@ sections: description: Display progress bars scriptEnv: type: object - description: Extra environment variables for scripts + description: Extra environment variables for scripts and commands scriptTempDir: description: Temporary directory for scripts sourceDir: diff --git a/internal/chezmoi/archivereadersystem.go b/internal/chezmoi/archivereadersystem.go index 5b11e6834ab..c4ffe604872 100644 --- a/internal/chezmoi/archivereadersystem.go +++ b/internal/chezmoi/archivereadersystem.go @@ -109,8 +109,3 @@ func (s *ArchiveReaderSystem) Readlink(name AbsPath) (string, error) { } return "", fs.ErrNotExist } - -// UnderlyingSystem implements System.UnderlyingSystem. -func (s *ArchiveReaderSystem) UnderlyingSystem() System { - return s -} diff --git a/internal/chezmoi/debugsystem.go b/internal/chezmoi/debugsystem.go index 2e2f3eefb5e..beb03b80cfd 100644 --- a/internal/chezmoi/debugsystem.go +++ b/internal/chezmoi/debugsystem.go @@ -191,11 +191,6 @@ func (s *DebugSystem) UnderlyingFS() vfs.FS { return s.system.UnderlyingFS() } -// UnderlyingSystem implements System.UnderlyingSystem. -func (s *DebugSystem) UnderlyingSystem() System { - return s.system -} - // WriteFile implements System.WriteFile. func (s *DebugSystem) WriteFile(name AbsPath, data []byte, perm fs.FileMode) error { err := s.system.WriteFile(name, data, perm) diff --git a/internal/chezmoi/dryrunsystem.go b/internal/chezmoi/dryrunsystem.go index fd0aac4d922..f8abfbc6931 100644 --- a/internal/chezmoi/dryrunsystem.go +++ b/internal/chezmoi/dryrunsystem.go @@ -127,11 +127,6 @@ func (s *DryRunSystem) UnderlyingFS() vfs.FS { return s.system.UnderlyingFS() } -// UnderlyingSystem implements System.UnderlyingSystem. -func (s *DryRunSystem) UnderlyingSystem() System { - return s.system -} - // WriteFile implements System.WriteFile. func (s *DryRunSystem) WriteFile(AbsPath, []byte, fs.FileMode) error { s.setModified() diff --git a/internal/chezmoi/dumpsystem.go b/internal/chezmoi/dumpsystem.go index 44d31491f95..e44d5d5cb48 100644 --- a/internal/chezmoi/dumpsystem.go +++ b/internal/chezmoi/dumpsystem.go @@ -124,11 +124,6 @@ func (s *DumpSystem) UnderlyingFS() vfs.FS { return nil } -// UnderlyingSystem implements System.UnderlyingSystem. -func (s *DumpSystem) UnderlyingSystem() System { - return s -} - // WriteFile implements System.WriteFile. func (s *DumpSystem) WriteFile(filename AbsPath, data []byte, perm fs.FileMode) error { return s.setData(filename.String(), &fileData{ diff --git a/internal/chezmoi/erroronwritesystem.go b/internal/chezmoi/erroronwritesystem.go index 94dc3f04271..0df465b38cf 100644 --- a/internal/chezmoi/erroronwritesystem.go +++ b/internal/chezmoi/erroronwritesystem.go @@ -114,11 +114,6 @@ func (s *ErrorOnWriteSystem) UnderlyingFS() vfs.FS { return s.system.UnderlyingFS() } -// UnderlyingSystem implements System.UnderlyingSystem. -func (s *ErrorOnWriteSystem) UnderlyingSystem() System { - return s.system -} - // WriteFile implements System.WriteFile. func (s *ErrorOnWriteSystem) WriteFile(AbsPath, []byte, fs.FileMode) error { return s.err diff --git a/internal/chezmoi/externaldiffsystem.go b/internal/chezmoi/externaldiffsystem.go index 14d4178320d..6b63a4e5d4c 100644 --- a/internal/chezmoi/externaldiffsystem.go +++ b/internal/chezmoi/externaldiffsystem.go @@ -224,11 +224,6 @@ func (s *ExternalDiffSystem) UnderlyingFS() vfs.FS { return s.system.UnderlyingFS() } -// UnderlyingSystem implements System.UnderlyingSystem. -func (s *ExternalDiffSystem) UnderlyingSystem() System { - return s.system -} - // WriteFile implements System.WriteFile. func (s *ExternalDiffSystem) WriteFile(filename AbsPath, data []byte, perm fs.FileMode) error { if s.filter.IncludeEntryTypeBits(EntryTypeFiles) { diff --git a/internal/chezmoi/gitdiffsystem.go b/internal/chezmoi/gitdiffsystem.go index 6e6bfc7468c..f0e7a39152c 100644 --- a/internal/chezmoi/gitdiffsystem.go +++ b/internal/chezmoi/gitdiffsystem.go @@ -247,11 +247,6 @@ func (s *GitDiffSystem) UnderlyingFS() vfs.FS { return s.system.UnderlyingFS() } -// UnderlyingSystem implements System.UnderlyingSystem. -func (s *GitDiffSystem) UnderlyingSystem() System { - return s.system -} - // WriteFile implements System.WriteFile. func (s *GitDiffSystem) WriteFile(filename AbsPath, data []byte, perm fs.FileMode) error { if s.filter.IncludeEntryTypeBits(EntryTypeFiles) { diff --git a/internal/chezmoi/nullsystem.go b/internal/chezmoi/nullsystem.go index 3197f6ab0bc..ddb7033b370 100644 --- a/internal/chezmoi/nullsystem.go +++ b/internal/chezmoi/nullsystem.go @@ -4,8 +4,3 @@ type NullSystem struct { emptySystemMixin noUpdateSystemMixin } - -// UnderlyingSystem implements System.UnderlyingSystem. -func (s *NullSystem) UnderlyingSystem() System { - return s -} diff --git a/internal/chezmoi/readonlysystem.go b/internal/chezmoi/readonlysystem.go index 6a57482c2f0..46e8c42f898 100644 --- a/internal/chezmoi/readonlysystem.go +++ b/internal/chezmoi/readonlysystem.go @@ -58,8 +58,3 @@ func (s *ReadOnlySystem) Stat(name AbsPath) (fs.FileInfo, error) { func (s *ReadOnlySystem) UnderlyingFS() vfs.FS { return s.system.UnderlyingFS() } - -// UnderlyingSystem implements System.UnderlyingSystem. -func (s *ReadOnlySystem) UnderlyingSystem() System { - return s.system -} diff --git a/internal/chezmoi/realsystem.go b/internal/chezmoi/realsystem.go index f4df6f08e4c..a93330983e0 100644 --- a/internal/chezmoi/realsystem.go +++ b/internal/chezmoi/realsystem.go @@ -128,7 +128,6 @@ func (s *RealSystem) RunScript( if err != nil { return err } - cmd.Env = s.scriptEnv cmd.Stdin = os.Stdin cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr @@ -136,11 +135,6 @@ func (s *RealSystem) RunScript( return s.RunCmd(cmd) } -// SetScriptEnv sets the environment variables for scripts. -func (s *RealSystem) SetScriptEnv(scriptEnv []string) { - s.scriptEnv = scriptEnv -} - // Stat implements System.Stat. func (s *RealSystem) Stat(name AbsPath) (fs.FileInfo, error) { return s.fileSystem.Stat(name.String()) @@ -151,11 +145,6 @@ func (s *RealSystem) UnderlyingFS() vfs.FS { return s.fileSystem } -// UnderlyingSystem implements System.UnderlyingSystem. -func (s *RealSystem) UnderlyingSystem() System { - return s -} - // getScriptWorkingDir returns the script's working directory. // // If this is a before_ script then the requested working directory may not diff --git a/internal/chezmoi/realsystem_unix.go b/internal/chezmoi/realsystem_unix.go index e291f20cdcc..b837824d5a7 100644 --- a/internal/chezmoi/realsystem_unix.go +++ b/internal/chezmoi/realsystem_unix.go @@ -21,7 +21,6 @@ type RealSystem struct { safe bool createScriptTempDirOnce sync.Once scriptTempDir AbsPath - scriptEnv []string devCache map[AbsPath]uint // devCache maps directories to device numbers. tempDirCache map[uint]string // tempDirCache maps device numbers to renameio temporary directories. } diff --git a/internal/chezmoi/sourcestate.go b/internal/chezmoi/sourcestate.go index 735e2ce3dd1..ca20dfec902 100644 --- a/internal/chezmoi/sourcestate.go +++ b/internal/chezmoi/sourcestate.go @@ -124,7 +124,6 @@ type SourceState struct { defaultTemplateData map[string]any userTemplateData map[string]any priorityTemplateData map[string]any - scriptEnv []string templateData map[string]any templateFuncs template.FuncMap templateOptions []string @@ -213,13 +212,6 @@ func WithReadTemplateData(readTemplateData bool) SourceStateOption { } } -// WithScriptEnv sets the script environment variables. -func WithScriptEnv(scriptEnv []string) SourceStateOption { - return func(s *SourceState) { - s.scriptEnv = scriptEnv - } -} - // WithSourceDir sets the source directory. func WithSourceDir(sourceDirAbsPath AbsPath) SourceStateOption { return func(s *SourceState) { @@ -1911,7 +1903,6 @@ func (s *SourceState) newModifyTargetStateEntryFunc( // Run the modifier on the current contents. cmd := interpreter.ExecCommand(tempFile.Name()) - cmd.Env = s.scriptEnv cmd.Stdin = bytes.NewReader(currentContents) cmd.Stderr = os.Stderr contents, err = chezmoilog.LogCmdOutput(cmd) diff --git a/internal/chezmoi/system.go b/internal/chezmoi/system.go index 2e69713b097..7302b3437f4 100644 --- a/internal/chezmoi/system.go +++ b/internal/chezmoi/system.go @@ -38,7 +38,6 @@ type System interface { //nolint:interfacebloat RunScript(scriptname RelPath, dir AbsPath, data []byte, options RunScriptOptions) error Stat(name AbsPath) (fs.FileInfo, error) UnderlyingFS() vfs.FS - UnderlyingSystem() System WriteFile(filename AbsPath, data []byte, perm fs.FileMode) error WriteSymlink(oldname string, newname AbsPath) error } diff --git a/internal/chezmoi/tarwritersystem.go b/internal/chezmoi/tarwritersystem.go index 97fcfd81f74..d66957783e5 100644 --- a/internal/chezmoi/tarwritersystem.go +++ b/internal/chezmoi/tarwritersystem.go @@ -52,11 +52,6 @@ func (s *TarWriterSystem) RunScript( return s.WriteFile(NewAbsPath(scriptname.String()), data, 0o700) } -// UnderlyingSystem implements System.UnderlyingSystem. -func (s *TarWriterSystem) UnderlyingSystem() System { - return s -} - // WriteFile implements System.WriteFile. func (s *TarWriterSystem) WriteFile(filename AbsPath, data []byte, perm fs.FileMode) error { header := s.headerTemplate diff --git a/internal/chezmoi/zipwritersystem.go b/internal/chezmoi/zipwritersystem.go index 766819460b3..c438413c138 100644 --- a/internal/chezmoi/zipwritersystem.go +++ b/internal/chezmoi/zipwritersystem.go @@ -57,11 +57,6 @@ func (s *ZIPWriterSystem) RunScript( return s.WriteFile(NewAbsPath(scriptname.String()), data, 0o700) } -// UnderlyingSystem implements System.UnderlyingSystem. -func (s *ZIPWriterSystem) UnderlyingSystem() System { - return s -} - // WriteFile implements System.WriteFile. func (s *ZIPWriterSystem) WriteFile(filename AbsPath, data []byte, perm fs.FileMode) error { fileHeader := zip.FileHeader{ diff --git a/internal/cmd/cdcmd.go b/internal/cmd/cdcmd.go index 74dd504b3cb..a9e88678f92 100644 --- a/internal/cmd/cdcmd.go +++ b/internal/cmd/cdcmd.go @@ -36,9 +36,10 @@ func (c *Config) newCDCmd() *cobra.Command { } func (c *Config) runCDCmd(cmd *cobra.Command, args []string) error { - if _, ok := os.LookupEnv("CHEZMOI"); ok { + if _, ok := os.LookupEnv("CHEZMOI_SUBSHELL"); ok { return errors.New("already in a chezmoi subshell") } + os.Setenv("CHEZMOI_SUBSHELL", "1") cdCommand, cdArgs, err := c.cdCommand() if err != nil { diff --git a/internal/cmd/config.go b/internal/cmd/config.go index ba5287994b7..67cc3c0d00d 100644 --- a/internal/cmd/config.go +++ b/internal/cmd/config.go @@ -232,7 +232,6 @@ type Config struct { sourceState *chezmoi.SourceState sourceStateErr error templateData *templateData - runEnv []string stdin io.Reader stdout io.Writer @@ -710,9 +709,7 @@ func (c *Config) createAndReloadConfigFile(cmd *cobra.Command) error { return err } c.templateData.sourceDir = sourceDirAbsPath - c.runEnv = append(c.runEnv, "CHEZMOI_SOURCE_DIR="+sourceDirAbsPath.String()) - realSystem := c.baseSystem.UnderlyingSystem().(*chezmoi.RealSystem) //nolint:forcetypeassert - realSystem.SetScriptEnv(c.runEnv) + os.Setenv("CHEZMOI_SOURCE_DIR", sourceDirAbsPath.String()) // Find config template, execute it, and create config file. configTemplate, err := c.findConfigTemplate() @@ -1705,7 +1702,6 @@ func (c *Config) newSourceState( chezmoi.WithLogger(&sourceStateLogger), chezmoi.WithMode(c.Mode), chezmoi.WithPriorityTemplateData(c.Data), - chezmoi.WithScriptEnv(c.runEnv), chezmoi.WithSourceDir(c.SourceDirAbsPath), chezmoi.WithSystem(c.sourceSystem), chezmoi.WithTemplateFuncs(c.templateFuncs), @@ -2091,9 +2087,8 @@ func (c *Config) persistentPreRunRootE(cmd *cobra.Command, args []string) error } } - scriptEnv := os.Environ() templateData := c.getTemplateData(cmd) - scriptEnv = append(scriptEnv, "CHEZMOI=1") + os.Setenv("CHEZMOI", "1") for key, value := range map[string]string{ "ARCH": templateData.arch, "ARGS": strings.Join(templateData.args, " "), @@ -2112,10 +2107,10 @@ func (c *Config) persistentPreRunRootE(cmd *cobra.Command, args []string) error "USERNAME": templateData.username, "WORKING_TREE": templateData.workingTree.String(), } { - scriptEnv = append(scriptEnv, "CHEZMOI_"+key+"="+value) + os.Setenv("CHEZMOI_"+key, value) } if c.Verbose { - scriptEnv = append(scriptEnv, "CHEZMOI_VERBOSE=1") + os.Setenv("CHEZMOI_VERBOSE", "1") } for groupKey, group := range map[string]map[string]any{ "KERNEL": templateData.kernel, @@ -2124,16 +2119,14 @@ func (c *Config) persistentPreRunRootE(cmd *cobra.Command, args []string) error "WINDOWS_VERSION": templateData.windowsVersion, } { for key, value := range group { - upperSnakeCaseKey := camelCaseToUpperSnakeCase(key) + key := "CHEZMOI_" + groupKey + "_" + camelCaseToUpperSnakeCase(key) valueStr := fmt.Sprintf("%s", value) - scriptEnv = append(scriptEnv, "CHEZMOI_"+groupKey+"_"+upperSnakeCaseKey+"="+valueStr) + os.Setenv(key, valueStr) } } for key, value := range c.ScriptEnv { - scriptEnv = append(scriptEnv, key+"="+value) + os.Setenv(key, value) } - c.runEnv = scriptEnv - realSystem.SetScriptEnv(scriptEnv) if command := c.Hooks[cmd.Name()].Pre; command.Command != "" { if err := c.run(c.homeDirAbsPath, command.Command, command.Args); err != nil { @@ -2326,7 +2319,6 @@ func (c *Config) run(dir chezmoi.AbsPath, name string, args []string) error { } cmd.Dir = dirRawAbsPath.String() } - cmd.Env = c.runEnv cmd.Stdin = c.stdin cmd.Stdout = c.stdout cmd.Stderr = c.stderr diff --git a/internal/cmd/testdata/scripts/issue3268.txtar b/internal/cmd/testdata/scripts/issue3268.txtar new file mode 100644 index 00000000000..b33956e7f21 --- /dev/null +++ b/internal/cmd/testdata/scripts/issue3268.txtar @@ -0,0 +1,12 @@ +[unix] chmod 755 bin/chezmoi-test-command + +# test that chezmoi sets CHEZMOI_ environment variables +exec chezmoi execute-template '{{ output "chezmoi-test-command" }}' +stdout 'CHEZMOI_SOURCE_DIR=.*/\.local/share/chezmoi\s?$' + +-- bin/chezmoi-test-command -- +#!/bin/sh + +echo CHEZMOI_SOURCE_DIR=${CHEZMOI_SOURCE_DIR} +-- bin/chezmoi-test-command.cmd -- +@echo CHEZMOI_SOURCE_DIR=%CHEZMOI_SOURCE_DIR%