- Added hard link extraction support
- Can now add comments to pkg.info files - Moved source package temp directory from /tmp to /var/tmp to allow for larger packages to be compiled
This commit is contained in:
parent
036578e652
commit
43c4a626f1
@ -22,6 +22,8 @@ type PackageInfo struct {
|
|||||||
Name string
|
Name string
|
||||||
Description string
|
Description string
|
||||||
Version string
|
Version string
|
||||||
|
Url string
|
||||||
|
License string
|
||||||
Arch string
|
Arch string
|
||||||
Type string
|
Type string
|
||||||
Depends []string
|
Depends []string
|
||||||
@ -29,6 +31,39 @@ type PackageInfo struct {
|
|||||||
Provides []string
|
Provides []string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetPackageInfoRaw(filename string) (string, error) {
|
||||||
|
if _, err := os.Stat(filename); os.IsNotExist(err) {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
file, err := os.Open(filename)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
archive, err := gzip.NewReader(file)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
tr := tar.NewReader(archive)
|
||||||
|
for {
|
||||||
|
header, err := tr.Next()
|
||||||
|
if err == io.EOF {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
if header.Name == "pkg.info" {
|
||||||
|
bs, _ := io.ReadAll(tr)
|
||||||
|
err := file.Close()
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return string(bs), nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "", errors.New("pkg.info not found in archive")
|
||||||
|
}
|
||||||
|
|
||||||
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
|
||||||
@ -71,6 +106,8 @@ func ReadPackageInfo(contents string, defaultValues bool) (*PackageInfo, error)
|
|||||||
Name: "",
|
Name: "",
|
||||||
Description: "",
|
Description: "",
|
||||||
Version: "",
|
Version: "",
|
||||||
|
Url: "",
|
||||||
|
License: "",
|
||||||
Arch: "",
|
Arch: "",
|
||||||
Type: "",
|
Type: "",
|
||||||
Depends: nil,
|
Depends: nil,
|
||||||
@ -82,6 +119,9 @@ func ReadPackageInfo(contents string, defaultValues bool) (*PackageInfo, error)
|
|||||||
if len(strings.TrimSpace(line)) == 0 {
|
if len(strings.TrimSpace(line)) == 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
if line[0] == '#' {
|
||||||
|
continue
|
||||||
|
}
|
||||||
split := strings.SplitN(line, ":", 2)
|
split := strings.SplitN(line, ":", 2)
|
||||||
if len(split) != 2 {
|
if len(split) != 2 {
|
||||||
return nil, errors.New("invalid pkg.info format at line " + strconv.Itoa(num))
|
return nil, errors.New("invalid pkg.info format at line " + strconv.Itoa(num))
|
||||||
@ -95,6 +135,10 @@ func ReadPackageInfo(contents string, defaultValues bool) (*PackageInfo, error)
|
|||||||
pkgInfo.Description = split[1]
|
pkgInfo.Description = split[1]
|
||||||
case "version":
|
case "version":
|
||||||
pkgInfo.Version = split[1]
|
pkgInfo.Version = split[1]
|
||||||
|
case "url":
|
||||||
|
pkgInfo.Url = split[1]
|
||||||
|
case "license":
|
||||||
|
pkgInfo.License = split[1]
|
||||||
case "architecture":
|
case "architecture":
|
||||||
pkgInfo.Arch = split[1]
|
pkgInfo.Arch = split[1]
|
||||||
case "type":
|
case "type":
|
||||||
@ -131,6 +175,12 @@ func CreateInfoFile(pkgInfo PackageInfo) string {
|
|||||||
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"
|
||||||
|
if pkgInfo.Url != "" {
|
||||||
|
ret = ret + "url: " + pkgInfo.Url + "\n"
|
||||||
|
}
|
||||||
|
if pkgInfo.License != "" {
|
||||||
|
ret = ret + "license: " + pkgInfo.License + "\n"
|
||||||
|
}
|
||||||
ret = ret + "architecture: " + pkgInfo.Arch + "\n"
|
ret = ret + "architecture: " + pkgInfo.Arch + "\n"
|
||||||
ret = ret + "type: " + pkgInfo.Type + "\n"
|
ret = ret + "type: " + pkgInfo.Type + "\n"
|
||||||
if len(pkgInfo.Depends) > 0 {
|
if len(pkgInfo.Depends) > 0 {
|
||||||
@ -168,7 +218,9 @@ func InstallPackage(filename, installDir string, force bool) error {
|
|||||||
return errors.New("Could not resolve all dependencies. Missing " + strings.Join(unresolved, ", "))
|
return errors.New("Could not resolve all dependencies. Missing " + strings.Join(unresolved, ", "))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if pkgInfo.Type == "binary" {
|
if pkgInfo.Type == "binary" {
|
||||||
|
seenHardlinks := make(map[string]string)
|
||||||
for {
|
for {
|
||||||
header, err := tr.Next()
|
header, err := tr.Next()
|
||||||
if err == io.EOF {
|
if err == io.EOF {
|
||||||
@ -190,6 +242,10 @@ func InstallPackage(filename, installDir string, force bool) error {
|
|||||||
fmt.Println("Creating Directory: " + extractFilename)
|
fmt.Println("Creating Directory: " + extractFilename)
|
||||||
}
|
}
|
||||||
case tar.TypeReg:
|
case tar.TypeReg:
|
||||||
|
err := os.Remove(extractFilename)
|
||||||
|
if err != nil && !os.IsNotExist(err) {
|
||||||
|
return err
|
||||||
|
}
|
||||||
outFile, err := os.Create(extractFilename)
|
outFile, err := os.Create(extractFilename)
|
||||||
fmt.Println("Creating File: " + extractFilename)
|
fmt.Println("Creating File: " + extractFilename)
|
||||||
files = append(files, strings.TrimPrefix(header.Name, "files/"))
|
files = append(files, strings.TrimPrefix(header.Name, "files/"))
|
||||||
@ -207,17 +263,36 @@ func InstallPackage(filename, installDir string, force bool) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
case tar.TypeSymlink:
|
case tar.TypeSymlink:
|
||||||
fmt.Println("Creating Symlink: "+extractFilename, " -> "+header.Linkname)
|
fmt.Println("Creating Symlink: " + extractFilename + " -> " + header.Linkname)
|
||||||
files = append(files, strings.TrimPrefix(header.Name, "files/"))
|
files = append(files, strings.TrimPrefix(header.Name, "files/"))
|
||||||
err := os.Symlink(header.Linkname, extractFilename)
|
err := os.Remove(extractFilename)
|
||||||
|
if err != nil && !os.IsNotExist(err) {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = os.Symlink(header.Linkname, extractFilename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
case tar.TypeLink:
|
||||||
|
fmt.Println("Detected Hard Link: " + extractFilename + " -> " + path.Join(installDir, strings.TrimPrefix(header.Linkname, "files/")))
|
||||||
|
files = append(files, strings.TrimPrefix(header.Name, "files/"))
|
||||||
|
seenHardlinks[extractFilename] = path.Join(strings.TrimPrefix(header.Linkname, "files/"))
|
||||||
|
err := os.Remove(extractFilename)
|
||||||
|
if err != nil && !os.IsNotExist(err) {
|
||||||
|
return err
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return errors.New("ExtractTarGz: unknown type: " + strconv.Itoa(int(header.Typeflag)) + " in " + extractFilename)
|
return errors.New("ExtractTarGz: unknown type: " + strconv.Itoa(int(header.Typeflag)) + " in " + extractFilename)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for extractFilename, destination := range seenHardlinks {
|
||||||
|
fmt.Println("Creating Hard Link: " + extractFilename + " -> " + path.Join(installDir, destination))
|
||||||
|
err := os.Link(path.Join(installDir, destination), extractFilename)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
} else if pkgInfo.Type == "source" {
|
} else if pkgInfo.Type == "source" {
|
||||||
for {
|
for {
|
||||||
header, err := tr.Next()
|
header, err := tr.Next()
|
||||||
@ -232,7 +307,7 @@ func InstallPackage(filename, installDir string, force bool) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
temp, err := os.MkdirTemp("/tmp/", "bpm_source-")
|
temp, err := os.MkdirTemp("/var/tmp/", "bpm_source-")
|
||||||
fmt.Println("Creating temp directory at: " + temp)
|
fmt.Println("Creating temp directory at: " + temp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -364,7 +439,11 @@ func InstallPackage(filename, installDir string, force bool) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
_, err = f.WriteString(CreateInfoFile(*pkgInfo))
|
raw, err := GetPackageInfoRaw(filename)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_, err = f.WriteString(raw)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -441,8 +520,25 @@ func CheckDependencies(pkgInfo *PackageInfo, rootDir string) []string {
|
|||||||
if !item.IsDir() {
|
if !item.IsDir() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if slices.Contains(unresolved, item.Name()) {
|
_, err := os.Stat(path.Join(installedDir, item.Name(), "/info"))
|
||||||
unresolved = stringSliceRemove(unresolved, item.Name())
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
bs, err := os.ReadFile(path.Join(installedDir, item.Name(), "/info"))
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
info, err := ReadPackageInfo(string(bs), false)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if slices.Contains(unresolved, info.Name) {
|
||||||
|
unresolved = stringSliceRemove(unresolved, info.Name)
|
||||||
|
}
|
||||||
|
for _, prov := range info.Provides {
|
||||||
|
if slices.Contains(unresolved, prov) {
|
||||||
|
unresolved = stringSliceRemove(unresolved, prov)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return unresolved
|
return unresolved
|
||||||
@ -464,8 +560,25 @@ func CheckMakeDependencies(pkgInfo *PackageInfo, rootDir string) []string {
|
|||||||
if !item.IsDir() {
|
if !item.IsDir() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if slices.Contains(unresolved, item.Name()) {
|
_, err := os.Stat(path.Join(installedDir, item.Name(), "/info"))
|
||||||
unresolved = stringSliceRemove(unresolved, item.Name())
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
bs, err := os.ReadFile(path.Join(installedDir, item.Name(), "/info"))
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
info, err := ReadPackageInfo(string(bs), false)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if slices.Contains(unresolved, info.Name) {
|
||||||
|
unresolved = stringSliceRemove(unresolved, info.Name)
|
||||||
|
}
|
||||||
|
for _, prov := range info.Provides {
|
||||||
|
if slices.Contains(unresolved, prov) {
|
||||||
|
unresolved = stringSliceRemove(unresolved, prov)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return unresolved
|
return unresolved
|
||||||
|
36
main.go
36
main.go
@ -17,7 +17,7 @@ import (
|
|||||||
/* A simple-to-use package manager */
|
/* A simple-to-use package manager */
|
||||||
/* ---------------------------------- */
|
/* ---------------------------------- */
|
||||||
|
|
||||||
var bpmVer = "0.0.8"
|
var bpmVer = "0.0.9"
|
||||||
var rootDir = "/"
|
var rootDir = "/"
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@ -168,6 +168,21 @@ func resolveCommand() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if !slices.Contains(flags, "y") {
|
||||||
|
reader := bufio.NewReader(os.Stdin)
|
||||||
|
if pkgInfo.Type == "source" {
|
||||||
|
fmt.Print("Would you like to view the source.sh file of this package? [Y\\n] ")
|
||||||
|
text, _ := reader.ReadString('\n')
|
||||||
|
if strings.TrimSpace(strings.ToLower(text)) != "n" && strings.TrimSpace(strings.ToLower(text)) != "no" {
|
||||||
|
script, err := bpm_utils.GetSourceScript(file)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Could not read source script\nError: %s\n", err)
|
||||||
|
}
|
||||||
|
fmt.Println(script)
|
||||||
|
fmt.Println("-------EOF-------")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if bpm_utils.IsPackageInstalled(pkgInfo.Name, rootDir) {
|
if bpm_utils.IsPackageInstalled(pkgInfo.Name, rootDir) {
|
||||||
if !slices.Contains(flags, "y") {
|
if !slices.Contains(flags, "y") {
|
||||||
installedInfo := bpm_utils.GetPackageInfo(pkgInfo.Name, rootDir, false)
|
installedInfo := bpm_utils.GetPackageInfo(pkgInfo.Name, rootDir, false)
|
||||||
@ -194,20 +209,7 @@ func resolveCommand() {
|
|||||||
}
|
}
|
||||||
} else if !slices.Contains(flags, "y") {
|
} else if !slices.Contains(flags, "y") {
|
||||||
reader := bufio.NewReader(os.Stdin)
|
reader := bufio.NewReader(os.Stdin)
|
||||||
if pkgInfo.Type == "source" {
|
|
||||||
fmt.Print("Would you like to view the source.sh file of this package? [Y\\n]")
|
|
||||||
text, _ := reader.ReadString('\n')
|
|
||||||
if strings.TrimSpace(strings.ToLower(text)) != "n" && strings.TrimSpace(strings.ToLower(text)) != "no" {
|
|
||||||
script, err := bpm_utils.GetSourceScript(file)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("Could not read source script\nError: %s\n", err)
|
|
||||||
}
|
|
||||||
fmt.Println(script)
|
|
||||||
fmt.Println("-------EOF-------")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fmt.Printf("Do you wish to %s this package? [y\\N] ", verb)
|
fmt.Printf("Do you wish to %s this package? [y\\N] ", verb)
|
||||||
|
|
||||||
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)
|
||||||
@ -217,9 +219,15 @@ func resolveCommand() {
|
|||||||
|
|
||||||
err = bpm_utils.InstallPackage(file, rootDir, slices.Contains(flags, "f"))
|
err = bpm_utils.InstallPackage(file, rootDir, slices.Contains(flags, "f"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
if pkgInfo.Type == "source" {
|
||||||
|
fmt.Println("** It is recommended you delete the temporary bpm folder in /var/tmp **")
|
||||||
|
}
|
||||||
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)
|
||||||
|
if pkgInfo.Type == "source" {
|
||||||
|
fmt.Println("** It is recommended you delete the temporary bpm folder in /var/tmp **")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
case remove:
|
case remove:
|
||||||
flags, i := resolveFlags()
|
flags, i := resolveFlags()
|
||||||
|
Binary file not shown.
@ -1,5 +1,7 @@
|
|||||||
name: bpm-utils
|
name: bpm-utils
|
||||||
description: Utilities to create BPM packages
|
description: Utilities to create BPM packages
|
||||||
version: 1.0.0
|
version: 1.0.0
|
||||||
|
url: https://gitlab.com/bubble-package-manager/bpm/
|
||||||
|
license: GPL3
|
||||||
architecture: x86_64
|
architecture: x86_64
|
||||||
type: binary
|
type: binary
|
Binary file not shown.
Binary file not shown.
@ -1,5 +1,7 @@
|
|||||||
name: bpm
|
name: bpm
|
||||||
description: The Bubble Package Manager
|
description: The Bubble Package Manager
|
||||||
version: 0.0.8
|
version: 0.0.9
|
||||||
|
url: https://gitlab.com/bubble-package-manager/bpm/
|
||||||
|
license: GPL3
|
||||||
architecture: x86_64
|
architecture: x86_64
|
||||||
type: binary
|
type: binary
|
||||||
|
Binary file not shown.
Binary file not shown.
@ -1,5 +1,8 @@
|
|||||||
name: htop
|
name: htop
|
||||||
description: An interactive process viewer
|
description: An interactive process viewer
|
||||||
version: 3.3.0
|
version: 3.3.0
|
||||||
|
url: https://github.com/htop-dev/htop
|
||||||
|
license: GPL2
|
||||||
architecture: x86_64
|
architecture: x86_64
|
||||||
type: source
|
type: source
|
||||||
|
#make_depends: git
|
@ -1,5 +1,5 @@
|
|||||||
# This file is read and executed by BPM to compile htop. It will run inside a temporary folder in /tmp during execution
|
# This file is read and executed by BPM to compile htop. It will run inside a temporary folder in /tmp during execution
|
||||||
echo "Building htop..."
|
echo "Compiling htop..."
|
||||||
# Creating 'source' directory
|
# Creating 'source' directory
|
||||||
mkdir source
|
mkdir source
|
||||||
# Cloning the git repository into the 'source' directory
|
# Cloning the git repository into the 'source' directory
|
||||||
|
Loading…
x
Reference in New Issue
Block a user