diff --git a/internal/chezmoi/sourcestate.go b/internal/chezmoi/sourcestate.go index b487fe0f666..15538651a09 100644 --- a/internal/chezmoi/sourcestate.go +++ b/internal/chezmoi/sourcestate.go @@ -321,6 +321,7 @@ type AddOptions struct { Filter *EntryTypeFilter // Entry type filter. OnIgnoreFunc func(RelPath) // Function to call when a target is ignored. PreAddFunc PreAddFunc // Function to be called before a source entry is added. + ConfigFileAbsPath AbsPath // Path to config file. ProtectedAbsPaths []AbsPath // Paths that must not be added. RemoveDir RelPath // Directory to remove before adding. ReplaceFunc ReplaceFunc // Function to be called before a source entry is replaced. @@ -360,12 +361,18 @@ func (s *SourceState) Add( destAbsPaths = destAbsPaths[:n] // Check for protected paths. + for _, destAbsPath := range destAbsPaths { + if destAbsPath == options.ConfigFileAbsPath { + format := "%s: cannot add chezmoi's config file to chezmoi, use a config file template instead" + return fmt.Errorf(format, destAbsPath) + } + } for _, destAbsPath := range destAbsPaths { for _, protectedAbsPath := range options.ProtectedAbsPaths { - if protectedAbsPath.Empty() { - continue - } - if strings.HasPrefix(destAbsPath.String(), protectedAbsPath.String()) { + switch { + case protectedAbsPath.Empty(): + // Do nothing. + case strings.HasPrefix(destAbsPath.String(), protectedAbsPath.String()): format := "%s: cannot add chezmoi file to chezmoi (%s is protected)" return fmt.Errorf(format, destAbsPath, protectedAbsPath) } diff --git a/internal/cmd/addcmd.go b/internal/cmd/addcmd.go index 779f0ffcb35..0ee7871ef7a 100644 --- a/internal/cmd/addcmd.go +++ b/internal/cmd/addcmd.go @@ -182,18 +182,19 @@ func (c *Config) runAddCmd(cmd *cobra.Command, args []string, sourceState *chezm c.destSystem, destAbsPathInfos, &chezmoi.AddOptions{ - AutoTemplate: c.Add.autoTemplate, - Create: c.Add.create, - Encrypt: c.Add.Encrypt, - EncryptedSuffix: c.encryption.EncryptedSuffix(), - Exact: c.Add.exact, - Filter: c.Add.filter, - OnIgnoreFunc: c.defaultOnIgnoreFunc, - PreAddFunc: c.defaultPreAddFunc, + AutoTemplate: c.Add.autoTemplate, + Create: c.Add.create, + Encrypt: c.Add.Encrypt, + EncryptedSuffix: c.encryption.EncryptedSuffix(), + Exact: c.Add.exact, + Filter: c.Add.filter, + OnIgnoreFunc: c.defaultOnIgnoreFunc, + PreAddFunc: c.defaultPreAddFunc, + ConfigFileAbsPath: c.getConfigFileAbsPath(), ProtectedAbsPaths: []chezmoi.AbsPath{ c.CacheDirAbsPath, c.WorkingTreeAbsPath, - c.getConfigFileAbsPath(), + c.getConfigFileAbsPath().Dir(), persistentStateFileAbsPath, c.sourceDirAbsPath, }, diff --git a/internal/cmd/testdata/scripts/issue2820.txtar b/internal/cmd/testdata/scripts/issue2820.txtar index d187dde8521..b95a09e9767 100644 --- a/internal/cmd/testdata/scripts/issue2820.txtar +++ b/internal/cmd/testdata/scripts/issue2820.txtar @@ -2,8 +2,12 @@ ! exec chezmoi add $CHEZMOISOURCEDIR stderr 'cannot add chezmoi file to chezmoi' -# test that chezmoi add refuses to add files in chezmoi's config directory -! exec chezmoi add $CHEZMOICONFIGDIR +# test that chezmoi add refuses to add chezmoi's config file +! exec chezmoi add $CHEZMOICONFIGDIR/chezmoi.toml +stderr 'cannot add chezmoi\x27s config file to chezmoi' + +# test that chezmoi add refuses to add files in chezmoi's cache directory +! exec chezmoi add $HOME/.cache/chezmoi stderr 'cannot add chezmoi file to chezmoi' # test that chezmoi add refuses to add files in chezmoi's source directory when already in that directory @@ -12,6 +16,7 @@ exists dot_file ! exec chezmoi add dot_file stderr 'cannot add chezmoi file to chezmoi' +-- home/user/.cache/chezmoi/.keep -- -- home/user/.config/chezmoi/chezmoi.toml -- -- home/user/.local/share/chezmoi/dot_file -- # contents of .file