Compare commits

..

No commits in common. "458c091ac2495e618ece4109d22631ba3e6e2236" and "d26d878308f69bdfd44ae024510a8d53158062d3" have entirely different histories.

11 changed files with 234 additions and 286 deletions

View File

@ -30,7 +30,7 @@ You are able to install bpm packages by typing the following:
```sh ```sh
bpm install /path/to/package.bpm bpm install /path/to/package.bpm
``` ```
You can also use the package name directly if using databases You can also use the package name directly if using repositories
```sh ```sh
bpm install package_name bpm install package_name
``` ```
@ -50,7 +50,7 @@ To remove all unused dependencies and clean cached files try using the cleanup c
bpm cleanup bpm cleanup
``` ```
If using databases, all packages can be updated using this simple command If using repositories, all packages can be updated using this simple command
```sh ```sh
bpm update bpm update
``` ```

View File

@ -1,8 +1,7 @@
ignore_packages: [] ignore_packages: []
privilege_escalator_cmd: "sudo" privilege_escalator_cmd: "sudo"
compilation_env: [] compilation_env: []
cleanup_make_dependencies: true repositories:
databases: - name: example-repository
- name: example-database source: https://my-repo.xyz/
source: https://my-database.xyz/
disabled: true disabled: true

View File

@ -39,12 +39,11 @@ var installationReason = ""
var nosync = true var nosync = true
var removeUnused = false var removeUnused = false
var doCleanup = false var doCleanup = false
var showDatabaseInfo = false var showRepoInfo = false
var installSrcPkgDepends = false var installSrcPkgDepends = false
var skipChecks = false var skipChecks = false
var outputDirectory = "" var outputDirectory = ""
var cleanupDependencies = false var cleanupDependencies = false
var cleanupMakeDependencies = false
var cleanupCompilationFiles = false var cleanupCompilationFiles = false
var cleanupCompiledPackages = false var cleanupCompiledPackages = false
var cleanupFetchedPackages = false var cleanupFetchedPackages = false
@ -117,7 +116,7 @@ func resolveCommand() {
} }
// Read local databases // Read local databases
err := bpmlib.ReadLocalDatabaseFiles() err := bpmlib.ReadLocalDatabases()
if err != nil { if err != nil {
log.Fatalf("Error: could not read local databases: %s", err) log.Fatalf("Error: could not read local databases: %s", err)
} }
@ -125,14 +124,13 @@ func resolveCommand() {
for n, pkg := range packages { for n, pkg := range packages {
var info *bpmlib.PackageInfo var info *bpmlib.PackageInfo
isFile := false isFile := false
showInstallationReason := false if showRepoInfo {
if showDatabaseInfo {
var err error var err error
var entry *bpmlib.BPMDatabaseEntry var entry *bpmlib.RepositoryEntry
entry, _, err = bpmlib.GetDatabaseEntry(pkg) entry, _, err = bpmlib.GetRepositoryEntry(pkg)
if err != nil { if err != nil {
if entry = bpmlib.ResolveVirtualPackage(pkg); entry == nil { if entry = bpmlib.ResolveVirtualPackage(pkg); entry == nil {
log.Fatalf("Error: could not find package (%s) in any database\n", pkg) log.Fatalf("Error: could not find package (%s) in any repository\n", pkg)
} }
} }
info = entry.Info info = entry.Info
@ -149,7 +147,6 @@ func resolveCommand() {
} else { } else {
info = bpmlib.GetPackageInfo(pkg, rootDir) info = bpmlib.GetPackageInfo(pkg, rootDir)
} }
showInstallationReason = true
} }
if info == nil { if info == nil {
log.Fatalf("Error: package (%s) is not installed\n", pkg) log.Fatalf("Error: package (%s) is not installed\n", pkg)
@ -164,11 +161,11 @@ func resolveCommand() {
} }
fmt.Println("File: " + abs) fmt.Println("File: " + abs)
} }
fmt.Println(bpmlib.CreateReadableInfo(true, true, true, showInstallationReason, info, rootDir)) fmt.Println(bpmlib.CreateReadableInfo(true, true, true, info, rootDir))
} }
case list: case list:
// Read local databases // Read local databases
err := bpmlib.ReadLocalDatabaseFiles() err := bpmlib.ReadLocalDatabases()
if err != nil { if err != nil {
log.Fatalf("Error: could not read local databases: %s", err) log.Fatalf("Error: could not read local databases: %s", err)
} }
@ -198,7 +195,7 @@ func resolveCommand() {
if n != 0 { if n != 0 {
fmt.Println() fmt.Println()
} }
fmt.Println(bpmlib.CreateReadableInfo(true, true, true, true, info, rootDir)) fmt.Println(bpmlib.CreateReadableInfo(true, true, true, info, rootDir))
} }
} }
case search: case search:
@ -208,7 +205,7 @@ func resolveCommand() {
} }
// Read local databases // Read local databases
err := bpmlib.ReadLocalDatabaseFiles() err := bpmlib.ReadLocalDatabases()
if err != nil { if err != nil {
log.Fatalf("Error: could not read local databases: %s", err) log.Fatalf("Error: could not read local databases: %s", err)
} }
@ -216,8 +213,8 @@ func resolveCommand() {
for i, term := range searchTerms { for i, term := range searchTerms {
nameResults := make([]*bpmlib.PackageInfo, 0) nameResults := make([]*bpmlib.PackageInfo, 0)
descResults := make([]*bpmlib.PackageInfo, 0) descResults := make([]*bpmlib.PackageInfo, 0)
for _, db := range bpmlib.BPMConfig.Databases { for _, repo := range bpmlib.BPMConfig.Repositories {
for _, entry := range db.Entries { for _, entry := range repo.Entries {
if strings.Contains(entry.Info.Name, term) { if strings.Contains(entry.Info.Name, term) {
nameResults = append(nameResults, entry.Info) nameResults = append(nameResults, entry.Info)
} else if strings.Contains(entry.Info.Description, term) { } else if strings.Contains(entry.Info.Description, term) {
@ -250,14 +247,12 @@ func resolveCommand() {
} }
// Check if installationReason argument is valid // Check if installationReason argument is valid
ir := bpmlib.InstallationReasonManual ir := bpmlib.InstallationReasonUnknown
switch installationReason { switch installationReason {
case "manual": case "manual":
ir = bpmlib.InstallationReasonManual ir = bpmlib.InstallationReasonManual
case "dependency": case "dependency":
ir = bpmlib.InstallationReasonDependency ir = bpmlib.InstallationReasonDependency
case "make-dependency":
ir = bpmlib.InstallationReasonMakeDependency
case "": case "":
default: default:
log.Fatalf("Error: %s is not a valid installation reason", installationReason) log.Fatalf("Error: %s is not a valid installation reason", installationReason)
@ -274,7 +269,7 @@ func resolveCommand() {
} }
// Read local databases // Read local databases
err := bpmlib.ReadLocalDatabaseFiles() err := bpmlib.ReadLocalDatabases()
if err != nil { if err != nil {
log.Fatalf("Error: could not read local databases: %s", err) log.Fatalf("Error: could not read local databases: %s", err)
} }
@ -332,7 +327,7 @@ func resolveCommand() {
// Read local databases if no sync // Read local databases if no sync
if nosync { if nosync {
err := bpmlib.ReadLocalDatabaseFiles() err := bpmlib.ReadLocalDatabases()
if err != nil { if err != nil {
log.Fatalf("Error: could not read local databases: %s", err) log.Fatalf("Error: could not read local databases: %s", err)
} }
@ -414,7 +409,7 @@ func resolveCommand() {
} }
// Read local databases // Read local databases
err := bpmlib.ReadLocalDatabaseFiles() err := bpmlib.ReadLocalDatabases()
if err != nil { if err != nil {
log.Fatalf("Error: could not read local databases: %s", err) log.Fatalf("Error: could not read local databases: %s", err)
} }
@ -470,15 +465,15 @@ func resolveCommand() {
log.Fatalf("Error: could not complete cache cleanup: %s", err) log.Fatalf("Error: could not complete cache cleanup: %s", err)
} }
if cleanupDependencies || cleanupMakeDependencies { if cleanupDependencies {
// Read local databases // Read local databases
err := bpmlib.ReadLocalDatabaseFiles() err := bpmlib.ReadLocalDatabases()
if err != nil { if err != nil {
log.Fatalf("Error: could not read local databases: %s", err) log.Fatalf("Error: could not read local databases: %s", err)
} }
// Create cleanup operation // Create cleanup operation
operation, err := bpmlib.CleanupPackages(cleanupMakeDependencies, rootDir) operation, err := bpmlib.CleanupPackages(rootDir)
if errors.As(err, &bpmlib.PackageNotFoundErr{}) || errors.As(err, &bpmlib.DependencyNotFoundErr{}) || errors.As(err, &bpmlib.PackageConflictErr{}) { if errors.As(err, &bpmlib.PackageNotFoundErr{}) || errors.As(err, &bpmlib.DependencyNotFoundErr{}) || errors.As(err, &bpmlib.PackageConflictErr{}) {
log.Fatalf("Error: %s", err) log.Fatalf("Error: %s", err)
} else if err != nil { } else if err != nil {
@ -574,7 +569,7 @@ func resolveCommand() {
} }
// Read local databases // Read local databases
err := bpmlib.ReadLocalDatabaseFiles() err := bpmlib.ReadLocalDatabases()
if err != nil { if err != nil {
log.Fatalf("Error: could not read local databases: %s", err) log.Fatalf("Error: could not read local databases: %s", err)
} }
@ -598,7 +593,7 @@ func resolveCommand() {
// Get direct runtime and make dependencies // Get direct runtime and make dependencies
totalDepends := make([]string, 0) totalDepends := make([]string, 0)
for depend := range bpmpkg.PkgInfo.GetDependencies(true, false) { for _, depend := range bpmpkg.PkgInfo.GetDependencies(true, false) {
if !slices.Contains(totalDepends, depend) { if !slices.Contains(totalDepends, depend) {
totalDepends = append(totalDepends, depend) totalDepends = append(totalDepends, depend)
} }
@ -627,7 +622,7 @@ func resolveCommand() {
} }
// Run 'bpm install' using the set privilege escalator command // Run 'bpm install' using the set privilege escalator command
args := []string{executable, "install", "--installation-reason=make-dependency"} args := []string{executable, "install", "--installation-reason=dependency"}
args = append(args, unmetDepends...) args = append(args, unmetDepends...)
cmd := exec.Command(bpmlib.BPMConfig.PrivilegeEscalatorCmd, args...) cmd := exec.Command(bpmlib.BPMConfig.PrivilegeEscalatorCmd, args...)
if yesAll { if yesAll {
@ -646,7 +641,7 @@ func resolveCommand() {
} else { } else {
// Ensure the required dependencies are installed // Ensure the required dependencies are installed
if len(unmetDepends) != 0 { if len(unmetDepends) != 0 {
log.Fatalf("Error: could not resolve dependencies: the following dependencies were not found in any databases: " + strings.Join(unmetDepends, ", ")) log.Fatalf("Error: could not resolve dependencies: the following dependencies were not found in any repositories: " + strings.Join(unmetDepends, ", "))
} }
} }
@ -741,14 +736,14 @@ func printHelp() {
fmt.Println("-> flags will be read if passed right after the subcommand otherwise they will be read as subcommand arguments") fmt.Println("-> flags will be read if passed right after the subcommand otherwise they will be read as subcommand arguments")
fmt.Println("\033[1m---- Command List ----\033[0m") fmt.Println("\033[1m---- Command List ----\033[0m")
fmt.Println("-> bpm version | shows information on the installed version of bpm") fmt.Println("-> bpm version | shows information on the installed version of bpm")
fmt.Println("-> bpm info [-R, --databases] <packages...> | shows information on an installed package") fmt.Println("-> bpm info [-R, --repos] <packages...> | shows information on an installed package")
fmt.Println(" -R=<path> lets you define the root path which will be used") fmt.Println(" -R=<path> lets you define the root path which will be used")
fmt.Println(" --databases show information on package in configured databases") fmt.Println(" --repos show information on package in repository")
fmt.Println("-> bpm list [-R, -c, -n] | lists all installed packages") fmt.Println("-> bpm list [-R, -c, -n] | lists all installed packages")
fmt.Println(" -R=<path> lets you define the root path which will be used") fmt.Println(" -R=<path> lets you define the root path which will be used")
fmt.Println(" -c lists the amount of installed packages") fmt.Println(" -c lists the amount of installed packages")
fmt.Println(" -n lists only the names of installed packages") fmt.Println(" -n lists only the names of installed packages")
fmt.Println("-> bpm search <search terms...> | Searches for packages through configured databases") fmt.Println("-> bpm search <search terms...> | Searches for packages through declared repositories")
fmt.Println("-> bpm install [-R, -v, -y, -f, --reinstall, --reinstall-all, --no-optional, --installation-reason] <packages...> | installs the following files") fmt.Println("-> bpm install [-R, -v, -y, -f, --reinstall, --reinstall-all, --no-optional, --installation-reason] <packages...> | installs the following files")
fmt.Println(" -R=<path> lets you define the root path which will be used") fmt.Println(" -R=<path> lets you define the root path which will be used")
fmt.Println(" -v Show additional information about what BPM is doing") fmt.Println(" -v Show additional information about what BPM is doing")
@ -758,7 +753,7 @@ func printHelp() {
fmt.Println(" --reinstall-all Same as --reinstall but also reinstalls dependencies") fmt.Println(" --reinstall-all Same as --reinstall but also reinstalls dependencies")
fmt.Println(" --no-optional Prevents installation of optional dependencies") fmt.Println(" --no-optional Prevents installation of optional dependencies")
fmt.Println(" --installation-reason=<manual/dependency> sets the installation reason for all newly installed packages") fmt.Println(" --installation-reason=<manual/dependency> sets the installation reason for all newly installed packages")
fmt.Println("-> bpm update [-R, -v, -y, -f, --reinstall, --no-sync] | updates all packages that are available in the configured databases") fmt.Println("-> bpm update [-R, -v, -y, -f, --reinstall, --no-sync] | updates all packages that are available in the repositories")
fmt.Println(" -R=<path> lets you define the root path which will be used") fmt.Println(" -R=<path> lets you define the root path which will be used")
fmt.Println(" -v Show additional information about what BPM is doing") fmt.Println(" -v Show additional information about what BPM is doing")
fmt.Println(" -y skips the confirmation prompt") fmt.Println(" -y skips the confirmation prompt")
@ -780,10 +775,9 @@ func printHelp() {
fmt.Println(" -R=<path> lets you define the root path which will be used") fmt.Println(" -R=<path> lets you define the root path which will be used")
fmt.Println(" -y skips the confirmation prompt") fmt.Println(" -y skips the confirmation prompt")
fmt.Println(" --depends performs a dependency cleanup") fmt.Println(" --depends performs a dependency cleanup")
fmt.Println(" --make-depends performs a make dependency cleanup")
fmt.Println(" --compilation-files performs a cleanup of compilation files") fmt.Println(" --compilation-files performs a cleanup of compilation files")
fmt.Println(" --compiled-pkgs performs a cleanup of compilation compiled binary packages") fmt.Println(" --compiled-pkgs performs a cleanup of compilation compiled binary packages")
fmt.Println(" --fetched-pkgs performs a cleanup of fetched packages from databases") fmt.Println(" --fetched-pkgs performs a cleanup of fetched packages from repositories")
fmt.Println("-> bpm file [-R] <files...> | shows what packages the following packages are managed by") fmt.Println("-> bpm file [-R] <files...> | shows what packages the following packages are managed by")
fmt.Println(" -R=<root_path> lets you define the root path which will be used") fmt.Println(" -R=<root_path> lets you define the root path which will be used")
fmt.Println("-> bpm compile [-d, -s, -o] <source packages...> | Compile source BPM package") fmt.Println("-> bpm compile [-d, -s, -o] <source packages...> | Compile source BPM package")
@ -806,7 +800,7 @@ func resolveFlags() {
// Info flags // Info flags
infoFlagSet := flag.NewFlagSet("Info flags", flag.ExitOnError) infoFlagSet := flag.NewFlagSet("Info flags", flag.ExitOnError)
infoFlagSet.StringVar(&rootDir, "R", "/", "Set the destination root") infoFlagSet.StringVar(&rootDir, "R", "/", "Set the destination root")
infoFlagSet.BoolVar(&showDatabaseInfo, "databases", false, "Show information on package in configured databases") infoFlagSet.BoolVar(&showRepoInfo, "repos", false, "Show information on package in repository")
infoFlagSet.Usage = printHelp infoFlagSet.Usage = printHelp
// Install flags // Install flags
installFlagSet := flag.NewFlagSet("Install flags", flag.ExitOnError) installFlagSet := flag.NewFlagSet("Install flags", flag.ExitOnError)
@ -847,10 +841,9 @@ func resolveFlags() {
cleanupFlagSet.BoolVar(&verbose, "v", false, "Show additional information about what BPM is doing") cleanupFlagSet.BoolVar(&verbose, "v", false, "Show additional information about what BPM is doing")
cleanupFlagSet.BoolVar(&yesAll, "y", false, "Skip confirmation prompts") cleanupFlagSet.BoolVar(&yesAll, "y", false, "Skip confirmation prompts")
cleanupFlagSet.BoolVar(&cleanupDependencies, "depends", false, "Perform a dependency cleanup") cleanupFlagSet.BoolVar(&cleanupDependencies, "depends", false, "Perform a dependency cleanup")
cleanupFlagSet.BoolVar(&cleanupMakeDependencies, "make-depends", false, "Perform a make dependency cleanup")
cleanupFlagSet.BoolVar(&cleanupCompilationFiles, "compilation-files", false, "Perform a cleanup of compilation files") cleanupFlagSet.BoolVar(&cleanupCompilationFiles, "compilation-files", false, "Perform a cleanup of compilation files")
cleanupFlagSet.BoolVar(&cleanupCompiledPackages, "compiled-pkgs", false, "Perform a cleanup of compilation compiled binary packages") cleanupFlagSet.BoolVar(&cleanupCompiledPackages, "compiled-pkgs", false, "Perform a cleanup of compilation compiled binary packages")
cleanupFlagSet.BoolVar(&cleanupFetchedPackages, "fetched-pkgs", false, "Perform a cleanup of fetched packages from databases") cleanupFlagSet.BoolVar(&cleanupFetchedPackages, "fetched-pkgs", false, "Perform a cleanup of fetched packages from repositories")
cleanupFlagSet.Usage = printHelp cleanupFlagSet.Usage = printHelp
// File flags // File flags
fileFlagSet := flag.NewFlagSet("Remove flags", flag.ExitOnError) fileFlagSet := flag.NewFlagSet("Remove flags", flag.ExitOnError)
@ -863,18 +856,8 @@ func resolveFlags() {
compileFlagSet.StringVar(&outputDirectory, "o", "", "Set output directory") compileFlagSet.StringVar(&outputDirectory, "o", "", "Set output directory")
compileFlagSet.BoolVar(&verbose, "v", false, "Show additional information about what BPM is doing") compileFlagSet.BoolVar(&verbose, "v", false, "Show additional information about what BPM is doing")
compileFlagSet.BoolVar(&yesAll, "y", false, "Skip confirmation prompts") compileFlagSet.BoolVar(&yesAll, "y", false, "Skip confirmation prompts")
compileFlagSet.Usage = printHelp compileFlagSet.Usage = printHelp
isFlagSet := func(flagSet *flag.FlagSet, name string) bool {
found := false
flagSet.Visit(func(f *flag.Flag) {
if f.Name == name {
found = true
}
})
return found
}
if len(os.Args[1:]) <= 0 { if len(os.Args[1:]) <= 0 {
subcommand = "help" subcommand = "help"
} else { } else {
@ -921,9 +904,8 @@ func resolveFlags() {
if err != nil { if err != nil {
return return
} }
if !isFlagSet(cleanupFlagSet, "depends") && !isFlagSet(cleanupFlagSet, "make-depends") && !isFlagSet(cleanupFlagSet, "compilation-files") && !isFlagSet(cleanupFlagSet, "compiled-pkgs") && !isFlagSet(cleanupFlagSet, "fetched-pkgs") { if !cleanupDependencies && !cleanupCompilationFiles && !cleanupCompiledPackages && !cleanupFetchedPackages {
cleanupDependencies = true cleanupDependencies = true
cleanupMakeDependencies = bpmlib.BPMConfig.CleanupMakeDependencies
cleanupCompilationFiles = true cleanupCompilationFiles = true
cleanupCompiledPackages = true cleanupCompiledPackages = true
cleanupFetchedPackages = true cleanupFetchedPackages = true

View File

@ -264,7 +264,8 @@ func CompileSourcePackage(archiveFilename, outputDirectory string, skipChecks bo
pkgInfo.Arch = GetArch() pkgInfo.Arch = GetArch()
} }
// Remove split package field // Remove source package specific fields
pkgInfo.MakeDepends = nil
pkgInfo.SplitPackages = nil pkgInfo.SplitPackages = nil
// Marshal package info // Marshal package info

View File

@ -6,11 +6,10 @@ import (
) )
type BPMConfigStruct struct { type BPMConfigStruct struct {
IgnorePackages []string `yaml:"ignore_packages"` IgnorePackages []string `yaml:"ignore_packages"`
PrivilegeEscalatorCmd string `yaml:"privilege_escalator_cmd"` PrivilegeEscalatorCmd string `yaml:"privilege_escalator_cmd"`
CompilationEnvironment []string `yaml:"compilation_env"` CompilationEnvironment []string `yaml:"compilation_env"`
CleanupMakeDependencies bool `yaml:"cleanup_make_dependencies"` Repositories []*Repository `yaml:"repositories"`
Databases []*BPMDatabase `yaml:"databases"`
} }
var BPMConfig BPMConfigStruct var BPMConfig BPMConfigStruct
@ -25,17 +24,15 @@ func ReadConfig() (err error) {
return err return err
} }
BPMConfig = BPMConfigStruct{ BPMConfig = BPMConfigStruct{}
CleanupMakeDependencies: true,
}
err = yaml.Unmarshal(bytes, &BPMConfig) err = yaml.Unmarshal(bytes, &BPMConfig)
if err != nil { if err != nil {
return err return err
} }
for i := len(BPMConfig.Databases) - 1; i >= 0; i-- { for i := len(BPMConfig.Repositories) - 1; i >= 0; i-- {
if BPMConfig.Databases[i].Disabled != nil && *BPMConfig.Databases[i].Disabled { if BPMConfig.Repositories[i].Disabled != nil && *BPMConfig.Repositories[i].Disabled {
BPMConfig.Databases = append(BPMConfig.Databases[:i], BPMConfig.Databases[i+1:]...) BPMConfig.Repositories = append(BPMConfig.Repositories[:i], BPMConfig.Repositories[i+1:]...)
} }
} }

View File

@ -6,25 +6,14 @@ import (
"slices" "slices"
) )
func (pkgInfo *PackageInfo) GetDependencies(includeMakeDepends, includeOptionalDepends bool) map[string]InstallationReason { func (pkgInfo *PackageInfo) GetDependencies(includeMakeDepends, includeOptionalDepends bool) []string {
allDepends := make(map[string]InstallationReason) allDepends := make([]string, 0)
allDepends = append(allDepends, pkgInfo.Depends...)
for _, depend := range pkgInfo.Depends { if includeMakeDepends {
allDepends[depend] = InstallationReasonDependency allDepends = append(allDepends, pkgInfo.MakeDepends...)
} }
if includeOptionalDepends { if includeOptionalDepends {
for _, depend := range pkgInfo.OptionalDepends { allDepends = append(allDepends, pkgInfo.OptionalDepends...)
if _, ok := allDepends[depend]; !ok {
allDepends[depend] = InstallationReasonDependency
}
}
}
if includeMakeDepends {
for _, depend := range pkgInfo.MakeDepends {
if _, ok := allDepends[depend]; !ok {
allDepends[depend] = InstallationReasonMakeDependency
}
}
} }
return allDepends return allDepends
} }
@ -45,10 +34,7 @@ func (pkgInfo *PackageInfo) getAllDependencies(resolved *[]string, unresolved *[
*unresolved = append(*unresolved, pkgInfo.Name) *unresolved = append(*unresolved, pkgInfo.Name)
// Loop through all dependencies // Loop through all dependencies
for depend := range pkgInfo.GetDependencies(includeMakeDepends, includeOptionalDepends) { for _, depend := range pkgInfo.GetDependencies(includeMakeDepends, includeOptionalDepends) {
if isVirtual, p := IsVirtualPackage(depend, rootDir); isVirtual {
depend = p
}
if !slices.Contains(*resolved, depend) { if !slices.Contains(*resolved, depend) {
// Add current dependency to resolved slice when circular dependency is detected // Add current dependency to resolved slice when circular dependency is detected
if slices.Contains(*unresolved, depend) { if slices.Contains(*unresolved, depend) {
@ -58,7 +44,13 @@ func (pkgInfo *PackageInfo) getAllDependencies(resolved *[]string, unresolved *[
continue continue
} }
dependInfo := GetPackageInfo(depend, rootDir) var dependInfo *PackageInfo
if isVirtual, p := IsVirtualPackage(depend, rootDir); isVirtual {
dependInfo = GetPackageInfo(p, rootDir)
} else {
dependInfo = GetPackageInfo(depend, rootDir)
}
if dependInfo != nil { if dependInfo != nil {
dependInfo.getAllDependencies(resolved, unresolved, includeMakeDepends, includeOptionalDepends, rootDir) dependInfo.getAllDependencies(resolved, unresolved, includeMakeDepends, includeOptionalDepends, rootDir)
@ -71,39 +63,39 @@ func (pkgInfo *PackageInfo) getAllDependencies(resolved *[]string, unresolved *[
*unresolved = stringSliceRemove(*unresolved, pkgInfo.Name) *unresolved = stringSliceRemove(*unresolved, pkgInfo.Name)
} }
func ResolveAllPackageDependenciesFromDatabases(pkgInfo *PackageInfo, checkMake, checkOptional, ignoreInstalled, verbose bool, rootDir string) (resolved map[string]InstallationReason, unresolved []string) { func ResolvePackageDependenciesFromDatabases(pkgInfo *PackageInfo, checkMake, checkOptional, ignoreInstalled, verbose bool, rootDir string) (resolved []string, unresolved []string) {
// Initialize slices // Initialize slices
resolved = make(map[string]InstallationReason) resolved = make([]string, 0)
unresolved = make([]string, 0) unresolved = make([]string, 0)
// Call unexported function // Call unexported function
resolvePackageDependenciesFromDatabase(resolved, &unresolved, pkgInfo, InstallationReasonDependency, checkMake, checkOptional, ignoreInstalled, verbose, rootDir) resolvePackageDependenciesFromDatabase(&resolved, &unresolved, pkgInfo, checkMake, checkOptional, ignoreInstalled, verbose, rootDir)
return resolved, unresolved return resolved, unresolved
} }
func resolvePackageDependenciesFromDatabase(resolved map[string]InstallationReason, unresolved *[]string, pkgInfo *PackageInfo, installationReason InstallationReason, checkMake, checkOptional, ignoreInstalled, verbose bool, rootDir string) { func resolvePackageDependenciesFromDatabase(resolved, unresolved *[]string, pkgInfo *PackageInfo, checkMake, checkOptional, ignoreInstalled, verbose bool, rootDir string) {
// Add current package name to unresolved slice // Add current package name to unresolved slice
*unresolved = append(*unresolved, pkgInfo.Name) *unresolved = append(*unresolved, pkgInfo.Name)
// Loop through all dependencies // Loop through all dependencies
for depend, ir := range pkgInfo.GetDependencies(pkgInfo.Type == "source", checkOptional) { for _, depend := range pkgInfo.GetDependencies(checkMake, checkOptional) {
if _, ok := resolved[depend]; !ok { if !slices.Contains(*resolved, depend) {
// Add current dependency to resolved slice when circular dependency is detected // Add current dependency to resolved slice when circular dependency is detected
if slices.Contains(*unresolved, depend) { if slices.Contains(*unresolved, depend) {
if verbose { if verbose {
fmt.Printf("Circular dependency was detected (%s -> %s). Installing %s first\n", pkgInfo.Name, depend, depend) fmt.Printf("Circular dependency was detected (%s -> %s). Installing %s first\n", pkgInfo.Name, depend, depend)
} }
if _, ok := resolved[depend]; !ok { if !slices.Contains(*resolved, depend) {
resolved[depend] = ir *resolved = append(*resolved, depend)
} }
continue continue
} else if ignoreInstalled && IsPackageProvided(depend, rootDir) { } else if ignoreInstalled && IsPackageProvided(depend, rootDir) {
continue continue
} }
var err error var err error
var entry *BPMDatabaseEntry var entry *RepositoryEntry
entry, _, err = GetDatabaseEntry(depend) entry, _, err = GetRepositoryEntry(depend)
if err != nil { if err != nil {
if entry = ResolveVirtualPackage(depend); entry == nil { if entry = ResolveVirtualPackage(depend); entry == nil {
if !slices.Contains(*unresolved, depend) { if !slices.Contains(*unresolved, depend) {
@ -112,12 +104,11 @@ func resolvePackageDependenciesFromDatabase(resolved map[string]InstallationReas
continue continue
} }
} }
resolvePackageDependenciesFromDatabase(resolved, unresolved, entry.Info, ir, checkMake, checkOptional, ignoreInstalled, verbose, rootDir) resolvePackageDependenciesFromDatabase(resolved, unresolved, entry.Info, checkMake, checkOptional, ignoreInstalled, verbose, rootDir)
} }
} }
if !slices.Contains(*resolved, pkgInfo.Name) {
if _, ok := resolved[pkgInfo.Name]; !ok { *resolved = append(*resolved, pkgInfo.Name)
resolved[pkgInfo.Name] = installationReason
} }
*unresolved = stringSliceRemove(*unresolved, pkgInfo.Name) *unresolved = stringSliceRemove(*unresolved, pkgInfo.Name)
} }
@ -154,7 +145,7 @@ func GetPackageDependants(pkgName string, rootDir string) ([]string, error) {
dependencies := installedPkg.PkgInfo.GetDependencies(false, true) dependencies := installedPkg.PkgInfo.GetDependencies(false, true)
// Add installed package to list if its dependencies include pkgName // Add installed package to list if its dependencies include pkgName
if _, ok := dependencies[pkgName]; ok { if slices.Contains(dependencies, pkgName) {
ret = append(ret, installedPkgName) ret = append(ret, installedPkgName)
continue continue
} }
@ -162,7 +153,7 @@ func GetPackageDependants(pkgName string, rootDir string) ([]string, error) {
// Loop through each virtual package // Loop through each virtual package
for _, vpkg := range pkg.PkgInfo.Provides { for _, vpkg := range pkg.PkgInfo.Provides {
// Add installed package to list if its dependencies contain a provided virtual package // Add installed package to list if its dependencies contain a provided virtual package
if _, ok := dependencies[vpkg]; ok { if slices.Contains(dependencies, vpkg) {
ret = append(ret, installedPkgName) ret = append(ret, installedPkgName)
break break
} }

View File

@ -10,7 +10,7 @@ type PackageNotFoundErr struct {
} }
func (e PackageNotFoundErr) Error() string { func (e PackageNotFoundErr) Error() string {
return "The following packages were not found in any databases: " + strings.Join(e.packages, ", ") return "The following packages were not found in any repositories: " + strings.Join(e.packages, ", ")
} }
type DependencyNotFoundErr struct { type DependencyNotFoundErr struct {
@ -18,7 +18,7 @@ type DependencyNotFoundErr struct {
} }
func (e DependencyNotFoundErr) Error() string { func (e DependencyNotFoundErr) Error() string {
return "The following dependencies were not found in any databases: " + strings.Join(e.dependencies, ", ") return "The following dependencies were not found in any repositories: " + strings.Join(e.dependencies, ", ")
} }
type PackageConflictErr struct { type PackageConflictErr struct {

View File

@ -17,15 +17,16 @@ const (
ReinstallMethodAll ReinstallMethod = iota ReinstallMethodAll ReinstallMethod = iota
) )
// InstallPackages installs the specified packages into the given root directory by fetching them from databases or directly from local bpm archives // InstallPackages installs the specified packages into the given root directory by fetching them from repositories or directly from local bpm archives
func InstallPackages(rootDir string, installationReason InstallationReason, reinstallMethod ReinstallMethod, installOptionalDependencies, forceInstallation, verbose bool, packages ...string) (operation *BPMOperation, err error) { func InstallPackages(rootDir string, installationReason InstallationReason, reinstallMethod ReinstallMethod, installOptionalDependencies, forceInstallation, verbose bool, packages ...string) (operation *BPMOperation, err error) {
// Setup operation struct // Setup operation struct
operation = &BPMOperation{ operation = &BPMOperation{
Actions: make([]OperationAction, 0), Actions: make([]OperationAction, 0),
UnresolvedDepends: make([]string, 0), UnresolvedDepends: make([]string, 0),
Changes: make(map[string]string), Changes: make(map[string]string),
RootDir: rootDir, RootDir: rootDir,
compiledPackages: make(map[string]string), ForceInstallationReason: installationReason,
compiledPackages: make(map[string]string),
} }
// Resolve packages // Resolve packages
@ -45,7 +46,7 @@ func InstallPackages(rootDir string, installationReason InstallationReason, rein
operation.AppendAction(&InstallPackageAction{ operation.AppendAction(&InstallPackageAction{
File: pkg, File: pkg,
InstallationReason: installationReason, IsDependency: false,
BpmPackage: bpmpkg, BpmPackage: bpmpkg,
SplitPackageToInstall: splitPkg.Name, SplitPackageToInstall: splitPkg.Name,
}) })
@ -58,17 +59,17 @@ func InstallPackages(rootDir string, installationReason InstallationReason, rein
} }
operation.AppendAction(&InstallPackageAction{ operation.AppendAction(&InstallPackageAction{
File: pkg, File: pkg,
InstallationReason: installationReason, IsDependency: false,
BpmPackage: bpmpkg, BpmPackage: bpmpkg,
}) })
} else { } else {
var entry *BPMDatabaseEntry var entry *RepositoryEntry
if e, _, err := GetDatabaseEntry(pkg); err == nil { if e, _, err := GetRepositoryEntry(pkg); err == nil {
entry = e entry = e
} else if isVirtual, p := IsVirtualPackage(pkg, rootDir); isVirtual { } else if isVirtual, p := IsVirtualPackage(pkg, rootDir); isVirtual {
entry, _, err = GetDatabaseEntry(p) entry, _, err = GetRepositoryEntry(p)
if err != nil { if err != nil {
pkgsNotFound = append(pkgsNotFound, pkg) pkgsNotFound = append(pkgsNotFound, pkg)
continue continue
@ -84,8 +85,8 @@ func InstallPackages(rootDir string, installationReason InstallationReason, rein
} }
operation.AppendAction(&FetchPackageAction{ operation.AppendAction(&FetchPackageAction{
InstallationReason: installationReason, IsDependency: false,
DatabaseEntry: entry, RepositoryEntry: entry,
}) })
} }
} }
@ -160,7 +161,7 @@ func RemovePackages(rootDir string, removeUnusedPackagesOnly, cleanupDependencie
// Do package cleanup // Do package cleanup
if cleanupDependencies { if cleanupDependencies {
err := operation.Cleanup(true) err := operation.Cleanup()
if err != nil { if err != nil {
return nil, fmt.Errorf("could not perform cleanup for operation: %s", err) return nil, fmt.Errorf("could not perform cleanup for operation: %s", err)
} }
@ -169,7 +170,7 @@ func RemovePackages(rootDir string, removeUnusedPackagesOnly, cleanupDependencie
} }
// CleanupPackages finds packages installed as dependencies which are no longer required by the rest of the system in the given root directory // CleanupPackages finds packages installed as dependencies which are no longer required by the rest of the system in the given root directory
func CleanupPackages(cleanupMakeDepends bool, rootDir string) (operation *BPMOperation, err error) { func CleanupPackages(rootDir string) (operation *BPMOperation, err error) {
operation = &BPMOperation{ operation = &BPMOperation{
Actions: make([]OperationAction, 0), Actions: make([]OperationAction, 0),
UnresolvedDepends: make([]string, 0), UnresolvedDepends: make([]string, 0),
@ -179,7 +180,7 @@ func CleanupPackages(cleanupMakeDepends bool, rootDir string) (operation *BPMOpe
} }
// Do package cleanup // Do package cleanup
err = operation.Cleanup(cleanupMakeDepends) err = operation.Cleanup()
if err != nil { if err != nil {
return nil, fmt.Errorf("could not perform cleanup for operation: %s", err) return nil, fmt.Errorf("could not perform cleanup for operation: %s", err)
} }
@ -271,7 +272,7 @@ func CleanupCache(rootDir string, cleanupCompilationFiles, cleanupCompiledPackag
// UpdatePackages fetches the newest versions of all installed packages from // UpdatePackages fetches the newest versions of all installed packages from
func UpdatePackages(rootDir string, syncDatabase bool, installOptionalDependencies, forceInstallation, verbose bool) (operation *BPMOperation, err error) { func UpdatePackages(rootDir string, syncDatabase bool, installOptionalDependencies, forceInstallation, verbose bool) (operation *BPMOperation, err error) {
// Sync databases // Sync repositories
if syncDatabase { if syncDatabase {
err := SyncDatabase(verbose) err := SyncDatabase(verbose)
if err != nil { if err != nil {
@ -286,7 +287,7 @@ func UpdatePackages(rootDir string, syncDatabase bool, installOptionalDependenci
if err != nil { if err != nil {
return nil, fmt.Errorf("could not read BPM config: %s", err) return nil, fmt.Errorf("could not read BPM config: %s", err)
} }
err = ReadLocalDatabaseFiles() err = ReadLocalDatabases()
if err != nil { if err != nil {
return nil, fmt.Errorf("could not read local databases: %s", err) return nil, fmt.Errorf("could not read local databases: %s", err)
} }
@ -299,11 +300,12 @@ func UpdatePackages(rootDir string, syncDatabase bool, installOptionalDependenci
} }
operation = &BPMOperation{ operation = &BPMOperation{
Actions: make([]OperationAction, 0), Actions: make([]OperationAction, 0),
UnresolvedDepends: make([]string, 0), UnresolvedDepends: make([]string, 0),
Changes: make(map[string]string), Changes: make(map[string]string),
RootDir: rootDir, RootDir: rootDir,
compiledPackages: make(map[string]string), ForceInstallationReason: InstallationReasonUnknown,
compiledPackages: make(map[string]string),
} }
// Search for packages // Search for packages
@ -311,11 +313,11 @@ func UpdatePackages(rootDir string, syncDatabase bool, installOptionalDependenci
if slices.Contains(BPMConfig.IgnorePackages, pkg) { if slices.Contains(BPMConfig.IgnorePackages, pkg) {
continue continue
} }
var entry *BPMDatabaseEntry var entry *RepositoryEntry
// Check if installed package can be replaced and install that instead // Check if installed package can be replaced and install that instead
if e := FindReplacement(pkg); e != nil { if e := FindReplacement(pkg); e != nil {
entry = e entry = e
} else if entry, _, err = GetDatabaseEntry(pkg); err != nil { } else if entry, _, err = GetRepositoryEntry(pkg); err != nil {
continue continue
} }
@ -326,8 +328,8 @@ func UpdatePackages(rootDir string, syncDatabase bool, installOptionalDependenci
comparison := ComparePackageVersions(*entry.Info, *installedInfo) comparison := ComparePackageVersions(*entry.Info, *installedInfo)
if comparison > 0 { if comparison > 0 {
operation.AppendAction(&FetchPackageAction{ operation.AppendAction(&FetchPackageAction{
InstallationReason: GetInstallationReason(pkg, rootDir), IsDependency: false,
DatabaseEntry: entry, RepositoryEntry: entry,
}) })
} }
} }
@ -353,12 +355,12 @@ func UpdatePackages(rootDir string, syncDatabase bool, installOptionalDependenci
// SyncDatabase syncs all databases declared in /etc/bpm.conf // SyncDatabase syncs all databases declared in /etc/bpm.conf
func SyncDatabase(verbose bool) (err error) { func SyncDatabase(verbose bool) (err error) {
for _, db := range BPMConfig.Databases { for _, repo := range BPMConfig.Repositories {
if verbose { if verbose {
fmt.Printf("Fetching package database file for database (%s)...\n", db.Name) fmt.Printf("Fetching package database for repository (%s)...\n", repo.Name)
} }
err := db.SyncLocalDatabaseFile() err := repo.SyncLocalDatabase()
if err != nil { if err != nil {
return err return err
} }

View File

@ -11,11 +11,12 @@ import (
) )
type BPMOperation struct { type BPMOperation struct {
Actions []OperationAction Actions []OperationAction
UnresolvedDepends []string UnresolvedDepends []string
Changes map[string]string Changes map[string]string
RootDir string RootDir string
compiledPackages map[string]string ForceInstallationReason InstallationReason
compiledPackages map[string]string
} }
func (operation *BPMOperation) ActionsContainPackage(pkg string) bool { func (operation *BPMOperation) ActionsContainPackage(pkg string) bool {
@ -25,7 +26,7 @@ func (operation *BPMOperation) ActionsContainPackage(pkg string) bool {
return true return true
} }
} else if action.GetActionType() == "fetch" { } else if action.GetActionType() == "fetch" {
if action.(*FetchPackageAction).DatabaseEntry.Info.Name == pkg { if action.(*FetchPackageAction).RepositoryEntry.Info.Name == pkg {
return true return true
} }
} else if action.GetActionType() == "remove" { } else if action.GetActionType() == "remove" {
@ -57,7 +58,7 @@ func (operation *BPMOperation) InsertActionAt(index int, action OperationAction)
operation.Changes[pkgInfo.Name] = "upgrade" operation.Changes[pkgInfo.Name] = "upgrade"
} }
} else if action.GetActionType() == "fetch" { } else if action.GetActionType() == "fetch" {
pkgInfo := action.(*FetchPackageAction).DatabaseEntry.Info pkgInfo := action.(*FetchPackageAction).RepositoryEntry.Info
if !IsPackageInstalled(pkgInfo.Name, operation.RootDir) { if !IsPackageInstalled(pkgInfo.Name, operation.RootDir) {
operation.Changes[pkgInfo.Name] = "install" operation.Changes[pkgInfo.Name] = "install"
} else { } else {
@ -76,7 +77,7 @@ func (operation *BPMOperation) RemoveAction(pkg, actionType string) {
if a.GetActionType() == "install" { if a.GetActionType() == "install" {
return a.(*InstallPackageAction).BpmPackage.PkgInfo.Name == pkg return a.(*InstallPackageAction).BpmPackage.PkgInfo.Name == pkg
} else if a.GetActionType() == "fetch" { } else if a.GetActionType() == "fetch" {
return a.(*FetchPackageAction).DatabaseEntry.Info.Name == pkg return a.(*FetchPackageAction).RepositoryEntry.Info.Name == pkg
} else if a.GetActionType() == "remove" { } else if a.GetActionType() == "remove" {
return a.(*RemovePackageAction).BpmPackage.PkgInfo.Name == pkg return a.(*RemovePackageAction).BpmPackage.PkgInfo.Name == pkg
} }
@ -88,7 +89,7 @@ func (operation *BPMOperation) GetTotalDownloadSize() uint64 {
var ret uint64 = 0 var ret uint64 = 0
for _, action := range operation.Actions { for _, action := range operation.Actions {
if action.GetActionType() == "fetch" { if action.GetActionType() == "fetch" {
ret += action.(*FetchPackageAction).DatabaseEntry.DownloadSize ret += action.(*FetchPackageAction).RepositoryEntry.DownloadSize
} }
} }
return ret return ret
@ -100,7 +101,7 @@ func (operation *BPMOperation) GetTotalInstalledSize() uint64 {
if action.GetActionType() == "install" { if action.GetActionType() == "install" {
ret += action.(*InstallPackageAction).BpmPackage.GetInstalledSize() ret += action.(*InstallPackageAction).BpmPackage.GetInstalledSize()
} else if action.GetActionType() == "fetch" { } else if action.GetActionType() == "fetch" {
ret += action.(*FetchPackageAction).DatabaseEntry.InstalledSize ret += action.(*FetchPackageAction).RepositoryEntry.InstalledSize
} }
} }
return ret return ret
@ -115,7 +116,7 @@ func (operation *BPMOperation) GetFinalActionSize(rootDir string) int64 {
ret -= int64(GetPackage(action.(*InstallPackageAction).BpmPackage.PkgInfo.Name, rootDir).GetInstalledSize()) ret -= int64(GetPackage(action.(*InstallPackageAction).BpmPackage.PkgInfo.Name, rootDir).GetInstalledSize())
} }
} else if action.GetActionType() == "fetch" { } else if action.GetActionType() == "fetch" {
ret += int64(action.(*FetchPackageAction).DatabaseEntry.InstalledSize) ret += int64(action.(*FetchPackageAction).RepositoryEntry.InstalledSize)
} else if action.GetActionType() == "remove" { } else if action.GetActionType() == "remove" {
ret -= int64(action.(*RemovePackageAction).BpmPackage.GetInstalledSize()) ret -= int64(action.(*RemovePackageAction).BpmPackage.GetInstalledSize())
} }
@ -132,28 +133,28 @@ func (operation *BPMOperation) ResolveDependencies(reinstallDependencies, instal
pkgInfo = action.BpmPackage.PkgInfo pkgInfo = action.BpmPackage.PkgInfo
} else if value.GetActionType() == "fetch" { } else if value.GetActionType() == "fetch" {
action := value.(*FetchPackageAction) action := value.(*FetchPackageAction)
pkgInfo = action.DatabaseEntry.Info pkgInfo = action.RepositoryEntry.Info
} else { } else {
pos++ pos++
continue continue
} }
resolved, unresolved := ResolveAllPackageDependenciesFromDatabases(pkgInfo, pkgInfo.Type == "source", installOptionalDependencies, !reinstallDependencies, verbose, operation.RootDir) resolved, unresolved := ResolvePackageDependenciesFromDatabases(pkgInfo, pkgInfo.Type == "source", installOptionalDependencies, !reinstallDependencies, verbose, operation.RootDir)
operation.UnresolvedDepends = append(operation.UnresolvedDepends, unresolved...) operation.UnresolvedDepends = append(operation.UnresolvedDepends, unresolved...)
for depend, installationReason := range resolved { for _, depend := range resolved {
if !operation.ActionsContainPackage(depend) && depend != pkgInfo.Name { if !operation.ActionsContainPackage(depend) && depend != pkgInfo.Name {
if !reinstallDependencies && IsPackageInstalled(depend, operation.RootDir) { if !reinstallDependencies && IsPackageInstalled(depend, operation.RootDir) {
continue continue
} }
entry, _, err := GetDatabaseEntry(depend) entry, _, err := GetRepositoryEntry(depend)
if err != nil { if err != nil {
return errors.New("could not get database entry for package (" + depend + ")") return errors.New("could not get repository entry for package (" + depend + ")")
} }
operation.InsertActionAt(pos, &FetchPackageAction{ operation.InsertActionAt(pos, &FetchPackageAction{
InstallationReason: installationReason, IsDependency: true,
DatabaseEntry: entry, RepositoryEntry: entry,
}) })
pos++ pos++
} }
@ -191,7 +192,7 @@ func (operation *BPMOperation) RemoveNeededPackages() error {
return nil return nil
} }
func (operation *BPMOperation) Cleanup(cleanupMakeDepends bool) error { func (operation *BPMOperation) Cleanup() error {
// Get all installed packages // Get all installed packages
installedPackageNames, err := GetInstalledPackages(operation.RootDir) installedPackageNames, err := GetInstalledPackages(operation.RootDir)
if err != nil { if err != nil {
@ -227,7 +228,7 @@ func (operation *BPMOperation) Cleanup(cleanupMakeDepends bool) error {
} }
keepPackages = append(keepPackages, pkg.Name) keepPackages = append(keepPackages, pkg.Name)
resolved := pkg.GetAllDependencies(!cleanupMakeDepends, true, operation.RootDir) resolved := pkg.GetAllDependencies(false, true, operation.RootDir)
for _, value := range resolved { for _, value := range resolved {
if !slices.Contains(keepPackages, value) { if !slices.Contains(keepPackages, value) {
keepPackages = append(keepPackages, value) keepPackages = append(keepPackages, value)
@ -262,7 +263,7 @@ func (operation *BPMOperation) ReplaceObsoletePackages() {
} else if value.GetActionType() == "fetch" { } else if value.GetActionType() == "fetch" {
action := value.(*FetchPackageAction) action := value.(*FetchPackageAction)
pkgInfo = action.DatabaseEntry.Info pkgInfo = action.RepositoryEntry.Info
} else { } else {
continue continue
} }
@ -300,7 +301,7 @@ func (operation *BPMOperation) CheckForConflicts() (map[string][]string, error)
allPackages = append(allPackages, pkgInfo) allPackages = append(allPackages, pkgInfo)
} else if value.GetActionType() == "fetch" { } else if value.GetActionType() == "fetch" {
action := value.(*FetchPackageAction) action := value.(*FetchPackageAction)
pkgInfo := action.DatabaseEntry.Info pkgInfo := action.RepositoryEntry.Info
allPackages = append(allPackages, pkgInfo) allPackages = append(allPackages, pkgInfo)
} else if value.GetActionType() == "remove" { } else if value.GetActionType() == "remove" {
action := value.(*RemovePackageAction) action := value.(*RemovePackageAction)
@ -335,16 +336,13 @@ func (operation *BPMOperation) ShowOperationSummary() {
for _, value := range operation.Actions { for _, value := range operation.Actions {
var pkgInfo *PackageInfo var pkgInfo *PackageInfo
var installationReason = InstallationReasonUnknown
if value.GetActionType() == "install" { if value.GetActionType() == "install" {
installationReason = value.(*InstallPackageAction).InstallationReason
pkgInfo = value.(*InstallPackageAction).BpmPackage.PkgInfo pkgInfo = value.(*InstallPackageAction).BpmPackage.PkgInfo
if value.(*InstallPackageAction).SplitPackageToInstall != "" { if value.(*InstallPackageAction).SplitPackageToInstall != "" {
pkgInfo = pkgInfo.GetSplitPackageInfo(value.(*InstallPackageAction).SplitPackageToInstall) pkgInfo = pkgInfo.GetSplitPackageInfo(value.(*InstallPackageAction).SplitPackageToInstall)
} }
} else if value.GetActionType() == "fetch" { } else if value.GetActionType() == "fetch" {
installationReason = value.(*FetchPackageAction).InstallationReason pkgInfo = value.(*FetchPackageAction).RepositoryEntry.Info
pkgInfo = value.(*FetchPackageAction).DatabaseEntry.Info
} else { } else {
pkgInfo = value.(*RemovePackageAction).BpmPackage.PkgInfo pkgInfo = value.(*RemovePackageAction).BpmPackage.PkgInfo
fmt.Printf("%s: %s (Remove)\n", pkgInfo.Name, pkgInfo.GetFullVersion()) fmt.Printf("%s: %s (Remove)\n", pkgInfo.Name, pkgInfo.GetFullVersion())
@ -352,32 +350,21 @@ func (operation *BPMOperation) ShowOperationSummary() {
} }
installedInfo := GetPackageInfo(pkgInfo.Name, operation.RootDir) installedInfo := GetPackageInfo(pkgInfo.Name, operation.RootDir)
additionalInfo := "" sourceInfo := ""
switch installationReason {
case InstallationReasonManual:
additionalInfo = "(Manual)"
case InstallationReasonDependency:
additionalInfo = "(Dependency)"
case InstallationReasonMakeDependency:
additionalInfo = "(Make dependency)"
default:
additionalInfo = "(Unknown)"
}
if pkgInfo.Type == "source" { if pkgInfo.Type == "source" {
additionalInfo += " (From Source)" sourceInfo = "(From Source)"
} }
if installedInfo == nil { if installedInfo == nil {
fmt.Printf("%s: %s (Install) %s\n", pkgInfo.Name, pkgInfo.GetFullVersion(), additionalInfo) fmt.Printf("%s: %s (Install) %s\n", pkgInfo.Name, pkgInfo.GetFullVersion(), sourceInfo)
} else { } else {
comparison := ComparePackageVersions(*pkgInfo, *installedInfo) comparison := ComparePackageVersions(*pkgInfo, *installedInfo)
if comparison < 0 { if comparison < 0 {
fmt.Printf("%s: %s -> %s (Downgrade) %s\n", pkgInfo.Name, installedInfo.GetFullVersion(), pkgInfo.GetFullVersion(), additionalInfo) fmt.Printf("%s: %s -> %s (Downgrade) %s\n", pkgInfo.Name, installedInfo.GetFullVersion(), pkgInfo.GetFullVersion(), sourceInfo)
} else if comparison > 0 { } else if comparison > 0 {
fmt.Printf("%s: %s -> %s (Upgrade) %s\n", pkgInfo.Name, installedInfo.GetFullVersion(), pkgInfo.GetFullVersion(), additionalInfo) fmt.Printf("%s: %s -> %s (Upgrade) %s\n", pkgInfo.Name, installedInfo.GetFullVersion(), pkgInfo.GetFullVersion(), sourceInfo)
} else { } else {
fmt.Printf("%s: %s (Reinstall) %s\n", pkgInfo.Name, pkgInfo.GetFullVersion(), additionalInfo) fmt.Printf("%s: %s (Reinstall) %s\n", pkgInfo.Name, pkgInfo.GetFullVersion(), sourceInfo)
} }
} }
} }
@ -427,11 +414,11 @@ func (operation *BPMOperation) RunHooks(verbose bool) error {
} }
func (operation *BPMOperation) Execute(verbose, force bool) (err error) { func (operation *BPMOperation) Execute(verbose, force bool) (err error) {
// Fetch packages from databases // Fetch packages from repositories
if slices.ContainsFunc(operation.Actions, func(action OperationAction) bool { if slices.ContainsFunc(operation.Actions, func(action OperationAction) bool {
return action.GetActionType() == "fetch" return action.GetActionType() == "fetch"
}) { }) {
fmt.Println("Fetching packages from available databases...") fmt.Println("Fetching packages from available repositories...")
// Create map for fetched packages // Create map for fetched packages
fetchedPackages := make(map[string]string) fetchedPackages := make(map[string]string)
@ -441,16 +428,16 @@ func (operation *BPMOperation) Execute(verbose, force bool) (err error) {
continue continue
} }
// Get database entry // Get repository entry
entry := action.(*FetchPackageAction).DatabaseEntry entry := action.(*FetchPackageAction).RepositoryEntry
// Create bpmpkg variable // Create bpmpkg variable
var bpmpkg *BPMPackage var bpmpkg *BPMPackage
// Check if package has already been fetched from download link // Check if package has already been fetched from download link
if _, ok := fetchedPackages[entry.Download]; !ok { if _, ok := fetchedPackages[entry.Download]; !ok {
// Fetch package from database // Fetch package from repository
fetchedPackage, err := entry.Database.FetchPackage(entry.Info.Name) fetchedPackage, err := entry.Repository.FetchPackage(entry.Info.Name)
if err != nil { if err != nil {
return errors.New(fmt.Sprintf("could not fetch package (%s): %s\n", entry.Info.Name, err)) return errors.New(fmt.Sprintf("could not fetch package (%s): %s\n", entry.Info.Name, err))
} }
@ -478,15 +465,15 @@ func (operation *BPMOperation) Execute(verbose, force bool) (err error) {
if bpmpkg.PkgInfo.IsSplitPackage() { if bpmpkg.PkgInfo.IsSplitPackage() {
operation.Actions[i] = &InstallPackageAction{ operation.Actions[i] = &InstallPackageAction{
File: fetchedPackages[entry.Download], File: fetchedPackages[entry.Download],
InstallationReason: action.(*FetchPackageAction).InstallationReason, IsDependency: action.(*FetchPackageAction).IsDependency,
BpmPackage: bpmpkg, BpmPackage: bpmpkg,
SplitPackageToInstall: entry.Info.Name, SplitPackageToInstall: entry.Info.Name,
} }
} else { } else {
operation.Actions[i] = &InstallPackageAction{ operation.Actions[i] = &InstallPackageAction{
File: fetchedPackages[entry.Download], File: fetchedPackages[entry.Download],
InstallationReason: action.(*FetchPackageAction).InstallationReason, IsDependency: action.(*FetchPackageAction).IsDependency,
BpmPackage: bpmpkg, BpmPackage: bpmpkg,
} }
} }
} }
@ -566,7 +553,7 @@ func (operation *BPMOperation) Execute(verbose, force bool) (err error) {
} }
} }
if value.InstallationReason != InstallationReasonManual { if value.IsDependency {
err = installPackage(fileToInstall, operation.RootDir, verbose, true) err = installPackage(fileToInstall, operation.RootDir, verbose, true)
} else { } else {
err = installPackage(fileToInstall, operation.RootDir, verbose, force) err = installPackage(fileToInstall, operation.RootDir, verbose, force)
@ -574,8 +561,13 @@ func (operation *BPMOperation) Execute(verbose, force bool) (err error) {
if err != nil { if err != nil {
return errors.New(fmt.Sprintf("could not install package (%s): %s\n", bpmpkg.PkgInfo.Name, err)) return errors.New(fmt.Sprintf("could not install package (%s): %s\n", bpmpkg.PkgInfo.Name, err))
} }
if !isReinstall { if operation.ForceInstallationReason != InstallationReasonUnknown && !value.IsDependency {
err := SetInstallationReason(bpmpkg.PkgInfo.Name, value.InstallationReason, operation.RootDir) err := SetInstallationReason(bpmpkg.PkgInfo.Name, operation.ForceInstallationReason, operation.RootDir)
if err != nil {
return errors.New(fmt.Sprintf("could not set installation reason for package (%s): %s\n", value.BpmPackage.PkgInfo.Name, err))
}
} else if value.IsDependency && !isReinstall {
err := SetInstallationReason(bpmpkg.PkgInfo.Name, InstallationReasonDependency, operation.RootDir)
if err != nil { if err != nil {
return errors.New(fmt.Sprintf("could not set installation reason for package (%s): %s\n", value.BpmPackage.PkgInfo.Name, err)) return errors.New(fmt.Sprintf("could not set installation reason for package (%s): %s\n", value.BpmPackage.PkgInfo.Name, err))
} }
@ -594,7 +586,7 @@ type OperationAction interface {
type InstallPackageAction struct { type InstallPackageAction struct {
File string File string
InstallationReason InstallationReason IsDependency bool
SplitPackageToInstall string SplitPackageToInstall string
BpmPackage *BPMPackage BpmPackage *BPMPackage
} }
@ -604,8 +596,8 @@ func (action *InstallPackageAction) GetActionType() string {
} }
type FetchPackageAction struct { type FetchPackageAction struct {
InstallationReason InstallationReason IsDependency bool
DatabaseEntry *BPMDatabaseEntry RepositoryEntry *RepositoryEntry
} }
func (action *FetchPackageAction) GetActionType() string { func (action *FetchPackageAction) GetActionType() string {

View File

@ -92,10 +92,9 @@ func (pkgInfo *PackageInfo) GetSplitPackageInfo(splitPkg string) *PackageInfo {
type InstallationReason string type InstallationReason string
const ( const (
InstallationReasonManual InstallationReason = "manual" InstallationReasonManual InstallationReason = "manual"
InstallationReasonDependency InstallationReason = "dependency" InstallationReasonDependency InstallationReason = "dependency"
InstallationReasonMakeDependency InstallationReason = "make_dependency" InstallationReasonUnknown InstallationReason = "unknown"
InstallationReasonUnknown InstallationReason = "unknown"
) )
func ComparePackageVersions(info1, info2 PackageInfo) int { func ComparePackageVersions(info1, info2 PackageInfo) int {
@ -120,8 +119,6 @@ func GetInstallationReason(pkg, rootDir string) InstallationReason {
return InstallationReasonManual return InstallationReasonManual
} else if reason == "dependency" { } else if reason == "dependency" {
return InstallationReasonDependency return InstallationReasonDependency
} else if reason == "make_dependency" {
return InstallationReasonMakeDependency
} }
return InstallationReasonUnknown return InstallationReasonUnknown
} }
@ -469,7 +466,8 @@ func ReadPackageInfo(contents string) (*PackageInfo, error) {
pkgInfoClone := *pkgInfo pkgInfoClone := *pkgInfo
pkgInfo.SplitPackages[i] = &pkgInfoClone pkgInfo.SplitPackages[i] = &pkgInfoClone
// Set split package field of split package to nil // Set make depends and split package field of split package to nil
pkgInfo.SplitPackages[i].MakeDepends = nil
pkgInfo.SplitPackages[i].SplitPackages = nil pkgInfo.SplitPackages[i].SplitPackages = nil
// Unmarshal json data back to struct // Unmarshal json data back to struct
@ -486,7 +484,7 @@ func ReadPackageInfo(contents string) (*PackageInfo, error) {
return pkgInfo, nil return pkgInfo, nil
} }
func CreateReadableInfo(showArchitecture, showType, showPackageRelations, showInstallationReason bool, pkgInfo *PackageInfo, rootDir string) string { func CreateReadableInfo(showArchitecture, showType, showPackageRelations bool, pkgInfo *PackageInfo, rootDir string) string {
ret := make([]string, 0) ret := make([]string, 0)
appendArray := func(label string, array []string) { appendArray := func(label string, array []string) {
if len(array) == 0 { if len(array) == 0 {
@ -526,21 +524,7 @@ func CreateReadableInfo(showArchitecture, showType, showPackageRelations, showIn
} }
appendArray("Split Packages", splitPkgs) appendArray("Split Packages", splitPkgs)
} }
if IsPackageInstalled(pkgInfo.Name, rootDir) && showInstallationReason { ret = append(ret, "Installation Reason: "+string(GetInstallationReason(pkgInfo.Name, rootDir)))
installationReason := GetInstallationReason(pkgInfo.Name, rootDir)
var installationReasonString string
switch installationReason {
case InstallationReasonManual:
installationReasonString = "Manual"
case InstallationReasonDependency:
installationReasonString = "Dependency"
case InstallationReasonMakeDependency:
installationReasonString = "Make dependency"
default:
installationReasonString = "Unknown"
}
ret = append(ret, "Installation Reason: "+installationReasonString)
}
return strings.Join(ret, "\n") return strings.Join(ret, "\n")
} }

View File

@ -12,41 +12,41 @@ import (
"strings" "strings"
) )
type BPMDatabase struct { type Repository struct {
Name string `yaml:"name"` Name string `yaml:"name"`
Source string `yaml:"source"` Source string `yaml:"source"`
Disabled *bool `yaml:"disabled"` Disabled *bool `yaml:"disabled"`
Entries map[string]*BPMDatabaseEntry Entries map[string]*RepositoryEntry
VirtualPackages map[string][]string VirtualPackages map[string][]string
} }
type BPMDatabaseEntry struct { type RepositoryEntry struct {
Info *PackageInfo `yaml:"info"` Info *PackageInfo `yaml:"info"`
Download string `yaml:"download"` Download string `yaml:"download"`
DownloadSize uint64 `yaml:"download_size"` DownloadSize uint64 `yaml:"download_size"`
InstalledSize uint64 `yaml:"installed_size"` InstalledSize uint64 `yaml:"installed_size"`
Database *BPMDatabase Repository *Repository
} }
func (db *BPMDatabase) ContainsPackage(pkg string) bool { func (repo *Repository) ContainsPackage(pkg string) bool {
_, ok := db.Entries[pkg] _, ok := repo.Entries[pkg]
return ok return ok
} }
func (db *BPMDatabase) ReadLocalDatabase() error { func (repo *Repository) ReadLocalDatabase() error {
dbFile := "/var/lib/bpm/databases/" + db.Name + ".bpmdb" repoFile := "/var/lib/bpm/repositories/" + repo.Name + ".bpmdb"
if _, err := os.Stat(dbFile); err != nil { if _, err := os.Stat(repoFile); err != nil {
return nil return nil
} }
bytes, err := os.ReadFile(dbFile) bytes, err := os.ReadFile(repoFile)
if err != nil { if err != nil {
return err return err
} }
data := string(bytes) data := string(bytes)
for _, b := range strings.Split(data, "---") { for _, b := range strings.Split(data, "---") {
entry := BPMDatabaseEntry{ entry := RepositoryEntry{
Info: &PackageInfo{ Info: &PackageInfo{
Name: "", Name: "",
Description: "", Description: "",
@ -66,14 +66,14 @@ func (db *BPMDatabase) ReadLocalDatabase() error {
Download: "", Download: "",
DownloadSize: 0, DownloadSize: 0,
InstalledSize: 0, InstalledSize: 0,
Database: db, Repository: repo,
} }
err := yaml.Unmarshal([]byte(b), &entry) err := yaml.Unmarshal([]byte(b), &entry)
if err != nil { if err != nil {
return err return err
} }
// Create database entries // Create repository entries
if entry.Info.IsSplitPackage() { if entry.Info.IsSplitPackage() {
for _, splitPkg := range entry.Info.SplitPackages { for _, splitPkg := range entry.Info.SplitPackages {
// Turn split package into json data // Turn split package into json data
@ -100,26 +100,26 @@ func (db *BPMDatabase) ReadLocalDatabase() error {
splitPkgClone.Url = entry.Info.Url splitPkgClone.Url = entry.Info.Url
// Create entry for split package // Create entry for split package
db.Entries[splitPkg.Name] = &BPMDatabaseEntry{ repo.Entries[splitPkg.Name] = &RepositoryEntry{
Info: &splitPkgClone, Info: &splitPkgClone,
Download: entry.Download, Download: entry.Download,
DownloadSize: entry.DownloadSize, DownloadSize: entry.DownloadSize,
InstalledSize: 0, InstalledSize: 0,
Database: db, Repository: repo,
} }
// Add virtual packages to database // Add virtual packages to repository
for _, p := range splitPkg.Provides { for _, p := range splitPkg.Provides {
db.VirtualPackages[p] = append(db.VirtualPackages[p], splitPkg.Name) repo.VirtualPackages[p] = append(repo.VirtualPackages[p], splitPkg.Name)
} }
} }
} else { } else {
// Create entry for package // Create entry for package
db.Entries[entry.Info.Name] = &entry repo.Entries[entry.Info.Name] = &entry
// Add virtual packages to database // Add virtual packages to repository
for _, p := range entry.Info.Provides { for _, p := range entry.Info.Provides {
db.VirtualPackages[p] = append(db.VirtualPackages[p], entry.Info.Name) repo.VirtualPackages[p] = append(repo.VirtualPackages[p], entry.Info.Name)
} }
} }
@ -128,11 +128,11 @@ func (db *BPMDatabase) ReadLocalDatabase() error {
return nil return nil
} }
func (db *BPMDatabase) SyncLocalDatabaseFile() error { func (repo *Repository) SyncLocalDatabase() error {
dbFile := "/var/lib/bpm/databases/" + db.Name + ".bpmdb" repoFile := "/var/lib/bpm/repositories/" + repo.Name + ".bpmdb"
// Get URL to database // Get URL to database
u, err := url.JoinPath(db.Source, "database.bpmdb") u, err := url.JoinPath(repo.Source, "database.bpmdb")
if err != nil { if err != nil {
return err return err
} }
@ -147,20 +147,20 @@ func (db *BPMDatabase) SyncLocalDatabaseFile() error {
// Load data into byte buffer // Load data into byte buffer
buffer, err := io.ReadAll(resp.Body) buffer, err := io.ReadAll(resp.Body)
// Unmarshal data to ensure it is a valid BPM database // Unmarshal data to ensure it is a valid BPM repository
err = yaml.Unmarshal(buffer, &BPMDatabase{}) err = yaml.Unmarshal(buffer, &Repository{})
if err != nil { if err != nil {
return fmt.Errorf("could not decode database: %s", err) return fmt.Errorf("could not decode repository: %s", err)
} }
// Create parent directories to database file // Create parent directories to repository file
err = os.MkdirAll(path.Dir(dbFile), 0755) err = os.MkdirAll(path.Dir(repoFile), 0755)
if err != nil { if err != nil {
return err return err
} }
// Create file and save database data // Create file and save repository data
out, err := os.Create(dbFile) out, err := os.Create(repoFile)
if err != nil { if err != nil {
return err return err
} }
@ -171,14 +171,14 @@ func (db *BPMDatabase) SyncLocalDatabaseFile() error {
return nil return nil
} }
func ReadLocalDatabaseFiles() (err error) { func ReadLocalDatabases() (err error) {
for _, db := range BPMConfig.Databases { for _, repo := range BPMConfig.Repositories {
// Initialize struct values // Initialize struct values
db.Entries = make(map[string]*BPMDatabaseEntry) repo.Entries = make(map[string]*RepositoryEntry)
db.VirtualPackages = make(map[string][]string) repo.VirtualPackages = make(map[string][]string)
// Read database // Read database
err = db.ReadLocalDatabase() err = repo.ReadLocalDatabase()
if err != nil { if err != nil {
return err return err
} }
@ -187,47 +187,47 @@ func ReadLocalDatabaseFiles() (err error) {
return nil return nil
} }
func GetDatabase(name string) *BPMDatabase { func GetRepository(name string) *Repository {
for _, db := range BPMConfig.Databases { for _, repo := range BPMConfig.Repositories {
if db.Name == name { if repo.Name == name {
return db return repo
} }
} }
return nil return nil
} }
func GetDatabaseEntry(str string) (*BPMDatabaseEntry, *BPMDatabase, error) { func GetRepositoryEntry(str string) (*RepositoryEntry, *Repository, error) {
split := strings.Split(str, "/") split := strings.Split(str, "/")
if len(split) == 1 { if len(split) == 1 {
pkgName := strings.TrimSpace(split[0]) pkgName := strings.TrimSpace(split[0])
if pkgName == "" { if pkgName == "" {
return nil, nil, errors.New("could not find database entry for this package") return nil, nil, errors.New("could not find repository entry for this package")
} }
for _, db := range BPMConfig.Databases { for _, repo := range BPMConfig.Repositories {
if db.ContainsPackage(pkgName) { if repo.ContainsPackage(pkgName) {
return db.Entries[pkgName], db, nil return repo.Entries[pkgName], repo, nil
} }
} }
return nil, nil, errors.New("could not find database entry for this package") return nil, nil, errors.New("could not find repository entry for this package")
} else if len(split) == 2 { } else if len(split) == 2 {
dbName := strings.TrimSpace(split[0]) repoName := strings.TrimSpace(split[0])
pkgName := strings.TrimSpace(split[1]) pkgName := strings.TrimSpace(split[1])
if dbName == "" || pkgName == "" { if repoName == "" || pkgName == "" {
return nil, nil, errors.New("could not find database entry for this package") return nil, nil, errors.New("could not find repository entry for this package")
} }
db := GetDatabase(dbName) repo := GetRepository(repoName)
if db == nil || !db.ContainsPackage(pkgName) { if repo == nil || !repo.ContainsPackage(pkgName) {
return nil, nil, errors.New("could not find database entry for this package") return nil, nil, errors.New("could not find repository entry for this package")
} }
return db.Entries[pkgName], db, nil return repo.Entries[pkgName], repo, nil
} else { } else {
return nil, nil, errors.New("could not find database entry for this package") return nil, nil, errors.New("could not find repository entry for this package")
} }
} }
func FindReplacement(pkg string) *BPMDatabaseEntry { func FindReplacement(pkg string) *RepositoryEntry {
for _, db := range BPMConfig.Databases { for _, repo := range BPMConfig.Repositories {
for _, entry := range db.Entries { for _, entry := range repo.Entries {
for _, replaced := range entry.Info.Replaces { for _, replaced := range entry.Info.Replaces {
if replaced == pkg { if replaced == pkg {
return entry return entry
@ -239,11 +239,11 @@ func FindReplacement(pkg string) *BPMDatabaseEntry {
return nil return nil
} }
func ResolveVirtualPackage(vpkg string) *BPMDatabaseEntry { func ResolveVirtualPackage(vpkg string) *RepositoryEntry {
for _, db := range BPMConfig.Databases { for _, repo := range BPMConfig.Repositories {
if v, ok := db.VirtualPackages[vpkg]; ok { if v, ok := repo.VirtualPackages[vpkg]; ok {
for _, pkg := range v { for _, pkg := range v {
return db.Entries[pkg] return repo.Entries[pkg]
} }
} }
} }
@ -251,12 +251,12 @@ func ResolveVirtualPackage(vpkg string) *BPMDatabaseEntry {
return nil return nil
} }
func (db *BPMDatabase) FetchPackage(pkg string) (string, error) { func (repo *Repository) FetchPackage(pkg string) (string, error) {
if !db.ContainsPackage(pkg) { if !repo.ContainsPackage(pkg) {
return "", errors.New("could not fetch package '" + pkg + "'") return "", errors.New("could not fetch package '" + pkg + "'")
} }
entry := db.Entries[pkg] entry := repo.Entries[pkg]
URL, err := url.JoinPath(db.Source, entry.Download) URL, err := url.JoinPath(repo.Source, entry.Download)
if err != nil { if err != nil {
return "", err return "", err
} }