changed procedure of package metadata ejection, removed unnecessary fields and unnecessary string conversions

This commit is contained in:
dancheg97 2023-06-26 12:28:14 +03:00
parent 1d1a5a312f
commit f1fae9ada6

View File

@ -10,141 +10,125 @@ import (
"crypto/md5" "crypto/md5"
"crypto/sha256" "crypto/sha256"
"encoding/hex" "encoding/hex"
"errors"
"fmt" "fmt"
"io" "io"
"os" "os"
"strconv" "strconv"
"strings" "strings"
"time"
"github.com/mholt/archiver/v3" "github.com/mholt/archiver/v3"
) )
// Metadata for arch package. // Metadata for arch package.
type Metadata struct { type Metadata struct {
Filename string Filename string
Name string Name string
Base string Base string
Version string Version string
Description string Description string
CompressedSize int64 CompressedSize int64
CompressedSizeMib string InstalledSize int64
InstalledSize int64 MD5 string
InstalledSizeMib string SHA256 string
MD5 string URL string
SHA256 string BuildDate int64
URL string BaseDomain string
BuildDate int64 Packager string
BuildDateStr string Provides []string
BaseDomain string License []string
Packager string Arch []string
Provides []string Depends []string
License []string OptDepends []string
Arch []string MakeDepends []string
Depends []string CheckDepends []string
OptDepends []string Backup []string
MakeDepends []string
CheckDepends []string
Backup []string
} }
// Function that recieves arch package archive data and returns it's metadata. // Function that recieves arch package archive data and returns it's metadata.
func EjectMetadata(filename, domain string, pkg []byte) (*Metadata, error) { func EjectMetadata(filename, domain string, pkg []byte) (*Metadata, error) {
pkgreader := io.LimitReader(bytes.NewReader(pkg), 250000) pkginfo, err := getPkginfo(pkg)
var buf bytes.Buffer
err := archiver.DefaultZstd.Decompress(pkgreader, &buf)
if err != nil { if err != nil {
if !errors.Is(err, io.ErrUnexpectedEOF) { return nil, err
return nil, err
}
} }
splt := strings.Split(buf.String(), "PKGINFO") var md = Metadata{
if len(splt) < 2 { Filename: filename,
return nil, errors.New("unable to eject .PKGINFO from archive") BaseDomain: domain,
CompressedSize: int64(len(pkg)),
MD5: md5sum(pkg),
SHA256: sha256sum(pkg),
} }
raw := splt[1][0:10000] for _, line := range strings.Split(pkginfo, "\n") {
inssize := int64(len(pkg)) splt := strings.Split(line, " = ")
compsize := ejectInt64(raw, "size") if len(splt) != 2 {
unixbuilddate := ejectInt64(raw, "builddate")
return &Metadata{
Filename: filename,
Name: ejectString(raw, "pkgname"),
Base: ejectString(raw, "pkgbase"),
Version: ejectString(raw, "pkgver"),
Description: ejectString(raw, "pkgdesc"),
CompressedSize: inssize,
CompressedSizeMib: ByteCountSI(inssize),
InstalledSize: compsize,
InstalledSizeMib: ByteCountSI(compsize),
MD5: md5sum(pkg),
SHA256: sha256sum(pkg),
URL: ejectString(raw, "url"),
BuildDate: unixbuilddate,
BuildDateStr: ReadableTime(unixbuilddate),
BaseDomain: domain,
Packager: ejectString(raw, "packager"),
Provides: ejectStrings(raw, "provides"),
License: ejectStrings(raw, "license"),
Arch: ejectStrings(raw, "arch"),
Depends: ejectStrings(raw, "depend"),
OptDepends: ejectStrings(raw, "optdepend"),
MakeDepends: ejectStrings(raw, "makedepend"),
CheckDepends: ejectStrings(raw, "checkdepend"),
Backup: ejectStrings(raw, "backup"),
}, nil
}
func ejectString(raw, field string) string {
splitted := strings.Split(raw, "\n"+field+" = ")
if len(splitted) < 2 {
return ``
}
return strings.Split(splitted[1], "\n")[0]
}
func ejectStrings(raw, field string) []string {
splitted := strings.Split(raw, "\n"+field+" = ")
if len(splitted) < 2 {
return nil
}
var rez []string
for i, v := range splitted {
if i == 0 {
continue continue
} }
rez = append(rez, strings.Split(v, "\n")[0]) switch splt[0] {
case "pkgname":
md.Name = splt[1]
case "pkgbase":
md.Base = splt[1]
case "pkgver":
md.Version = splt[1]
case "pkgdesc":
md.Description = splt[1]
case "url":
md.URL = splt[1]
case "packager":
md.Packager = splt[1]
case "builddate":
num, err := strconv.ParseInt(splt[1], 10, 64)
if err != nil {
return nil, err
}
md.BuildDate = num
case "size":
num, err := strconv.ParseInt(splt[1], 10, 64)
if err != nil {
return nil, err
}
md.InstalledSize = num
case "provides":
md.Provides = append(md.Provides, splt[1])
case "license":
md.License = append(md.License, splt[1])
case "arch":
md.Arch = append(md.Arch, splt[1])
case "depend":
md.Depends = append(md.Depends, splt[1])
case "optdepend":
md.Depends = append(md.OptDepends, splt[1])
case "makedepend":
md.Depends = append(md.MakeDepends, splt[1])
case "checkdepend":
md.Depends = append(md.CheckDepends, splt[1])
case "backup":
md.Depends = append(md.Backup, splt[1])
}
} }
return rez return &md, nil
} }
func ejectInt64(raw, field string) int64 { func getPkginfo(data []byte) (string, error) {
splitted := strings.Split(raw, "\n"+field+" = ") pkgreader := io.LimitReader(bytes.NewReader(data), 250000)
if len(splitted) < 2 { zstd := archiver.NewTarZstd()
return 0 err := zstd.Open(pkgreader, int64(250000))
}
i, err := strconv.ParseInt(strings.Split(splitted[1], "\n")[0], 10, 64)
if err != nil { if err != nil {
return 0 return ``, err
} }
return i for {
} f, err := zstd.Read()
if err != nil {
func ByteCountSI(b int64) string { return ``, err
const unit = 1000 }
if b < unit { if f.Name() != ".PKGINFO" {
return fmt.Sprintf("%d B", b) continue
}
b, err := io.ReadAll(f)
if err != nil {
return ``, err
}
return string(b), nil
} }
div, exp := int64(unit), 0
for n := b / unit; n >= unit; n /= unit {
div *= unit
exp++
}
return fmt.Sprintf("%.1f %cB", float64(b)/float64(div), "kMGTPE"[exp])
}
func ReadableTime(unix int64) string {
return time.Unix(unix, 0).Format(time.DateTime)
} }
func md5sum(data []byte) string { func md5sum(data []byte) string {