Skip to content
This repository was archived by the owner on Sep 11, 2020. It is now read-only.

Commit 34b101e

Browse files
authored
Merge pull request #933 from kuba--/fix-895/clean-dir
Remove empty dirs when cleaning with Dir opt.
2 parents 5cc316b + 75fa41d commit 34b101e

File tree

3 files changed

+62
-16
lines changed

3 files changed

+62
-16
lines changed

status.go

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
package git
22

3-
import "fmt"
4-
import "bytes"
3+
import (
4+
"bytes"
5+
"fmt"
6+
"path/filepath"
7+
)
58

69
// Status represents the current status of a Worktree.
710
// The key of the map is the path of the file.
@@ -17,6 +20,12 @@ func (s Status) File(path string) *FileStatus {
1720
return s[path]
1821
}
1922

23+
// IsUntracked checks if file for given path is 'Untracked'
24+
func (s Status) IsUntracked(path string) bool {
25+
stat, ok := (s)[filepath.ToSlash(path)]
26+
return ok && stat.Worktree == Untracked
27+
}
28+
2029
// IsClean returns true if all the files aren't in Unmodified status.
2130
func (s Status) IsClean() bool {
2231
for _, status := range s {

worktree.go

Lines changed: 42 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -713,29 +713,54 @@ func (w *Worktree) readGitmodulesFile() (*config.Modules, error) {
713713
}
714714

715715
// Clean the worktree by removing untracked files.
716+
// An empty dir could be removed - this is what `git clean -f -d .` does.
716717
func (w *Worktree) Clean(opts *CleanOptions) error {
717718
s, err := w.Status()
718719
if err != nil {
719720
return err
720721
}
721722

722-
// Check Worktree status to be Untracked, obtain absolute path and delete.
723-
for relativePath, status := range s {
724-
// Check if the path contains a directory and if Dir options is false,
725-
// skip the path.
726-
if relativePath != filepath.Base(relativePath) && !opts.Dir {
723+
root := ""
724+
files, err := w.Filesystem.ReadDir(root)
725+
if err != nil {
726+
return err
727+
}
728+
return w.doClean(s, opts, root, files)
729+
}
730+
731+
func (w *Worktree) doClean(status Status, opts *CleanOptions, dir string, files []os.FileInfo) error {
732+
for _, fi := range files {
733+
if fi.Name() == ".git" {
727734
continue
728735
}
729736

730-
// Remove the file only if it's an untracked file.
731-
if status.Worktree == Untracked {
732-
absPath := filepath.Join(w.Filesystem.Root(), relativePath)
733-
if err := os.Remove(absPath); err != nil {
737+
// relative path under the root
738+
path := filepath.Join(dir, fi.Name())
739+
if fi.IsDir() {
740+
if !opts.Dir {
741+
continue
742+
}
743+
744+
subfiles, err := w.Filesystem.ReadDir(path)
745+
if err != nil {
746+
return err
747+
}
748+
err = w.doClean(status, opts, path, subfiles)
749+
if err != nil {
734750
return err
735751
}
752+
} else {
753+
if status.IsUntracked(path) {
754+
if err := w.Filesystem.Remove(path); err != nil {
755+
return err
756+
}
757+
}
736758
}
737759
}
738760

761+
if opts.Dir {
762+
return doCleanDirectories(w.Filesystem, dir)
763+
}
739764
return nil
740765
}
741766

@@ -881,15 +906,18 @@ func rmFileAndDirIfEmpty(fs billy.Filesystem, name string) error {
881906
return err
882907
}
883908

884-
path := filepath.Dir(name)
885-
files, err := fs.ReadDir(path)
909+
dir := filepath.Dir(name)
910+
return doCleanDirectories(fs, dir)
911+
}
912+
913+
// doCleanDirectories removes empty subdirs (without files)
914+
func doCleanDirectories(fs billy.Filesystem, dir string) error {
915+
files, err := fs.ReadDir(dir)
886916
if err != nil {
887917
return err
888918
}
889-
890919
if len(files) == 0 {
891-
fs.Remove(path)
920+
return fs.Remove(dir)
892921
}
893-
894922
return nil
895923
}

worktree_test.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1591,6 +1591,10 @@ func (s *WorktreeSuite) TestClean(c *C) {
15911591

15921592
c.Assert(len(status), Equals, 1)
15931593

1594+
fi, err := fs.Lstat("pkgA")
1595+
c.Assert(err, IsNil)
1596+
c.Assert(fi.IsDir(), Equals, true)
1597+
15941598
// Clean with Dir: true.
15951599
err = wt.Clean(&CleanOptions{Dir: true})
15961600
c.Assert(err, IsNil)
@@ -1599,6 +1603,11 @@ func (s *WorktreeSuite) TestClean(c *C) {
15991603
c.Assert(err, IsNil)
16001604

16011605
c.Assert(len(status), Equals, 0)
1606+
1607+
// An empty dir should be deleted, as well.
1608+
_, err = fs.Lstat("pkgA")
1609+
c.Assert(err, ErrorMatches, ".*(no such file or directory.*|.*file does not exist)*.")
1610+
16021611
}
16031612

16041613
func (s *WorktreeSuite) TestAlternatesRepo(c *C) {

0 commit comments

Comments
 (0)