- Added a little bit of formatting to the help subcommand
- Removed unnecessary version.go file - Moved utils to their own go package - Moved test packages under the to the test_packages directory - Added the bpm-utils test package which can be used to make your own bpm packages
This commit is contained in:
parent
88d4b94225
commit
b67f357996
Binary file not shown.
Binary file not shown.
@ -1,4 +1,4 @@
|
|||||||
package main
|
package bpm_utils
|
||||||
|
|
||||||
import "syscall"
|
import "syscall"
|
||||||
|
|
||||||
@ -20,6 +20,25 @@ func getKernel() string {
|
|||||||
return byteArrayToString(u.Sysname[:]) + " " + byteArrayToString(u.Release[:])
|
return byteArrayToString(u.Sysname[:]) + " " + byteArrayToString(u.Release[:])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func stringSliceRemove(s []string, r string) []string {
|
||||||
|
for i, v := range s {
|
||||||
|
if v == r {
|
||||||
|
return append(s[:i], s[i+1:]...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
func stringSliceRemoveEmpty(s []string) []string {
|
||||||
|
var r []string
|
||||||
|
for _, str := range s {
|
||||||
|
if str != "" {
|
||||||
|
r = append(r, str)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
func byteArrayToString(bs []int8) string {
|
func byteArrayToString(bs []int8) string {
|
||||||
b := make([]byte, len(bs))
|
b := make([]byte, len(bs))
|
||||||
for i, v := range bs {
|
for i, v := range bs {
|
@ -1,4 +1,4 @@
|
|||||||
package main
|
package bpm_utils
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"archive/tar"
|
"archive/tar"
|
||||||
@ -14,16 +14,16 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
type packageInfo struct {
|
type PackageInfo struct {
|
||||||
name string
|
Name string
|
||||||
description string
|
Description string
|
||||||
version string
|
Version string
|
||||||
pkgType string
|
Type string
|
||||||
depends []string
|
Depends []string
|
||||||
provides []string
|
Provides []string
|
||||||
}
|
}
|
||||||
|
|
||||||
func readPackage(filename string) (*packageInfo, error) {
|
func ReadPackage(filename string) (*PackageInfo, error) {
|
||||||
if _, err := os.Stat(filename); os.IsNotExist(err) {
|
if _, err := os.Stat(filename); os.IsNotExist(err) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -50,7 +50,7 @@ func readPackage(filename string) (*packageInfo, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
pkgInfo, err := readPackageInfo(string(bs))
|
pkgInfo, err := ReadPackageInfo(string(bs))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -60,8 +60,8 @@ func readPackage(filename string) (*packageInfo, error) {
|
|||||||
return nil, errors.New("pkg.info not found in archive")
|
return nil, errors.New("pkg.info not found in archive")
|
||||||
}
|
}
|
||||||
|
|
||||||
func readPackageInfo(contents string) (*packageInfo, error) {
|
func ReadPackageInfo(contents string) (*PackageInfo, error) {
|
||||||
pkgInfo := packageInfo{}
|
pkgInfo := PackageInfo{}
|
||||||
lines := strings.Split(contents, "\n")
|
lines := strings.Split(contents, "\n")
|
||||||
for num, line := range lines {
|
for num, line := range lines {
|
||||||
if len(strings.TrimSpace(line)) == 0 {
|
if len(strings.TrimSpace(line)) == 0 {
|
||||||
@ -75,28 +75,40 @@ func readPackageInfo(contents string) (*packageInfo, error) {
|
|||||||
split[1] = strings.Trim(split[1], " ")
|
split[1] = strings.Trim(split[1], " ")
|
||||||
switch split[0] {
|
switch split[0] {
|
||||||
case "name":
|
case "name":
|
||||||
pkgInfo.name = split[1]
|
pkgInfo.Name = split[1]
|
||||||
case "description":
|
case "description":
|
||||||
pkgInfo.description = split[1]
|
pkgInfo.Description = split[1]
|
||||||
case "version":
|
case "version":
|
||||||
pkgInfo.version = split[1]
|
pkgInfo.Version = split[1]
|
||||||
case "type":
|
case "type":
|
||||||
pkgInfo.pkgType = split[1]
|
pkgInfo.Type = split[1]
|
||||||
|
case "depends":
|
||||||
|
pkgInfo.Depends = strings.Split(strings.Replace(split[1], " ", "", -1), ",")
|
||||||
|
pkgInfo.Depends = stringSliceRemoveEmpty(pkgInfo.Depends)
|
||||||
|
case "provides":
|
||||||
|
pkgInfo.Provides = strings.Split(strings.Replace(split[1], " ", "", -1), ",")
|
||||||
|
pkgInfo.Provides = stringSliceRemoveEmpty(pkgInfo.Depends)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return &pkgInfo, nil
|
return &pkgInfo, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func createInfoFile(pkgInfo packageInfo) string {
|
func CreateInfoFile(pkgInfo PackageInfo) string {
|
||||||
ret := ""
|
ret := ""
|
||||||
ret = ret + "name: " + pkgInfo.name + "\n"
|
ret = ret + "name: " + pkgInfo.Name + "\n"
|
||||||
ret = ret + "description: " + pkgInfo.description + "\n"
|
ret = ret + "description: " + pkgInfo.Description + "\n"
|
||||||
ret = ret + "version: " + pkgInfo.version + "\n"
|
ret = ret + "version: " + pkgInfo.Version + "\n"
|
||||||
ret = ret + "type: " + pkgInfo.pkgType + "\n"
|
ret = ret + "type: " + pkgInfo.Type + "\n"
|
||||||
|
if len(pkgInfo.Depends) > 0 {
|
||||||
|
ret = ret + "depends (" + strconv.Itoa(len(pkgInfo.Depends)) + "): " + strings.Join(pkgInfo.Depends, ",") + "\n"
|
||||||
|
}
|
||||||
|
if len(pkgInfo.Provides) > 0 {
|
||||||
|
ret = ret + "provides (" + strconv.Itoa(len(pkgInfo.Provides)) + "): " + strings.Join(pkgInfo.Provides, ",") + "\n"
|
||||||
|
}
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
func installPackage(filename, installDir string) error {
|
func InstallPackage(filename, installDir string, force bool) error {
|
||||||
if _, err := os.Stat(filename); os.IsNotExist(err) {
|
if _, err := os.Stat(filename); os.IsNotExist(err) {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -110,7 +122,15 @@ func installPackage(filename, installDir string) error {
|
|||||||
}
|
}
|
||||||
tr := tar.NewReader(archive)
|
tr := tar.NewReader(archive)
|
||||||
var files []string
|
var files []string
|
||||||
var pkgInfo *packageInfo
|
pkgInfo, err := ReadPackage(filename)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if !force {
|
||||||
|
if unresolved := CheckDependencies(pkgInfo, installDir); len(unresolved) != 0 {
|
||||||
|
return errors.New("Could not resolve all dependencies. Missing " + strings.Join(unresolved, ", "))
|
||||||
|
}
|
||||||
|
}
|
||||||
for {
|
for {
|
||||||
header, err := tr.Next()
|
header, err := tr.Next()
|
||||||
if err == io.EOF {
|
if err == io.EOF {
|
||||||
@ -119,16 +139,6 @@ func installPackage(filename, installDir string) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if header.Name == "pkg.info" {
|
|
||||||
bs, _ := io.ReadAll(tr)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
pkgInfo, err = readPackageInfo(string(bs))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if strings.HasPrefix(header.Name, "files/") && header.Name != "files/" {
|
if strings.HasPrefix(header.Name, "files/") && header.Name != "files/" {
|
||||||
extractFilename := path.Join(installDir, strings.TrimPrefix(header.Name, "files/"))
|
extractFilename := path.Join(installDir, strings.TrimPrefix(header.Name, "files/"))
|
||||||
switch header.Typeflag {
|
switch header.Typeflag {
|
||||||
@ -164,12 +174,12 @@ func installPackage(filename, installDir string) error {
|
|||||||
slices.Sort(files)
|
slices.Sort(files)
|
||||||
slices.Reverse(files)
|
slices.Reverse(files)
|
||||||
|
|
||||||
dataDir := path.Join(installDir, "var/lib/bpm/installed/")
|
installedDir := path.Join(installDir, "var/lib/bpm/installed/")
|
||||||
err = os.MkdirAll(dataDir, 755)
|
err = os.MkdirAll(installedDir, 755)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
pkgDir := path.Join(dataDir, pkgInfo.name)
|
pkgDir := path.Join(installedDir, pkgInfo.Name)
|
||||||
err = os.RemoveAll(pkgDir)
|
err = os.RemoveAll(pkgDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -189,35 +199,70 @@ func installPackage(filename, installDir string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
f.Close()
|
err = f.Close()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
f, err = os.Create(path.Join(pkgDir, "info"))
|
f, err = os.Create(path.Join(pkgDir, "info"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
_, err = f.WriteString(createInfoFile(*pkgInfo))
|
_, err = f.WriteString(CreateInfoFile(*pkgInfo))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = f.Close()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
f.Close()
|
|
||||||
|
|
||||||
archive.Close()
|
err = archive.Close()
|
||||||
file.Close()
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = file.Close()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func isPackageInstalled(pkg string) bool {
|
func CheckDependencies(pkgInfo *PackageInfo, rootDir string) []string {
|
||||||
dataDir := path.Join(rootDir, "var/lib/bpm/installed/")
|
unresolved := make([]string, len(pkgInfo.Depends))
|
||||||
pkgDir := path.Join(dataDir, pkg)
|
copy(unresolved, pkgInfo.Depends)
|
||||||
|
installedDir := path.Join(rootDir, "var/lib/bpm/installed/")
|
||||||
|
if _, err := os.Stat(installedDir); err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
items, err := os.ReadDir(installedDir)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, item := range items {
|
||||||
|
if !item.IsDir() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if slices.Contains(unresolved, item.Name()) {
|
||||||
|
unresolved = stringSliceRemove(unresolved, item.Name())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return unresolved
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsPackageInstalled(pkg, rootDir string) bool {
|
||||||
|
installedDir := path.Join(rootDir, "var/lib/bpm/installed/")
|
||||||
|
pkgDir := path.Join(installedDir, pkg)
|
||||||
if _, err := os.Stat(pkgDir); err != nil {
|
if _, err := os.Stat(pkgDir); err != nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func getInstalledPackages() ([]string, error) {
|
func GetInstalledPackages(rootDir string) ([]string, error) {
|
||||||
dataDir := path.Join(rootDir, "var/lib/bpm/installed/")
|
installedDir := path.Join(rootDir, "var/lib/bpm/installed/")
|
||||||
items, err := os.ReadDir(dataDir)
|
items, err := os.ReadDir(installedDir)
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
@ -231,12 +276,12 @@ func getInstalledPackages() ([]string, error) {
|
|||||||
return ret, nil
|
return ret, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getPackageFiles(pkg string) []string {
|
func GetPackageFiles(pkg, rootDir string) []string {
|
||||||
var ret []string
|
var ret []string
|
||||||
dataDir := path.Join(rootDir, "var/lib/bpm/installed/")
|
installedDir := path.Join(rootDir, "var/lib/bpm/installed/")
|
||||||
pkgDir := path.Join(dataDir, pkg)
|
pkgDir := path.Join(installedDir, pkg)
|
||||||
files := path.Join(pkgDir, "files")
|
files := path.Join(pkgDir, "files")
|
||||||
if _, err := os.Stat(dataDir); os.IsNotExist(err) {
|
if _, err := os.Stat(installedDir); os.IsNotExist(err) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if _, err := os.Stat(pkgDir); os.IsNotExist(err) {
|
if _, err := os.Stat(pkgDir); os.IsNotExist(err) {
|
||||||
@ -253,11 +298,11 @@ func getPackageFiles(pkg string) []string {
|
|||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
func getPackageInfo(pkg string) *packageInfo {
|
func GetPackageInfo(pkg, rootDir string) *PackageInfo {
|
||||||
dataDir := path.Join(rootDir, "var/lib/bpm/installed/")
|
installedDir := path.Join(rootDir, "var/lib/bpm/installed/")
|
||||||
pkgDir := path.Join(dataDir, pkg)
|
pkgDir := path.Join(installedDir, pkg)
|
||||||
files := path.Join(pkgDir, "info")
|
files := path.Join(pkgDir, "info")
|
||||||
if _, err := os.Stat(dataDir); os.IsNotExist(err) {
|
if _, err := os.Stat(installedDir); os.IsNotExist(err) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if _, err := os.Stat(pkgDir); os.IsNotExist(err) {
|
if _, err := os.Stat(pkgDir); os.IsNotExist(err) {
|
||||||
@ -271,17 +316,17 @@ func getPackageInfo(pkg string) *packageInfo {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
info, err := readPackageInfo(string(bs))
|
info, err := ReadPackageInfo(string(bs))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return info
|
return info
|
||||||
}
|
}
|
||||||
|
|
||||||
func removePackage(pkg string) error {
|
func RemovePackage(pkg, rootDir string) error {
|
||||||
dataDir := path.Join(rootDir, "var/lib/bpm/installed/")
|
installedDir := path.Join(rootDir, "var/lib/bpm/installed/")
|
||||||
pkgDir := path.Join(dataDir, pkg)
|
pkgDir := path.Join(installedDir, pkg)
|
||||||
files := getPackageFiles(pkg)
|
files := GetPackageFiles(pkg, rootDir)
|
||||||
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)
|
91
main.go
91
main.go
@ -2,6 +2,7 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
|
"capcreepergr.me/bpm/bpm_utils"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
@ -14,11 +15,14 @@ import (
|
|||||||
/* A simple-to-use package manager */
|
/* A simple-to-use package manager */
|
||||||
/* ---------------------------------- */
|
/* ---------------------------------- */
|
||||||
|
|
||||||
var bpmVer = "0.0.3"
|
var bpmVer = "0.0.5"
|
||||||
var rootDir string = "/"
|
var rootDir = "/"
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
//fmt.Printf("Running %s %s\n", getKernel(), getArch())
|
if os.Getuid() != 0 {
|
||||||
|
fmt.Println("BPM needs to be run with superuser permissions")
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
||||||
resolveCommand()
|
resolveCommand()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -76,19 +80,19 @@ func resolveCommand() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
for n, pkg := range packages {
|
for n, pkg := range packages {
|
||||||
info := getPackageInfo(pkg)
|
info := bpm_utils.GetPackageInfo(pkg, rootDir)
|
||||||
if info == nil {
|
if info == nil {
|
||||||
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" + bpm_utils.CreateInfoFile(*info))
|
||||||
if n == len(packages)-1 {
|
if n == len(packages)-1 {
|
||||||
fmt.Println("----------------")
|
fmt.Println("----------------")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case list:
|
case list:
|
||||||
resolveFlags()
|
resolveFlags()
|
||||||
packages, err := getInstalledPackages()
|
packages, err := bpm_utils.GetInstalledPackages(rootDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Could not get installed packages\nError: %s", err.Error())
|
log.Fatalf("Could not get installed packages\nError: %s", err.Error())
|
||||||
return
|
return
|
||||||
@ -98,12 +102,12 @@ func resolveCommand() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
for n, pkg := range packages {
|
for n, pkg := range packages {
|
||||||
info := getPackageInfo(pkg)
|
info := bpm_utils.GetPackageInfo(pkg, rootDir)
|
||||||
if info == nil {
|
if info == nil {
|
||||||
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" + bpm_utils.CreateInfoFile(*info))
|
||||||
if n == len(packages)-1 {
|
if n == len(packages)-1 {
|
||||||
fmt.Println("----------------")
|
fmt.Println("----------------")
|
||||||
}
|
}
|
||||||
@ -116,33 +120,38 @@ func resolveCommand() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
for _, file := range files {
|
for _, file := range files {
|
||||||
pkgInfo, err := readPackage(file)
|
pkgInfo, err := bpm_utils.ReadPackage(file)
|
||||||
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" + bpm_utils.CreateInfoFile(*pkgInfo))
|
||||||
fmt.Println("----------------")
|
fmt.Println("----------------")
|
||||||
if isPackageInstalled(pkgInfo.name) {
|
if !slices.Contains(flags, "f") {
|
||||||
|
if unresolved := bpm_utils.CheckDependencies(pkgInfo, rootDir); len(unresolved) != 0 {
|
||||||
|
log.Fatalf("Cannot install package (%s) due to missing dependencies: %s\n", pkgInfo.Name, strings.Join(unresolved, ", "))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if bpm_utils.IsPackageInstalled(pkgInfo.Name, rootDir) {
|
||||||
if !slices.Contains(flags, "y") {
|
if !slices.Contains(flags, "y") {
|
||||||
installedInfo := getPackageInfo(pkgInfo.name)
|
installedInfo := bpm_utils.GetPackageInfo(pkgInfo.Name, rootDir)
|
||||||
if strings.Compare(pkgInfo.version, installedInfo.version) > 0 {
|
if strings.Compare(pkgInfo.Version, installedInfo.Version) > 0 {
|
||||||
fmt.Println("This file contains a newer version of this package (" + installedInfo.version + " -> " + pkgInfo.version + ")")
|
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] ")
|
fmt.Print("Do you wish to update this package? [y\\N] ")
|
||||||
} else if strings.Compare(pkgInfo.version, installedInfo.version) < 0 {
|
} 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.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] ")
|
fmt.Print("Do you wish to downgrade this package? (Not recommended) [y\\N] ")
|
||||||
} else if strings.Compare(pkgInfo.version, installedInfo.version) == 0 {
|
} 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.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] ")
|
fmt.Print("Do you wish to reinstall this package? [y\\N] ")
|
||||||
}
|
}
|
||||||
reader := bufio.NewReader(os.Stdin)
|
reader := bufio.NewReader(os.Stdin)
|
||||||
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)
|
err := bpm_utils.RemovePackage(pkgInfo.Name, rootDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Could not remove current version of the package\nError: %s\n", err)
|
log.Fatalf("Could not remove current version of the package\nError: %s\n", err)
|
||||||
}
|
}
|
||||||
@ -151,16 +160,16 @@ func resolveCommand() {
|
|||||||
reader := bufio.NewReader(os.Stdin)
|
reader := bufio.NewReader(os.Stdin)
|
||||||
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 = installPackage(file, rootDir)
|
err = bpm_utils.InstallPackage(file, rootDir, slices.Contains(flags, "f"))
|
||||||
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)
|
||||||
}
|
}
|
||||||
fmt.Printf("Package (%s) was successfully installed!\n", pkgInfo.name)
|
fmt.Printf("Package (%s) was successfully installed!\n", pkgInfo.Name)
|
||||||
}
|
}
|
||||||
case remove:
|
case remove:
|
||||||
flags, i := resolveFlags()
|
flags, i := resolveFlags()
|
||||||
@ -170,37 +179,41 @@ func resolveCommand() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
for _, pkg := range packages {
|
for _, pkg := range packages {
|
||||||
pkgInfo := getPackageInfo(pkg)
|
pkgInfo := bpm_utils.GetPackageInfo(pkg, rootDir)
|
||||||
if pkgInfo == nil {
|
if pkgInfo == nil {
|
||||||
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" + bpm_utils.CreateInfoFile(*pkgInfo))
|
||||||
fmt.Println("----------------")
|
fmt.Println("----------------")
|
||||||
if !slices.Contains(flags, "y") {
|
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')
|
||||||
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(pkg)
|
err := bpm_utils.RemovePackage(pkg, rootDir)
|
||||||
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)
|
||||||
}
|
}
|
||||||
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("\033[1m------Help------\033[0m")
|
||||||
fmt.Println("bpm version | shows information on the installed version of bpm")
|
fmt.Println("\033[1m\\ Command Format /\033[0m")
|
||||||
fmt.Println("bpm info | shows information on an installed package")
|
fmt.Println("-> command format: bpm <subcommand> [-flags]...")
|
||||||
fmt.Println("bpm list [-e] | lists all installed packages. -e lists only explicitly installed packages")
|
fmt.Println("-> flags will be read if passed right after the subcommand otherwise they will be read as subcommand arguments")
|
||||||
fmt.Println("bpm install [-y] <files...> | installs the following files. -y skips the confirmation prompt")
|
fmt.Println("\033[1m\\ Command List /\033[0m")
|
||||||
fmt.Println("bpm remove [-y] <packages...> | removes the following packages. -y skips the confirmation prompt")
|
fmt.Println("-> bpm version | shows information on the installed version of bpm")
|
||||||
fmt.Println("bpm cleanup | removes all unneeded dependencies")
|
fmt.Println("-> bpm info | shows information on an installed package")
|
||||||
fmt.Println("----------------")
|
fmt.Println("-> bpm list | lists all installed packages")
|
||||||
|
fmt.Println("-> bpm install [-y, -f] <files...> | installs the following files. -y skips the confirmation prompt. -f skips dependency resolution")
|
||||||
|
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("\033[1m----------------\033[0m")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -213,14 +226,8 @@ func resolveFlags() ([]string, int) {
|
|||||||
switch getCommandType() {
|
switch getCommandType() {
|
||||||
default:
|
default:
|
||||||
log.Fatalf("Invalid flag " + flag)
|
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:
|
case install:
|
||||||
v := [...]string{"y"}
|
v := [...]string{"y", "f"}
|
||||||
if !slices.Contains(v[:], f) {
|
if !slices.Contains(v[:], f) {
|
||||||
log.Fatalf("Invalid flag " + flag)
|
log.Fatalf("Invalid flag " + flag)
|
||||||
}
|
}
|
||||||
|
Binary file not shown.
BIN
test_packages/bpm-utils/bpm-utils.bpm
Normal file
BIN
test_packages/bpm-utils/bpm-utils.bpm
Normal file
Binary file not shown.
28
test_packages/bpm-utils/files/usr/bin/bpm-create
Executable file
28
test_packages/bpm-utils/files/usr/bin/bpm-create
Executable file
@ -0,0 +1,28 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
if [ $# -eq 0 ]
|
||||||
|
then
|
||||||
|
echo "No output package name given!"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
output=$1
|
||||||
|
|
||||||
|
echo "Creating package with the name $output..."
|
||||||
|
|
||||||
|
if [ -d files ]; then
|
||||||
|
echo "files/ directory found"
|
||||||
|
else
|
||||||
|
echo "files/ directory not found in $PWD"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -f pkg.info ]; then
|
||||||
|
echo "pkg.info file found"
|
||||||
|
else
|
||||||
|
echo "pkg.info file not found in $PWD"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Creating $output.bpm package..."
|
||||||
|
|
||||||
|
tar -czf $output.bpm files/ pkg.info
|
4
test_packages/bpm-utils/pkg.info
Normal file
4
test_packages/bpm-utils/pkg.info
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
name: bpm-utils
|
||||||
|
description: Utilities to create BPM packages
|
||||||
|
version: 1.0.0
|
||||||
|
type: binary
|
BIN
test_packages/bpm/bpm.bpm
Normal file
BIN
test_packages/bpm/bpm.bpm
Normal file
Binary file not shown.
BIN
test_packages/bpm/files/usr/bin/bpm
Executable file
BIN
test_packages/bpm/files/usr/bin/bpm
Executable file
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.3
|
version: 0.0.5
|
||||||
type: binary
|
type: binary
|
BIN
test_packages/hello/hello.bpm
Normal file
BIN
test_packages/hello/hello.bpm
Normal file
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-1
|
version: 1.0
|
||||||
type: binary
|
type: binary
|
118
version.go
118
version.go
@ -1,118 +0,0 @@
|
|||||||
// 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