Skip to content
This repository was archived by the owner on Sep 11, 2020. It is now read-only.

Commit 66f08b8

Browse files
committed
new methods Worktree.[AddGlob|AddDirectory]
Signed-off-by: Máximo Cuadros <mcuadros@gmail.com>
1 parent 5d5b951 commit 66f08b8

File tree

3 files changed

+344
-35
lines changed

3 files changed

+344
-35
lines changed

worktree_commit.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,6 @@ func (w *Worktree) autoAddModifiedAndDeleted() error {
6363
if _, err := w.Add(path); err != nil {
6464
return err
6565
}
66-
6766
}
6867

6968
return nil

worktree_status.go

Lines changed: 184 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"io"
77
"os"
88

9+
"gopkg.in/src-d/go-billy.v4/util"
910
"gopkg.in/src-d/go-git.v4/plumbing"
1011
"gopkg.in/src-d/go-git.v4/plumbing/filemode"
1112
"gopkg.in/src-d/go-git.v4/plumbing/format/gitignore"
@@ -18,9 +19,16 @@ import (
1819
"gopkg.in/src-d/go-git.v4/utils/merkletrie/noder"
1920
)
2021

21-
// ErrDestinationExists in an Move operation means that the target exists on
22-
// the worktree.
23-
var ErrDestinationExists = errors.New("destination exists")
22+
var (
23+
// ErrDestinationExists in an Move operation means that the target exists on
24+
// the worktree.
25+
ErrDestinationExists = errors.New("destination exists")
26+
// ErrGlobNoMatches in an AddGlob if the glob pattern does not match any
27+
// file in the worktree.ErrNotDirectory
28+
ErrGlobNoMatches = errors.New("glob pattern did not match any files")
29+
// ErrNotDirectory in an AddDirectory if the path is not a directory.
30+
ErrNotDirectory = errors.New("path is not a directory")
31+
)
2432

