aboutsummaryrefslogblamecommitdiffstats
path: root/plumbing/protocol/packp/uppackresp.go
blob: a1179563d7618cdf3796ab65ba772c4539d82aa9 (plain) (tree)












































































                                                                                          
package packp

import (
	"errors"
	"io"

	"gopkg.in/src-d/go-git.v4/plumbing/protocol/packp/capability"
)

// ErrUploadPackResponseNotDecoded is returned if Read is called without
// decoding first
var ErrUploadPackResponseNotDecoded = errors.New("upload-pack-response should be decoded")

// UploadPackResponse contains all the information responded by the upload-pack
// service, the response implements io.ReadCloser that allows to read the
// packfile directly from it.
type UploadPackResponse struct {
	ShallowUpdate
	ServerResponse
	r io.ReadCloser

	isShallow  bool
	isMultiACK bool
	isOk       bool
}

// NewUploadPackResponse create a new UploadPackResponse instance, the request
// being responded by the response is required.
func NewUploadPackResponse(req *UploadPackRequest) *UploadPackResponse {
	isShallow := !req.Depth.IsZero()
	isMultiACK := req.Capabilities.Supports(capability.MultiACK) ||
		req.Capabilities.Supports(capability.MultiACKDetailed)

	return &UploadPackResponse{
		isShallow:  isShallow,
		isMultiACK: isMultiACK,
	}
}

// Decode decodes all the responses sent by upload-pack service into the struct
// and prepares it to read the packfile using the Read method
func (r *UploadPackResponse) Decode(reader io.ReadCloser) error {
	if r.isShallow {
		if err := r.ShallowUpdate.Decode(reader); err != nil {
			return err
		}
	}

	if err := r.ServerResponse.Decode(reader, r.isMultiACK); err != nil {
		return err
	}

	// now the reader is ready to read the packfile content
	r.r = reader

	return nil
}

// Read reads the packfile data, if the request was done with any Sideband
// capability the content read should be demultiplexed. If the methods wasn't
// called before the ErrUploadPackResponseNotDecoded will be return
func (r *UploadPackResponse) Read(p []byte) (int, error) {
	if r.r == nil {
		return 0, ErrUploadPackResponseNotDecoded
	}

	return r.r.Read(p)
}

// Close the underlying reader, if any
func (r *UploadPackResponse) Close() error {
	if r.r == nil {
		return nil
	}

	return r.r.Close()
}