Major update 4

This should be the final code update before we start testing things.
I think all the code is now in place to have the program function, barring any bugs in my code.

So, with that said, here's the changelog:

global changes:
```
- implement logger.go across the whole program
```

changes to main.go:
```
- add an import for strings
- implement the roughed in handling functions
```

changes to logger.go:
```
- create this little helper package to just handle all our logging nice and gracefully
```

changes to all_updater.go:
```
- basically completely redone. Accomplishes the same thing, just in a different, more efficient way.
```

changes to aur.go:
```
- add a function to clear the AllPac build cache for aur
```

changes to install.go:
```
- removed a duplicate function, set install.go to call the right one
```

changes to pacman.go:
```
- removed GetVersionFromPacman function (it shouldn't be here, it should be in search.go)
```

changes to search.go:
```
- add functions for getting info from, and parsing output from Snap, Pacman, Flatpak, and aur
```
This commit is contained in:
VetheonGames 2024-01-04 19:17:43 -07:00
parent 4b0a6e6d59
commit 50af1b9613
11 changed files with 610 additions and 71 deletions

View File

@ -6,6 +6,7 @@ import (
"flag" "flag"
"fmt" "fmt"
"os" "os"
"strings"
"pixelridgesoftworks.com/AllPac/pkg/packagemanager" "pixelridgesoftworks.com/AllPac/pkg/packagemanager"
) )
@ -70,27 +71,195 @@ func handleUpdate(cmd *flag.FlagSet) {
} }
} }
// handles the install command for packages
func handleInstall(cmd *flag.FlagSet) { func handleInstall(cmd *flag.FlagSet) {
// Parse and handle the install command packageNames := cmd.String("packages", "", "Comma-separated list of packages to install")
// Use functions from install to install packages cmd.Parse(os.Args[2:])
if *packageNames == "" {
fmt.Println("You must specify at least one package name.")
cmd.Usage()
return
} }
packages := strings.Split(*packageNames, ",")
searchResults, err := packagemanager.SearchAllSources(packages)
if err != nil {
fmt.Printf("Error searching for packages: %v\n", err)
return
}
for _, result := range searchResults {
fmt.Printf("Searching for package: %s\n", result.PackageName)
if len(result.Results) == 0 {
fmt.Println("No sources found for package.")
continue
}
sourceIndex := promptUserForSource(result.Results)
if sourceIndex < 0 || sourceIndex >= len(result.Results) {
fmt.Println("Invalid selection. Skipping package.")
continue
}
selectedSource := result.Results[sourceIndex].Source
fmt.Printf("Installing %s from %s...\n", result.PackageName, selectedSource)
switch selectedSource {
case "pacman":
err = packagemanager.InstallPackagePacman(result.PackageName)
case "snap":
err = packagemanager.InstallPackageSnap(result.PackageName)
case "flatpak":
err = packagemanager.InstallPackageFlatpak(result.PackageName)
case "aur":
_, err = packagemanager.CloneAndInstallFromAUR(fmt.Sprintf("https://aur.archlinux.org/%s.git", result.PackageName), false)
default:
fmt.Printf("Unknown source for package %s\n", result.PackageName)
continue
}
if err != nil {
fmt.Printf("Error installing package %s from %s: %v\n", result.PackageName, selectedSource, err)
} else {
fmt.Printf("Package %s installed successfully from %s.\n", result.PackageName, selectedSource)
}
}
}
// handleUninstall handles the uninstall command for packages
func handleUninstall(cmd *flag.FlagSet) { func handleUninstall(cmd *flag.FlagSet) {
// Parse and handle the uninstall command // Define a flag for accepting multiple package names
// Use functions from packagemanager to uninstall packages packageNames := cmd.String("packages", "", "Comma-separated list of packages to uninstall")
// Parse the command line arguments
cmd.Parse(os.Args[2:])
// Check if the package names were provided
if *packageNames == "" {
fmt.Println("You must specify at least one package name.")
cmd.Usage()
return
} }
// Split the package names and convert to a slice
packages := strings.Split(*packageNames, ",")
// Call the function to uninstall the packages
err := packagemanager.UninstallPackages(packages)
if err != nil {
fmt.Printf("Error uninstalling packages: %v\n", err)
} else {
fmt.Println("Requested packages uninstalled successfully.")
}
}
// handleSearch handles the search command for packages across different package managers
func handleSearch(cmd *flag.FlagSet) { func handleSearch(cmd *flag.FlagSet) {
// Parse and handle the search command // Define a flag for the package name
// Use functions from search to search for packages packageName := cmd.String("package", "", "Name of the package to search")
// Parse the command line arguments
cmd.Parse(os.Args[2:])
// Check if the package name was provided
if *packageName == "" {
fmt.Println("You must specify a package name.")
cmd.Usage()
return
} }
// Search in Pacman
pacmanResults, err := packagemanager.SearchPacman(*packageName)
if err != nil {
fmt.Printf("Error searching in Pacman: %v\n", err)
} else {
fmt.Println("Pacman Results:")
for _, result := range pacmanResults {
fmt.Println(result)
}
}
// Search in Snap
snapResults, err := packagemanager.SearchSnap(*packageName)
if err != nil {
fmt.Printf("Error searching in Snap: %v\n", err)
} else {
fmt.Println("Snap Results:")
for _, result := range snapResults {
fmt.Println(result)
}
}
// Search in Flatpak
flatpakResults, err := packagemanager.SearchFlatpak(*packageName)
if err != nil {
fmt.Printf("Error searching in Flatpak: %v\n", err)
} else {
fmt.Println("Flatpak Results:")
for _, result := range flatpakResults {
fmt.Println(result)
}
}
// Search in AUR
aurResults, err := packagemanager.SearchAUR(*packageName)
if err != nil {
fmt.Printf("Error searching in AUR: %v\n", err)
} else {
fmt.Println("AUR Results:")
for _, result := range aurResults {
fmt.Printf("%s - %s\n", result.Name, result.Version)
}
}
}
// handleRebuild handles the rebuild command for an AUR package
func handleRebuild(cmd *flag.FlagSet) { func handleRebuild(cmd *flag.FlagSet) {
// Parse and handle the search command // Define a flag for the package name
// Use functions from search to search for packages packageName := cmd.String("package", "", "Name of the AUR package to rebuild")
// Parse the command line arguments
cmd.Parse(os.Args[2:])
// Check if the package name was provided
if *packageName == "" {
fmt.Println("You must specify a package name.")
cmd.Usage()
return
} }
func handleCleanAur(cmd *flag.FlagSet) { // Call the function to rebuild and reinstall the AUR package
// Parse and handle the search command err := packagemanager.RebuildAndReinstallAURPackage(*packageName)
// Use functions from search to search for packages if err != nil {
fmt.Printf("Error rebuilding package %s: %v\n", *packageName, err)
} else {
fmt.Printf("Package %s rebuilt and reinstalled successfully.\n", *packageName)
}
}
// handleCleanAur handles the cleaning of AUR cache
func handleCleanAur(cmd *flag.FlagSet) {
// Parse the command flags if needed
cmd.Parse(os.Args[2:])
// Call the function to clear the AUR cache
err := packagemanager.ClearAllPacCache()
if err != nil {
fmt.Printf("Error clearing AUR cache: %v\n", err)
return
}
fmt.Println("AUR cache cleared successfully.")
}
// prompts the user to select a source for installation
func promptUserForSource(sources []packagemanager.SourceResult) int {
for i, source := range sources {
fmt.Printf("%d: %s\n", i, source.Source)
}
fmt.Print("Select the source number to install from: ")
var choice int
fmt.Scan(&choice)
return choice
} }

