77 "os"
88 "path"
99 "path/filepath"
10+ "strings"
1011
1112 "github.com/go-git/go-billy/v5/util"
1213 "github.com/go-git/go-git/v5/plumbing"
@@ -264,43 +265,22 @@ func diffTreeIsEquals(a, b noder.Hasher) bool {
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 ) {
267- // TODO(mcuadros): remove plumbing.Hash from signature at v5.
268- s , err := w .Status ()
269- if err != nil {
270- return plumbing .ZeroHash , err
271- }
272-
273- idx , err := w .r .Storer .Index ()
274- if err != nil {
275- return plumbing .ZeroHash , err
276- }
277-
278- var h plumbing.Hash
279- var added bool
280-
281- fi , err := w .Filesystem .Lstat (path )
282- if err != nil || ! fi .IsDir () {
283- added , h , err = w .doAddFile (idx , s , path )
284- } else {
285- added , err = w .doAddDirectory (idx , s , path )
286- }
287-
288- if err != nil {
289- return h , err
290- }
291-
292- if ! added {
293- return h , nil
294- }
295-
296- return h , w .r .Storer .SetIndex (idx )
268+ return w .doAdd (path , make ([]gitignore.Pattern , 0 ))
297269}
298270
299- func (w * Worktree ) doAddDirectory (idx * index.Index , s Status , directory string ) (added bool , err error ) {
271+ 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 }
276+ if len (ignorePattern ) > 0 {
277+ m := gitignore .NewMatcher (ignorePattern )
278+ matchPath := strings .Split (directory , string (os .PathSeparator ))
279+ if m .Match (matchPath , true ) {
280+ // ignore
281+ return false , nil
282+ }
283+ }
304284
305285 for _ , file := range files {
306286 name := path .Join (directory , file .Name ())
@@ -311,9 +291,9 @@ func (w *Worktree) doAddDirectory(idx *index.Index, s Status, directory string)
311291 // ignore special git directory
312292 continue
313293 }
314- a , err = w .doAddDirectory (idx , s , name )
294+ a , err = w .doAddDirectory (idx , s , name , ignorePattern )
315295 } else {
316- a , _ , err = w .doAddFile (idx , s , name )
296+ a , _ , err = w .doAddFile (idx , s , name , ignorePattern )
317297 }
318298
319299 if err != nil {
@@ -328,6 +308,47 @@ func (w *Worktree) doAddDirectory(idx *index.Index, s Status, directory string)
328308 return
329309}
330310
311+ // add changes from all tracked and untracked files
312+ func (w * Worktree ) AddWithOptions (opts * AddOptions ) (plumbing.Hash , error ) {
313+ if opts .All {
314+ return w .doAdd ("." , w .Excludes )
315+ }
316+ return w .Add (opts .Path )
317+ }
318+
319+ func (w * Worktree ) doAdd (path string , ignorePattern []gitignore.Pattern ) (plumbing.Hash , error ) {
320+ // TODO(mcuadros): remove plumbing.Hash from signature at v5.
321+ s , err := w .Status ()
322+ if err != nil {
323+ return plumbing .ZeroHash , err
324+ }
325+
326+ idx , err := w .r .Storer .Index ()
327+ if err != nil {
328+ return plumbing .ZeroHash , err
329+ }
330+
331+ var h plumbing.Hash
332+ var added bool
333+
334+ fi , err := w .Filesystem .Lstat (path )
335+ if err != nil || ! fi .IsDir () {
336+ added , h , err = w .doAddFile (idx , s , path , ignorePattern )
337+ } else {
338+ added , err = w .doAddDirectory (idx , s , path , ignorePattern )
339+ }
340+
341+ if err != nil {
342+ return h , err
343+ }
344+
345+ if ! added {
346+ return h , nil
347+ }
348+
349+ return h , w .r .Storer .SetIndex (idx )
350+ }
351+
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.
@@ -360,9 +381,9 @@ func (w *Worktree) AddGlob(pattern string) error {
360381
361382 var added bool
362383 if fi .IsDir () {
363- added , err = w .doAddDirectory (idx , s , file )
384+ added , err = w .doAddDirectory (idx , s , file , make ([]gitignore. Pattern , 0 ) )
364385 } else {
365- added , _ , err = w .doAddFile (idx , s , file )
386+ added , _ , err = w .doAddFile (idx , s , file , make ([]gitignore. Pattern , 0 ) )
366387 }
367388
368389 if err != nil {
@@ -383,10 +404,18 @@ func (w *Worktree) AddGlob(pattern string) error {
383404
384405// doAddFile create a new blob from path and update the index, added is true if
385406// the file added is different from the index.
386- func (w * Worktree ) doAddFile (idx * index.Index , s Status , path string ) (added bool , h plumbing.Hash , err error ) {
407+ 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
389410 }
411+ if len (ignorePattern ) > 0 {
412+ m := gitignore .NewMatcher (ignorePattern )
413+ matchPath := strings .Split (path , string (os .PathSeparator ))
414+ if m .Match (matchPath , true ) {
415+ // ignore
416+ return false , h , nil
417+ }
418+ }
390419
391420 h , err = w .copyFileToStorage (path )
392421 if err != nil {
0 commit comments