Skip to content

Commit

Permalink
feat: Apply diff.exclude to all diffs
Browse files Browse the repository at this point in the history
  • Loading branch information
twpayne committed Nov 28, 2021
1 parent 4ec24b6 commit 98b6a39
Show file tree
Hide file tree
Showing 6 changed files with 137 additions and 68 deletions.
2 changes: 1 addition & 1 deletion docs/REFERENCE.md
Original file line number Diff line number Diff line change
Expand Up @@ -375,7 +375,7 @@ The following configuration variables are available:
| | `command` | string | *none* | Shell to run in `cd` command |
| `diff` | `args` | []string | *see `diff` below* | Extra args to external diff command |
| | `command` | string | *none* | External diff command |
| | `exclude` | []string | *none* | Entry types to exclude from diff |
| | `exclude` | []string | *none* | Entry types to exclude from diffs |
| | `pager` | string | *none* | Diff-specific pager |
| `docs` | `maxWidth` | int | 80 | Maximum width of output |
| | `pager` | string | *none* | Docs-specific pager |
Expand Down
5 changes: 5 additions & 0 deletions internal/chezmoi/entrytypeset.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,11 @@ func NewEntryTypeSet(bits EntryTypeBits) *EntryTypeSet {
}
}

// Include returns if s includes b.
func (s *EntryTypeSet) Include(b EntryTypeBits) bool {
return s.bits&b != 0
}

