slp/main.go

222 lines
6.2 KiB
Go

package main
import (
"fmt"
"os"
"path/filepath"
"strings"
"git.rawtext.club/slope-lang/slp/operators"
)
const (
version string = "1.1"
globalText string = " (\033[36mglobal\033[0m)"
globalPath string = "/usr/local/lib/slope/modules/"
banner string = "\033[32;1mslp - slope package manager\033[0m"
helptext string = `
slp deps [[-g]] [file] # install the dependencies of 'file'
slp fetch # fetches the updated registry
slp gen [[-s|--solo]] # creates new module dir/skeleton
slp help # print usage information
slp install [[-g]] [module...] # installs module(s)
slp installed [[-g]] # lists all installed packages
slp list # lists all available packages
slp local [[-g]] [filepath] # installs the module at filepath
slp remove [[-g]] [module...] # removes module(s)
slp search [term...] # searches for modules
slp show [module...] # shows details for module(s)
slp update [[-g]] [module...] # updates module(s)
slp update-all [[-g]] [module...] # updates all installed modules
slp version # print the current slp version
Operations that accept a -g flag will attempt to install a module systemwide (this may require root access). A --global flag may be passed in lieu of a -g flag if desired for clarity.
slp gen will automatically init a git repository in the created folder. The -s/--solo flag will change that behavior to create a solo repository instead.
The install location for global modules is: /usr/local/lib/slope/modules
Globals modules must be dealt with separately from local modules and cannot be combined in a single command.`
)
func main() {
arg := os.Args
if len(arg) <= 1 || arg[1] == "--help" || arg[1] == "-h" || arg[1] == "help" {
printHelp()
return
} else if arg[1] == "version" || arg[1] == "-v" || arg[1] == "--version" {
fmt.Println(version)
return
}
global := false
globalTxt := ""
modules := arg[2:]
if len(arg) > 3 && (arg[2] == "-g" || arg[2] == "--global") {
checkGlobalEnv()
global = true
modules = arg[3:]
globalTxt = globalText
}
MainSwitch:
switch arg[1] {
case "deps":
if len(modules) == 0 {
fmt.Fprint(os.Stderr, "The 'deps' command requires a path to a slope file: `slp deps [file]`\n")
break
}
mods, err := operators.Deps(modules[0])
if err != nil {
fmt.Println(err)
os.Exit(1)
}
modules = mods
arg[1] = "install"
goto MainSwitch
case "fetch":
err := operators.Fetch()
if err != nil {
fmt.Fprintf(os.Stderr, "%s\n", err.Error())
os.Exit(1)
}
case "list":
err := operators.List()
if err != nil {
fmt.Fprintf(os.Stderr, "%s\n", err.Error())
os.Exit(1)
}
case "local":
locals := make([]string, 0, 5)
for _, mod := range modules {
fmt.Printf("installing from local %s%s\n", mod, globalTxt)
err := operators.LocalInstall(mod, global)
if err != nil {
fmt.Fprintf(os.Stderr, " \033[2m└\033[0m \033[31mERROR:\033[0m %s\n\n", err.Error())
continue
}
locals = append(locals, mod)
fmt.Print(" \033[2m└\033[0m \033[32mdone\033[0m\n\n")
}
printStat("\033[1;32m", "LOCALED", locals)
case "installed":
if len(arg) > 2 && (arg[2] == "-g" || arg[2] == "--global") {
global = true
globalTxt = globalText
}
err := operators.ShowInstalled(global, globalTxt)
if err != nil {
fmt.Fprintf(os.Stderr, "%s\n", err.Error())
os.Exit(1)
}
case "gen":
solo := false
if len(arg) > 2 && arg[2] == "-s" || arg[2] == "--solo" {
solo = true
}
err := operators.Generate(solo)
if err != nil {
fmt.Fprintf(os.Stderr, "%s\n", err.Error())
os.Exit(1)
}
case "install":
installs := make([]string, 0, 5)
for _, mod := range modules {
fmt.Printf("installing %s%s\n", mod, globalTxt)
err := operators.Install(mod, global)
if err != nil {
fmt.Fprintf(os.Stderr, " \033[2m└\033[0m \033[31mERROR:\033[0m %s\n\n", err.Error())
continue
}
installs = append(installs, mod)
fmt.Fprint(os.Stderr, " \033[2m└\033[0m \033[32mdone\033[0m\n\n")
}
printStat("\033[1;32m", "INSTALLED", installs)
case "remove":
removes := make([]string, 0, 5)
for _, mod := range modules {
fmt.Printf("removing %s%s\n", mod, globalTxt)
err := operators.Remove(mod, global)
if err != nil {
fmt.Println(err)
continue
}
removes = append(removes, mod)
fmt.Print(" \033[2m└\033[0m \033[32mdone\033[0m\n\n")
}
printStat("\033[1;31m", "REMOVED", removes)
case "update":
updates := make([]string, 0, 5)
for _, mod := range modules {
fmt.Printf("updating %s%s\n", mod, globalTxt)
err := operators.Update(mod, global)
if err != nil {
fmt.Println(err)
continue
}
updates = append(updates, mod)
fmt.Print(" \033[2m└\033[0m \033[32mdone\033[0m\n\n")
}
printStat("\033[1;36m", "UPDATED", updates)
case "update-all":
baseDir := operators.GetModBaseDir()
if global {
baseDir = operators.GlobalPath
}
mods, _ := filepath.Glob(filepath.Join(baseDir, "*"))
for i := range mods {
mods[i] = filepath.Base(mods[i])
}
modules = mods
arg[1] = "update"
goto MainSwitch
case "search":
for _, term := range modules {
fmt.Printf("searching for %q\n\n", term)
err := operators.Search(term)
if err != nil {
fmt.Println(err)
continue
}
}
case "show":
for _, mod := range modules {
err := operators.Show(mod)
if err != nil {
fmt.Println(err)
continue
}
}
default:
fmt.Fprintf(os.Stderr, "Unknown command %s\n\n%s\n", arg[1], helptext)
}
}
func printStat(color, prefix string, pkgs []string) {
count := len(pkgs)
if count > 0 {
fmt.Printf("%s%10s\033[0m ", color, prefix)
if count > 1 {
fmt.Printf("%d packages", count)
} else {
fmt.Printf("1 package")
}
fmt.Printf(" (%s)\n", strings.Join(pkgs, ", "))
}
}
func checkGlobalEnv() {
err := os.MkdirAll(globalPath, 0755)
if err != nil {
fmt.Fprintf(os.Stderr, "\033[1;31mError:\033[0m Unable to access global environment.\n\nAre you root? Using a \033[3m-g\033[0m or \033[3m--global\033[0m flag accesses the /usr/local/lib heirarchy,\nwhich will require root access on most systems\n")
os.Exit(1)
}
}
func printHelp() {
fmt.Printf("%s\n%s\n", banner, helptext)
}