mirror of
https://github.com/gogrlx/snack.git
synced 2026-04-02 05:08:42 -07:00
Implements the dnf sub-package with Manager, VersionQuerier, Holder, Cleaner, FileOwner, RepoManager, KeyManager, Grouper, and NameNormalizer interfaces. Implements the rpm sub-package with Manager, FileOwner, and NameNormalizer interfaces. Both follow the existing pattern: exported methods on struct delegate to unexported functions, _linux.go for real implementations, _other.go with build-tag stubs, embedded snack.Locker for mutating operations, and compile-time interface checks. Includes parser tests for all output formats.
98 lines
2.0 KiB
Go
98 lines
2.0 KiB
Go
package rpm
|
|
|
|
import (
|
|
"strings"
|
|
|
|
"github.com/gogrlx/snack"
|
|
)
|
|
|
|
// knownArchs is the set of RPM architecture suffixes.
|
|
var knownArchs = map[string]bool{
|
|
"x86_64": true,
|
|
"i686": true,
|
|
"i386": true,
|
|
"aarch64": true,
|
|
"armv7hl": true,
|
|
"ppc64le": true,
|
|
"s390x": true,
|
|
"noarch": true,
|
|
"src": true,
|
|
}
|
|
|
|
// normalizeName strips architecture suffixes from a package name.
|
|
func normalizeName(name string) string {
|
|
n, _ := parseArchSuffix(name)
|
|
return n
|
|
}
|
|
|
|
// parseArchSuffix extracts the architecture from a package name if present.
|
|
func parseArchSuffix(name string) (string, string) {
|
|
idx := strings.LastIndex(name, ".")
|
|
if idx < 0 {
|
|
return name, ""
|
|
}
|
|
arch := name[idx+1:]
|
|
if knownArchs[arch] {
|
|
return name[:idx], arch
|
|
}
|
|
return name, ""
|
|
}
|
|
|
|
// parseList parses rpm -qa --queryformat output.
|
|
// Format: "NAME\tVERSION-RELEASE\tSUMMARY\n"
|
|
func parseList(output string) []snack.Package {
|
|
var pkgs []snack.Package
|
|
for _, line := range strings.Split(output, "\n") {
|
|
line = strings.TrimSpace(line)
|
|
if line == "" {
|
|
continue
|
|
}
|
|
parts := strings.SplitN(line, "\t", 3)
|
|
if len(parts) < 2 {
|
|
continue
|
|
}
|
|
pkg := snack.Package{
|
|
Name: parts[0],
|
|
Version: parts[1],
|
|
Installed: true,
|
|
}
|
|
if len(parts) >= 3 {
|
|
pkg.Description = parts[2]
|
|
}
|
|
pkgs = append(pkgs, pkg)
|
|
}
|
|
return pkgs
|
|
}
|
|
|
|
// parseInfo parses rpm -qi output.
|
|
// Format is "Key : Value" lines.
|
|
func parseInfo(output string) *snack.Package {
|
|
pkg := &snack.Package{}
|
|
for _, line := range strings.Split(output, "\n") {
|
|
idx := strings.Index(line, ":")
|
|
if idx < 0 {
|
|
continue
|
|
}
|
|
key := strings.TrimSpace(line[:idx])
|
|
val := strings.TrimSpace(line[idx+1:])
|
|
switch key {
|
|
case "Name":
|
|
pkg.Name = val
|
|
case "Version":
|
|
pkg.Version = val
|
|
case "Release":
|
|
if pkg.Version != "" {
|
|
pkg.Version = pkg.Version + "-" + val
|
|
}
|
|
case "Architecture", "Arch":
|
|
pkg.Arch = val
|
|
case "Summary":
|
|
pkg.Description = val
|
|
}
|
|
}
|
|
if pkg.Name == "" {
|
|
return nil
|
|
}
|
|
return pkg
|
|
}
|