diff --git a/internal/chezmoi/realsystem.go b/internal/chezmoi/realsystem.go index aa9d599a786..51cdcd0726b 100644 --- a/internal/chezmoi/realsystem.go +++ b/internal/chezmoi/realsystem.go @@ -123,6 +123,9 @@ func (s *RealSystem) RunScript(scriptname RelPath, dir AbsPath, data []byte, opt if err != nil { return err } + cmd.Env = append(os.Environ(), + "CHEZMOI_SOURCE_FILE="+options.SourceRelPath.String(), + ) cmd.Stdin = os.Stdin cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr diff --git a/internal/chezmoi/sourcestate.go b/internal/chezmoi/sourcestate.go index 2ee3501c807..a0c5147b6a4 100644 --- a/internal/chezmoi/sourcestate.go +++ b/internal/chezmoi/sourcestate.go @@ -1855,6 +1855,9 @@ func (s *SourceState) newModifyTargetStateEntryFunc( // Run the modifier on the current contents. cmd := interpreter.ExecCommand(tempFile.Name()) + cmd.Env = append(os.Environ(), + "CHEZMOI_SOURCE_FILE="+sourceRelPath.String(), + ) cmd.Stdin = bytes.NewReader(currentContents) cmd.Stderr = os.Stderr contents, err = chezmoilog.LogCmdOutput(cmd) @@ -1911,6 +1914,7 @@ func (s *SourceState) newScriptTargetStateEntryFunc( sourceAttr: SourceAttr{ Condition: fileAttr.Condition, }, + sourceRelPath: sourceRelPath, }, nil } } diff --git a/internal/chezmoi/sourcestate_test.go b/internal/chezmoi/sourcestate_test.go index 840c578c7ac..8e7ee901993 100644 --- a/internal/chezmoi/sourcestate_test.go +++ b/internal/chezmoi/sourcestate_test.go @@ -1016,6 +1016,7 @@ func TestSourceStateRead(t *testing.T) { sourceAttr: SourceAttr{ Condition: ScriptConditionAlways, }, + sourceRelPath: NewSourceRelPath("run_script"), }, }, }), @@ -1046,6 +1047,7 @@ func TestSourceStateRead(t *testing.T) { sourceAttr: SourceAttr{ Condition: ScriptConditionAlways, }, + sourceRelPath: NewSourceRelPath("run_script"), }, }, }), diff --git a/internal/chezmoi/system.go b/internal/chezmoi/system.go index 0a9e7c1160c..31547db8ced 100644 --- a/internal/chezmoi/system.go +++ b/internal/chezmoi/system.go @@ -14,8 +14,9 @@ import ( ) type RunScriptOptions struct { - Interpreter *Interpreter - Condition ScriptCondition + Interpreter *Interpreter + Condition ScriptCondition + SourceRelPath SourceRelPath } // A System reads from and writes to a filesystem, runs scripts, and persists diff --git a/internal/chezmoi/targetstateentry.go b/internal/chezmoi/targetstateentry.go index 65a3897e2cd..27779bec00b 100644 --- a/internal/chezmoi/targetstateentry.go +++ b/internal/chezmoi/targetstateentry.go @@ -52,10 +52,11 @@ type TargetStateRemove struct{} // A TargetStateScript represents the state of a script. type TargetStateScript struct { *lazyContents - name RelPath - interpreter *Interpreter - condition ScriptCondition - sourceAttr SourceAttr + name RelPath + interpreter *Interpreter + condition ScriptCondition + sourceAttr SourceAttr + sourceRelPath SourceRelPath } // A TargetStateSymlink represents the state of a symlink in the target state. @@ -333,8 +334,9 @@ func (t *TargetStateScript) Apply( runAt := time.Now().UTC() if !isEmpty(contents) { if err := system.RunScript(t.name, actualStateEntry.Path().Dir(), contents, RunScriptOptions{ - Condition: t.condition, - Interpreter: t.interpreter, + Condition: t.condition, + Interpreter: t.interpreter, + SourceRelPath: t.sourceRelPath, }); err != nil { return false, err } diff --git a/internal/cmd/testdata/scripts/issue2934.txtar b/internal/cmd/testdata/scripts/issue2934.txtar index 973d72be04f..c5b6a77737b 100644 --- a/internal/cmd/testdata/scripts/issue2934.txtar +++ b/internal/cmd/testdata/scripts/issue2934.txtar @@ -1,10 +1,24 @@ -[windows] skip +[windows] skip 'UNIX only' # test that chezmoi sets environment variables for modify_ scripts -exec chezmoi apply -grep ^${CHEZMOISOURCEDIR@R}$ $HOME/.modify +exec chezmoi apply $HOME${/}.modify +grep ^CHEZMOI_SOURCE_DIR=${CHEZMOISOURCEDIR@R}$ $HOME/.modify +grep ^CHEZMOI_SOURCE_FILE=modify_dot_modify$ $HOME/.modify + +chhome home2/user + +# test that CHEZMOI_SOURCE_FILE environment variable is set when running scripts +exec chezmoi apply $HOME${/}script.sh +stdout ^CHEZMOI_SOURCE_DIR=${CHEZMOISOURCEDIR@R}$ +stdout ^CHEZMOI_SOURCE_FILE=run_script.sh$ -- home/user/.local/share/chezmoi/modify_dot_modify -- #!/bin/sh -echo ${CHEZMOI_SOURCE_DIR} +echo CHEZMOI_SOURCE_DIR=${CHEZMOI_SOURCE_DIR} +echo CHEZMOI_SOURCE_FILE=${CHEZMOI_SOURCE_FILE} +-- home2/user/.local/share/chezmoi/run_script.sh -- +#!/bin/sh + +echo CHEZMOI_SOURCE_DIR=${CHEZMOI_SOURCE_DIR} +echo CHEZMOI_SOURCE_FILE=${CHEZMOI_SOURCE_FILE}