2533
// Status returns the working tree status.
2634
func (w *Worktree) Status() (Status, error) {
@@ -243,30 +251,170 @@ func diffTreeIsEquals(a, b noder.Hasher) bool {
243251
}
244252

245253
// Add adds the file contents of a file in the worktree to the index. if the
246-
// file is already staged in the index no error is returned.
254+
// file is already staged in the index no error is returned. If a file deleted
255+
// from the Workspace is given, the file is removed from the index.
247256
func (w *Worktree) Add(path string) (plumbing.Hash, error) {
248257
s, err := w.Status()
249258
if err != nil {
250259
return plumbing.ZeroHash, err
251260
}
252261

253-
h, err := w.copyFileToStorage(path)
262+
idx, err := w.r.Storer.Index()
263+
if err != nil {
264+
return plumbing.ZeroHash, err
265+
}
266+
267+
added, h, err := w.doAdd(idx, s, path)
268+
if err != nil {
269+
return h, err
270+
}
271+
272+
if !added {
273+
return h, nil
274+
}
275+
276+
return h, w.r.Storer.SetIndex(idx)
277+
}
278+
279+
// AddDirectory adds the files contents of a directory and all his
280+
// sub-directories recursively in the worktree to the index. If any of the
281+
// file is already staged in the index no error is returned.
282+
func (w *Worktree) AddDirectory(path string) error {
283+
fi, err := w.Filesystem.Lstat(path)
284+
if err != nil {
285+
return err
286+
}
287+
288+
if !fi.IsDir() {
289+
return ErrNotDirectory
290+
}
291+
292+
s, err := w.Status()
293+
if err != nil {
294+
return err
295+
}
296+
297+
idx, err := w.r.Storer.Index()
298+
if err != nil {
299+
return err
300+
}
301+
302+
added, err := w.doAddDirectory(idx, s, path)
303+
if err != nil {
304+
return err
305+
}
306+
307+
if !added {
308+
return nil
309+
}
310+
311+
return w.r.Storer.SetIndex(idx)
312+
}
313+
314+
func (w *Worktree) doAddDirectory(idx *index.Index, s Status, path string) (added bool, err error) {
315+
files, err := w.Filesystem.ReadDir(path)
316+
if err != nil {
317+
return false, err
318+
}
319+
320+
for _, file := range files {
321+
name := w.Filesystem.Join(path, file.Name())
322+
323+
var a bool
324+
if file.IsDir() {
325+
a, err = w.doAddDirectory(idx, s, name)
326+
} else {
327+
a, _, err = w.doAdd(idx, s, name)
328+
}
329+
330+
if err != nil {
331+
return
332+
}
333+
334+
if !added && a {
335+
added = true
336+
}
337+
}
338+
339+
return
340+
341+
}
342+
343+
// AddGlob given a glob pattern adds all the matching files content and all his
344+
// sub-directories recursively in the worktree to the index. If any of the
345+
// file is already staged in the index no error is returned.
346+
func (w *Worktree) AddGlob(pattern string) error {
347+
files, err := util.Glob(w.Filesystem, pattern)
348+
if err != nil {
349+
return err
350+
}
351+
352+
if len(files) == 0 {
353+
return ErrGlobNoMatches
354+
}
355+
356+
s, err := w.Status()
357+
if err != nil {
358+
return err
359+
}
360+
361+
idx, err := w.r.Storer.Index()
362+
if err != nil {
363+
return err
364+
}
365+
366+
var saveIndex bool
367+
for _, file := range files {
368+
fi, err := w.Filesystem.Lstat(file)
369+
if err != nil {
370+
return err
371+
}
372+
373+
var added bool
374+
if fi.IsDir() {
375+
added, err = w.doAddDirectory(idx, s, file)
376+
} else {
377+
added, _, err = w.doAdd(idx, s, file)
378+
}
379+
380+
if err != nil {
381+
return err
382+
}
383+
384+
if !saveIndex && added {
385+
saveIndex = true
386+
}
387+
}
388+
389+
if saveIndex {
390+
return w.r.Storer.SetIndex(idx)
391+
}
392+
393+
return nil
394+
}
395+
396+
// doAdd create a new blob from path and update the index, added is true if
397+
// the file added is different from the index.
398+
func (w *Worktree) doAdd(idx *index.Index, s Status, path string) (added bool, h plumbing.Hash, err error) {
399+
h, err = w.copyFileToStorage(path)
254400
if err != nil {
255401
if os.IsNotExist(err) {
256-
h, err = w.deleteFromIndex(path)
402+
added = true
403+
h, err = w.deleteFromIndex(idx, path)
257404
}
258-
return h, err
405+
406+
return
259407
}
260408

261409
if s.File(path).Worktree == Unmodified {
262-
return h, nil
410+
return false, h, nil
263411
}
264412

265-
if err := w.addOrUpdateFileToIndex(path, h); err != nil {
266-
return h, err
413+
if err := w.addOrUpdateFileToIndex(idx, path, h); err != nil {
414+
return false, h, err
267415
}
268416

269-
return h, err
417+
return true, h, err
270418
}
271419

272420
func (w *Worktree) copyFileToStorage(path string) (hash plumbing.Hash, err error) {
@@ -324,28 +472,17 @@ func (w *Worktree) fillEncodedObjectFromSymlink(dst io.Writer, path string, fi o
324472
return err
325473
}
326474

327-
func (w *Worktree) addOrUpdateFileToIndex(filename string, h plumbing.Hash) error {
328-
idx, err := w.r.Storer.Index()
329-
if err != nil {
330-
return err
331-
}
332-
475+
func (w *Worktree) addOrUpdateFileToIndex(idx *index.Index, filename string, h plumbing.Hash) error {
333476
e, err := idx.Entry(filename)
334477
if err != nil && err != index.ErrEntryNotFound {
335478
return err
336479
}
337480

338481
if err == index.ErrEntryNotFound {
339-
if err := w.doAddFileToIndex(idx, filename, h); err != nil {
340-
return err
341-
}
342-
} else {
343-
if err := w.doUpdateFileToIndex(e, filename, h); err != nil {
344-
return err
345-
}
482+
return w.doAddFileToIndex(idx, filename, h)
346483
}
347484

348-
return w.r.Storer.SetIndex(idx)
485+
return w.doUpdateFileToIndex(e, filename, h)
349486
}
350487

351488
func (w *Worktree) doAddFileToIndex(idx *index.Index, filename string, h plumbing.Hash) error {
@@ -378,26 +515,30 @@ func (w *Worktree) doUpdateFileToIndex(e *index.Entry, filename string, h plumbi
378515

379516
// Remove removes files from the working tree and from the index.
380517
func (w *Worktree) Remove(path string) (plumbing.Hash, error) {
381-
hash, err := w.deleteFromIndex(path)
518+
idx, err := w.r.Storer.Index()
382519
if err != nil {
383520
return plumbing.ZeroHash, err
384521
}
385522

386-
return hash, w.deleteFromFilesystem(path)
387-
}
388-
389-
func (w *Worktree) deleteFromIndex(path string) (plumbing.Hash, error) {
390-
idx, err := w.r.Storer.Index()
523+
hash, err := w.deleteFromIndex(idx, path)
391524
if err != nil {
392525
return plumbing.ZeroHash, err
393526
}
394527

528+
if err := w.deleteFromFilesystem(path); err != nil {
529+
return hash, err
530+
}
531+
532+
return hash, w.r.Storer.SetIndex(idx)
533+
}
534+
535+
func (w *Worktree) deleteFromIndex(idx *index.Index, path string) (plumbing.Hash, error) {
395536
e, err := idx.Remove(path)
396537
if err != nil {
397538
return plumbing.ZeroHash, err
398539
}
399540

400-
return e.Hash, w.r.Storer.SetIndex(idx)
541+
return e.Hash, nil
401542
}
402543

403544
func (w *Worktree) deleteFromFilesystem(path string) error {
@@ -420,7 +561,12 @@ func (w *Worktree) Move(from, to string) (plumbing.Hash, error) {
420561
return plumbing.ZeroHash, ErrDestinationExists
421562
}
422563

423-
hash, err := w.deleteFromIndex(from)
564+
idx, err := w.r.Storer.Index()
565+
if err != nil {
566+
return plumbing.ZeroHash, err
567+
}
568+
569+
hash, err := w.deleteFromIndex(idx, from)
424570
if err != nil {
425571
return plumbing.ZeroHash, err
426572
}
@@ -429,5 +575,9 @@ func (w *Worktree) Move(from, to string) (plumbing.Hash, error) {
429575
return hash, err
430576
}
431577

432-
return hash, w.addOrUpdateFileToIndex(to, hash)
578+
if err := w.addOrUpdateFileToIndex(idx, to, hash); err != nil {
579+
return hash, err
580+
}
581+
582+
return hash, w.r.Storer.SetIndex(idx)
433583
}

0 commit comments

Comments
 (0)