4 Commits
9 changed files with 313 additions and 232 deletions
+7 -6
View File
@@ -77,7 +77,7 @@ mkdir files
5) Either copy the bpm-create script from the bpm-utils test package into your /usr/local/bin directory or install the bpm-utils.bpm package
6) Run the following
```
bpm-create <filename_without_extension>
bpm-create <filename.bpm>
```
7) It's done! You now hopefully have a working BPM package!
### Source Packages
@@ -85,10 +85,11 @@ bpm-create <filename_without_extension>
```
touch source.sh
```
4) You are able to run bash code in this file. BPM will extract this file in a directory under /tmp and it will be ran there
5) Your goal is to download your program's source code with either git, wget, curl, etc. and put the binaries under a folder called 'output' in the root of the temp directory. There is a simple example script with helpful comments in the htop-src test package
6) As of this moment there is no script to automate package compression like for binary packages. You will need to create the archive manually
4) If you would like to bundle patches or other files with your source package create a 'source-files' directory and place your files in there. They will be extracted to the same location as the source.sh file during compilation
5) You are able to run bash code in source.sh. BPM will extract this file in a directory under /tmp and it will be run there
6) Your goal is to download your program's source code with either git, wget, curl, etc. and put the binaries under a folder called 'output' in the root of the temp directory. There is a simple example script with helpful comments in the htop-src test package
7) When you are done making your source.sh script run the following to create a package archive
```
tar -czvf my_package-src.bpm pkg.info source.sh
bpm-create <filename.bpm>
```
7) That's it! Your source package should now be compiling correctly!
8) That's it! Your source package should now be compiling correctly!
+110 -60
View File
@@ -8,7 +8,6 @@ import (
"fmt"
"io"
"io/fs"
"log"
"os"
"os/exec"
"path"
@@ -304,19 +303,6 @@ func InstallPackage(filename, installDir string, force, binaryPkgFromSrc, keepTe
}
}
} else if pkgInfo.Type == "source" {
for {
header, err := tr.Next()
if err == io.EOF {
break
}
if err != nil {
return err
}
if header.Name == "source.sh" {
bs, err := io.ReadAll(tr)
if err != nil {
return err
}
temp := "/var/tmp/bpm_source-" + pkgInfo.Name
err = os.RemoveAll(temp)
if err != nil {
@@ -327,16 +313,97 @@ func InstallPackage(filename, installDir string, force, binaryPkgFromSrc, keepTe
if err != nil {
return err
}
for {
header, err := tr.Next()
if err == io.EOF {
break
}
if err != nil {
return err
}
if strings.HasPrefix(header.Name, "source-files/") && header.Name != "source-files/" {
extractFilename := path.Join(temp, strings.TrimPrefix(header.Name, "source-files/"))
switch header.Typeflag {
case tar.TypeDir:
if err := os.Mkdir(extractFilename, 0755); err != nil {
if !os.IsExist(err) {
return err
}
} else {
fmt.Println("Creating Directory: " + extractFilename)
}
case tar.TypeReg:
err := os.Remove(extractFilename)
if err != nil && !os.IsNotExist(err) {
return err
}
outFile, err := os.Create(extractFilename)
fmt.Println("Creating File: " + extractFilename)
if err != nil {
return err
}
if _, err := io.Copy(outFile, tr); err != nil {
return err
}
if err := os.Chmod(extractFilename, header.FileInfo().Mode()); err != nil {
return err
}
err = outFile.Close()
if err != nil {
return err
}
case tar.TypeSymlink:
fmt.Println("Skipping symlink (Bundling symlinks in source packages is not supported)")
case tar.TypeLink:
fmt.Println("Skipping hard link (Bundling hard links in source packages is not supported)")
default:
return errors.New("ExtractTarGz: unknown type: " + strconv.Itoa(int(header.Typeflag)) + " in " + extractFilename)
}
}
if header.Name == "source.sh" {
bs, err := io.ReadAll(tr)
if err != nil {
return err
}
err = os.WriteFile(path.Join(temp, "source.sh"), bs, 0644)
if err != nil {
return err
}
}
}
if _, err := os.Stat(path.Join(temp, "source.sh")); os.IsNotExist(err) {
return errors.New("source.sh file could not be found in the temporary build directory")
}
if err != nil {
return err
}
fmt.Println("Running source.sh file...")
cmd := exec.Command("/usr/bin/sh", "source.sh")
if err != nil {
return err
}
cmd := exec.Command("/bin/bash", "-e", "source.sh")
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.Dir = temp
cmd.Env = os.Environ()
cmd.Env = append(cmd.Env, fmt.Sprintf("BPM_PKG_NAME=%s", pkgInfo.Name))
cmd.Env = append(cmd.Env, fmt.Sprintf("BPM_PKG_DESC=%s", pkgInfo.Description))
cmd.Env = append(cmd.Env, fmt.Sprintf("BPM_PKG_VERSION=%s", pkgInfo.Version))
cmd.Env = append(cmd.Env, fmt.Sprintf("BPM_PKG_URL=%s", pkgInfo.Url))
depends := make([]string, len(pkgInfo.Depends))
copy(depends, pkgInfo.Depends)
for i := 0; i < len(depends); i++ {
depends[i] = fmt.Sprintf("\"%s\"", depends[i])
}
makeDepends := make([]string, len(pkgInfo.MakeDepends))
copy(makeDepends, pkgInfo.MakeDepends)
for i := 0; i < len(makeDepends); i++ {
makeDepends[i] = fmt.Sprintf("\"%s\"", makeDepends[i])
}
cmd.Env = append(cmd.Env, fmt.Sprintf("BPM_PKG_DEPENDS=(%s)", strings.Join(depends, " ")))
cmd.Env = append(cmd.Env, fmt.Sprintf("BPM_PKG_MAKE_DEPENDS=(%s)", strings.Join(makeDepends, " ")))
cmd.Env = append(cmd.Env, "BPM_PKG_TYPE=source")
err = cmd.Run()
if err != nil {
return err
@@ -432,7 +499,7 @@ func InstallPackage(filename, installDir string, force, binaryPkgFromSrc, keepTe
return err
}
sed := fmt.Sprintf("s/%s/files/", strings.Replace(strings.TrimPrefix(path.Join(temp, "/output/"), "/"), "/", `\/`, -1))
cmd := exec.Command("/usr/bin/tar", "-czvf", compiledInfo.Name+".bpm", "pkg.info", path.Join(temp, "/output/"), "--transform", sed)
cmd := exec.Command("/usr/bin/tar", "-czvf", compiledInfo.Name+"-"+compiledInfo.Version+".bpm", "pkg.info", path.Join(temp, "/output/"), "--transform", sed)
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
@@ -456,8 +523,6 @@ func InstallPackage(filename, installDir string, force, binaryPkgFromSrc, keepTe
if len(files) == 0 {
return errors.New("no output files for source package. Cancelling package installation")
}
}
}
} else {
return errors.New("Unknown package type: " + pkgInfo.Type)
}
@@ -526,7 +591,33 @@ func InstallPackage(filename, installDir string, force, binaryPkgFromSrc, keepTe
if len(filesDiff) != 0 {
fmt.Println("Removing obsolete files")
for _, f := range filesDiff {
fmt.Println("Removing: " + path.Join(installedDir, f))
f = path.Join(installDir, f)
stat, err := os.Lstat(f)
if os.IsNotExist(err) {
continue
}
if err != nil {
return err
}
if stat.IsDir() {
dir, err := os.ReadDir(f)
if err != nil {
return err
}
if len(dir) == 0 {
fmt.Println("Removing: " + f)
err := os.Remove(f)
if err != nil {
return err
}
}
} else {
fmt.Println("Removing: " + f)
err := os.Remove(f)
if err != nil {
return err
}
}
}
}
return nil
@@ -783,44 +874,3 @@ func RemovePackage(pkg, rootDir string) error {
fmt.Println("Removing: " + pkgDir)
return nil
}
func FixInstalledPackages(rootDir string) (map[string]error, int) {
var errs map[string]error
totalFixed := 0
pkgs, err := GetInstalledPackages(rootDir)
if err != nil {
log.Fatalf("Could not check if installed package info files are formatted correctly\nError: %s", err.Error())
}
for _, pkg := range pkgs {
fixed := false
pkgInfo := GetPackageInfo(pkg, "/", true)
if pkgInfo.Name == "" {
errs[pkg] = errors.New("this package contains no name")
continue
}
if pkgInfo.Description == "" {
pkgInfo.Description = "Default Description"
fixed = true
}
if pkgInfo.Version == "" {
errs[pkg] = errors.New("this package contains no version")
continue
}
if pkgInfo.Arch == "" {
pkgInfo.Arch = GetArch()
fixed = true
}
if pkgInfo.Type == "" {
errs[pkg] = errors.New("this package contains no type")
continue
}
if fixed {
totalFixed++
}
err := setPackageInfo(pkg, CreateInfoFile(*pkgInfo), rootDir)
if err != nil {
log.Fatalf("Could not check if installed package info files are formatted correctly\nError: %s", err.Error())
}
}
return errs, totalFixed
}
+74 -51
View File
@@ -7,6 +7,8 @@ import (
"fmt"
"log"
"os"
"path/filepath"
"slices"
"strings"
)
@@ -15,7 +17,7 @@ import (
/* A simple-to-use package manager */
/* ---------------------------------- */
var bpmVer = "0.1.1"
var bpmVer = "0.1.5"
var subcommand = "help"
var subcommandArgs []string
@@ -43,7 +45,7 @@ const (
list
install
remove
cleanup
file
)
func getCommandType() commandType {
@@ -58,12 +60,11 @@ func getCommandType() commandType {
return install
case "remove":
return remove
case "cleanup":
return cleanup
case "file":
return file
default:
return help
}
}
func resolveCommand() {
@@ -251,6 +252,53 @@ func resolveCommand() {
}
fmt.Printf("Package (%s) was successfully removed!\n", pkgInfo.Name)
}
case file:
files := subcommandArgs
if len(files) == 0 {
fmt.Println("No files were given to get which packages manage it")
return
}
for _, file := range files {
absFile, err := filepath.Abs(file)
if err != nil {
log.Fatalf("Could not get absolute path of %s", file)
}
stat, err := os.Stat(absFile)
if os.IsNotExist(err) {
log.Fatalf(absFile + " does not exist!")
}
pkgs, err := bpm_utils.GetInstalledPackages(rootDir)
if err != nil {
log.Fatalf("Could not get installed packages. Error %s", err.Error())
}
if !strings.HasPrefix(absFile, rootDir) {
log.Fatalf("Could not get relative path of %s to root path", absFile)
}
absFile, err = filepath.Rel(rootDir, absFile)
if err != nil {
log.Fatalf("Could not get relative path of %s to root path", absFile)
}
absFile = strings.TrimPrefix(absFile, "/")
if stat.IsDir() {
absFile = absFile + "/"
}
var pkgList []string
for _, pkg := range pkgs {
if slices.Contains(bpm_utils.GetPackageFiles(pkg, rootDir), absFile) {
pkgList = append(pkgList, pkg)
}
}
if len(pkgList) == 0 {
fmt.Println(absFile + " is not managed by any packages")
} else {
fmt.Println(absFile + " is managed by the following packages:")
for _, pkg := range pkgList {
fmt.Println("- " + pkg)
}
}
}
default:
printHelp()
}
@@ -263,18 +311,23 @@ func printHelp() {
fmt.Println("-> flags will be read if passed right after the subcommand otherwise they will be read as subcommand arguments")
fmt.Println("\033[1m\\ Command List /\033[0m")
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 [-n, -l] | lists all installed packages")
fmt.Println("-> bpm info [-R] | shows information on an installed package")
fmt.Println(" -R=<root_path> lets you define the root path which will be used")
fmt.Println("-> bpm list [-R, -n, -l] | lists all installed packages")
fmt.Println(" -R=<root_path> lets you define the root path which will be used")
fmt.Println(" -n shows the number of packages")
fmt.Println(" -l lists package names only")
fmt.Println("-> bpm install [-y, -f, -b] <files...> | installs the following files")
fmt.Println("-> bpm install [-R, -y, -f, -b] <files...> | installs the following files")
fmt.Println(" -R=<root_path> lets you define the root path which will be used")
fmt.Println(" -y skips the confirmation prompt")
fmt.Println(" -f skips dependency and architecture checking")
fmt.Println(" -b creates a binary package for a source package after compilation and saves it in /var/lib/bpm/compiled")
fmt.Println(" -k keeps the temp directory created by BPM after source package installation")
fmt.Println("-> bpm remove [-y] <packages...> | removes the following packages")
fmt.Println("-> bpm remove [-R, -y] <packages...> | removes the following packages")
fmt.Println(" -R=<root_path> lets you define the root path which will be used")
fmt.Println(" -y skips the confirmation prompt")
//fmt.Println("-> bpm cleanup | removes all unneeded dependencies")
fmt.Println("-> bpm file [-R] <files...> | shows what packages the following packages are managed by")
fmt.Println(" -R=<root_path> lets you define the root path which will be used")
fmt.Println("\033[1m----------------\033[0m")
}
@@ -303,6 +356,11 @@ func resolveFlags() {
removeFlagSet.StringVar(&rootDir, "R", "/", "Set the destination root")
removeFlagSet.BoolVar(&yesAll, "y", false, "Skip confirmation prompts")
removeFlagSet.Usage = printHelp
// File flags
// Remove flags
fileFlagSet := flag.NewFlagSet("Remove flags", flag.ExitOnError)
fileFlagSet.StringVar(&rootDir, "R", "/", "Set the destination root")
fileFlagSet.Usage = printHelp
if len(os.Args[1:]) <= 0 {
subcommand = "help"
} else {
@@ -332,47 +390,12 @@ func resolveFlags() {
return
}
subcommandArgs = removeFlagSet.Args()
} else if getCommandType() == file {
err := fileFlagSet.Parse(subcommandArgs)
if err != nil {
return
}
subcommandArgs = fileFlagSet.Args()
}
}
}
/*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{"l", "n"}
if !slices.Contains(v[:], f) {
log.Fatalf("Invalid flag " + flag)
}
ret = append(ret, f)
case install:
v := [...]string{"y", "f", "b", "k"}
if !slices.Contains(v[:], f) {
log.Fatalf("Invalid flag " + flag)
}
ret = append(ret, f)
case remove:
v := [...]string{"y", "r"}
if !slices.Contains(v[:], f) {
log.Fatalf("Invalid flag " + flag)
}
ret = append(ret, f)
case info:
v := [...]string{"r"}
if !slices.Contains(v[:], f) {
log.Fatalf("Invalid flag " + flag)
}
ret = append(ret, f)
}
} else {
break
}
}
return ret, len(ret)
}*/
Binary file not shown.
@@ -7,7 +7,7 @@ fi
output=$1
if [[ ! "$output" =~ ^[a-zA-Z0-9_-]{1,}$ ]]; then
if [[ ! "$output" =~ ^[a-z.A-Z0-9_-]{1,}$ ]]; then
echo "Invalid output name! The name must only contain letters, numbers, hyphens or underscores!"
exit 1
fi
@@ -22,6 +22,9 @@ else
if [ -f source.sh ]; then
type="source"
echo "source.sh file found"
if [ -d source-files ]; then
echo "source-files/ directory found"
fi
else
echo "files/ directory or source.sh file not found in $PWD"
exit 1
@@ -35,10 +38,14 @@ else
exit 1
fi
echo "Creating $type package as $output.bpm"
echo "Creating $type package as $output"
if [[ "$type" == "binary" ]]; then
tar -czf "$output".bpm files/ pkg.info
tar -czf "$output" files/ pkg.info
else
tar -czf "$output".bpm source.sh pkg.info
if [ -d source-files ]; then
tar -czf "$output" source.sh source-files/ pkg.info
else
tar -czf "$output" source.sh pkg.info
fi
fi
+1 -1
View File
@@ -1,6 +1,6 @@
name: bpm-utils
description: Utilities to create BPM packages
version: 1.2.0
version: 1.3.0
url: https://gitlab.com/bubble-package-manager/bpm/
license: GPL3
architecture: x86_64
Binary file not shown.
Binary file not shown.
+1 -1
View File
@@ -1,6 +1,6 @@
name: bpm
description: The Bubble Package Manager
version: 0.1.1
version: 0.1.5
url: https://gitlab.com/bubble-package-manager/bpm/
license: GPL3
architecture: x86_64