basic.go 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. // Copyright 2020 The Gogs Authors. All rights reserved.
  2. // Use of this source code is governed by a MIT-style
  3. // license that can be found in the LICENSE file.
  4. package lfs
  5. import (
  6. "encoding/json"
  7. "io"
  8. "net/http"
  9. "os"
  10. "strconv"
  11. log "unknwon.dev/clog/v2"
  12. "gogs.io/gogs/internal/conf"
  13. "gogs.io/gogs/internal/context"
  14. "gogs.io/gogs/internal/db"
  15. "gogs.io/gogs/internal/lfsutil"
  16. "gogs.io/gogs/internal/strutil"
  17. )
  18. const transferBasic = "basic"
  19. const (
  20. basicOperationUpload = "upload"
  21. basicOperationDownload = "download"
  22. )
  23. // GET /{owner}/{repo}.git/info/lfs/object/basic/{oid}
  24. func serveBasicDownload(c *context.Context, repo *db.Repository, oid lfsutil.OID) {
  25. object, err := db.LFS.GetObjectByOID(repo.ID, oid)
  26. if err != nil {
  27. if db.IsErrLFSObjectNotExist(err) {
  28. responseJSON(c.Resp, http.StatusNotFound, responseError{
  29. Message: "Object does not exist",
  30. })
  31. } else {
  32. internalServerError(c.Resp)
  33. log.Error("Failed to get object [repo_id: %d, oid: %s]: %v", repo.ID, oid, err)
  34. }
  35. return
  36. }
  37. fpath := lfsutil.StorageLocalPath(conf.LFS.ObjectsPath, object.OID)
  38. r, err := os.Open(fpath)
  39. if err != nil {
  40. internalServerError(c.Resp)
  41. log.Error("Failed to open object file [path: %s]: %v", fpath, err)
  42. return
  43. }
  44. defer r.Close()
  45. c.Header().Set("Content-Type", "application/octet-stream")
  46. c.Header().Set("Content-Length", strconv.FormatInt(object.Size, 10))
  47. _, err = io.Copy(c.Resp, r)
  48. if err != nil {
  49. c.Status(http.StatusInternalServerError)
  50. log.Error("Failed to copy object file: %v", err)
  51. return
  52. }
  53. c.Status(http.StatusOK)
  54. }
  55. // PUT /{owner}/{repo}.git/info/lfs/object/basic/{oid}
  56. func serveBasicUpload(c *context.Context, repo *db.Repository, oid lfsutil.OID) {
  57. err := db.LFS.CreateObject(repo.ID, oid, c.Req.Request.Body, lfsutil.StorageLocal)
  58. if err != nil {
  59. internalServerError(c.Resp)
  60. log.Error("Failed to create object [repo_id: %d, oid: %s]: %v", repo.ID, oid, err)
  61. return
  62. }
  63. c.Status(http.StatusOK)
  64. log.Trace("[LFS] Object created %q", oid)
  65. }
  66. // POST /{owner}/{repo}.git/info/lfs/object/basic/verify
  67. func serveBasicVerify(c *context.Context, repo *db.Repository) {
  68. var request basicVerifyRequest
  69. defer c.Req.Request.Body.Close()
  70. err := json.NewDecoder(c.Req.Request.Body).Decode(&request)
  71. if err != nil {
  72. responseJSON(c.Resp, http.StatusBadRequest, responseError{
  73. Message: strutil.ToUpperFirst(err.Error()),
  74. })
  75. return
  76. }
  77. if !lfsutil.ValidOID(request.Oid) {
  78. responseJSON(c.Resp, http.StatusBadRequest, responseError{
  79. Message: "Invalid oid",
  80. })
  81. return
  82. }
  83. object, err := db.LFS.GetObjectByOID(repo.ID, lfsutil.OID(request.Oid))
  84. if err != nil {
  85. if db.IsErrLFSObjectNotExist(err) {
  86. responseJSON(c.Resp, http.StatusNotFound, responseError{
  87. Message: "Object does not exist",
  88. })
  89. } else {
  90. internalServerError(c.Resp)
  91. log.Error("Failed to get object [repo_id: %d, oid: %s]: %v", repo.ID, request.Oid, err)
  92. }
  93. return
  94. }
  95. if object.Size != request.Size {
  96. responseJSON(c.Resp, http.StatusNotFound, responseError{
  97. Message: "Object size mismatch",
  98. })
  99. return
  100. }
  101. c.Status(http.StatusOK)
  102. }
  103. type basicVerifyRequest struct {
  104. Oid lfsutil.OID `json:"oid"`
  105. Size int64 `json:"size"`
  106. }