Merge pull request #569 from erizocosmico/fix/race-condition-dotgit-refs

dotgit: avoid duplicated references returned by Refs
diff --git a/storage/filesystem/internal/dotgit/dotgit.go b/storage/filesystem/internal/dotgit/dotgit.go
index b50cdab..2840bc7 100644
--- a/storage/filesystem/internal/dotgit/dotgit.go
+++ b/storage/filesystem/internal/dotgit/dotgit.go
@@ -266,11 +266,12 @@
 // Symbolic references are resolved and included in the output.
 func (d *DotGit) Refs() ([]*plumbing.Reference, error) {
 	var refs []*plumbing.Reference
-	if err := d.addRefsFromPackedRefs(&refs); err != nil {
+	var seen = make(map[plumbing.ReferenceName]bool)
+	if err := d.addRefsFromRefDir(&refs, seen); err != nil {
 		return nil, err
 	}
 
-	if err := d.addRefsFromRefDir(&refs); err != nil {
+	if err := d.addRefsFromPackedRefs(&refs, seen); err != nil {
 		return nil, err
 	}
 
@@ -359,13 +360,16 @@
 	return d.rewritePackedRefsWithoutRef(name)
 }
 
-func (d *DotGit) addRefsFromPackedRefs(refs *[]*plumbing.Reference) (err error) {
+func (d *DotGit) addRefsFromPackedRefs(refs *[]*plumbing.Reference, seen map[plumbing.ReferenceName]bool) (err error) {
 	if err := d.syncPackedRefs(); err != nil {
 		return err
 	}
 
-	for _, ref := range d.cachedPackedRefs {
-		*refs = append(*refs, ref)
+	for name, ref := range d.cachedPackedRefs {
+		if !seen[name] {
+			*refs = append(*refs, ref)
+			seen[name] = true
+		}
 	}
 
 	return nil
@@ -448,11 +452,11 @@
 	}
 }
 
-func (d *DotGit) addRefsFromRefDir(refs *[]*plumbing.Reference) error {
-	return d.walkReferencesTree(refs, []string{refsPath})
+func (d *DotGit) addRefsFromRefDir(refs *[]*plumbing.Reference, seen map[plumbing.ReferenceName]bool) error {
+	return d.walkReferencesTree(refs, []string{refsPath}, seen)
 }
 
-func (d *DotGit) walkReferencesTree(refs *[]*plumbing.Reference, relPath []string) error {
+func (d *DotGit) walkReferencesTree(refs *[]*plumbing.Reference, relPath []string, seen map[plumbing.ReferenceName]bool) error {
 	files, err := d.fs.ReadDir(d.fs.Join(relPath...))
 	if err != nil {
 		if os.IsNotExist(err) {
@@ -465,7 +469,7 @@
 	for _, f := range files {
 		newRelPath := append(append([]string(nil), relPath...), f.Name())
 		if f.IsDir() {
-			if err = d.walkReferencesTree(refs, newRelPath); err != nil {
+			if err = d.walkReferencesTree(refs, newRelPath, seen); err != nil {
 				return err
 			}
 
@@ -477,8 +481,9 @@
 			return err
 		}
 
-		if ref != nil {
+		if ref != nil && !seen[ref.Name()] {
 			*refs = append(*refs, ref)
+			seen[ref.Name()] = true
 		}
 	}