59
pkg/logger/logger.go Normal file
View File

@ -0,0 +1,59 @@
package logger
import (
"io"
"log"
"os"
"path/filepath"
"fmt"
)
var Logger *log.Logger
func Init(logFilePath string) error {
if err := os.MkdirAll(filepath.Dir(logFilePath), 0755); err != nil {
return err
}
logFile, err := os.OpenFile(logFilePath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
if err != nil {
return err
}
Logger = log.New(logFile, "AllPac: ", log.Ldate|log.Ltime|log.Lshortfile)
Logger.SetOutput(io.MultiWriter(os.Stderr, logFile))
return nil
}
func Info(v ...interface{}) {
Logger.Println("INFO: " + fmt.Sprint(v...))
}
func Infof(format string, v ...interface{}) {
Logger.Printf("INFO: "+format, v...)
}
func Warn(v ...interface{}) {
Logger.Println("WARN: " + fmt.Sprint(v...))
}
func Warnf(format string, v ...interface{}) {
Logger.Printf("WARN: "+format, v...)
}
func Error(v ...interface{}) {
Logger.Println("ERROR: " + fmt.Sprint(v...))
}
func Errorf(format string, v ...interface{}) {
Logger.Printf("ERROR: "+format, v...)
}
func Debug(v ...interface{}) {
Logger.Println("DEBUG: " + fmt.Sprint(v...))
}
func Debugf(format string, v ...interface{}) {
Logger.Printf("DEBUG: "+format, v...)
}

View File

@ -3,44 +3,126 @@ package packagemanager
import ( import (
"fmt" "fmt"
"sync" "sync"
"pixelridgesoftworks.com/AllPac/pkg/logger"
) )
// UpdateAllPackages updates all packages on the system // UpdateAllPackages updates all packages on the system
func UpdateAllPackages() error { func UpdateAllPackages() error {
pkgList, err := readPackageList() pkgList, err := readPackageList()
if err != nil { if err != nil {
logger.Errorf("Failed to load config: %v", err)
return fmt.Errorf("error reading package list: %v", err) return fmt.Errorf("error reading package list: %v", err)
} }
var wg sync.WaitGroup // Categorize packages by their source
for pkgName, pkgInfo := range pkgList { pacmanPackages, aurPackages, snapPackages, flatpakPackages := separatePackagesBySource(pkgList)
wg.Add(1)
go func(name string, info PackageInfo) { // Check and collect packages that need updating for each category
defer wg.Done() pacmanToUpdate := checkPackagesForUpdate(pacmanPackages, "pacman")
if err := checkAndUpdatePackage(name, info); err != nil { snapToUpdate := checkPackagesForUpdate(snapPackages, "snap")
fmt.Printf("Error updating package %s: %v\n", name, err) flatpakToUpdate := checkPackagesForUpdate(flatpakPackages, "flatpak")
// Perform batch updates
if err := UpdatePacmanPackages(pacmanToUpdate...); err != nil {
logger.Errorf("Error updating Pacman packages: %v\n", err)
} }
}(pkgName, pkgInfo) if err := UpdateSnapPackages(snapToUpdate...); err != nil {
logger.Errorf("Error updating Snap packages: %v\n", err)
}
if err := UpdateFlatpakPackages(flatpakToUpdate...); err != nil {
logger.Errorf("Error updating Flatpak packages: %v\n", err)
} }
wg.Wait() // Update AUR packages (can be done concurrently)
updateAURPackagesConcurrently(aurPackages)
fmt.Println("All packages have been updated.") fmt.Println("All packages have been updated.")
logger.Info("All packages have been updated.")
return nil return nil
} }
// checkAndUpdatePackage checks if an update is available for the package and updates it // separatePackagesBySource categorizes package names by their source
func checkAndUpdatePackage(name string, info PackageInfo) error { func separatePackagesBySource(pkgList PackageList) ([]string, []string, []string, []string) {
// Implement logic to check for the latest version and update var pacmanPackages, aurPackages, snapPackages, flatpakPackages []string
return nil for pkgName, pkgInfo := range pkgList {
switch pkgInfo.Source {
case "pacman":
pacmanPackages = append(pacmanPackages, pkgName)
case "aur":
aurPackages = append(aurPackages, pkgName)
case "snap":
snapPackages = append(snapPackages, pkgName)
case "flatpak":
flatpakPackages = append(flatpakPackages, pkgName)
}
}
return pacmanPackages, aurPackages, snapPackages, flatpakPackages
} }
// functions to get the latest version for each package manager // checkPackagesForUpdate checks which packages need updating and returns their names
func getLatestPacmanVersion(packageName string) (string, error) { func checkPackagesForUpdate(packageNames []string, source string) []string {
// Use SearchPacman to get the latest version var toUpdate []string
// Parse the output to extract the version for _, name := range packageNames {
// Return the version if needsUpdate, _ := checkIfPackageNeedsUpdate(name, source); needsUpdate {
// ... toUpdate = append(toUpdate, name)
return "", nil }
}
return toUpdate
} }
// Similar implementations for getLatestAURVersion, getLatestSnapVersion, getLatestFlatpakVersion // checkIfPackageNeedsUpdate checks if a given package needs an update
func checkIfPackageNeedsUpdate(name, source string) (bool, error) {
var currentVersion, latestVersion string
var err error
// Retrieve the current version of the package from the package list
pkgList, err := readPackageList()
if err != nil {
logger.Errorf("error reading package list: %v", err)
return false, fmt.Errorf("error reading package list: %v", err)
}
if pkgInfo, exists := pkgList[name]; exists {
currentVersion = pkgInfo.Version
} else {
logger.Errorf("package %s not found in package list", name)
return false, fmt.Errorf("package %s not found in package list", name)
}
// Get the latest version based on the source
switch source {
case "pacman":
latestVersion, err = GetPacmanPackageVersion(name)
case "aur":
latestVersion, err = GetAURPackageVersion(name)
case "snap":
latestVersion, err = GetSnapPackageVersion(name)
case "flatpak":
latestVersion, err = GetFlatpakPackageVersion(name)
default:
logger.Errorf("unknown package source for %s", name)
return false, fmt.Errorf("unknown package source for %s", name)
}
if err != nil {
logger.Errorf("An error has occured:", err)
return false, err
}
// Compare the current version with the latest version
return currentVersion != latestVersion, nil
}
// updateAURPackagesConcurrently updates AUR packages using concurrency
func updateAURPackagesConcurrently(packageNames []string) {
var wg sync.WaitGroup
for _, pkgName := range packageNames {
wg.Add(1)
go func(name string) {
defer wg.Done()
if err := UpdateAURPackages(name); err != nil {
logger.Errorf("Error updating AUR package %s: %v\n", name, err)
}
}(pkgName)
}
wg.Wait()
}

