Skip to content

Commit

Permalink
feat: Add initial --watch flag to edit command
Browse files Browse the repository at this point in the history
  • Loading branch information
twpayne committed Aug 19, 2022
1 parent 25ded1a commit ac0c759
Show file tree
Hide file tree
Showing 5 changed files with 86 additions and 18 deletions.
16 changes: 16 additions & 0 deletions assets/chezmoi.io/docs/reference/commands/edit.md
Expand Up @@ -22,6 +22,22 @@ Invoke the editor with a hard link to the source file with a name matching the
target filename. This can help the editor determine the type of the file
correctly. This is the default.

## `--watch`

Automatically apply changes when files are saved.

!!! warning

`--watch` is a beta feature with limitations. Known limitations include:

* Only works when `chezmoi edit` is invoked with arguments (i.e.
argument-free `chezmoi edit` is not supported).
* All edited files are applied when any file is saved.
* Only the edited files are watched, not any dependent files (e.g.
`.chezmoitemplates` and `include`d files in templates are not watched).
* Only works on operating systems supported by
[fsnotify](https://github.com/fsnotify/fsnotify).

!!! example

```console
Expand Down
Expand Up @@ -45,6 +45,7 @@ The following configuration variables are available:
| | `command` | string | `$EDITOR` / `$VISUAL` | Edit command |
| | `hardlink` | bool | `true` | Invoke editor with a hardlink to the source file |
| | `minDuration` | duration | `1s` | Minimum duration for edit command |
| | `watch` | bool | `false` | Automatically apply changes when files are saved |
| `git` | `autoAdd ` | bool | `false` | Add changes to the source state after any change |
| | `autoCommit` | bool | `false` | Commit changes to the source state after any change |
| | `autoPush` | bool | `false` | Push changes to the source state after any change |
Expand Down
Expand Up @@ -6,7 +6,8 @@ There are five popular approaches:

1. Use `chezmoi edit $FILE`. This will open the source file for `$FILE` in your
editor, including . For extra ease, use `chezmoi edit --apply $FILE` to apply
the changes when you quit your editor.
the changes when you quit your editor, and `chezmoi edit --watch $FILE` to
apply the changes whenever you save the file.

2. Use `chezmoi cd` and edit the files in the source directory directly. Run
`chezmoi diff` to see what changes would be made, and `chezmoi apply` to make
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Expand Up @@ -12,6 +12,7 @@ require (
github.com/bradenhilton/mozillainstallhash v1.0.0
github.com/charmbracelet/glamour v0.5.0
github.com/coreos/go-semver v0.3.0
github.com/fsnotify/fsnotify v1.5.4
github.com/go-git/go-git/v5 v5.4.2
github.com/google/go-github/v45 v45.2.0
github.com/google/gops v0.3.25
Expand Down Expand Up @@ -70,7 +71,6 @@ require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dlclark/regexp2 v1.7.0 // indirect
github.com/emirpasic/gods v1.18.1 // indirect
github.com/fsnotify/fsnotify v1.5.4 // indirect
github.com/go-git/gcfg v1.5.0 // indirect
github.com/go-git/go-billy/v5 v5.3.1 // indirect
github.com/godbus/dbus/v5 v5.1.0 // indirect
Expand Down
82 changes: 66 additions & 16 deletions pkg/cmd/editcmd.go
Expand Up @@ -5,6 +5,7 @@ import (
"runtime"
"time"

"github.com/fsnotify/fsnotify"
"github.com/spf13/cobra"

"github.com/twpayne/chezmoi/v2/pkg/chezmoi"
Expand All @@ -15,6 +16,7 @@ type editCmdConfig struct {
Args []string `mapstructure:"args"`
Hardlink bool `mapstructure:"hardlink"`
MinDuration time.Duration `mapstructure:"minDuration"`
Watch bool `mapstructure:"watch"`
apply bool
exclude *chezmoi.EntryTypeSet
include *chezmoi.EntryTypeSet
Expand Down Expand Up @@ -44,6 +46,7 @@ func (c *Config) newEditCmd() *cobra.Command {
flags.BoolVar(&c.Edit.Hardlink, "hardlink", c.Edit.Hardlink, "Invoke editor with a hardlink to the source file")
flags.VarP(c.Edit.include, "include", "i", "Include entry types")
flags.BoolVar(&c.Edit.init, "init", c.Edit.init, "Recreate config file from template")
flags.BoolVar(&c.Edit.Watch, "watch", c.Edit.Watch, "Apply on save")

return editCmd
}
Expand Down Expand Up @@ -156,30 +159,77 @@ TARGETRELPATH:
}
}

if err := c.runEditor(editorArgs); err != nil {
return err
postEditFunc := func() error {
for _, transparentlyDecryptedFile := range transparentlyDecryptedFiles {
contents, err := c.encryption.EncryptFile(transparentlyDecryptedFile.decryptedAbsPath)
if err != nil {
return err
}
if err := c.baseSystem.WriteFile(transparentlyDecryptedFile.sourceAbsPath, contents, 0o666); err != nil {
return err
}
}

if c.Edit.apply || c.Edit.Watch {
if err := c.applyArgs(cmd.Context(), c.destSystem, c.DestDirAbsPath, args, applyArgsOptions{
include: c.Edit.include,
init: c.Edit.init,
recursive: false,
umask: c.Umask,
preApplyFunc: c.defaultPreApplyFunc,
}); err != nil {
return err
}
}

return nil
}

for _, transparentlyDecryptedFile := range transparentlyDecryptedFiles {
contents, err := c.encryption.EncryptFile(transparentlyDecryptedFile.decryptedAbsPath)
if c.Edit.Watch {
watcher, err := fsnotify.NewWatcher()
if err != nil {
return err
}
if err := c.baseSystem.WriteFile(transparentlyDecryptedFile.sourceAbsPath, contents, 0o666); err != nil {
return err
defer watcher.Close()

for _, editorArg := range editorArgs {
if err := watcher.Add(editorArg); err != nil {
return err
}
}

go func() {
for {
select {
case event, ok := <-watcher.Events:
if !ok {
return
}
c.logger.Debug().
Stringer("Op", event.Op).
Str("Name", event.Name).
Msg("watcher.Events")
err := postEditFunc()
c.logger.Err(err).
Msg("postEditFunc")
case _, ok := <-watcher.Errors:
if !ok {
return
}
c.logger.Error().
Err(err).
Msg("watcher.Errors")
}
}
}()
}

if c.Edit.apply {
if err := c.applyArgs(cmd.Context(), c.destSystem, c.DestDirAbsPath, args, applyArgsOptions{
include: c.Edit.include,
init: c.Edit.init,
recursive: false,
umask: c.Umask,
preApplyFunc: c.defaultPreApplyFunc,
}); err != nil {
return err
}
if err := c.runEditor(editorArgs); err != nil {
return err
}

if err := postEditFunc(); err != nil {
return err
}

return nil
Expand Down

0 comments on commit ac0c759

Please sign in to comment.