AllPac/cmd/main.go

323 lines
10 KiB
Go

package main
// This file is our main entrypoint, and build point for AllPac
import (
"fmt"
"os"
"strings"
"pixelridgesoftworks.com/AllPac/pkg/packagemanager"
"pixelridgesoftworks.com/AllPac/pkg/logger"
"pixelridgesoftworks.com/AllPac/pkg/toolcheck"
"path/filepath"
"regexp"
)
func main() {
// Initialize the logger
logFilePath := filepath.Join(os.Getenv("HOME"), ".allpac", "logs", "allpac.log")
if err := logger.Init(logFilePath); err != nil {
logger.Errorf("Failed to initialize logger: %v", err)
}
if len(os.Args) < 2 {
fmt.Println("Expected 'update', 'install', 'uninstall', 'search', 'rebuild', 'clean-aur', or 'toolcheck' subcommands")
os.Exit(1)
}
command := os.Args[1]
args := os.Args[2:]
switch command {
case "update":
handleUpdate(args)
case "install":
handleInstall(args)
case "uninstall":
handleUninstall(args)
case "search":
handleSearch(args)
case "rebuild":
handleRebuild(args)
case "clean-aur":
handleCleanAur(args)
case "toolcheck":
handleToolCheck(args)
case "version":
handleVersion(args)
default:
fmt.Printf("Unknown subcommand: %s\n", command)
os.Exit(1)
}
}
func handleUpdate(args []string) {
if len(args) == 0 {
fmt.Println("You must specify an update option: 'everything', 'snaps', 'aur', 'arch', 'flats', or a specific package name.")
return
}
updateFuncs := map[string]func() error{
"everything": packagemanager.UpdateAllPackages,
"snaps": func() error { return packagemanager.UpdateSnapPackages() },
"aur": func() error { return packagemanager.UpdateAURPackages() },
"arch": func() error { return packagemanager.UpdatePacmanPackages() },
"flats": func() error { return packagemanager.UpdateFlatpakPackages() },
}
updateOption := args[0]
if updateFunc, ok := updateFuncs[updateOption]; ok {
err := updateFunc()
handleUpdateError(updateOption, err)
} else {
err := packagemanager.UpdatePackageByName(updateOption)
handleUpdateError(updateOption, err)
}
}
// handles the install command for packages
func handleInstall(args []string) {
if len(args) == 0 {
fmt.Println("You must specify at least one package name.")
return
}
// Join the args to form a single string, then split by comma
packagesInput := strings.Join(args, " ")
packageNames := strings.Split(packagesInput, ",")
// Trim whitespace from each package name
for i, pkg := range packageNames {
packageNames[i] = strings.TrimSpace(pkg)
}
searchResults, err := packagemanager.SearchAllSources(packageNames)
if err != nil {
fmt.Printf("Error searching for packages: %v\n", err)
return
}
installFuncs := map[string]func(string) error{
"Pacman": packagemanager.InstallPackagePacman,
"Snap": packagemanager.InstallPackageSnap,
"Flatpak": packagemanager.InstallPackageFlatpak,
"AUR": func(pkgName string) error {
_, err := packagemanager.CloneAndInstallFromAUR(fmt.Sprintf("https://aur.archlinux.org/%s.git", pkgName), false)
return err
},
}
for _, result := range searchResults {
fmt.Printf("Searching for package: %s\n", result.PackageName)
exactMatches := filterExactMatches(result.PackageName, result.Results)
if len(exactMatches) == 0 {
fmt.Println("No exact matches found for package.")
continue
}
selectedSource := getSelectedSource(exactMatches)
if selectedSource == "" {
continue
}
// Display the actual package name that will be installed
fmt.Printf("Available package(s) for installation from %s:\n", selectedSource)
for _, match := range exactMatches {
if match.Source == selectedSource {
for _, pkg := range match.Results {
fmt.Println(pkg)
}
}
}
fmt.Printf("Installing %s from %s...\n", result.PackageName, selectedSource)
if installFunc, ok := installFuncs[selectedSource]; ok {
if err := installFunc(result.PackageName); 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)
}
} else {
fmt.Printf("Unknown source for package %s\n", result.PackageName)
}
}
}
func getSelectedSource(exactMatches []packagemanager.SourceResult) string {
if len(exactMatches) == 1 {
return exactMatches[0].Source
}
sourceIndex := promptUserForSource(exactMatches)
if sourceIndex < 0 || sourceIndex >= len(exactMatches) {
fmt.Println("Invalid selection. Skipping package.")
return ""
}
return exactMatches[sourceIndex].Source
}
// filters the search results to include only those with an exact match
func filterExactMatches(packageName string, sourceResults []packagemanager.SourceResult) []packagemanager.SourceResult {
var exactMatches []packagemanager.SourceResult
for _, sourceResult := range sourceResults {
var filteredResults []string
for _, result := range sourceResult.Results {
if isExactMatch(packageName, result) {
filteredResults = append(filteredResults, result)
}
}
if len(filteredResults) > 0 {
exactMatches = append(exactMatches, packagemanager.SourceResult{Source: sourceResult.Source, Results: filteredResults})
}
}
return exactMatches
}
// checks if the given result string is an exact match for the package name
func isExactMatch(packageName, result string) bool {
pattern := fmt.Sprintf("^%s(?:-\\d+|\\-dev)?(?: - [^ ]+)?", regexp.QuoteMeta(packageName))
matched, _ := regexp.MatchString(pattern, result)
return matched
}
// handles the uninstall command for packages
func handleUninstall(args []string) {
if len(args) == 0 {
fmt.Println("You must specify at least one package name.")
return
}
// Join the args to form a single string, then split by comma
packagesInput := strings.Join(args, " ")
packageNames := strings.Split(packagesInput, ",")
// Trim whitespace from each package name
for i, pkg := range packageNames {
packageNames[i] = strings.TrimSpace(pkg)
}
// Call the function to uninstall the packages
err := packagemanager.UninstallPackages(packageNames)
if err != nil {
fmt.Printf("Error uninstalling packages: %v\n", err)
} else {
fmt.Println("Requested packages uninstalled successfully.")
}
}
// handles the search command for packages across different package managers
func handleSearch(args []string) {
if len(args) < 1 {
fmt.Println("You must specify a package name.")
return
}
packageName := args[0]
// Search across all sources
searchResults, err := packagemanager.SearchAllSources([]string{packageName})
if err != nil {
logger.Errorf("Error searching for package %s: %v", packageName, err)
return
}
if len(searchResults) == 0 {
fmt.Println("No results found for package:", packageName)
return
}
// Iterate over the search results and print them
for _, result := range searchResults {
if len(result.Results) == 0 {
fmt.Printf("%s: No results found\n", result.PackageName)
continue
}
for _, sourceResult := range result.Results {
fmt.Printf("%s Results from %s:\n", result.PackageName, sourceResult.Source)
for _, res := range sourceResult.Results {
fmt.Println(res)
}
}
}
}
// handles the rebuild command for an AUR package
func handleRebuild(args []string) {
if len(args) == 0 {
fmt.Println("You must specify the name of an AUR package to rebuild.")
return
}
packageName := args[0]
pkgList, err := packagemanager.ReadPackageList()
if err != nil {
fmt.Printf("Error reading package list: %v\n", err)
return
}
if _, exists := pkgList[packageName]; !exists {
fmt.Printf("Package %s is not managed by AllPac or not installed.\n", packageName)
return
}
cacheDir := filepath.Join(os.Getenv("HOME"), ".allpac", "cache", packageName)
if err := os.RemoveAll(cacheDir); err != nil {
fmt.Printf("Error removing old build directory: %v\n", err)
return
}
err = packagemanager.RebuildAndReinstallAURPackage(packageName)
if err != nil {
fmt.Printf("Error rebuilding package %s: %v\n", packageName, err)
} else {
fmt.Printf("Package %s rebuilt and reinstalled successfully.\n", packageName)
}
}
// handles the cleaning of AUR cache
func handleCleanAur(args []string) {
// Call the function to clear the AUR cache
err := packagemanager.ClearAllPacCache()
if err != nil {
fmt.Printf("Error clearing AllPac cache: %v\n", err)
return
}
fmt.Println("AllPac 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
}
func handleToolCheck(args []string) {
checks := []struct {
Name string
Func func() error
}{
{"Pacman", toolcheck.EnsurePacman},
{"Base-devel", toolcheck.EnsureBaseDevel},
{"Git", toolcheck.EnsureGit},
{"Snap", toolcheck.EnsureSnap},
{"Flatpak", toolcheck.EnsureFlatpak},
}
for _, check := range checks {
if err := check.Func(); err != nil {
fmt.Printf("%s check failed: %v\n", check.Name, err)
} else {
fmt.Printf("%s is installed and available.\n", check.Name)
}
}
}