mirror of
https://github.com/gogrlx/snack.git
synced 2026-04-02 05:08:42 -07:00
Merge pull request #6 from gogrlx/cd/pacman-apk-capabilities
feat(pacman,apk): implement capability interfaces
This commit is contained in:
58
apk/capabilities.go
Normal file
58
apk/capabilities.go
Normal file
@@ -0,0 +1,58 @@
|
||||
package apk
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/gogrlx/snack"
|
||||
)
|
||||
|
||||
// Compile-time interface checks.
|
||||
var (
|
||||
_ snack.VersionQuerier = (*Apk)(nil)
|
||||
_ snack.Cleaner = (*Apk)(nil)
|
||||
_ snack.FileOwner = (*Apk)(nil)
|
||||
)
|
||||
|
||||
// LatestVersion returns the latest available version from configured repositories.
|
||||
func (a *Apk) LatestVersion(ctx context.Context, pkg string) (string, error) {
|
||||
return latestVersion(ctx, pkg)
|
||||
}
|
||||
|
||||
// ListUpgrades returns packages that have newer versions available.
|
||||
func (a *Apk) ListUpgrades(ctx context.Context) ([]snack.Package, error) {
|
||||
return listUpgrades(ctx)
|
||||
}
|
||||
|
||||
// UpgradeAvailable reports whether a newer version is available.
|
||||
func (a *Apk) UpgradeAvailable(ctx context.Context, pkg string) (bool, error) {
|
||||
return upgradeAvailable(ctx, pkg)
|
||||
}
|
||||
|
||||
// VersionCmp compares two version strings using apk's native comparison.
|
||||
func (a *Apk) VersionCmp(ctx context.Context, ver1, ver2 string) (int, error) {
|
||||
return versionCmp(ctx, ver1, ver2)
|
||||
}
|
||||
|
||||
// Autoremove is not directly supported by apk. apk does not track
|
||||
// "auto-installed" dependencies in a way that allows safe autoremoval.
|
||||
// This is a no-op that returns nil.
|
||||
func (a *Apk) Autoremove(ctx context.Context, opts ...snack.Option) error {
|
||||
return autoremove(ctx, opts...)
|
||||
}
|
||||
|
||||
// Clean removes cached package files.
|
||||
func (a *Apk) Clean(ctx context.Context) error {
|
||||
a.Lock()
|
||||
defer a.Unlock()
|
||||
return clean(ctx)
|
||||
}
|
||||
|
||||
// FileList returns all files installed by a package.
|
||||
func (a *Apk) FileList(ctx context.Context, pkg string) ([]string, error) {
|
||||
return fileList(ctx, pkg)
|
||||
}
|
||||
|
||||
// Owner returns the package that owns a given file path.
|
||||
func (a *Apk) Owner(ctx context.Context, path string) (string, error) {
|
||||
return owner(ctx, path)
|
||||
}
|
||||
177
apk/capabilities_linux.go
Normal file
177
apk/capabilities_linux.go
Normal file
@@ -0,0 +1,177 @@
|
||||
//go:build linux
|
||||
|
||||
package apk
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os/exec"
|
||||
"strings"
|
||||
|
||||
"github.com/gogrlx/snack"
|
||||
)
|
||||
|
||||
func latestVersion(ctx context.Context, pkg string) (string, error) {
|
||||
// Use `apk policy` to get available versions
|
||||
c := exec.CommandContext(ctx, "apk", "policy", pkg)
|
||||
out, err := c.CombinedOutput()
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("apk latestVersion %s: %w", pkg, snack.ErrNotFound)
|
||||
}
|
||||
// Output format:
|
||||
// pkg-1.2.3-r0:
|
||||
// lib/apk/db/installed
|
||||
// http://...
|
||||
// First line contains the version
|
||||
lines := strings.Split(strings.TrimSpace(string(out)), "\n")
|
||||
if len(lines) == 0 {
|
||||
return "", fmt.Errorf("apk latestVersion %s: %w", pkg, snack.ErrNotFound)
|
||||
}
|
||||
// First line: "pkg-1.2.3-r0:"
|
||||
first := strings.TrimSuffix(strings.TrimSpace(lines[0]), ":")
|
||||
_, ver := splitNameVersion(first)
|
||||
if ver == "" {
|
||||
return "", fmt.Errorf("apk latestVersion %s: %w", pkg, snack.ErrNotFound)
|
||||
}
|
||||
return ver, nil
|
||||
}
|
||||
|
||||
func listUpgrades(ctx context.Context) ([]snack.Package, error) {
|
||||
c := exec.CommandContext(ctx, "apk", "upgrade", "--simulate")
|
||||
out, err := c.CombinedOutput()
|
||||
if err != nil {
|
||||
// If simulate fails, it could mean no upgrades or an error
|
||||
outStr := strings.TrimSpace(string(out))
|
||||
if outStr == "" || strings.Contains(outStr, "OK") {
|
||||
return nil, nil
|
||||
}
|
||||
return nil, fmt.Errorf("apk listUpgrades: %w", err)
|
||||
}
|
||||
return parseUpgradeSimulation(string(out)), nil
|
||||
}
|
||||
|
||||
// parseUpgradeSimulation parses `apk upgrade --simulate` output.
|
||||
// Lines look like: "(1/3) Upgrading pkg (oldver -> newver)"
|
||||
func parseUpgradeSimulation(output string) []snack.Package {
|
||||
var pkgs []snack.Package
|
||||
for _, line := range strings.Split(output, "\n") {
|
||||
line = strings.TrimSpace(line)
|
||||
if !strings.Contains(line, "Upgrading") {
|
||||
continue
|
||||
}
|
||||
// "(1/3) Upgrading pkg (oldver -> newver)"
|
||||
idx := strings.Index(line, "Upgrading ")
|
||||
if idx < 0 {
|
||||
continue
|
||||
}
|
||||
rest := line[idx+len("Upgrading "):]
|
||||
// "pkg (oldver -> newver)"
|
||||
parts := strings.SplitN(rest, " (", 2)
|
||||
if len(parts) < 1 {
|
||||
continue
|
||||
}
|
||||
name := strings.TrimSpace(parts[0])
|
||||
var ver string
|
||||
if len(parts) == 2 {
|
||||
// "oldver -> newver)"
|
||||
verPart := strings.TrimSuffix(parts[1], ")")
|
||||
arrow := strings.Split(verPart, " -> ")
|
||||
if len(arrow) == 2 {
|
||||
ver = strings.TrimSpace(arrow[1])
|
||||
}
|
||||
}
|
||||
pkgs = append(pkgs, snack.Package{
|
||||
Name: name,
|
||||
Version: ver,
|
||||
Installed: true,
|
||||
})
|
||||
}
|
||||
return pkgs
|
||||
}
|
||||
|
||||
func upgradeAvailable(ctx context.Context, pkg string) (bool, error) {
|
||||
upgrades, err := listUpgrades(ctx)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
for _, u := range upgrades {
|
||||
if u.Name == pkg {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func versionCmp(ctx context.Context, ver1, ver2 string) (int, error) {
|
||||
c := exec.CommandContext(ctx, "apk", "version", "-t", ver1, ver2)
|
||||
out, err := c.CombinedOutput()
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("apk versionCmp: %w", err)
|
||||
}
|
||||
result := strings.TrimSpace(string(out))
|
||||
switch result {
|
||||
case "<":
|
||||
return -1, nil
|
||||
case ">":
|
||||
return 1, nil
|
||||
case "=":
|
||||
return 0, nil
|
||||
default:
|
||||
return 0, fmt.Errorf("apk versionCmp: unexpected output %q", result)
|
||||
}
|
||||
}
|
||||
|
||||
// autoremove is a no-op for apk. Alpine's apk does not have a direct
|
||||
// autoremove equivalent. `apk fix` repairs packages but does not remove
|
||||
// unused dependencies.
|
||||
func autoremove(_ context.Context, _ ...snack.Option) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func clean(ctx context.Context) error {
|
||||
c := exec.CommandContext(ctx, "apk", "cache", "clean")
|
||||
out, err := c.CombinedOutput()
|
||||
if err != nil {
|
||||
return fmt.Errorf("apk clean: %s: %w", strings.TrimSpace(string(out)), err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func fileList(ctx context.Context, pkg string) ([]string, error) {
|
||||
c := exec.CommandContext(ctx, "apk", "info", "-L", pkg)
|
||||
out, err := c.CombinedOutput()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("apk fileList %s: %w", pkg, snack.ErrNotInstalled)
|
||||
}
|
||||
var files []string
|
||||
for _, line := range strings.Split(strings.TrimSpace(string(out)), "\n") {
|
||||
line = strings.TrimSpace(line)
|
||||
if line == "" {
|
||||
continue
|
||||
}
|
||||
// First line is "pkg-version contains:" — skip it
|
||||
if strings.Contains(line, " contains:") {
|
||||
continue
|
||||
}
|
||||
files = append(files, line)
|
||||
}
|
||||
return files, nil
|
||||
}
|
||||
|
||||
func owner(ctx context.Context, path string) (string, error) {
|
||||
c := exec.CommandContext(ctx, "apk", "info", "--who-owns", path)
|
||||
out, err := c.CombinedOutput()
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("apk owner %s: %w", path, snack.ErrNotFound)
|
||||
}
|
||||
// Output: "/path is owned by pkg-version"
|
||||
outStr := strings.TrimSpace(string(out))
|
||||
if idx := strings.Index(outStr, "is owned by "); idx != -1 {
|
||||
nameVer := strings.TrimSpace(outStr[idx+len("is owned by "):])
|
||||
name, _ := splitNameVersion(nameVer)
|
||||
if name != "" {
|
||||
return name, nil
|
||||
}
|
||||
}
|
||||
return "", fmt.Errorf("apk owner %s: unexpected output %q", path, outStr)
|
||||
}
|
||||
41
apk/capabilities_other.go
Normal file
41
apk/capabilities_other.go
Normal file
@@ -0,0 +1,41 @@
|
||||
//go:build !linux
|
||||
|
||||
package apk
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/gogrlx/snack"
|
||||
)
|
||||
|
||||
func latestVersion(_ context.Context, _ string) (string, error) {
|
||||
return "", snack.ErrUnsupportedPlatform
|
||||
}
|
||||
|
||||
func listUpgrades(_ context.Context) ([]snack.Package, error) {
|
||||
return nil, snack.ErrUnsupportedPlatform
|
||||
}
|
||||
|
||||
func upgradeAvailable(_ context.Context, _ string) (bool, error) {
|
||||
return false, snack.ErrUnsupportedPlatform
|
||||
}
|
||||
|
||||
func versionCmp(_ context.Context, _, _ string) (int, error) {
|
||||
return 0, snack.ErrUnsupportedPlatform
|
||||
}
|
||||
|
||||
func autoremove(_ context.Context, _ ...snack.Option) error {
|
||||
return snack.ErrUnsupportedPlatform
|
||||
}
|
||||
|
||||
func clean(_ context.Context) error {
|
||||
return snack.ErrUnsupportedPlatform
|
||||
}
|
||||
|
||||
func fileList(_ context.Context, _ string) ([]string, error) {
|
||||
return nil, snack.ErrUnsupportedPlatform
|
||||
}
|
||||
|
||||
func owner(_ context.Context, _ string) (string, error) {
|
||||
return "", snack.ErrUnsupportedPlatform
|
||||
}
|
||||
80
pacman/capabilities.go
Normal file
80
pacman/capabilities.go
Normal file
@@ -0,0 +1,80 @@
|
||||
package pacman
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/gogrlx/snack"
|
||||
)
|
||||
|
||||
// Compile-time interface checks.
|
||||
var (
|
||||
_ snack.VersionQuerier = (*Pacman)(nil)
|
||||
_ snack.Cleaner = (*Pacman)(nil)
|
||||
_ snack.FileOwner = (*Pacman)(nil)
|
||||
_ snack.Grouper = (*Pacman)(nil)
|
||||
)
|
||||
|
||||
// NOTE: snack.Holder is not implemented for pacman. While pacman supports
|
||||
// IgnorePkg in /etc/pacman.conf, there is no clean CLI command to hold/unhold
|
||||
// packages. pacman-contrib provides some tooling but it's not standard.
|
||||
|
||||
// LatestVersion returns the latest available version from configured repositories.
|
||||
func (p *Pacman) LatestVersion(ctx context.Context, pkg string) (string, error) {
|
||||
return latestVersion(ctx, pkg)
|
||||
}
|
||||
|
||||
// ListUpgrades returns packages that have newer versions available.
|
||||
func (p *Pacman) ListUpgrades(ctx context.Context) ([]snack.Package, error) {
|
||||
return listUpgrades(ctx)
|
||||
}
|
||||
|
||||
// UpgradeAvailable reports whether a newer version is available.
|
||||
func (p *Pacman) UpgradeAvailable(ctx context.Context, pkg string) (bool, error) {
|
||||
return upgradeAvailable(ctx, pkg)
|
||||
}
|
||||
|
||||
// VersionCmp compares two version strings using pacman's vercmp.
|
||||
func (p *Pacman) VersionCmp(ctx context.Context, ver1, ver2 string) (int, error) {
|
||||
return versionCmp(ctx, ver1, ver2)
|
||||
}
|
||||
|
||||
// Autoremove removes orphaned packages.
|
||||
func (p *Pacman) Autoremove(ctx context.Context, opts ...snack.Option) error {
|
||||
p.Lock()
|
||||
defer p.Unlock()
|
||||
return autoremove(ctx, opts...)
|
||||
}
|
||||
|
||||
// Clean removes cached package files.
|
||||
func (p *Pacman) Clean(ctx context.Context) error {
|
||||
p.Lock()
|
||||
defer p.Unlock()
|
||||
return clean(ctx)
|
||||
}
|
||||
|
||||
// FileList returns all files installed by a package.
|
||||
func (p *Pacman) FileList(ctx context.Context, pkg string) ([]string, error) {
|
||||
return fileList(ctx, pkg)
|
||||
}
|
||||
|
||||
// Owner returns the package that owns a given file path.
|
||||
func (p *Pacman) Owner(ctx context.Context, path string) (string, error) {
|
||||
return owner(ctx, path)
|
||||
}
|
||||
|
||||
// GroupList returns all available package groups.
|
||||
func (p *Pacman) GroupList(ctx context.Context) ([]string, error) {
|
||||
return groupList(ctx)
|
||||
}
|
||||
|
||||
// GroupInfo returns the packages in a group.
|
||||
func (p *Pacman) GroupInfo(ctx context.Context, group string) ([]snack.Package, error) {
|
||||
return groupInfo(ctx, group)
|
||||
}
|
||||
|
||||
// GroupInstall installs all packages in a group.
|
||||
func (p *Pacman) GroupInstall(ctx context.Context, group string, opts ...snack.Option) error {
|
||||
p.Lock()
|
||||
defer p.Unlock()
|
||||
return groupInstall(ctx, group, opts...)
|
||||
}
|
||||
221
pacman/capabilities_linux.go
Normal file
221
pacman/capabilities_linux.go
Normal file
@@ -0,0 +1,221 @@
|
||||
//go:build linux
|
||||
|
||||
package pacman
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os/exec"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/gogrlx/snack"
|
||||
)
|
||||
|
||||
func latestVersion(ctx context.Context, pkg string) (string, error) {
|
||||
out, err := run(ctx, []string{"-Si", pkg}, snack.Options{})
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), "exit status 1") {
|
||||
return "", fmt.Errorf("pacman latestVersion %s: %w", pkg, snack.ErrNotFound)
|
||||
}
|
||||
return "", fmt.Errorf("pacman latestVersion: %w", err)
|
||||
}
|
||||
p := parseInfo(out)
|
||||
if p == nil || p.Version == "" {
|
||||
return "", fmt.Errorf("pacman latestVersion %s: %w", pkg, snack.ErrNotFound)
|
||||
}
|
||||
return p.Version, nil
|
||||
}
|
||||
|
||||
func listUpgrades(ctx context.Context) ([]snack.Package, error) {
|
||||
out, err := run(ctx, []string{"-Qu"}, snack.Options{})
|
||||
if err != nil {
|
||||
// exit status 1 means no upgrades available
|
||||
if strings.Contains(err.Error(), "exit status 1") {
|
||||
return nil, nil
|
||||
}
|
||||
return nil, fmt.Errorf("pacman listUpgrades: %w", err)
|
||||
}
|
||||
return parseUpgrades(out), nil
|
||||
}
|
||||
|
||||
// parseUpgrades parses `pacman -Qu` output.
|
||||
// Format: "pkg oldver -> newver"
|
||||
func parseUpgrades(output string) []snack.Package {
|
||||
var pkgs []snack.Package
|
||||
for _, line := range strings.Split(output, "\n") {
|
||||
line = strings.TrimSpace(line)
|
||||
if line == "" {
|
||||
continue
|
||||
}
|
||||
// "pkg oldver -> newver"
|
||||
parts := strings.Fields(line)
|
||||
if len(parts) >= 4 && parts[2] == "->" {
|
||||
pkgs = append(pkgs, snack.Package{
|
||||
Name: parts[0],
|
||||
Version: parts[3],
|
||||
Installed: true,
|
||||
})
|
||||
} else if len(parts) >= 2 {
|
||||
// fallback: "pkg newver"
|
||||
pkgs = append(pkgs, snack.Package{
|
||||
Name: parts[0],
|
||||
Version: parts[1],
|
||||
Installed: true,
|
||||
})
|
||||
}
|
||||
}
|
||||
return pkgs
|
||||
}
|
||||
|
||||
func upgradeAvailable(ctx context.Context, pkg string) (bool, error) {
|
||||
_, err := run(ctx, []string{"-Qu", pkg}, snack.Options{})
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), "exit status 1") {
|
||||
return false, nil
|
||||
}
|
||||
return false, fmt.Errorf("pacman upgradeAvailable: %w", err)
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func versionCmp(ctx context.Context, ver1, ver2 string) (int, error) {
|
||||
c := exec.CommandContext(ctx, "vercmp", ver1, ver2)
|
||||
out, err := c.Output()
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("vercmp: %w", err)
|
||||
}
|
||||
n, err := strconv.Atoi(strings.TrimSpace(string(out)))
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("vercmp: unexpected output %q: %w", string(out), err)
|
||||
}
|
||||
// Normalize to -1, 0, 1
|
||||
switch {
|
||||
case n < 0:
|
||||
return -1, nil
|
||||
case n > 0:
|
||||
return 1, nil
|
||||
default:
|
||||
return 0, nil
|
||||
}
|
||||
}
|
||||
|
||||
func autoremove(ctx context.Context, opts ...snack.Option) error {
|
||||
o := snack.ApplyOptions(opts...)
|
||||
|
||||
// First get list of orphans
|
||||
orphans, err := run(ctx, []string{"-Qdtq"}, snack.Options{})
|
||||
if err != nil {
|
||||
// exit status 1 means no orphans
|
||||
if strings.Contains(err.Error(), "exit status 1") {
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("pacman autoremove: %w", err)
|
||||
}
|
||||
orphans = strings.TrimSpace(orphans)
|
||||
if orphans == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
pkgs := strings.Fields(orphans)
|
||||
args := append([]string{"-Rns", "--noconfirm"}, pkgs...)
|
||||
_, err = run(ctx, args, o)
|
||||
return err
|
||||
}
|
||||
|
||||
func clean(ctx context.Context) error {
|
||||
_, err := run(ctx, []string{"-Sc", "--noconfirm"}, snack.Options{})
|
||||
return err
|
||||
}
|
||||
|
||||
func fileList(ctx context.Context, pkg string) ([]string, error) {
|
||||
out, err := run(ctx, []string{"-Ql", pkg}, snack.Options{})
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), "exit status 1") {
|
||||
return nil, fmt.Errorf("pacman fileList %s: %w", pkg, snack.ErrNotInstalled)
|
||||
}
|
||||
return nil, fmt.Errorf("pacman fileList: %w", err)
|
||||
}
|
||||
var files []string
|
||||
for _, line := range strings.Split(out, "\n") {
|
||||
line = strings.TrimSpace(line)
|
||||
if line == "" {
|
||||
continue
|
||||
}
|
||||
// "pkg /path/to/file"
|
||||
parts := strings.SplitN(line, " ", 2)
|
||||
if len(parts) == 2 {
|
||||
files = append(files, strings.TrimSpace(parts[1]))
|
||||
}
|
||||
}
|
||||
return files, nil
|
||||
}
|
||||
|
||||
func owner(ctx context.Context, path string) (string, error) {
|
||||
out, err := run(ctx, []string{"-Qo", path}, snack.Options{})
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), "exit status 1") || strings.Contains(err.Error(), "No package owns") {
|
||||
return "", fmt.Errorf("pacman owner %s: %w", path, snack.ErrNotFound)
|
||||
}
|
||||
return "", fmt.Errorf("pacman owner: %w", err)
|
||||
}
|
||||
// Output: "/path is owned by pkg ver"
|
||||
out = strings.TrimSpace(out)
|
||||
if idx := strings.Index(out, "is owned by "); idx != -1 {
|
||||
remainder := out[idx+len("is owned by "):]
|
||||
parts := strings.Fields(remainder)
|
||||
if len(parts) >= 1 {
|
||||
return parts[0], nil
|
||||
}
|
||||
}
|
||||
return "", fmt.Errorf("pacman owner %s: unexpected output %q", path, out)
|
||||
}
|
||||
|
||||
func groupList(ctx context.Context) ([]string, error) {
|
||||
out, err := run(ctx, []string{"-Sg"}, snack.Options{})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("pacman groupList: %w", err)
|
||||
}
|
||||
seen := make(map[string]struct{})
|
||||
var groups []string
|
||||
for _, line := range strings.Split(out, "\n") {
|
||||
parts := strings.Fields(line)
|
||||
if len(parts) >= 1 {
|
||||
g := parts[0]
|
||||
if _, ok := seen[g]; !ok {
|
||||
seen[g] = struct{}{}
|
||||
groups = append(groups, g)
|
||||
}
|
||||
}
|
||||
}
|
||||
return groups, nil
|
||||
}
|
||||
|
||||
func groupInfo(ctx context.Context, group string) ([]snack.Package, error) {
|
||||
out, err := run(ctx, []string{"-Sg", group}, snack.Options{})
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), "exit status 1") {
|
||||
return nil, fmt.Errorf("pacman groupInfo %s: %w", group, snack.ErrNotFound)
|
||||
}
|
||||
return nil, fmt.Errorf("pacman groupInfo: %w", err)
|
||||
}
|
||||
var pkgs []snack.Package
|
||||
for _, line := range strings.Split(out, "\n") {
|
||||
line = strings.TrimSpace(line)
|
||||
if line == "" {
|
||||
continue
|
||||
}
|
||||
// "group pkg"
|
||||
parts := strings.Fields(line)
|
||||
if len(parts) >= 2 {
|
||||
pkgs = append(pkgs, snack.Package{Name: parts[1]})
|
||||
}
|
||||
}
|
||||
return pkgs, nil
|
||||
}
|
||||
|
||||
func groupInstall(ctx context.Context, group string, opts ...snack.Option) error {
|
||||
o := snack.ApplyOptions(opts...)
|
||||
_, err := run(ctx, []string{"-S", "--noconfirm", group}, o)
|
||||
return err
|
||||
}
|
||||
53
pacman/capabilities_other.go
Normal file
53
pacman/capabilities_other.go
Normal file
@@ -0,0 +1,53 @@
|
||||
//go:build !linux
|
||||
|
||||
package pacman
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/gogrlx/snack"
|
||||
)
|
||||
|
||||
func latestVersion(_ context.Context, _ string) (string, error) {
|
||||
return "", snack.ErrUnsupportedPlatform
|
||||
}
|
||||
|
||||
func listUpgrades(_ context.Context) ([]snack.Package, error) {
|
||||
return nil, snack.ErrUnsupportedPlatform
|
||||
}
|
||||
|
||||
func upgradeAvailable(_ context.Context, _ string) (bool, error) {
|
||||
return false, snack.ErrUnsupportedPlatform
|
||||
}
|
||||
|
||||
func versionCmp(_ context.Context, _, _ string) (int, error) {
|
||||
return 0, snack.ErrUnsupportedPlatform
|
||||
}
|
||||
|
||||
func autoremove(_ context.Context, _ ...snack.Option) error {
|
||||
return snack.ErrUnsupportedPlatform
|
||||
}
|
||||
|
||||
func clean(_ context.Context) error {
|
||||
return snack.ErrUnsupportedPlatform
|
||||
}
|
||||
|
||||
func fileList(_ context.Context, _ string) ([]string, error) {
|
||||
return nil, snack.ErrUnsupportedPlatform
|
||||
}
|
||||
|
||||
func owner(_ context.Context, _ string) (string, error) {
|
||||
return "", snack.ErrUnsupportedPlatform
|
||||
}
|
||||
|
||||
func groupList(_ context.Context) ([]string, error) {
|
||||
return nil, snack.ErrUnsupportedPlatform
|
||||
}
|
||||
|
||||
func groupInfo(_ context.Context, _ string) ([]snack.Package, error) {
|
||||
return nil, snack.ErrUnsupportedPlatform
|
||||
}
|
||||
|
||||
func groupInstall(_ context.Context, _ string, _ ...snack.Option) error {
|
||||
return snack.ErrUnsupportedPlatform
|
||||
}
|
||||
Reference in New Issue
Block a user