gitea源码

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. // Copyright 2021 The Gitea Authors. All rights reserved.
  2. // SPDX-License-Identifier: MIT
  3. package lfs
  4. import (
  5. "bytes"
  6. "context"
  7. "io"
  8. "net/http"
  9. "code.gitea.io/gitea/modules/json"
  10. "code.gitea.io/gitea/modules/log"
  11. )
  12. // TransferAdapter represents an adapter for downloading/uploading LFS objects.
  13. type TransferAdapter interface {
  14. Name() string
  15. Download(ctx context.Context, l *Link) (io.ReadCloser, error)
  16. Upload(ctx context.Context, l *Link, p Pointer, r io.Reader) error
  17. Verify(ctx context.Context, l *Link, p Pointer) error
  18. }
  19. // BasicTransferAdapter implements the "basic" adapter.
  20. type BasicTransferAdapter struct {
  21. client *http.Client
  22. }
  23. // Name returns the name of the adapter.
  24. func (a *BasicTransferAdapter) Name() string {
  25. return "basic"
  26. }
  27. // Download reads the download location and downloads the data.
  28. func (a *BasicTransferAdapter) Download(ctx context.Context, l *Link) (io.ReadCloser, error) {
  29. req, err := createRequest(ctx, http.MethodGet, l.Href, l.Header, nil)
  30. if err != nil {
  31. return nil, err
  32. }
  33. log.Debug("Download Request: %+v", req)
  34. resp, err := performRequest(ctx, a.client, req)
  35. if err != nil {
  36. return nil, err
  37. }
  38. return resp.Body, nil
  39. }
  40. // Upload sends the content to the LFS server.
  41. func (a *BasicTransferAdapter) Upload(ctx context.Context, l *Link, p Pointer, r io.Reader) error {
  42. req, err := createRequest(ctx, http.MethodPut, l.Href, l.Header, r)
  43. if err != nil {
  44. return err
  45. }
  46. if req.Header.Get("Content-Type") == "" {
  47. req.Header.Set("Content-Type", "application/octet-stream")
  48. }
  49. if req.Header.Get("Transfer-Encoding") == "chunked" {
  50. req.TransferEncoding = []string{"chunked"}
  51. }
  52. req.ContentLength = p.Size
  53. res, err := performRequest(ctx, a.client, req)
  54. if err != nil {
  55. return err
  56. }
  57. defer res.Body.Close()
  58. return nil
  59. }
  60. // Verify calls the verify handler on the LFS server
  61. func (a *BasicTransferAdapter) Verify(ctx context.Context, l *Link, p Pointer) error {
  62. b, err := json.Marshal(p)
  63. if err != nil {
  64. log.Error("Error encoding json: %v", err)
  65. return err
  66. }
  67. req, err := createRequest(ctx, http.MethodPost, l.Href, l.Header, bytes.NewReader(b))
  68. if err != nil {
  69. return err
  70. }
  71. req.Header.Set("Content-Type", MediaType)
  72. res, err := performRequest(ctx, a.client, req)
  73. if err != nil {
  74. return err
  75. }
  76. defer res.Body.Close()
  77. return nil
  78. }