refactoring

This commit is contained in:
Danila Fominykh 2023-08-03 20:43:13 +03:00
parent ebaa5436ad
commit 0c7aa7f63e
No known key found for this signature in database
GPG Key ID: 1134F8EBF98AA06F
3 changed files with 95 additions and 78 deletions

View File

@ -15,7 +15,6 @@ import (
"strconv" "strconv"
"strings" "strings"
"code.gitea.io/gitea/modules/container"
pkg_module "code.gitea.io/gitea/modules/packages" pkg_module "code.gitea.io/gitea/modules/packages"
"github.com/mholt/archiver/v3" "github.com/mholt/archiver/v3"
@ -24,8 +23,6 @@ import (
// JSON with pacakage parameters that are not related to specific // JSON with pacakage parameters that are not related to specific
// architecture/distribution that will be stored in sql database. // architecture/distribution that will be stored in sql database.
type Metadata struct { type Metadata struct {
Name string
Version string
URL string `json:"url"` URL string `json:"url"`
Description string `json:"description"` Description string `json:"description"`
Provides []string `json:"provides,omitempty"` Provides []string `json:"provides,omitempty"`
@ -64,7 +61,7 @@ type DbDesc struct {
} }
// Function that receives arch package archive data and returns it's metadata. // Function that receives arch package archive data and returns it's metadata.
func EjectMetadata(filename, distribution string, buf *pkg_module.HashedBuffer) (*DbDesc, error) { func EjectMetadata(filename, distro string, buf *pkg_module.HashedBuffer) (*DbDesc, error) {
pkginfo, err := getPkginfo(buf) pkginfo, err := getPkginfo(buf)
if err != nil { if err != nil {
return nil, err return nil, err
@ -84,52 +81,58 @@ func EjectMetadata(filename, distribution string, buf *pkg_module.HashedBuffer)
if len(splt) != 2 { if len(splt) != 2 {
continue continue
} }
switch splt[0] { var (
parameter = splt[0]
value = splt[1]
)
switch parameter {
case "pkgname": case "pkgname":
md.Name = splt[1] md.Name = value
case "pkgbase": case "pkgbase":
md.Base = splt[1] md.Base = value
case "pkgver": case "pkgver":
md.Version = splt[1] md.Version = value
case "pkgdesc": case "pkgdesc":
md.Description = splt[1] md.Description = value
case "url": case "url":
md.URL = splt[1] md.URL = value
case "packager": case "packager":
md.Packager = splt[1] md.Packager = value
case "builddate": case "builddate":
num, err := strconv.ParseInt(splt[1], 10, 64) num, err := strconv.ParseInt(value, 10, 64)
if err != nil { if err != nil {
return nil, err return nil, err
} }
md.BuildDate = num md.BuildDate = num
case "size": case "size":
num, err := strconv.ParseInt(splt[1], 10, 64) num, err := strconv.ParseInt(value, 10, 64)
if err != nil { if err != nil {
return nil, err return nil, err
} }
md.InstalledSize = num md.InstalledSize = num
case "provides": case "provides":
md.Provides = append(md.Provides, splt[1]) md.Provides = append(md.Provides, value)
case "license": case "license":
md.License = append(md.License, splt[1]) md.License = append(md.License, value)
case "arch": case "arch":
md.Arch = append(md.Arch, splt[1]) md.Arch = append(md.Arch, value)
case "depend": case "depend":
md.Depends = append(md.Depends, splt[1]) md.Depends = append(md.Depends, value)
case "optdepend": case "optdepend":
md.OptDepends = append(md.OptDepends, splt[1]) md.OptDepends = append(md.OptDepends, value)
case "makedepend": case "makedepend":
md.MakeDepends = append(md.MakeDepends, splt[1]) md.MakeDepends = append(md.MakeDepends, value)
case "checkdepend": case "checkdepend":
md.CheckDepends = append(md.CheckDepends, splt[1]) md.CheckDepends = append(md.CheckDepends, value)
case "backup": case "backup":
md.Backup = append(md.Backup, splt[1]) md.Backup = append(md.Backup, value)
} }
} }
return &md, nil return &md, nil
} }
// Eject .PKGINFO file as string from package archive.
func getPkginfo(data io.Reader) (string, error) { func getPkginfo(data io.Reader) (string, error) {
br := bufio.NewReader(data) br := bufio.NewReader(data)
zstd := archiver.NewTarZstd() zstd := archiver.NewTarZstd()
@ -153,8 +156,7 @@ func getPkginfo(data io.Reader) (string, error) {
} }
} }
// This function returns pacman package description in unarchived raw database // Create pacman package description file.
// format.
func (m *DbDesc) GetDbDesc() string { func (m *DbDesc) GetDbDesc() string {
return strings.Join(rmEmptyStrings([]string{ return strings.Join(rmEmptyStrings([]string{
formatField("FILENAME", m.Filename), formatField("FILENAME", m.Filename),
@ -244,12 +246,3 @@ func writeToArchive(files map[string][]byte, buf io.Writer) error {
} }
return nil return nil
} }
// This function creates a list containing unique values formed of 2 passed
// slices.
func UnifiedList(first, second []string) []string {
set := make(container.Set[string], len(first)+len(second))
set.AddMultiple(first...)
set.AddMultiple(second...)
return set.Values()
}

View File

@ -10,10 +10,12 @@ import (
"net/http" "net/http"
"strings" "strings"
pkg_model "code.gitea.io/gitea/models/packages"
"code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/context"
pkg_module "code.gitea.io/gitea/modules/packages" pkg_module "code.gitea.io/gitea/modules/packages"
arch_module "code.gitea.io/gitea/modules/packages/arch" arch_module "code.gitea.io/gitea/modules/packages/arch"
"code.gitea.io/gitea/routers/api/packages/helper" "code.gitea.io/gitea/routers/api/packages/helper"
pkg_service "code.gitea.io/gitea/services/packages"
arch_service "code.gitea.io/gitea/services/packages/arch" arch_service "code.gitea.io/gitea/services/packages/arch"
) )
@ -56,8 +58,6 @@ func Push(ctx *context.Context) {
// Metadata related to SQL database. // Metadata related to SQL database.
dbmd := &arch_module.Metadata{ dbmd := &arch_module.Metadata{
Name: pkgmd.Name,
Version: pkgmd.Version,
URL: pkgmd.URL, URL: pkgmd.URL,
Description: pkgmd.Description, Description: pkgmd.Description,
Provides: pkgmd.Provides, Provides: pkgmd.Provides,
@ -74,10 +74,12 @@ func Push(ctx *context.Context) {
pkgid, err := arch_service.SaveFile(ctx, &arch_service.SaveFileParams{ pkgid, err := arch_service.SaveFile(ctx, &arch_service.SaveFileParams{
Creator: ctx.ContextUser, Creator: ctx.ContextUser,
Owner: ctx.Package.Owner, Owner: ctx.Package.Owner,
Filename: filename,
Buf: buf,
Metadata: dbmd, Metadata: dbmd,
Buf: buf,
Filename: filename,
Distro: distro, Distro: distro,
PkgName: pkgmd.Name,
PkgVer: pkgmd.Version,
}) })
if err != nil { if err != nil {
apiError(ctx, http.StatusInternalServerError, err) apiError(ctx, http.StatusInternalServerError, err)
@ -100,6 +102,8 @@ func Push(ctx *context.Context) {
Buf: buf, Buf: buf,
Metadata: dbmd, Metadata: dbmd,
Distro: distro, Distro: distro,
PkgName: pkgmd.Name,
PkgVer: pkgmd.Version,
}) })
if err != nil { if err != nil {
apiError(ctx, http.StatusInternalServerError, err) apiError(ctx, http.StatusInternalServerError, err)
@ -124,6 +128,8 @@ func Push(ctx *context.Context) {
Filename: filename + ".sig", Filename: filename + ".sig",
Metadata: dbmd, Metadata: dbmd,
Distro: distro, Distro: distro,
PkgName: pkgmd.Name,
PkgVer: pkgmd.Version,
}) })
if err != nil { if err != nil {
apiError(ctx, http.StatusInternalServerError, err) apiError(ctx, http.StatusInternalServerError, err)
@ -133,8 +139,9 @@ func Push(ctx *context.Context) {
// Add new architectures and distribution info to package version metadata. // Add new architectures and distribution info to package version metadata.
err = arch_service.UpdateMetadata(ctx, &arch_service.UpdateMetadataParameters{ err = arch_service.UpdateMetadata(ctx, &arch_service.UpdateMetadataParameters{
User: ctx.Package.Owner, User: ctx.Package.Owner,
Md: dbmd, Metadata: dbmd,
DbDesc: pkgmd,
}) })
if err != nil { if err != nil {
apiError(ctx, http.StatusInternalServerError, err) apiError(ctx, http.StatusInternalServerError, err)
@ -142,7 +149,7 @@ func Push(ctx *context.Context) {
} }
// Automatically connect repository for provided package if name matched. // Automatically connect repository for provided package if name matched.
err = arch_service.RepositoryAutoconnect(ctx, owner, dbmd.Name, pkgid) err = arch_service.RepositoryAutoconnect(ctx, owner, pkgmd.Name, pkgid)
if err != nil { if err != nil {
apiError(ctx, http.StatusInternalServerError, err) apiError(ctx, http.StatusInternalServerError, err)
return return
@ -160,8 +167,7 @@ func Get(ctx *context.Context) {
arch = ctx.Params("arch") arch = ctx.Params("arch")
) )
// Packages are stored in different way from pacman databases, and loaded // Packages and signatures are loaded directly from object storage.
// with LoadPackageFile function.
if strings.HasSuffix(file, "tar.zst") || strings.HasSuffix(file, "zst.sig") { if strings.HasSuffix(file, "tar.zst") || strings.HasSuffix(file, "zst.sig") {
pkg, err := arch_service.GetFileObject(ctx, distro, file) pkg, err := arch_service.GetFileObject(ctx, distro, file)
if err != nil { if err != nil {
@ -175,8 +181,9 @@ func Get(ctx *context.Context) {
return return
} }
// Pacman databases is not stored in gitea's storage, it is created for // Pacman databases is not stored in giteas storage and created 'on-request'
// incoming request and cached. // for user/organization scope with accordance to requested architecture
// and distribution.
if strings.HasSuffix(file, ".db.tar.gz") || strings.HasSuffix(file, ".db") { if strings.HasSuffix(file, ".db.tar.gz") || strings.HasSuffix(file, ".db") {
db, err := arch_service.CreatePacmanDb(ctx, owner, arch, distro) db, err := arch_service.CreatePacmanDb(ctx, owner, arch, distro)
if err != nil { if err != nil {
@ -200,8 +207,13 @@ func Remove(ctx *context.Context) {
ver = ctx.Params("version") ver = ctx.Params("version")
) )
// Remove package files and pacman database entry. version, err := pkg_model.GetVersionByNameAndVersion(ctx, ctx.Package.Owner.ID, pkg_model.TypeArch, pkg, ver)
err := arch_service.RemovePackage(ctx, ctx.Package.Owner, pkg, ver) if err != nil {
apiError(ctx, http.StatusInternalServerError, err)
return
}
err = pkg_service.RemovePackageVersion(ctx.Package.Owner, version)
if err != nil { if err != nil {
apiError(ctx, http.StatusInternalServerError, err) apiError(ctx, http.StatusInternalServerError, err)
return return

View File

@ -13,6 +13,7 @@ import (
pkg_model "code.gitea.io/gitea/models/packages" pkg_model "code.gitea.io/gitea/models/packages"
"code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/user" "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/container"
"code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/json" "code.gitea.io/gitea/modules/json"
"code.gitea.io/gitea/modules/packages" "code.gitea.io/gitea/modules/packages"
@ -22,15 +23,21 @@ import (
) )
type UpdateMetadataParameters struct { type UpdateMetadataParameters struct {
User *user.User User *user.User
Md *arch.Metadata Metadata *arch.Metadata
DbDesc *arch.DbDesc
} }
// This function gets existing package metadata for provided version present, // Update package metadata stored in SQL database with new combination of
// combines architecture and distribution info and creates new metadata with // distribution and architecture.
// combined set of parameters.
func UpdateMetadata(ctx *context.Context, p *UpdateMetadataParameters) error { func UpdateMetadata(ctx *context.Context, p *UpdateMetadataParameters) error {
ver, err := pkg_model.GetVersionByNameAndVersion(ctx, p.User.ID, pkg_model.TypeArch, p.Md.Name, p.Md.Version) ver, err := pkg_model.GetVersionByNameAndVersion(
ctx,
p.User.ID,
pkg_model.TypeArch,
p.DbDesc.Name,
p.DbDesc.Version,
)
if err != nil { if err != nil {
return err return err
} }
@ -41,7 +48,7 @@ func UpdateMetadata(ctx *context.Context, p *UpdateMetadataParameters) error {
return err return err
} }
currmd.DistroArch = arch.UnifiedList(currmd.DistroArch, p.Md.DistroArch) currmd.DistroArch = uniqueSlice(currmd.DistroArch, p.Metadata.DistroArch)
b, err := json.Marshal(&currmd) b, err := json.Marshal(&currmd)
if err != nil { if err != nil {
@ -53,6 +60,14 @@ func UpdateMetadata(ctx *context.Context, p *UpdateMetadataParameters) error {
return pkg_model.UpdateVersion(ctx, ver) return pkg_model.UpdateVersion(ctx, ver)
} }
// Creates a list containing unique values formed of 2 passed slices.
func uniqueSlice(first, second []string) []string {
set := make(container.Set[string], len(first)+len(second))
set.AddMultiple(first...)
set.AddMultiple(second...)
return set.Values()
}
// Parameters required to save new arch package. // Parameters required to save new arch package.
type SaveFileParams struct { type SaveFileParams struct {
Creator *user.User Creator *user.User
@ -62,10 +77,12 @@ type SaveFileParams struct {
Filename string Filename string
Distro string Distro string
IsLead bool IsLead bool
PkgName string
PkgVer string
} }
// This function creates new package, version and package_file properties in // Creates new package, version and package_file properties in database,
// database, and writes blob to file storage. If package/version/blob exists it // and writes blob to file storage. If package/version/blob exists it
// will overwrite existing data. Package id and error will be returned. // will overwrite existing data. Package id and error will be returned.
func SaveFile(ctx *context.Context, p *SaveFileParams) (int64, error) { func SaveFile(ctx *context.Context, p *SaveFileParams) (int64, error) {
ver, _, err := pkg_service.CreatePackageOrAddFileToExisting( ver, _, err := pkg_service.CreatePackageOrAddFileToExisting(
@ -73,8 +90,8 @@ func SaveFile(ctx *context.Context, p *SaveFileParams) (int64, error) {
PackageInfo: pkg_service.PackageInfo{ PackageInfo: pkg_service.PackageInfo{
Owner: p.Owner, Owner: p.Owner,
PackageType: pkg_model.TypeArch, PackageType: pkg_model.TypeArch,
Name: p.Metadata.Name, Name: p.PkgName,
Version: p.Metadata.Version, Version: p.PkgVer,
}, },
Creator: p.Creator, Creator: p.Creator,
Metadata: p.Metadata, Metadata: p.Metadata,
@ -96,8 +113,8 @@ func SaveFile(ctx *context.Context, p *SaveFileParams) (int64, error) {
return ver.ID, nil return ver.ID, nil
} }
// Get data related to provided file name and distribution, and update download // Get data related to provided filename and distribution, for package files
// counter if actual package file is retrieved from database. // update download counter.
func GetFileObject(ctx *context.Context, distro, file string) (storage.Object, error) { func GetFileObject(ctx *context.Context, distro, file string) (storage.Object, error) {
db := db.GetEngine(ctx) db := db.GetEngine(ctx)
@ -125,8 +142,8 @@ func GetFileObject(ctx *context.Context, distro, file string) (storage.Object, e
return cs.Get(packages.BlobHash256Key(blob.HashSHA256)) return cs.Get(packages.BlobHash256Key(blob.HashSHA256))
} }
// Automatically connect repository to pushed package, if package with provided // Automatically connect repository with source code to published package, if
// with provided name exists in namespace scope. // repository with the same name exists in user/organization scope.
func RepositoryAutoconnect(ctx *context.Context, owner, repository string, pkgid int64) error { func RepositoryAutoconnect(ctx *context.Context, owner, repository string, pkgid int64) error {
repo, err := repo.GetRepositoryByOwnerAndName(ctx, owner, repository) repo, err := repo.GetRepositoryByOwnerAndName(ctx, owner, repository)
if err == nil { if err == nil {
@ -138,8 +155,11 @@ func RepositoryAutoconnect(ctx *context.Context, owner, repository string, pkgid
return nil return nil
} }
// This function is collecting information about packages in some organization/ // Finds all arch packages in user/organization scope, each package version
// user space, and created pacman database archive based on package metadata. // starting from latest in descending order is checked to be compatible with
// requested combination of architecture and distribution. When/If the first
// compatible version is found, related desc file will be loaded from object
// storage and added to database archive.
func CreatePacmanDb(ctx *context.Context, owner, architecture, distro string) ([]byte, error) { func CreatePacmanDb(ctx *context.Context, owner, architecture, distro string) ([]byte, error) {
u, err := user.GetUserByName(ctx, owner) u, err := user.GetUserByName(ctx, owner)
if err != nil { if err != nil {
@ -164,10 +184,11 @@ func CreatePacmanDb(ctx *context.Context, owner, architecture, distro string) ([
}) })
for _, version := range versions { for _, version := range versions {
desc, err := GetPacmanDbDesc(ctx, &DescParams{ desc, err := LoadDbDescFile(ctx, &DescParams{
Version: version, Version: version,
Arch: architecture, Arch: architecture,
Distro: distro, Distro: distro,
PkgName: pkg.Name,
}) })
if err != nil { if err != nil {
return nil, err return nil, err
@ -187,11 +208,12 @@ type DescParams struct {
Version *pkg_model.PackageVersion Version *pkg_model.PackageVersion
Arch string Arch string
Distro string Distro string
PkgName string
} }
// Checks if desc file exists for required architecture or any and returns it // Get pacman desc file from object storage if combination of distribution and
// in form of byte slice. // architecture is supported (checked in metadata).
func GetPacmanDbDesc(ctx *context.Context, p *DescParams) ([]byte, error) { func LoadDbDescFile(ctx *context.Context, p *DescParams) ([]byte, error) {
var md arch.Metadata var md arch.Metadata
err := json.Unmarshal([]byte(p.Version.MetadataJSON), &md) err := json.Unmarshal([]byte(p.Version.MetadataJSON), &md)
if err != nil { if err != nil {
@ -202,10 +224,10 @@ func GetPacmanDbDesc(ctx *context.Context, p *DescParams) ([]byte, error) {
var storagekey string var storagekey string
if distroarch == p.Distro+"-"+p.Arch { if distroarch == p.Distro+"-"+p.Arch {
storagekey = md.Name + "-" + md.Version + "-" + p.Arch + ".desc" storagekey = p.PkgName + "-" + p.Version.Version + "-" + p.Arch + ".desc"
} }
if distroarch == p.Distro+"-any" { if distroarch == p.Distro+"-any" {
storagekey = md.Name + "-" + md.Version + "-any.desc" storagekey = p.PkgName + "-" + p.Version.Version + "-any.desc"
} }
if storagekey == "" { if storagekey == "" {
@ -221,13 +243,3 @@ func GetPacmanDbDesc(ctx *context.Context, p *DescParams) ([]byte, error) {
} }
return nil, nil return nil, nil
} }
// Remove specific package version related to provided user or organization.
func RemovePackage(ctx *context.Context, u *user.User, name, version string) error {
ver, err := pkg_model.GetVersionByNameAndVersion(ctx, u.ID, pkg_model.TypeArch, name, version)
if err != nil {
return err
}
return pkg_service.RemovePackageVersion(u, ver)
}