From 5dbdfdd4c1e5594a0d1c10f5d72ad2dccf59f3d9 Mon Sep 17 00:00:00 2001 From: EnumDev Date: Sat, 25 Apr 2026 10:46:10 +0300 Subject: [PATCH] Move package recipes to separate directory --- src/bpm-package/main.go | 53 +++++++------- src/bpm-repo/main.go | 135 +++++++++++++++++++---------------- src/bpm-setup/main.go | 67 ++++++++++------- src/bpm-utils-shared/repo.go | 29 ++++++++ 4 files changed, 169 insertions(+), 115 deletions(-) diff --git a/src/bpm-package/main.go b/src/bpm-package/main.go index 4b0480b..9b9ee5a 100644 --- a/src/bpm-package/main.go +++ b/src/bpm-package/main.go @@ -26,7 +26,6 @@ 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 moveToBinaryDir = flag.BoolP("move", "m", false, "Move output packages to the current repository's binary directory") 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") @@ -44,6 +43,10 @@ func main() { if *compile { compilePackage(outputFile) } + + if repo := bpmutilsshared.GetRepository(); repo != "" { + bpmutilsshared.UpdateDatabases(repo) + } } func runChecks() { @@ -138,32 +141,35 @@ func createArchive() string { } } - // Remove old BPM archives in current directory - oldArchives, err := filepath.Glob("*.bpm") - if err != nil { - log.Printf("Warning: could not search for old BPM archives: %s", err) - } - for _, bpmArchive := range oldArchives { - err = os.Remove(bpmArchive) - if err != nil { - log.Printf("Warning: could not remove old BPM archive (%s): %s", bpmArchive, err) - } - } + // Remove old package from source dir + if repo := bpmutilsshared.GetRepository(); repo != "" { + if database, err := bpmutilsshared.ReadDatabase(path.Join(repo, "source/database.bpmdb")); err == nil { + if entry, ok := database.Entries[pkgInfo.Name]; ok { + pkgFilepath := path.Join(repo, "source", entry.Filepath) + err := os.Remove(pkgFilepath) + if err != nil { + log.Printf("Warning: could not remove old source package (%s): %s", pkgFilepath, err) + } - // 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) + // 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 source package signature (%s): %s", pkgFilepath+".str", err) + } + } + } } } // Create filename filename := fmt.Sprintf("%s-%s-%d-%s-src.bpm", pkgInfo.Name, pkgInfo.Version, pkgInfo.Revision, pkgInfo.Arch) + if repo := bpmutilsshared.GetRepository(); repo != "" { + // Create source directory + os.MkdirAll(path.Join(repo, "source", pkgInfo.Arch), 0755) + + filename = path.Join(repo, "source", pkgInfo.Arch, filename) + } // Create archive using tar args := make([]string, 0) @@ -263,7 +269,7 @@ func compilePackage(archive string) { // Read generated package info pkgInfo, err := bpmutilsshared.ReadPacakgeInfoFromTarball(line) - if repo := bpmutilsshared.GetRepository(); repo != "" && *moveToBinaryDir { + if repo := bpmutilsshared.GetRepository(); repo != "" { // Remove old package from binary dir if database, err := bpmutilsshared.ReadDatabase(path.Join(repo, "binary/database.bpmdb")); err == nil { if entry, ok := database.Entries[pkgInfo.Name]; ok { @@ -296,9 +302,6 @@ func compilePackage(archive string) { outputPkgs[pkgInfo.Name] = line } } - if repo := bpmutilsshared.GetRepository(); repo != "" && *moveToBinaryDir { - bpmutilsshared.UpdateDatabases(repo) - } // Sign package if *signPackage { diff --git a/src/bpm-repo/main.go b/src/bpm-repo/main.go index 8557620..58abdb3 100644 --- a/src/bpm-repo/main.go +++ b/src/bpm-repo/main.go @@ -147,7 +147,7 @@ func createRepository(name, description string) { log.Fatalf("Error: could not write to file: %s", err) } - err = os.Mkdir(path.Join(name, "source"), 0755) + err = os.Mkdir(path.Join(name, "recipes"), 0755) if err != nil { log.Fatalf("Error: could not create directory: %s", err) } @@ -185,14 +185,14 @@ func checkVersionsFunc(repo string) { directories := make([]string, 0) if currentFlagSet.NArg() > 0 { for _, dir := range currentFlagSet.Args() { - if _, err := os.Stat(path.Join(repo, "source", dir, "pkg.info")); err != nil { + 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) } - directories = append(directories, path.Join(repo, "source", dir)) + directories = append(directories, path.Join(repo, "recipes", dir)) } } else { // Loop through each directory with a 'pkg.info' file - err := filepath.Walk(path.Join(repo, "source"), func(path string, info fs.FileInfo, err error) error { + err := filepath.Walk(path.Join(repo, "recipes"), func(path string, info fs.FileInfo, err error) error { if filepath.Base(path) == "pkg.info" { directories = append(directories, filepath.Dir(path)) } @@ -375,7 +375,7 @@ func holdPackage(repo string) { } // Ensure package exists - if _, err := os.Stat(path.Join(repo, "source", pkgName, "pkg.info")); err != nil { + 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) } @@ -435,44 +435,40 @@ func holdPackage(repo string) { } func listPackagesFunc(repo string) { + // Read package recipes + pkgs := bpmutilsshared.ReadRepositoryRecipes(repo) + // Read databases - sourceDatabase, err := bpmutilsshared.ReadDatabase(path.Join(repo, "source/database.bpmdb")) - if err != nil { - return - } + sourceDatabase, _ := bpmutilsshared.ReadDatabase(path.Join(repo, "source/database.bpmdb")) + binaryDatabase, _ := bpmutilsshared.ReadDatabase(path.Join(repo, "binary/database.bpmdb")) - binaryDatabase, err := bpmutilsshared.ReadDatabase(path.Join(repo, "binary/database.bpmdb")) - if err != nil { - binaryDatabase = &bpmutilsshared.BPMDatabase{} - } + for _, pkg := range pkgs { + fmt.Printf("%s (%s):\n", pkg.Name, pkg.Version) - // Sort database entries - entriesSorted := slices.Collect(maps.Values(sourceDatabase.Entries)) - sort.Slice(entriesSorted, func(i, j int) bool { - return entriesSorted[i].PackageInfo.Name < entriesSorted[j].PackageInfo.Name - }) - - // Loop through each entry - for _, entry := range entriesSorted { - if len(entry.PackageInfo.SplitPackages) > 0 { - for _, splitPkg := range entry.PackageInfo.SplitPackages { - // Handle split packages - additionalText := "" - if binaryEntry, ok := binaryDatabase.Entries[splitPkg.Name]; !ok { - additionalText += "(Binary package missing) " - } else if fmt.Sprintf("%s-%d", binaryEntry.PackageInfo.Version, binaryEntry.PackageInfo.Revision) != fmt.Sprintf("%s-%d", entry.PackageInfo.Version, entry.PackageInfo.Revision) { - additionalText += "(Binary package version mismatch) " + // Show source package version + if sourceDatabase != nil { + if entry, ok := sourceDatabase.Entries[pkg.Name]; ok { + if entry.PackageInfo.Version == pkg.Version { + fmt.Printf(" Source package: %s\n", entry.PackageInfo.Version) + } else { + fmt.Printf(" Source package: %s ≠ %s (Version mismatch)\n", entry.PackageInfo.Version, pkg.Version) } - fmt.Printf("%s %s-%d %s\n", splitPkg.Name, entry.PackageInfo.Version, entry.PackageInfo.Revision, additionalText) + } else { + fmt.Println(" Source package not found!") } - } else { - additionalText := "" - if binaryEntry, ok := binaryDatabase.Entries[entry.PackageInfo.Name]; !ok { - additionalText += "(Binary package missing) " - } else if fmt.Sprintf("%s-%d", binaryEntry.PackageInfo.Version, binaryEntry.PackageInfo.Revision) != fmt.Sprintf("%s-%d", entry.PackageInfo.Version, entry.PackageInfo.Revision) { - additionalText += "(Binary package version mismatch) " + } + + // Show binary package version + if binaryDatabase != nil { + if entry, ok := binaryDatabase.Entries[pkg.Name]; ok { + if entry.PackageInfo.Version == pkg.Version { + fmt.Printf(" Binary package: %s\n", entry.PackageInfo.Version) + } else { + fmt.Printf(" Binary package: %s ≠ %s (Version mismatch)\n", entry.PackageInfo.Version, pkg.Version) + } + } else { + fmt.Println(" Binary package not found!") } - fmt.Printf("%s %s-%d %s\n", entry.PackageInfo.Name, entry.PackageInfo.Version, entry.PackageInfo.Revision, additionalText) } } } @@ -489,27 +485,22 @@ func compileAllPackagesFunc(repo string) { log.Fatalf("Error: failed to read config: %s", err) } - // Ensure database is updated - bpmutilsshared.UpdateDatabases(repo) + // Read package recipes + pkgs := bpmutilsshared.ReadRepositoryRecipes(repo) + pkgsMap := make(map[string]bpmutilsshared.PackageInfo) + for _, pkg := range pkgs { + pkgsMap[pkg.Name] = pkg + } // 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 { + 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 { @@ -524,12 +515,12 @@ func compileAllPackagesFunc(repo string) { for _, depend := range depends { // Find package in repository - dependEntry, ok := sourceDatabase.Entries[depend] + dependInfo, ok := pkgsMap[depend] if !ok { // Search for virtual package - for _, entry := range sourceDatabase.Entries { - if slices.Contains(entry.PackageInfo.Provides, depend) { - dependEntry = entry + for _, pkg := range pkgsMap { + if slices.Contains(pkg.Provides, depend) { + dependInfo = pkg ok = true break } @@ -540,30 +531,48 @@ func compileAllPackagesFunc(repo string) { } } - err := visit(dependEntry.PackageInfo) + err := visit(dependInfo) if err != nil && verbose { - fmt.Printf("Circular dependency found! (%s -> %s)\n", pkgInfo.Name, dependEntry.PackageInfo.Name) + fmt.Printf("Circular dependency found! (%s -> %s)\n", pkgInfo.Name, dependInfo.Name) } } marked[pkgInfo.Name] = 2 - sorted = append(sorted, *pkgInfo) + sorted = append(sorted, pkgInfo) return nil } - for _, entry := range packages { - if mark, _ := marked[entry.PackageInfo.Name]; mark != 2 { - visit(entry.PackageInfo) + for _, pkg := range pkgsMap { + if mark, _ := marked[pkg.Name]; mark != 2 { + visit(pkg) } } // 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 + skip := false + + if modifiedOnly { + skip = true + + // Check if source database entry is not synced + if sourceDatabase != nil { + if sourcePkgInfo, ok := sourceDatabase.Entries[pkgInfo.Name]; !ok || sourcePkgInfo.PackageInfo.GetFullVersion() != pkgInfo.GetFullVersion() { + skip = false + } } + + // Check if binary database entry is not synced + if binaryDatabase != nil { + if binaryPkgInfo, ok := binaryDatabase.Entries[pkgInfo.Name]; !ok || binaryPkgInfo.PackageInfo.GetFullVersion() != pkgInfo.GetFullVersion() { + skip = false + } + } + } + + if skip { + continue } if showOrder { diff --git a/src/bpm-setup/main.go b/src/bpm-setup/main.go index 9e671bc..f1b4877 100644 --- a/src/bpm-setup/main.go +++ b/src/bpm-setup/main.go @@ -10,14 +10,12 @@ import ( "os" "os/exec" "path" - "path/filepath" "strings" flag "github.com/spf13/pflag" yaml "gopkg.in/yaml.v3" ) -var directory = flag.StringP("directory", "D", "", "Path to package directory") var name = flag.StringP("name", "n", "", "Set the package name") var description = flag.StringP("description", "d", "Default Package Description", "Set the description") var version = flag.StringP("version", "v", "1.0", "Set the package version") @@ -26,20 +24,35 @@ var license = flag.StringP("license", "l", "", "Set the package licenses") var template = flag.StringP("template", "t", "gnu-configure", "Set the package template") var git = flag.BoolP("git", "g", true, "Create git repository") +var directory = "" + func main() { // Setup flags and help setupFlagsAndHelp("bpm-setup ", "Sets up files and directories for BPM source package creation") + // Trim package name + *name = strings.TrimSpace(*name) + // Show command help if no directory name is given - if *directory == "" { - log.Println("Error: directory flag is required") + if *name == "" { + log.Println("Error: name flag is required") flag.Usage() os.Exit(1) } - // Set package name to directory name if empty - if *name == "" { - *name = filepath.Base(*directory) + // Get current repository + repo := bpmutilsshared.GetRepository() + + // Set directory + if repo != "" { + directory = path.Join(repo, "recipes", *name) + } else { + workDir, err := os.Getwd() + if err != nil { + log.Fatalf("Error: could not get working directory") + } + + directory = path.Join(workDir, *name) } // run checks @@ -62,25 +75,29 @@ func main() { } func runChecks() { - if strings.TrimSpace(*directory) == "" { - log.Fatalf("No directory was specified!") + // Check if package name is valid + if *name == "" { + log.Fatalf("Error: no package name was specified!") } - if strings.TrimSpace(*name) == "" { - log.Fatalf("No package name was specified!") + // Check if parent directory is valid + if _, err := os.Stat(path.Dir(directory)); err != nil { + log.Fatalf("Error: %s is not a valid directory: %s", path.Dir(directory), err) } + // Check if package directory exists + if _, err := os.Stat(directory); err == nil { + log.Fatalf("Error: %s already exists", directory) + } + + // Check if template file is valid if stat, err := os.Stat(path.Join("/etc/bpm-utils/templates/", *template)); err != nil || stat.IsDir() { - log.Fatalf("%s is not a valid template file!", *template) + log.Fatalf("Error: '%s' is not a valid template file!", *template) } } func showSummary() { - absPath, err := filepath.Abs(strings.TrimSpace(*directory)) - if err != nil { - log.Fatalf("Failed to determine absolute path: %s", err) - } - fmt.Printf("Setting up package directory at %s with the following information:\n", absPath) + fmt.Printf("Setting up package directory at %s with the following information:\n", directory) fmt.Printf("Package name: %s\n", strings.TrimSpace(*name)) fmt.Printf("Package description: %s\n", *description) fmt.Printf("Package version: %s\n", *version) @@ -114,12 +131,8 @@ func createDirectory() { log.Fatalf("Error: failed to read config: %s", err) } - // Trim spaces - *directory = strings.TrimSpace(*directory) - *name = strings.TrimSpace(*name) - // Create directory - err = os.Mkdir(*directory, 0755) + err = os.Mkdir(directory, 0755) if err != nil { log.Fatalf("Error: could not create directory: %s", err) } @@ -153,13 +166,13 @@ 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, "pkg.info"), buffer.Bytes(), 0644) if err != nil { log.Fatalf("Could not write to pkg.info: %s", err) } // Create source-files directory - err = os.Mkdir(path.Join(*directory, "source-files"), 0755) + err = os.Mkdir(path.Join(directory, "source-files"), 0755) if err != nil { log.Fatalf("Error: could not create directory: %s", err) } @@ -174,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, "source.sh"), input, 0644) if err != nil { log.Fatalf("Error: could not write to source file: %s", err) return @@ -182,7 +195,7 @@ func createDirectory() { // Create git repository if git != nil && *git { - err = exec.Command("git", "init", *directory).Run() + err = exec.Command("git", "init", directory).Run() if err != nil { log.Fatalf("Error: could not initialize git repository: %s", err) } @@ -193,7 +206,7 @@ func createDirectory() { return } defer defaultGitignoreFile.Close() - newGitignoreFile, err := os.OpenFile(path.Join(*directory, ".gitignore"), os.O_CREATE|os.O_WRONLY, 0644) + newGitignoreFile, err := os.OpenFile(path.Join(directory, ".gitignore"), os.O_CREATE|os.O_WRONLY, 0644) if err != nil { log.Fatalf("Error: could not create .gitignore file: %s", err) } diff --git a/src/bpm-utils-shared/repo.go b/src/bpm-utils-shared/repo.go index 12186d5..fdf44fe 100644 --- a/src/bpm-utils-shared/repo.go +++ b/src/bpm-utils-shared/repo.go @@ -3,6 +3,7 @@ package bpm_utils_shared import ( "os" "path" + "sort" ) func GetRepository() string { @@ -23,3 +24,31 @@ func GetRepository() string { } return dir } + +func ReadRepositoryRecipes(repository string) []PackageInfo { + // Read package recipes + recipeDirs, err := os.ReadDir(path.Join(repository, "recipes")) + if err != nil { + return nil + } + + pkgs := make([]PackageInfo, 0) + for _, dir := range recipeDirs { + pkgInfoPath := path.Join(repository, "recipes", dir.Name(), "pkg.info") + if _, err := os.Stat(pkgInfoPath); err != nil { + continue + } + + pkgInfo, err := ReadPacakgeInfoFromFile(pkgInfoPath) + if err == nil { + pkgs = append(pkgs, *pkgInfo) + } + } + + // Sort package recipes + sort.Slice(pkgs, func(i, j int) bool { + return pkgs[i].Name < pkgs[j].Name + }) + + return pkgs +}