Major Update 3
changes to main.go: ``` - rough write main.go ``` changes to install package: ``` - merged install package with packagemanager package ``` changes to packagemanager package: ``` - merged search and install packages into this one - write all_updater.go in rough form, this will handle when the user wants to update all the packages across all backends - rough write all of aur.go, this will handle AUR package update logic, and AUR package uninstall logic - add a function to flatpak.go to retrieve a packages version - move utility functions out of install.go and into installer_utils.go - add a function to pacman.go to fetch a programs version from pacman - add a function to snap.go to fetch a programs version from pacman ``` changes to toolcheck package: ``` - change toolcheck.go to import the packagemanager instead of install, since we merged the two ```
This commit is contained in:
parent
5d9a6e428a
commit
4b0a6e6d59
93
cmd/main.go
93
cmd/main.go
|
@ -1,3 +1,96 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
// This file is our main entrypoint, and build point for AllPac
|
// This file is our main entrypoint, and build point for AllPac
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"pixelridgesoftworks.com/AllPac/pkg/packagemanager"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
// Define flags for different commands
|
||||||
|
updateCmd := flag.NewFlagSet("update", flag.ExitOnError)
|
||||||
|
installCmd := flag.NewFlagSet("install", flag.ExitOnError)
|
||||||
|
uninstallCmd := flag.NewFlagSet("uninstall", flag.ExitOnError)
|
||||||
|
searchCmd := flag.NewFlagSet("search", flag.ExitOnError)
|
||||||
|
aurRebuildCmd := flag.NewFlagSet("rebuild", flag.ExitOnError)
|
||||||
|
aurCleanCmd := flag.NewFlagSet("clean-aur", flag.ExitOnError)
|
||||||
|
|
||||||
|
if len(os.Args) < 2 {
|
||||||
|
fmt.Println("Expected 'update', 'install', 'uninstall', 'search', 'rebuild', or 'clean-aur' subcommands")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
switch os.Args[1] {
|
||||||
|
case "update":
|
||||||
|
handleUpdate(updateCmd)
|
||||||
|
case "install":
|
||||||
|
handleInstall(installCmd)
|
||||||
|
case "uninstall":
|
||||||
|
handleUninstall(uninstallCmd)
|
||||||
|
case "search":
|
||||||
|
handleSearch(searchCmd)
|
||||||
|
case "rebuild":
|
||||||
|
handleRebuild(aurRebuildCmd)
|
||||||
|
case "clean-aur":
|
||||||
|
handleCleanAur(aurCleanCmd)
|
||||||
|
default:
|
||||||
|
fmt.Printf("Unknown subcommand: %s\n", os.Args[1])
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleUpdate(cmd *flag.FlagSet) {
|
||||||
|
everythingFlag := cmd.Bool("everything", false, "Update all packages on the system")
|
||||||
|
snapFlag := cmd.Bool("snap", false, "Update all Snap packages")
|
||||||
|
aurFlag := cmd.Bool("aur", false, "Update all AUR packages")
|
||||||
|
archFlag := cmd.Bool("arch", false, "Update all Arch packages")
|
||||||
|
flatsFlag := cmd.Bool("flats", false, "Update all Flatpak packages")
|
||||||
|
cmd.Parse(os.Args[2:])
|
||||||
|
|
||||||
|
if *everythingFlag {
|
||||||
|
// Call function to update all packages
|
||||||
|
packagemanager.UpdateAllPackages()
|
||||||
|
} else if *snapFlag {
|
||||||
|
// Call function to update Snap packages
|
||||||
|
packagemanager.UpdateSnapPackages()
|
||||||
|
} else if *aurFlag {
|
||||||
|
// Call function to update AUR packages
|
||||||
|
packagemanager.UpdateAURPackages()
|
||||||
|
} else if *archFlag {
|
||||||
|
// Call function to update Arch packages
|
||||||
|
packagemanager.UpdatePacmanPackages()
|
||||||
|
} else if *flatsFlag {
|
||||||
|
// Call function to update Flatpak packages
|
||||||
|
packagemanager.UpdateFlatpakPackages()
|
||||||
|
} else {
|
||||||
|
fmt.Println("No update option specified or unrecognized option")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleInstall(cmd *flag.FlagSet) {
|
||||||
|
// Parse and handle the install command
|
||||||
|
// Use functions from install to install packages
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleUninstall(cmd *flag.FlagSet) {
|
||||||
|
// Parse and handle the uninstall command
|
||||||
|
// Use functions from packagemanager to uninstall packages
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleSearch(cmd *flag.FlagSet) {
|
||||||
|
// Parse and handle the search command
|
||||||
|
// Use functions from search to search for packages
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleRebuild(cmd *flag.FlagSet) {
|
||||||
|
// Parse and handle the search command
|
||||||
|
// Use functions from search to search for packages
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleCleanAur(cmd *flag.FlagSet) {
|
||||||
|
// Parse and handle the search command
|
||||||
|
// Use functions from search to search for packages
|
||||||
|
}
|
||||||
|
|
46
pkg/packagemanager/all_updater.go
Normal file
46
pkg/packagemanager/all_updater.go
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
package packagemanager
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
// UpdateAllPackages updates all packages on the system
|
||||||
|
func UpdateAllPackages() error {
|
||||||
|
pkgList, err := readPackageList()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error reading package list: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
for pkgName, pkgInfo := range pkgList {
|
||||||
|
wg.Add(1)
|
||||||
|
go func(name string, info PackageInfo) {
|
||||||
|
defer wg.Done()
|
||||||
|
if err := checkAndUpdatePackage(name, info); err != nil {
|
||||||
|
fmt.Printf("Error updating package %s: %v\n", name, err)
|
||||||
|
}
|
||||||
|
}(pkgName, pkgInfo)
|
||||||
|
}
|
||||||
|
|
||||||
|
wg.Wait()
|
||||||
|
fmt.Println("All packages have been updated.")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// checkAndUpdatePackage checks if an update is available for the package and updates it
|
||||||
|
func checkAndUpdatePackage(name string, info PackageInfo) error {
|
||||||
|
// Implement logic to check for the latest version and update
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// functions to get the latest version for each package manager
|
||||||
|
func getLatestPacmanVersion(packageName string) (string, error) {
|
||||||
|
// Use SearchPacman to get the latest version
|
||||||
|
// Parse the output to extract the version
|
||||||
|
// Return the version
|
||||||
|
// ...
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Similar implementations for getLatestAURVersion, getLatestSnapVersion, getLatestFlatpakVersion
|
46
pkg/packagemanager/aur.go
Normal file
46
pkg/packagemanager/aur.go
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
package packagemanager
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os/exec"
|
||||||
|
)
|
||||||
|
|
||||||
|
// AURPackageInfo represents the package information from the AUR
|
||||||
|
type AURPackageInfo struct {
|
||||||
|
Version string `json:"Version"`
|
||||||
|
// Add other relevant fields
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateAURPackages updates specified AUR packages or all if no specific package is provided
|
||||||
|
func UpdateAURPackages(packageNames ...string) error {
|
||||||
|
pkgList, err := ReadPackageList()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error reading package list: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, packageName := range packageNames {
|
||||||
|
aurInfo, err := fetchAURPackageInfo(packageName)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error fetching AUR package info for %s: %v", packageName, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
installedInfo, ok := pkgList[packageName]
|
||||||
|
if !ok || installedInfo.Version != aurInfo.Version {
|
||||||
|
_, err := CloneAndInstallFromAUR("https://aur.archlinux.org/" + packageName + ".git", true)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error updating AUR package %s: %v", packageName, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UninstallAURPackage uninstalls a specified AUR package
|
||||||
|
func UninstallAURPackage(packageName string) error {
|
||||||
|
// Uninstalling an AUR package is typically done with pacman
|
||||||
|
cmd := exec.Command("sudo", "pacman", "-Rns", "--noconfirm", packageName)
|
||||||
|
if output, err := cmd.CombinedOutput(); err != nil {
|
||||||
|
return fmt.Errorf("error uninstalling AUR package: %s, %v", output, err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -5,6 +5,7 @@ package packagemanager
|
||||||
import (
|
import (
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
// 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
|
||||||
|
@ -31,3 +32,24 @@ func UninstallFlatpakPackage(packageName string) error {
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetVersionFromFlatpak gets the installed version of a Flatpak package
|
||||||
|
func GetVersionFromFlatpak(applicationID string) (string, error) {
|
||||||
|
cmd := exec.Command("flatpak", "info", applicationID)
|
||||||
|
output, err := cmd.CombinedOutput()
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("error getting flatpak package info: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
lines := strings.Split(string(output), "\n")
|
||||||
|
for _, line := range lines {
|
||||||
|
if strings.HasPrefix(line, "Version:") {
|
||||||
|
parts := strings.Fields(line)
|
||||||
|
if len(parts) >= 2 {
|
||||||
|
return parts[1], nil
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "", fmt.Errorf("version not found for flatpak package: %s", applicationID)
|
||||||
|
}
|
||||||
|
|
|
@ -1,132 +1,86 @@
|
||||||
package install
|
package packagemanager
|
||||||
|
|
||||||
// This package is responsible for handling our actual install logic. We could have probably gotten away with
|
// This package is responsible for handling our actual install logic. We could have probably gotten away with
|
||||||
// implementing this into the packagemanager package, but this seems like a better way
|
// implementing this into the packagemanager package, but this seems like a better way
|
||||||
// because this provides a single interface for all our install functions
|
// because this provides a single interface for all our install functions
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"os/user"
|
"os/user"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"fmt"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// PackageList represents the mapping of installed packages to their sources
|
// InstallPackagePacman installs a package using Pacman and logs the installation
|
||||||
type PackageList map[string]string
|
|
||||||
|
|
||||||
const pkgListFilename = "pkg.list"
|
|
||||||
|
|
||||||
// getPkgListPath returns the file path for the package list
|
|
||||||
func getPkgListPath() (string, error) {
|
|
||||||
usr, err := user.Current()
|
|
||||||
if err != nil {
|
|
||||||
return "", fmt.Errorf("error getting current user: %v", err)
|
|
||||||
}
|
|
||||||
return filepath.Join(usr.HomeDir, ".allpac", pkgListFilename), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// readPackageList reads the package list from the file
|
|
||||||
func readPackageList() (PackageList, error) {
|
|
||||||
pkgListPath, err := getPkgListPath()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
file, err := os.Open(pkgListPath)
|
|
||||||
if err != nil {
|
|
||||||
if os.IsNotExist(err) {
|
|
||||||
return PackageList{}, nil // Return an empty list if file doesn't exist
|
|
||||||
}
|
|
||||||
return nil, fmt.Errorf("error opening package list file: %v", err)
|
|
||||||
}
|
|
||||||
defer file.Close()
|
|
||||||
|
|
||||||
var pkgList PackageList
|
|
||||||
err = json.NewDecoder(file).Decode(&pkgList)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("error decoding package list: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return pkgList, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// writePackageList writes the package list to the file
|
|
||||||
func writePackageList(pkgList PackageList) error {
|
|
||||||
pkgListPath, err := getPkgListPath()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
file, err := os.Create(pkgListPath)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("error creating package list file: %v", err)
|
|
||||||
}
|
|
||||||
defer file.Close()
|
|
||||||
|
|
||||||
err = json.NewEncoder(file).Encode(pkgList)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("error encoding package list: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// logInstallation logs the package installation details
|
|
||||||
func LogInstallation(packageName, source string) error {
|
|
||||||
pkgList, err := readPackageList()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
pkgList[packageName] = source
|
|
||||||
|
|
||||||
return writePackageList(pkgList)
|
|
||||||
}
|
|
||||||
|
|
||||||
// InstallPackagePacman installs a package using Pacman
|
|
||||||
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 {
|
||||||
return fmt.Errorf("error installing package with Pacman: %s, %v", output, err)
|
return fmt.Errorf("error installing package with Pacman: %s, %v", output, err)
|
||||||
}
|
}
|
||||||
if err := LogInstallation(packageName, "pacman"); err != nil {
|
|
||||||
|
version, err := GetVersionFromPacman(packageName)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := LogInstallation(packageName, "pacman", version); err != nil {
|
||||||
return fmt.Errorf("error logging installation: %v", err)
|
return fmt.Errorf("error logging installation: %v", err)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// InstallPackageSnap installs a package using Snap
|
// InstallPackageSnap installs a package using Snap and logs the installation
|
||||||
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 {
|
||||||
return fmt.Errorf("error installing package with Snap: %s, %v", output, err)
|
return fmt.Errorf("error installing package with Snap: %s, %v", output, err)
|
||||||
}
|
}
|
||||||
if err := LogInstallation(packageName, "snap"); err != nil {
|
|
||||||
|
version, err := GetVersionFromSnap(packageName)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := LogInstallation(packageName, "snap", version); err != nil {
|
||||||
return fmt.Errorf("error logging installation: %v", err)
|
return fmt.Errorf("error logging installation: %v", err)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// InstallPackageFlatpak installs a package using Flatpak
|
// InstallPackageFlatpak installs a package using Flatpak and logs the installation
|
||||||
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 {
|
||||||
return fmt.Errorf("error installing package with Flatpak: %s, %v", output, err)
|
return fmt.Errorf("error installing package with Flatpak: %s, %v", output, err)
|
||||||
}
|
}
|
||||||
if err := LogInstallation(packageName, "flatpak"); err != nil {
|
|
||||||
|
version, err := GetVersionFromFlatpak(packageName)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := LogInstallation(packageName, "flatpak", version); err != nil {
|
||||||
return fmt.Errorf("error logging installation: %v", err)
|
return fmt.Errorf("error logging installation: %v", err)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// cloneAndInstallFromAUR clones the given AUR repository and installs it
|
// cloneAndInstallFromAUR clones the given AUR repository and installs it
|
||||||
func CloneAndInstallFromAUR(repoURL string) error {
|
func CloneAndInstallFromAUR(repoURL string, skipConfirmation bool) (string, error) {
|
||||||
|
// Request root permissions
|
||||||
|
if !skipConfirmation && !requestRootPermissions() {
|
||||||
|
return "", fmt.Errorf("root permissions denied")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Confirm before proceeding with each step
|
||||||
|
if !skipConfirmation && !confirmAction("Do you want to download and build package from " + repoURL + "?") {
|
||||||
|
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 {
|
||||||
return fmt.Errorf("error getting current user: %v", err)
|
return "", fmt.Errorf("error getting current user: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Define the base directory for AllPac cache
|
// Define the base directory for AllPac cache
|
||||||
|
@ -134,13 +88,13 @@ func CloneAndInstallFromAUR(repoURL string) error {
|
||||||
|
|
||||||
// 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 {
|
||||||
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 {
|
||||||
return fmt.Errorf("error cloning AUR repo: %s, %v", output, err)
|
return "", fmt.Errorf("error cloning AUR repo: %s, %v", output, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Determine the name of the created directory (and the package name)
|
// Determine the name of the created directory (and the package name)
|
||||||
|
@ -149,29 +103,41 @@ func CloneAndInstallFromAUR(repoURL string) error {
|
||||||
|
|
||||||
// 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 {
|
||||||
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 {
|
||||||
return fmt.Errorf("error building package with makepkg: %s, %v", output, err)
|
return "", fmt.Errorf("error building package with makepkg: %s, %v", output, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Log the installation
|
// Extract the version from PKGBUILD
|
||||||
if err := LogInstallation(repoName, "aur"); err != nil {
|
version, err := ExtractVersionFromPKGBUILD(repoDir)
|
||||||
return fmt.Errorf("error logging installation: %v", err)
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("error extracting version from PKGBUILD: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
// Confirm before installing
|
||||||
|
if !skipConfirmation && !confirmAction("Do you want to install the built package " + repoName + "?") {
|
||||||
|
return "", fmt.Errorf("user aborted the installation")
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := LogInstallation(repoName, "aur", version); err != nil {
|
||||||
|
return "", fmt.Errorf("error logging installation: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return version, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// InstallSnap installs Snap manually from the AUR
|
// InstallSnap installs Snap manually from the AUR
|
||||||
func InstallSnap() error {
|
func InstallSnap() error {
|
||||||
if err := CloneAndInstallFromAUR("https://aur.archlinux.org/snapd.git"); err != nil {
|
version, err := CloneAndInstallFromAUR("https://aur.archlinux.org/snapd.git", true)
|
||||||
|
if err != nil {
|
||||||
return fmt.Errorf("error installing Snap: %v", err)
|
return fmt.Errorf("error installing Snap: %v", err)
|
||||||
}
|
}
|
||||||
if err := LogInstallation("snapd", "aur"); err != nil {
|
|
||||||
|
if err := LogInstallation("snapd", "aur", version); err != nil {
|
||||||
return fmt.Errorf("error logging installation: %v", err)
|
return fmt.Errorf("error logging installation: %v", err)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
140
pkg/packagemanager/installer_utils.go
Normal file
140
pkg/packagemanager/installer_utils.go
Normal file
|
@ -0,0 +1,140 @@
|
||||||
|
package packagemanager
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"os"
|
||||||
|
"os/user"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
"fmt"
|
||||||
|
"encoding/json"
|
||||||
|
)
|
||||||
|
|
||||||
|
// extractVersionFromPKGBUILD reads the PKGBUILD file and extracts the package version
|
||||||
|
func ExtractVersionFromPKGBUILD(repoDir string) (string, error) {
|
||||||
|
pkgbuildPath := filepath.Join(repoDir, "PKGBUILD")
|
||||||
|
file, err := os.Open(pkgbuildPath)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
scanner := bufio.NewScanner(file)
|
||||||
|
for scanner.Scan() {
|
||||||
|
line := scanner.Text()
|
||||||
|
if strings.HasPrefix(line, "pkgver=") {
|
||||||
|
return strings.TrimPrefix(line, "pkgver="), nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := scanner.Err(); err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return "", fmt.Errorf("pkgver not found in PKGBUILD")
|
||||||
|
}
|
||||||
|
|
||||||
|
type PackageInfo struct {
|
||||||
|
Source string `json:"source"`
|
||||||
|
Version string `json:"version"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type PackageList map[string]PackageInfo
|
||||||
|
|
||||||
|
const pkgListFilename = "pkg.list"
|
||||||
|
|
||||||
|
// getPkgListPath returns the file path for the package list
|
||||||
|
func GetPkgListPath() (string, error) {
|
||||||
|
usr, err := user.Current()
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("error getting current user: %v", err)
|
||||||
|
}
|
||||||
|
return filepath.Join(usr.HomeDir, ".allpac", pkgListFilename), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// readPackageList reads the package list from the file
|
||||||
|
func ReadPackageList() (PackageList, error) {
|
||||||
|
pkgListPath, err := GetPkgListPath()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
file, err := os.Open(pkgListPath)
|
||||||
|
if err != nil {
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
return PackageList{}, nil // Return an empty list if file doesn't exist
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("error opening package list file: %v", err)
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
var pkgList PackageList
|
||||||
|
err = json.NewDecoder(file).Decode(&pkgList)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("error decoding package list: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return pkgList, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// writePackageList writes the package list to the file
|
||||||
|
func writePackageList(pkgList PackageList) error {
|
||||||
|
pkgListPath, err := GetPkgListPath()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
file, err := os.Create(pkgListPath)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error creating package list file: %v", err)
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
err = json.NewEncoder(file).Encode(pkgList)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error encoding package list: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// logInstallation logs the package installation details
|
||||||
|
func LogInstallation(packageName, source, version string) error {
|
||||||
|
pkgList, err := readPackageList()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
pkgList[packageName] = PackageInfo{
|
||||||
|
Source: source,
|
||||||
|
Version: version,
|
||||||
|
}
|
||||||
|
|
||||||
|
return writePackageList(pkgList)
|
||||||
|
}
|
||||||
|
|
||||||
|
// requestRootPermissions prompts the user for root permissions
|
||||||
|
func requestRootPermissions() bool {
|
||||||
|
fmt.Println("Root permissions are required to install AUR packages.")
|
||||||
|
return confirmAction("Do you want to continue with root permissions?")
|
||||||
|
}
|
||||||
|
|
||||||
|
// confirmAction prompts the user with a yes/no question and returns true if the answer is yes
|
||||||
|
func confirmAction(question string) bool {
|
||||||
|
reader := bufio.NewReader(os.Stdin)
|
||||||
|
for {
|
||||||
|
fmt.Printf("%s [Y/n]: ", question)
|
||||||
|
response, err := reader.ReadString('\n')
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Error reading response:", err)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
response = strings.ToLower(strings.TrimSpace(response))
|
||||||
|
|
||||||
|
if response == "y" || response == "yes" {
|
||||||
|
return true
|
||||||
|
} else if response == "n" || response == "no" {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,6 +5,7 @@ package packagemanager
|
||||||
import (
|
import (
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
// 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
|
||||||
|
@ -31,3 +32,19 @@ func UninstallPacmanPackage(packageName string) error {
|
||||||
}
|
}
|
||||||
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)
|
||||||
|
}
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
package search
|
package packagemanager
|
||||||
|
|
||||||
// This package is responsible for searching various sources for the availability of the requested package
|
// This package is responsible for searching various sources for the availability of the requested package
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"pixelridgesoftworks.com/AllPac/pkg/packagemanager"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
@ -14,9 +13,6 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
// PackageList represents the mapping of installed packages to their sources
|
|
||||||
type PackageList map[string]string
|
|
||||||
|
|
||||||
// UninstallPackages uninstalls the provided packages
|
// UninstallPackages uninstalls the provided packages
|
||||||
func UninstallPackages(packageNames []string) error {
|
func UninstallPackages(packageNames []string) error {
|
||||||
pkgList, err := readPackageList()
|
pkgList, err := readPackageList()
|
||||||
|
@ -33,11 +29,11 @@ func UninstallPackages(packageNames []string) error {
|
||||||
|
|
||||||
switch source {
|
switch source {
|
||||||
case "pacman":
|
case "pacman":
|
||||||
err = packagemanager.UninstallPacmanPackage(packageName)
|
err = UninstallPacmanPackage(packageName)
|
||||||
case "snap":
|
case "snap":
|
||||||
err = packagemanager.UninstallSnapPackage(packageName)
|
err = UninstallSnapPackage(packageName)
|
||||||
case "flatpak":
|
case "flatpak":
|
||||||
err = packagemanager.UninstallFlatpakPackage(packageName)
|
err = UninstallFlatpakPackage(packageName)
|
||||||
// Add cases for other package managers if necessary
|
// Add cases for other package managers if necessary
|
||||||
default:
|
default:
|
||||||
fmt.Printf("Unknown source for package %s\n", packageName)
|
fmt.Printf("Unknown source for package %s\n", packageName)
|
||||||
|
@ -166,3 +162,52 @@ func parsePacmanOutput(output string) []string {
|
||||||
|
|
||||||
return packages
|
return packages
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetPacmanPackageVersion returns the version of a package in the Pacman repositories
|
||||||
|
func GetPacmanPackageVersion(packageName string) (string, error) {
|
||||||
|
searchResults, err := SearchPacman(packageName)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, result := range searchResults {
|
||||||
|
if strings.Contains(result, packageName) {
|
||||||
|
return extractVersionFromPacmanResult(result), nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return "", fmt.Errorf("package %s not found in Pacman", packageName)
|
||||||
|
}
|
||||||
|
|
||||||
|
// extractVersionFromPacmanResult extracts the version from a Pacman search result string
|
||||||
|
func extractVersionFromPacmanResult(result string) string {
|
||||||
|
// Assuming the result is in the format "packageName version description"
|
||||||
|
parts := strings.Fields(result)
|
||||||
|
if len(parts) >= 2 {
|
||||||
|
return parts[1] // The second element should be the version
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// fetchAURPackageInfo fetches package information from the AUR
|
||||||
|
func fetchAURPackageInfo(packageName string) (*AURPackageInfo, error) {
|
||||||
|
url := fmt.Sprintf("https://aur.archlinux.org/rpc/?v=5&type=info&arg[]=%s", packageName)
|
||||||
|
resp, err := http.Get(url)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
var result struct {
|
||||||
|
Results []AURPackageInfo `json:"results"`
|
||||||
|
}
|
||||||
|
if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(result.Results) == 0 {
|
||||||
|
return nil, fmt.Errorf("package %s not found in AUR", packageName)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &result.Results[0], nil
|
||||||
|
}
|
|
@ -5,6 +5,7 @@ package packagemanager
|
||||||
import (
|
import (
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
// 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
|
||||||
|
@ -31,3 +32,24 @@ func UninstallSnapPackage(packageName string) error {
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetVersionFromSnap gets the installed version of a Snap package
|
||||||
|
func GetVersionFromSnap(packageName string) (string, error) {
|
||||||
|
cmd := exec.Command("snap", "info", packageName)
|
||||||
|
output, err := cmd.CombinedOutput()
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("error getting snap package info: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
lines := strings.Split(string(output), "\n")
|
||||||
|
for _, line := range lines {
|
||||||
|
if strings.HasPrefix(line, "installed:") {
|
||||||
|
parts := strings.Fields(line)
|
||||||
|
if len(parts) >= 2 {
|
||||||
|
return parts[1], nil
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "", fmt.Errorf("version not found for snap package: %s", packageName)
|
||||||
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ package toolcheck
|
||||||
import (
|
import (
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"fmt"
|
"fmt"
|
||||||
"pixelridgesoftworks.com/AllPac/pkg/install"
|
"pixelridgesoftworks.com/AllPac/pkg/packagemanager"
|
||||||
)
|
)
|
||||||
|
|
||||||
// isCommandAvailable checks if a command exists
|
// isCommandAvailable checks if a command exists
|
||||||
|
@ -33,7 +33,7 @@ func EnsurePacman() error {
|
||||||
// EnsureSnap ensures that Snap is installed and available
|
// EnsureSnap ensures that Snap is installed and available
|
||||||
func EnsureSnap() error {
|
func EnsureSnap() error {
|
||||||
if !isCommandAvailable("snap") {
|
if !isCommandAvailable("snap") {
|
||||||
return install.InstallSnap()
|
return packagemanager.InstallSnap()
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -41,7 +41,7 @@ func EnsureSnap() error {
|
||||||
// EnsureGit ensures that Git is installed and available
|
// EnsureGit ensures that Git is installed and available
|
||||||
func EnsureGit() error {
|
func EnsureGit() error {
|
||||||
if !isCommandAvailable("git") {
|
if !isCommandAvailable("git") {
|
||||||
return install.InstallGit()
|
return packagemanager.InstallGit()
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -49,7 +49,7 @@ func EnsureGit() error {
|
||||||
// EnsureBaseDevel ensures that the base-devel group is installed
|
// EnsureBaseDevel ensures that the base-devel group is installed
|
||||||
func EnsureBaseDevel() error {
|
func EnsureBaseDevel() error {
|
||||||
if !isCommandAvailable("make") { // 'make' is part of base-devel, this is the best method to check
|
if !isCommandAvailable("make") { // 'make' is part of base-devel, this is the best method to check
|
||||||
return install.InstallBaseDevel()
|
return packagemanager.InstallBaseDevel()
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -57,7 +57,7 @@ func EnsureBaseDevel() error {
|
||||||
// EnsureFlatpak ensures that Flatpak is installed and available
|
// EnsureFlatpak ensures that Flatpak is installed and available
|
||||||
func EnsureFlatpak() error {
|
func EnsureFlatpak() error {
|
||||||
if !isCommandAvailable("flatpak") {
|
if !isCommandAvailable("flatpak") {
|
||||||
return install.InstallFlatpak()
|
return packagemanager.InstallFlatpak()
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user