View File

@ -3,6 +3,9 @@ package packagemanager
import ( import (
"fmt" "fmt"
"os/exec" "os/exec"
"os"
"path/filepath"
"pixelridgesoftworks.com/AllPac/pkg/logger"
) )
// AURPackageInfo represents the package information from the AUR // AURPackageInfo represents the package information from the AUR
@ -15,12 +18,14 @@ type AURPackageInfo struct {
func UpdateAURPackages(packageNames ...string) error { func UpdateAURPackages(packageNames ...string) error {
pkgList, err := ReadPackageList() pkgList, err := ReadPackageList()
if err != nil { if err != nil {
logger.Errorf("error reading package list: %v", err)
return fmt.Errorf("error reading package list: %v", err) return fmt.Errorf("error reading package list: %v", err)
} }
for _, packageName := range packageNames { for _, packageName := range packageNames {
aurInfo, err := fetchAURPackageInfo(packageName) aurInfo, err := fetchAURPackageInfo(packageName)
if err != nil { if err != nil {
logger.Errorf("error fetching AUR package info for %s: %v", packageName, err)
return fmt.Errorf("error fetching AUR package info for %s: %v", packageName, err) return fmt.Errorf("error fetching AUR package info for %s: %v", packageName, err)
} }
@ -28,6 +33,7 @@ func UpdateAURPackages(packageNames ...string) error {
if !ok || installedInfo.Version != aurInfo.Version { if !ok || installedInfo.Version != aurInfo.Version {
_, err := CloneAndInstallFromAUR("https://aur.archlinux.org/" + packageName + ".git", true) _, err := CloneAndInstallFromAUR("https://aur.archlinux.org/" + packageName + ".git", true)
if err != nil { if err != nil {
logger.Errorf("error updating AUR package %s: %v", packageName, err)
return fmt.Errorf("error updating AUR package %s: %v", packageName, err) return fmt.Errorf("error updating AUR package %s: %v", packageName, err)
} }
} }
@ -40,7 +46,59 @@ func UninstallAURPackage(packageName string) error {
// Uninstalling an AUR package is typically done with pacman // Uninstalling an AUR package is typically done with pacman
cmd := exec.Command("sudo", "pacman", "-Rns", "--noconfirm", packageName) cmd := exec.Command("sudo", "pacman", "-Rns", "--noconfirm", packageName)
if output, err := cmd.CombinedOutput(); err != nil { if output, err := cmd.CombinedOutput(); err != nil {
logger.Errorf("error uninstalling AUR package: %s, %v", output, err)
return fmt.Errorf("error uninstalling AUR package: %s, %v", output, err) return fmt.Errorf("error uninstalling AUR package: %s, %v", output, err)
} }
return nil return nil
} }
// ClearAllPacCache clears the contents of the ~/.allpac/cache/ directory
func ClearAllPacCache() error {
cacheDir, err := getCacheDir()
if err != nil {
logger.Errorf("An error has occured:", err)
return err
}
// Remove the directory and its contents
err = os.RemoveAll(cacheDir)
if err != nil {
logger.Errorf("An error has occured:", err)
return err
}
// Optionally, recreate the cache directory after clearing it
return os.MkdirAll(cacheDir, 0755)
}
// getCacheDir returns the path to the ~/.allpac/cache/ directory
func getCacheDir() (string, error) {
userHomeDir, err := os.UserHomeDir()
if err != nil {
logger.Errorf("An error has occured:", err)
return "", err
}
return filepath.Join(userHomeDir, ".allpac", "cache"), nil
}
// RebuildAndReinstallAURPackage rebuilds and reinstalls the specified AUR package
func RebuildAndReinstallAURPackage(packageName string) error {
// Read the package list
pkgList, err := readPackageList()
if err != nil {
logger.Errorf("error reading package list: %v", err)
return fmt.Errorf("error reading package list: %v", err)
}
// Check if the package is in the list and is an AUR package
pkgInfo, found := pkgList[packageName]
if !found || pkgInfo.Source != "aur" {
logger.Errorf("package %s is not found or not an AUR package", packageName)
return fmt.Errorf("package %s is not found or not an AUR package", packageName)
}
// Rebuild and reinstall the package
_, err = CloneAndInstallFromAUR(fmt.Sprintf("https://aur.archlinux.org/%s.git", packageName), false)
logger.Errorf("An error has occured:", err)
return err
}

View File

@ -6,6 +6,7 @@ import (
"os/exec" "os/exec"
"fmt" "fmt"
"strings" "strings"
"pixelridgesoftworks.com/AllPac/pkg/logger"
) )
// UpdateFlatpakPackages updates specified Flatpak packages or all if no specific package is provided // UpdateFlatpakPackages updates specified Flatpak packages or all if no specific package is provided
@ -19,6 +20,7 @@ func UpdateFlatpakPackages(packageNames ...string) error {
} }
if output, err := cmd.CombinedOutput(); err != nil { if output, err := cmd.CombinedOutput(); err != nil {
logger.Errorf("error updating Flatpak packages: %s, %v", output, err)
return fmt.Errorf("error updating Flatpak packages: %s, %v", output, err) return fmt.Errorf("error updating Flatpak packages: %s, %v", output, err)
} }
return nil return nil
@ -28,6 +30,7 @@ func UpdateFlatpakPackages(packageNames ...string) error {
func UninstallFlatpakPackage(packageName string) error { func UninstallFlatpakPackage(packageName string) error {
cmd := exec.Command("flatpak", "uninstall", "-y", packageName) cmd := exec.Command("flatpak", "uninstall", "-y", packageName)
if output, err := cmd.CombinedOutput(); err != nil { if output, err := cmd.CombinedOutput(); err != nil {
logger.Errorf("error uninstalling Flatpak package: %s, %v", output, err)
return fmt.Errorf("error uninstalling Flatpak package: %s, %v", output, err) return fmt.Errorf("error uninstalling Flatpak package: %s, %v", output, err)
} }
return nil return nil
@ -38,6 +41,7 @@ func GetVersionFromFlatpak(applicationID string) (string, error) {
cmd := exec.Command("flatpak", "info", applicationID) cmd := exec.Command("flatpak", "info", applicationID)
output, err := cmd.CombinedOutput() output, err := cmd.CombinedOutput()
if err != nil { if err != nil {
logger.Errorf("error getting flatpak package info: %v", err)
return "", fmt.Errorf("error getting flatpak package info: %v", err) return "", fmt.Errorf("error getting flatpak package info: %v", err)
} }
@ -51,5 +55,6 @@ func GetVersionFromFlatpak(applicationID string) (string, error) {
break break
} }
} }
logger.Errorf("version not found for flatpak package: %s", applicationID)
return "", fmt.Errorf("version not found for flatpak package: %s", applicationID) return "", fmt.Errorf("version not found for flatpak package: %s", applicationID)
} }

View File

@ -10,21 +10,25 @@ import (
"os/exec" "os/exec"
"os/user" "os/user"
"path/filepath" "path/filepath"
"pixelridgesoftworks.com/AllPac/pkg/logger"
) )
// InstallPackagePacman installs a package using Pacman and logs the installation // InstallPackagePacman installs a package using Pacman and logs the installation
func InstallPackagePacman(packageName string) error { func InstallPackagePacman(packageName string) error {
cmd := exec.Command("sudo", "pacman", "-S", "--noconfirm", packageName) cmd := exec.Command("sudo", "pacman", "-S", "--noconfirm", packageName)
if output, err := cmd.CombinedOutput(); err != nil { if output, err := cmd.CombinedOutput(); err != nil {
logger.Errorf("error installing package with Pacman: %s, %v", output, err)
return fmt.Errorf("error installing package with Pacman: %s, %v", output, err) return fmt.Errorf("error installing package with Pacman: %s, %v", output, err)
} }
version, err := GetVersionFromPacman(packageName) version, err := GetPacmanPackageVersion(packageName)
if err != nil { if err != nil {
logger.Errorf("An error has occured:", err)
return err return err
} }
if err := LogInstallation(packageName, "pacman", version); err != nil { if err := LogInstallation(packageName, "pacman", version); err != nil {
logger.Errorf("error logging installation: %v", err)
return fmt.Errorf("error logging installation: %v", err) return fmt.Errorf("error logging installation: %v", err)
} }
return nil return nil
@ -34,15 +38,18 @@ func InstallPackagePacman(packageName string) error {
func InstallPackageSnap(packageName string) error { func InstallPackageSnap(packageName string) error {
cmd := exec.Command("sudo", "snap", "install", packageName) cmd := exec.Command("sudo", "snap", "install", packageName)
if output, err := cmd.CombinedOutput(); err != nil { if output, err := cmd.CombinedOutput(); err != nil {
logger.Errorf("error installing package with Snap: %s, %v", output, err)
return fmt.Errorf("error installing package with Snap: %s, %v", output, err) return fmt.Errorf("error installing package with Snap: %s, %v", output, err)
} }
version, err := GetVersionFromSnap(packageName) version, err := GetVersionFromSnap(packageName)
if err != nil { if err != nil {
logger.Errorf("An error has occured:", err)
return err return err
} }
if err := LogInstallation(packageName, "snap", version); err != nil { if err := LogInstallation(packageName, "snap", version); err != nil {
logger.Errorf("error logging installation: %v", err)
return fmt.Errorf("error logging installation: %v", err) return fmt.Errorf("error logging installation: %v", err)
} }
return nil return nil
@ -52,15 +59,18 @@ func InstallPackageSnap(packageName string) error {
func InstallPackageFlatpak(packageName string) error { func InstallPackageFlatpak(packageName string) error {
cmd := exec.Command("flatpak", "install", "-y", packageName) cmd := exec.Command("flatpak", "install", "-y", packageName)
if output, err := cmd.CombinedOutput(); err != nil { if output, err := cmd.CombinedOutput(); err != nil {
logger.Errorf("error installing package with Flatpak: %s, %v", output, err)
return fmt.Errorf("error installing package with Flatpak: %s, %v", output, err) return fmt.Errorf("error installing package with Flatpak: %s, %v", output, err)
} }
version, err := GetVersionFromFlatpak(packageName) version, err := GetVersionFromFlatpak(packageName)
if err != nil { if err != nil {
logger.Errorf("An error has occured:", err)
return err return err
} }
if err := LogInstallation(packageName, "flatpak", version); err != nil { if err := LogInstallation(packageName, "flatpak", version); err != nil {
logger.Errorf("error logging installation: %v", err)
return fmt.Errorf("error logging installation: %v", err) return fmt.Errorf("error logging installation: %v", err)
} }
return nil return nil
@ -70,16 +80,19 @@ func InstallPackageFlatpak(packageName string) error {
func CloneAndInstallFromAUR(repoURL string, skipConfirmation bool) (string, error) { func CloneAndInstallFromAUR(repoURL string, skipConfirmation bool) (string, error) {
// Request root permissions // Request root permissions
if !skipConfirmation && !requestRootPermissions() { if !skipConfirmation && !requestRootPermissions() {
logger.Warnf("root permissions denied")
return "", fmt.Errorf("root permissions denied") return "", fmt.Errorf("root permissions denied")
} }
// Confirm before proceeding with each step // Confirm before proceeding with each step
if !skipConfirmation && !confirmAction("Do you want to download and build package from " + repoURL + "?") { if !skipConfirmation && !confirmAction("Do you want to download and build package from " + repoURL + "?") {
logger.Warnf("user aborted the action")
return "", fmt.Errorf("user aborted the action") return "", fmt.Errorf("user aborted the action")
} }
// Get the current user's home directory // Get the current user's home directory
usr, err := user.Current() usr, err := user.Current()
if err != nil { if err != nil {
logger.Errorf("error getting current user: %v", err)
return "", fmt.Errorf("error getting current user: %v", err) return "", fmt.Errorf("error getting current user: %v", err)
} }
@ -88,12 +101,14 @@ func CloneAndInstallFromAUR(repoURL string, skipConfirmation bool) (string, erro
// Ensure the base directory exists // Ensure the base directory exists
if err := os.MkdirAll(baseDir, 0755); err != nil { if err := os.MkdirAll(baseDir, 0755); err != nil {
logger.Errorf("error creating base directory: %v", err)
return "", fmt.Errorf("error creating base directory: %v", err) return "", fmt.Errorf("error creating base directory: %v", err)
} }
// Clone the repository // Clone the repository
cmdGitClone := exec.Command("git", "clone", repoURL, baseDir) cmdGitClone := exec.Command("git", "clone", repoURL, baseDir)
if output, err := cmdGitClone.CombinedOutput(); err != nil { if output, err := cmdGitClone.CombinedOutput(); err != nil {
logger.Errorf("error cloning AUR repo: %s, %v", output, err)
return "", fmt.Errorf("error cloning AUR repo: %s, %v", output, err) return "", fmt.Errorf("error cloning AUR repo: %s, %v", output, err)
} }
@ -103,27 +118,32 @@ func CloneAndInstallFromAUR(repoURL string, skipConfirmation bool) (string, erro
// Change directory to the cloned repository // Change directory to the cloned repository
if err := os.Chdir(repoDir); err != nil { if err := os.Chdir(repoDir); err != nil {
logger.Errorf("error changing directory: %v", err)
return "", fmt.Errorf("error changing directory: %v", err) return "", fmt.Errorf("error changing directory: %v", err)
} }
// Build the package using makepkg // Build the package using makepkg
cmdMakePkg := exec.Command("makepkg", "-si", "--noconfirm") cmdMakePkg := exec.Command("makepkg", "-si", "--noconfirm")
if output, err := cmdMakePkg.CombinedOutput(); err != nil { if output, err := cmdMakePkg.CombinedOutput(); err != nil {
logger.Errorf("error building package with makepkg: %s, %v", output, err)
return "", fmt.Errorf("error building package with makepkg: %s, %v", output, err) return "", fmt.Errorf("error building package with makepkg: %s, %v", output, err)
} }
// Extract the version from PKGBUILD // Extract the version from PKGBUILD
version, err := ExtractVersionFromPKGBUILD(repoDir) version, err := ExtractVersionFromPKGBUILD(repoDir)
if err != nil { if err != nil {
logger.Errorf("error extracting version from PKGBUILD: %v", err)
return "", fmt.Errorf("error extracting version from PKGBUILD: %v", err) return "", fmt.Errorf("error extracting version from PKGBUILD: %v", err)
} }
// Confirm before installing // Confirm before installing
if !skipConfirmation && !confirmAction("Do you want to install the built package " + repoName + "?") { if !skipConfirmation && !confirmAction("Do you want to install the built package " + repoName + "?") {
logger.Warnf("user aborted the installation")
return "", fmt.Errorf("user aborted the installation") return "", fmt.Errorf("user aborted the installation")
} }
if err := LogInstallation(repoName, "aur", version); err != nil { if err := LogInstallation(repoName, "aur", version); err != nil {
logger.Errorf("error logging installation")
return "", fmt.Errorf("error logging installation: %v", err) return "", fmt.Errorf("error logging installation: %v", err)
} }
@ -134,10 +154,12 @@ func CloneAndInstallFromAUR(repoURL string, skipConfirmation bool) (string, erro
func InstallSnap() error { func InstallSnap() error {
version, err := CloneAndInstallFromAUR("https://aur.archlinux.org/snapd.git", true) version, err := CloneAndInstallFromAUR("https://aur.archlinux.org/snapd.git", true)
if err != nil { if err != nil {
logger.Errorf("error installing Snap: %v", err)
return fmt.Errorf("error installing Snap: %v", err) return fmt.Errorf("error installing Snap: %v", err)
} }
if err := LogInstallation("snapd", "aur", version); err != nil { if err := LogInstallation("snapd", "aur", version); err != nil {
logger.Errorf("error logging installation")
return fmt.Errorf("error logging installation: %v", err) return fmt.Errorf("error logging installation: %v", err)
} }
return nil return nil
@ -146,6 +168,7 @@ func InstallSnap() error {
// InstallGit installs Git using Pacman // InstallGit installs Git using Pacman
func InstallGit() error { func InstallGit() error {
if err := InstallPackagePacman("git"); err != nil { if err := InstallPackagePacman("git"); err != nil {
logger.Errorf("error installing Git: %v", err)
return fmt.Errorf("error installing Git: %v", err) return fmt.Errorf("error installing Git: %v", err)
} }
return nil return nil
@ -154,6 +177,7 @@ func InstallGit() error {
// InstallBaseDevel installs the base-devel group using Pacman // InstallBaseDevel installs the base-devel group using Pacman
func InstallBaseDevel() error { func InstallBaseDevel() error {
if err := InstallPackagePacman("base-devel"); err != nil { if err := InstallPackagePacman("base-devel"); err != nil {
logger.Errorf("error installing base-devel: %v", err)
return fmt.Errorf("error installing base-devel: %v", err) return fmt.Errorf("error installing base-devel: %v", err)
} }
return nil return nil
@ -162,6 +186,7 @@ func InstallBaseDevel() error {
// InstallFlatpak installs the Flatpak package using Pacman // InstallFlatpak installs the Flatpak package using Pacman
func InstallFlatpak() error { func InstallFlatpak() error {
if err := InstallPackagePacman("flatpak"); err != nil { if err := InstallPackagePacman("flatpak"); err != nil {
logger.Errorf("error installing flatpak: %v", err)
return fmt.Errorf("error installing flatpak: %v", err) return fmt.Errorf("error installing flatpak: %v", err)
} }
return nil return nil

View File

@ -8,6 +8,7 @@ import (
"strings" "strings"
"fmt" "fmt"
"encoding/json" "encoding/json"
"pixelridgesoftworks.com/AllPac/pkg/logger"
) )
// extractVersionFromPKGBUILD reads the PKGBUILD file and extracts the package version // extractVersionFromPKGBUILD reads the PKGBUILD file and extracts the package version
@ -15,6 +16,7 @@ func ExtractVersionFromPKGBUILD(repoDir string) (string, error) {
pkgbuildPath := filepath.Join(repoDir, "PKGBUILD") pkgbuildPath := filepath.Join(repoDir, "PKGBUILD")
file, err := os.Open(pkgbuildPath) file, err := os.Open(pkgbuildPath)
if err != nil { if err != nil {
logger.Errorf("An error has occured:", err)
return "", err return "", err
} }
defer file.Close() defer file.Close()
@ -28,9 +30,11 @@ func ExtractVersionFromPKGBUILD(repoDir string) (string, error) {
} }
if err := scanner.Err(); err != nil { if err := scanner.Err(); err != nil {
logger.Errorf("An error has occured:", err)
return "", err return "", err
} }
logger.Errorf("pkgver not found in PKGBUILD")
return "", fmt.Errorf("pkgver not found in PKGBUILD") return "", fmt.Errorf("pkgver not found in PKGBUILD")
} }
@ -47,6 +51,7 @@ const pkgListFilename = "pkg.list"
func GetPkgListPath() (string, error) { func GetPkgListPath() (string, error) {
usr, err := user.Current() usr, err := user.Current()
if err != nil { if err != nil {
logger.Errorf("error getting current user: %v", err)
return "", fmt.Errorf("error getting current user: %v", err) return "", fmt.Errorf("error getting current user: %v", err)
} }
return filepath.Join(usr.HomeDir, ".allpac", pkgListFilename), nil return filepath.Join(usr.HomeDir, ".allpac", pkgListFilename), nil
@ -56,6 +61,7 @@ func GetPkgListPath() (string, error) {
func ReadPackageList() (PackageList, error) { func ReadPackageList() (PackageList, error) {
pkgListPath, err := GetPkgListPath() pkgListPath, err := GetPkgListPath()
if err != nil { if err != nil {
logger.Errorf("An error has occured:", err)
return nil, err return nil, err
} }
@ -64,6 +70,7 @@ func ReadPackageList() (PackageList, error) {
if os.IsNotExist(err) { if os.IsNotExist(err) {
return PackageList{}, nil // Return an empty list if file doesn't exist return PackageList{}, nil // Return an empty list if file doesn't exist
} }
logger.Errorf("error opening package list file: %v", err)
return nil, fmt.Errorf("error opening package list file: %v", err) return nil, fmt.Errorf("error opening package list file: %v", err)
} }
defer file.Close() defer file.Close()
@ -71,6 +78,7 @@ func ReadPackageList() (PackageList, error) {
var pkgList PackageList var pkgList PackageList
err = json.NewDecoder(file).Decode(&pkgList) err = json.NewDecoder(file).Decode(&pkgList)
if err != nil { if err != nil {
logger.Errorf("error decoding package list: %v", err)
return nil, fmt.Errorf("error decoding package list: %v", err) return nil, fmt.Errorf("error decoding package list: %v", err)
} }
@ -81,17 +89,20 @@ func ReadPackageList() (PackageList, error) {
func writePackageList(pkgList PackageList) error { func writePackageList(pkgList PackageList) error {
pkgListPath, err := GetPkgListPath() pkgListPath, err := GetPkgListPath()
if err != nil { if err != nil {
logger.Errorf("An error has occured:", err)
return err return err
} }
file, err := os.Create(pkgListPath) file, err := os.Create(pkgListPath)
if err != nil { if err != nil {
logger.Errorf("error creating package list file: %v", err)
return fmt.Errorf("error creating package list file: %v", err) return fmt.Errorf("error creating package list file: %v", err)
} }
defer file.Close() defer file.Close()
err = json.NewEncoder(file).Encode(pkgList) err = json.NewEncoder(file).Encode(pkgList)
if err != nil { if err != nil {
logger.Errorf("error encoding package list: %v", err)
return fmt.Errorf("error encoding package list: %v", err) return fmt.Errorf("error encoding package list: %v", err)
} }
@ -102,6 +113,7 @@ func writePackageList(pkgList PackageList) error {
func LogInstallation(packageName, source, version string) error { func LogInstallation(packageName, source, version string) error {
pkgList, err := readPackageList() pkgList, err := readPackageList()
if err != nil { if err != nil {
logger.Errorf("An error has occured:", err)
return err return err
} }
@ -126,6 +138,7 @@ func confirmAction(question string) bool {
fmt.Printf("%s [Y/n]: ", question) fmt.Printf("%s [Y/n]: ", question)
response, err := reader.ReadString('\n') response, err := reader.ReadString('\n')
if err != nil { if err != nil {
logger.Errorf("Error reading response: %v", err)
fmt.Println("Error reading response:", err) fmt.Println("Error reading response:", err)
return false return false
} }

View File

@ -3,9 +3,10 @@ package packagemanager
// This package is responsible for handling updating and uninstalling pacman packages // This package is responsible for handling updating and uninstalling pacman packages
import ( import (
"os/exec"
"fmt" "fmt"
"strings" "os/exec"
"pixelridgesoftworks.com/AllPac/pkg/logger"
) )
// UpdatePacmanPackages updates specified Pacman packages or all if no specific package is provided // UpdatePacmanPackages updates specified Pacman packages or all if no specific package is provided
@ -19,6 +20,7 @@ func UpdatePacmanPackages(packageNames ...string) error {
} }
if output, err := cmd.CombinedOutput(); err != nil { if output, err := cmd.CombinedOutput(); err != nil {
logger.Errorf("error updating Pacman packages: %s, %v", string(output), err)
return fmt.Errorf("error updating Pacman packages: %s, %v", string(output), err) return fmt.Errorf("error updating Pacman packages: %s, %v", string(output), err)
} }
return nil return nil
@ -28,23 +30,8 @@ func UpdatePacmanPackages(packageNames ...string) error {
func UninstallPacmanPackage(packageName string) error { func UninstallPacmanPackage(packageName string) error {
cmd := exec.Command("sudo", "pacman", "-Rns", "--noconfirm", packageName) cmd := exec.Command("sudo", "pacman", "-Rns", "--noconfirm", packageName)
if output, err := cmd.CombinedOutput(); err != nil { if output, err := cmd.CombinedOutput(); err != nil {
logger.Errorf("error uninstalling Pacman package: %s, %v", output, err)
return fmt.Errorf("error uninstalling Pacman package: %s, %v", output, err) return fmt.Errorf("error uninstalling Pacman package: %s, %v", output, err)
} }
return nil return nil
} }
// getVersionFromPacman gets the installed version of a package using Pacman
func GetVersionFromPacman(packageName string) (string, error) {
cmd := exec.Command("pacman", "-Qi", packageName)
output, err := cmd.CombinedOutput()
if err != nil {
return "", fmt.Errorf("error getting package version: %v", err)
}
for _, line := range strings.Split(string(output), "\n") {
if strings.HasPrefix(line, "Version") {
return strings.Fields(line)[2], nil
}
}
return "", fmt.Errorf("version not found for package: %s", packageName)
}

View File

@ -11,38 +11,45 @@ import (
"path/filepath" "path/filepath"
"strings" "strings"
"net/http" "net/http"
"pixelridgesoftworks.com/AllPac/pkg/logger"
) )
// UninstallPackages uninstalls the provided packages // uninstalls the provided packages
func UninstallPackages(packageNames []string) error { func UninstallPackages(packageNames []string) error {
pkgList, err := readPackageList() pkgList, err := readPackageList()
if err != nil { if err != nil {
logger.Errorf("An error has occured:", err)
return err return err
} }
for _, packageName := range packageNames { for _, packageName := range packageNames {
source, exists := pkgList[packageName] pkgInfo, exists := pkgList[packageName]
if !exists { if !exists {
logger.Warnf("Package %s not found in installed packages list\n", packageNames)
fmt.Printf("Package %s not found in installed packages list\n", packageName) fmt.Printf("Package %s not found in installed packages list\n", packageName)
continue continue
} }
switch source { switch pkgInfo.Source {
case "pacman": case "pacman":
err = UninstallPacmanPackage(packageName) err = UninstallPacmanPackage(packageName)
case "snap": case "snap":
err = UninstallSnapPackage(packageName) err = UninstallSnapPackage(packageName)
case "flatpak": case "flatpak":
err = UninstallFlatpakPackage(packageName) err = UninstallFlatpakPackage(packageName)
// Add cases for other package managers if necessary case "aur":
err = UninstallAURPackage(packageName)
default: default:
logger.Warnf("Unknown source for package %s\n", packageNames)
fmt.Printf("Unknown source for package %s\n", packageName) fmt.Printf("Unknown source for package %s\n", packageName)
continue continue
} }
if err != nil { if err != nil {
logger.Warnf("Error uninstalling package %s: %v\n", packageName, err)
fmt.Printf("Error uninstalling package %s: %v\n", packageName, err) fmt.Printf("Error uninstalling package %s: %v\n", packageName, err)
} else { } else {
logger.Infof("Successfully uninstalled package %s\n", packageName)
fmt.Printf("Successfully uninstalled package %s\n", packageName) fmt.Printf("Successfully uninstalled package %s\n", packageName)
} }
} }
@ -50,29 +57,32 @@ func UninstallPackages(packageNames []string) error {
return nil return nil
} }
// readPackageList reads the package list from the pkg.list file // reads the package list from the pkg.list file
func readPackageList() (PackageList, error) { func readPackageList() (PackageList, error) {
usr, err := user.Current() usr, err := user.Current()
if err != nil { if err != nil {
logger.Errorf("error getting current user: %v", err)
return nil, fmt.Errorf("error getting current user: %v", err) return nil, fmt.Errorf("error getting current user: %v", err)
} }
pkgListPath := filepath.Join(usr.HomeDir, ".allpac", "pkg.list") pkgListPath := filepath.Join(usr.HomeDir, ".allpac", "pkg.list")
file, err := ioutil.ReadFile(pkgListPath) file, err := ioutil.ReadFile(pkgListPath)
if err != nil { if err != nil {
logger.Errorf("error reading package list file: %v", err)
return nil, fmt.Errorf("error reading package list file: %v", err) return nil, fmt.Errorf("error reading package list file: %v", err)
} }
var pkgList PackageList var pkgList PackageList
err = json.Unmarshal(file, &pkgList) err = json.Unmarshal(file, &pkgList)
if err != nil { if err != nil {
logger.Errorf("error decoding package list: %v", err)
return nil, fmt.Errorf("error decoding package list: %v", err) return nil, fmt.Errorf("error decoding package list: %v", err)
} }
return pkgList, nil return pkgList, nil
} }
// AURResponse represents the structure of the response from AUR RPC // represents the structure of the response from AUR RPC
type AURResponse struct { type AURResponse struct {
Version int `json:"version"` Version int `json:"version"`
Type string `json:"type"` Type string `json:"type"`
@ -80,7 +90,7 @@ type AURResponse struct {
Results []AURPackage `json:"results"` Results []AURPackage `json:"results"`
} }
// AURPackage represents a package in the AUR // represents a package in the AUR
type AURPackage struct { type AURPackage struct {
ID int `json:"ID"` ID int `json:"ID"`
Name string `json:"Name"` Name string `json:"Name"`
@ -90,61 +100,64 @@ type AURPackage struct {
// Add other fields as needed // Add other fields as needed
} }
// SearchPacman searches for a package in the Pacman repositories // searches for a package in the Pacman repositories
func SearchPacman(packageName string) ([]string, error) { func SearchPacman(packageName string) ([]string, error) {
cmd := exec.Command("pacman", "-Ss", packageName) cmd := exec.Command("pacman", "-Ss", packageName)
output, err := cmd.CombinedOutput() output, err := cmd.CombinedOutput()
if err != nil { if err != nil {
logger.Errorf("error searching Pacman: %v", err)
return nil, fmt.Errorf("error searching Pacman: %v", err) return nil, fmt.Errorf("error searching Pacman: %v", err)
} }
return parsePacmanOutput(string(output)), nil return parsePacmanOutput(string(output)), nil
} }
// SearchSnap searches for a package in the Snap store // searches for a package in the Snap store
func SearchSnap(packageName string) ([]string, error) { func SearchSnap(packageName string) ([]string, error) {
cmd := exec.Command("snap", "find", packageName) cmd := exec.Command("snap", "find", packageName)
output, err := cmd.CombinedOutput() output, err := cmd.CombinedOutput()
if err != nil { if err != nil {
logger.Errorf("error searching Snap: %v", err)
return nil, fmt.Errorf("error searching Snap: %v", err) return nil, fmt.Errorf("error searching Snap: %v", err)
} }
return strings.Split(string(output), "\n"), nil return strings.Split(string(output), "\n"), nil
} }
// SearchFlatpak searches for a package in Flatpak repositories // searches for a package in Flatpak repositories
func SearchFlatpak(packageName string) ([]string, error) { func SearchFlatpak(packageName string) ([]string, error) {
cmd := exec.Command("flatpak", "search", packageName) cmd := exec.Command("flatpak", "search", packageName)
output, err := cmd.CombinedOutput() output, err := cmd.CombinedOutput()
if err != nil { if err != nil {
logger.Errorf("error searching Flatpak: %v", err)
return nil, fmt.Errorf("error searching Flatpak: %v", err) return nil, fmt.Errorf("error searching Flatpak: %v", err)
} }
return strings.Split(string(output), "\n"), nil return strings.Split(string(output), "\n"), nil
} }
// SearchAUR searches the AUR for the given term // searches the AUR for the given term
func SearchAUR(searchTerm string) ([]AURPackage, error) { func SearchAUR(searchTerm string) ([]AURPackage, error) {
url := fmt.Sprintf("https://aur.archlinux.org/rpc/?v=5&type=search&arg=%s", searchTerm) url := fmt.Sprintf("https://aur.archlinux.org/rpc/?v=5&type=search&arg=%s", searchTerm)
resp, err := http.Get(url) resp, err := http.Get(url)
if err != nil { if err != nil {
logger.Errorf("error making request to AUR: %v", err)
return nil, fmt.Errorf("error making request to AUR: %v", err) return nil, fmt.Errorf("error making request to AUR: %v", err)
} }
defer resp.Body.Close() defer resp.Body.Close()
var aurResponse AURResponse var aurResponse AURResponse
if err := json.NewDecoder(resp.Body).Decode(&aurResponse); err != nil { if err := json.NewDecoder(resp.Body).Decode(&aurResponse); err != nil {
logger.Errorf("error decoding AUR response: %v", err)
return nil, fmt.Errorf("error decoding AUR response: %v", err) return nil, fmt.Errorf("error decoding AUR response: %v", err)
} }
return aurResponse.Results, nil return aurResponse.Results, nil
} }
// parsePacmanOutput parses the output from Pacman search command // parses the output from Pacman search command
func parsePacmanOutput(output string) []string { func parsePacmanOutput(output string) []string {
// Split the output into sections, each representing a package
sections := strings.Split(output, "\n\n") sections := strings.Split(output, "\n\n")
var packages []string var packages []string
for _, section := range sections { for _, section := range sections {
// Split each section into lines
lines := strings.Split(section, "\n") lines := strings.Split(section, "\n")
// The first line should contain the package name and version // The first line should contain the package name and version
@ -163,10 +176,11 @@ func parsePacmanOutput(output string) []string {
return packages return packages
} }
// GetPacmanPackageVersion returns the version of a package in the Pacman repositories // returns the version of a package in the Pacman repositories
func GetPacmanPackageVersion(packageName string) (string, error) { func GetPacmanPackageVersion(packageName string) (string, error) {
searchResults, err := SearchPacman(packageName) searchResults, err := SearchPacman(packageName)
if err != nil { if err != nil {
logger.Errorf("An error has occured:", err)
return "", err return "", err
} }
@ -176,24 +190,26 @@ func GetPacmanPackageVersion(packageName string) (string, error) {
} }
} }
logger.Errorf("package %s not found in Pacman", packageName)
return "", fmt.Errorf("package %s not found in Pacman", packageName) return "", fmt.Errorf("package %s not found in Pacman", packageName)
} }
// extractVersionFromPacmanResult extracts the version from a Pacman search result string // extracts the version from a Pacman search result string
func extractVersionFromPacmanResult(result string) string { func extractVersionFromPacmanResult(result string) string {
// Assuming the result is in the format "packageName version description" // Assuming the result is in the format "packageName version description"
parts := strings.Fields(result) parts := strings.Fields(result)
if len(parts) >= 2 { if len(parts) >= 2 {
return parts[1] // The second element should be the version return parts[1]
} }
return "" return ""
} }
// fetchAURPackageInfo fetches package information from the AUR // fetches package information from the AUR
func fetchAURPackageInfo(packageName string) (*AURPackageInfo, error) { func fetchAURPackageInfo(packageName string) (*AURPackageInfo, error) {
url := fmt.Sprintf("https://aur.archlinux.org/rpc/?v=5&type=info&arg[]=%s", packageName) url := fmt.Sprintf("https://aur.archlinux.org/rpc/?v=5&type=info&arg[]=%s", packageName)
resp, err := http.Get(url) resp, err := http.Get(url)
if err != nil { if err != nil {
logger.Errorf("An error has occured:", err)
return nil, err return nil, err
} }
defer resp.Body.Close() defer resp.Body.Close()
@ -202,12 +218,130 @@ func fetchAURPackageInfo(packageName string) (*AURPackageInfo, error) {
Results []AURPackageInfo `json:"results"` Results []AURPackageInfo `json:"results"`
} }
if err := json.NewDecoder(resp.Body).Decode(&result); err != nil { if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
logger.Errorf("An error has occured:", err)
return nil, err return nil, err
} }
if len(result.Results) == 0 { if len(result.Results) == 0 {
logger.Errorf("package %s not found in AUR", packageName)
return nil, fmt.Errorf("package %s not found in AUR", packageName) return nil, fmt.Errorf("package %s not found in AUR", packageName)
} }
return &result.Results[0], nil return &result.Results[0], nil
} }
// returns the version of a package in the Snap store
func GetSnapPackageVersion(packageName string) (string, error) {
cmd := exec.Command("snap", "info", packageName)
output, err := cmd.CombinedOutput()
if err != nil {
logger.Errorf("error getting Snap package info: %v", err)
return "", fmt.Errorf("error getting Snap package info: %v", err)
}
return parseSnapInfoOutput(string(output)), nil
}
// parses the output from the Snap info command to extract the version
func parseSnapInfoOutput(output string) string {
lines := strings.Split(output, "\n")
for _, line := range lines {
if strings.HasPrefix(line, "installed:") {
parts := strings.Fields(line)
if len(parts) >= 2 {
return strings.TrimSpace(parts[1])
}
}
}
return ""
}
// returns the version of a package in Flatpak repositories
func GetFlatpakPackageVersion(packageName string) (string, error) {
cmd := exec.Command("flatpak", "info", packageName)
output, err := cmd.CombinedOutput()
if err != nil {
logger.Errorf("error getting Flatpak package info: %v", err)
return "", fmt.Errorf("error getting Flatpak package info: %v", err)
}
return parseFlatpakInfoOutput(string(output)), nil
}
// parses the output from the Flatpak info command to extract the version
func parseFlatpakInfoOutput(output string) string {
lines := strings.Split(output, "\n")
for _, line := range lines {
if strings.HasPrefix(line, "Version:") {
parts := strings.Fields(line)
if len(parts) >= 2 {
return strings.TrimSpace(parts[1])
}
}
}
return ""
}
// returns the version of a package in the AUR
func GetAURPackageVersion(packageName string) (string, error) {
aurInfo, err := fetchAURPackageInfo(packageName)
if err != nil {
logger.Errorf("An error has occured:", err)
return "", err
}
return aurInfo.Version, nil
}
// represents the search result from a specific source
type SourceResult struct {
Source string
Results []string
}
// represents the search results for a package across different sources
type PackageSearchResult struct {
PackageName string
Results []SourceResult
}
// searches for packages across Pacman, Snap, Flatpak, and AUR
func SearchAllSources(packageNames []string) ([]PackageSearchResult, error) {
var allPackageResults []PackageSearchResult
for _, packageName := range packageNames {
var packageResults PackageSearchResult
packageResults.PackageName = packageName
// Search in Pacman
pacmanResults, err := SearchPacman(packageName)
if err == nil {
packageResults.Results = append(packageResults.Results, SourceResult{"Pacman", pacmanResults})
}
// Search in Snap
snapResults, err := SearchSnap(packageName)
if err == nil {
packageResults.Results = append(packageResults.Results, SourceResult{"Snap", snapResults})
}
// Search in Flatpak
flatpakResults, err := SearchFlatpak(packageName)
if err == nil {
packageResults.Results = append(packageResults.Results, SourceResult{"Flatpak", flatpakResults})
}
// Search in AUR
aurResults, err := SearchAUR(packageName)
if err == nil {
var aurResultStrings []string
for _, result := range aurResults {
aurResultStrings = append(aurResultStrings, fmt.Sprintf("%s - %s", result.Name, result.Version))
}
packageResults.Results = append(packageResults.Results, SourceResult{"AUR", aurResultStrings})
}
allPackageResults = append(allPackageResults, packageResults)
}
return allPackageResults, nil
}

View File

@ -6,6 +6,7 @@ import (
"os/exec" "os/exec"
"fmt" "fmt"
"strings" "strings"
"pixelridgesoftworks.com/AllPac/pkg/logger"
) )
// UpdateSnapPackages updates specified Snap packages or all if no specific package is provided // UpdateSnapPackages updates specified Snap packages or all if no specific package is provided
@ -19,6 +20,7 @@ func UpdateSnapPackages(packageNames ...string) error {
} }
if output, err := cmd.CombinedOutput(); err != nil { if output, err := cmd.CombinedOutput(); err != nil {
logger.Errorf("error updating Snap packages: %s, %v", string(output), err)
return fmt.Errorf("error updating Snap packages: %s, %v", string(output), err) return fmt.Errorf("error updating Snap packages: %s, %v", string(output), err)
} }
return nil return nil
@ -28,6 +30,7 @@ func UpdateSnapPackages(packageNames ...string) error {
func UninstallSnapPackage(packageName string) error { func UninstallSnapPackage(packageName string) error {
cmd := exec.Command("sudo", "snap", "remove", packageName) cmd := exec.Command("sudo", "snap", "remove", packageName)
if output, err := cmd.CombinedOutput(); err != nil { if output, err := cmd.CombinedOutput(); err != nil {
logger.Errorf("error uninstalling Snap package: %s, %v", string(output), err)
return fmt.Errorf("error uninstalling Snap package: %s, %v", string(output), err) return fmt.Errorf("error uninstalling Snap package: %s, %v", string(output), err)
} }
return nil return nil
@ -38,6 +41,7 @@ func GetVersionFromSnap(packageName string) (string, error) {
cmd := exec.Command("snap", "info", packageName) cmd := exec.Command("snap", "info", packageName)
output, err := cmd.CombinedOutput() output, err := cmd.CombinedOutput()
if err != nil { if err != nil {
logger.Errorf("error getting snap package info: %v", err)
return "", fmt.Errorf("error getting snap package info: %v", err) return "", fmt.Errorf("error getting snap package info: %v", err)
} }
@ -51,5 +55,6 @@ func GetVersionFromSnap(packageName string) (string, error) {
break break
} }
} }
logger.Errorf("version not found for snap package: %s", packageName)
return "", fmt.Errorf("version not found for snap package: %s", packageName) return "", fmt.Errorf("version not found for snap package: %s", packageName)
} }

View File

@ -10,6 +10,7 @@ import (
"os/exec" "os/exec"
"fmt" "fmt"
"pixelridgesoftworks.com/AllPac/pkg/packagemanager" "pixelridgesoftworks.com/AllPac/pkg/packagemanager"
"pixelridgesoftworks.com/AllPac/pkg/logger"
) )
// isCommandAvailable checks if a command exists // isCommandAvailable checks if a command exists
@ -24,6 +25,7 @@ func isCommandAvailable(name string) bool {
// EnsurePacman ensures that Pacman is installed and available // EnsurePacman ensures that Pacman is installed and available
func EnsurePacman() error { func EnsurePacman() error {
if !isCommandAvailable("pacman") { if !isCommandAvailable("pacman") {
logger.Errorf("pacman is not available, which is required for AllPac to function")
// Pacman should always be available on Arch-based systems, handle this as an error or special case // Pacman should always be available on Arch-based systems, handle this as an error or special case
return fmt.Errorf("pacman is not available, which is required for AllPac to function") return fmt.Errorf("pacman is not available, which is required for AllPac to function")
} }