99 "os"
1010 "path/filepath"
1111 "strings"
12+ "sync"
1213
1314 "gopkg.in/src-d/go-git.v4/config"
1415 "gopkg.in/src-d/go-git.v4/plumbing"
@@ -304,6 +305,7 @@ func (w *Worktree) resetIndex(t *object.Tree) error {
304305 if err != nil {
305306 return err
306307 }
308+ b := newIndexBuilder (idx )
307309
308310 changes , err := w .diffTreeWithStaging (t , true )
309311 if err != nil {
@@ -330,19 +332,20 @@ func (w *Worktree) resetIndex(t *object.Tree) error {
330332 name = ch .From .String ()
331333 }
332334
333- _ , _ = idx .Remove (name )
335+ b .Remove (name )
334336 if e == nil {
335337 continue
336338 }
337339
338- idx . Entries = append ( idx . Entries , & index.Entry {
340+ b . Add ( & index.Entry {
339341 Name : name ,
340342 Hash : e .Hash ,
341343 Mode : e .Mode ,
342344 })
343345
344346 }
345347
348+ b .Write (idx )
346349 return w .r .Storer .SetIndex (idx )
347350}
348351
@@ -356,17 +359,19 @@ func (w *Worktree) resetWorktree(t *object.Tree) error {
356359 if err != nil {
357360 return err
358361 }
362+ b := newIndexBuilder (idx )
359363
360364 for _ , ch := range changes {
361- if err := w .checkoutChange (ch , t , idx ); err != nil {
365+ if err := w .checkoutChange (ch , t , b ); err != nil {
362366 return err
363367 }
364368 }
365369
370+ b .Write (idx )
366371 return w .r .Storer .SetIndex (idx )
367372}
368373
369- func (w * Worktree ) checkoutChange (ch merkletrie.Change , t * object.Tree , idx * index. Index ) error {
374+ func (w * Worktree ) checkoutChange (ch merkletrie.Change , t * object.Tree , idx * indexBuilder ) error {
370375 a , err := ch .Action ()
371376 if err != nil {
372377 return err
@@ -445,7 +450,7 @@ func (w *Worktree) setHEADCommit(commit plumbing.Hash) error {
445450func (w * Worktree ) checkoutChangeSubmodule (name string ,
446451 a merkletrie.Action ,
447452 e * object.TreeEntry ,
448- idx * index. Index ,
453+ idx * indexBuilder ,
449454) error {
450455 switch a {
451456 case merkletrie .Modify :
@@ -479,11 +484,11 @@ func (w *Worktree) checkoutChangeRegularFile(name string,
479484 a merkletrie.Action ,
480485 t * object.Tree ,
481486 e * object.TreeEntry ,
482- idx * index. Index ,
487+ idx * indexBuilder ,
483488) error {
484489 switch a {
485490 case merkletrie .Modify :
486- _ , _ = idx .Remove (name )
491+ idx .Remove (name )
487492
488493 // to apply perm changes the file is deleted, billy doesn't implement
489494 // chmod
@@ -508,6 +513,12 @@ func (w *Worktree) checkoutChangeRegularFile(name string,
508513 return nil
509514}
510515
516+ var copyBufferPool = sync.Pool {
517+ New : func () interface {} {
518+ return make ([]byte , 32 * 1024 )
519+ },
520+ }
521+
511522func (w * Worktree ) checkoutFile (f * object.File ) (err error ) {
512523 mode , err := f .Mode .ToOSFileMode ()
513524 if err != nil {
@@ -531,8 +542,9 @@ func (w *Worktree) checkoutFile(f *object.File) (err error) {
531542 }
532543
533544 defer ioutil .CheckClose (to , & err )
534-
535- _ , err = io .Copy (to , from )
545+ buf := copyBufferPool .Get ().([]byte )
546+ _ , err = io .CopyBuffer (to , from , buf )
547+ copyBufferPool .Put (buf )
536548 return
537549}
538550
@@ -569,19 +581,18 @@ func (w *Worktree) checkoutFileSymlink(f *object.File) (err error) {
569581 return
570582}
571583
572- func (w * Worktree ) addIndexFromTreeEntry (name string , f * object.TreeEntry , idx * index. Index ) error {
573- _ , _ = idx .Remove (name )
574- idx .Entries = append ( idx . Entries , & index.Entry {
584+ func (w * Worktree ) addIndexFromTreeEntry (name string , f * object.TreeEntry , idx * indexBuilder ) error {
585+ idx .Remove (name )
586+ idx .Add ( & index.Entry {
575587 Hash : f .Hash ,
576588 Name : name ,
577589 Mode : filemode .Submodule ,
578590 })
579-
580591 return nil
581592}
582593
583- func (w * Worktree ) addIndexFromFile (name string , h plumbing.Hash , idx * index. Index ) error {
584- _ , _ = idx .Remove (name )
594+ func (w * Worktree ) addIndexFromFile (name string , h plumbing.Hash , idx * indexBuilder ) error {
595+ idx .Remove (name )
585596 fi , err := w .Filesystem .Lstat (name )
586597 if err != nil {
587598 return err
@@ -605,8 +616,7 @@ func (w *Worktree) addIndexFromFile(name string, h plumbing.Hash, idx *index.Ind
605616 if fillSystemInfo != nil {
606617 fillSystemInfo (e , fi .Sys ())
607618 }
608-
609- idx .Entries = append (idx .Entries , e )
619+ idx .Add (e )
610620 return nil
611621}
612622
@@ -913,3 +923,32 @@ func doCleanDirectories(fs billy.Filesystem, dir string) error {
913923 }
914924 return nil
915925}
926+
927+ type indexBuilder struct {
928+ entries map [string ]* index.Entry
929+ }
930+
931+ func newIndexBuilder (idx * index.Index ) * indexBuilder {
932+ entries := make (map [string ]* index.Entry , len (idx .Entries ))
933+ for _ , e := range idx .Entries {
934+ entries [e .Name ] = e
935+ }
936+ return & indexBuilder {
937+ entries : entries ,
938+ }
939+ }
940+
941+ func (b * indexBuilder ) Write (idx * index.Index ) {
942+ idx .Entries = idx .Entries [:0 ]
943+ for _ , e := range b .entries {
944+ idx .Entries = append (idx .Entries , e )
945+ }
946+ }
947+
948+ func (b * indexBuilder ) Add (e * index.Entry ) {
949+ b .entries [e .Name ] = e
950+ }
951+
952+ func (b * indexBuilder ) Remove (name string ) {
953+ delete (b .entries , filepath .ToSlash (name ))
954+ }
0 commit comments