Files
snack/dpkg/capabilities_linux.go
Tai Groot e5c749558f feat(apt,dpkg): implement capability interfaces
apt: VersionQuerier, Holder, Cleaner, FileOwner, RepoManager, KeyManager, NameNormalizer
dpkg: FileOwner, NameNormalizer

All new interfaces follow the existing pattern of exported methods on
struct delegating to unexported platform-specific functions. Mutating
operations use Lock/Unlock; read-only operations do not.

Platform stubs in _other.go files return ErrUnsupportedPlatform.
Compile-time interface checks added for all implemented interfaces.
2026-02-25 20:47:44 +00:00

56 lines
1.4 KiB
Go

//go:build linux
package dpkg
import (
"bytes"
"context"
"fmt"
"os/exec"
"strings"
"github.com/gogrlx/snack"
)
func fileList(ctx context.Context, pkg string) ([]string, error) {
cmd := exec.CommandContext(ctx, "dpkg", "-L", pkg)
var stderr bytes.Buffer
cmd.Stderr = &stderr
out, err := cmd.Output()
if err != nil {
errMsg := stderr.String()
if strings.Contains(errMsg, "is not installed") || strings.Contains(errMsg, "not found") {
return nil, fmt.Errorf("dpkg -L %s: %w", pkg, snack.ErrNotInstalled)
}
return nil, fmt.Errorf("dpkg -L %s: %w: %s", pkg, err, errMsg)
}
var files []string
for _, line := range strings.Split(strings.TrimSpace(string(out)), "\n") {
line = strings.TrimSpace(line)
if line != "" {
files = append(files, line)
}
}
return files, nil
}
func owner(ctx context.Context, path string) (string, error) {
cmd := exec.CommandContext(ctx, "dpkg", "-S", path)
var stderr bytes.Buffer
cmd.Stderr = &stderr
out, err := cmd.Output()
if err != nil {
return "", fmt.Errorf("dpkg -S %s: %w", path, snack.ErrNotFound)
}
line := strings.TrimSpace(strings.Split(string(out), "\n")[0])
colonIdx := strings.Index(line, ":")
if colonIdx < 0 {
return "", fmt.Errorf("dpkg -S %s: unexpected output", path)
}
pkgPart := line[:colonIdx]
if commaIdx := strings.Index(pkgPart, ","); commaIdx >= 0 {
pkgPart = strings.TrimSpace(pkgPart[:commaIdx])
}
return strings.TrimSpace(pkgPart), nil
}