Skip to content

Commit 390968c

Browse files
authored
Merge pull request go-git#86 from jk2K/master
feat: add file with using .gitignore, fixed src-d/go-git#1219
2 parents 96a108e + e4a5532 commit 390968c

File tree

3 files changed

+117
-36
lines changed

3 files changed

+117
-36
lines changed

options.go

+6
Original file line numberDiff line numberDiff line change
@@ -373,6 +373,12 @@ var (
373373
ErrMissingAuthor = errors.New("author field is required")
374374
)
375375

376+
// AddOptions describes how a add operation should be performed
377+
type AddOptions struct {
378+
All bool
379+
Path string
380+
}
381+
376382
// CommitOptions describes how a commit operation should be performed.
377383
type CommitOptions struct {
378384
// All automatically stage files that have been modified and deleted, but

worktree_status.go

+65-36
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
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.
266267
func (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 {

worktree_test.go

+46
Original file line numberDiff line numberDiff line change
@@ -1370,6 +1370,52 @@ func (s *WorktreeSuite) TestAddDirectoryErrorNotFound(c *C) {
13701370
c.Assert(h.IsZero(), Equals, true)
13711371
}
13721372

1373+
func (s *WorktreeSuite) TestAddAll(c *C) {
1374+
fs := memfs.New()
1375+
w := &Worktree{
1376+
r: s.Repository,
1377+
Filesystem: fs,
1378+
}
1379+
1380+
err := w.Checkout(&CheckoutOptions{Force: true})
1381+
c.Assert(err, IsNil)
1382+
1383+
idx, err := w.r.Storer.Index()
1384+
c.Assert(err, IsNil)
1385+
c.Assert(idx.Entries, HasLen, 9)
1386+
1387+
err = util.WriteFile(w.Filesystem, "file1", []byte("file1"), 0644)
1388+
c.Assert(err, IsNil)
1389+
1390+
err = util.WriteFile(w.Filesystem, "file2", []byte("file2"), 0644)
1391+
c.Assert(err, IsNil)
1392+
1393+
err = util.WriteFile(w.Filesystem, "file3", []byte("ignore me"), 0644)
1394+
c.Assert(err, IsNil)
1395+
1396+
w.Excludes = make([]gitignore.Pattern, 0)
1397+
w.Excludes = append(w.Excludes, gitignore.ParsePattern("file3", nil))
1398+
1399+
_, err = w.AddWithOptions(&AddOptions{All: true})
1400+
c.Assert(err, IsNil)
1401+
1402+
idx, err = w.r.Storer.Index()
1403+
c.Assert(err, IsNil)
1404+
c.Assert(idx.Entries, HasLen, 11)
1405+
1406+
status, err := w.Status()
1407+
c.Assert(err, IsNil)
1408+
c.Assert(status, HasLen, 2)
1409+
1410+
file1 := status.File("file1")
1411+
c.Assert(file1.Staging, Equals, Added)
1412+
file2 := status.File("file2")
1413+
c.Assert(file2.Staging, Equals, Added)
1414+
file3 := status.File("file3")
1415+
c.Assert(file3.Staging, Equals, Untracked)
1416+
c.Assert(file3.Worktree, Equals, Untracked)
1417+
}
1418+
13731419
func (s *WorktreeSuite) TestAddGlob(c *C) {
13741420
fs := memfs.New()
13751421
w := &Worktree{

0 commit comments

Comments
 (0)