24 Commits
Author SHA1 Message Date
EnumDev eb13b2653d other: update default gitignore 2026-02-25 09:02:34 +02:00
EnumDev 581c864f1d bpm-repo: sign all packages when compiling 2026-02-24 18:52:45 +02:00
EnumDev 7e7b8487ea bpm-package: add package signing 2026-02-24 18:52:08 +02:00
EnumDev a7f751c094 Fix on_hold value being removed when checking versions 2026-02-20 12:51:14 +02:00
EnumDev 54e192f220 bpm-repo: add 'hold' subcommand 2026-02-15 15:33:48 +02:00
EnumDev c508ce6a01 bpm-repo: remove testing println and generate source package in correct directory 2026-02-15 15:06:08 +02:00
EnumDev 2b81dad6cf other: recognize 'check_depends' field 2026-01-28 18:51:03 +02:00
EnumDev 82777ebac1 bpm-package: add config option to add default maintainer on pkg.info update 2026-01-25 17:47:07 +02:00
EnumDev b20766bddb bpm-package: rename 'update-checksums' flag to 'update-info' 2026-01-25 17:31:25 +02:00
EnumDev 0ff9eb9cf2 other: add 'default_maintainer' config option 2026-01-25 17:28:41 +02:00
EnumDev 4371b7f0e3 Recognize 'maintainers' field in pkg.info 2026-01-25 17:04:42 +02:00
EnumDev 65849fdf86 bpm-repo: add 'compile-all' subcommand 2026-01-25 17:02:39 +02:00
EnumDev a64ad39ca7 bpm-repo: generate source package after applying new version 2026-01-12 08:52:17 +02:00
EnumDev bf9874af6b bpm-repo: add 'apply' flag to 'check-versions' subcommand 2026-01-11 11:50:03 +02:00
EnumDev 07a9e8c9d2 Add 'jobs' flag 2026-01-11 10:12:06 +02:00
EnumDev 598e6710f4 bpm-setup: set revision number on package creation 2026-01-04 17:19:49 +02:00
EnumDev 902fcbf296 bpm-repo: create 'source' directory upon repository creation 2026-01-04 15:27:41 +02:00
EnumDev 03bf97b8d8 Add 'RuntimeDepends' field to PackageInfo struct 2026-01-04 14:34:36 +02:00
EnumDev 5240ae4a8c Add rust template 2025-10-28 16:09:14 +02:00
EnumDev 9d03b5b423 Add 'verbose' flag to bpm-package 2025-10-27 18:18:40 +02:00
EnumDev f17bc777d9 Add 'options' field to package info 2025-10-27 18:15:10 +02:00
EnumDev 154f546b7f Fix installed size being wrong 2025-10-25 13:03:36 +03:00
EnumDev c4a0e9f860 Add 'keep' flag 2025-10-17 21:11:16 +03:00
EnumDev b9d7dfd9d0 Update databases only once after compiling split packages 2025-10-17 15:02:30 +03:00
8 changed files with 444 additions and 22 deletions
+2 -1
View File
@@ -1,2 +1,3 @@
# Exclude bpm archives # Ignore BPM archives and signatures
*.bpm *.bpm
*.bpm.sig
+31
View File
@@ -0,0 +1,31 @@
# 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"
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 --locked --frozen
}
# 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 --release --frozen
}
# The package function is executed in the source directory
# This function is used to move the compiled files into the output directory
package() {
# Cargo built packages are not usually packaged manually and not with an 'install' subcommand
# Install package license
install -Dm644 "$BPM_SOURCE"/LICENSE "$BPM_OUTPUT"/usr/share/licenses/$NAME/LICENSE
}
+84 -5
View File
@@ -12,6 +12,7 @@ import (
"path" "path"
"path/filepath" "path/filepath"
"slices" "slices"
"strconv"
"strings" "strings"
flag "github.com/spf13/pflag" flag "github.com/spf13/pflag"
@@ -19,11 +20,15 @@ import (
) )
var compile = flag.BoolP("compile", "c", false, "Compile BPM source package") var compile = flag.BoolP("compile", "c", false, "Compile BPM source package")
var skipCheck = flag.BoolP("skip-checks", "s", false, "Skip 'check' function while compiling") var verbose = flag.BoolP("verbose", "v", false, "Show additional information about the compilation process")
var skipCheck = flag.Bool("skip-checks", false, "Skip 'check' function while compiling")
var keepCompilationFiles = flag.BoolP("keep", "k", false, "Keep compilation files after successful package compilation")
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 compilationJobs = flag.IntP("jobs", "j", 0, "Set the amount of concurrent processes to use for source package compilation")
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 updateInfo = flag.BoolP("update-info", "u", false, "Update the pkg.info file")
var signPackage = flag.BoolP("sign", "s", false, "Sign package using GPG")
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() {
@@ -54,6 +59,12 @@ func runChecks() {
} }
func createArchive() string { func createArchive() string {
// Read BPM utils config
config, err := bpmutilsshared.ReadBPMUtilsConfig()
if err != nil {
log.Fatalf("Error: failed to read config: %s", err)
}
filesToInclude := make([]string, 0) filesToInclude := make([]string, 0)
// Include base files // Include base files
@@ -82,8 +93,9 @@ func createArchive() string {
log.Fatalf("Error: could not read package info: %s", err) log.Fatalf("Error: could not read package info: %s", err)
} }
// Update checksums // Update pkg.info file
if *updateChecksums { if *updateInfo {
// Update download checksums
for i, download := range pkgInfo.Downloads { for i, download := range pkgInfo.Downloads {
if download.Checksum == "skip" { if download.Checksum == "skip" {
continue continue
@@ -97,6 +109,13 @@ func createArchive() string {
pkgInfo.Downloads[i] = download pkgInfo.Downloads[i] = download
} }
// Add default maintainer
if config.AddDefaultMaintainer {
if !slices.Contains(pkgInfo.Maintainers, config.DefaultMaintainer) {
pkgInfo.Maintainers = append(pkgInfo.Maintainers, config.DefaultMaintainer)
}
}
// Save yaml back to file // Save yaml back to file
var data bytes.Buffer var data bytes.Buffer
encoder := yaml.NewEncoder(&data) encoder := yaml.NewEncoder(&data)
@@ -131,6 +150,18 @@ func createArchive() string {
} }
} }
// Remove old BPM archive signatures in current directory
oldSignatures, err := filepath.Glob("*.sig")
if err != nil {
log.Printf("Warning: could not search for old BPM archive signatures: %s", err)
}
for _, signature := range oldSignatures {
err = os.Remove(signature)
if err != nil {
log.Printf("Warning: could not remove old BPM archive signature (%s): %s", signature, err)
}
}
// Create filename // Create filename
filename := fmt.Sprintf("%s-%s-%d-%s-src.bpm", pkgInfo.Name, pkgInfo.Version, pkgInfo.Revision, pkgInfo.Arch) filename := fmt.Sprintf("%s-%s-%d-%s-src.bpm", pkgInfo.Name, pkgInfo.Version, pkgInfo.Revision, pkgInfo.Arch)
@@ -146,6 +177,19 @@ func createArchive() string {
log.Fatalf("Error: failed to create BPM source archive: %s", err) log.Fatalf("Error: failed to create BPM source archive: %s", err)
} }
// Sign package
if *signPackage {
cmd := exec.Command("gpg", "--detach-sign", filename)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.Stdin = os.Stdin
err := cmd.Run()
if err != nil {
log.Fatalf("Error: could not sign package: %s", err)
}
}
// Get absolute path to filename // Get absolute path to filename
absFilepath, err := filepath.Abs(filename) absFilepath, err := filepath.Abs(filename)
if err != nil { if err != nil {
@@ -160,12 +204,21 @@ func compilePackage(archive string) {
// Setup compile command // Setup compile command
args := make([]string, 0) args := make([]string, 0)
args = append(args, "compile") args = append(args, "compile")
if *verbose {
args = append(args, "-v")
}
if *skipCheck { if *skipCheck {
args = append(args, "-s") args = append(args, "-s")
} }
if *keepCompilationFiles {
args = append(args, "-k")
}
if *installDepends { if *installDepends {
args = append(args, "-d") args = append(args, "-d")
} }
if *compilationJobs > 0 {
args = append(args, "-j"+strconv.Itoa(*compilationJobs))
}
if *yesAll { if *yesAll {
args = append(args, "-y") args = append(args, "-y")
} }
@@ -219,6 +272,14 @@ func compilePackage(archive string) {
if err != nil { if err != nil {
log.Printf("Warning: could not remove old binary package (%s): %s", pkgFilepath, err) log.Printf("Warning: could not remove old binary package (%s): %s", pkgFilepath, err)
} }
// Remove package signature
if _, err := os.Stat(pkgFilepath + ".sig"); err == nil {
err := os.Remove(pkgFilepath + ".sig")
if err != nil {
log.Printf("Warning: could not remove old binary package signature (%s): %s", pkgFilepath+".str", err)
}
}
} }
} }
@@ -231,11 +292,29 @@ func compilePackage(archive string) {
os.Rename(line, newPath) os.Rename(line, newPath)
outputPkgs[pkgInfo.Name] = newPath outputPkgs[pkgInfo.Name] = newPath
bpmutilsshared.UpdateDatabases(repo)
} else { } else {
outputPkgs[pkgInfo.Name] = line outputPkgs[pkgInfo.Name] = line
} }
} }
if repo := bpmutilsshared.GetRepository(); repo != "" && *moveToBinaryDir {
bpmutilsshared.UpdateDatabases(repo)
}
// Sign package
if *signPackage {
for k, v := range outputPkgs {
cmd := exec.Command("gpg", "--detach-sign", v)
cmd.Dir = path.Dir(v)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.Stdin = os.Stdin
err := cmd.Run()
if err != nil {
log.Fatalf("Error: could not sign package (%s) at: %s", k, v)
}
}
}
// Print out generated packages // Print out generated packages
for k, v := range outputPkgs { for k, v := range outputPkgs {
+276 -1
View File
@@ -3,6 +3,7 @@ package main
import ( import (
bpmutilsshared "bpm-utils-shared" bpmutilsshared "bpm-utils-shared"
"bufio" "bufio"
"bytes"
"context" "context"
"fmt" "fmt"
"io/fs" "io/fs"
@@ -14,6 +15,7 @@ import (
"path/filepath" "path/filepath"
"slices" "slices"
"sort" "sort"
"strconv"
"strings" "strings"
"time" "time"
@@ -85,6 +87,7 @@ func main() {
flagset := flag.NewFlagSet("check-versions", flag.ExitOnError) flagset := flag.NewFlagSet("check-versions", flag.ExitOnError)
flagset.BoolP("verbose", "v", false, "Show additional information about the current operation") flagset.BoolP("verbose", "v", false, "Show additional information about the current operation")
flagset.BoolP("force", "f", false, "Force current operation to bypass certain conditions") flagset.BoolP("force", "f", false, "Force current operation to bypass certain conditions")
flagset.BoolP("apply", "a", false, "Apply new versions to packages")
setupFlagsAndHelp(flagset, fmt.Sprintf("bpm-repo %s <options>", subcommand), "Manage BPM repositories and databases", os.Args[2:]) setupFlagsAndHelp(flagset, fmt.Sprintf("bpm-repo %s <options>", subcommand), "Manage BPM repositories and databases", os.Args[2:])
currentFlagSet = flagset currentFlagSet = flagset
@@ -95,6 +98,36 @@ func main() {
} }
checkVersionsFunc(repo) checkVersionsFunc(repo)
case "hold", "h":
// Setup flags and help
flagset := flag.NewFlagSet("hold", flag.ExitOnError)
flagset.Bool("get", false, "Show current value")
setupFlagsAndHelp(flagset, fmt.Sprintf("bpm-repo %s <options>", subcommand), "Manage BPM repositories and databases", os.Args[2:])
currentFlagSet = flagset
// Get current database
repo := bpmutilsshared.GetRepository()
if repo == "" {
log.Fatal("Error: this command may only be run inside a BPM repository")
}
holdPackage(repo)
case "compile-all", "a":
// Setup flags and help
flagset := flag.NewFlagSet("check-versions", flag.ExitOnError)
flagset.BoolP("verbose", "v", false, "Show additional information about the current operation")
flagset.BoolP("modified", "m", true, "Skip non-modified source packages")
flagset.BoolP("show-order", "o", false, "Show the order in which all packages will be compiled and exit")
setupFlagsAndHelp(flagset, fmt.Sprintf("bpm-repo %s <options>", subcommand), "Manage BPM repositories and databases", os.Args[2:])
currentFlagSet = flagset
// Get current database
repo := bpmutilsshared.GetRepository()
if repo == "" {
log.Fatal("Error: this command may only be run inside a BPM repository")
}
compileAllPackagesFunc(repo)
default: default:
log.Println("Error: unknown subcommand") log.Println("Error: unknown subcommand")
listSubcommands() listSubcommands()
@@ -114,6 +147,11 @@ func createRepository(name, description string) {
log.Fatalf("Error: could not write to file: %s", err) log.Fatalf("Error: could not write to file: %s", err)
} }
err = os.Mkdir(path.Join(name, "source"), 0755)
if err != nil {
log.Fatalf("Error: could not create directory: %s", err)
}
fmt.Println("Repository created successfully!") fmt.Println("Repository created successfully!")
} }
@@ -121,6 +159,7 @@ func checkVersionsFunc(repo string) {
// Get flags // Get flags
verbose, _ := currentFlagSet.GetBool("verbose") verbose, _ := currentFlagSet.GetBool("verbose")
force, _ := currentFlagSet.GetBool("force") force, _ := currentFlagSet.GetBool("force")
apply, _ := currentFlagSet.GetBool("apply")
// Read environment files // Read environment files
err := readEnvFile(repo) err := readEnvFile(repo)
@@ -132,6 +171,7 @@ func checkVersionsFunc(repo string) {
type CachedVersionEntry struct { type CachedVersionEntry struct {
LatestVersion string `yaml:"latest_version"` LatestVersion string `yaml:"latest_version"`
Timestamp int64 `yaml:"timestamp"` Timestamp int64 `yaml:"timestamp"`
OnHold bool `yaml:"on_hold,omitempty"`
} }
cachedVersions := make(map[string]CachedVersionEntry) cachedVersions := make(map[string]CachedVersionEntry)
data, err := os.ReadFile(path.Join(repo, ".version-cache")) data, err := os.ReadFile(path.Join(repo, ".version-cache"))
@@ -220,10 +260,17 @@ func checkVersionsFunc(repo string) {
continue continue
} }
// Get current on_hold value
onHold := false
if v, ok := cachedVersions[pkgInfo.Name]; ok {
onHold = v.OnHold
}
// Cache latest version // Cache latest version
cachedVersions[pkgInfo.Name] = CachedVersionEntry{ cachedVersions[pkgInfo.Name] = CachedVersionEntry{
LatestVersion: latestVersion, LatestVersion: latestVersion,
Timestamp: time.Now().UnixMilli(), Timestamp: time.Now().UnixMilli(),
OnHold: onHold,
} }
} }
@@ -236,6 +283,31 @@ func checkVersionsFunc(repo string) {
OldVersion: pkgInfo.Version, OldVersion: pkgInfo.Version,
NewVersion: latestVersion, NewVersion: latestVersion,
} }
// Apply new version
pkgInfo.Version = latestVersion
pkgInfo.Revision = 1
if apply && !cachedVersions[pkgInfo.Name].OnHold {
var data bytes.Buffer
encoder := yaml.NewEncoder(&data)
encoder.SetIndent(2)
encoder.Encode(pkgInfo)
// Write package information
err := os.WriteFile(path.Join(dir, "pkg.info"), data.Bytes(), 0644)
if err != nil {
log.Printf("Warning: could not write new version for package (%s) to file: %s", pkgInfo.Name, err)
}
// Generate source package
cmd := exec.Command("bpm-package")
cmd.Stderr = os.Stderr
cmd.Dir = dir
if err := cmd.Run(); err != nil {
log.Printf("Warning: could not generate source pacakge (%s): %s", pkgInfo.Name, err)
}
}
continue continue
} }
@@ -255,7 +327,11 @@ func checkVersionsFunc(repo string) {
keys := slices.Collect(maps.Keys(pkgsWithUpdates)) keys := slices.Collect(maps.Keys(pkgsWithUpdates))
sort.Strings(keys) sort.Strings(keys)
for _, pkg := range keys { for _, pkg := range keys {
fmt.Printf("Update available for package (%s): %s -> %s\n", pkg, pkgsWithUpdates[pkg].OldVersion, pkgsWithUpdates[pkg].NewVersion) fmt.Printf("Update available for package (%s): %s -> %s", pkg, pkgsWithUpdates[pkg].OldVersion, pkgsWithUpdates[pkg].NewVersion)
if cachedVersions[pkg].OnHold {
fmt.Print(" (On hold)")
}
fmt.Println()
} }
if verbose { if verbose {
@@ -286,6 +362,78 @@ func checkVersionsFunc(repo string) {
fmt.Println("Errors:", len(pkgsWithError)) fmt.Println("Errors:", len(pkgsWithError))
} }
func holdPackage(repo string) {
// Get flags
get, _ := currentFlagSet.GetBool("get")
// Get package name
pkgName := ""
if len(currentFlagSet.Args()) < 1 {
log.Fatalf("Error: no package name set")
} else {
pkgName = currentFlagSet.Arg(0)
}
// Ensure package exists
if _, err := os.Stat(path.Join(repo, "source", pkgName, "pkg.info")); err != nil {
log.Fatalf("Error: could not find pkg.info file in directory (%s): %s", pkgName, err)
}
// Read version cache
type CachedVersionEntry struct {
LatestVersion string `yaml:"latest_version"`
Timestamp int64 `yaml:"timestamp"`
OnHold bool `yaml:"on_hold,omitempty"`
}
cachedVersions := make(map[string]*CachedVersionEntry)
data, err := os.ReadFile(path.Join(repo, ".version-cache"))
if err == nil {
err := yaml.Unmarshal(data, &cachedVersions)
if err != nil {
cachedVersions = make(map[string]*CachedVersionEntry)
}
}
// Get current on_hold value
if get {
if cachedVersion, ok := cachedVersions[pkgName]; ok && cachedVersion.OnHold {
fmt.Printf("Package (%s) has been put on hold.\n", pkgName)
} else {
fmt.Printf("Package (%s) has not been put on hold.\n", pkgName)
}
return
}
// Get boolean value
var value bool
if len(currentFlagSet.Args()) < 2 {
log.Fatalf("Error: no boolean value set")
} else {
value, err = strconv.ParseBool(currentFlagSet.Arg(1))
if err != nil {
log.Fatalf("Error: value (%s) is not a boolean", currentFlagSet.Arg(1))
}
}
// Set on_hold value
cachedVersions[pkgName].OnHold = value
// Save cached versions to file
data, err = yaml.Marshal(cachedVersions)
if err == nil {
err := os.WriteFile(path.Join(repo, ".version-cache"), data, 0644)
if err != nil {
log.Printf("Warning: could not write cached versions to file: %s", err)
}
}
if value {
fmt.Printf("Package (%s) was put on hold.\n", pkgName)
} else {
fmt.Printf("Package (%s) is no longer put on hold.\n", pkgName)
}
}
func listPackagesFunc(repo string) { func listPackagesFunc(repo string) {
// Read databases // Read databases
sourceDatabase, err := bpmutilsshared.ReadDatabase(path.Join(repo, "source/database.bpmdb")) sourceDatabase, err := bpmutilsshared.ReadDatabase(path.Join(repo, "source/database.bpmdb"))
@@ -329,6 +477,130 @@ func listPackagesFunc(repo string) {
} }
} }
func compileAllPackagesFunc(repo string) {
// Get flags
verbose, _ := currentFlagSet.GetBool("verbose")
modifiedOnly, _ := currentFlagSet.GetBool("modified")
showOrder, _ := currentFlagSet.GetBool("show-order")
// Read BPM utils config
config, err := bpmutilsshared.ReadBPMUtilsConfig()
if err != nil {
log.Fatalf("Error: failed to read config: %s", err)
}
// Ensure database is updated
bpmutilsshared.UpdateDatabases(repo)
// Read databases
sourceDatabase, err := bpmutilsshared.ReadDatabase(path.Join(repo, "source/database.bpmdb"))
if err != nil {
log.Fatalf("Error: could not read source database: %s", err)
}
binaryDatabase, _ := bpmutilsshared.ReadDatabase(path.Join(repo, "binary/database.bpmdb"))
// Get all packages from database entries
packages := slices.Collect(maps.Values(sourceDatabase.Entries))
sort.Slice(packages, func(a, b int) bool {
return packages[a].PackageInfo.Name < packages[b].PackageInfo.Name
})
// Toposort packages using Depth-first search algorithm
sorted := make([]bpmutilsshared.PackageInfo, 0)
marked := make(map[string]int) // 0 = Unmarked, 1 = Temporary mark, 2 = Permanent mark
var visit func(pkgInfo *bpmutilsshared.PackageInfo) error
visit = func(pkgInfo *bpmutilsshared.PackageInfo) error {
if mark, _ := marked[pkgInfo.Name]; mark == 2 {
return nil
} else if mark == 1 {
return fmt.Errorf("Circular dependency found!")
}
marked[pkgInfo.Name] = 1
// Get all dependencies
depends := slices.Clone(pkgInfo.Depends)
depends = append(depends, pkgInfo.MakeDepends...)
for _, depend := range depends {
// Find package in repository
dependEntry, ok := sourceDatabase.Entries[depend]
if !ok {
// Search for virtual package
for _, entry := range sourceDatabase.Entries {
if slices.Contains(entry.PackageInfo.Provides, depend) {
dependEntry = entry
ok = true
break
}
}
if !ok {
continue
}
}
err := visit(dependEntry.PackageInfo)
if err != nil && verbose {
fmt.Printf("Circular dependency found! (%s -> %s)\n", pkgInfo.Name, dependEntry.PackageInfo.Name)
}
}
marked[pkgInfo.Name] = 2
sorted = append(sorted, *pkgInfo)
return nil
}
for _, entry := range packages {
if mark, _ := marked[entry.PackageInfo.Name]; mark != 2 {
visit(entry.PackageInfo)
}
}
// Compile all packages in order
for _, pkgInfo := range sorted {
if modifiedOnly && binaryDatabase != nil {
if binaryPkgInfo, ok := binaryDatabase.Entries[pkgInfo.Name]; ok && binaryPkgInfo.PackageInfo.GetFullVersion() == pkgInfo.GetFullVersion() {
continue
}
}
if showOrder {
fmt.Println(pkgInfo.Name)
continue
}
// Ensure installed packages are up-to-date
cmd := exec.Command(config.PrivilegeEscalatorCmd, "sh", "-c", "bpm u -y")
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil {
log.Fatalf("Error: could not update packages): %s", err)
}
// Compile source package
cmd = exec.Command("bpm-package", "-cdvusmy")
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.Dir = path.Join(repo, "source", pkgInfo.Name)
if err := cmd.Run(); err != nil {
log.Fatalf("Error: could not compile package (%s): %s", pkgInfo.Name, err)
}
}
// Ensure installed packages are up-to-date
cmd := exec.Command(config.PrivilegeEscalatorCmd, "sh", "-c", "bpm u -y")
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil {
log.Fatalf("Error: could not update packages): %s", err)
}
}
func readEnvFile(repo string) error { func readEnvFile(repo string) error {
data, err := os.ReadFile(path.Join(repo, ".env")) data, err := os.ReadFile(path.Join(repo, ".env"))
if os.IsNotExist(err) { if os.IsNotExist(err) {
@@ -361,7 +633,10 @@ func listSubcommands() {
fmt.Println(" c, create-repo Create a new BPM repository") fmt.Println(" c, create-repo Create a new BPM repository")
fmt.Println(" u, update-db Update update source and binary databases in current repositor") fmt.Println(" u, update-db Update update source and binary databases in current repositor")
fmt.Println(" v, check-versions Manage BPM repositories and databases") fmt.Println(" v, check-versions Manage BPM repositories and databases")
fmt.Println(" h, hold Prevent package from being automatically updated")
fmt.Println(" l, list List packages") fmt.Println(" l, list List packages")
fmt.Println(" a, compile-all Compile all packages in the current repository")
} }
func setupFlagsAndHelp(flagset *flag.FlagSet, usage, desc string, args []string) { func setupFlagsAndHelp(flagset *flag.FlagSet, usage, desc string, args []string) {
+11 -1
View File
@@ -108,12 +108,18 @@ func replaceVariables(templateContents string) string {
} }
func createDirectory() { func createDirectory() {
// Read BPM utils config
config, err := bpmutilsshared.ReadBPMUtilsConfig()
if err != nil {
log.Fatalf("Error: failed to read config: %s", err)
}
// Trim spaces // Trim spaces
*directory = strings.TrimSpace(*directory) *directory = strings.TrimSpace(*directory)
*name = strings.TrimSpace(*name) *name = strings.TrimSpace(*name)
// Create directory // Create directory
err := os.Mkdir(*directory, 0755) err = os.Mkdir(*directory, 0755)
if err != nil { if err != nil {
log.Fatalf("Error: could not create directory: %s", err) log.Fatalf("Error: could not create directory: %s", err)
} }
@@ -123,6 +129,7 @@ func createDirectory() {
Name: *name, Name: *name,
Description: *description, Description: *description,
Version: *version, Version: *version,
Revision: 1,
Url: *url, Url: *url,
License: *license, License: *license,
Arch: "any", Arch: "any",
@@ -136,6 +143,9 @@ func createDirectory() {
}, },
}, },
} }
if config.DefaultMaintainer != "" {
pkgInfo.Maintainers = append(pkgInfo.Maintainers, config.DefaultMaintainer)
}
var buffer bytes.Buffer var buffer bytes.Buffer
encoder := yaml.NewEncoder(&buffer) encoder := yaml.NewEncoder(&buffer)
+27 -14
View File
@@ -58,31 +58,44 @@ func GenerateDatabase(path string) error {
// Initialize database entry // Initialize database entry
entry := BPMDatabaseEntry{} entry := BPMDatabaseEntry{}
entry.DownloadSize = info.Size() entry.DownloadSize = info.Size()
entry.InstalledSize = 0
entry.Filepath, err = filepath.Rel(path, packagePath) entry.Filepath, err = filepath.Rel(path, packagePath)
if err != nil { if err != nil {
return err return err
} }
// Get package installed size
cmd := exec.Command("tar", "-t", "-v", "-f", packagePath, "files.tar.gz")
output, err := cmd.Output()
if err == nil {
entry.InstalledSize, err = strconv.ParseInt(strings.Fields(string(output))[2], 10, 64)
if err != nil {
return err
}
} else if err.(*exec.ExitError).ExitCode() == 2 {
entry.InstalledSize = 0
} else {
return err
}
// Get package info // Get package info
entry.PackageInfo, err = ReadPacakgeInfoFromTarball(packagePath) entry.PackageInfo, err = ReadPacakgeInfoFromTarball(packagePath)
if err != nil { if err != nil {
return err return err
} }
// Get package installed size
if entry.PackageInfo.Type == "binary" {
cmd := exec.Command("tar", "xf", packagePath, "pkg.files", "-O")
output, err := cmd.Output()
if err != nil {
return err
}
for _, line := range strings.Split(string(output), "\n") {
line = strings.TrimSpace(line)
if line == "" {
continue
}
stringEntry := strings.Split(line, " ")
if len(stringEntry) < 5 {
return fmt.Errorf("pkg.files is not formatted correctly")
}
size, err := strconv.ParseInt(stringEntry[len(stringEntry)-1], 10, 64)
if err != nil {
return err
}
entry.InstalledSize += size
}
}
// Add entry to database // Add entry to database
if _, ok := database.Entries[entry.PackageInfo.Name]; ok { if _, ok := database.Entries[entry.PackageInfo.Name]; ok {
return fmt.Errorf("package (%s) has already been added to the database", entry.PackageInfo.Name) return fmt.Errorf("package (%s) has already been added to the database", entry.PackageInfo.Name)
+2
View File
@@ -8,6 +8,8 @@ import (
type BPMUtilsConfig struct { type BPMUtilsConfig struct {
PrivilegeEscalatorCmd string `yaml:"privilege_escalator_cmd"` PrivilegeEscalatorCmd string `yaml:"privilege_escalator_cmd"`
DefaultMaintainer string `yaml:"default_maintainer,omitempty"`
AddDefaultMaintainer bool `yaml:"add_default_maintainer,omitempty"`
} }
func ReadBPMUtilsConfig() (*BPMUtilsConfig, error) { func ReadBPMUtilsConfig() (*BPMUtilsConfig, error) {
+11
View File
@@ -4,6 +4,7 @@ import (
"fmt" "fmt"
"os" "os"
"os/exec" "os/exec"
"strconv"
"strings" "strings"
"github.com/drone/envsubst" "github.com/drone/envsubst"
@@ -17,16 +18,20 @@ type PackageInfo struct {
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"`
Maintainers []string `yaml:"maintainers,omitempty"`
Arch string `yaml:"architecture,omitempty"` Arch string `yaml:"architecture,omitempty"`
OutputArch string `yaml:"output_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"`
RuntimeDepends []string `yaml:"runtime_depends,omitempty"`
OptionalDepends []string `yaml:"optional_depends,omitempty"` OptionalDepends []string `yaml:"optional_depends,omitempty"`
MakeDepends []string `yaml:"make_depends,omitempty"` MakeDepends []string `yaml:"make_depends,omitempty"`
CheckDepends []string `yaml:"check_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"`
Options []string `yaml:"options,omitempty"`
Downloads []PackageDownload `yaml:"downloads,omitempty"` Downloads []PackageDownload `yaml:"downloads,omitempty"`
SplitPackages []*PackageInfo `yaml:"split_packages,omitempty"` SplitPackages []*PackageInfo `yaml:"split_packages,omitempty"`
} }
@@ -54,10 +59,12 @@ func ReadPackageInfo(data []byte) (*PackageInfo, error) {
Keep: make([]string, 0), Keep: make([]string, 0),
Depends: make([]string, 0), Depends: make([]string, 0),
MakeDepends: make([]string, 0), MakeDepends: make([]string, 0),
RuntimeDepends: make([]string, 0),
OptionalDepends: make([]string, 0), OptionalDepends: make([]string, 0),
Conflicts: make([]string, 0), Conflicts: make([]string, 0),
Replaces: make([]string, 0), Replaces: make([]string, 0),
Provides: make([]string, 0), Provides: make([]string, 0),
Options: make([]string, 0),
Downloads: make([]PackageDownload, 0), Downloads: make([]PackageDownload, 0),
SplitPackages: make([]*PackageInfo, 0), SplitPackages: make([]*PackageInfo, 0),
} }
@@ -71,6 +78,10 @@ func ReadPackageInfo(data []byte) (*PackageInfo, error) {
return pkgInfo, nil return pkgInfo, nil
} }
func (pkgInfo *PackageInfo) GetFullVersion() string {
return pkgInfo.Version + "-" + strconv.Itoa(pkgInfo.Revision)
}
func ReadPacakgeInfoFromTarball(path string) (*PackageInfo, error) { func ReadPacakgeInfoFromTarball(path string) (*PackageInfo, error) {
// Extract package info using tar // Extract package info using tar
cmd := exec.Command("tar", "-x", "-f", path, "pkg.info", "-O") cmd := exec.Command("tar", "-x", "-f", path, "pkg.info", "-O")