12 Commits
Author SHA1 Message Date
EnumDev 4217626dde Update passed flag to bpm 2025-10-05 20:00:05 +03:00
EnumDevandGitHub d7da13034c Merge pull request #1 from EnumeratedDev/go_rewrite
Rewrite bpm-utils in go
2025-10-05 09:37:55 +00:00
EnumDev cdb044d751 Update pkg.info format 2025-10-05 12:14:54 +03:00
EnumDev 60b0f4489e Improve git branch checksum fetching 2025-10-05 11:00:15 +03:00
EnumDev 65c32d628f Update repository version checking messages 2025-10-03 14:18:53 +03:00
EnumDev 4ff4a74fa3 Improve package info parsing 2025-09-29 10:35:54 +03:00
EnumDev f6ef60aa40 Add cargo template 2025-09-28 18:24:35 +03:00
EnumDev 9625b5d7af Use drone/envsubst module for bash variable expansion 2025-09-28 12:39:30 +03:00
EnumDev d881ac31c3 Update README.md 2025-09-27 21:32:07 +03:00
EnumDev 96a39a6b40 Update default pkg.info content 2025-09-27 21:19:13 +03:00
EnumDev 7a63ad6388 Update templates 2025-09-27 21:18:39 +03:00
EnumDev 10f918034a Add 'update-checksums' flag 2025-09-27 13:39:54 +03:00
20 changed files with 304 additions and 128 deletions
+19 -7
View File
@@ -8,7 +8,7 @@ BPM Utils provides a number of different helper commands for creating and mainta
## Provided utilities ## Provided utilities
- bpm-setup (Sets up directories for BPM source package creation) - bpm-setup (Sets up directories for BPM source package creation)
- bpm-repo (Allows for easy management of multiple-package repositories) - bpm-repo (Allows for easy management of multiple-package repositories)
- bpm-package (Turns a BPM package directory into a .bpm archive) - bpm-package (Turns a BPM source package directory into a .bpm archive)
## Installation ## Installation
#### Using a package manager #### Using a package manager
@@ -33,7 +33,7 @@ Creating a package for BPM with these utilities is simple
bpm-setup -D my_package bpm-setup -D my_package
``` ```
2) This will create a directory named `my_package` containing all files required for bpm package creation 2) This will create a directory named `my_package` containing all files required for bpm package creation
3) You may wish to edit the pkg.info descriptor file inside the newly created directory to include dependencies or add/change other information. Here's an example of what a descriptor file could look like 3) You may wish to edit the pkg.info metedata file inside the newly created directory to include dependencies or add/change other information. Here's an example of what a metedata file could look like
```yaml ```yaml
name: my_package name: my_package
description: My package's description description: My package's description
@@ -42,11 +42,23 @@ revision: 2 (Optional)
url: https://www.my-website.com/ (Optional) url: https://www.my-website.com/ (Optional)
license: MyLicense (Optional) license: MyLicense (Optional)
architecture: x86_64 architecture: x86_64
depends: ["dependency1","dependency2"] (Optional)
optional_depends: ["optional_depend1","optional_depend2"] (Optional)
make_depends: ["make_depend1","make_depend2"] (Optional)
keep: ["etc/my_config.conf"] (Optional)
type: source type: source
depends:
- dependency1
- dependency2
optional_depends:
- optional_depend1
- optional_depend2
make_depends:
- make_depend1
- make_depend2
keep:
- etc/my_config.conf
downloads:
- url: https://wwww.my-url.com/file.tar.gz
extract_strip_components: 1
extract_to_bpm_source: true
checksum: 9d19c8884cb22a594ba06a4caa6a3088e15ddfd4f3ede8c3b9e8f5cbb5a4a7a8
``` ```
4) If you would like to bundle patches or other files with your package place them in the 'source-files' directory. They will be extracted to the same location as the source.sh file during compilation 4) If you would like to bundle patches or other files with your package place them in the 'source-files' directory. They will be extracted to the same location as the source.sh file during compilation
@@ -55,4 +67,4 @@ type: source
``` ```
bpm-package bpm-package
``` ```
7) The `bpm-package` command will output a binary bpm archive which can be installed by BPM using `bpm install <file.bpm>`. If you are operating inside a BPM repository created using `bpm-repo` the file will automatically be moved to the binary subdirectory of your package repository 7) The `bpm-package` command will output a source bpm archive (and binary if passed the '-c' flag) which can be installed by BPM using `bpm install <file.bpm>`. If you are operating inside a BPM repository created using `bpm-repo` the file will automatically be moved to the binary subdirectory of your package repository
+32
View File
@@ -0,0 +1,32 @@
# This is the source.sh script. It is executed by BPM in a temporary directory when compiling a source package
# BPM Expects the source code to be extracted into the automatically created 'source' directory which can be accessed using $BPM_SOURCE
# BPM Expects the output files to be present in the automatically created 'output' directory which can be accessed using $BPM_OUTPUT
# The prepare function is executed in the root of the temp directory
# This function is used for putting downloaded files to the correct location or applying patches
prepare() {
cd "$BPM_SOURCE"
# Fetch cargo dependencies
cargo fetch --locked --target "$(rustc -vV | sed -n 's/host: //p')"
}
# The build function is executed in the source directory
# This function is used to compile the source code
build() {
cargo build --release --frozen --workspace
}
# The check function is executed in the source directory
# This function is used to run tests to verify the package has been compiled correctly
check() {
cargo test --frozen
}
# The package function is executed in the source directory
# This function is used to move the compiled files into the output directory
package() {
find target/release -maxdepth 1 -type f -executable -exec install -Dm755 -t "$BPM_OUTPUT"/usr/bin {} +
# Install package license
install -Dm644 "$BPM_SOURCE"/LICENSE "$BPM_OUTPUT"/usr/share/licenses/$NAME/LICENSE
}
+2 -6
View File
@@ -2,14 +2,10 @@
# BPM Expects the source code to be extracted into the automatically created 'source' directory which can be accessed using $BPM_SOURCE # BPM Expects the source code to be extracted into the automatically created 'source' directory which can be accessed using $BPM_SOURCE
# BPM Expects the output files to be present in the automatically created 'output' directory which can be accessed using $BPM_OUTPUT # BPM Expects the output files to be present in the automatically created 'output' directory which can be accessed using $BPM_OUTPUT
DOWNLOAD="https://wwww.my-url.com/file.tar.gz"
FILENAME="${DOWNLOAD##*/}"
# The prepare function is executed in the root of the temp directory # The prepare function is executed in the root of the temp directory
# This function is used for downloading files and putting them into the correct location # This function is used for putting downloaded files to the correct location or applying patches
prepare() { prepare() {
wget "$DOWNLOAD" echo "You may remove this function if you do not intend to use it"
tar -xvf "$FILENAME" --strip-components=1 -C "$BPM_SOURCE"
} }
# The build function is executed in the source directory # The build function is executed in the source directory
+2 -6
View File
@@ -2,14 +2,10 @@
# BPM Expects the source code to be extracted into the automatically created 'source' directory which can be accessed using $BPM_SOURCE # BPM Expects the source code to be extracted into the automatically created 'source' directory which can be accessed using $BPM_SOURCE
# BPM Expects the output files to be present in the automatically created 'output' directory which can be accessed using $BPM_OUTPUT # BPM Expects the output files to be present in the automatically created 'output' directory which can be accessed using $BPM_OUTPUT
DOWNLOAD="https://wwww.my-url.com/file.tar.gz"
FILENAME="${DOWNLOAD##*/}"
# The prepare function is executed in the root of the temp directory # The prepare function is executed in the root of the temp directory
# This function is used for downloading files and putting them into the correct location # This function is used for putting downloaded files to the correct location or applying patches
prepare() { prepare() {
wget "$DOWNLOAD" echo "You may remove this function if you do not intend to use it"
tar -xvf "$FILENAME" --strip-components=1 -C "$BPM_SOURCE"
} }
# The build function is executed in the source directory # The build function is executed in the source directory
+2 -6
View File
@@ -2,14 +2,10 @@
# BPM Expects the source code to be extracted into the automatically created 'source' directory which can be accessed using $BPM_SOURCE # BPM Expects the source code to be extracted into the automatically created 'source' directory which can be accessed using $BPM_SOURCE
# BPM Expects the output files to be present in the automatically created 'output' directory which can be accessed using $BPM_OUTPUT # BPM Expects the output files to be present in the automatically created 'output' directory which can be accessed using $BPM_OUTPUT
DOWNLOAD="https://wwww.my-url.com/file.tar.gz"
FILENAME="${DOWNLOAD##*/}"
# The prepare function is executed in the root of the temp directory # The prepare function is executed in the root of the temp directory
# This function is used for downloading files and putting them into the correct location # This function is used for putting downloaded files to the correct location or applying patches
prepare() { prepare() {
wget "$DOWNLOAD" echo "You may remove this function if you do not intend to use it"
tar -xvf "$FILENAME" --strip-components=1 -C "$BPM_SOURCE"
} }
# The build function is executed in the source directory # The build function is executed in the source directory
+2 -6
View File
@@ -2,14 +2,10 @@
# BPM Expects the source code to be extracted into the automatically created 'source' directory which can be accessed using $BPM_SOURCE # BPM Expects the source code to be extracted into the automatically created 'source' directory which can be accessed using $BPM_SOURCE
# BPM Expects the output files to be present in the automatically created 'output' directory which can be accessed using $BPM_OUTPUT # BPM Expects the output files to be present in the automatically created 'output' directory which can be accessed using $BPM_OUTPUT
DOWNLOAD="https://wwww.my-url.com/file.tar.gz"
FILENAME="${DOWNLOAD##*/}"
# The prepare function is executed in the root of the temp directory # The prepare function is executed in the root of the temp directory
# This function is used for downloading files and putting them into the correct location # This function is used for putting downloaded files to the correct location or applying patches
prepare() { prepare() {
wget "$DOWNLOAD" echo "You may remove this function if you do not intend to use it"
tar -xvf "$FILENAME" --strip-components=1 -C "$BPM_SOURCE"
} }
# The build function is executed in the source directory # The build function is executed in the source directory
+2 -6
View File
@@ -2,14 +2,10 @@
# BPM Expects the source code to be extracted into the automatically created 'source' directory which can be accessed using $BPM_SOURCE # BPM Expects the source code to be extracted into the automatically created 'source' directory which can be accessed using $BPM_SOURCE
# BPM Expects the output files to be present in the automatically created 'output' directory which can be accessed using $BPM_OUTPUT # BPM Expects the output files to be present in the automatically created 'output' directory which can be accessed using $BPM_OUTPUT
DOWNLOAD="https://wwww.my-url.com/file.tar.gz"
FILENAME="${DOWNLOAD##*/}"
# The prepare function is executed in the root of the temp directory # The prepare function is executed in the root of the temp directory
# This function is used for downloading files and putting them into the correct location # This function is used for putting downloaded files to the correct location or applying patches
prepare() { prepare() {
wget "$DOWNLOAD" echo "You may remove this function if you do not intend to use it"
tar -xvf "$FILENAME" --strip-components=1 -C "$BPM_SOURCE"
} }
# The build function is executed in the source directory # The build function is executed in the source directory
+2
View File
@@ -8,4 +8,6 @@ require (
gopkg.in/yaml.v3 v3.0.1 gopkg.in/yaml.v3 v3.0.1
) )
require github.com/drone/envsubst v1.0.3 // indirect
replace bpm-utils-shared => ../bpm-utils-shared replace bpm-utils-shared => ../bpm-utils-shared
+4
View File
@@ -1,3 +1,7 @@
github.com/drone/envsubst v1.0.3 h1:PCIBwNDYjs50AsLZPYdfhSATKaRg/FJmDc2D6+C2x8g=
github.com/drone/envsubst v1.0.3/go.mod h1:N2jZmlMufstn1KEqvbHjw40h1KyTmnVzHcSc9bFiJ2g=
github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk= github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk=
github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
+42 -15
View File
@@ -2,6 +2,7 @@ package main
import ( import (
bpmutilsshared "bpm-utils-shared" bpmutilsshared "bpm-utils-shared"
"bytes"
"fmt" "fmt"
"io" "io"
"log" "log"
@@ -22,6 +23,7 @@ var skipCheck = flag.BoolP("skip-checks", "s", false, "Skip 'check' function whi
var installDepends = flag.BoolP("depends", "d", false, "Install package dependencies for compilation") var installDepends = flag.BoolP("depends", "d", false, "Install package dependencies for compilation")
var installPackage = flag.BoolP("install", "i", false, "Install compiled BPM package after compilation finishes") var installPackage = flag.BoolP("install", "i", false, "Install compiled BPM package after compilation finishes")
var moveToBinaryDir = flag.BoolP("move", "m", false, "Move output packages to the current repository's binary directory") var moveToBinaryDir = flag.BoolP("move", "m", false, "Move output packages to the current repository's binary directory")
var updateChecksums = flag.BoolP("update-checksums", "u", false, "Update the checksums for all download entries")
var yesAll = flag.BoolP("yes", "y", false, "Accept all confirmation prompts") var yesAll = flag.BoolP("yes", "y", false, "Accept all confirmation prompts")
func main() { func main() {
@@ -74,22 +76,47 @@ func createArchive() string {
} }
} }
// Read pkg.info file into basic struct // Read pkg.info file
pkgInfo := struct { pkgInfo, err := bpmutilsshared.ReadPacakgeInfoFromFile("pkg.info")
Name string `yaml:"name"`
Version string `yaml:"version"`
Revision int `yaml:"revision"`
Arch string `yaml:"architecture"`
}{
Revision: 1,
}
data, err := os.ReadFile("pkg.info")
if err != nil { if err != nil {
log.Fatalf("Error: could not read pkg.info file") log.Fatalf("Error: could not read package info: %s", err)
} }
err = yaml.Unmarshal(data, &pkgInfo)
// Update checksums
if *updateChecksums {
for i, download := range pkgInfo.Downloads {
if download.Checksum == "skip" {
continue
}
download.Checksum, err = download.CalculateChecksum(pkgInfo)
if err != nil { if err != nil {
log.Fatalf("Error: could not unmarshal pkg.info file") log.Fatalf("Could not calculate checksum for download entry %d: %s", i+1, err)
}
pkgInfo.Downloads[i] = download
}
// Save yaml back to file
var data bytes.Buffer
encoder := yaml.NewEncoder(&data)
encoder.SetIndent(2)
encoder.Encode(pkgInfo)
if err != nil {
log.Fatalf("Could not marshal package info: %s", err)
}
// Stat pkg.info
stat, err := os.Stat("pkg.info")
if err != nil {
log.Fatalf("Could not stat pkg.info: %s", err)
}
// Write package info back to file
err = os.WriteFile("pkg.info", data.Bytes(), stat.Mode().Perm())
if err != nil {
log.Fatalf("Could not write package info to pkg.info: %s", err)
}
} }
// Remove old BPM archives in current directory // Remove old BPM archives in current directory
@@ -142,7 +169,7 @@ func compilePackage(archive string) {
if *yesAll { if *yesAll {
args = append(args, "-y") args = append(args, "-y")
} }
args = append(args, "--fd=3") args = append(args, "--output-fd=3")
args = append(args, archive) args = append(args, archive)
cmd := exec.Command("bpm", args...) cmd := exec.Command("bpm", args...)
cmd.Stdin = os.Stdin cmd.Stdin = os.Stdin
@@ -181,7 +208,7 @@ func compilePackage(archive string) {
outputPkgs := make(map[string]string) outputPkgs := make(map[string]string)
for _, line := range strings.Split(strings.TrimSpace(string(cmdOutput)), "\n") { for _, line := range strings.Split(strings.TrimSpace(string(cmdOutput)), "\n") {
// Read generated package info // Read generated package info
pkgInfo, err := bpmutilsshared.ReadPacakgeInfo(line) pkgInfo, err := bpmutilsshared.ReadPacakgeInfoFromTarball(line)
if repo := bpmutilsshared.GetRepository(); repo != "" && *moveToBinaryDir { if repo := bpmutilsshared.GetRepository(); repo != "" && *moveToBinaryDir {
// Remove old package from binary dir // Remove old package from binary dir
+2
View File
@@ -8,4 +8,6 @@ require (
gopkg.in/yaml.v3 v3.0.1 gopkg.in/yaml.v3 v3.0.1
) )
require github.com/drone/envsubst v1.0.3 // indirect
replace bpm-utils-shared => ../bpm-utils-shared replace bpm-utils-shared => ../bpm-utils-shared
+4
View File
@@ -1,3 +1,7 @@
github.com/drone/envsubst v1.0.3 h1:PCIBwNDYjs50AsLZPYdfhSATKaRg/FJmDc2D6+C2x8g=
github.com/drone/envsubst v1.0.3/go.mod h1:N2jZmlMufstn1KEqvbHjw40h1KyTmnVzHcSc9bFiJ2g=
github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk= github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk=
github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
+9 -2
View File
@@ -3,6 +3,7 @@ package main
import ( import (
bpmutilsshared "bpm-utils-shared" bpmutilsshared "bpm-utils-shared"
"bufio" "bufio"
"context"
"fmt" "fmt"
"io/fs" "io/fs"
"log" "log"
@@ -176,6 +177,10 @@ func checkVersionsFunc(repo string) {
log.Fatalf("Could not read package info: %s", err) log.Fatalf("Could not read package info: %s", err)
} }
if verbose {
fmt.Printf("Checking version for package (%s)...\n", pkgInfo.Name)
}
// Check cached latest version // Check cached latest version
latestVersion := "" latestVersion := ""
if cachedVersion, ok := cachedVersions[pkgInfo.Name]; ok && !force && time.Since(time.UnixMilli(cachedVersion.Timestamp)).Milliseconds() < 604800000 { if cachedVersion, ok := cachedVersions[pkgInfo.Name]; ok && !force && time.Since(time.UnixMilli(cachedVersion.Timestamp)).Milliseconds() < 604800000 {
@@ -188,7 +193,9 @@ func checkVersionsFunc(repo string) {
} }
// Execute check-version.sh script // Execute check-version.sh script
cmd := exec.Command("bash", "-e", path.Join(dir, "check-version.sh")) ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
cmd := exec.CommandContext(ctx, "bash", "-e", path.Join(dir, "check-version.sh"))
cmd.Environ() cmd.Environ()
output, err := cmd.Output() output, err := cmd.Output()
if err != nil { if err != nil {
@@ -261,6 +268,7 @@ func checkVersionsFunc(repo string) {
for _, pkg := range pkgsWithoutScript { for _, pkg := range pkgsWithoutScript {
log.Printf("Warning: package (%s) has no check-version.sh script\n", pkg) log.Printf("Warning: package (%s) has no check-version.sh script\n", pkg)
} }
}
// Print errors // Print errors
keys = slices.Collect(maps.Keys(pkgsWithError)) keys = slices.Collect(maps.Keys(pkgsWithError))
@@ -268,7 +276,6 @@ func checkVersionsFunc(repo string) {
for _, pkg := range keys { for _, pkg := range keys {
log.Printf("Error: check-version.sh script for package (%s) failed: %s", pkg, pkgsWithError[pkg]) log.Printf("Error: check-version.sh script for package (%s) failed: %s", pkg, pkgsWithError[pkg])
} }
}
// Print summary // Print summary
fmt.Println("----- Summary -----") fmt.Println("----- Summary -----")
+7 -1
View File
@@ -2,6 +2,12 @@ module git.enumerated.dev/bubble-package-manager/bpm-utils/src/bpm-setup
go 1.23 go 1.23
require github.com/spf13/pflag v1.0.10 require (
bpm-utils-shared v1.0.0
github.com/spf13/pflag v1.0.10
gopkg.in/yaml.v3 v3.0.1
)
require github.com/drone/envsubst v1.0.3 // indirect
replace bpm-utils-shared => ../bpm-utils-shared replace bpm-utils-shared => ../bpm-utils-shared
+8
View File
@@ -1,2 +1,10 @@
github.com/drone/envsubst v1.0.3 h1:PCIBwNDYjs50AsLZPYdfhSATKaRg/FJmDc2D6+C2x8g=
github.com/drone/envsubst v1.0.3/go.mod h1:N2jZmlMufstn1KEqvbHjw40h1KyTmnVzHcSc9bFiJ2g=
github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk= github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk=
github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+27 -13
View File
@@ -1,7 +1,9 @@
package main package main
import ( import (
bpmutilsshared "bpm-utils-shared"
"bufio" "bufio"
"bytes"
"fmt" "fmt"
"io" "io"
"log" "log"
@@ -12,6 +14,7 @@ import (
"strings" "strings"
flag "github.com/spf13/pflag" flag "github.com/spf13/pflag"
yaml "gopkg.in/yaml.v3"
) )
var directory = flag.StringP("directory", "D", "", "Path to package directory") var directory = flag.StringP("directory", "D", "", "Path to package directory")
@@ -115,21 +118,32 @@ func createDirectory() {
log.Fatalf("Error: could not create directory: %s", err) log.Fatalf("Error: could not create directory: %s", err)
} }
// Create pkg.info contents string // Create package info struct
pkgInfo := "name: " + *name + "\n" pkgInfo := bpmutilsshared.PackageInfo{
pkgInfo += "description: " + *description + "\n" Name: *name,
pkgInfo += "version: " + *version + "\n" Description: *description,
if url != nil && *url != "" { Version: *version,
pkgInfo += "url: " + *url + "\n" Url: *url,
License: *license,
Arch: "any",
Type: "source",
Downloads: []bpmutilsshared.PackageDownload{
{
Url: "https://wwww.my-url.com/file.tar.gz",
ExtractTo: "${BPM_SOURCE}",
ExtractStripComponents: 1,
Checksum: "replaceme",
},
},
} }
if license != nil && *license != "" {
pkgInfo += "license: " + *license + "\n"
}
pkgInfo += "architecture: any\n"
pkgInfo += "type: source\n"
// Write string to file var buffer bytes.Buffer
err = os.WriteFile(path.Join(*directory, "pkg.info"), []byte(pkgInfo), 0644) encoder := yaml.NewEncoder(&buffer)
encoder.SetIndent(2)
encoder.Encode(&pkgInfo)
// Write package info to file
err = os.WriteFile(path.Join(*directory, "pkg.info"), buffer.Bytes(), 0644)
if err != nil { if err != nil {
log.Fatalf("Could not write to pkg.info: %s", err) log.Fatalf("Could not write to pkg.info: %s", err)
} }
+1 -1
View File
@@ -78,7 +78,7 @@ func GenerateDatabase(path string) error {
} }
// Get package info // Get package info
entry.PackageInfo, err = ReadPacakgeInfo(packagePath) entry.PackageInfo, err = ReadPacakgeInfoFromTarball(packagePath)
if err != nil { if err != nil {
return err return err
} }
+2
View File
@@ -3,3 +3,5 @@ module bpm-utils-shared
go 1.23 go 1.23
require gopkg.in/yaml.v3 v3.0.1 require gopkg.in/yaml.v3 v3.0.1
require github.com/drone/envsubst v1.0.3
+4
View File
@@ -1,3 +1,7 @@
github.com/drone/envsubst v1.0.3 h1:PCIBwNDYjs50AsLZPYdfhSATKaRg/FJmDc2D6+C2x8g=
github.com/drone/envsubst v1.0.3/go.mod h1:N2jZmlMufstn1KEqvbHjw40h1KyTmnVzHcSc9bFiJ2g=
github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
+110 -38
View File
@@ -1,48 +1,56 @@
package bpm_utils_shared package bpm_utils_shared
import ( import (
"fmt"
"os" "os"
"os/exec" "os/exec"
"strings"
"github.com/drone/envsubst"
"gopkg.in/yaml.v3" "gopkg.in/yaml.v3"
) )
type PackageInfo struct { type PackageInfo struct {
Name string `yaml:"name,omitempty"` Name string `yaml:"name"`
Description string `yaml:"description,omitempty"` Description string `yaml:"description,omitempty"`
Version string `yaml:"version,omitempty"` Version string `yaml:"version,omitempty"`
Revision int `yaml:"revision,omitempty"` Revision int `yaml:"revision,omitempty"`
Url string `yaml:"url,omitempty"` Url string `yaml:"url,omitempty"`
License string `yaml:"license,omitempty"` License string `yaml:"license,omitempty"`
Arch string `yaml:"architecture,omitempty"` Arch string `yaml:"architecture,omitempty"`
OutputArch string `yaml:"output_architecture,omitempty"`
Type string `yaml:"type,omitempty"` Type string `yaml:"type,omitempty"`
Keep []string `yaml:"keep,omitempty"` Keep []string `yaml:"keep,omitempty"`
Depends []string `yaml:"depends,omitempty"` Depends []string `yaml:"depends,omitempty"`
MakeDepends []string `yaml:"make_depends,omitempty"`
OptionalDepends []string `yaml:"optional_depends,omitempty"` OptionalDepends []string `yaml:"optional_depends,omitempty"`
MakeDepends []string `yaml:"make_depends,omitempty"`
Conflicts []string `yaml:"conflicts,omitempty"` Conflicts []string `yaml:"conflicts,omitempty"`
Replaces []string `yaml:"replaces,omitempty"` Replaces []string `yaml:"replaces,omitempty"`
Provides []string `yaml:"provides,omitempty"` Provides []string `yaml:"provides,omitempty"`
Downloads []PackageDownload `yaml:"downloads,omitempty"`
SplitPackages []*PackageInfo `yaml:"split_packages,omitempty"` SplitPackages []*PackageInfo `yaml:"split_packages,omitempty"`
} }
func ReadPacakgeInfo(path string) (*PackageInfo, error) { type PackageDownload struct {
// Extract package info using tar Url string `yaml:"url"`
cmd := exec.Command("tar", "-x", "-f", path, "pkg.info", "-O") Type string `yaml:"type,omitempty"`
output, err := cmd.Output() Filepath string `yaml:"filepath,omitempty,omitempty"`
if err != nil {
return nil, err // Archive options
NoExtract bool `yaml:"no_extract,omitempty"`
ExtractTo string `yaml:"extract_to,omitempty"`
ExtractStripComponents int `yaml:"extract_strip_components,omitempty"`
// Git options
CloneTo string `yaml:"clone_to,omitempty"`
GitBranch string `yaml:"git_branch,omitempty"`
Checksum string `yaml:"checksum,omitempty"`
} }
func ReadPackageInfo(data []byte) (*PackageInfo, error) {
pkgInfo := &PackageInfo{ pkgInfo := &PackageInfo{
Name: "",
Description: "",
Version: "",
Revision: 1, Revision: 1,
Url: "",
License: "",
Arch: "",
Type: "",
Keep: make([]string, 0), Keep: make([]string, 0),
Depends: make([]string, 0), Depends: make([]string, 0),
MakeDepends: make([]string, 0), MakeDepends: make([]string, 0),
@@ -50,11 +58,28 @@ func ReadPacakgeInfo(path string) (*PackageInfo, error) {
Conflicts: make([]string, 0), Conflicts: make([]string, 0),
Replaces: make([]string, 0), Replaces: make([]string, 0),
Provides: make([]string, 0), Provides: make([]string, 0),
Downloads: make([]PackageDownload, 0),
SplitPackages: make([]*PackageInfo, 0), SplitPackages: make([]*PackageInfo, 0),
} }
// Unmarshal yaml // Unmarshal yaml
err = yaml.Unmarshal(output, pkgInfo) err := yaml.Unmarshal(data, pkgInfo)
if err != nil {
return nil, err
}
return pkgInfo, nil
}
func ReadPacakgeInfoFromTarball(path string) (*PackageInfo, error) {
// Extract package info using tar
cmd := exec.Command("tar", "-x", "-f", path, "pkg.info", "-O")
output, err := cmd.Output()
if err != nil {
return nil, err
}
pkgInfo, err := ReadPackageInfo(output)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -63,36 +88,83 @@ func ReadPacakgeInfo(path string) (*PackageInfo, error) {
} }
func ReadPacakgeInfoFromFile(path string) (*PackageInfo, error) { func ReadPacakgeInfoFromFile(path string) (*PackageInfo, error) {
// Extract package info using tar // Read data from file
output, err := os.ReadFile(path) output, err := os.ReadFile(path)
if err != nil { if err != nil {
return nil, err return nil, err
} }
pkgInfo := &PackageInfo{ pkgInfo, err := ReadPackageInfo(output)
Name: "",
Description: "",
Version: "",
Revision: 1,
Url: "",
License: "",
Arch: "",
Type: "",
Keep: make([]string, 0),
Depends: make([]string, 0),
MakeDepends: make([]string, 0),
OptionalDepends: make([]string, 0),
Conflicts: make([]string, 0),
Replaces: make([]string, 0),
Provides: make([]string, 0),
SplitPackages: make([]*PackageInfo, 0),
}
// Unmarshal yaml
err = yaml.Unmarshal(output, pkgInfo)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return pkgInfo, nil return pkgInfo, nil
} }
func (pkgDownload *PackageDownload) CalculateChecksum(pkgInfo *PackageInfo) (string, error) {
switch pkgDownload.Type {
case "", "file":
fmt.Println("Downloading and calculating checksum for file...")
// Replace variables in download url
downloadUrl := pkgDownload.Url
downloadUrl, err := envsubst.Eval(downloadUrl, func(s string) string {
switch s {
case "BPM_PKG_VERSION":
return pkgInfo.Version
case "BPM_PKG_NAME":
return pkgInfo.Name
default:
return ""
}
})
if err != nil {
return "", err
}
cmd := exec.Command("sh", "-c", fmt.Sprintf("curl -s -L %s | sha256sum | awk '{print $1}'", downloadUrl))
cmd.Stderr = os.Stderr
checksum, err := cmd.Output()
if err != nil {
return "", err
}
return strings.TrimSpace(string(checksum)), err
case "git":
fmt.Println("Calculating checksum for git branch...")
// Replace variables in git branch
gitBranch := pkgDownload.GitBranch
gitBranch, err := envsubst.Eval(gitBranch, func(s string) string {
switch s {
case "BPM_PKG_VERSION":
return pkgInfo.Version
case "BPM_PKG_NAME":
return pkgInfo.Name
default:
return ""
}
})
if err != nil {
return "", err
}
if pkgDownload.GitBranch == "" {
return "", fmt.Errorf("'git_branch' field cannot be empty")
}
cmd := exec.Command("sh", "-c", fmt.Sprintf("git ls-remote -bt %s | grep -E 'refs/.*/%s(\\^\\{\\})?$' | tail -n1 | awk '{print $1}'", pkgDownload.Url, gitBranch))
cmd.Stderr = os.Stderr
checksum, err := cmd.Output()
if err != nil {
return "", err
}
return strings.TrimSpace(string(checksum)), err
default:
return "", fmt.Errorf("unknown download type (%s)", pkgDownload.Type)
}
}