// IncludeEncrypted returns true if s includes encrypted files.
func (s *EntryTypeSet) IncludeEncrypted() bool {
return s.bits&EntryTypeEncrypted != 0
Expand Down
149 changes: 84 additions & 65 deletions internal/chezmoi/gitdiffsystem.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,15 @@ import (
type GitDiffSystem struct {
system System
dirAbsPath AbsPath
include *EntryTypeSet
reverse bool
unifiedEncoder *diff.UnifiedEncoder
}

// GetDiffSystemOptions are options for NewGitDiffSystem.
type GitDiffSystemOptions struct {
Color bool
Include *EntryTypeSet
Reverse bool
}

Expand All @@ -39,6 +41,7 @@ func NewGitDiffSystem(system System, w io.Writer, dirAbsPath AbsPath, options *G
return &GitDiffSystem{
system: system,
dirAbsPath: dirAbsPath,
include: options.Include,
reverse: options.Reverse,
unifiedEncoder: unifiedEncoder,
}
Expand All @@ -50,17 +53,19 @@ func (s *GitDiffSystem) Chmod(name AbsPath, mode fs.FileMode) error {
if err != nil {
return err
}
toMode := fromInfo.Mode().Type() | mode
var toData []byte
if fromInfo.Mode().IsRegular() {
toData, err = s.ReadFile(name)
if err != nil {
if s.include.IncludeFileInfo(fromInfo) {
toMode := fromInfo.Mode().Type() | mode
var toData []byte
if fromInfo.Mode().IsRegular() {
toData, err = s.ReadFile(name)
if err != nil {
return err
}
}
if err := s.encodeDiff(name, toData, toMode); err != nil {
return err
}
}
if err := s.encodeDiff(name, toData, toMode); err != nil {
return err
}
return s.system.Chmod(name, mode)
}

Expand Down Expand Up @@ -92,8 +97,10 @@ func (s *GitDiffSystem) Lstat(name AbsPath) (fs.FileInfo, error) {

// Mkdir implements System.Mkdir.
func (s *GitDiffSystem) Mkdir(name AbsPath, perm fs.FileMode) error {
if err := s.encodeDiff(name, nil, fs.ModeDir|perm); err != nil {
return err
if s.include.Include(EntryTypeDirs) {
if err := s.encodeDiff(name, nil, fs.ModeDir|perm); err != nil {
return err
}
}
return s.system.Mkdir(name, perm)
}
Expand All @@ -120,51 +127,57 @@ func (s *GitDiffSystem) Readlink(name AbsPath) (string, error) {

// RemoveAll implements System.RemoveAll.
func (s *GitDiffSystem) RemoveAll(name AbsPath) error {
if err := s.encodeDiff(name, nil, 0); err != nil {
return err
if s.include.Include(EntryTypeRemove) {
if err := s.encodeDiff(name, nil, 0); err != nil {
return err
}
}
return s.system.RemoveAll(name)
}

// Rename implements System.Rename.
func (s *GitDiffSystem) Rename(oldpath, newpath AbsPath) error {
var fileMode filemode.FileMode
var hash plumbing.Hash
switch fromFileInfo, err := s.Stat(oldpath); {
case err != nil:
fromFileInfo, err := s.Stat(oldpath)
if err != nil {
return err
case fromFileInfo.Mode().IsDir():
hash = plumbing.ZeroHash // LATER be more intelligent here
case fromFileInfo.Mode().IsRegular():
data, err := s.system.ReadFile(oldpath)
if err != nil {
return err
}
hash = plumbing.ComputeHash(plumbing.BlobObject, data)
default:
fileMode = filemode.FileMode(fromFileInfo.Mode())
}
fromPath, toPath := s.trimPrefix(oldpath), s.trimPrefix(newpath)
if s.reverse {
fromPath, toPath = toPath, fromPath
}
if err := s.unifiedEncoder.Encode(&gitDiffPatch{
filePatches: []diff.FilePatch{
&gitDiffFilePatch{
from: &gitDiffFile{
fileMode: fileMode,
relPath: fromPath,
hash: hash,
},
to: &gitDiffFile{
fileMode: fileMode,
relPath: toPath,
hash: hash,
if s.include.IncludeFileInfo(fromFileInfo) {
var fileMode filemode.FileMode
var hash plumbing.Hash
switch {
case fromFileInfo.Mode().IsDir():
hash = plumbing.ZeroHash // LATER be more intelligent here
case fromFileInfo.Mode().IsRegular():
data, err := s.system.ReadFile(oldpath)
if err != nil {
return err
}
hash = plumbing.ComputeHash(plumbing.BlobObject, data)
default:
fileMode = filemode.FileMode(fromFileInfo.Mode())
}
fromPath, toPath := s.trimPrefix(oldpath), s.trimPrefix(newpath)
if s.reverse {
fromPath, toPath = toPath, fromPath
}
if err := s.unifiedEncoder.Encode(&gitDiffPatch{
filePatches: []diff.FilePatch{
&gitDiffFilePatch{
from: &gitDiffFile{
fileMode: fileMode,
relPath: fromPath,
hash: hash,
},
to: &gitDiffFile{
fileMode: fileMode,
relPath: toPath,
hash: hash,
},
},
},
},
}); err != nil {
return err
}); err != nil {
return err
}
}
return s.system.Rename(oldpath, newpath)
}
Expand All @@ -181,17 +194,19 @@ func (s *GitDiffSystem) RunIdempotentCmd(cmd *exec.Cmd) error {

// RunScript implements System.RunScript.
func (s *GitDiffSystem) RunScript(scriptname RelPath, dir AbsPath, data []byte, interpreter *Interpreter) error {
mode := fs.FileMode(filemode.Executable)
fromData, toData := []byte(nil), data
if s.reverse {
fromData, toData = toData, fromData
}
diffPatch, err := DiffPatch(scriptname, fromData, mode, toData, mode)
if err != nil {
return err
}
if err := s.unifiedEncoder.Encode(diffPatch); err != nil {
return err
if s.include.Include(EntryTypeScripts) {
mode := fs.FileMode(filemode.Executable)
fromData, toData := []byte(nil), data
if s.reverse {
fromData, toData = toData, fromData
}
diffPatch, err := DiffPatch(scriptname, fromData, mode, toData, mode)
if err != nil {
return err
}
if err := s.unifiedEncoder.Encode(diffPatch); err != nil {
return err
}
}
return s.system.RunScript(scriptname, dir, data, interpreter)
}
Expand All @@ -208,21 +223,25 @@ func (s *GitDiffSystem) UnderlyingFS() vfs.FS {

// WriteFile implements System.WriteFile.
func (s *GitDiffSystem) WriteFile(filename AbsPath, data []byte, perm fs.FileMode) error {
if err := s.encodeDiff(filename, data, perm); err != nil {
return err
if s.include.Include(EntryTypeFiles) {
if err := s.encodeDiff(filename, data, perm); err != nil {
return err
}
}
return s.system.WriteFile(filename, data, perm)
}

// WriteSymlink implements System.WriteSymlink.
func (s *GitDiffSystem) WriteSymlink(oldname string, newname AbsPath) error {
toData := append([]byte(normalizeLinkname(oldname)), '\n')
toMode := fs.ModeSymlink
if runtime.GOOS == "windows" {
toMode |= 0o666
}
if err := s.encodeDiff(newname, toData, toMode); err != nil {
return err
if s.include.Include(EntryTypeSymlinks) {
toData := append([]byte(normalizeLinkname(oldname)), '\n')
toMode := fs.ModeSymlink
if runtime.GOOS == "windows" {
toMode |= 0o666
}
if err := s.encodeDiff(newname, toData, toMode); err != nil {
return err
}
}
return s.system.WriteSymlink(oldname, newname)
}
Expand Down
6 changes: 4 additions & 2 deletions internal/cmd/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -1593,10 +1593,12 @@ func (c *Config) persistentPreRunRootE(cmd *cobra.Command, args []string) error
}
if c.Verbose {
c.sourceSystem = chezmoi.NewGitDiffSystem(c.sourceSystem, c.stdout, c.SourceDirAbsPath, &chezmoi.GitDiffSystemOptions{
Color: color,
Color: color,
Include: c.Diff.include.Sub(c.Diff.Exclude),
})
c.destSystem = chezmoi.NewGitDiffSystem(c.destSystem, c.stdout, c.DestDirAbsPath, &chezmoi.GitDiffSystemOptions{
Color: color,
Color: color,
Include: c.Diff.include.Sub(c.Diff.Exclude),
})
}

Expand Down
1 change: 1 addition & 0 deletions internal/cmd/diffcmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ func (c *Config) runDiffCmd(cmd *cobra.Command, args []string) (err error) {
color := c.Color.Value(c.colorAutoFunc)
gitDiffSystem := chezmoi.NewGitDiffSystem(dryRunSystem, &builder, c.DestDirAbsPath, &chezmoi.GitDiffSystemOptions{
Color: color,
Include: c.Diff.include.Sub(c.Diff.Exclude),
Reverse: c.Diff.reverse,
})
if err = c.applyArgs(cmd.Context(), gitDiffSystem, c.DestDirAbsPath, args, applyArgsOptions{
Expand Down
42 changes: 42 additions & 0 deletions internal/cmd/testdata/scripts/applyverbose.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# test that chezmoi apply --dry-run --verbose does not show scripts when scripts are excluded from diffs
chezmoi apply --dry-run --verbose
[!windows] cmp stdout golden/apply
[windows] cmp stdout golden/apply-windows

chhome home2/user

# test that chezmoi apply --dry-run --force --verbose does not show removes when removes are excluded from diffs
chezmoi apply --dry-run --force --verbose
! stdout .

-- golden/apply --
diff --git a/.file b/.file
new file mode 100644
index 0000000000000000000000000000000000000000..8a52cb9ce9551221716a53786ad74104c5902362
--- /dev/null
+++ b/.file
@@ -0,0 +1 @@
+# contents of .file
-- golden/apply-windows --
diff --git a/.file b/.file
new file mode 100666
index 0000000000000000000000000000000000000000..8a52cb9ce9551221716a53786ad74104c5902362
--- /dev/null
+++ b/.file
@@ -0,0 +1 @@
+# contents of .file
-- home/user/.config/chezmoi/chezmoi.toml --
[diff]
exclude = ["scripts"]
-- home/user/.local/share/chezmoi/dot_file --
# contents of .file
-- home/user/.local/share/chezmoi/run_script --
# contents of script
-- home2/user/.config/chezmoi/chezmoi.yaml --
diff:
exclude:
- remove
-- home2/user/.file --
# contents of .file
-- home2/user/.local/share/chezmoi/.chezmoiremove --
.file

0 comments on commit 98b6a39

Please sign in to comment.