From d8a42c780d4dc20ce1943d5198427fca1bbe78ac Mon Sep 17 00:00:00 2001 From: EnumDev Date: Thu, 1 May 2025 16:40:42 +0300 Subject: [PATCH] Allow direct split source package installation through local BPM archive --- src/bpmlib/compilation.go | 31 ++---------------- src/bpmlib/general.go | 27 +++++++++++++--- src/bpmlib/operations.go | 34 +++++++++++++++----- src/bpmlib/packages.go | 66 ++++++++++++++++++++++++++++++++++++--- 4 files changed, 112 insertions(+), 46 deletions(-) diff --git a/src/bpmlib/compilation.go b/src/bpmlib/compilation.go index caa6075..7e7ce31 100644 --- a/src/bpmlib/compilation.go +++ b/src/bpmlib/compilation.go @@ -175,21 +175,17 @@ func CompileSourcePackage(archiveFilename, outputDirectory string, skipChecks bo } } - // Variable that will be used later - isSplitPkg := true - // Get all packages to compile packagesToCompile := bpmpkg.PkgInfo.SplitPackages - if len(packagesToCompile) == 0 { + if !bpmpkg.PkgInfo.IsSplitPackage() { packagesToCompile = append(packagesToCompile, bpmpkg.PkgInfo) - isSplitPkg = false } // Compile each package for _, pkg := range packagesToCompile { // Get package function name packageFunctionName := "package" - if isSplitPkg { + if bpmpkg.PkgInfo.IsSplitPackage() { packageFunctionName = "package_" + pkg.Name } @@ -250,28 +246,7 @@ func CompileSourcePackage(archiveFilename, outputDirectory string, skipChecks bo } // Clone source package info - var pkgInfo PackageInfo - if !isSplitPkg { - pkgInfo = *bpmpkg.PkgInfo - } else { - pkgInfo = *pkg - - // Ensure required fields are set - if strings.TrimSpace(pkgInfo.Name) == "" { - return nil, fmt.Errorf("split package name is empty") - } - - // Copy data from main source package - if pkgInfo.Description == "" { - pkgInfo.Description = bpmpkg.PkgInfo.Description - } - pkgInfo.Version = bpmpkg.PkgInfo.Version - pkgInfo.Revision = bpmpkg.PkgInfo.Revision - pkgInfo.Url = bpmpkg.PkgInfo.Url - if pkgInfo.License == "" { - pkgInfo.License = bpmpkg.PkgInfo.License - } - } + pkgInfo := *pkg // Set package type to binary pkgInfo.Type = "binary" diff --git a/src/bpmlib/general.go b/src/bpmlib/general.go index 4c7657a..c9cc1bd 100644 --- a/src/bpmlib/general.go +++ b/src/bpmlib/general.go @@ -25,6 +25,7 @@ func InstallPackages(rootDir string, installationReason InstallationReason, rein Changes: make(map[string]string), RootDir: rootDir, ForceInstallationReason: installationReason, + compiledPackages: make(map[string]string), } // Resolve packages @@ -35,12 +36,25 @@ func InstallPackages(rootDir string, installationReason InstallationReason, rein if err != nil { return nil, fmt.Errorf("could not read package: %s", err) } - if reinstallMethod == ReinstallMethodNone && IsPackageInstalled(bpmpkg.PkgInfo.Name, rootDir) && GetPackageInfo(bpmpkg.PkgInfo.Name, rootDir).GetFullVersion() == bpmpkg.PkgInfo.GetFullVersion() { + + if bpmpkg.PkgInfo.Type == "source" && bpmpkg.PkgInfo.IsSplitPackage() { + for _, splitPkg := range bpmpkg.PkgInfo.SplitPackages { + if reinstallMethod == ReinstallMethodNone && IsPackageInstalled(splitPkg.Name, rootDir) && GetPackageInfo(splitPkg.Name, rootDir).GetFullVersion() == splitPkg.GetFullVersion() { + continue + } + + operation.AppendAction(&InstallPackageAction{ + File: pkg, + IsDependency: false, + BpmPackage: bpmpkg, + SplitPackageToInstall: splitPkg.Name, + }) + } continue } - if bpmpkg.PkgInfo.Type == "source" && len(bpmpkg.PkgInfo.SplitPackages) != 0 { - return nil, fmt.Errorf("direct source package installation has not been implemented") + if reinstallMethod == ReinstallMethodNone && IsPackageInstalled(bpmpkg.PkgInfo.Name, rootDir) && GetPackageInfo(bpmpkg.PkgInfo.Name, rootDir).GetFullVersion() == bpmpkg.PkgInfo.GetFullVersion() { + continue } operation.AppendAction(&InstallPackageAction{ @@ -69,8 +83,8 @@ func InstallPackages(rootDir string, installationReason InstallationReason, rein continue } - if entry.Info.Type == "source" && len(entry.Info.SplitPackages) != 0 { - return nil, fmt.Errorf("direct source package installation has not been implemented") + if entry.Info.IsSplitPackage() { + return nil, fmt.Errorf("direct split source package installation has not been implemented") } operation.AppendAction(&FetchPackageAction{ @@ -128,6 +142,7 @@ func RemovePackages(rootDir string, removeUnusedPackagesOnly, cleanupDependencie UnresolvedDepends: make([]string, 0), Changes: make(map[string]string), RootDir: rootDir, + compiledPackages: make(map[string]string), } // Search for packages @@ -164,6 +179,7 @@ func CleanupPackages(rootDir string, verbose bool) (operation *BPMOperation, err UnresolvedDepends: make([]string, 0), Changes: make(map[string]string), RootDir: rootDir, + compiledPackages: make(map[string]string), } // Do package cleanup @@ -206,6 +222,7 @@ func UpdatePackages(rootDir string, syncDatabase bool, installOptionalDependenci Changes: make(map[string]string), RootDir: rootDir, ForceInstallationReason: InstallationReasonUnknown, + compiledPackages: make(map[string]string), } // Search for packages diff --git a/src/bpmlib/operations.go b/src/bpmlib/operations.go index a78c6a7..efb5a04 100644 --- a/src/bpmlib/operations.go +++ b/src/bpmlib/operations.go @@ -16,6 +16,7 @@ type BPMOperation struct { Changes map[string]string RootDir string ForceInstallationReason InstallationReason + compiledPackages map[string]string } func (operation *BPMOperation) ActionsContainPackage(pkg string) bool { @@ -337,6 +338,9 @@ func (operation *BPMOperation) ShowOperationSummary() { var pkgInfo *PackageInfo if value.GetActionType() == "install" { pkgInfo = value.(*InstallPackageAction).BpmPackage.PkgInfo + if value.(*InstallPackageAction).SplitPackageToInstall != "" { + pkgInfo = pkgInfo.GetSplitPackageInfo(value.(*InstallPackageAction).SplitPackageToInstall) + } } else if value.GetActionType() == "fetch" { pkgInfo = value.(*FetchPackageAction).RepositoryEntry.Info } else { @@ -484,14 +488,27 @@ func (operation *BPMOperation) Execute(verbose, force bool) error { } } - // Compile source package - outputBpmPackages, err := CompileSourcePackage(value.File, compiledDir, false) - if err != nil { - return fmt.Errorf("could not compile source package (%s): %s\n", value.File, err) + // Get package name to install + pkgNameToInstall := bpmpkg.PkgInfo.Name + if bpmpkg.PkgInfo.IsSplitPackage() { + pkgNameToInstall = value.SplitPackageToInstall + } + + // Compile source package if not compiled already + if _, ok := operation.compiledPackages[pkgNameToInstall]; !ok { + outputBpmPackages, err := CompileSourcePackage(value.File, compiledDir, false) + if err != nil { + return fmt.Errorf("could not compile source package (%s): %s\n", value.File, err) + } + + // Add compiled packages to slice + for pkgName, pkgFile := range outputBpmPackages { + operation.compiledPackages[pkgName] = pkgFile + } } // Set values - fileToInstall = outputBpmPackages[bpmpkg.PkgInfo.Name] + fileToInstall = operation.compiledPackages[pkgNameToInstall] bpmpkg, err = ReadPackage(fileToInstall) if err != nil { return fmt.Errorf("could not read package (%s): %s\n", fileToInstall, err) @@ -530,9 +547,10 @@ type OperationAction interface { } type InstallPackageAction struct { - File string - IsDependency bool - BpmPackage *BPMPackage + File string + IsDependency bool + SplitPackageToInstall string + BpmPackage *BPMPackage } func (action *InstallPackageAction) GetActionType() string { diff --git a/src/bpmlib/packages.go b/src/bpmlib/packages.go index fd48021..6e510a8 100644 --- a/src/bpmlib/packages.go +++ b/src/bpmlib/packages.go @@ -70,6 +70,25 @@ func (pkgInfo *PackageInfo) GetFullVersion() string { return pkgInfo.Version + "-" + strconv.Itoa(pkgInfo.Revision) } +func (pkgInfo *PackageInfo) IsSplitPackage() bool { + // Return false if not a source package + if pkgInfo.Type != "source" { + return false + } + + return len(pkgInfo.SplitPackages) > 0 +} + +func (pkgInfo *PackageInfo) GetSplitPackageInfo(splitPkg string) *PackageInfo { + for _, splitPkgInfo := range pkgInfo.SplitPackages { + if splitPkgInfo.Name == splitPkg { + return splitPkgInfo + } + } + + return nil +} + type InstallationReason string const ( @@ -149,7 +168,6 @@ func ReadPackage(filename string) (*BPMPackage, error) { var pkgFiles []*PackageFileEntry if _, err := os.Stat(filename); os.IsNotExist(err) { - fmt.Println("a") return nil, err } @@ -388,7 +406,7 @@ func executePackageScripts(filename, rootDir string, operation packageOperation, } func ReadPackageInfo(contents string) (*PackageInfo, error) { - pkgInfo := PackageInfo{ + pkgInfo := &PackageInfo{ Name: "", Description: "", Version: "", @@ -410,6 +428,8 @@ func ReadPackageInfo(contents string) (*PackageInfo, error) { if err != nil { return nil, err } + + // Ensure required fields are set properly if pkgInfo.Name == "" { return nil, errors.New("this package contains no name") } else if pkgInfo.Description == "" { @@ -423,10 +443,46 @@ func ReadPackageInfo(contents string) (*PackageInfo, error) { } else if pkgInfo.Type == "" { return nil, errors.New("this package contains no type") } - for i := 0; i < len(pkgInfo.Keep); i++ { - pkgInfo.Keep[i] = strings.TrimPrefix(pkgInfo.Keep[i], "/") + for _, val := range pkgInfo.Keep { + if strings.HasPrefix(val, "/") { + return nil, fmt.Errorf("cannot keep file (%s) after update because it starts with a slash", val) + } } - return &pkgInfo, nil + + // Setup split package information + for i, splitPkg := range pkgInfo.SplitPackages { + // Ensure split package contains a name and one that is different from the main package name + if splitPkg.Name == "" || splitPkg.Name == pkgInfo.Name { + return nil, fmt.Errorf("invalid split package name: %s", splitPkg.Name) + } + + // Turn split package into json data + splitPkgJson, err := yaml.Marshal(splitPkg) + if err != nil { + return nil, err + } + + // Clone all main package fields onto split package + pkgInfoClone := *pkgInfo + pkgInfo.SplitPackages[i] = &pkgInfoClone + + // Set make depends and split package field of split package to nil + pkgInfo.SplitPackages[i].MakeDepends = nil + pkgInfo.SplitPackages[i].SplitPackages = nil + + // Unmarshal json data back to struct + err = yaml.Unmarshal(splitPkgJson, &pkgInfo.SplitPackages[i]) + if err != nil { + return nil, err + } + + // Force set split package version, revision and URL + pkgInfo.SplitPackages[i].Version = pkgInfo.Version + pkgInfo.SplitPackages[i].Revision = pkgInfo.Revision + pkgInfo.SplitPackages[i].Url = pkgInfo.Url + } + + return pkgInfo, nil } func CreateReadableInfo(showArchitecture, showType, showPackageRelations bool, pkgInfo *PackageInfo, rootDir string) string {