···373373 ErrMissingAuthor = errors.New("author field is required")
374374)
375375376376+// AddOptions describes how a add operation should be performed
377377+type AddOptions struct {
378378+ All bool
379379+ Path string
380380+}
381381+376382// CommitOptions describes how a commit operation should be performed.
377383type CommitOptions struct {
378384 // All automatically stage files that have been modified and deleted, but
+65-36
worktree_status.go
···77 "os"
88 "path"
99 "path/filepath"
1010+ "strings"
10111112 "github.com/go-git/go-billy/v5/util"
1213 "github.com/go-git/go-git/v5/plumbing"
···264265// the worktree to the index. If any of the files is already staged in the index
265266// no error is returned. When path is a file, the blob.Hash is returned.
266267func (w *Worktree) Add(path string) (plumbing.Hash, error) {
267267- // TODO(mcuadros): remove plumbing.Hash from signature at v5.
268268- s, err := w.Status()
269269- if err != nil {
270270- return plumbing.ZeroHash, err
271271- }
272272-273273- idx, err := w.r.Storer.Index()
274274- if err != nil {
275275- return plumbing.ZeroHash, err
276276- }
277277-278278- var h plumbing.Hash
279279- var added bool
280280-281281- fi, err := w.Filesystem.Lstat(path)
282282- if err != nil || !fi.IsDir() {
283283- added, h, err = w.doAddFile(idx, s, path)
284284- } else {
285285- added, err = w.doAddDirectory(idx, s, path)
286286- }
287287-288288- if err != nil {
289289- return h, err
290290- }
291291-292292- if !added {
293293- return h, nil
294294- }
295295-296296- return h, w.r.Storer.SetIndex(idx)
268268+ return w.doAdd(path, make([]gitignore.Pattern, 0))
297269}
298270299299-func (w *Worktree) doAddDirectory(idx *index.Index, s Status, directory string) (added bool, err error) {
271271+func (w *Worktree) doAddDirectory(idx *index.Index, s Status, directory string, ignorePattern []gitignore.Pattern) (added bool, err error) {
300272 files, err := w.Filesystem.ReadDir(directory)
301273 if err != nil {
302274 return false, err
303275 }
276276+ if len(ignorePattern) > 0 {
277277+ m := gitignore.NewMatcher(ignorePattern)
278278+ matchPath := strings.Split(directory, string(os.PathSeparator))
279279+ if m.Match(matchPath, true) {
280280+ // ignore
281281+ return false, nil
282282+ }
283283+ }
304284305285 for _, file := range files {
306286 name := path.Join(directory, file.Name())
···311291 // ignore special git directory
312292 continue
313293 }
314314- a, err = w.doAddDirectory(idx, s, name)
294294+ a, err = w.doAddDirectory(idx, s, name, ignorePattern)
315295 } else {
316316- a, _, err = w.doAddFile(idx, s, name)
296296+ a, _, err = w.doAddFile(idx, s, name, ignorePattern)
317297 }
318298319299 if err != nil {
···328308 return
329309}
330310311311+// add changes from all tracked and untracked files
312312+func (w *Worktree) AddWithOptions(opts *AddOptions) (plumbing.Hash, error) {
313313+ if opts.All {
314314+ return w.doAdd(".", w.Excludes)
315315+ }
316316+ return w.Add(opts.Path)
317317+}
318318+319319+func (w *Worktree) doAdd(path string, ignorePattern []gitignore.Pattern) (plumbing.Hash, error) {
320320+ // TODO(mcuadros): remove plumbing.Hash from signature at v5.
321321+ s, err := w.Status()
322322+ if err != nil {
323323+ return plumbing.ZeroHash, err
324324+ }
325325+326326+ idx, err := w.r.Storer.Index()
327327+ if err != nil {
328328+ return plumbing.ZeroHash, err
329329+ }
330330+331331+ var h plumbing.Hash
332332+ var added bool
333333+334334+ fi, err := w.Filesystem.Lstat(path)
335335+ if err != nil || !fi.IsDir() {
336336+ added, h, err = w.doAddFile(idx, s, path, ignorePattern)
337337+ } else {
338338+ added, err = w.doAddDirectory(idx, s, path, ignorePattern)
339339+ }
340340+341341+ if err != nil {
342342+ return h, err
343343+ }
344344+345345+ if !added {
346346+ return h, nil
347347+ }
348348+349349+ return h, w.r.Storer.SetIndex(idx)
350350+}
351351+331352// AddGlob adds all paths, matching pattern, to the index. If pattern matches a
332353// directory path, all directory contents are added to the index recursively. No
333354// error is returned if all matching paths are already staged in index.
···360381361382 var added bool
362383 if fi.IsDir() {
363363- added, err = w.doAddDirectory(idx, s, file)
384384+ added, err = w.doAddDirectory(idx, s, file, make([]gitignore.Pattern, 0))
364385 } else {
365365- added, _, err = w.doAddFile(idx, s, file)
386386+ added, _, err = w.doAddFile(idx, s, file, make([]gitignore.Pattern, 0))
366387 }
367388368389 if err != nil {
···383404384405// doAddFile create a new blob from path and update the index, added is true if
385406// the file added is different from the index.
386386-func (w *Worktree) doAddFile(idx *index.Index, s Status, path string) (added bool, h plumbing.Hash, err error) {
407407+func (w *Worktree) doAddFile(idx *index.Index, s Status, path string, ignorePattern []gitignore.Pattern) (added bool, h plumbing.Hash, err error) {
387408 if s.File(path).Worktree == Unmodified {
388409 return false, h, nil
410410+ }
411411+ if len(ignorePattern) > 0 {
412412+ m := gitignore.NewMatcher(ignorePattern)
413413+ matchPath := strings.Split(path, string(os.PathSeparator))
414414+ if m.Match(matchPath, true) {
415415+ // ignore
416416+ return false, h, nil
417417+ }
389418 }
390419391420 h, err = w.copyFileToStorage(path)