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

Commit 6d23b50

Browse files
committed
new methods Worktree.[AddGlob|RemoveBlob] and recursive Worktree.[Add|Remove]
Signed-off-by: Máximo Cuadros <mcuadros@gmail.com>
1 parent 9fb58fc commit 6d23b50

File tree

2 files changed

+254
-77
lines changed

2 files changed

+254
-77
lines changed

worktree_status.go

Lines changed: 129 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import (
55
"errors"
66
"io"
77
"os"
8+
"path"
9+
"path/filepath"
810

911
"gopkg.in/src-d/go-billy.v4/util"
1012
"gopkg.in/src-d/go-git.v4/plumbing"
@@ -24,10 +26,8 @@ var (
2426
// the worktree.
2527
ErrDestinationExists = errors.New("destination exists")
2628
// ErrGlobNoMatches in an AddGlob if the glob pattern does not match any
27-
// file in the worktree.ErrNotDirectory
29+
// files in the worktree.
2830
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")
3131
)
3232

3333
// Status returns the working tree status.
@@ -252,8 +252,12 @@ func diffTreeIsEquals(a, b noder.Hasher) bool {
252252

253253
// Add adds the file contents of a file in the worktree to the index. if the
254254
// 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.
255+
// from the Workspace is given, the file is removed from the index. If a
256+
// directory given, adds the files and all his sub-directories recursively in
257+
// the worktree to the index. If any of the files is already staged in the index
258+
// no error is returned. When path is a file, the blob.Hash is returned.
256259
func (w *Worktree) Add(path string) (plumbing.Hash, error) {
260+
// TODO(mcuadros): remove plumbing.Hash from signature at v5.
257261
s, err := w.Status()
258262
if err != nil {
259263
return plumbing.ZeroHash, err
@@ -264,67 +268,41 @@ func (w *Worktree) Add(path string) (plumbing.Hash, error) {
264268
return plumbing.ZeroHash, err
265269
}
266270

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-
}
271+
var h plumbing.Hash
272+
var added bool
275273

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 {
283274
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
275+
if err != nil || !fi.IsDir() {
276+
added, h, err = w.doAddFile(idx, s, path)
277+
} else {
278+
added, err = w.doAddDirectory(idx, s, path)
300279
}
301280

302-
added, err := w.doAddDirectory(idx, s, path)
303281
if err != nil {
304-
return err
282+
return h, err
305283
}
306284

307285
if !added {
308-
return nil
286+
return h, nil
309287
}
310288

311-
return w.r.Storer.SetIndex(idx)
289+
return h, w.r.Storer.SetIndex(idx)
312290
}
313291

314-
func (w *Worktree) doAddDirectory(idx *index.Index, s Status, path string) (added bool, err error) {
315-
files, err := w.Filesystem.ReadDir(path)
292+
func (w *Worktree) doAddDirectory(idx *index.Index, s Status, directory string) (added bool, err error) {
293+
files, err := w.Filesystem.ReadDir(directory)
316294
if err != nil {
317295
return false, err
318296
}
319297

320298
for _, file := range files {
321-
name := w.Filesystem.Join(path, file.Name())
299+
name := path.Join(directory, file.Name())
322300

323301
var a bool
324302
if file.IsDir() {
325303
a, err = w.doAddDirectory(idx, s, name)
326304
} else {
327-
a, _, err = w.doAdd(idx, s, name)
305+
a, _, err = w.doAddFile(idx, s, name)
328306
}
329307

330308
if err != nil {
@@ -337,12 +315,11 @@ func (w *Worktree) doAddDirectory(idx *index.Index, s Status, path string) (adde
337315
}
338316

339317
return
340-
341318
}
342319

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.
320+
// AddGlob adds all paths, matching pattern, to the index. If pattern matches a
321+
// directory path, all directory contents are added to the index recursively. No
322+
// error is returned if all matching paths are already staged in index.
346323
func (w *Worktree) AddGlob(pattern string) error {
347324
files, err := util.Glob(w.Filesystem, pattern)
348325
if err != nil {
@@ -374,7 +351,7 @@ func (w *Worktree) AddGlob(pattern string) error {
374351
if fi.IsDir() {
375352
added, err = w.doAddDirectory(idx, s, file)
376353
} else {
377-
added, _, err = w.doAdd(idx, s, file)
354+
added, _, err = w.doAddFile(idx, s, file)
378355
}
379356

380357
if err != nil {
@@ -393,9 +370,13 @@ func (w *Worktree) AddGlob(pattern string) error {
393370
return nil
394371
}
395372

396-
// doAdd create a new blob from path and update the index, added is true if
373+
// doAddFile create a new blob from path and update the index, added is true if
397374
// 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) {
375+
func (w *Worktree) doAddFile(idx *index.Index, s Status, path string) (added bool, h plumbing.Hash, err error) {
376+
if s.File(path).Worktree == Unmodified {
377+
return false, h, nil
378+
}
379+
399380
h, err = w.copyFileToStorage(path)
400381
if err != nil {
401382
if os.IsNotExist(err) {
@@ -406,10 +387,6 @@ func (w *Worktree) doAdd(idx *index.Index, s Status, path string) (added bool, h
406387
return
407388
}
408389

409-
if s.File(path).Worktree == Unmodified {
410-
return false, h, nil
411-
}
412-
413390
if err := w.addOrUpdateFileToIndex(idx, path, h); err != nil {
414391
return false, h, err
415392
}
@@ -486,10 +463,7 @@ func (w *Worktree) addOrUpdateFileToIndex(idx *index.Index, filename string, h p
486463
}
487464

488465
func (w *Worktree) doAddFileToIndex(idx *index.Index, filename string, h plumbing.Hash) error {
489-
e := &index.Entry{Name: filename}
490-
idx.Entries = append(idx.Entries, e)
491-
492-
return w.doUpdateFileToIndex(e, filename, h)
466+
return w.doUpdateFileToIndex(idx.Add(filename), filename, h)
493467
}
494468

495469
func (w *Worktree) doUpdateFileToIndex(e *index.Entry, filename string, h plumbing.Hash) error {
@@ -515,21 +489,79 @@ func (w *Worktree) doUpdateFileToIndex(e *index.Entry, filename string, h plumbi
515489

516490
// Remove removes files from the working tree and from the index.
517491
func (w *Worktree) Remove(path string) (plumbing.Hash, error) {
492+
// TODO(mcuadros): remove plumbing.Hash from signature at v5.
518493
idx, err := w.r.Storer.Index()
519494
if err != nil {
520495
return plumbing.ZeroHash, err
521496
}
522497

523-
hash, err := w.deleteFromIndex(idx, path)
498+
var h plumbing.Hash
499+
500+
fi, err := w.Filesystem.Lstat(path)
501+
if err != nil || !fi.IsDir() {
502+
h, err = w.doRemoveFile(idx, path)
503+
} else {
504+
_, err = w.doRemoveDirectory(idx, path)
505+
}
524506
if err != nil {
525-
return plumbing.ZeroHash, err
507+
return h, err
526508
}
527509

528-
if err := w.deleteFromFilesystem(path); err != nil {
529-
return hash, err
510+
return h, w.r.Storer.SetIndex(idx)
511+
}
512+
513+
func (w *Worktree) doRemoveDirectory(idx *index.Index, directory string) (removed bool, err error) {
514+
files, err := w.Filesystem.ReadDir(directory)
515+
if err != nil {
516+
return false, err
530517
}
531518

532-
return hash, w.r.Storer.SetIndex(idx)
519+
for _, file := range files {
520+
name := path.Join(directory, file.Name())
521+
522+
var r bool
523+
if file.IsDir() {
524+
r, err = w.doRemoveDirectory(idx, name)
525+
} else {
526+
_, err = w.doRemoveFile(idx, name)
527+
if err == index.ErrEntryNotFound {
528+
err = nil
529+
}
530+
}
531+
532+
if err != nil {
533+
return
534+
}
535+
536+
if !removed && r {
537+
removed = true
538+
}
539+
}
540+
541+
err = w.removeEmptyDirectory(directory)
542+
return
543+
}
544+
545+
func (w *Worktree) removeEmptyDirectory(path string) error {
546+
files, err := w.Filesystem.ReadDir(path)
547+
if err != nil {
548+
return err
549+
}
550+
551+
if len(files) != 0 {
552+
return nil
553+
}
554+
555+
return w.Filesystem.Remove(path)
556+
}
557+
558+
func (w *Worktree) doRemoveFile(idx *index.Index, path string) (plumbing.Hash, error) {
559+
hash, err := w.deleteFromIndex(idx, path)
560+
if err != nil {
561+
return plumbing.ZeroHash, err
562+
}
563+
564+
return hash, w.deleteFromFilesystem(path)
533565
}
534566

535567
func (w *Worktree) deleteFromIndex(idx *index.Index, path string) (plumbing.Hash, error) {
@@ -550,9 +582,43 @@ func (w *Worktree) deleteFromFilesystem(path string) error {
550582
return err
551583
}
552584

585+
// RemoveGlob removes all paths, matching pattern, from the index. If pattern
586+
// matches a directory path, all directory contents are removed from the index
587+
// recursively.
588+
func (w *Worktree) RemoveGlob(pattern string) error {
589+
idx, err := w.r.Storer.Index()
590+
if err != nil {
591+
return err
592+
}
593+
594+
entries, err := idx.Glob(pattern)
595+
if err != nil {
596+
return err
597+
}
598+
599+
for _, e := range entries {
600+
file := filepath.FromSlash(e.Name)
601+
if _, err := w.Filesystem.Lstat(file); err != nil && !os.IsNotExist(err) {
602+
return err
603+
}
604+
605+
if _, err := w.doRemoveFile(idx, file); err != nil {
606+
return err
607+
}
608+
609+
dir, _ := filepath.Split(file)
610+
if err := w.removeEmptyDirectory(dir); err != nil {
611+
return err
612+
}
613+
}
614+
615+
return w.r.Storer.SetIndex(idx)
616+
}
617+
553618
// Move moves or rename a file in the worktree and the index, directories are
554619
// not supported.
555620
func (w *Worktree) Move(from, to string) (plumbing.Hash, error) {
621+
// TODO(mcuadros): support directories and/or implement support for glob
556622
if _, err := w.Filesystem.Lstat(from); err != nil {
557623
return plumbing.ZeroHash, err
558624
}

0 commit comments

Comments
 (0)