本站源代码
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

110 lines
2.7KB

  1. package packp
  2. import (
  3. "errors"
  4. "io"
  5. "bufio"
  6. "gopkg.in/src-d/go-git.v4/plumbing/protocol/packp/capability"
  7. "gopkg.in/src-d/go-git.v4/utils/ioutil"
  8. )
  9. // ErrUploadPackResponseNotDecoded is returned if Read is called without
  10. // decoding first
  11. var ErrUploadPackResponseNotDecoded = errors.New("upload-pack-response should be decoded")
  12. // UploadPackResponse contains all the information responded by the upload-pack
  13. // service, the response implements io.ReadCloser that allows to read the
  14. // packfile directly from it.
  15. type UploadPackResponse struct {
  16. ShallowUpdate
  17. ServerResponse
  18. r io.ReadCloser
  19. isShallow bool
  20. isMultiACK bool
  21. isOk bool
  22. }
  23. // NewUploadPackResponse create a new UploadPackResponse instance, the request
  24. // being responded by the response is required.
  25. func NewUploadPackResponse(req *UploadPackRequest) *UploadPackResponse {
  26. isShallow := !req.Depth.IsZero()
  27. isMultiACK := req.Capabilities.Supports(capability.MultiACK) ||
  28. req.Capabilities.Supports(capability.MultiACKDetailed)
  29. return &UploadPackResponse{
  30. isShallow: isShallow,
  31. isMultiACK: isMultiACK,
  32. }
  33. }
  34. // NewUploadPackResponseWithPackfile creates a new UploadPackResponse instance,
  35. // and sets its packfile reader.
  36. func NewUploadPackResponseWithPackfile(req *UploadPackRequest,
  37. pf io.ReadCloser) *UploadPackResponse {
  38. r := NewUploadPackResponse(req)
  39. r.r = pf
  40. return r
  41. }
  42. // Decode decodes all the responses sent by upload-pack service into the struct
  43. // and prepares it to read the packfile using the Read method
  44. func (r *UploadPackResponse) Decode(reader io.ReadCloser) error {
  45. buf := bufio.NewReader(reader)
  46. if r.isShallow {
  47. if err := r.ShallowUpdate.Decode(buf); err != nil {
  48. return err
  49. }
  50. }
  51. if err := r.ServerResponse.Decode(buf, r.isMultiACK); err != nil {
  52. return err
  53. }
  54. // now the reader is ready to read the packfile content
  55. r.r = ioutil.NewReadCloser(buf, reader)
  56. return nil
  57. }
  58. // Encode encodes an UploadPackResponse.
  59. func (r *UploadPackResponse) Encode(w io.Writer) (err error) {
  60. if r.isShallow {
  61. if err := r.ShallowUpdate.Encode(w); err != nil {
  62. return err
  63. }
  64. }
  65. if err := r.ServerResponse.Encode(w); err != nil {
  66. return err
  67. }
  68. defer ioutil.CheckClose(r.r, &err)
  69. _, err = io.Copy(w, r.r)
  70. return err
  71. }
  72. // Read reads the packfile data, if the request was done with any Sideband
  73. // capability the content read should be demultiplexed. If the methods wasn't
  74. // called before the ErrUploadPackResponseNotDecoded will be return
  75. func (r *UploadPackResponse) Read(p []byte) (int, error) {
  76. if r.r == nil {
  77. return 0, ErrUploadPackResponseNotDecoded
  78. }
  79. return r.r.Read(p)
  80. }
  81. // Close the underlying reader, if any
  82. func (r *UploadPackResponse) Close() error {
  83. if r.r == nil {
  84. return nil
  85. }
  86. return r.r.Close()
  87. }
上海开阖软件有限公司 沪ICP备12045867号-1