Changes in package format

This commit is contained in:
2026-06-10 11:41:35 +03:00
parent 677da23c9d
commit 140cd3c64b
4 changed files with 87 additions and 47 deletions
+3 -3
View File
@@ -92,7 +92,7 @@ func main() {
currentFlagSet.String("installation-reason", "", "Specify the installation reason to use for the specified packages") currentFlagSet.String("installation-reason", "", "Specify the installation reason to use for the specified packages")
currentFlagSet.BoolP("reinstall", "r", false, "Reinstall the specified packages") currentFlagSet.BoolP("reinstall", "r", false, "Reinstall the specified packages")
currentFlagSet.IntP("jobs", "j", bpmlib.CompilationBPMConfig.CompilationJobs, "Set the amount of concurrent processes to use for source package compilation") currentFlagSet.IntP("jobs", "j", bpmlib.CompilationBPMConfig.CompilationJobs, "Set the amount of concurrent processes to use for source package compilation")
currentFlagSet.BoolP("skip-checks", "s", false, "Skip the check function in source.sh scripts") currentFlagSet.BoolP("skip-checks", "s", false, "Skip the check function in recipe.sh scripts")
setupFlagsAndHelp(currentFlagSet, fmt.Sprintf("bpm %s <options>", subcommand), "Install the specified packages", os.Args[2:]) setupFlagsAndHelp(currentFlagSet, fmt.Sprintf("bpm %s <options>", subcommand), "Install the specified packages", os.Args[2:])
installPackages() installPackages()
@@ -141,7 +141,7 @@ func main() {
currentFlagSet.BoolP("yes", "y", false, "Enter 'yes' in all prompts") currentFlagSet.BoolP("yes", "y", false, "Enter 'yes' in all prompts")
currentFlagSet.BoolP("no-sync", "n", false, "Do not sync databases") currentFlagSet.BoolP("no-sync", "n", false, "Do not sync databases")
currentFlagSet.Bool("allow-downgrades", false, "Allow package downgrades") currentFlagSet.Bool("allow-downgrades", false, "Allow package downgrades")
currentFlagSet.BoolP("skip-checks", "s", false, "Skip the check function in source.sh scripts") currentFlagSet.BoolP("skip-checks", "s", false, "Skip the check function in recipe.sh scripts")
currentFlagSet.IntP("jobs", "j", bpmlib.CompilationBPMConfig.CompilationJobs, "Set the amount of concurrent processes to use for source package compilation") currentFlagSet.IntP("jobs", "j", bpmlib.CompilationBPMConfig.CompilationJobs, "Set the amount of concurrent processes to use for source package compilation")
setupFlagsAndHelp(currentFlagSet, fmt.Sprintf("bpm %s <options>", subcommand), "Update installed packages", os.Args[2:]) setupFlagsAndHelp(currentFlagSet, fmt.Sprintf("bpm %s <options>", subcommand), "Update installed packages", os.Args[2:])
@@ -161,7 +161,7 @@ func main() {
currentFlagSet.BoolP("force", "f", false, "Bypass warnings during package compilation") currentFlagSet.BoolP("force", "f", false, "Bypass warnings during package compilation")
currentFlagSet.BoolP("yes", "y", false, "Enter 'yes' in all prompts") currentFlagSet.BoolP("yes", "y", false, "Enter 'yes' in all prompts")
currentFlagSet.BoolP("depends", "d", false, "Install required dependencies for package compilation") currentFlagSet.BoolP("depends", "d", false, "Install required dependencies for package compilation")
currentFlagSet.BoolP("skip-checks", "s", false, "Skip the check function in source.sh scripts") currentFlagSet.BoolP("skip-checks", "s", false, "Skip the check function in recipe.sh scripts")
currentFlagSet.BoolP("keep", "k", false, "Keep compilation files after successful package compilation") currentFlagSet.BoolP("keep", "k", false, "Keep compilation files after successful package compilation")
currentFlagSet.BoolP("output-directory", "o", false, "Set the output directory for the binary packages") currentFlagSet.BoolP("output-directory", "o", false, "Set the output directory for the binary packages")
currentFlagSet.Int("output-fd", -1, "Set the file descriptor output package names will be written to") currentFlagSet.Int("output-fd", -1, "Set the file descriptor output package names will be written to")
+38 -25
View File
@@ -96,8 +96,8 @@ func CompileSourcePackage(archiveFilename, outputDirectory string, compilationJo
return nil, err return nil, err
} }
// Extract source.sh file // Extract recipe.sh file
err = extractTarballFile(archiveFilename, "source.sh", tempDirectory, uid, gid) err = extractTarballFile(archiveFilename, "recipe.sh", tempDirectory, uid, gid)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -166,10 +166,10 @@ func CompileSourcePackage(archiveFilename, outputDirectory string, compilationJo
env = append(env, "CMAKE_BUILD_PARALLEL_LEVEL="+strconv.Itoa(compilationJobs)) env = append(env, "CMAKE_BUILD_PARALLEL_LEVEL="+strconv.Itoa(compilationJobs))
env = append(env, "CARGO_BUILD_JOBS="+strconv.Itoa(compilationJobs)) env = append(env, "CARGO_BUILD_JOBS="+strconv.Itoa(compilationJobs))
// Execute prepare and build functions in source.sh script // Execute prepare and build functions in recipe.sh script
cmd := exec.Command("bash", "-c", cmd := exec.Command("bash", "-c",
"set -a\n"+ // Source and export functions and variables in source.sh script "set -a\n"+ // Source and export functions and variables in recipe.sh script
". \"${BPM_WORKDIR}\"/source.sh\n"+ ". \"${BPM_WORKDIR}\"/recipe.sh\n"+
"set +a\n"+ "set +a\n"+
"[[ $(type -t prepare) == \"function\" ]] && { echo \"Running prepare() function...\"; bash -e -c 'cd \"$BPM_WORKDIR\" && prepare' || exit 1; }\n"+ // Run prepare() function if it exists "[[ $(type -t prepare) == \"function\" ]] && { echo \"Running prepare() function...\"; bash -e -c 'cd \"$BPM_WORKDIR\" && prepare' || exit 1; }\n"+ // Run prepare() function if it exists
"[[ $(type -t build) == \"function\" ]] && { echo \"Running build() function...\"; bash -e -c 'cd \"$BPM_SOURCE\" && build' || exit 1; }\n"+ // Run build() function if it exists "[[ $(type -t build) == \"function\" ]] && { echo \"Running build() function...\"; bash -e -c 'cd \"$BPM_SOURCE\" && build' || exit 1; }\n"+ // Run build() function if it exists
@@ -187,11 +187,11 @@ func CompileSourcePackage(archiveFilename, outputDirectory string, compilationJo
return nil, err return nil, err
} }
// Execute check function in source.sh script if not skipping checks // Execute check function in recipe.sh script if not skipping checks
if !skipChecks { if !skipChecks {
cmd = exec.Command("bash", "-c", cmd = exec.Command("bash", "-c",
"set -a\n"+ // Source and export functions and variables in source.sh script "set -a\n"+ // Source and export functions and variables in recipe.sh script
". \"${BPM_WORKDIR}\"/source.sh\n"+ ". \"${BPM_WORKDIR}\"/recipe.sh\n"+
"set +a\n"+ "set +a\n"+
"[[ $(type -t check) == \"function\" ]] && { echo \"Running check() function...\"; bash -e -c 'cd \"$BPM_SOURCE\" && check' || exit 1; }\n"+ // Run check() function if it exists "[[ $(type -t check) == \"function\" ]] && { echo \"Running check() function...\"; bash -e -c 'cd \"$BPM_SOURCE\" && check' || exit 1; }\n"+ // Run check() function if it exists
"exit 0") "exit 0")
@@ -238,10 +238,10 @@ func CompileSourcePackage(archiveFilename, outputDirectory string, compilationJo
packageFunctionName = "package_" + pkg.Name packageFunctionName = "package_" + pkg.Name
} }
// Execute package function in source.sh script and generate package file list // Execute package function in recipe.sh script and generate package file list
cmd = exec.Command("bash", "-c", cmd = exec.Command("bash", "-c",
"set -a\n"+ // Source and export functions and variables in source.sh script "set -a\n"+ // Source and export functions and variables in recipe.sh script
". \"${BPM_WORKDIR}\"/source.sh\n"+ ". \"${BPM_WORKDIR}\"/recipe.sh\n"+
"set +a\n"+ "set +a\n"+
"echo \"Running "+packageFunctionName+"() function...\"\n"+ "echo \"Running "+packageFunctionName+"() function...\"\n"+
"( cd \"$BPM_SOURCE\" && fakeroot -s \"$BPM_WORKDIR\"/fakeroot_file bash -e -c '"+packageFunctionName+"' ) || exit 1\n") // Run package() function "( cd \"$BPM_SOURCE\" && fakeroot -s \"$BPM_WORKDIR\"/fakeroot_file bash -e -c '"+packageFunctionName+"' ) || exit 1\n") // Run package() function
@@ -329,7 +329,7 @@ func CompileSourcePackage(archiveFilename, outputDirectory string, compilationJo
// Generate package file list // Generate package file list
fmt.Println("Generating package file list...") fmt.Println("Generating package file list...")
cmd = exec.Command("bash", "-c", "fakeroot -i \"$BPM_WORKDIR\"/fakeroot_file find \"$BPM_OUTPUT\" -mindepth 1 -printf \"%P %#m %U %G %s\\n\" > \"$BPM_WORKDIR\"/pkg.files") cmd = exec.Command("bash", "-c", "fakeroot -i \"$BPM_WORKDIR\"/fakeroot_file find \"$BPM_OUTPUT\" -mindepth 1 -printf \"%P %#m %U %G %s\\n\" > \"$BPM_WORKDIR\"/files.txt")
cmd.Dir = tempDirectory cmd.Dir = tempDirectory
cmd.Stdout = os.Stdout cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr cmd.Stderr = os.Stderr
@@ -345,7 +345,15 @@ func CompileSourcePackage(archiveFilename, outputDirectory string, compilationJo
// Create gzip-compressed archive for the package files // Create gzip-compressed archive for the package files
fmt.Println("Generating compressed file archive...") fmt.Println("Generating compressed file archive...")
cmd = exec.Command("bash", "-c", fmt.Sprintf("find %s -printf \"%%P\\n\" | fakeroot -i %s/fakeroot_file tar -czf files.tar.gz --no-recursion -C %s -T -", "output_"+pkg.Name, tempDirectory, "output_"+pkg.Name)) cmd = exec.Command("bash", "-c", fmt.Sprintf(`find %s -printf "%%P\n" | fakeroot -i %s/fakeroot_file tar czf files.tar.gz \
--sort=name \
--pax-option=exthdr.name=%%d/PaxHeaders/%%f,delete=atime,delete=ctime \
--mtime="UTC 1970-01-01" \
--numeric-owner \
--no-recursion \
-C %s \
-T -`,
"output_"+pkg.Name, tempDirectory, "output_"+pkg.Name))
cmd.Dir = tempDirectory cmd.Dir = tempDirectory
cmd.Stdout = os.Stdout cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr cmd.Stderr = os.Stderr
@@ -380,26 +388,31 @@ func CompileSourcePackage(archiveFilename, outputDirectory string, compilationJo
} }
pkgInfoBytes = append(pkgInfoBytes, '\n') pkgInfoBytes = append(pkgInfoBytes, '\n')
// Create pkg.info file // Create info.yml file
err = os.WriteFile(path.Join(tempDirectory, "pkg.info"), pkgInfoBytes, 0644) err = os.WriteFile(path.Join(tempDirectory, "info.yml"), pkgInfoBytes, 0644)
if err != nil { if err != nil {
return nil, err return nil, err
} }
// Change pkg.info file owner // Change info.yml file owner
err = os.Chown(path.Join(tempDirectory, "pkg.info"), uid, gid) err = os.Chown(path.Join(tempDirectory, "info.yml"), uid, gid)
if err != nil { if err != nil {
return nil, err return nil, err
} }
// Get files to include in BPM archive // Get files to include in BPM archive
bpmArchiveFiles := make([]string, 0) bpmArchiveFiles := make([]string, 0)
bpmArchiveFiles = append(bpmArchiveFiles, "pkg.info", "pkg.files", "files.tar.gz") // Base files bpmArchiveFiles = append(bpmArchiveFiles, "info.yml", "files.txt", "files.tar.gz") // Base files
bpmArchiveFiles = append(bpmArchiveFiles, packageScripts...) // Package scripts bpmArchiveFiles = append(bpmArchiveFiles, packageScripts...) // Package scripts
// Create final BPM archive // Create final BPM archive
fmt.Println("Generating final BPM archive...") fmt.Println("Generating final BPM archive...")
cmd = exec.Command("bash", "-c", "tar -cf final-archive.bpm --owner=0 --group=0 -C \"$BPM_WORKDIR\" "+strings.Join(bpmArchiveFiles, " ")) cmd = exec.Command("tar", "cf", "final-archive.bpm",
"--sort=name",
"--pax-option=exthdr.name=%d/PaxHeaders/%f,delete=atime,delete=ctime",
"--mtime=UTC 1970-01-01",
"--owner=0", "--group=0", "--numeric-owner")
cmd.Args = append(cmd.Args, bpmArchiveFiles...)
cmd.Dir = tempDirectory cmd.Dir = tempDirectory
cmd.Stdout = os.Stdout cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr cmd.Stderr = os.Stderr
@@ -417,8 +430,8 @@ func CompileSourcePackage(archiveFilename, outputDirectory string, compilationJo
return nil, fmt.Errorf("BPM archive could not be created: %s", err) return nil, fmt.Errorf("BPM archive could not be created: %s", err)
} }
// Remove pkg.info file // Remove info.yml file
err = os.Remove(path.Join(tempDirectory, "pkg.info")) err = os.Remove(path.Join(tempDirectory, "info.yml"))
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -725,8 +738,8 @@ func showPackageFiles(archiveFilename string) error {
return nil return nil
} }
// Print pkg.info content // Print info.yml content
err = printTarballContent("pkg.info") err = printTarballContent("info.yml")
if err != nil { if err != nil {
return err return err
} }
@@ -748,8 +761,8 @@ func showPackageFiles(archiveFilename string) error {
} }
} }
// Print source.sh content // Print recipe.sh content
err = printTarballContent("source.sh") err = printTarballContent("recipe.sh")
if err != nil { if err != nil {
return err return err
} }
+37 -10
View File
@@ -63,7 +63,7 @@ func InitializeLocalPackageInformation(rootDir string) (err error) {
} }
// Read package info // Read package info
infoData, err := os.ReadFile(path.Join(installedDir, item.Name(), "info")) infoData, err := os.ReadFile(path.Join(installedDir, item.Name(), "info.yml"))
if err != nil { if err != nil {
return err return err
} }
@@ -220,7 +220,7 @@ func getPackageFiles(pkg, rootDir string) []*PackageFileEntry {
var pkgFiles []*PackageFileEntry var pkgFiles []*PackageFileEntry
installedDir := path.Join(rootDir, "var/lib/bpm/installed/") installedDir := path.Join(rootDir, "var/lib/bpm/installed/")
pkgDir := path.Join(installedDir, pkg) pkgDir := path.Join(installedDir, pkg)
files := path.Join(pkgDir, "files") files := path.Join(pkgDir, "files.txt")
if _, err := os.Stat(installedDir); os.IsNotExist(err) { if _, err := os.Stat(installedDir); os.IsNotExist(err) {
return nil return nil
} }
@@ -280,7 +280,7 @@ func getPackageLocalInfo(pkg, rootDir string) PackageLocalInfo {
installedDir := path.Join(rootDir, "var/lib/bpm/installed/") installedDir := path.Join(rootDir, "var/lib/bpm/installed/")
pkgDir := path.Join(installedDir, pkg) pkgDir := path.Join(installedDir, pkg)
localInfoFile := path.Join(path.Join(pkgDir, "local")) localInfoFile := path.Join(path.Join(pkgDir, "local.yml"))
if _, err := os.Stat(localInfoFile); os.IsNotExist(err) { if _, err := os.Stat(localInfoFile); os.IsNotExist(err) {
return localInfo return localInfo
@@ -304,7 +304,7 @@ func SetPackageLocalInfo(pkg string, localInfo PackageLocalInfo, rootDir string)
installedDir := path.Join(rootDir, "var/lib/bpm/installed/") installedDir := path.Join(rootDir, "var/lib/bpm/installed/")
pkgDir := path.Join(installedDir, pkg) pkgDir := path.Join(installedDir, pkg)
localFile, err := os.OpenFile(path.Join(pkgDir, "local"), os.O_WRONLY|os.O_CREATE, 0644) localFile, err := os.OpenFile(path.Join(pkgDir, "local.yml"), os.O_WRONLY|os.O_CREATE, 0644)
if err != nil { if err != nil {
return err return err
} }
@@ -332,10 +332,35 @@ func UpgradePersistentData(rootDir string) error {
for _, entry := range dirEntries { for _, entry := range dirEntries {
pkgDir := path.Join(persistentDataDir, "installed", entry.Name()) pkgDir := path.Join(persistentDataDir, "installed", entry.Name())
// Generate default local package information file // Rename 'info' file to 'info.yml'
if _, err := os.Stat(path.Join(pkgDir, "local")); err != nil && !os.IsNotExist(err) { if _, err := os.Stat(path.Join(pkgDir, "info")); err == nil {
fmt.Printf("Moving 'info' to 'info.yml' for package (%s)\n", entry.Name())
err := os.Rename(path.Join(pkgDir, "info"), path.Join(pkgDir, "info.yml"))
if err != nil {
return err return err
} else if os.IsNotExist(err) { }
}
// Rename 'files' file to 'files.txt'
if _, err := os.Stat(path.Join(pkgDir, "files")); err == nil {
fmt.Printf("Moving 'files' to 'files.txt' for package (%s)\n", entry.Name())
err := os.Rename(path.Join(pkgDir, "files"), path.Join(pkgDir, "files.txt"))
if err != nil {
return err
}
}
// Rename 'local' file to 'local.yml'
if _, err := os.Stat(path.Join(pkgDir, "local")); err == nil {
fmt.Printf("Moving 'local' to 'local.yml' for package (%s)\n", entry.Name())
err := os.Rename(path.Join(pkgDir, "local"), path.Join(pkgDir, "local.yml"))
if err != nil {
return err
}
}
// Generate default local package information file
if _, err := os.Stat(path.Join(pkgDir, "local.yml")); os.IsNotExist(err) {
fmt.Printf("Generating local package information for package (%s)\n", entry.Name()) fmt.Printf("Generating local package information for package (%s)\n", entry.Name())
out, err := yaml.Marshal(PackageLocalInfo{ out, err := yaml.Marshal(PackageLocalInfo{
@@ -347,10 +372,12 @@ func UpgradePersistentData(rootDir string) error {
return err return err
} }
err = os.WriteFile(path.Join(pkgDir, "local"), out, 0644) err = os.WriteFile(path.Join(pkgDir, "local.yml"), out, 0644)
if err != nil { if err != nil {
return err return err
} }
} else if err != nil {
return err
} }
// Move installation reason to local package information file // Move installation reason to local package information file
@@ -359,7 +386,7 @@ func UpgradePersistentData(rootDir string) error {
} else if err == nil { } else if err == nil {
fmt.Printf("Moving installation reason to local package information for package (%s)\n", entry.Name()) fmt.Printf("Moving installation reason to local package information for package (%s)\n", entry.Name())
data, err := os.ReadFile(path.Join(pkgDir, "local")) data, err := os.ReadFile(path.Join(pkgDir, "local.yml"))
if err != nil { if err != nil {
return err return err
} }
@@ -377,7 +404,7 @@ func UpgradePersistentData(rootDir string) error {
return err return err
} }
err = os.WriteFile(path.Join(pkgDir, "local"), out, 0644) err = os.WriteFile(path.Join(pkgDir, "local.yml"), out, 0644)
if err != nil { if err != nil {
return err return err
} }
+9 -9
View File
@@ -163,7 +163,7 @@ func GetPackageInfoRaw(filename string) (string, error) {
if err != nil { if err != nil {
return "", err return "", err
} }
if header.Name == "pkg.info" { if header.Name == "info.yml" {
bs, _ := io.ReadAll(tr) bs, _ := io.ReadAll(tr)
err := file.Close() err := file.Close()
if err != nil { if err != nil {
@@ -172,7 +172,7 @@ func GetPackageInfoRaw(filename string) (string, error) {
return string(bs), nil return string(bs), nil
} }
} }
return "", errors.New("pkg.info not found in archive") return "", errors.New("info.yml not found in archive")
} }
func ReadPackage(filename string) (*BPMPackage, error) { func ReadPackage(filename string) (*BPMPackage, error) {
@@ -198,13 +198,13 @@ func ReadPackage(filename string) (*BPMPackage, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
if header.Name == "pkg.info" { if header.Name == "info.yml" {
bs, _ := io.ReadAll(tr) bs, _ := io.ReadAll(tr)
pkgInfo, err = ReadPackageInfo(string(bs)) pkgInfo, err = ReadPackageInfo(string(bs))
if err != nil { if err != nil {
return nil, err return nil, err
} }
} else if header.Name == "pkg.files" { } else if header.Name == "files.txt" {
bs, _ := io.ReadAll(tr) bs, _ := io.ReadAll(tr)
for _, line := range strings.Split(string(bs), "\n") { for _, line := range strings.Split(string(bs), "\n") {
if strings.TrimSpace(line) == "" { if strings.TrimSpace(line) == "" {
@@ -212,7 +212,7 @@ func ReadPackage(filename string) (*BPMPackage, error) {
} }
stringEntry := strings.Split(strings.TrimSpace(line), " ") stringEntry := strings.Split(strings.TrimSpace(line), " ")
if len(stringEntry) < 5 { if len(stringEntry) < 5 {
return nil, errors.New("pkg.files is not formatted correctly") return nil, errors.New("files.txt is not formatted correctly")
} }
octalPerms, err := strconv.ParseUint(stringEntry[len(stringEntry)-4], 8, 32) octalPerms, err := strconv.ParseUint(stringEntry[len(stringEntry)-4], 8, 32)
if err != nil { if err != nil {
@@ -242,7 +242,7 @@ func ReadPackage(filename string) (*BPMPackage, error) {
} }
if pkgInfo == nil { if pkgInfo == nil {
return nil, errors.New("pkg.info not found in archive") return nil, errors.New("info.yml not found in archive")
} }
return &BPMPackage{ return &BPMPackage{
PkgInfo: pkgInfo, PkgInfo: pkgInfo,
@@ -1034,12 +1034,12 @@ func installPackage(filename string, installationReason InstallationReason, root
return err return err
} }
f, err := os.Create(path.Join(pkgDir, "files")) f, err := os.Create(path.Join(pkgDir, "files.txt"))
if err != nil { if err != nil {
return err return err
} }
tarballFile, err := readTarballFile(filename, "pkg.files") tarballFile, err := readTarballFile(filename, "files.txt")
if err != nil { if err != nil {
return err return err
} }
@@ -1050,7 +1050,7 @@ func installPackage(filename string, installationReason InstallationReason, root
return err return err
} }
f, err = os.Create(path.Join(pkgDir, "info")) f, err = os.Create(path.Join(pkgDir, "info.yml"))
if err != nil { if err != nil {
return err return err
} }