mirror of
https://github.com/go-gitea/gitea.git
synced 2024-08-28 15:17:26 +02:00
* Inital routes to git refs api * Git refs API implementation * Update swagger * Fix copyright * Make swagger happy add basic test * Fix test * Fix test again :)
146 lines
3.0 KiB
Go
146 lines
3.0 KiB
Go
package packp
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"io"
|
|
"time"
|
|
|
|
"gopkg.in/src-d/go-git.v4/plumbing"
|
|
"gopkg.in/src-d/go-git.v4/plumbing/format/pktline"
|
|
)
|
|
|
|
// Encode writes the UlReq encoding of u to the stream.
|
|
//
|
|
// All the payloads will end with a newline character. Wants and
|
|
// shallows are sorted alphabetically. A depth of 0 means no depth
|
|
// request is sent.
|
|
func (u *UploadRequest) Encode(w io.Writer) error {
|
|
e := newUlReqEncoder(w)
|
|
return e.Encode(u)
|
|
}
|
|
|
|
type ulReqEncoder struct {
|
|
pe *pktline.Encoder // where to write the encoded data
|
|
data *UploadRequest // the data to encode
|
|
err error // sticky error
|
|
}
|
|
|
|
func newUlReqEncoder(w io.Writer) *ulReqEncoder {
|
|
return &ulReqEncoder{
|
|
pe: pktline.NewEncoder(w),
|
|
}
|
|
}
|
|
|
|
func (e *ulReqEncoder) Encode(v *UploadRequest) error {
|
|
e.data = v
|
|
|
|
if len(v.Wants) == 0 {
|
|
return fmt.Errorf("empty wants provided")
|
|
}
|
|
|
|
plumbing.HashesSort(e.data.Wants)
|
|
for state := e.encodeFirstWant; state != nil; {
|
|
state = state()
|
|
}
|
|
|
|
return e.err
|
|
}
|
|
|
|
func (e *ulReqEncoder) encodeFirstWant() stateFn {
|
|
var err error
|
|
if e.data.Capabilities.IsEmpty() {
|
|
err = e.pe.Encodef("want %s\n", e.data.Wants[0])
|
|
} else {
|
|
err = e.pe.Encodef(
|
|
"want %s %s\n",
|
|
e.data.Wants[0],
|
|
e.data.Capabilities.String(),
|
|
)
|
|
}
|
|
|
|
if err != nil {
|
|
e.err = fmt.Errorf("encoding first want line: %s", err)
|
|
return nil
|
|
}
|
|
|
|
return e.encodeAditionalWants
|
|
}
|
|
|
|
func (e *ulReqEncoder) encodeAditionalWants() stateFn {
|
|
last := e.data.Wants[0]
|
|
for _, w := range e.data.Wants[1:] {
|
|
if bytes.Equal(last[:], w[:]) {
|
|
continue
|
|
}
|
|
|
|
if err := e.pe.Encodef("want %s\n", w); err != nil {
|
|
e.err = fmt.Errorf("encoding want %q: %s", w, err)
|
|
return nil
|
|
}
|
|
|
|
last = w
|
|
}
|
|
|
|
return e.encodeShallows
|
|
}
|
|
|
|
func (e *ulReqEncoder) encodeShallows() stateFn {
|
|
plumbing.HashesSort(e.data.Shallows)
|
|
|
|
var last plumbing.Hash
|
|
for _, s := range e.data.Shallows {
|
|
if bytes.Equal(last[:], s[:]) {
|
|
continue
|
|
}
|
|
|
|
if err := e.pe.Encodef("shallow %s\n", s); err != nil {
|
|
e.err = fmt.Errorf("encoding shallow %q: %s", s, err)
|
|
return nil
|
|
}
|
|
|
|
last = s
|
|
}
|
|
|
|
return e.encodeDepth
|
|
}
|
|
|
|
func (e *ulReqEncoder) encodeDepth() stateFn {
|
|
switch depth := e.data.Depth.(type) {
|
|
case DepthCommits:
|
|
if depth != 0 {
|
|
commits := int(depth)
|
|
if err := e.pe.Encodef("deepen %d\n", commits); err != nil {
|
|
e.err = fmt.Errorf("encoding depth %d: %s", depth, err)
|
|
return nil
|
|
}
|
|
}
|
|
case DepthSince:
|
|
when := time.Time(depth).UTC()
|
|
if err := e.pe.Encodef("deepen-since %d\n", when.Unix()); err != nil {
|
|
e.err = fmt.Errorf("encoding depth %s: %s", when, err)
|
|
return nil
|
|
}
|
|
case DepthReference:
|
|
reference := string(depth)
|
|
if err := e.pe.Encodef("deepen-not %s\n", reference); err != nil {
|
|
e.err = fmt.Errorf("encoding depth %s: %s", reference, err)
|
|
return nil
|
|
}
|
|
default:
|
|
e.err = fmt.Errorf("unsupported depth type")
|
|
return nil
|
|
}
|
|
|
|
return e.encodeFlush
|
|
}
|
|
|
|
func (e *ulReqEncoder) encodeFlush() stateFn {
|
|
if err := e.pe.Flush(); err != nil {
|
|
e.err = fmt.Errorf("encoding flush-pkt: %s", err)
|
|
return nil
|
|
}
|
|
|
|
return nil
|
|
}
|