diff options
author | Daniel Baumann <daniel@debian.org> | 2024-10-18 20:33:49 +0200 |
---|---|---|
committer | Daniel Baumann <daniel@debian.org> | 2024-12-12 23:57:56 +0100 |
commit | e68b9d00a6e05b3a941f63ffb696f91e554ac5ec (patch) | |
tree | 97775d6c13b0f416af55314eb6a89ef792474615 /modules/packages/goproxy/metadata.go | |
parent | Initial commit. (diff) | |
download | forgejo-e68b9d00a6e05b3a941f63ffb696f91e554ac5ec.tar.xz forgejo-e68b9d00a6e05b3a941f63ffb696f91e554ac5ec.zip |
Adding upstream version 9.0.3.
Signed-off-by: Daniel Baumann <daniel@debian.org>
Diffstat (limited to 'modules/packages/goproxy/metadata.go')
-rw-r--r-- | modules/packages/goproxy/metadata.go | 94 |
1 files changed, 94 insertions, 0 deletions
diff --git a/modules/packages/goproxy/metadata.go b/modules/packages/goproxy/metadata.go new file mode 100644 index 0000000..40f7d20 --- /dev/null +++ b/modules/packages/goproxy/metadata.go @@ -0,0 +1,94 @@ +// Copyright 2023 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package goproxy + +import ( + "archive/zip" + "fmt" + "io" + "path" + "strings" + + "code.gitea.io/gitea/modules/util" +) + +const ( + PropertyGoMod = "go.mod" + + maxGoModFileSize = 16 * 1024 * 1024 // https://go.dev/ref/mod#zip-path-size-constraints +) + +var ( + ErrInvalidStructure = util.NewInvalidArgumentErrorf("package has invalid structure") + ErrGoModFileTooLarge = util.NewInvalidArgumentErrorf("go.mod file is too large") +) + +type Package struct { + Name string + Version string + GoMod string +} + +// ParsePackage parses the Go package file +// https://go.dev/ref/mod#zip-files +func ParsePackage(r io.ReaderAt, size int64) (*Package, error) { + archive, err := zip.NewReader(r, size) + if err != nil { + return nil, err + } + + var p *Package + + for _, file := range archive.File { + nameAndVersion := path.Dir(file.Name) + + parts := strings.SplitN(nameAndVersion, "@", 2) + if len(parts) != 2 { + continue + } + + versionParts := strings.SplitN(parts[1], "/", 2) + + if p == nil { + p = &Package{ + Name: strings.TrimSuffix(nameAndVersion, "@"+parts[1]), + Version: versionParts[0], + } + } + + if len(versionParts) > 1 { + // files are expected in the "root" folder + continue + } + + if path.Base(file.Name) == "go.mod" { + if file.UncompressedSize64 > maxGoModFileSize { + return nil, ErrGoModFileTooLarge + } + + f, err := archive.Open(file.Name) + if err != nil { + return nil, err + } + defer f.Close() + + bytes, err := io.ReadAll(&io.LimitedReader{R: f, N: maxGoModFileSize}) + if err != nil { + return nil, err + } + + p.GoMod = string(bytes) + + return p, nil + } + } + + if p == nil { + return nil, ErrInvalidStructure + } + + p.GoMod = fmt.Sprintf("module %s", p.Name) + + return p, nil +} |