feat(platform): add Reinstall helpers to Pacman and Yay
This commit is contained in:
@@ -52,6 +52,17 @@ func (y *Yay) Install(ctx context.Context, pkgs []string) error {
|
|||||||
return y.Runner.Run(ctx, "yay", args...)
|
return y.Runner.Run(ctx, "yay", args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Reinstall runs `yay -S --noconfirm <pkgs...>` WITHOUT `--needed`, forcing
|
||||||
|
// yay/pacman to re-fetch and reinstall the packages even if already present.
|
||||||
|
// Used by the `--force` flag to bypass idempotency.
|
||||||
|
func (y *Yay) Reinstall(ctx context.Context, pkgs []string) error {
|
||||||
|
if len(pkgs) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
args := append([]string{"-S", "--noconfirm"}, pkgs...)
|
||||||
|
return y.Runner.Run(ctx, "yay", args...)
|
||||||
|
}
|
||||||
|
|
||||||
func shellQuote(s string) string {
|
func shellQuote(s string) string {
|
||||||
return "'" + strings.ReplaceAll(s, "'", `'\''`) + "'"
|
return "'" + strings.ReplaceAll(s, "'", `'\''`) + "'"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -70,6 +70,32 @@ func TestAUREnsureInstalledBootstrapsYay(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestYayReinstall(t *testing.T) {
|
||||||
|
r := &aurFakeRunner{yayInstalled: true}
|
||||||
|
y := NewYay(r)
|
||||||
|
if err := y.Reinstall(context.Background(), []string{"git", "curl"}); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if len(r.runCalls) == 0 {
|
||||||
|
t.Fatal("expected yay reinstall call")
|
||||||
|
}
|
||||||
|
c := r.runCalls[len(r.runCalls)-1]
|
||||||
|
want := []string{"yay", "-S", "--noconfirm", "git", "curl"}
|
||||||
|
if len(c) != len(want) {
|
||||||
|
t.Fatalf("call = %v, want %v", c, want)
|
||||||
|
}
|
||||||
|
for i, w := range want {
|
||||||
|
if c[i] != w {
|
||||||
|
t.Fatalf("call = %v, want %v", c, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, a := range c {
|
||||||
|
if a == "--needed" {
|
||||||
|
t.Fatalf("Reinstall must not pass --needed; got %v", c)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestAURInstall(t *testing.T) {
|
func TestAURInstall(t *testing.T) {
|
||||||
r := &aurFakeRunner{yayInstalled: true}
|
r := &aurFakeRunner{yayInstalled: true}
|
||||||
y := NewYay(r)
|
y := NewYay(r)
|
||||||
|
|||||||
@@ -76,6 +76,17 @@ func (p Pacman) Install(ctx context.Context, pkgs []string) error {
|
|||||||
return p.Runner.Run(ctx, "sudo", args...)
|
return p.Runner.Run(ctx, "sudo", args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Reinstall runs `sudo pacman -S --noconfirm <pkgs...>` WITHOUT `--needed`,
|
||||||
|
// so pacman physically re-fetches and reinstalls the packages even if they
|
||||||
|
// are already present. Used by the `--force` flag to bypass idempotency.
|
||||||
|
func (p Pacman) Reinstall(ctx context.Context, pkgs []string) error {
|
||||||
|
if len(pkgs) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
args := append([]string{"pacman", "-S", "--noconfirm"}, pkgs...)
|
||||||
|
return p.Runner.Run(ctx, "sudo", args...)
|
||||||
|
}
|
||||||
|
|
||||||
// Update runs `sudo pacman -Syu --noconfirm` (full sync + system upgrade).
|
// Update runs `sudo pacman -Syu --noconfirm` (full sync + system upgrade).
|
||||||
// On Arch, a bare `pacman -Sy` followed by an install is the partial-upgrade
|
// On Arch, a bare `pacman -Sy` followed by an install is the partial-upgrade
|
||||||
// anti-pattern that can break the system when a dep's ABI changes, so we
|
// anti-pattern that can break the system when a dep's ABI changes, so we
|
||||||
|
|||||||
@@ -39,6 +39,27 @@ func TestPacmanInstallShellsOutCorrectly(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestPacmanReinstall(t *testing.T) {
|
||||||
|
r := &fakeRunner{}
|
||||||
|
p := NewPacman(r)
|
||||||
|
if err := p.Reinstall(context.Background(), []string{"git", "curl"}); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if len(r.runCalls) != 1 {
|
||||||
|
t.Fatalf("run calls = %d", len(r.runCalls))
|
||||||
|
}
|
||||||
|
got := r.runCalls[0]
|
||||||
|
want := []string{"sudo", "pacman", "-S", "--noconfirm", "git", "curl"}
|
||||||
|
if !reflect.DeepEqual(got, want) {
|
||||||
|
t.Fatalf("args = %v, want %v", got, want)
|
||||||
|
}
|
||||||
|
for _, a := range got {
|
||||||
|
if a == "--needed" {
|
||||||
|
t.Fatalf("Reinstall must not pass --needed; got %v", got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestPacmanInstallEmptyIsNoop(t *testing.T) {
|
func TestPacmanInstallEmptyIsNoop(t *testing.T) {
|
||||||
r := &fakeRunner{}
|
r := &fakeRunner{}
|
||||||
p := NewPacman(r)
|
p := NewPacman(r)
|
||||||
|
|||||||
Reference in New Issue
Block a user