gitea源码

metadata.go 1.7KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. // Copyright 2023 The Gitea Authors. All rights reserved.
  2. // SPDX-License-Identifier: MIT
  3. package goproxy
  4. import (
  5. "archive/zip"
  6. "io"
  7. "path"
  8. "strings"
  9. "code.gitea.io/gitea/modules/util"
  10. )
  11. const (
  12. PropertyGoMod = "go.mod"
  13. maxGoModFileSize = 16 * 1024 * 1024 // https://go.dev/ref/mod#zip-path-size-constraints
  14. )
  15. var (
  16. ErrInvalidStructure = util.NewInvalidArgumentErrorf("package has invalid structure")
  17. ErrGoModFileTooLarge = util.NewInvalidArgumentErrorf("go.mod file is too large")
  18. )
  19. type Package struct {
  20. Name string
  21. Version string
  22. GoMod string
  23. }
  24. // ParsePackage parses the Go package file
  25. // https://go.dev/ref/mod#zip-files
  26. func ParsePackage(r io.ReaderAt, size int64) (*Package, error) {
  27. archive, err := zip.NewReader(r, size)
  28. if err != nil {
  29. return nil, err
  30. }
  31. var p *Package
  32. for _, file := range archive.File {
  33. nameAndVersion := path.Dir(file.Name)
  34. parts := strings.SplitN(nameAndVersion, "@", 2)
  35. if len(parts) != 2 {
  36. continue
  37. }
  38. versionParts := strings.SplitN(parts[1], "/", 2)
  39. if p == nil {
  40. p = &Package{
  41. Name: strings.TrimSuffix(nameAndVersion, "@"+parts[1]),
  42. Version: versionParts[0],
  43. }
  44. }
  45. if len(versionParts) > 1 {
  46. // files are expected in the "root" folder
  47. continue
  48. }
  49. if path.Base(file.Name) == "go.mod" {
  50. if file.UncompressedSize64 > maxGoModFileSize {
  51. return nil, ErrGoModFileTooLarge
  52. }
  53. f, err := archive.Open(file.Name)
  54. if err != nil {
  55. return nil, err
  56. }
  57. defer f.Close()
  58. bytes, err := io.ReadAll(&io.LimitedReader{R: f, N: maxGoModFileSize})
  59. if err != nil {
  60. return nil, err
  61. }
  62. p.GoMod = string(bytes)
  63. return p, nil
  64. }
  65. }
  66. if p == nil {
  67. return nil, ErrInvalidStructure
  68. }
  69. p.GoMod = "module " + p.Name
  70. return p, nil
  71. }