aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaulo Gomes <pjbgf@linux.com>2024-06-28 21:20:36 +0000
committerGitHub <noreply@github.com>2024-06-28 21:20:36 +0000
commitcc6b98e366436b69a0e91aa0698972d583080900 (patch)
treef0af1e3bff6a7a69f009faac0bef2915ebcaa385
parentc817be6af4dde11b0c0c978dc2ecb77a2065c8b1 (diff)
parent86d3f41c8eb5939f384d30667f6097d716c1e916 (diff)
downloadgo-git-cc6b98e366436b69a0e91aa0698972d583080900.tar.gz
Merge pull request #995 from msuozzo/git-clean
Add option approximating `git clean -x` flag.
-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 d7776da..622bd47 100644
--- a/options.go
+++ b/options.go
@@ -721,7 +721,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 ab11d42..1de17c8 100644
--- a/worktree.go
+++ b/worktree.go
@@ -865,10 +865,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
@@ -885,12 +886,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 dd9b243..1eee042 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 3e151f6..5b0cc32 100644
--- a/worktree_test.go
+++ b/worktree_test.go
@@ -2371,6 +2371,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()