205 lines
5.2 KiB
Go
205 lines
5.2 KiB
Go
package rpm
|
|
|
|
import "io/fs"
|
|
import "path/filepath"
|
|
import "sort"
|
|
import "strings"
|
|
|
|
import repokit "repokit"
|
|
|
|
type PackageSummary struct {
|
|
Filename string `json:"filename"`
|
|
Name string `json:"name"`
|
|
Version string `json:"version"`
|
|
Release string `json:"release"`
|
|
Arch string `json:"arch"`
|
|
Summary string `json:"summary"`
|
|
}
|
|
|
|
type PackageDetail struct {
|
|
PackageSummary
|
|
Description string `json:"description"`
|
|
License string `json:"license"`
|
|
URL string `json:"url"`
|
|
BuildTime int64 `json:"build_time"`
|
|
Size int64 `json:"size"`
|
|
Files []string `json:"files"`
|
|
Requires []string `json:"requires"`
|
|
Provides []string `json:"provides"`
|
|
Changelogs []PackageChangeLog `json:"changelogs"`
|
|
}
|
|
|
|
type PackageChangeLog struct {
|
|
Author string `json:"author"`
|
|
Date int64 `json:"date"`
|
|
Text string `json:"text"`
|
|
}
|
|
|
|
func ListPackages(repoPath string) ([]PackageSummary, error) {
|
|
var packages []PackageSummary
|
|
var walkErr error
|
|
var err error
|
|
walkErr = filepath.WalkDir(repoPath, func(path string, entry fs.DirEntry, entryErr error) error {
|
|
var lower string
|
|
var rel string
|
|
var pkg *repokit.RpmPackage
|
|
var summary PackageSummary
|
|
if entryErr != nil {
|
|
return entryErr
|
|
}
|
|
if entry.IsDir() {
|
|
return nil
|
|
}
|
|
lower = strings.ToLower(entry.Name())
|
|
if !strings.HasSuffix(lower, ".rpm") {
|
|
return nil
|
|
}
|
|
rel, err = filepath.Rel(repoPath, path)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
pkg, err = repokit.RpmPackageFromRpmBase(path, 0)
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
summary = packageSummaryFromRepokit(pkg, filepath.ToSlash(rel))
|
|
packages = append(packages, summary)
|
|
return nil
|
|
})
|
|
if walkErr != nil {
|
|
return nil, walkErr
|
|
}
|
|
sort.Slice(packages, func(i int, j int) bool {
|
|
if packages[i].Name == packages[j].Name {
|
|
return packages[i].Filename < packages[j].Filename
|
|
}
|
|
return packages[i].Name < packages[j].Name
|
|
})
|
|
return packages, nil
|
|
}
|
|
|
|
func GetPackageDetail(repoPath string, filename string) (PackageDetail, error) {
|
|
var detail PackageDetail
|
|
var fullPath string
|
|
var pkg *repokit.RpmPackage
|
|
var err error
|
|
fullPath = filepath.Join(repoPath, filepath.FromSlash(filename))
|
|
pkg, err = repokit.RpmPackageFromRpmBase(fullPath, 256)
|
|
if err != nil {
|
|
return detail, err
|
|
}
|
|
detail = packageDetailFromRepokit(pkg, filename)
|
|
return detail, nil
|
|
}
|
|
|
|
func packageSummaryFromRepokit(pkg *repokit.RpmPackage, filename string) PackageSummary {
|
|
var summary PackageSummary
|
|
summary = PackageSummary{
|
|
Filename: filename,
|
|
Name: strings.TrimSpace(pkg.Name),
|
|
Version: strings.TrimSpace(pkg.Version),
|
|
Release: strings.TrimSpace(pkg.Release),
|
|
Arch: strings.TrimSpace(pkg.Arch),
|
|
Summary: strings.TrimSpace(pkg.Summary),
|
|
}
|
|
return summary
|
|
}
|
|
|
|
func packageDetailFromRepokit(pkg *repokit.RpmPackage, filename string) PackageDetail {
|
|
var files []string
|
|
var file repokit.RpmPackageFile
|
|
var changelogs []PackageChangeLog
|
|
var changelog repokit.RpmChangelogEntry
|
|
var detail PackageDetail
|
|
files = make([]string, 0, len(pkg.Files))
|
|
for _, file = range pkg.Files {
|
|
if file.FullPath == "" {
|
|
continue
|
|
}
|
|
files = append(files, file.FullPath)
|
|
}
|
|
changelogs = make([]PackageChangeLog, 0, len(pkg.Changelogs))
|
|
for _, changelog = range pkg.Changelogs {
|
|
changelogs = append(changelogs, PackageChangeLog{
|
|
Author: strings.TrimSpace(changelog.Author),
|
|
Date: changelog.Date,
|
|
Text: strings.TrimSpace(changelog.Changelog),
|
|
})
|
|
}
|
|
sort.SliceStable(changelogs, func(i int, j int) bool {
|
|
return changelogs[i].Date > changelogs[j].Date
|
|
})
|
|
sort.Strings(files)
|
|
detail = PackageDetail{
|
|
PackageSummary: packageSummaryFromRepokit(pkg, filename),
|
|
Description: strings.TrimSpace(pkg.Description),
|
|
License: strings.TrimSpace(pkg.RpmLicense),
|
|
URL: strings.TrimSpace(pkg.Url),
|
|
BuildTime: pkg.TimeBuild,
|
|
Size: pkg.SizePackage,
|
|
Files: files,
|
|
Requires: dependencyListToStrings(pkg.Requires),
|
|
Provides: dependencyListToStrings(pkg.Provides),
|
|
Changelogs: changelogs,
|
|
}
|
|
return detail
|
|
}
|
|
|
|
func dependencyListToStrings(deps []repokit.RpmDependency) []string {
|
|
var lines []string
|
|
var dep repokit.RpmDependency
|
|
lines = make([]string, 0, len(deps))
|
|
for _, dep = range deps {
|
|
lines = append(lines, dependencyToString(dep))
|
|
}
|
|
return lines
|
|
}
|
|
|
|
func dependencyToString(dep repokit.RpmDependency) string {
|
|
var op string
|
|
var evr string
|
|
var line string
|
|
op = normalizeDependencyOp(dep.Flags)
|
|
evr = dependencyEVR(dep)
|
|
line = dep.Name
|
|
if op == "" || evr == "" {
|
|
return line
|
|
}
|
|
line = line + " " + op + " " + evr
|
|
return line
|
|
}
|
|
|
|
func normalizeDependencyOp(flag string) string {
|
|
switch strings.ToUpper(strings.TrimSpace(flag)) {
|
|
case "LT":
|
|
return "<"
|
|
case "GT":
|
|
return ">"
|
|
case "EQ":
|
|
return "="
|
|
case "LE":
|
|
return "<="
|
|
case "GE":
|
|
return ">="
|
|
default:
|
|
return strings.TrimSpace(flag)
|
|
}
|
|
}
|
|
|
|
func dependencyEVR(dep repokit.RpmDependency) string {
|
|
var value string
|
|
var version string
|
|
version = strings.TrimSpace(dep.Version)
|
|
if version == "" {
|
|
return ""
|
|
}
|
|
value = version
|
|
if strings.TrimSpace(dep.Release) != "" {
|
|
value = value + "-" + strings.TrimSpace(dep.Release)
|
|
}
|
|
if strings.TrimSpace(dep.Epoch) != "" && strings.TrimSpace(dep.Epoch) != "0" {
|
|
value = strings.TrimSpace(dep.Epoch) + ":" + value
|
|
}
|
|
return value
|
|
}
|