Expanded on top of the current argument system by adding flags
This commit is contained in:
parent
b4de7341ac
commit
88d4b94225
Binary file not shown.
Binary file not shown.
@ -1,4 +1,4 @@
|
|||||||
name: bpm
|
name: bpm
|
||||||
description: The Bubble Package Manager
|
description: The Bubble Package Manager
|
||||||
version: 0.0.1
|
version: 0.0.3
|
||||||
type: binary
|
type: binary
|
||||||
|
131
main.go
131
main.go
@ -5,6 +5,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
|
"slices"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -13,18 +14,12 @@ import (
|
|||||||
/* A simple-to-use package manager */
|
/* A simple-to-use package manager */
|
||||||
/* ---------------------------------- */
|
/* ---------------------------------- */
|
||||||
|
|
||||||
var bpmVer = "0.0.1"
|
var bpmVer = "0.0.3"
|
||||||
var rootDir string = "/"
|
var rootDir string = "/"
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
fmt.Printf("Running %s %s\n", getKernel(), getArch())
|
//fmt.Printf("Running %s %s\n", getKernel(), getArch())
|
||||||
resolveCommand()
|
resolveCommand()
|
||||||
/*_, err := readPackage("test_hello_package/hello.bpm")
|
|
||||||
err := installPackage("test_hello_package/hello.bpm", rootDir)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("Could not read package\nError: %s\n", err)
|
|
||||||
}
|
|
||||||
removePackage("hello")*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func getArgs() []string {
|
func getArgs() []string {
|
||||||
@ -64,15 +59,18 @@ func getCommandType() commandType {
|
|||||||
default:
|
default:
|
||||||
return help
|
return help
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func resolveCommand() {
|
func resolveCommand() {
|
||||||
switch getCommandType() {
|
switch getCommandType() {
|
||||||
case version:
|
case version:
|
||||||
|
resolveFlags()
|
||||||
fmt.Println("Bubble Package Manager (BPM)")
|
fmt.Println("Bubble Package Manager (BPM)")
|
||||||
fmt.Println("Version: " + bpmVer)
|
fmt.Println("Version: " + bpmVer)
|
||||||
case info:
|
case info:
|
||||||
packages := getArgs()[1:]
|
_, i := resolveFlags()
|
||||||
|
packages := getArgs()[1+i:]
|
||||||
if len(packages) == 0 {
|
if len(packages) == 0 {
|
||||||
fmt.Println("No packages were given")
|
fmt.Println("No packages were given")
|
||||||
return
|
return
|
||||||
@ -83,13 +81,36 @@ func resolveCommand() {
|
|||||||
fmt.Printf("Package (%s) could not be found\n", pkg)
|
fmt.Printf("Package (%s) could not be found\n", pkg)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
fmt.Print("---------------\n" + createInfoFile(*info))
|
fmt.Print("----------------\n" + createInfoFile(*info))
|
||||||
if n == len(packages)-1 {
|
if n == len(packages)-1 {
|
||||||
fmt.Println("---------------")
|
fmt.Println("----------------")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case list:
|
||||||
|
resolveFlags()
|
||||||
|
packages, err := getInstalledPackages()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Could not get installed packages\nError: %s", err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if len(packages) == 0 {
|
||||||
|
fmt.Println("No packages have been installed")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for n, pkg := range packages {
|
||||||
|
info := getPackageInfo(pkg)
|
||||||
|
if info == nil {
|
||||||
|
fmt.Printf("Package (%s) could not be found\n", pkg)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
fmt.Print("----------------\n" + createInfoFile(*info))
|
||||||
|
if n == len(packages)-1 {
|
||||||
|
fmt.Println("----------------")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case install:
|
case install:
|
||||||
files := getArgs()[1:]
|
flags, i := resolveFlags()
|
||||||
|
files := getArgs()[1+i:]
|
||||||
if len(files) == 0 {
|
if len(files) == 0 {
|
||||||
fmt.Println("No files were given to install")
|
fmt.Println("No files were given to install")
|
||||||
return
|
return
|
||||||
@ -99,15 +120,42 @@ func resolveCommand() {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Could not read package\nError: %s\n", err)
|
log.Fatalf("Could not read package\nError: %s\n", err)
|
||||||
}
|
}
|
||||||
fmt.Print("---------------\n" + createInfoFile(*pkgInfo))
|
fmt.Print("----------------\n" + createInfoFile(*pkgInfo))
|
||||||
fmt.Println("---------------")
|
fmt.Println("----------------")
|
||||||
|
if isPackageInstalled(pkgInfo.name) {
|
||||||
|
if !slices.Contains(flags, "y") {
|
||||||
|
installedInfo := getPackageInfo(pkgInfo.name)
|
||||||
|
if strings.Compare(pkgInfo.version, installedInfo.version) > 0 {
|
||||||
|
fmt.Println("This file contains a newer version of this package (" + installedInfo.version + " -> " + pkgInfo.version + ")")
|
||||||
|
fmt.Print("Do you wish to update this package? [y\\N] ")
|
||||||
|
} else if strings.Compare(pkgInfo.version, installedInfo.version) < 0 {
|
||||||
|
fmt.Println("This file contains an older version of this package (" + installedInfo.version + " -> " + pkgInfo.version + ")")
|
||||||
|
fmt.Print("Do you wish to downgrade this package? (Not recommended) [y\\N] ")
|
||||||
|
} else if strings.Compare(pkgInfo.version, installedInfo.version) == 0 {
|
||||||
|
fmt.Println("This package is already installed on the system and is up to date")
|
||||||
|
fmt.Print("Do you wish to reinstall this package? [y\\N] ")
|
||||||
|
}
|
||||||
reader := bufio.NewReader(os.Stdin)
|
reader := bufio.NewReader(os.Stdin)
|
||||||
fmt.Print("Do you wish to install this package? [y\\N] ")
|
|
||||||
text, _ := reader.ReadString('\n')
|
text, _ := reader.ReadString('\n')
|
||||||
if strings.TrimSpace(strings.ToLower(text)) != "y" && strings.TrimSpace(strings.ToLower(text)) != "yes" {
|
if strings.TrimSpace(strings.ToLower(text)) != "y" && strings.TrimSpace(strings.ToLower(text)) != "yes" {
|
||||||
fmt.Printf("Skipping package (%s)...\n", pkgInfo.name)
|
fmt.Printf("Skipping package (%s)...\n", pkgInfo.name)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
err := removePackage(pkgInfo.name)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Could not remove current version of the package\nError: %s\n", err)
|
||||||
|
}
|
||||||
|
} else if !slices.Contains(flags, "y") {
|
||||||
|
fmt.Print("Do you wish to install this package? [y\\N] ")
|
||||||
|
reader := bufio.NewReader(os.Stdin)
|
||||||
|
text, _ := reader.ReadString('\n')
|
||||||
|
if strings.TrimSpace(strings.ToLower(text)) != "y" && strings.TrimSpace(strings.ToLower(text)) != "yes" {
|
||||||
|
fmt.Printf("Skipping package (%s)...\n", pkgInfo.name)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
err = installPackage(file, rootDir)
|
err = installPackage(file, rootDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Could not install package\nError: %s\n", err)
|
log.Fatalf("Could not install package\nError: %s\n", err)
|
||||||
@ -115,7 +163,8 @@ func resolveCommand() {
|
|||||||
fmt.Printf("Package (%s) was successfully installed!\n", pkgInfo.name)
|
fmt.Printf("Package (%s) was successfully installed!\n", pkgInfo.name)
|
||||||
}
|
}
|
||||||
case remove:
|
case remove:
|
||||||
packages := getArgs()[1:]
|
flags, i := resolveFlags()
|
||||||
|
packages := getArgs()[1+i:]
|
||||||
if len(packages) == 0 {
|
if len(packages) == 0 {
|
||||||
fmt.Println("No packages were given")
|
fmt.Println("No packages were given")
|
||||||
return
|
return
|
||||||
@ -126,8 +175,9 @@ func resolveCommand() {
|
|||||||
fmt.Printf("Package (%s) could not be found\n", pkg)
|
fmt.Printf("Package (%s) could not be found\n", pkg)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
fmt.Print("---------------\n" + createInfoFile(*pkgInfo))
|
fmt.Print("----------------\n" + createInfoFile(*pkgInfo))
|
||||||
fmt.Println("---------------")
|
fmt.Println("----------------")
|
||||||
|
if !slices.Contains(flags, "y") {
|
||||||
reader := bufio.NewReader(os.Stdin)
|
reader := bufio.NewReader(os.Stdin)
|
||||||
fmt.Print("Do you wish to remove this package? [y\\N] ")
|
fmt.Print("Do you wish to remove this package? [y\\N] ")
|
||||||
text, _ := reader.ReadString('\n')
|
text, _ := reader.ReadString('\n')
|
||||||
@ -135,6 +185,7 @@ func resolveCommand() {
|
|||||||
fmt.Printf("Skipping package (%s)...\n", pkgInfo.name)
|
fmt.Printf("Skipping package (%s)...\n", pkgInfo.name)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
}
|
||||||
err := removePackage(pkg)
|
err := removePackage(pkg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Could not remove package\nError: %s\n", err)
|
log.Fatalf("Could not remove package\nError: %s\n", err)
|
||||||
@ -142,6 +193,48 @@ func resolveCommand() {
|
|||||||
fmt.Printf("Package (%s) was successfully removed!\n", pkgInfo.name)
|
fmt.Printf("Package (%s) was successfully removed!\n", pkgInfo.name)
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
fmt.Println("help...")
|
fmt.Println("------Help------")
|
||||||
|
fmt.Println("bpm version | shows information on the installed version of bpm")
|
||||||
|
fmt.Println("bpm info | shows information on an installed package")
|
||||||
|
fmt.Println("bpm list [-e] | lists all installed packages. -e lists only explicitly installed packages")
|
||||||
|
fmt.Println("bpm install [-y] <files...> | installs the following files. -y skips the confirmation prompt")
|
||||||
|
fmt.Println("bpm remove [-y] <packages...> | removes the following packages. -y skips the confirmation prompt")
|
||||||
|
fmt.Println("bpm cleanup | removes all unneeded dependencies")
|
||||||
|
fmt.Println("----------------")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func resolveFlags() ([]string, int) {
|
||||||
|
flags := getArgs()[1:]
|
||||||
|
var ret []string
|
||||||
|
for _, flag := range flags {
|
||||||
|
if strings.HasPrefix(flag, "-") {
|
||||||
|
f := strings.TrimPrefix(flag, "-")
|
||||||
|
switch getCommandType() {
|
||||||
|
default:
|
||||||
|
log.Fatalf("Invalid flag " + flag)
|
||||||
|
case list:
|
||||||
|
v := [...]string{"e"}
|
||||||
|
if !slices.Contains(v[:], f) {
|
||||||
|
log.Fatalf("Invalid flag " + flag)
|
||||||
|
}
|
||||||
|
ret = append(ret, f)
|
||||||
|
case install:
|
||||||
|
v := [...]string{"y"}
|
||||||
|
if !slices.Contains(v[:], f) {
|
||||||
|
log.Fatalf("Invalid flag " + flag)
|
||||||
|
}
|
||||||
|
ret = append(ret, f)
|
||||||
|
case remove:
|
||||||
|
v := [...]string{"y"}
|
||||||
|
if !slices.Contains(v[:], f) {
|
||||||
|
log.Fatalf("Invalid flag " + flag)
|
||||||
|
}
|
||||||
|
ret = append(ret, f)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret, len(ret)
|
||||||
|
}
|
||||||
|
@ -206,6 +206,15 @@ func installPackage(filename, installDir string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func isPackageInstalled(pkg string) bool {
|
||||||
|
dataDir := path.Join(rootDir, "var/lib/bpm/installed/")
|
||||||
|
pkgDir := path.Join(dataDir, pkg)
|
||||||
|
if _, err := os.Stat(pkgDir); err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
func getInstalledPackages() ([]string, error) {
|
func getInstalledPackages() ([]string, error) {
|
||||||
dataDir := path.Join(rootDir, "var/lib/bpm/installed/")
|
dataDir := path.Join(rootDir, "var/lib/bpm/installed/")
|
||||||
items, err := os.ReadDir(dataDir)
|
items, err := os.ReadDir(dataDir)
|
||||||
@ -276,6 +285,9 @@ func removePackage(pkg string) error {
|
|||||||
for _, file := range files {
|
for _, file := range files {
|
||||||
file = path.Join(rootDir, file)
|
file = path.Join(rootDir, file)
|
||||||
stat, err := os.Stat(file)
|
stat, err := os.Stat(file)
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
Binary file not shown.
@ -1,4 +1,4 @@
|
|||||||
name: hello
|
name: hello
|
||||||
description: A simple hello world program
|
description: A simple hello world program
|
||||||
version: 1.0
|
version: 1.0-1
|
||||||
type: binary
|
type: binary
|
118
version.go
Normal file
118
version.go
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
// Copyright (c) Tailscale Inc & AUTHORS
|
||||||
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
|
// Package cmpver implements a variant of debian version number
|
||||||
|
// comparison.
|
||||||
|
//
|
||||||
|
// A version is a string consisting of alternating non-numeric and
|
||||||
|
// numeric fields. When comparing two versions, each one is broken
|
||||||
|
// down into its respective fields, and the fields are compared
|
||||||
|
// pairwise. The comparison is lexicographic for non-numeric fields,
|
||||||
|
// numeric for numeric fields. The first non-equal field pair
|
||||||
|
// determines the ordering of the two versions.
|
||||||
|
//
|
||||||
|
// This comparison scheme is a simplified version of Debian's version
|
||||||
|
// number comparisons. Debian differs in a few details of
|
||||||
|
// lexicographical field comparison, where certain characters have
|
||||||
|
// special meaning and ordering. We don't need that, because Tailscale
|
||||||
|
// version numbers don't need it.
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Less reports whether v1 is less than v2.
|
||||||
|
//
|
||||||
|
// Note that "12" is less than "12.0".
|
||||||
|
func Less(v1, v2 string) bool {
|
||||||
|
return Compare(v1, v2) < 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// LessEq reports whether v1 is less than or equal to v2.
|
||||||
|
//
|
||||||
|
// Note that "12" is less than "12.0".
|
||||||
|
func LessEq(v1, v2 string) bool {
|
||||||
|
return Compare(v1, v2) <= 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func isnum(r rune) bool {
|
||||||
|
return r >= '0' && r <= '9'
|
||||||
|
}
|
||||||
|
|
||||||
|
func notnum(r rune) bool {
|
||||||
|
return !isnum(r)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compare returns an integer comparing two strings as version numbers.
|
||||||
|
// The result will be -1, 0, or 1 representing the sign of v1 - v2:
|
||||||
|
//
|
||||||
|
// Compare(v1, v2) < 0 if v1 < v2
|
||||||
|
// == 0 if v1 == v2
|
||||||
|
// > 0 if v1 > v2
|
||||||
|
func Compare(v1, v2 string) int {
|
||||||
|
var (
|
||||||
|
f1, f2 string
|
||||||
|
n1, n2 uint64
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
for v1 != "" || v2 != "" {
|
||||||
|
// Compare the non-numeric character run lexicographically.
|
||||||
|
f1, v1 = splitPrefixFunc(v1, notnum)
|
||||||
|
f2, v2 = splitPrefixFunc(v2, notnum)
|
||||||
|
|
||||||
|
if res := strings.Compare(f1, f2); res != 0 {
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compare the numeric character run numerically.
|
||||||
|
f1, v1 = splitPrefixFunc(v1, isnum)
|
||||||
|
f2, v2 = splitPrefixFunc(v2, isnum)
|
||||||
|
|
||||||
|
// ParseUint refuses to parse empty strings, which would only
|
||||||
|
// happen if we reached end-of-string. We follow the Debian
|
||||||
|
// convention that empty strings mean zero, because
|
||||||
|
// empirically that produces reasonable-feeling comparison
|
||||||
|
// behavior.
|
||||||
|
n1 = 0
|
||||||
|
if f1 != "" {
|
||||||
|
n1, err = strconv.ParseUint(f1, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
panic(fmt.Sprintf("all-number string %q didn't parse as string: %s", f1, err))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
n2 = 0
|
||||||
|
if f2 != "" {
|
||||||
|
n2, err = strconv.ParseUint(f2, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
panic(fmt.Sprintf("all-number string %q didn't parse as string: %s", f2, err))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case n1 == n2:
|
||||||
|
case n1 < n2:
|
||||||
|
return -1
|
||||||
|
case n1 > n2:
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only way to reach here is if v1 and v2 run out of fields
|
||||||
|
// simultaneously - i.e. exactly equal versions.
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// splitPrefixFunc splits s at the first rune where f(rune) is false.
|
||||||
|
func splitPrefixFunc(s string, f func(rune) bool) (string, string) {
|
||||||
|
for i, r := range s {
|
||||||
|
if !f(r) {
|
||||||
|
return s[:i], s[i:]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return s, s[:0]
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user