From 3f84dd4bc3ebacb57b414d1cdccc9271ae78f58e Mon Sep 17 00:00:00 2001 From: EnumDev Date: Wed, 10 Jun 2026 11:41:08 +0300 Subject: [PATCH] Update to new package format --- README.md | 8 +-- config/templates/cargo | 2 +- config/templates/cmake | 2 +- config/templates/gnu-configure | 2 +- config/templates/gnu-make | 2 +- config/templates/meson | 2 +- config/templates/python-module | 2 +- config/templates/rust | 4 +- src/bpm-package/main.go | 42 +++++++-------- src/bpm-repo/main.go | 87 +++++++++++++++++++++++++------- src/bpm-setup/main.go | 6 +-- src/bpm-utils-shared/database.go | 4 +- src/bpm-utils-shared/package.go | 2 +- src/bpm-utils-shared/repo.go | 2 +- 14 files changed, 109 insertions(+), 58 deletions(-) diff --git a/README.md b/README.md index f182f92..b6e7780 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ Creating a package for BPM with these utilities is simple bpm-setup -D my_package ``` 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 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 +3) You may wish to edit the info.yml 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 name: my_package description: My package's description @@ -61,9 +61,9 @@ downloads: 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 -5) You now need to edit your source.sh file which contains the compilation instructions for your package, the default source template comments should explain the basic process of compiling your program and how to edit it -6) When you are done editing your source.sh script run the following command to create a BPM source package archive. You may run the `bpm-package` command with no arguments to get an explanation of what each flag does +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 recipe.sh file during compilation +5) You now need to edit your recipe.sh file which contains the compilation instructions for your package, the default source template comments should explain the basic process of compiling your program and how to edit it +6) When you are done editing your recipe.sh script run the following command to create a BPM source package archive. You may run the `bpm-package` command with no arguments to get an explanation of what each flag does ``` bpm-package ``` diff --git a/config/templates/cargo b/config/templates/cargo index 7c1a965..d9aa156 100644 --- a/config/templates/cargo +++ b/config/templates/cargo @@ -1,4 +1,4 @@ -# This is the source.sh script. It is executed by BPM in a temporary directory when compiling a source package +# This is the recipe.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 diff --git a/config/templates/cmake b/config/templates/cmake index b7da340..9ddd444 100644 --- a/config/templates/cmake +++ b/config/templates/cmake @@ -1,4 +1,4 @@ -# This is the source.sh script. It is executed by BPM in a temporary directory when compiling a source package +# This is the recipe.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 diff --git a/config/templates/gnu-configure b/config/templates/gnu-configure index d80723a..01522dc 100644 --- a/config/templates/gnu-configure +++ b/config/templates/gnu-configure @@ -1,4 +1,4 @@ -# This is the source.sh script. It is executed by BPM in a temporary directory when compiling a source package +# This is the recipe.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 diff --git a/config/templates/gnu-make b/config/templates/gnu-make index cda80e2..5ee3e2a 100644 --- a/config/templates/gnu-make +++ b/config/templates/gnu-make @@ -1,4 +1,4 @@ -# This is the source.sh script. It is executed by BPM in a temporary directory when compiling a source package +# This is the recipe.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 diff --git a/config/templates/meson b/config/templates/meson index 81774bb..ed26b3f 100644 --- a/config/templates/meson +++ b/config/templates/meson @@ -1,4 +1,4 @@ -# This is the source.sh script. It is executed by BPM in a temporary directory when compiling a source package +# This is the recipe.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 diff --git a/config/templates/python-module b/config/templates/python-module index 0b0a7d0..4935476 100644 --- a/config/templates/python-module +++ b/config/templates/python-module @@ -1,4 +1,4 @@ -# This is the source.sh script. It is executed by BPM in a temporary directory when compiling a source package +# This is the recipe.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 diff --git a/config/templates/rust b/config/templates/rust index 7d78d7d..4c7cf5d 100644 --- a/config/templates/rust +++ b/config/templates/rust @@ -1,4 +1,4 @@ -# This is the source.sh script. It is executed by BPM in a temporary directory when compiling a source package +# This is the recipe.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 @@ -6,7 +6,7 @@ # 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')" + cargo fetch --locked --target "$(rustc --print host-tuple)" } # The build function is executed in the source directory diff --git a/src/bpm-package/main.go b/src/bpm-package/main.go index 9b9ee5a..3c9e16f 100644 --- a/src/bpm-package/main.go +++ b/src/bpm-package/main.go @@ -26,7 +26,7 @@ var keepCompilationFiles = flag.BoolP("keep", "k", false, "Keep compilation file 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 compilationJobs = flag.IntP("jobs", "j", 0, "Set the amount of concurrent processes to use for source package compilation") -var updateInfo = flag.BoolP("update-info", "u", false, "Update the pkg.info file") +var updateInfo = flag.BoolP("update-info", "u", false, "Update the info.yml file") var signPackage = flag.BoolP("sign", "s", false, "Sign package using GPG") var yesAll = flag.BoolP("yes", "y", false, "Accept all confirmation prompts") @@ -50,14 +50,14 @@ func main() { } func runChecks() { - // Check if pkg.info file exists - if stat, err := os.Stat("pkg.info"); err != nil || !stat.Mode().IsRegular() { - log.Fatalf("Error: pkg.info does not exist or is not a regular file") + // Check if info.yml file exists + if stat, err := os.Stat("info.yml"); err != nil || !stat.Mode().IsRegular() { + log.Fatalf("Error: info.yml does not exist or is not a regular file") } - // Check if source.sh file exists - if stat, err := os.Stat("source.sh"); err != nil || !stat.Mode().IsRegular() { - log.Fatalf("Error: pkg.info does not exist or is not a regular file") + // Check if recipe.sh file exists + if stat, err := os.Stat("recipe.sh"); err != nil || !stat.Mode().IsRegular() { + log.Fatalf("Error: info.yml does not exist or is not a regular file") } } @@ -71,7 +71,7 @@ func createArchive() string { filesToInclude := make([]string, 0) // Include base files - filesToInclude = append(filesToInclude, "pkg.info", "source.sh") + filesToInclude = append(filesToInclude, "info.yml", "recipe.sh") // Check if non-empty source-files directory exists and include it if stat, err := os.Stat("source-files"); err == nil && stat.IsDir() { @@ -90,13 +90,13 @@ func createArchive() string { } } - // Read pkg.info file - pkgInfo, err := bpmutilsshared.ReadPacakgeInfoFromFile("pkg.info") + // Read info.yml file + pkgInfo, err := bpmutilsshared.ReadPacakgeInfoFromFile("info.yml") if err != nil { log.Fatalf("Error: could not read package info: %s", err) } - // Update pkg.info file + // Update info.yml file if *updateInfo { // Update download checksums for i, download := range pkgInfo.Downloads { @@ -128,16 +128,16 @@ func createArchive() string { log.Fatalf("Could not marshal package info: %s", err) } - // Stat pkg.info - stat, err := os.Stat("pkg.info") + // Stat info.yml + stat, err := os.Stat("info.yml") if err != nil { - log.Fatalf("Could not stat pkg.info: %s", err) + log.Fatalf("Could not stat info.yml: %s", err) } // Write package info back to file - err = os.WriteFile("pkg.info", data.Bytes(), stat.Mode().Perm()) + err = os.WriteFile("info.yml", data.Bytes(), stat.Mode().Perm()) if err != nil { - log.Fatalf("Could not write package info to pkg.info: %s", err) + log.Fatalf("Could not write package info to info.yml: %s", err) } } @@ -172,10 +172,12 @@ func createArchive() string { } // Create archive using tar - args := make([]string, 0) - args = append(args, "-c", "--owner=0", "--group=0", "--no-same-owner", "-f", filename) - args = append(args, filesToInclude...) - cmd := exec.Command("tar", args...) + cmd := exec.Command("tar", "cf", filename, + "--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, filesToInclude...) cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr err = cmd.Run() diff --git a/src/bpm-repo/main.go b/src/bpm-repo/main.go index 95e3a46..354a7ec 100644 --- a/src/bpm-repo/main.go +++ b/src/bpm-repo/main.go @@ -185,15 +185,15 @@ func checkVersionsFunc(repo string) { directories := make([]string, 0) if currentFlagSet.NArg() > 0 { for _, dir := range currentFlagSet.Args() { - if _, err := os.Stat(path.Join(repo, "recipes", dir, "pkg.info")); err != nil { - log.Fatalf("Error: could not find pkg.info file in directory (%s): %s", dir, err) + if _, err := os.Stat(path.Join(repo, "recipes", dir, "info.yml")); err != nil { + log.Fatalf("Error: could not find info.yml file in directory (%s): %s", dir, err) } directories = append(directories, path.Join(repo, "recipes", dir)) } } else { - // Loop through each directory with a 'pkg.info' file + // Loop through each directory with a 'info.yml' file err := filepath.Walk(path.Join(repo, "recipes"), func(path string, info fs.FileInfo, err error) error { - if filepath.Base(path) == "pkg.info" { + if filepath.Base(path) == "info.yml" { directories = append(directories, filepath.Dir(path)) } return nil @@ -212,7 +212,7 @@ func checkVersionsFunc(repo string) { }, 0) pkgsUpToDate := 0 for _, dir := range directories { - pkgInfo, err := bpmutilsshared.ReadPacakgeInfoFromFile(path.Join(dir, "pkg.info")) + pkgInfo, err := bpmutilsshared.ReadPacakgeInfoFromFile(path.Join(dir, "info.yml")) if err != nil { log.Fatalf("Could not read package info: %s", err) } @@ -294,7 +294,7 @@ func checkVersionsFunc(repo string) { encoder.Encode(pkgInfo) // Write package information - err := os.WriteFile(path.Join(dir, "pkg.info"), data.Bytes(), 0644) + err := os.WriteFile(path.Join(dir, "info.yml"), data.Bytes(), 0644) if err != nil { log.Printf("Warning: could not write new version for package (%s) to file: %s", pkgInfo.Name, err) } @@ -379,8 +379,8 @@ func holdPackage(repo string) { } // Ensure package exists - if _, err := os.Stat(path.Join(repo, "recipes", pkgName, "pkg.info")); err != nil { - log.Fatalf("Error: could not find pkg.info file in directory (%s): %s", pkgName, err) + if _, err := os.Stat(path.Join(repo, "recipes", pkgName, "info.yml")); err != nil { + log.Fatalf("Error: could not find info.yml file in directory (%s): %s", pkgName, err) } // Read version cache @@ -494,6 +494,13 @@ func compileAllPackagesFunc(repo string) { pkgsMap := make(map[string]bpmutilsshared.PackageInfo) for _, pkg := range pkgs { pkgsMap[pkg.Name] = pkg + + // Add split packages + for _, splitPkg := range pkg.SplitPackages { + if _, ok := pkgsMap[splitPkg.Name]; !ok { + pkgsMap[splitPkg.Name] = pkg + } + } } // Read databases @@ -508,7 +515,7 @@ func compileAllPackagesFunc(repo string) { if mark, _ := marked[pkgInfo.Name]; mark == 2 { return nil } else if mark == 1 { - return fmt.Errorf("Circular dependency found!") + return fmt.Errorf("circular dependency found") } marked[pkgInfo.Name] = 1 @@ -518,12 +525,15 @@ func compileAllPackagesFunc(repo string) { depends = append(depends, pkgInfo.MakeDepends...) for _, depend := range depends { + dependName, _, _ := bpmutilsshared.SplitPkgNameAndVersion(depend) + // Find package in repository - dependInfo, ok := pkgsMap[depend] + dependInfo, ok := pkgsMap[dependName] + if !ok { // Search for virtual package for _, pkg := range pkgsMap { - if slices.Contains(pkg.Provides, depend) { + if slices.Contains(pkg.Provides, dependName) { dependInfo = pkg ok = true break @@ -531,13 +541,24 @@ func compileAllPackagesFunc(repo string) { } if !ok { + // Try to see if package exists in BPM's other repositories + err := exec.Command("bpm", "query", "-d", depend).Run() + if err != nil { + return fmt.Errorf("could not find package (%s) in any database", depend) + } continue } } err := visit(dependInfo) - if err != nil && verbose { - fmt.Printf("Circular dependency found! (%s -> %s)\n", pkgInfo.Name, dependInfo.Name) + if err != nil { + if strings.Contains(err.Error(), "circular") { + if verbose { + fmt.Printf("Circular dependency found! (%s -> %s)\n", pkgInfo.Name, dependInfo.Name) + } + } else { + log.Fatalf("Error: could not resolve dependencies: %s", err) + } } } @@ -560,6 +581,32 @@ func compileAllPackagesFunc(repo string) { if modifiedOnly { skip = true + // Check if required version is valid + for _, depend := range pkgInfo.Depends { + if !strings.ContainsRune(depend, '=') { + continue + } + + dependName, _, _ := bpmutilsshared.SplitPkgNameAndVersion(depend) + + if !bpmutilsshared.EvaluateDependency(depend, pkgsMap[dependName].Version) { + skip = false + break + } + } + for _, depend := range pkgInfo.MakeDepends { + if !strings.ContainsRune(depend, '=') { + continue + } + + dependName, _, _ := bpmutilsshared.SplitPkgNameAndVersion(depend) + + if !bpmutilsshared.EvaluateDependency(depend, pkgsMap[dependName].Version) { + skip = false + break + } + } + // Check if source database entry is not synced if sourceDatabase != nil { if len(pkgInfo.SplitPackages) != 0 { @@ -634,12 +681,14 @@ func compileAllPackagesFunc(repo string) { } // 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) + if !showOrder { + 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) + } } } diff --git a/src/bpm-setup/main.go b/src/bpm-setup/main.go index f1b4877..843000d 100644 --- a/src/bpm-setup/main.go +++ b/src/bpm-setup/main.go @@ -166,9 +166,9 @@ func createDirectory() { encoder.Encode(&pkgInfo) // Write package info to file - err = os.WriteFile(path.Join(directory, "pkg.info"), buffer.Bytes(), 0644) + err = os.WriteFile(path.Join(directory, "info.yml"), buffer.Bytes(), 0644) if err != nil { - log.Fatalf("Could not write to pkg.info: %s", err) + log.Fatalf("Could not write to info.yml: %s", err) } // Create source-files directory @@ -187,7 +187,7 @@ func createDirectory() { // Replace variables in template file input = []byte(replaceVariables(string(input))) - err = os.WriteFile(path.Join(directory, "source.sh"), input, 0644) + err = os.WriteFile(path.Join(directory, "recipe.sh"), input, 0644) if err != nil { log.Fatalf("Error: could not write to source file: %s", err) return diff --git a/src/bpm-utils-shared/database.go b/src/bpm-utils-shared/database.go index cd790fd..17f4a73 100644 --- a/src/bpm-utils-shared/database.go +++ b/src/bpm-utils-shared/database.go @@ -72,7 +72,7 @@ func GenerateDatabase(path string) error { // Get package installed size if entry.PackageInfo.Type == "binary" { - cmd := exec.Command("tar", "xf", packagePath, "pkg.files", "-O") + cmd := exec.Command("tar", "xf", packagePath, "files.txt", "-O") output, err := cmd.Output() if err != nil { return err @@ -85,7 +85,7 @@ func GenerateDatabase(path string) error { } stringEntry := strings.Split(line, " ") if len(stringEntry) < 5 { - return fmt.Errorf("pkg.files is not formatted correctly") + return fmt.Errorf("files.txt is not formatted correctly") } size, err := strconv.ParseInt(stringEntry[len(stringEntry)-1], 10, 64) if err != nil { diff --git a/src/bpm-utils-shared/package.go b/src/bpm-utils-shared/package.go index b55bf52..701fc1a 100644 --- a/src/bpm-utils-shared/package.go +++ b/src/bpm-utils-shared/package.go @@ -85,7 +85,7 @@ func (pkgInfo *PackageInfo) GetFullVersion() string { func ReadPacakgeInfoFromTarball(path string) (*PackageInfo, error) { // Extract package info using tar - cmd := exec.Command("tar", "-x", "-f", path, "pkg.info", "-O") + cmd := exec.Command("tar", "-x", "-f", path, "info.yml", "-O") output, err := cmd.Output() if err != nil { return nil, err diff --git a/src/bpm-utils-shared/repo.go b/src/bpm-utils-shared/repo.go index fdf44fe..55db0ef 100644 --- a/src/bpm-utils-shared/repo.go +++ b/src/bpm-utils-shared/repo.go @@ -34,7 +34,7 @@ func ReadRepositoryRecipes(repository string) []PackageInfo { pkgs := make([]PackageInfo, 0) for _, dir := range recipeDirs { - pkgInfoPath := path.Join(repository, "recipes", dir.Name(), "pkg.info") + pkgInfoPath := path.Join(repository, "recipes", dir.Name(), "info.yml") if _, err := os.Stat(pkgInfoPath); err != nil { continue }