aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjk2k <4025839+jk2K@users.noreply.github.com>2020-06-07 20:06:33 +0800
committerjk2k <4025839+jk2K@users.noreply.github.com>2020-06-10 20:26:51 +0800
commite4a55327a2f1bd53fa173ce3e536eef530bfc272 (patch)
treeb9f9f33604905b135b79667a14f36d5d3c90912e
parent96a108e35075afd13e81df9ba2bf96c8c6125283 (diff)
downloadgo-git-e4a55327a2f1bd53fa173ce3e536eef530bfc272.tar.gz
feat: add file with using .gitignore, fixed src-d/go-git#1219
-rw-r--r--options.go6
-rw-r--r--worktree_status.go101
-rw-r--r--worktree_test.go46
3 files changed, 117 insertions, 36 deletions
diff --git a/options.go b/options.go
index fd347d3..d222267 100644
--- a/options.go
+++ b/options.go
@@ -373,6 +373,12 @@ var (
ErrMissingAuthor = errors.New("author field is required")
)
+// AddOptions describes how a add operation should be performed
+type AddOptions struct {
+ All bool
+ Path string
+}
+
// CommitOptions describes how a commit operation should be performed.
type CommitOptions struct {
// All automatically stage files that have been modified and deleted, but
diff --git a/worktree_status.go b/worktree_status.go
index 1542f5e..658ed94 100644
--- a/worktree_status.go
+++ b/worktree_status.go
@@ -7,6 +7,7 @@ import (
"os"
"path"
"path/filepath"
+ "strings"
"github.com/go-git/go-billy/v5/util"
"github.com/go-git/go-git/v5/plumbing"
@@ -264,43 +265,22 @@ func diffTreeIsEquals(a, b noder.Hasher) bool {
// the worktree to the index. If any of the files is already staged in the index
// no error is returned. When path is a file, the blob.Hash is returned.
func (w *Worktree) Add(path string) (plumbing.Hash, error) {
- // TODO(mcuadros): remove plumbing.Hash from signature at v5.
- s, err := w.Status()
- if err != nil {
- return plumbing.ZeroHash, err
- }
-
- idx, err := w.r.Storer.Index()
- if err != nil {
- return plumbing.ZeroHash, err
- }
-
- var h plumbing.Hash
- var added bool
-
- fi, err := w.Filesystem.Lstat(path)
- if err != nil || !fi.IsDir() {
- added, h, err = w.doAddFile(idx, s, path)
- } else {
- added, err = w.doAddDirectory(idx, s, path)
- }
-
- if err != nil {
- return h, err
- }
-
- if !added {
- return h, nil
- }
-
- return h, w.r.Storer.SetIndex(idx)
+ return w.doAdd(path, make([]gitignore.Pattern, 0))
}
-func (w *Worktree) doAddDirectory(idx *index.Index, s Status, directory string) (added bool, err error) {
+func (w *Worktree) doAddDirectory(idx *index.Index, s Status, directory string, ignorePattern []gitignore.Pattern) (added bool, err error) {
files, err := w.Filesystem.ReadDir(directory)
if err != nil {
return false, err
}
+ if len(ignorePattern) > 0 {
+ m := gitignore.NewMatcher(ignorePattern)
+ matchPath := strings.Split(directory, string(os.PathSeparator))
+ if m.Match(matchPath, true) {
+ // ignore
+ return false, nil
+ }
+ }
for _, file := range files {
name := path.Join(directory, file.Name())
@@ -311,9 +291,9 @@ func (w *Worktree) doAddDirectory(idx *index.Index, s Status, directory string)
// ignore special git directory
continue
}
- a, err = w.doAddDirectory(idx, s, name)
+ a, err = w.doAddDirectory(idx, s, name, ignorePattern)
} else {
- a, _, err = w.doAddFile(idx, s, name)
+ a, _, err = w.doAddFile(idx, s, name, ignorePattern)
}
if err != nil {
@@ -328,6 +308,47 @@ func (w *Worktree) doAddDirectory(idx *index.Index, s Status, directory string)
return
}
+// add changes from all tracked and untracked files
+func (w *Worktree) AddWithOptions(opts *AddOptions) (plumbing.Hash, error) {
+ if opts.All {
+ return w.doAdd(".", w.Excludes)
+ }
+ return w.Add(opts.Path)
+}
+
+func (w *Worktree) doAdd(path string, ignorePattern []gitignore.Pattern) (plumbing.Hash, error) {
+ // TODO(mcuadros): remove plumbing.Hash from signature at v5.
+ s, err := w.Status()
+ if err != nil {
+ return plumbing.ZeroHash, err
+ }
+
+ idx, err := w.r.Storer.Index()
+ if err != nil {
+ return plumbing.ZeroHash, err
+ }
+
+ var h plumbing.Hash
+ var added bool
+
+ fi, err := w.Filesystem.Lstat(path)
+ if err != nil || !fi.IsDir() {
+ added, h, err = w.doAddFile(idx, s, path, ignorePattern)
+ } else {
+ added, err = w.doAddDirectory(idx, s, path, ignorePattern)
+ }
+
+ if err != nil {
+ return h, err
+ }
+
+ if !added {
+ return h, nil
+ }
+
+ return h, w.r.Storer.SetIndex(idx)
+}
+
// AddGlob adds all paths, matching pattern, to the index. If pattern matches a
// directory path, all directory contents are added to the index recursively. No
// error is returned if all matching paths are already staged in index.
@@ -360,9 +381,9 @@ func (w *Worktree) AddGlob(pattern string) error {
var added bool
if fi.IsDir() {
- added, err = w.doAddDirectory(idx, s, file)
+ added, err = w.doAddDirectory(idx, s, file, make([]gitignore.Pattern, 0))
} else {
- added, _, err = w.doAddFile(idx, s, file)
+ added, _, err = w.doAddFile(idx, s, file, make([]gitignore.Pattern, 0))
}
if err != nil {
@@ -383,10 +404,18 @@ func (w *Worktree) AddGlob(pattern string) error {
// doAddFile create a new blob from path and update the index, added is true if
// the file added is different from the index.
-func (w *Worktree) doAddFile(idx *index.Index, s Status, path string) (added bool, h plumbing.Hash, err error) {
+func (w *Worktree) doAddFile(idx *index.Index, s Status, path string, ignorePattern []gitignore.Pattern) (added bool, h plumbing.Hash, err error) {
if s.File(path).Worktree == Unmodified {
return false, h, nil
}
+ if len(ignorePattern) > 0 {
+ m := gitignore.NewMatcher(ignorePattern)
+ matchPath := strings.Split(path, string(os.PathSeparator))
+ if m.Match(matchPath, true) {
+ // ignore
+ return false, h, nil
+ }
+ }
h, err = w.copyFileToStorage(path)
if err != nil {
diff --git a/worktree_test.go b/worktree_test.go
index 24a65eb..2ee830a 100644
--- a/worktree_test.go
+++ b/worktree_test.go
@@ -1370,6 +1370,52 @@ func (s *WorktreeSuite) TestAddDirectoryErrorNotFound(c *C) {
c.Assert(h.IsZero(), Equals, true)
}
+func (s *WorktreeSuite) TestAddAll(c *C) {
+ fs := memfs.New()
+ w := &Worktree{
+ r: s.Repository,
+ Filesystem: fs,
+ }
+
+ err := w.Checkout(&CheckoutOptions{Force: true})
+ c.Assert(err, IsNil)
+
+ idx, err := w.r.Storer.Index()
+ c.Assert(err, IsNil)
+ c.Assert(idx.Entries, HasLen, 9)
+
+ err = util.WriteFile(w.Filesystem, "file1", []byte("file1"), 0644)
+ c.Assert(err, IsNil)
+
+ err = util.WriteFile(w.Filesystem, "file2", []byte("file2"), 0644)
+ c.Assert(err, IsNil)
+
+ err = util.WriteFile(w.Filesystem, "file3", []byte("ignore me"), 0644)
+ c.Assert(err, IsNil)
+
+ w.Excludes = make([]gitignore.Pattern, 0)
+ w.Excludes = append(w.Excludes, gitignore.ParsePattern("file3", nil))
+
+ _, err = w.AddWithOptions(&AddOptions{All: true})
+ c.Assert(err, IsNil)
+
+ idx, err = w.r.Storer.Index()
+ c.Assert(err, IsNil)
+ c.Assert(idx.Entries, HasLen, 11)
+
+ status, err := w.Status()
+ c.Assert(err, IsNil)
+ c.Assert(status, HasLen, 2)
+
+ file1 := status.File("file1")
+ c.Assert(file1.Staging, Equals, Added)
+ file2 := status.File("file2")
+ c.Assert(file2.Staging, Equals, Added)
+ file3 := status.File("file3")
+ c.Assert(file3.Staging, Equals, Untracked)
+ c.Assert(file3.Worktree, Equals, Untracked)
+}
+
func (s *WorktreeSuite) TestAddGlob(c *C) {
fs := memfs.New()
w := &Worktree{