diff options
author | Máximo Cuadros <mcuadros@gmail.com> | 2016-12-01 09:59:19 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2016-12-01 09:59:19 +0100 |
commit | c15bf1dff332873644290db0e186b8f5ad9b8fb2 (patch) | |
tree | 1dd79212333823b70f2792ad116864ea127e4a1c /plumbing/protocol/packp/ulreq.go | |
parent | 7de79aef5d4aa3100382d4df3e99525f9949e8d1 (diff) | |
download | go-git-c15bf1dff332873644290db0e186b8f5ad9b8fb2.tar.gz |
capabilities: full integration (#151)
* format/pktline: fix readPayloadLen err handling
* protocol/pakp: UploadReq validation and creation of capabilities
* protocol/pakp: AdvRef tests
* protocol/pakp: capability.List.Delete
* protocol: filter unsupported capabilities
* remote capability negociation
* transport: UploadRequest validation
* requested changes
Diffstat (limited to 'plumbing/protocol/packp/ulreq.go')
-rw-r--r-- | plumbing/protocol/packp/ulreq.go | 105 |
1 files changed, 98 insertions, 7 deletions
diff --git a/plumbing/protocol/packp/ulreq.go b/plumbing/protocol/packp/ulreq.go index be68b26..254e85e 100644 --- a/plumbing/protocol/packp/ulreq.go +++ b/plumbing/protocol/packp/ulreq.go @@ -1,12 +1,15 @@ package packp import ( + "fmt" "time" "gopkg.in/src-d/go-git.v4/plumbing" "gopkg.in/src-d/go-git.v4/plumbing/protocol/packp/capability" ) +const DefaultAgent = "go-git/4.x" + // UploadRequest values represent the information transmitted on a // upload-request message. Values from this type are not zero-value // safe, use the New function instead. @@ -41,10 +44,9 @@ type DepthReference string func (d DepthReference) isDepth() {} -// NewUploadRequest returns a pointer to a new UlReq value, ready to be used. It has -// no capabilities, wants or shallows and an infinite depth. Please -// note that to encode an upload-request it has to have at least one -// wanted hash. +// NewUploadRequest returns a pointer to a new UploadRequest value, ready to be +// used. It has no capabilities, wants or shallows and an infinite depth. Please +// note that to encode an upload-request it has to have at least one wanted hash. func NewUploadRequest() *UploadRequest { return &UploadRequest{ Capabilities: capability.NewList(), @@ -54,7 +56,96 @@ func NewUploadRequest() *UploadRequest { } } -// Want adds a hash reference to the 'wants' list. -func (r *UploadRequest) Want(h ...plumbing.Hash) { - r.Wants = append(r.Wants, h...) +// NewUploadRequestFromCapabilities returns a pointer to a new UploadRequest +// value, the request capabilities are filled with the most optiomal ones, based +// on the adv value (advertaised capabilities), the UploadRequest generated it +// has no wants or shallows and an infinite depth. +func NewUploadRequestFromCapabilities(adv *capability.List) *UploadRequest { + r := NewUploadRequest() + + if adv.Supports(capability.MultiACKDetailed) { + r.Capabilities.Set(capability.MultiACKDetailed) + } else if adv.Supports(capability.MultiACK) { + r.Capabilities.Set(capability.MultiACK) + } + + if adv.Supports(capability.ThinPack) { + r.Capabilities.Set(capability.ThinPack) + } + + if adv.Supports(capability.OFSDelta) { + r.Capabilities.Set(capability.OFSDelta) + } + + if adv.Supports(capability.Agent) { + r.Capabilities.Set(capability.Agent, DefaultAgent) + } + + return r +} + +// Validate validates the content of UploadRequest, following the next rules: +// - Wants MUST have at least one reference +// - capability.Shallow MUST be present if Shallows is not empty +// - is a non-zero DepthCommits is given capability.Shallow MUST be present +// - is a DepthSince is given capability.Shallow MUST be present +// - is a DepthReference is given capability.DeepenNot MUST be present +// - MUST contain only maximum of one of capability.Sideband and capability.Sideband64k +// - MUST contain only maximum of one of capability.MultiACK and capability.MultiACKDetailed +func (r *UploadRequest) Validate() error { + if len(r.Wants) == 0 { + return fmt.Errorf("want can't be empty") + } + + if err := r.validateRequiredCapabilities(); err != nil { + return err + } + + if err := r.validateConflictCapabilities(); err != nil { + return err + } + + return nil +} + +func (r *UploadRequest) validateRequiredCapabilities() error { + msg := "missing capability %s" + + if len(r.Shallows) != 0 && !r.Capabilities.Supports(capability.Shallow) { + return fmt.Errorf(msg, capability.Shallow) + } + + switch r.Depth.(type) { + case DepthCommits: + if r.Depth != DepthCommits(0) { + if !r.Capabilities.Supports(capability.Shallow) { + return fmt.Errorf(msg, capability.Shallow) + } + } + case DepthSince: + if !r.Capabilities.Supports(capability.DeepenSince) { + return fmt.Errorf(msg, capability.DeepenSince) + } + case DepthReference: + if !r.Capabilities.Supports(capability.DeepenNot) { + return fmt.Errorf(msg, capability.DeepenNot) + } + } + + return nil +} + +func (r *UploadRequest) validateConflictCapabilities() error { + msg := "capabilities %s and %s are mutually exclusive" + if r.Capabilities.Supports(capability.Sideband) && + r.Capabilities.Supports(capability.Sideband64k) { + return fmt.Errorf(msg, capability.Sideband, capability.Sideband64k) + } + + if r.Capabilities.Supports(capability.MultiACK) && + r.Capabilities.Supports(capability.MultiACKDetailed) { + return fmt.Errorf(msg, capability.MultiACK, capability.MultiACKDetailed) + } + + return nil } |