diff --git a/bigdl b/bigdl new file mode 100644 index 0000000..b354a9b Binary files /dev/null and b/bigdl differ diff --git a/fsearch.go b/fsearch.go index c9591d1..e477322 100644 --- a/fsearch.go +++ b/fsearch.go @@ -7,7 +7,6 @@ import ( "fmt" "io/ioutil" "net/http" - "os" "path/filepath" "strings" ) @@ -79,17 +78,12 @@ func fSearch(searchTerm string) { name := parts[0] description := parts[1] - // Use INSTALL_DIR or fallback to $HOME/.local/bin - installDir := os.Getenv("INSTALL_DIR") - if installDir == "" { - installDir = filepath.Join(os.Getenv("HOME"), ".local", "bin") - } - installDirLocation := filepath.Join(installDir, name) + installPath := filepath.Join(InstallDir, name) cachedLocation, _ := ReturnCachedFile(name) var prefix string - if fileExists(installDirLocation) { + if fileExists(installPath) { prefix = "[i]" } else if cachedLocation != "" && isExecutable(cachedLocation) { prefix = "[c]" diff --git a/helperFunctions.go b/helperFunctions.go index 3a58382..380210b 100644 --- a/helperFunctions.go +++ b/helperFunctions.go @@ -98,6 +98,15 @@ func fetchBinaryFromURL(url, destination string) error { if useProgressBar { bar = progressbar.NewOptions(int(resp.ContentLength), progressbar.OptionClearOnFinish(), + progressbar.OptionFullWidth(), + progressbar.OptionShowBytes(true), + progressbar.OptionSetTheme(progressbar.Theme{ + Saucer: "=", + SaucerHead: ">", + SaucerPadding: " ", + BarStart: "[", + BarEnd: "]", + }), ) } else { bar = progressbar.NewOptions(-1, @@ -277,13 +286,13 @@ func truncateSprintf(format string, a ...interface{}) string { formatted := fmt.Sprintf(format, a...) // Determine the truncation length & truncate the formatted string if it exceeds the available space - availableSpace := getTerminalWidth() - 4 + availableSpace := getTerminalWidth() - len(indicator) if len(formatted) > availableSpace { formatted = fmt.Sprintf("%s", formatted[:availableSpace]) for strings.HasSuffix(formatted, ",") || strings.HasSuffix(formatted, ".") || strings.HasSuffix(formatted, " ") { formatted = formatted[:len(formatted)-1] } - formatted = fmt.Sprintf("%s...>", formatted) // Add the dots. + formatted = fmt.Sprintf("%s%s", formatted, indicator) // Add the dots. } return formatted diff --git a/install.go b/install.go index 65486c4..6efc478 100644 --- a/install.go +++ b/install.go @@ -3,29 +3,11 @@ package main import ( "fmt" - "os" "path/filepath" ) -func installCommand(binaryName string, args []string, messages ...string) error { - installDir := os.Getenv("INSTALL_DIR") - if len(args) > 0 && args[0] != "" { - installDir = args[0] - } - - if installDir == "" { - homeDir, err := os.UserHomeDir() - if err != nil { - return fmt.Errorf("Error: Failed to get user's Home directory: %w", err) - } - installDir = filepath.Join(homeDir, ".local", "bin") - } - - if err := os.MkdirAll(installDir, os.ModePerm); err != nil { - return fmt.Errorf("Error: Could not create installation directory: %v", err) - } - - installPath := filepath.Join(installDir, binaryName) +func installCommand(binaryName string, messages ...string) error { + installPath := filepath.Join(InstallDir, binaryName) // Use ReturnCachedFile to check for a cached file if installUseCache { diff --git a/main.go b/main.go index b24afe8..542e175 100644 --- a/main.go +++ b/main.go @@ -4,40 +4,45 @@ package main import ( "fmt" "os" + "path/filepath" "runtime" ) -// Repositories contains the URLs for fetching metadata. var Repositories []string - -// MetadataURLs contains the URLs for fetching metadata. var MetadataURLs []string - -// Array for storing a variable that fsearch and info use. var validatedArch = [3]string{} +var InstallDir = os.Getenv("INSTALL_DIR") func init() { + if InstallDir == "" { + homeDir, err := os.UserHomeDir() + if err != nil { + fmt.Fprintf(os.Stderr, "Error: Failed to get user's Home directory. %v\n", err) + os.Exit(1) + } + InstallDir = filepath.Join(homeDir, ".local", "bin") + } + if err := os.MkdirAll(InstallDir, os.ModePerm); err != nil { + fmt.Fprintf(os.Stderr, "Error: Failed to get user's Home directory. %v\n", err) + os.Exit(1) + } switch runtime.GOARCH { case "amd64": - Repositories = append(Repositories, "https://bin.ajam.dev/x86_64_Linux/") - Repositories = append(Repositories, "https://raw.githubusercontent.com/xplshn/Handyscripts/master/") - Repositories = append(Repositories, "https://bin.ajam.dev/x86_64_Linux/Baseutils/") - MetadataURLs = append(MetadataURLs, "https://bin.ajam.dev/x86_64_Linux/METADATA.json") - MetadataURLs = append(MetadataURLs, "https://bin.ajam.dev/x86_64_Linux/Baseutils/METADATA.json") - MetadataURLs = append(MetadataURLs, "https://api.github.com/repos/xplshn/Handyscripts/contents") validatedArch = [3]string{"x86_64_Linux", "x86_64", "x86_64-Linux"} case "arm64": - Repositories = append(Repositories, "https://bin.ajam.dev/aarch64_arm64_Linux/") - Repositories = append(Repositories, "https://raw.githubusercontent.com/xplshn/Handyscripts/master/") - Repositories = append(Repositories, "https://bin.ajam.dev/aarch64_arm64_Linux/Baseutils/") - MetadataURLs = append(MetadataURLs, "https://bin.ajam.dev/aarch64_arm64_Linux/METADATA.json") - MetadataURLs = append(MetadataURLs, "https://bin.ajam.dev/aarch64_arm64_Linux/Baseutils/METADATA.json") - MetadataURLs = append(MetadataURLs, "https://api.github.com/repos/xplshn/Handyscripts/contents") validatedArch = [3]string{"aarch64_arm64_Linux", "aarch64_arm64", "aarch64-Linux"} default: fmt.Println("Unsupported architecture:", runtime.GOARCH) os.Exit(1) } + arch := validatedArch[0] + Repositories = append(Repositories, "https://bin.ajam.dev/"+arch+"/") + Repositories = append(Repositories, "https://bin.ajam.dev/"+arch+"/Baseutils/") + Repositories = append(Repositories, "https://raw.githubusercontent.com/xplshn/Handyscripts/master/") + // These are used for listing and fetching info about the binaries themselves + MetadataURLs = append(MetadataURLs, "https://bin.ajam.dev/"+arch+"/METADATA.json") + MetadataURLs = append(MetadataURLs, "https://bin.ajam.dev/"+arch+"/Baseutils/METADATA.json") + MetadataURLs = append(MetadataURLs, "https://api.github.com/repos/xplshn/Handyscripts/contents") } var installUseCache = true @@ -46,18 +51,21 @@ var useProgressBar = true const RMetadataURL = "https://raw.githubusercontent.com/Azathothas/Toolpacks/main/metadata.json" const RNMetadataURL = "https://bin.ajam.dev/METADATA.json" const VERSION = "1.3" +const usagePage = "Usage: bigdl [-vh] {list|install|remove|update|run|info|search|tldr} [args...]" ///// YOU MAY CHANGE THESE TO POINT TO ANOTHER PLACE. const ( + // Truncation indicator + indicator = "...>" // Cache size limit & handling. MaxCacheSize = 10 BinariesToDelete = 5 - TEMP_DIR = "/tmp/bigdl_cached" + TEMP_DIR = "/tmp/bigdl_cached" ) func printHelp() { - fmt.Println("Usage: bigdl [-vh] {list|install|remove|update|run|info|search|tldr} [args...]") + fmt.Printf("%s\n", usagePage) fmt.Println("\nOptions:") fmt.Println(" -h, --help Show this help message") fmt.Println(" -v, --version Show the version number") @@ -97,7 +105,7 @@ func main() { // If no arguments are received, show the usage text if len(os.Args) < 2 { - fmt.Println("Usage: bigdl [-vh] {list|install|remove|update|run|info|search|tldr} [args...]") + fmt.Printf("%s\n", usagePage) os.Exit(1) } @@ -123,24 +131,24 @@ func main() { os.Exit(1) } binaryName := os.Args[2] - var installDir, installMessage string + var installMessage string if len(os.Args) > 3 { - installDir = os.Args[3] + InstallDir = os.Args[3] } if len(os.Args) > 4 { installMessage = os.Args[4] } - err := installCommand(binaryName, []string{installDir}, installMessage) + err := installCommand(binaryName, installMessage) if err != nil { fmt.Printf("%s\n", err.Error()) os.Exit(1) } case "remove", "del": - if len(os.Args) != 3 { + if len(os.Args) < 3 { fmt.Printf("Usage: bigdl %s \n", os.Args[1]) os.Exit(1) } - remove(os.Args[2]) + remove(os.Args[2:]) case "run": if len(os.Args) < 3 { fmt.Println("Usage: bigdl run [--verbose, --silent] [args...]") diff --git a/remove.go b/remove.go index 15c9598..c5bb04e 100644 --- a/remove.go +++ b/remove.go @@ -7,29 +7,18 @@ import ( "path/filepath" ) -func remove(binaryToRemove string) { - removeFromDir := func(dirPath string) { - binaryPath := filepath.Join(dirPath, binaryToRemove) - err := os.Remove(binaryPath) +func remove(binariesToRemove []string) { + for _, binaryName := range binariesToRemove { + installPath := filepath.Join(InstallDir, binaryName) + err := os.Remove(installPath) if err != nil { - fmt.Printf("Binary %s not found in %s\n", binaryToRemove, dirPath) - return + if os.IsNotExist(err) { + fmt.Fprintf(os.Stderr, "Warning: Binary %s does not exist in %s\n", binaryName, InstallDir) + } else { + fmt.Fprintf(os.Stderr, "Error: Failed to remove binary %s from %s. %v\n", binaryName, InstallDir, err) + } + continue } - fmt.Printf("Binary %s removed from %s\n", binaryToRemove, dirPath) - } - - // Check if INSTALL_DIR environment variable is set - if installDir := os.Getenv("INSTALL_DIR"); installDir != "" { - removeFromDir(installDir) - return - } - - // If INSTALL_DIR is not set, check %HOME/.local/bin - if homeDir, err := os.UserHomeDir(); err == nil { - localBinDir := filepath.Join(homeDir, ".local", "bin") - removeFromDir(localBinDir) - } else { - fmt.Println("Error getting user home directory:", err) - os.Exit(1) + fmt.Printf("Binary %s removed from %s\n", binaryName, InstallDir) } } diff --git a/update.go b/update.go index 296b064..49f2e34 100644 --- a/update.go +++ b/update.go @@ -18,16 +18,6 @@ func update(programsToUpdate []string) error { var skipped, updated, toBeChecked uint32 var checked uint32 = 1 - // Define installDir at the beginning of the function - installDir := os.Getenv("INSTALL_DIR") - if installDir == "" { - homeDir, err := os.UserHomeDir() - if err != nil { - return fmt.Errorf("failed to get user home directory: %w", err) - } - installDir = filepath.Join(homeDir, ".local", "bin") - } - // Fetch the list of binaries from the remote source once remotePrograms, err := listBinaries() if err != nil { @@ -36,14 +26,14 @@ func update(programsToUpdate []string) error { // If programsToUpdate is nil, list files from InstallDir and validate against remote if programsToUpdate == nil { - info, err := os.Stat(installDir) + info, err := os.Stat(InstallDir) if err != nil || !info.IsDir() { - return fmt.Errorf("installation directory %s is not a directory", installDir) + return fmt.Errorf("installation directory %s is not a directory", InstallDir) } - files, err := os.ReadDir(installDir) + files, err := os.ReadDir(InstallDir) if err != nil { - return fmt.Errorf("failed to read directory %s: %w", installDir, err) + return fmt.Errorf("failed to read directory %s: %w", InstallDir, err) } programsToUpdate = make([]string, 0) @@ -71,8 +61,8 @@ func update(programsToUpdate []string) error { // Launch a goroutine to update the program go func(program string) { defer wg.Done() - localFilePath := filepath.Join(installDir, program) - _, err := os.Stat(localFilePath) + installPath := filepath.Join(InstallDir, program) + _, err := os.Stat(installPath) if os.IsNotExist(err) { progressMutex.Lock() truncatePrintf("\033[2K\rWarning: Tried to update a non-existent program %s. <%d/%d>", program, atomic.LoadUint32(&checked), toBeChecked) @@ -80,7 +70,7 @@ func update(programsToUpdate []string) error { progressMutex.Unlock() return } - localSHA256, err := getLocalSHA256(localFilePath) + localSHA256, err := getLocalSHA256(installPath) if err != nil { atomic.AddUint32(&skipped, 1) progressMutex.Lock() @@ -112,7 +102,7 @@ func update(programsToUpdate []string) error { installMessage := truncateSprintf("\x1b[A\033[KUpdating %s to version %s", program, binaryInfo.SHA256) installUseCache = false //I hate myself, this is DISGUSTING. useProgressBar = false // I hate myself, this is AWFUL. - err := installCommand(program, []string{installDir}, installMessage) + err := installCommand(program, installMessage) if err != nil { progressMutex.Lock() truncatePrintf("\033[2K\rFailed to update %s: %s <%d/%d>", program, err.Error(), atomic.LoadUint32(&checked), toBeChecked)