mirror of
https://github.com/Luzifer/ansible-role-version.git
synced 2024-12-25 12:01:21 +00:00
114 lines
3.2 KiB
Go
114 lines
3.2 KiB
Go
|
package packp
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
"strings"
|
||
|
|
||
|
"gopkg.in/src-d/go-git.v4/plumbing"
|
||
|
"gopkg.in/src-d/go-git.v4/plumbing/protocol/packp/capability"
|
||
|
"gopkg.in/src-d/go-git.v4/plumbing/storer"
|
||
|
"gopkg.in/src-d/go-git.v4/storage/memory"
|
||
|
)
|
||
|
|
||
|
// AdvRefs values represent the information transmitted on an
|
||
|
// advertised-refs message. Values from this type are not zero-value
|
||
|
// safe, use the New function instead.
|
||
|
type AdvRefs struct {
|
||
|
// Prefix stores prefix payloads.
|
||
|
//
|
||
|
// When using this message over (smart) HTTP, you have to add a pktline
|
||
|
// before the whole thing with the following payload:
|
||
|
//
|
||
|
// '# service=$servicename" LF
|
||
|
//
|
||
|
// Moreover, some (all) git HTTP smart servers will send a flush-pkt
|
||
|
// just after the first pkt-line.
|
||
|
//
|
||
|
// To accommodate both situations, the Prefix field allow you to store
|
||
|
// any data you want to send before the actual pktlines. It will also
|
||
|
// be filled up with whatever is found on the line.
|
||
|
Prefix [][]byte
|
||
|
// Head stores the resolved HEAD reference if present.
|
||
|
// This can be present with git-upload-pack, not with git-receive-pack.
|
||
|
Head *plumbing.Hash
|
||
|
// Capabilities are the capabilities.
|
||
|
Capabilities *capability.List
|
||
|
// References are the hash references.
|
||
|
References map[string]plumbing.Hash
|
||
|
// Peeled are the peeled hash references.
|
||
|
Peeled map[string]plumbing.Hash
|
||
|
// Shallows are the shallow object ids.
|
||
|
Shallows []plumbing.Hash
|
||
|
}
|
||
|
|
||
|
// NewAdvRefs returns a pointer to a new AdvRefs value, ready to be used.
|
||
|
func NewAdvRefs() *AdvRefs {
|
||
|
return &AdvRefs{
|
||
|
Prefix: [][]byte{},
|
||
|
Capabilities: capability.NewList(),
|
||
|
References: make(map[string]plumbing.Hash),
|
||
|
Peeled: make(map[string]plumbing.Hash),
|
||
|
Shallows: []plumbing.Hash{},
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (a *AdvRefs) AddReference(r *plumbing.Reference) error {
|
||
|
switch r.Type() {
|
||
|
case plumbing.SymbolicReference:
|
||
|
v := fmt.Sprintf("%s:%s", r.Name().String(), r.Target().String())
|
||
|
a.Capabilities.Add(capability.SymRef, v)
|
||
|
case plumbing.HashReference:
|
||
|
a.References[r.Name().String()] = r.Hash()
|
||
|
default:
|
||
|
return plumbing.ErrInvalidType
|
||
|
}
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func (a *AdvRefs) AllReferences() (memory.ReferenceStorage, error) {
|
||
|
s := memory.ReferenceStorage{}
|
||
|
if err := addRefs(s, a); err != nil {
|
||
|
return s, plumbing.NewUnexpectedError(err)
|
||
|
}
|
||
|
|
||
|
return s, nil
|
||
|
}
|
||
|
|
||
|
func addRefs(s storer.ReferenceStorer, ar *AdvRefs) error {
|
||
|
for name, hash := range ar.References {
|
||
|
ref := plumbing.NewReferenceFromStrings(name, hash.String())
|
||
|
if err := s.SetReference(ref); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return addSymbolicRefs(s, ar)
|
||
|
}
|
||
|
|
||
|
func addSymbolicRefs(s storer.ReferenceStorer, ar *AdvRefs) error {
|
||
|
if !hasSymrefs(ar) {
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
for _, symref := range ar.Capabilities.Get(capability.SymRef) {
|
||
|
chunks := strings.Split(symref, ":")
|
||
|
if len(chunks) != 2 {
|
||
|
err := fmt.Errorf("bad number of `:` in symref value (%q)", symref)
|
||
|
return plumbing.NewUnexpectedError(err)
|
||
|
}
|
||
|
name := plumbing.ReferenceName(chunks[0])
|
||
|
target := plumbing.ReferenceName(chunks[1])
|
||
|
ref := plumbing.NewSymbolicReference(name, target)
|
||
|
if err := s.SetReference(ref); err != nil {
|
||
|
return nil
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func hasSymrefs(ar *AdvRefs) bool {
|
||
|
return ar.Capabilities.Supports(capability.SymRef)
|
||
|
}
|