aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--options.go3
-rw-r--r--worktree.go7
-rw-r--r--worktree_status.go16
-rw-r--r--worktree_test.go39
4 files changed, 54 insertions, 11 deletions
diff --git a/options.go b/options.go
index e748b91..bc8b379 100644
--- a/options.go
+++ b/options.go
@@ -685,7 +685,10 @@ const (
// CleanOptions describes how a clean should be performed.
type CleanOptions struct {
+ // Dir recurses into nested directories.
Dir bool
+ // All removes all changes, even those excluded by gitignore.
+ All bool
}
// GrepOptions describes how a grep should be performed.
diff --git a/worktree.go b/worktree.go
index 4dfe036..b812885 100644
--- a/worktree.go
+++ b/worktree.go
@@ -861,10 +861,11 @@ func (w *Worktree) Clean(opts *CleanOptions) error {
if err != nil {
return err
}
+ m := gitignore.NewMatcher([]gitignore.Pattern{})
return w.doClean(s, opts, root, files)
}
-func (w *Worktree) doClean(status Status, opts *CleanOptions, dir string, files []os.FileInfo) error {
+func (w *Worktree) doClean(status Status, matcher gitignore.Matcher, opts *CleanOptions, dir string, files []os.FileInfo) error {
for _, fi := range files {
if fi.Name() == GitDirName {
continue
@@ -881,12 +882,12 @@ func (w *Worktree) doClean(status Status, opts *CleanOptions, dir string, files
if err != nil {
return err
}
- err = w.doClean(status, opts, path, subfiles)
+ err = w.doClean(status, matcher, opts, path, subfiles)
if err != nil {
return err
}
} else {
- if status.IsUntracked(path) {
+ if status.IsUntracked(path) || (opts.All && matcher.Match(strings.Split(path, string(os.PathSeparator)), false)) {
if err := w.Filesystem.Remove(path); err != nil {
return err
}
diff --git a/worktree_status.go b/worktree_status.go
index 7301087..c07bc6b 100644
--- a/worktree_status.go
+++ b/worktree_status.go
@@ -144,20 +144,20 @@ func (w *Worktree) diffStagingWithWorktree(reverse, excludeIgnoredChanges bool)
return c, nil
}
-func (w *Worktree) excludeIgnoredChanges(changes merkletrie.Changes) merkletrie.Changes {
+func (w *Worktree) gitignoreMatcher() (gitignore.Matcher, error) {
patterns, err := gitignore.ReadPatterns(w.Filesystem, nil)
if err != nil {
- return changes
+ return nil, err
}
-
patterns = append(patterns, w.Excludes...)
-
- if len(patterns) == 0 {
+ return gitignore.NewMatcher(patterns), nil
+}
+
+func (w *Worktree) excludeIgnoredChanges(changes merkletrie.Changes) merkletrie.Changes {
+ m, err := w.gitignoreMatcher()
+ if err != nil {
return changes
}
-
- m := gitignore.NewMatcher(patterns)
-
var res merkletrie.Changes
for _, ch := range changes {
var path []string
diff --git a/worktree_test.go b/worktree_test.go
index 5759ec4..c00d630 100644
--- a/worktree_test.go
+++ b/worktree_test.go
@@ -2204,6 +2204,45 @@ func (s *WorktreeSuite) TestClean(c *C) {
c.Assert(err, ErrorMatches, ".*(no such file or directory.*|.*file does not exist)*.")
}
+func (s *WorktreeSuite) TestCleanAll(c *C) {
+ fs := fixtures.Basic().ByTag("worktree").One().Worktree()
+ r, err := PlainOpen(fs.Root())
+ c.Assert(err, IsNil)
+ w, err := r.Worktree()
+ c.Assert(err, IsNil)
+
+ err = util.WriteFile(w.Filesystem, ".gitignore", []byte("foo\n"), 0755)
+ c.Assert(err, IsNil)
+
+ _, err = w.Add(".")
+ c.Assert(err, IsNil)
+
+ commitOpts := &CommitOptions{Author: &object.Signature{Name: "foo", Email: "foo@foo.foo", When: time.Now()}}
+ _, err = w.Commit("Add gitignore", commitOpts)
+ c.Assert(err, IsNil)
+
+ status, err := w.Status()
+ c.Assert(err, IsNil)
+ c.Assert(len(status), Equals, 0)
+
+ err = util.WriteFile(w.Filesystem, "foo", []byte("foo\n"), 0755)
+ c.Assert(err, IsNil)
+
+ status, err = w.Status()
+ c.Assert(err, IsNil)
+ c.Assert(len(status), Equals, 0)
+
+ err = w.Clean(&CleanOptions{All: true, Dir: true})
+ c.Assert(err, IsNil)
+
+ status, err = w.Status()
+ c.Assert(err, IsNil)
+ c.Assert(len(status), Equals, 0)
+
+ _, err = fs.Lstat("foo")
+ c.Assert(err, ErrorMatches, ".*(no such file or directory.*|.*file does not exist)*.")
+}
+
func (s *WorktreeSuite) TestCleanBare(c *C) {
storer := memory.NewStorage()