package main import ( "fmt" "os" "path/filepath" paths "qulay/config" "qulay/database" "qulay/helpers" pkg "qulay/package" "slices" "strings" ) var _name string = filepath.Base(os.Args[0]) var _cmds = []string{"h", "+", "-", "g", "s", "p", "u", "r", "q", "f", "v", "b", "o"} const _version string = "1.0" const _help string = `{_name}: Qulay Package Manager Usage: {_name} h -> help menu {_name} + pkg -> download and install package (or .qpmp file path) {_name} - pkg -> remove package {_name} b pkg -> build package into .tar.zst (or .qpmp on :qpmp) {_name} g pkg -> get package version {_name} s pkg -> search packages by name {_name} p repo -> purge local repo directory {_name} u -> update all repositories {_name} r -> get all repositories configs {_name} o -> upgrade all installed packages {_name} q -> get all installed packages {_name} f -> get files path for destDir {_name} v -> get {_name} version Options: :a -> ask before doing :nl -> disable recording in databases and logs :nd -> do not download deps :r -> reinstall already installed deps :f -> force install (ignore conflicts) :qpmp -> build a .qpmp archive instead of .tar.zst Tags (for +, - , b and o): @all -> apply to all packages repo/@all -> apply to all packages in repo @inst -> apply to installed (for b: built) packages repo/@inst -> apply to installed (for b: built) packages in repo @notinst -> apply to not installed (for b: not built) packages repo/@notinst-> apply to not installed (for b: not built) packages in repo @old -> apply to installed/built packages outdated by version repo/@old -> apply to outdated packages in repo o without tags applies @old automatically Vars: DESTDIR -> path where the package will be installed/removed` func parseArgs(args []string) ([]string, []string, []string) { var cmds, oths, opts []string for _, arg := range args { if strings.HasPrefix(arg, ":") { opts = append(opts, arg) } else if slices.Contains(_cmds, arg) && len(cmds) < 1 { cmds = append(cmds, arg) } else { oths = append(oths, arg) } } return cmds, oths, opts } func printHelp() { r := strings.NewReplacer("{_name}", _name) fmt.Println(r.Replace(_help)) } func main() { var args []string = os.Args[1:] cmds, oths, opts := parseArgs(args) destDir := os.Getenv("DESTDIR") if destDir == "" { destDir = "/" } absDestDir, err := filepath.Abs(destDir) if err != nil { fmt.Fprintf(os.Stderr, "!! failed to get absolute path of destDir: %v\n", err) os.Exit(1) } if len(args) == 0 || len(cmds) == 0 { printHelp() os.Exit(1) } // fmt.Println(cmds, oths, opts) if cmds[0] == "h" { printHelp() } else if cmds[0] == "+" { if len(oths) < 1 { fmt.Println("!! no package(s) received") os.Exit(1) } names, err := pkg.Expand("+", oths, absDestDir) if err != nil { fmt.Println("!!", err) os.Exit(1) } for _, n := range names { err := pkg.Install(n, opts, absDestDir) if err != nil { fmt.Println("!!", err) os.Exit(1) } } } else if cmds[0] == "-" { if len(oths) < 1 { fmt.Println("!! no package(s) received") os.Exit(1) } names, err := pkg.Expand("-", oths, absDestDir) if err != nil { fmt.Println("!!", err) os.Exit(1) } for _, n := range names { err := pkg.Remove(n, opts, absDestDir) if err != nil { fmt.Println("!!", err) os.Exit(1) } } } else if cmds[0] == "u" { database.DownloadRepos(absDestDir) } else if cmds[0] == "b" { if len(oths) < 1 { fmt.Println("!! no package(s) received") os.Exit(1) } names, err := pkg.Expand("b", oths, absDestDir) if err != nil { fmt.Println("!!", err) os.Exit(1) } for _, n := range names { err := pkg.Build(n, opts, absDestDir) if err != nil { fmt.Println("!!", err) os.Exit(1) } } } else if cmds[0] == "g" { if len(oths) < 1 { fmt.Println("!! no package(s) received") os.Exit(1) } for _, name := range oths { fmt.Println(database.GetPackageVersion(name, absDestDir)) } } else if cmds[0] == "r" { for _, repo := range database.GetRepos(absDestDir) { fmt.Println(repo.Name, "url:", repo.URL) } } else if cmds[0] == "o" { if len(oths) < 1 { oths = []string{"@old"} } names, err := pkg.Expand("o", oths, absDestDir) if err != nil { fmt.Println("!!", err) os.Exit(1) } err = pkg.Upgrade(names, opts, absDestDir) if err != nil { fmt.Println("!!", err) os.Exit(1) } } else if cmds[0] == "q" { for name, version := range database.ReadInstalled(absDestDir) { if len(version) > 0 { fmt.Println(name, "-", version[0]) } } } else if cmds[0] == "s" { if len(oths) < 1 { pkgs := pkg.GetPackages(absDestDir) for _, p := range pkgs { if database.IsInstalled(p.Repo+"/"+p.Name, absDestDir) { fmt.Printf("[+] %s/%s - %v - %v\n", p.Repo, p.Name, p.Version, p.Desc) } else { fmt.Printf(" %s/%s - %v - %v\n", p.Repo, p.Name, p.Version, p.Desc) } } } else { for _, n := range oths { pkgs := pkg.FindPackages(n, absDestDir) for _, p := range pkgs { if database.IsInstalled(p.Repo+"/"+p.Name, absDestDir) { fmt.Printf("[+] %s/%s - %v - %v\n", p.Repo, p.Name, p.Version, p.Desc) } else { fmt.Printf(" %s/%s - %v - %v\n", p.Repo, p.Name, p.Version, p.Desc) } } } } } else if cmds[0] == "p" { if slices.Contains(opts, ":a") { if !helpers.Ask("do you want purge repo(s)?") { os.Exit(1) } } if len(oths) >= 1 { for _, n := range oths { err := database.PurgeRepository(n, absDestDir) if err != nil { fmt.Println("!!", err) os.Exit(1) } else { fmt.Println(":: deleted", n, "repository in", paths.ReposDir) } } } } else if cmds[0] == "f" { fmt.Printf("dest dir: %v\n", destDir) fmt.Printf("abs dest dir: %v\n", absDestDir) fmt.Printf("is abs: %v\n", filepath.IsAbs(destDir)) fmt.Printf("repos config dir: %v\n", filepath.Join(absDestDir, paths.ReposConfigDir)) fmt.Printf("repos dir: %v\n", filepath.Join(absDestDir, paths.ReposDir)) fmt.Printf("installed pkgs database: %v\n", filepath.Join(absDestDir, paths.InstalledFile)) fmt.Printf("built pkgs dir: %v\n", filepath.Join(absDestDir, paths.BuiltDir)) fmt.Printf("build config file: %v\n", filepath.Join(absDestDir, paths.BuildConfigFile)) } else if cmds[0] == "v" { fmt.Println(_version) } else { fmt.Println("w! unknown command:", cmds[0]) printHelp() os.Exit(1) } }