forked from Plemya-x/ALR
		
	fix: removeAlreadyInstalled before FindPkgs
This commit is contained in:
		@@ -149,6 +149,21 @@ func (a *APK) ListInstalled(opts *Opts) (map[string]string, error) {
 | 
			
		||||
	return out, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (a *APK) IsInstalled(pkg string) (bool, error) {
 | 
			
		||||
	cmd := exec.Command("apk", "info", "--installed", pkg)
 | 
			
		||||
	output, err := cmd.CombinedOutput()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		if exitErr, ok := err.(*exec.ExitError); ok {
 | 
			
		||||
			// Exit code 1 means the package is not installed
 | 
			
		||||
			if exitErr.ExitCode() == 1 {
 | 
			
		||||
				return false, nil
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		return false, fmt.Errorf("apk: isinstalled: %w, output: %s", err, output)
 | 
			
		||||
	}
 | 
			
		||||
	return true, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (a *APK) getCmd(opts *Opts, mgrCmd string, args ...string) *exec.Cmd {
 | 
			
		||||
	var cmd *exec.Cmd
 | 
			
		||||
	if opts.AsRoot {
 | 
			
		||||
 
 | 
			
		||||
@@ -135,6 +135,21 @@ func (a *APT) ListInstalled(opts *Opts) (map[string]string, error) {
 | 
			
		||||
	return out, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (a *APT) IsInstalled(pkg string) (bool, error) {
 | 
			
		||||
	cmd := exec.Command("dpkg-query", "-l", pkg)
 | 
			
		||||
	output, err := cmd.CombinedOutput()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		if exitErr, ok := err.(*exec.ExitError); ok {
 | 
			
		||||
			// Exit code 1 means the package is not installed
 | 
			
		||||
			if exitErr.ExitCode() == 1 {
 | 
			
		||||
				return false, nil
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		return false, fmt.Errorf("apt: isinstalled: %w, output: %s", err, output)
 | 
			
		||||
	}
 | 
			
		||||
	return true, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (a *APT) getCmd(opts *Opts, mgrCmd string, args ...string) *exec.Cmd {
 | 
			
		||||
	var cmd *exec.Cmd
 | 
			
		||||
	if opts.AsRoot {
 | 
			
		||||
 
 | 
			
		||||
@@ -17,7 +17,6 @@
 | 
			
		||||
package manager
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bufio"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"os/exec"
 | 
			
		||||
	"strings"
 | 
			
		||||
@@ -25,6 +24,7 @@ import (
 | 
			
		||||
 | 
			
		||||
// APTRpm represents the APT-RPM package manager
 | 
			
		||||
type APTRpm struct {
 | 
			
		||||
	CommonRPM
 | 
			
		||||
	rootCmd string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -106,38 +106,6 @@ func (a *APTRpm) UpgradeAll(opts *Opts) error {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (y *APTRpm) ListInstalled(opts *Opts) (map[string]string, error) {
 | 
			
		||||
	out := map[string]string{}
 | 
			
		||||
	cmd := exec.Command("rpm", "-qa", "--queryformat", "%{NAME}\u200b%|EPOCH?{%{EPOCH}:}:{}|%{VERSION}-%{RELEASE}\\n")
 | 
			
		||||
 | 
			
		||||
	stdout, err := cmd.StdoutPipe()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err = cmd.Start()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	scanner := bufio.NewScanner(stdout)
 | 
			
		||||
	for scanner.Scan() {
 | 
			
		||||
		name, version, ok := strings.Cut(scanner.Text(), "\u200b")
 | 
			
		||||
		if !ok {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		version = strings.TrimPrefix(version, "0:")
 | 
			
		||||
		out[name] = version
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err = scanner.Err()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return out, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (a *APTRpm) getCmd(opts *Opts, mgrCmd string, args ...string) *exec.Cmd {
 | 
			
		||||
	var cmd *exec.Cmd
 | 
			
		||||
	if opts.AsRoot {
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										72
									
								
								pkg/manager/common_rpm.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								pkg/manager/common_rpm.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,72 @@
 | 
			
		||||
// ALR - Any Linux Repository
 | 
			
		||||
// Copyright (C) 2025 Евгений Храмов
 | 
			
		||||
//
 | 
			
		||||
// This program is free software: you can redistribute it and/or modify
 | 
			
		||||
// it under the terms of the GNU General Public License as published by
 | 
			
		||||
// the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
// (at your option) any later version.
 | 
			
		||||
//
 | 
			
		||||
// This program is distributed in the hope that it will be useful,
 | 
			
		||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
// GNU General Public License for more details.
 | 
			
		||||
//
 | 
			
		||||
// You should have received a copy of the GNU General Public License
 | 
			
		||||
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 | 
			
		||||
package manager
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bufio"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"os/exec"
 | 
			
		||||
	"strings"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type CommonRPM struct{}
 | 
			
		||||
 | 
			
		||||
func (c *CommonRPM) ListInstalled(opts *Opts) (map[string]string, error) {
 | 
			
		||||
	out := map[string]string{}
 | 
			
		||||
	cmd := exec.Command("rpm", "-qa", "--queryformat", "%{NAME}\u200b%|EPOCH?{%{EPOCH}:}:{}|%{VERSION}-%{RELEASE}\\n")
 | 
			
		||||
 | 
			
		||||
	stdout, err := cmd.StdoutPipe()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err = cmd.Start()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	scanner := bufio.NewScanner(stdout)
 | 
			
		||||
	for scanner.Scan() {
 | 
			
		||||
		name, version, ok := strings.Cut(scanner.Text(), "\u200b")
 | 
			
		||||
		if !ok {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		version = strings.TrimPrefix(version, "0:")
 | 
			
		||||
		out[name] = version
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err = scanner.Err()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return out, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (a *CommonRPM) IsInstalled(pkg string) (bool, error) {
 | 
			
		||||
	cmd := exec.Command("rpm", "-q", "--whatprovides", pkg)
 | 
			
		||||
	output, err := cmd.CombinedOutput()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		if exitErr, ok := err.(*exec.ExitError); ok {
 | 
			
		||||
			if exitErr.ExitCode() == 1 {
 | 
			
		||||
				return false, nil
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		return false, fmt.Errorf("rpm: isinstalled: %w, output: %s", err, output)
 | 
			
		||||
	}
 | 
			
		||||
	return true, nil
 | 
			
		||||
}
 | 
			
		||||
@@ -19,14 +19,13 @@
 | 
			
		||||
package manager
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bufio"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"os/exec"
 | 
			
		||||
	"strings"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// DNF представляет менеджер пакетов DNF
 | 
			
		||||
type DNF struct {
 | 
			
		||||
	CommonRPM
 | 
			
		||||
	rootCmd string // rootCmd хранит команду, используемую для выполнения команд с правами root
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -120,39 +119,6 @@ func (d *DNF) UpgradeAll(opts *Opts) error {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ListInstalled возвращает список установленных пакетов и их версий
 | 
			
		||||
func (d *DNF) ListInstalled(opts *Opts) (map[string]string, error) {
 | 
			
		||||
	out := map[string]string{}
 | 
			
		||||
	cmd := exec.Command("rpm", "-qa", "--queryformat", "%{NAME}\u200b%|EPOCH?{%{EPOCH}:}:{}|%{VERSION}-%{RELEASE}\\n")
 | 
			
		||||
 | 
			
		||||
	stdout, err := cmd.StdoutPipe()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err = cmd.Start()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	scanner := bufio.NewScanner(stdout)
 | 
			
		||||
	for scanner.Scan() {
 | 
			
		||||
		name, version, ok := strings.Cut(scanner.Text(), "\u200b")
 | 
			
		||||
		if !ok {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		version = strings.TrimPrefix(version, "0:")
 | 
			
		||||
		out[name] = version
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err = scanner.Err()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return out, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// getCmd создает и возвращает команду exec.Cmd для менеджера пакетов DNF
 | 
			
		||||
func (d *DNF) getCmd(opts *Opts, mgrCmd string, args ...string) *exec.Cmd {
 | 
			
		||||
	var cmd *exec.Cmd
 | 
			
		||||
 
 | 
			
		||||
@@ -80,6 +80,8 @@ type Manager interface {
 | 
			
		||||
	UpgradeAll(*Opts) error
 | 
			
		||||
	// ListInstalled returns all installed packages mapped to their versions
 | 
			
		||||
	ListInstalled(*Opts) (map[string]string, error)
 | 
			
		||||
	//
 | 
			
		||||
	IsInstalled(string) (bool, error)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Detect returns the package manager detected on the system
 | 
			
		||||
 
 | 
			
		||||
@@ -142,6 +142,21 @@ func (p *Pacman) ListInstalled(opts *Opts) (map[string]string, error) {
 | 
			
		||||
	return out, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *Pacman) IsInstalled(pkg string) (bool, error) {
 | 
			
		||||
	cmd := exec.Command("pacman", "-Q", pkg)
 | 
			
		||||
	output, err := cmd.CombinedOutput()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		// Pacman returns exit code 1 if the package is not found
 | 
			
		||||
		if exitErr, ok := err.(*exec.ExitError); ok {
 | 
			
		||||
			if exitErr.ExitCode() == 1 {
 | 
			
		||||
				return false, nil
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		return false, fmt.Errorf("pacman: isinstalled: %w, output: %s", err, output)
 | 
			
		||||
	}
 | 
			
		||||
	return true, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *Pacman) getCmd(opts *Opts, mgrCmd string, args ...string) *exec.Cmd {
 | 
			
		||||
	var cmd *exec.Cmd
 | 
			
		||||
	if opts.AsRoot {
 | 
			
		||||
 
 | 
			
		||||
@@ -20,14 +20,14 @@
 | 
			
		||||
package manager
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bufio"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"os/exec"
 | 
			
		||||
	"strings"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// YUM represents the YUM package manager
 | 
			
		||||
type YUM struct {
 | 
			
		||||
	CommonRPM
 | 
			
		||||
 | 
			
		||||
	rootCmd string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -111,38 +111,6 @@ func (y *YUM) UpgradeAll(opts *Opts) error {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (y *YUM) ListInstalled(opts *Opts) (map[string]string, error) {
 | 
			
		||||
	out := map[string]string{}
 | 
			
		||||
	cmd := exec.Command("rpm", "-qa", "--queryformat", "%{NAME}\u200b%|EPOCH?{%{EPOCH}:}:{}|%{VERSION}-%{RELEASE}\\n")
 | 
			
		||||
 | 
			
		||||
	stdout, err := cmd.StdoutPipe()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err = cmd.Start()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	scanner := bufio.NewScanner(stdout)
 | 
			
		||||
	for scanner.Scan() {
 | 
			
		||||
		name, version, ok := strings.Cut(scanner.Text(), "\u200b")
 | 
			
		||||
		if !ok {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		version = strings.TrimPrefix(version, "0:")
 | 
			
		||||
		out[name] = version
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err = scanner.Err()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return out, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (y *YUM) getCmd(opts *Opts, mgrCmd string, args ...string) *exec.Cmd {
 | 
			
		||||
	var cmd *exec.Cmd
 | 
			
		||||
	if opts.AsRoot {
 | 
			
		||||
 
 | 
			
		||||
@@ -20,14 +20,13 @@
 | 
			
		||||
package manager
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bufio"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"os/exec"
 | 
			
		||||
	"strings"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Zypper represents the Zypper package manager
 | 
			
		||||
type Zypper struct {
 | 
			
		||||
	CommonRPM
 | 
			
		||||
	rootCmd string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -111,38 +110,6 @@ func (z *Zypper) UpgradeAll(opts *Opts) error {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (z *Zypper) ListInstalled(opts *Opts) (map[string]string, error) {
 | 
			
		||||
	out := map[string]string{}
 | 
			
		||||
	cmd := exec.Command("rpm", "-qa", "--queryformat", "%{NAME}\u200b%|EPOCH?{%{EPOCH}:}:{}|%{VERSION}-%{RELEASE}\\n")
 | 
			
		||||
 | 
			
		||||
	stdout, err := cmd.StdoutPipe()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err = cmd.Start()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	scanner := bufio.NewScanner(stdout)
 | 
			
		||||
	for scanner.Scan() {
 | 
			
		||||
		name, version, ok := strings.Cut(scanner.Text(), "\u200b")
 | 
			
		||||
		if !ok {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		version = strings.TrimPrefix(version, "0:")
 | 
			
		||||
		out[name] = version
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err = scanner.Err()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return out, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (z *Zypper) getCmd(opts *Opts, mgrCmd string, args ...string) *exec.Cmd {
 | 
			
		||||
	var cmd *exec.Cmd
 | 
			
		||||
	if opts.AsRoot {
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user