mirror of
https://github.com/gogrlx/snack.git
synced 2026-04-02 05:08:42 -07:00
feat(pacman): implement Manager interface for pacman package manager
Adds full pacman wrapper with: - All Manager interface methods (Install, Remove, Purge, Upgrade, Update, List, Search, Info, IsInstalled, Version, Available) - Linux implementation using exec.CommandContext - Non-linux stubs returning ErrUnsupportedPlatform - Output parsing for -Q, -Ss, -Si formats - Options support: WithSudo, WithAssumeYes, WithDryRun, WithRoot - Unit tests for parsing and argument building
This commit is contained in:
105
pacman/parse.go
Normal file
105
pacman/parse.go
Normal file
@@ -0,0 +1,105 @@
|
||||
package pacman
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/gogrlx/snack"
|
||||
)
|
||||
|
||||
// parseList parses the output of `pacman -Q` into packages.
|
||||
// Each line is "name version".
|
||||
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.Fields(line)
|
||||
if len(parts) < 2 {
|
||||
continue
|
||||
}
|
||||
pkgs = append(pkgs, snack.Package{
|
||||
Name: parts[0],
|
||||
Version: parts[1],
|
||||
Installed: true,
|
||||
})
|
||||
}
|
||||
return pkgs
|
||||
}
|
||||
|
||||
// parseSearch parses the output of `pacman -Ss` into packages.
|
||||
// Format:
|
||||
//
|
||||
// repo/name version [installed]
|
||||
// Description text
|
||||
func parseSearch(output string) []snack.Package {
|
||||
var pkgs []snack.Package
|
||||
lines := strings.Split(output, "\n")
|
||||
for i := 0; i < len(lines); i++ {
|
||||
line := lines[i]
|
||||
if line == "" || strings.HasPrefix(line, " ") || strings.HasPrefix(line, "\t") {
|
||||
continue
|
||||
}
|
||||
// repo/name version [installed]
|
||||
parts := strings.Fields(line)
|
||||
if len(parts) < 2 {
|
||||
continue
|
||||
}
|
||||
repoName := strings.SplitN(parts[0], "/", 2)
|
||||
pkg := snack.Package{
|
||||
Version: parts[1],
|
||||
}
|
||||
if len(repoName) == 2 {
|
||||
pkg.Repository = repoName[0]
|
||||
pkg.Name = repoName[1]
|
||||
} else {
|
||||
pkg.Name = repoName[0]
|
||||
}
|
||||
for _, p := range parts[2:] {
|
||||
if strings.Contains(p, "installed") {
|
||||
pkg.Installed = true
|
||||
}
|
||||
}
|
||||
// Next line is description
|
||||
if i+1 < len(lines) {
|
||||
desc := strings.TrimSpace(lines[i+1])
|
||||
if desc != "" {
|
||||
pkg.Description = desc
|
||||
i++
|
||||
}
|
||||
}
|
||||
pkgs = append(pkgs, pkg)
|
||||
}
|
||||
return pkgs
|
||||
}
|
||||
|
||||
// parseInfo parses the output of `pacman -Si` into a Package.
|
||||
// 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 "Description":
|
||||
pkg.Description = val
|
||||
case "Architecture":
|
||||
pkg.Arch = val
|
||||
case "Repository":
|
||||
pkg.Repository = val
|
||||
}
|
||||
}
|
||||
if pkg.Name == "" {
|
||||
return nil
|
||||
}
|
||||
return pkg
|
||||
}
|
||||
Reference in New Issue
Block a user