Skip to content

Commit

Permalink
feat: Add common --parent-dirs/-P flag
Browse files Browse the repository at this point in the history
  • Loading branch information
twpayne committed Oct 12, 2024
1 parent 1b789a6 commit 56d8f40
Show file tree
Hide file tree
Showing 11 changed files with 81 additions and 36 deletions.
4 changes: 4 additions & 0 deletions assets/chezmoi.io/docs/reference/command-line-flags/common.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ Prompt before applying each target.

Write the output to *filename* instead of stdout.

## `-P`, `--parent-dirs`

Also perform command on all parent directories of *target*.

## `-r`, `--recursive`

Recurse into subdirectories, `true` by default.
Expand Down
9 changes: 6 additions & 3 deletions internal/cmd/applycmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@ import (
)

type applyCmdConfig struct {
filter *chezmoi.EntryTypeFilter
init bool
recursive bool
filter *chezmoi.EntryTypeFilter
init bool
parentDirs bool
recursive bool
}

func (c *Config) newApplyCmd() *cobra.Command {
Expand All @@ -30,6 +31,7 @@ func (c *Config) newApplyCmd() *cobra.Command {
applyCmd.Flags().VarP(c.apply.filter.Exclude, "exclude", "x", "Exclude entry types")
applyCmd.Flags().VarP(c.apply.filter.Include, "include", "i", "Include entry types")
applyCmd.Flags().BoolVar(&c.apply.init, "init", c.apply.init, "Recreate config file from template")
applyCmd.Flags().BoolVarP(&c.apply.parentDirs, "parent-dirs", "P", c.apply.parentDirs, "Apply all parent directories")
applyCmd.Flags().BoolVarP(&c.apply.recursive, "recursive", "r", c.apply.recursive, "Recurse into subdirectories")

return applyCmd
Expand All @@ -40,6 +42,7 @@ func (c *Config) runApplyCmd(cmd *cobra.Command, args []string) error {
cmd: cmd,
filter: c.apply.filter,
init: c.apply.init,
parentDirs: c.apply.parentDirs,
recursive: c.apply.recursive,
umask: c.Umask,
preApplyFunc: c.defaultPreApplyFunc,
Expand Down
9 changes: 5 additions & 4 deletions internal/cmd/archivecmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,10 +73,11 @@ func (c *Config) runArchiveCmd(cmd *cobra.Command, args []string) error {
return chezmoi.UnknownArchiveFormatError(format)
}
if err := c.applyArgs(cmd.Context(), archiveSystem, chezmoi.EmptyAbsPath, args, applyArgsOptions{
cmd: cmd,
filter: c.archive.filter,
init: c.archive.init,
recursive: c.archive.recursive,
cmd: cmd,
filter: c.archive.filter,
init: c.archive.init,
parentDirs: true,
recursive: c.archive.recursive,
}); err != nil {
return err
}
Expand Down
16 changes: 16 additions & 0 deletions internal/cmd/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ import (
"github.com/twpayne/chezmoi/v2/internal/chezmoierrors"
"github.com/twpayne/chezmoi/v2/internal/chezmoigit"
"github.com/twpayne/chezmoi/v2/internal/chezmoilog"
"github.com/twpayne/chezmoi/v2/internal/chezmoimaps"
"github.com/twpayne/chezmoi/v2/internal/chezmoiset"
)

Expand Down Expand Up @@ -564,6 +565,7 @@ type applyArgsOptions struct {
cmd *cobra.Command
filter *chezmoi.EntryTypeFilter
init bool
parentDirs bool
recursive bool
umask fs.FileMode
preApplyFunc chezmoi.PreApplyFunc
Expand Down Expand Up @@ -652,6 +654,20 @@ func (c *Config) applyArgs(
}
}

if options.parentDirs {
targetRelPathSet := make(map[chezmoi.RelPath]struct{})
for _, targetRelPath := range targetRelPaths {
targetRelPathSet[targetRelPath] = struct{}{}
components := targetRelPath.SplitAll()
for i := 1; i < len(components); i++ {
parentTargetRelPath := chezmoi.EmptyRelPath.Join(components[:i]...)
targetRelPathSet[parentTargetRelPath] = struct{}{}
}
}
targetRelPaths = chezmoimaps.Keys(targetRelPathSet)
sort.Sort(targetRelPaths)
}

applyOptions := chezmoi.ApplyOptions{
Filter: options.filter,
PreApplyFunc: options.preApplyFunc,
Expand Down
13 changes: 8 additions & 5 deletions internal/cmd/diffcmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ type diffCmdConfig struct {
ScriptContents bool `json:"scriptContents" mapstructure:"scriptContents" yaml:"scriptContents"`
include *chezmoi.EntryTypeSet
init bool
parentDirs bool
recursive bool
}

Expand All @@ -38,6 +39,7 @@ func (c *Config) newDiffCmd() *cobra.Command {
diffCmd.Flags().VarP(c.Diff.include, "include", "i", "Include entry types")
diffCmd.Flags().BoolVar(&c.Diff.init, "init", c.Diff.init, "Recreate config file from template")
diffCmd.Flags().StringVar(&c.Diff.Pager, "pager", c.Diff.Pager, "Set pager")
diffCmd.Flags().BoolVarP(&c.Diff.parentDirs, "parent-dirs", "P", c.apply.parentDirs, "Print the diff of all parent directories")
diffCmd.Flags().BoolVarP(&c.Diff.recursive, "recursive", "r", c.Diff.recursive, "Recurse into subdirectories")
diffCmd.Flags().BoolVar(&c.Diff.Reverse, "reverse", c.Diff.Reverse, "Reverse the direction of the diff")
diffCmd.Flags().BoolVar(&c.Diff.ScriptContents, "script-contents", c.Diff.ScriptContents, "Show script contents")
Expand All @@ -47,10 +49,11 @@ func (c *Config) newDiffCmd() *cobra.Command {

func (c *Config) runDiffCmd(cmd *cobra.Command, args []string) (err error) {
return c.applyArgs(cmd.Context(), c.destSystem, c.DestDirAbsPath, args, applyArgsOptions{
cmd: cmd,
filter: chezmoi.NewEntryTypeFilter(c.Diff.include.Bits(), c.Diff.Exclude.Bits()),
init: c.Diff.init,
recursive: c.Diff.recursive,
umask: c.Umask,
cmd: cmd,
filter: chezmoi.NewEntryTypeFilter(c.Diff.include.Bits(), c.Diff.Exclude.Bits()),
init: c.Diff.init,
parentDirs: c.Diff.parentDirs,
recursive: c.Diff.recursive,
umask: c.Umask,
})
}
19 changes: 11 additions & 8 deletions internal/cmd/dumpcmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@ import (
)

type dumpCmdConfig struct {
filter *chezmoi.EntryTypeFilter
init bool
recursive bool
filter *chezmoi.EntryTypeFilter
init bool
parentDirs bool
recursive bool
}

func (c *Config) newDumpCmd() *cobra.Command {
Expand All @@ -30,6 +31,7 @@ func (c *Config) newDumpCmd() *cobra.Command {
dumpCmd.Flags().VarP(&c.Format, "format", "f", "Output format")
dumpCmd.Flags().VarP(c.dump.filter.Include, "include", "i", "Include entry types")
dumpCmd.Flags().BoolVar(&c.dump.init, "init", c.dump.init, "Recreate config file from template")
dumpCmd.Flags().BoolVarP(&c.dump.parentDirs, "parent-dirs", "P", c.dump.parentDirs, "Dump all parent directories")
dumpCmd.Flags().BoolVarP(&c.dump.recursive, "recursive", "r", c.dump.recursive, "Recurse into subdirectories")

return dumpCmd
Expand All @@ -38,11 +40,12 @@ func (c *Config) newDumpCmd() *cobra.Command {
func (c *Config) runDumpCmd(cmd *cobra.Command, args []string) error {
dumpSystem := chezmoi.NewDumpSystem()
if err := c.applyArgs(cmd.Context(), dumpSystem, chezmoi.EmptyAbsPath, args, applyArgsOptions{
cmd: cmd,
filter: c.dump.filter,
init: c.dump.init,
recursive: c.dump.recursive,
umask: c.Umask,
cmd: cmd,
filter: c.dump.filter,
init: c.dump.init,
parentDirs: c.dump.parentDirs,
recursive: c.dump.recursive,
umask: c.Umask,
}); err != nil {
return err
}
Expand Down
13 changes: 8 additions & 5 deletions internal/cmd/statuscmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,12 @@ import (
)

type statusCmdConfig struct {
Exclude *chezmoi.EntryTypeSet `json:"exclude" mapstructure:"exclude" yaml:"exclude"`
PathStyle *chezmoi.PathStyle `json:"pathStyle" mapstructure:"pathStyle" yaml:"pathStyle"`
include *chezmoi.EntryTypeSet
init bool
recursive bool
Exclude *chezmoi.EntryTypeSet `json:"exclude" mapstructure:"exclude" yaml:"exclude"`
PathStyle *chezmoi.PathStyle `json:"pathStyle" mapstructure:"pathStyle" yaml:"pathStyle"`
include *chezmoi.EntryTypeSet
init bool
parentDirs bool
recursive bool
}

func (c *Config) newStatusCmd() *cobra.Command {
Expand All @@ -40,6 +41,7 @@ func (c *Config) newStatusCmd() *cobra.Command {
statusCmd.Flags().VarP(c.Status.PathStyle, "path-style", "p", "Path style")
statusCmd.Flags().VarP(c.Status.include, "include", "i", "Include entry types")
statusCmd.Flags().BoolVar(&c.Status.init, "init", c.Status.init, "Recreate config file from template")
statusCmd.Flags().BoolVarP(&c.Status.parentDirs, "parent-dirs", "P", c.Status.parentDirs, "Show status of all parent directories")
statusCmd.Flags().BoolVarP(&c.Status.recursive, "recursive", "r", c.Status.recursive, "Recurse into subdirectories")

return statusCmd
Expand Down Expand Up @@ -88,6 +90,7 @@ func (c *Config) runStatusCmd(cmd *cobra.Command, args []string) error {
cmd: cmd,
filter: chezmoi.NewEntryTypeFilter(c.Status.include.Bits(), c.Status.Exclude.Bits()),
init: c.Status.init,
parentDirs: c.Status.parentDirs,
recursive: c.Status.recursive,
umask: c.Umask,
preApplyFunc: preApplyFunc,
Expand Down
6 changes: 6 additions & 0 deletions internal/cmd/testdata/scripts/issue3987.txtar
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# test that chezmoi apply --parent-dirs creates parent directories
exec chezmoi apply --parent-dirs $HOME/.config/nvim/after/queries/gotmpl/injections.scm
exists $HOME/.config/nvim/after/queries/gotmpl/injections.scm

-- home/user/.local/share/chezmoi/private_dot_config/nvim/after/queries/gotmpl/injections.scm --
# contents of injections.scm
4 changes: 2 additions & 2 deletions internal/cmd/testdata/scripts/scriptsubdir_unix.txtar
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@ $HOME
$HOME/dir
$HOME/anotherdir
-- golden/archive --
otherdir/script.sh
anotherdir/
anotherdir/script.sh
dir/
dir/script.sh
otherdir/
anotherdir/script.sh
otherdir/script.sh
-- golden/archive-openbsd --
otherdir/script.sh
anotherdir
Expand Down
3 changes: 3 additions & 0 deletions internal/cmd/updatecmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ type updateCmdConfig struct {
RecurseSubmodules bool `json:"recurseSubmodules" mapstructure:"recurseSubmodules" yaml:"recurseSubmodules"`
filter *chezmoi.EntryTypeFilter
init bool
parentDirs bool
recursive bool
}

Expand All @@ -40,6 +41,7 @@ func (c *Config) newUpdateCmd() *cobra.Command {
updateCmd.Flags().VarP(c.Update.filter.Exclude, "exclude", "x", "Exclude entry types")
updateCmd.Flags().VarP(c.Update.filter.Include, "include", "i", "Include entry types")
updateCmd.Flags().BoolVar(&c.Update.init, "init", c.Update.init, "Recreate config file from template")
updateCmd.Flags().BoolVarP(&c.Update.parentDirs, "parent-dirs", "P", c.Update.parentDirs, "Update all parent directories")
updateCmd.Flags().
BoolVar(&c.Update.RecurseSubmodules, "recurse-submodules", c.Update.RecurseSubmodules, "Recursively update submodules")
updateCmd.Flags().BoolVarP(&c.Update.recursive, "recursive", "r", c.Update.recursive, "Recurse into subdirectories")
Expand Down Expand Up @@ -92,6 +94,7 @@ func (c *Config) runUpdateCmd(cmd *cobra.Command, args []string) error {
cmd: cmd,
filter: c.Update.filter,
init: c.Update.init,
parentDirs: c.Update.parentDirs,
recursive: c.Update.recursive,
umask: c.Umask,
preApplyFunc: c.defaultPreApplyFunc,
Expand Down
21 changes: 12 additions & 9 deletions internal/cmd/verifycmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@ import (
)

type verifyCmdConfig struct {
Exclude *chezmoi.EntryTypeSet `json:"exclude" mapstructure:"exclude" yaml:"exclude"`
include *chezmoi.EntryTypeSet
init bool
recursive bool
Exclude *chezmoi.EntryTypeSet `json:"exclude" mapstructure:"exclude" yaml:"exclude"`
include *chezmoi.EntryTypeSet
init bool
parentDirs bool
recursive bool
}

func (c *Config) newVerifyCmd() *cobra.Command {
Expand All @@ -30,6 +31,7 @@ func (c *Config) newVerifyCmd() *cobra.Command {
verifyCmd.Flags().VarP(c.Verify.Exclude, "exclude", "x", "Exclude entry types")
verifyCmd.Flags().VarP(c.Verify.include, "include", "i", "Include entry types")
verifyCmd.Flags().BoolVar(&c.Verify.init, "init", c.Verify.init, "Recreate config file from template")
verifyCmd.Flags().BoolVarP(&c.Verify.parentDirs, "parent-dirs", "P", c.Verify.parentDirs, "Verify all parent directories")
verifyCmd.Flags().BoolVarP(&c.Verify.recursive, "recursive", "r", c.Verify.recursive, "Recurse into subdirectories")

return verifyCmd
Expand All @@ -38,10 +40,11 @@ func (c *Config) newVerifyCmd() *cobra.Command {
func (c *Config) runVerifyCmd(cmd *cobra.Command, args []string) error {
errorOnWriteSystem := chezmoi.NewErrorOnWriteSystem(c.destSystem, chezmoi.ExitCodeError(1))
return c.applyArgs(cmd.Context(), errorOnWriteSystem, c.DestDirAbsPath, args, applyArgsOptions{
cmd: cmd,
filter: chezmoi.NewEntryTypeFilter(c.Verify.include.Bits(), c.Verify.Exclude.Bits()),
init: c.Verify.init,
recursive: c.Verify.recursive,
umask: c.Umask,
cmd: cmd,
filter: chezmoi.NewEntryTypeFilter(c.Verify.include.Bits(), c.Verify.Exclude.Bits()),
init: c.Verify.init,
parentDirs: c.Verify.parentDirs,
recursive: c.Verify.recursive,
umask: c.Umask,
})
}

0 comments on commit 56d8f40

Please sign in to comment.