···2233import (
44 "fmt"
55+ "sort"
56 "strings"
6778 "gopkg.in/src-d/go-git.v4/plumbing"
···68696970func (a *AdvRefs) AllReferences() (memory.ReferenceStorage, error) {
7071 s := memory.ReferenceStorage{}
7171- if err := addRefs(s, a); err != nil {
7272+ if err := a.addRefs(s); err != nil {
7273 return s, plumbing.NewUnexpectedError(err)
7374 }
74757576 return s, nil
7677}
77787878-func addRefs(s storer.ReferenceStorer, ar *AdvRefs) error {
7979- for name, hash := range ar.References {
7979+func (a *AdvRefs) addRefs(s storer.ReferenceStorer) error {
8080+ for name, hash := range a.References {
8081 ref := plumbing.NewReferenceFromStrings(name, hash.String())
8182 if err := s.SetReference(ref); err != nil {
8283 return err
8384 }
8485 }
85868686- return addSymbolicRefs(s, ar)
8787+ if a.supportSymrefs() {
8888+ return a.addSymbolicRefs(s)
8989+ }
9090+9191+ return a.resolveHead(s)
8792}
88938989-func addSymbolicRefs(s storer.ReferenceStorer, ar *AdvRefs) error {
9090- if !hasSymrefs(ar) {
9494+// If the server does not support symrefs capability,
9595+// we need to guess the reference where HEAD is pointing to.
9696+//
9797+// Git versions prior to 1.8.4.3 has an special procedure to get
9898+// the reference where is pointing to HEAD:
9999+// - Check if a reference called master exists. If exists and it
100100+// has the same hash as HEAD hash, we can say that HEAD is pointing to master
101101+// - If master does not exists or does not have the same hash as HEAD,
102102+// order references and check in that order if that reference has the same
103103+// hash than HEAD. If yes, set HEAD pointing to that branch hash
104104+// - If no reference is found, throw an error
105105+func (a *AdvRefs) resolveHead(s storer.ReferenceStorer) error {
106106+ if a.Head == nil {
91107 return nil
92108 }
931099494- for _, symref := range ar.Capabilities.Get(capability.SymRef) {
110110+ ref, err := s.Reference(plumbing.ReferenceName(plumbing.Master))
111111+112112+ // check first if HEAD is pointing to master
113113+ if err == nil {
114114+ ok, err := a.createHeadIfCorrectReference(ref, s)
115115+ if err != nil {
116116+ return err
117117+ }
118118+119119+ if ok {
120120+ return nil
121121+ }
122122+ }
123123+124124+ if err != nil && err != plumbing.ErrReferenceNotFound {
125125+ return err
126126+ }
127127+128128+ // From here we are trying to guess the branch that HEAD is pointing
129129+ refIter, err := s.IterReferences()
130130+ if err != nil {
131131+ return err
132132+ }
133133+134134+ var refNames []string
135135+ err = refIter.ForEach(func(r *plumbing.Reference) error {
136136+ refNames = append(refNames, string(r.Name()))
137137+ return nil
138138+ })
139139+ if err != nil {
140140+ return err
141141+ }
142142+143143+ sort.Strings(refNames)
144144+145145+ var headSet bool
146146+ for _, refName := range refNames {
147147+ ref, err := s.Reference(plumbing.ReferenceName(refName))
148148+ if err != nil {
149149+ return err
150150+ }
151151+ ok, err := a.createHeadIfCorrectReference(ref, s)
152152+ if err != nil {
153153+ return err
154154+ }
155155+ if ok {
156156+ headSet = true
157157+ break
158158+ }
159159+ }
160160+161161+ if !headSet {
162162+ return plumbing.ErrReferenceNotFound
163163+ }
164164+165165+ return nil
166166+}
167167+168168+func (a *AdvRefs) createHeadIfCorrectReference(
169169+ reference *plumbing.Reference,
170170+ s storer.ReferenceStorer) (bool, error) {
171171+ if reference.Hash() == *a.Head {
172172+ headRef := plumbing.NewSymbolicReference(plumbing.HEAD, reference.Name())
173173+ if err := s.SetReference(headRef); err != nil {
174174+ return false, err
175175+ }
176176+177177+ return true, nil
178178+ }
179179+180180+ return false, nil
181181+}
182182+183183+func (a *AdvRefs) addSymbolicRefs(s storer.ReferenceStorer) error {
184184+ for _, symref := range a.Capabilities.Get(capability.SymRef) {
95185 chunks := strings.Split(symref, ":")
96186 if len(chunks) != 2 {
97187 err := fmt.Errorf("bad number of `:` in symref value (%q)", symref)
···108198 return nil
109199}
110200111111-func hasSymrefs(ar *AdvRefs) bool {
112112- return ar.Capabilities.Supports(capability.SymRef)
201201+func (a *AdvRefs) supportSymrefs() bool {
202202+ return a.Capabilities.Supports(capability.SymRef)
113203}