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.

lfs.go 3.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. package models
  2. import (
  3. "crypto/sha256"
  4. "encoding/hex"
  5. "errors"
  6. "fmt"
  7. "io"
  8. "code.gitea.io/gitea/modules/timeutil"
  9. )
  10. // LFSMetaObject stores metadata for LFS tracked files.
  11. type LFSMetaObject struct {
  12. ID int64 `xorm:"pk autoincr"`
  13. Oid string `xorm:"UNIQUE(s) INDEX NOT NULL"`
  14. Size int64 `xorm:"NOT NULL"`
  15. RepositoryID int64 `xorm:"UNIQUE(s) INDEX NOT NULL"`
  16. Existing bool `xorm:"-"`
  17. CreatedUnix timeutil.TimeStamp `xorm:"created"`
  18. }
  19. // Pointer returns the string representation of an LFS pointer file
  20. func (m *LFSMetaObject) Pointer() string {
  21. return fmt.Sprintf("%s\n%s%s\nsize %d\n", LFSMetaFileIdentifier, LFSMetaFileOidPrefix, m.Oid, m.Size)
  22. }
  23. // LFSTokenResponse defines the JSON structure in which the JWT token is stored.
  24. // This structure is fetched via SSH and passed by the Git LFS client to the server
  25. // endpoint for authorization.
  26. type LFSTokenResponse struct {
  27. Header map[string]string `json:"header"`
  28. Href string `json:"href"`
  29. }
  30. var (
  31. // ErrLFSObjectNotExist is returned from lfs models functions in order
  32. // to differentiate between database and missing object errors.
  33. ErrLFSObjectNotExist = errors.New("LFS Meta object does not exist")
  34. )
  35. const (
  36. // LFSMetaFileIdentifier is the string appearing at the first line of LFS pointer files.
  37. // https://github.com/git-lfs/git-lfs/blob/master/docs/spec.md
  38. LFSMetaFileIdentifier = "version https://git-lfs.github.com/spec/v1"
  39. // LFSMetaFileOidPrefix appears in LFS pointer files on a line before the sha256 hash.
  40. LFSMetaFileOidPrefix = "oid sha256:"
  41. )
  42. // NewLFSMetaObject stores a given populated LFSMetaObject structure in the database
  43. // if it is not already present.
  44. func NewLFSMetaObject(m *LFSMetaObject) (*LFSMetaObject, error) {
  45. var err error
  46. sess := x.NewSession()
  47. defer sess.Close()
  48. if err = sess.Begin(); err != nil {
  49. return nil, err
  50. }
  51. has, err := sess.Get(m)
  52. if err != nil {
  53. return nil, err
  54. }
  55. if has {
  56. m.Existing = true
  57. return m, sess.Commit()
  58. }
  59. if _, err = sess.Insert(m); err != nil {
  60. return nil, err
  61. }
  62. return m, sess.Commit()
  63. }
  64. // GenerateLFSOid generates a Sha256Sum to represent an oid for arbitrary content
  65. func GenerateLFSOid(content io.Reader) (string, error) {
  66. h := sha256.New()
  67. if _, err := io.Copy(h, content); err != nil {
  68. return "", err
  69. }
  70. sum := h.Sum(nil)
  71. return hex.EncodeToString(sum), nil
  72. }
  73. // GetLFSMetaObjectByOid selects a LFSMetaObject entry from database by its OID.
  74. // It may return ErrLFSObjectNotExist or a database error. If the error is nil,
  75. // the returned pointer is a valid LFSMetaObject.
  76. func (repo *Repository) GetLFSMetaObjectByOid(oid string) (*LFSMetaObject, error) {
  77. if len(oid) == 0 {
  78. return nil, ErrLFSObjectNotExist
  79. }
  80. m := &LFSMetaObject{Oid: oid, RepositoryID: repo.ID}
  81. has, err := x.Get(m)
  82. if err != nil {
  83. return nil, err
  84. } else if !has {
  85. return nil, ErrLFSObjectNotExist
  86. }
  87. return m, nil
  88. }
  89. // RemoveLFSMetaObjectByOid removes a LFSMetaObject entry from database by its OID.
  90. // It may return ErrLFSObjectNotExist or a database error.
  91. func (repo *Repository) RemoveLFSMetaObjectByOid(oid string) error {
  92. if len(oid) == 0 {
  93. return ErrLFSObjectNotExist
  94. }
  95. sess := x.NewSession()
  96. defer sess.Close()
  97. if err := sess.Begin(); err != nil {
  98. return err
  99. }
  100. m := &LFSMetaObject{Oid: oid, RepositoryID: repo.ID}
  101. if _, err := sess.Delete(m); err != nil {
  102. return err
  103. }
  104. return sess.Commit()
  105. }