Skip to content

Commit

Permalink
feat: Make chezmoi edit with no args open working tree (#1455)
Browse files Browse the repository at this point in the history
  • Loading branch information
twpayne authored Sep 24, 2021
1 parent f7f6fef commit f86d7b5
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 24 deletions.
2 changes: 1 addition & 1 deletion docs/REFERENCE.md
Original file line number Diff line number Diff line change
Expand Up @@ -1138,7 +1138,7 @@ $ chezmoi dump --format=yaml
### `edit` [*target*...]

Edit the source state of *target*s, which must be files or symlinks. If no
targets are given the the source directory itself is opened.
targets are given then the working tree of the source directory is opened.

The editor used is the first non-empty string of the `edit.command`
configuration variable, the `$VISUAL` environment variable, the `$EDITOR`
Expand Down
15 changes: 15 additions & 0 deletions internal/cmd/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -1634,6 +1634,21 @@ func (c *Config) validateData() error {
return validateKeys(c.Data, identifierRx)
}

// workingTree searches upwards to find the git working tree.
func (c *Config) workingTree() chezmoi.AbsPath {
workingTreeDirAbsPath := c.SourceDirAbsPath
for {
if info, err := c.baseSystem.Stat(workingTreeDirAbsPath.Join(".git")); err == nil && info.IsDir() {
return workingTreeDirAbsPath
}
prevWorkingTreeDirAbsPath := workingTreeDirAbsPath
workingTreeDirAbsPath = workingTreeDirAbsPath.Dir()
if len(workingTreeDirAbsPath) >= len(prevWorkingTreeDirAbsPath) {
return ""
}
}
}

func (c *Config) writeOutput(data []byte) error {
if c.outputAbsPath == "" || c.outputAbsPath == "-" {
_, err := c.stdout.Write(data)
Expand Down
6 changes: 5 additions & 1 deletion internal/cmd/editcmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,11 @@ func (c *Config) newEditCmd() *cobra.Command {

func (c *Config) runEditCmd(cmd *cobra.Command, args []string, sourceState *chezmoi.SourceState) error {
if len(args) == 0 {
if err := c.runEditor([]string{string(c.SourceDirAbsPath)}); err != nil {
dirAbsPath := c.workingTree()
if dirAbsPath == "" {
dirAbsPath = c.SourceDirAbsPath
}
if err := c.runEditor([]string{string(dirAbsPath)}); err != nil {
return err
}
if c.Edit.apply {
Expand Down
20 changes: 2 additions & 18 deletions internal/cmd/initcmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,24 +132,8 @@ func (c *Config) runInitCmd(cmd *cobra.Command, args []string) error {
c.init.purgeBinary = true
}

// Search upwards to find out if we're already in a git repository.
inWorkingCopy := false
workingCopyDirAbsPath := c.SourceDirAbsPath
FOR:
for {
if info, err := c.baseSystem.Stat(workingCopyDirAbsPath.Join(".git")); err == nil && info.IsDir() {
inWorkingCopy = true
break FOR
}
prevWorkingCopyDirAbsPath := workingCopyDirAbsPath
workingCopyDirAbsPath = workingCopyDirAbsPath.Dir()
if len(workingCopyDirAbsPath) >= len(prevWorkingCopyDirAbsPath) {
break FOR
}
}

// If the working copy does not exist then init it or clone it.
if !inWorkingCopy {
// If we're not in a working tree then init it or clone it.
if c.workingTree() == "" {
rawSourceDir, err := c.baseSystem.RawPath(c.SourceDirAbsPath)
if err != nil {
return err
Expand Down
28 changes: 24 additions & 4 deletions internal/cmd/testdata/scripts/edit.txt
Original file line number Diff line number Diff line change
@@ -1,31 +1,51 @@
mkhomedir
mksourcedir

# test that chezmoi edit edits a single file
chezmoi edit $HOME${/}.file
grep -count=1 '# edited' $CHEZMOISOURCEDIR/dot_file
! grep '# edited' $HOME/.file

# test that chezmoi edit --apply applies the edit.
chezmoi edit --apply --force $HOME${/}.file
grep -count=2 '# edited' $CHEZMOISOURCEDIR/dot_file
grep -count=2 '# edited' $HOME/.file

# test that chezmoi edit edits a symlink
chezmoi edit $HOME${/}.symlink
grep -count=1 '# edited' $CHEZMOISOURCEDIR/symlink_dot_symlink

chezmoi edit -v $HOME${/}script
# test that chezmoi edit edits a script
chezmoi edit $HOME${/}script
grep -count=1 '# edited' $CHEZMOISOURCEDIR/run_script

# test that chezmoi edit edits a file and a symlink
chezmoi edit $HOME${/}.file $HOME${/}.symlink
grep -count=3 '# edited' $CHEZMOISOURCEDIR/dot_file
grep -count=2 '# edited' $CHEZMOISOURCEDIR/symlink_dot_symlink

# test that chezmoi edit edits the working tree
chezmoi edit
exists $CHEZMOISOURCEDIR/.edited

[windows] stop 'remaining tests use file modes'
# test that chezmoi edit edits a directory
[!windows] chezmoi edit $HOME${/}.dir
[!windows] exists $CHEZMOISOURCEDIR/dot_dir/.edited

chezmoi edit $HOME${/}.dir
exists $CHEZMOISOURCEDIR/dot_dir/.edited
# test that chezmoi edit edits a file when the working tree and the source dir are different
chhome home2/user
chezmoi edit $HOME${/}.file
grep -count=1 '# edited' $CHEZMOISOURCEDIR/home/dot_file

# test that chezmoi edit edits the working tree when working tree and the source dir are different
chezmoi edit
exists $CHEZMOISOURCEDIR/.edited
! exists $CHEZMOISOURCEDIR/home/.edited

-- home/user/.local/share/chezmoi/run_script --
#!/bin/sh
-- home2/user/.config/chezmoi/chezmoi.toml --
sourceDir = "~/.local/share/chezmoi/home"
-- home2/user/.local/share/chezmoi/.git/.keep --
-- home2/user/.local/share/chezmoi/home/dot_file --
# contents of .file

0 comments on commit f86d7b5

Please sign in to comment.