5 Commits
7 changed files with 197 additions and 134 deletions
+27 -9
View File
@@ -92,7 +92,7 @@ func main() {
currentFlagSet.String("installation-reason", "", "Specify the installation reason to use for the specified packages") currentFlagSet.String("installation-reason", "", "Specify the installation reason to use for the specified packages")
currentFlagSet.BoolP("reinstall", "r", false, "Reinstall the specified packages") currentFlagSet.BoolP("reinstall", "r", false, "Reinstall the specified packages")
currentFlagSet.IntP("jobs", "j", bpmlib.CompilationBPMConfig.CompilationJobs, "Set the amount of concurrent processes to use for source package compilation") currentFlagSet.IntP("jobs", "j", bpmlib.CompilationBPMConfig.CompilationJobs, "Set the amount of concurrent processes to use for source package compilation")
currentFlagSet.BoolP("skip-checks", "s", false, "Skip the check function in source.sh scripts") currentFlagSet.BoolP("skip-checks", "s", false, "Skip the check function in recipe.sh scripts")
setupFlagsAndHelp(currentFlagSet, fmt.Sprintf("bpm %s <options>", subcommand), "Install the specified packages", os.Args[2:]) setupFlagsAndHelp(currentFlagSet, fmt.Sprintf("bpm %s <options>", subcommand), "Install the specified packages", os.Args[2:])
installPackages() installPackages()
@@ -141,7 +141,7 @@ func main() {
currentFlagSet.BoolP("yes", "y", false, "Enter 'yes' in all prompts") currentFlagSet.BoolP("yes", "y", false, "Enter 'yes' in all prompts")
currentFlagSet.BoolP("no-sync", "n", false, "Do not sync databases") currentFlagSet.BoolP("no-sync", "n", false, "Do not sync databases")
currentFlagSet.Bool("allow-downgrades", false, "Allow package downgrades") currentFlagSet.Bool("allow-downgrades", false, "Allow package downgrades")
currentFlagSet.BoolP("skip-checks", "s", false, "Skip the check function in source.sh scripts") currentFlagSet.BoolP("skip-checks", "s", false, "Skip the check function in recipe.sh scripts")
currentFlagSet.IntP("jobs", "j", bpmlib.CompilationBPMConfig.CompilationJobs, "Set the amount of concurrent processes to use for source package compilation") currentFlagSet.IntP("jobs", "j", bpmlib.CompilationBPMConfig.CompilationJobs, "Set the amount of concurrent processes to use for source package compilation")
setupFlagsAndHelp(currentFlagSet, fmt.Sprintf("bpm %s <options>", subcommand), "Update installed packages", os.Args[2:]) setupFlagsAndHelp(currentFlagSet, fmt.Sprintf("bpm %s <options>", subcommand), "Update installed packages", os.Args[2:])
@@ -161,7 +161,7 @@ func main() {
currentFlagSet.BoolP("force", "f", false, "Bypass warnings during package compilation") currentFlagSet.BoolP("force", "f", false, "Bypass warnings during package compilation")
currentFlagSet.BoolP("yes", "y", false, "Enter 'yes' in all prompts") currentFlagSet.BoolP("yes", "y", false, "Enter 'yes' in all prompts")
currentFlagSet.BoolP("depends", "d", false, "Install required dependencies for package compilation") currentFlagSet.BoolP("depends", "d", false, "Install required dependencies for package compilation")
currentFlagSet.BoolP("skip-checks", "s", false, "Skip the check function in source.sh scripts") currentFlagSet.BoolP("skip-checks", "s", false, "Skip the check function in recipe.sh scripts")
currentFlagSet.BoolP("keep", "k", false, "Keep compilation files after successful package compilation") currentFlagSet.BoolP("keep", "k", false, "Keep compilation files after successful package compilation")
currentFlagSet.BoolP("output-directory", "o", false, "Set the output directory for the binary packages") currentFlagSet.BoolP("output-directory", "o", false, "Set the output directory for the binary packages")
currentFlagSet.Int("output-fd", -1, "Set the file descriptor output package names will be written to") currentFlagSet.Int("output-fd", -1, "Set the file descriptor output package names will be written to")
@@ -240,11 +240,12 @@ func showPackageInfo() {
for n, pkg := range packages { for n, pkg := range packages {
if showDatabaseInfo { if showDatabaseInfo {
var err error // Split package name and required version
var entry *bpmlib.BPMDatabaseEntry pkgName, _, _ := bpmlib.SplitPkgNameAndVersion(pkg)
entry, _, err = bpmlib.GetDatabaseEntry(pkg)
entry, _, err := bpmlib.GetDatabaseEntry(pkgName)
if err != nil { if err != nil {
if providers := bpmlib.GetDatabaseVirtualPackageEntry(pkg); len(providers) > 0 { if providers := bpmlib.GetDatabaseVirtualPackageEntry(pkgName); len(providers) > 0 {
entry = providers[0] entry = providers[0]
} else { } else {
log.Printf("Error: could not find package (%s) in any database\n", pkg) log.Printf("Error: could not find package (%s) in any database\n", pkg)
@@ -253,6 +254,12 @@ func showPackageInfo() {
} }
} }
if !bpmlib.EvaluateDependency(pkg, entry.Info.Version) {
log.Printf("Error: could not find package (%s) in any database\n", pkg)
exitCode = 1
continue
}
if n != 0 { if n != 0 {
fmt.Println() fmt.Println()
} }
@@ -272,17 +279,28 @@ func showPackageInfo() {
} }
isFile = true isFile = true
} else { } else {
if providers := bpmlib.GetVirtualPackageInfo(pkg, rootDir); len(providers) > 0 { // Split package name and required version
pkgName, _, _ := bpmlib.SplitPkgNameAndVersion(pkg)
if providers := bpmlib.GetVirtualPackageInfo(pkgName, rootDir); len(providers) > 0 {
bpmpkg = bpmlib.GetPackage(providers[0].Name, rootDir) bpmpkg = bpmlib.GetPackage(providers[0].Name, rootDir)
} else { } else {
bpmpkg = bpmlib.GetPackage(pkg, rootDir) bpmpkg = bpmlib.GetPackage(pkgName, rootDir)
} }
} }
if bpmpkg == nil { if bpmpkg == nil {
log.Printf("Error: package (%s) is not installed\n", pkg) log.Printf("Error: package (%s) is not installed\n", pkg)
exitCode = 1 exitCode = 1
return return
} }
if !bpmlib.EvaluateDependency(pkg, bpmpkg.PkgInfo.Version) {
log.Printf("Error: package (%s) is not installed\n", pkg)
exitCode = 1
return
}
if n != 0 { if n != 0 {
fmt.Println() fmt.Println()
} }
+38 -25
View File
@@ -96,8 +96,8 @@ func CompileSourcePackage(archiveFilename, outputDirectory string, compilationJo
return nil, err return nil, err
} }
// Extract source.sh file // Extract recipe.sh file
err = extractTarballFile(archiveFilename, "source.sh", tempDirectory, uid, gid) err = extractTarballFile(archiveFilename, "recipe.sh", tempDirectory, uid, gid)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -166,10 +166,10 @@ func CompileSourcePackage(archiveFilename, outputDirectory string, compilationJo
env = append(env, "CMAKE_BUILD_PARALLEL_LEVEL="+strconv.Itoa(compilationJobs)) env = append(env, "CMAKE_BUILD_PARALLEL_LEVEL="+strconv.Itoa(compilationJobs))
env = append(env, "CARGO_BUILD_JOBS="+strconv.Itoa(compilationJobs)) env = append(env, "CARGO_BUILD_JOBS="+strconv.Itoa(compilationJobs))
// Execute prepare and build functions in source.sh script // Execute prepare and build functions in recipe.sh script
cmd := exec.Command("bash", "-c", cmd := exec.Command("bash", "-c",
"set -a\n"+ // Source and export functions and variables in source.sh script "set -a\n"+ // Source and export functions and variables in recipe.sh script
". \"${BPM_WORKDIR}\"/source.sh\n"+ ". \"${BPM_WORKDIR}\"/recipe.sh\n"+
"set +a\n"+ "set +a\n"+
"[[ $(type -t prepare) == \"function\" ]] && { echo \"Running prepare() function...\"; bash -e -c 'cd \"$BPM_WORKDIR\" && prepare' || exit 1; }\n"+ // Run prepare() function if it exists "[[ $(type -t prepare) == \"function\" ]] && { echo \"Running prepare() function...\"; bash -e -c 'cd \"$BPM_WORKDIR\" && prepare' || exit 1; }\n"+ // Run prepare() function if it exists
"[[ $(type -t build) == \"function\" ]] && { echo \"Running build() function...\"; bash -e -c 'cd \"$BPM_SOURCE\" && build' || exit 1; }\n"+ // Run build() function if it exists "[[ $(type -t build) == \"function\" ]] && { echo \"Running build() function...\"; bash -e -c 'cd \"$BPM_SOURCE\" && build' || exit 1; }\n"+ // Run build() function if it exists
@@ -187,11 +187,11 @@ func CompileSourcePackage(archiveFilename, outputDirectory string, compilationJo
return nil, err return nil, err
} }
// Execute check function in source.sh script if not skipping checks // Execute check function in recipe.sh script if not skipping checks
if !skipChecks { if !skipChecks {
cmd = exec.Command("bash", "-c", cmd = exec.Command("bash", "-c",
"set -a\n"+ // Source and export functions and variables in source.sh script "set -a\n"+ // Source and export functions and variables in recipe.sh script
". \"${BPM_WORKDIR}\"/source.sh\n"+ ". \"${BPM_WORKDIR}\"/recipe.sh\n"+
"set +a\n"+ "set +a\n"+
"[[ $(type -t check) == \"function\" ]] && { echo \"Running check() function...\"; bash -e -c 'cd \"$BPM_SOURCE\" && check' || exit 1; }\n"+ // Run check() function if it exists "[[ $(type -t check) == \"function\" ]] && { echo \"Running check() function...\"; bash -e -c 'cd \"$BPM_SOURCE\" && check' || exit 1; }\n"+ // Run check() function if it exists
"exit 0") "exit 0")
@@ -238,10 +238,10 @@ func CompileSourcePackage(archiveFilename, outputDirectory string, compilationJo
packageFunctionName = "package_" + pkg.Name packageFunctionName = "package_" + pkg.Name
} }
// Execute package function in source.sh script and generate package file list // Execute package function in recipe.sh script and generate package file list
cmd = exec.Command("bash", "-c", cmd = exec.Command("bash", "-c",
"set -a\n"+ // Source and export functions and variables in source.sh script "set -a\n"+ // Source and export functions and variables in recipe.sh script
". \"${BPM_WORKDIR}\"/source.sh\n"+ ". \"${BPM_WORKDIR}\"/recipe.sh\n"+
"set +a\n"+ "set +a\n"+
"echo \"Running "+packageFunctionName+"() function...\"\n"+ "echo \"Running "+packageFunctionName+"() function...\"\n"+
"( cd \"$BPM_SOURCE\" && fakeroot -s \"$BPM_WORKDIR\"/fakeroot_file bash -e -c '"+packageFunctionName+"' ) || exit 1\n") // Run package() function "( cd \"$BPM_SOURCE\" && fakeroot -s \"$BPM_WORKDIR\"/fakeroot_file bash -e -c '"+packageFunctionName+"' ) || exit 1\n") // Run package() function
@@ -329,7 +329,7 @@ func CompileSourcePackage(archiveFilename, outputDirectory string, compilationJo
// Generate package file list // Generate package file list
fmt.Println("Generating package file list...") fmt.Println("Generating package file list...")
cmd = exec.Command("bash", "-c", "fakeroot -i \"$BPM_WORKDIR\"/fakeroot_file find \"$BPM_OUTPUT\" -mindepth 1 -printf \"%P %#m %U %G %s\\n\" > \"$BPM_WORKDIR\"/pkg.files") cmd = exec.Command("bash", "-c", "fakeroot -i \"$BPM_WORKDIR\"/fakeroot_file find \"$BPM_OUTPUT\" -mindepth 1 -printf \"%P %#m %U %G %s\\n\" > \"$BPM_WORKDIR\"/files.txt")
cmd.Dir = tempDirectory cmd.Dir = tempDirectory
cmd.Stdout = os.Stdout cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr cmd.Stderr = os.Stderr
@@ -345,7 +345,15 @@ func CompileSourcePackage(archiveFilename, outputDirectory string, compilationJo
// Create gzip-compressed archive for the package files // Create gzip-compressed archive for the package files
fmt.Println("Generating compressed file archive...") fmt.Println("Generating compressed file archive...")
cmd = exec.Command("bash", "-c", fmt.Sprintf("find %s -printf \"%%P\\n\" | fakeroot -i %s/fakeroot_file tar -czf files.tar.gz --no-recursion -C %s -T -", "output_"+pkg.Name, tempDirectory, "output_"+pkg.Name)) cmd = exec.Command("bash", "-c", fmt.Sprintf(`find %s -printf "%%P\n" | fakeroot -i %s/fakeroot_file tar czf files.tar.gz \
--sort=name \
--pax-option=exthdr.name=%%d/PaxHeaders/%%f,delete=atime,delete=ctime \
--mtime="UTC 1970-01-01" \
--numeric-owner \
--no-recursion \
-C %s \
-T -`,
"output_"+pkg.Name, tempDirectory, "output_"+pkg.Name))
cmd.Dir = tempDirectory cmd.Dir = tempDirectory
cmd.Stdout = os.Stdout cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr cmd.Stderr = os.Stderr
@@ -380,26 +388,31 @@ func CompileSourcePackage(archiveFilename, outputDirectory string, compilationJo
} }
pkgInfoBytes = append(pkgInfoBytes, '\n') pkgInfoBytes = append(pkgInfoBytes, '\n')
// Create pkg.info file // Create info.yml file
err = os.WriteFile(path.Join(tempDirectory, "pkg.info"), pkgInfoBytes, 0644) err = os.WriteFile(path.Join(tempDirectory, "info.yml"), pkgInfoBytes, 0644)
if err != nil { if err != nil {
return nil, err return nil, err
} }
// Change pkg.info file owner // Change info.yml file owner
err = os.Chown(path.Join(tempDirectory, "pkg.info"), uid, gid) err = os.Chown(path.Join(tempDirectory, "info.yml"), uid, gid)
if err != nil { if err != nil {
return nil, err return nil, err
} }
// Get files to include in BPM archive // Get files to include in BPM archive
bpmArchiveFiles := make([]string, 0) bpmArchiveFiles := make([]string, 0)
bpmArchiveFiles = append(bpmArchiveFiles, "pkg.info", "pkg.files", "files.tar.gz") // Base files bpmArchiveFiles = append(bpmArchiveFiles, "info.yml", "files.txt", "files.tar.gz") // Base files
bpmArchiveFiles = append(bpmArchiveFiles, packageScripts...) // Package scripts bpmArchiveFiles = append(bpmArchiveFiles, packageScripts...) // Package scripts
// Create final BPM archive // Create final BPM archive
fmt.Println("Generating final BPM archive...") fmt.Println("Generating final BPM archive...")
cmd = exec.Command("bash", "-c", "tar -cf final-archive.bpm --owner=0 --group=0 -C \"$BPM_WORKDIR\" "+strings.Join(bpmArchiveFiles, " ")) cmd = exec.Command("tar", "cf", "final-archive.bpm",
"--sort=name",
"--pax-option=exthdr.name=%d/PaxHeaders/%f,delete=atime,delete=ctime",
"--mtime=UTC 1970-01-01",
"--owner=0", "--group=0", "--numeric-owner")
cmd.Args = append(cmd.Args, bpmArchiveFiles...)
cmd.Dir = tempDirectory cmd.Dir = tempDirectory
cmd.Stdout = os.Stdout cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr cmd.Stderr = os.Stderr
@@ -417,8 +430,8 @@ func CompileSourcePackage(archiveFilename, outputDirectory string, compilationJo
return nil, fmt.Errorf("BPM archive could not be created: %s", err) return nil, fmt.Errorf("BPM archive could not be created: %s", err)
} }
// Remove pkg.info file // Remove info.yml file
err = os.Remove(path.Join(tempDirectory, "pkg.info")) err = os.Remove(path.Join(tempDirectory, "info.yml"))
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -725,8 +738,8 @@ func showPackageFiles(archiveFilename string) error {
return nil return nil
} }
// Print pkg.info content // Print info.yml content
err = printTarballContent("pkg.info") err = printTarballContent("info.yml")
if err != nil { if err != nil {
return err return err
} }
@@ -748,8 +761,8 @@ func showPackageFiles(archiveFilename string) error {
} }
} }
// Print source.sh content // Print recipe.sh content
err = printTarballContent("source.sh") err = printTarballContent("recipe.sh")
if err != nil { if err != nil {
return err return err
} }
+1 -1
View File
@@ -159,7 +159,7 @@ func ResolveDependencies(pkgInfo *PackageInfo, resolvedVirtualPackages map[strin
} }
// Skip ignored packages in config // Skip ignored packages in config
if slices.Contains(MainBPMConfig.IgnorePackages, dependEntry.Info.Name) { if rootDir == "/" && slices.Contains(MainBPMConfig.IgnorePackages, dependEntry.Info.Name) {
continue continue
} }
+13 -13
View File
@@ -51,7 +51,7 @@ func InstallPackages(rootDir string, forceInstallationReason InstallationReason,
} }
} }
operation.AppendAction(&InstallPackageAction{ operation.Actions = append(operation.Actions, &InstallPackageAction{
File: pkg, File: pkg,
InstallationReason: installationReason, InstallationReason: installationReason,
BpmPackage: bpmpkg, BpmPackage: bpmpkg,
@@ -75,7 +75,7 @@ func InstallPackages(rootDir string, forceInstallationReason InstallationReason,
} }
} }
operation.AppendAction(&InstallPackageAction{ operation.Actions = append(operation.Actions, &InstallPackageAction{
File: pkg, File: pkg,
InstallationReason: installationReason, InstallationReason: installationReason,
BpmPackage: bpmpkg, BpmPackage: bpmpkg,
@@ -120,7 +120,7 @@ func InstallPackages(rootDir string, forceInstallationReason InstallationReason,
} }
} }
operation.AppendAction(&FetchPackageAction{ operation.Actions = append(operation.Actions, &FetchPackageAction{
InstallationReason: installationReason, InstallationReason: installationReason,
DatabaseEntry: entry, DatabaseEntry: entry,
}) })
@@ -206,7 +206,7 @@ func RemovePackages(rootDir string, force, cleanupDependencies bool, packages ..
if bpmpkg == nil { if bpmpkg == nil {
continue continue
} }
operation.AppendAction(&RemovePackageAction{BpmPackage: bpmpkg}) operation.Actions = append(operation.Actions, &RemovePackageAction{BpmPackage: bpmpkg})
} }
// Do package cleanup // Do package cleanup
@@ -223,7 +223,7 @@ func RemovePackages(rootDir string, force, cleanupDependencies bool, packages ..
packageDepndants := make(map[string][]string, 0) packageDepndants := make(map[string][]string, 0)
for _, action := range operation.Actions { for _, action := range operation.Actions {
// Skip package if ignored in config // Skip package if ignored in config
if slices.Contains(MainBPMConfig.IgnorePackages, action.(*RemovePackageAction).BpmPackage.PkgInfo.Name) { if rootDir == "/" && slices.Contains(MainBPMConfig.IgnorePackages, action.(*RemovePackageAction).BpmPackage.PkgInfo.Name) {
continue continue
} }
@@ -243,7 +243,7 @@ func RemovePackages(rootDir string, force, cleanupDependencies bool, packages ..
// Remove dependant packages if ignored // Remove dependant packages if ignored
for pkg, required := range packageDepndants { for pkg, required := range packageDepndants {
required = slices.DeleteFunc(required, func(pkgName string) bool { required = slices.DeleteFunc(required, func(pkgName string) bool {
return slices.Contains(MainBPMConfig.IgnorePackages, pkgName) return rootDir == "/" && slices.Contains(MainBPMConfig.IgnorePackages, pkgName)
}) })
packageDepndants[pkg] = required packageDepndants[pkg] = required
} }
@@ -404,7 +404,7 @@ func UpdatePackages(rootDir string, syncDatabase, allowDowngrades, forceInstalla
// Search for packages // Search for packages
pkgsNotFound := make([]string, 0) pkgsNotFound := make([]string, 0)
for _, pkg := range pkgs { for _, pkg := range pkgs {
if slices.Contains(MainBPMConfig.IgnorePackages, pkg) { if rootDir == "/" && slices.Contains(MainBPMConfig.IgnorePackages, pkg) {
continue continue
} }
var entry *BPMDatabaseEntry var entry *BPMDatabaseEntry
@@ -421,7 +421,7 @@ func UpdatePackages(rootDir string, syncDatabase, allowDowngrades, forceInstalla
} else { } else {
comparison := CompareVersions(entry.Info.GetFullVersion(), installedInfo.GetFullVersion()) comparison := CompareVersions(entry.Info.GetFullVersion(), installedInfo.GetFullVersion())
if (!allowDowngrades && comparison > 0) || (allowDowngrades && comparison != 0) { if (!allowDowngrades && comparison > 0) || (allowDowngrades && comparison != 0) {
operation.AppendAction(&FetchPackageAction{ operation.Actions = append(operation.Actions, &FetchPackageAction{
InstallationReason: GetPackage(pkg, rootDir).LocalInfo.GetInstallationReason(), InstallationReason: GetPackage(pkg, rootDir).LocalInfo.GetInstallationReason(),
DatabaseEntry: entry, DatabaseEntry: entry,
}) })
@@ -452,12 +452,12 @@ func UpdatePackages(rootDir string, syncDatabase, allowDowngrades, forceInstalla
} }
// Skip dependency if action already exists // Skip dependency if action already exists
if operation.ActionsContainPackage(dependEntry.Info.Name) { if ActionSliceIndex(operation.Actions, dependEntry.Info.Name) != -1 {
continue continue
} }
// Skip dependency if ignored in config // Skip dependency if ignored in config
if slices.Contains(MainBPMConfig.IgnorePackages, dependEntry.Info.Name) { if rootDir == "/" && slices.Contains(MainBPMConfig.IgnorePackages, dependEntry.Info.Name) {
continue continue
} }
@@ -468,7 +468,7 @@ func UpdatePackages(rootDir string, syncDatabase, allowDowngrades, forceInstalla
} }
// Fetch dependency // Fetch dependency
operation.AppendAction(&FetchPackageAction{ operation.Actions = append(operation.Actions, &FetchPackageAction{
InstallationReason: InstallationReasonDependency, InstallationReason: InstallationReasonDependency,
DatabaseEntry: dependEntry, DatabaseEntry: dependEntry,
}) })
@@ -499,7 +499,7 @@ func UpdatePackages(rootDir string, syncDatabase, allowDowngrades, forceInstalla
} }
// Skip dependency if ignored in config // Skip dependency if ignored in config
if slices.Contains(MainBPMConfig.IgnorePackages, dependEntry.Info.Name) { if rootDir == "/" && slices.Contains(MainBPMConfig.IgnorePackages, dependEntry.Info.Name) {
continue continue
} }
@@ -510,7 +510,7 @@ func UpdatePackages(rootDir string, syncDatabase, allowDowngrades, forceInstalla
} }
// Fetch dependency // Fetch dependency
operation.AppendAction(&FetchPackageAction{ operation.Actions = append(operation.Actions, &FetchPackageAction{
InstallationReason: InstallationReasonDependency, InstallationReason: InstallationReasonDependency,
DatabaseEntry: dependEntry, DatabaseEntry: dependEntry,
}) })
+37 -10
View File
@@ -63,7 +63,7 @@ func InitializeLocalPackageInformation(rootDir string) (err error) {
} }
// Read package info // Read package info
infoData, err := os.ReadFile(path.Join(installedDir, item.Name(), "info")) infoData, err := os.ReadFile(path.Join(installedDir, item.Name(), "info.yml"))
if err != nil { if err != nil {
return err return err
} }
@@ -220,7 +220,7 @@ func getPackageFiles(pkg, rootDir string) []*PackageFileEntry {
var pkgFiles []*PackageFileEntry var pkgFiles []*PackageFileEntry
installedDir := path.Join(rootDir, "var/lib/bpm/installed/") installedDir := path.Join(rootDir, "var/lib/bpm/installed/")
pkgDir := path.Join(installedDir, pkg) pkgDir := path.Join(installedDir, pkg)
files := path.Join(pkgDir, "files") files := path.Join(pkgDir, "files.txt")
if _, err := os.Stat(installedDir); os.IsNotExist(err) { if _, err := os.Stat(installedDir); os.IsNotExist(err) {
return nil return nil
} }
@@ -280,7 +280,7 @@ func getPackageLocalInfo(pkg, rootDir string) PackageLocalInfo {
installedDir := path.Join(rootDir, "var/lib/bpm/installed/") installedDir := path.Join(rootDir, "var/lib/bpm/installed/")
pkgDir := path.Join(installedDir, pkg) pkgDir := path.Join(installedDir, pkg)
localInfoFile := path.Join(path.Join(pkgDir, "local")) localInfoFile := path.Join(path.Join(pkgDir, "local.yml"))
if _, err := os.Stat(localInfoFile); os.IsNotExist(err) { if _, err := os.Stat(localInfoFile); os.IsNotExist(err) {
return localInfo return localInfo
@@ -304,7 +304,7 @@ func SetPackageLocalInfo(pkg string, localInfo PackageLocalInfo, rootDir string)
installedDir := path.Join(rootDir, "var/lib/bpm/installed/") installedDir := path.Join(rootDir, "var/lib/bpm/installed/")
pkgDir := path.Join(installedDir, pkg) pkgDir := path.Join(installedDir, pkg)
localFile, err := os.OpenFile(path.Join(pkgDir, "local"), os.O_WRONLY|os.O_CREATE, 0644) localFile, err := os.OpenFile(path.Join(pkgDir, "local.yml"), os.O_WRONLY|os.O_CREATE, 0644)
if err != nil { if err != nil {
return err return err
} }
@@ -332,10 +332,35 @@ func UpgradePersistentData(rootDir string) error {
for _, entry := range dirEntries { for _, entry := range dirEntries {
pkgDir := path.Join(persistentDataDir, "installed", entry.Name()) pkgDir := path.Join(persistentDataDir, "installed", entry.Name())
// Generate default local package information file // Rename 'info' file to 'info.yml'
if _, err := os.Stat(path.Join(pkgDir, "local")); err != nil && !os.IsNotExist(err) { if _, err := os.Stat(path.Join(pkgDir, "info")); err == nil {
fmt.Printf("Moving 'info' to 'info.yml' for package (%s)\n", entry.Name())
err := os.Rename(path.Join(pkgDir, "info"), path.Join(pkgDir, "info.yml"))
if err != nil {
return err return err
} else if os.IsNotExist(err) { }
}
// Rename 'files' file to 'files.txt'
if _, err := os.Stat(path.Join(pkgDir, "files")); err == nil {
fmt.Printf("Moving 'files' to 'files.txt' for package (%s)\n", entry.Name())
err := os.Rename(path.Join(pkgDir, "files"), path.Join(pkgDir, "files.txt"))
if err != nil {
return err
}
}
// Rename 'local' file to 'local.yml'
if _, err := os.Stat(path.Join(pkgDir, "local")); err == nil {
fmt.Printf("Moving 'local' to 'local.yml' for package (%s)\n", entry.Name())
err := os.Rename(path.Join(pkgDir, "local"), path.Join(pkgDir, "local.yml"))
if err != nil {
return err
}
}
// Generate default local package information file
if _, err := os.Stat(path.Join(pkgDir, "local.yml")); os.IsNotExist(err) {
fmt.Printf("Generating local package information for package (%s)\n", entry.Name()) fmt.Printf("Generating local package information for package (%s)\n", entry.Name())
out, err := yaml.Marshal(PackageLocalInfo{ out, err := yaml.Marshal(PackageLocalInfo{
@@ -347,10 +372,12 @@ func UpgradePersistentData(rootDir string) error {
return err return err
} }
err = os.WriteFile(path.Join(pkgDir, "local"), out, 0644) err = os.WriteFile(path.Join(pkgDir, "local.yml"), out, 0644)
if err != nil { if err != nil {
return err return err
} }
} else if err != nil {
return err
} }
// Move installation reason to local package information file // Move installation reason to local package information file
@@ -359,7 +386,7 @@ func UpgradePersistentData(rootDir string) error {
} else if err == nil { } else if err == nil {
fmt.Printf("Moving installation reason to local package information for package (%s)\n", entry.Name()) fmt.Printf("Moving installation reason to local package information for package (%s)\n", entry.Name())
data, err := os.ReadFile(path.Join(pkgDir, "local")) data, err := os.ReadFile(path.Join(pkgDir, "local.yml"))
if err != nil { if err != nil {
return err return err
} }
@@ -377,7 +404,7 @@ func UpgradePersistentData(rootDir string) error {
return err return err
} }
err = os.WriteFile(path.Join(pkgDir, "local"), out, 0644) err = os.WriteFile(path.Join(pkgDir, "local.yml"), out, 0644)
if err != nil { if err != nil {
return err return err
} }
+65 -60
View File
@@ -23,54 +23,6 @@ type BPMOperation struct {
hasFetchedPackages bool hasFetchedPackages bool
} }
func (operation *BPMOperation) ActionsContainPackage(pkg string) bool {
for _, action := range operation.Actions {
if action.GetActionType() == "install" {
if action.(*InstallPackageAction).BpmPackage.PkgInfo.Name == pkg {
return true
}
} else if action.GetActionType() == "fetch" {
if action.(*FetchPackageAction).DatabaseEntry.Info.Name == pkg {
return true
}
} else if action.GetActionType() == "remove" {
if action.(*RemovePackageAction).BpmPackage.PkgInfo.Name == pkg {
return true
}
}
}
return false
}
func (operation *BPMOperation) AppendAction(action OperationAction) {
operation.InsertActionAt(len(operation.Actions), action)
}
func (operation *BPMOperation) InsertActionAt(index int, action OperationAction) {
if len(operation.Actions) == index { // nil or empty slice or after last element
operation.Actions = append(operation.Actions, action)
} else {
operation.Actions = append(operation.Actions[:index+1], operation.Actions[index:]...) // index < len(a)
operation.Actions[index] = action
}
}
func (operation *BPMOperation) RemoveAction(pkg, actionType string) {
operation.Actions = slices.DeleteFunc(operation.Actions, func(a OperationAction) bool {
if a.GetActionType() != actionType {
return false
}
if a.GetActionType() == "install" {
return a.(*InstallPackageAction).BpmPackage.PkgInfo.Name == pkg
} else if a.GetActionType() == "fetch" {
return a.(*FetchPackageAction).DatabaseEntry.Info.Name == pkg
} else if a.GetActionType() == "remove" {
return a.(*RemovePackageAction).BpmPackage.PkgInfo.Name == pkg
}
return false
})
}
func (operation *BPMOperation) GetTotalDownloadSize() int64 { func (operation *BPMOperation) GetTotalDownloadSize() int64 {
var ret int64 = 0 var ret int64 = 0
for _, action := range operation.Actions { for _, action := range operation.Actions {
@@ -136,8 +88,8 @@ func (operation *BPMOperation) ResolveDependencies(installRuntimeDepends bool) {
} }
// Discover all dependencies // Discover all dependencies
pos := 0 newActions := make([]OperationAction, 0)
for _, value := range slices.Clone(operation.Actions) { for _, value := range operation.Actions {
var pkgInfo *PackageInfo var pkgInfo *PackageInfo
if value.GetActionType() == "install" { if value.GetActionType() == "install" {
action := value.(*InstallPackageAction) action := value.(*InstallPackageAction)
@@ -156,11 +108,12 @@ func (operation *BPMOperation) ResolveDependencies(installRuntimeDepends bool) {
operation.UnresolvedDepends = removeDuplicates(operation.UnresolvedDepends) operation.UnresolvedDepends = removeDuplicates(operation.UnresolvedDepends)
for _, resolvedPkg := range resolved { for _, resolvedPkg := range resolved {
if !operation.ActionsContainPackage(resolvedPkg.DatabaseEntry.Info.Name) && resolvedPkg.DatabaseEntry.Info.Name != pkgInfo.Name { if ActionSliceIndex(newActions, resolvedPkg.DatabaseEntry.Info.Name) == -1 { // Dependency not in actions slice
operation.InsertActionAt(pos, &FetchPackageAction{ var action OperationAction = &FetchPackageAction{
InstallationReason: resolvedPkg.InstallationReason, InstallationReason: resolvedPkg.InstallationReason,
DatabaseEntry: resolvedPkg.DatabaseEntry, DatabaseEntry: resolvedPkg.DatabaseEntry,
}) }
newActions = append(newActions, action)
for _, vpkg := range resolvedPkg.DatabaseEntry.Info.Provides { for _, vpkg := range resolvedPkg.DatabaseEntry.Info.Provides {
if _, ok := resolvedVirtualPackages[vpkg]; !ok { if _, ok := resolvedVirtualPackages[vpkg]; !ok {
@@ -168,12 +121,19 @@ func (operation *BPMOperation) ResolveDependencies(installRuntimeDepends bool) {
} }
} }
pos++ // Check if can move original action
if i := ActionSliceIndex(operation.Actions, resolvedPkg.DatabaseEntry.Info.Name); i != -1 {
newActions[len(newActions)-1] = operation.Actions[i]
}
} }
} }
pos++ if ActionSliceIndex(newActions, pkgInfo.Name) == -1 {
newActions = append(newActions, value)
} }
}
operation.Actions = newActions
} }
func (operation *BPMOperation) Cleanup(cleanupMakeDepends bool) error { func (operation *BPMOperation) Cleanup(cleanupMakeDepends bool) error {
@@ -289,10 +249,11 @@ func (operation *BPMOperation) ReplaceObsoletePackages() {
} }
for _, r := range pkgInfo.Replaces { for _, r := range pkgInfo.Replaces {
if bpmpkg := GetPackage(r, operation.RootDir); bpmpkg != nil && !operation.ActionsContainPackage(bpmpkg.PkgInfo.Name) { if bpmpkg := GetPackage(r, operation.RootDir); bpmpkg != nil && ActionSliceIndex(operation.Actions, bpmpkg.PkgInfo.Name) == -1 {
operation.InsertActionAt(0, &RemovePackageAction{ var action OperationAction = &RemovePackageAction{
BpmPackage: bpmpkg, BpmPackage: bpmpkg,
}) }
operation.Actions = slices.Insert(operation.Actions, 0, action)
} }
} }
} }
@@ -688,10 +649,16 @@ func (operation *BPMOperation) GetModifiedFiles() {
installAction := action.(*InstallPackageAction) installAction := action.(*InstallPackageAction)
isUpgrade := IsPackageInstalled(installAction.BpmPackage.PkgInfo.Name, operation.RootDir) isUpgrade := IsPackageInstalled(installAction.BpmPackage.PkgInfo.Name, operation.RootDir)
if isUpgrade {
for _, pkgFile := range installAction.BpmPackage.PkgFiles {
operation.ModifiedFiles[pkgFile.Path] = "upgrade"
}
for _, pkgFile := range GetPackage(installAction.BpmPackage.PkgInfo.Name, operation.RootDir).PkgFiles {
operation.ModifiedFiles[pkgFile.Path] = "upgrade"
}
} else {
for _, pkgFile := range installAction.BpmPackage.PkgFiles { for _, pkgFile := range installAction.BpmPackage.PkgFiles {
operation.ModifiedFiles[pkgFile.Path] = "install" operation.ModifiedFiles[pkgFile.Path] = "install"
if isUpgrade {
operation.ModifiedFiles[pkgFile.Path] = "upgrade"
} }
} }
} }
@@ -832,3 +799,41 @@ type RemovePackageAction struct {
func (action *RemovePackageAction) GetActionType() string { func (action *RemovePackageAction) GetActionType() string {
return "remove" return "remove"
} }
func ActionSliceIndex(actions []OperationAction, pkg string) int {
for i, action := range actions {
if action.GetActionType() == "install" {
if action.(*InstallPackageAction).BpmPackage.PkgInfo.Name == pkg {
return i
}
} else if action.GetActionType() == "fetch" {
if action.(*FetchPackageAction).DatabaseEntry.Info.Name == pkg {
return i
}
} else if action.GetActionType() == "remove" {
if action.(*RemovePackageAction).BpmPackage.PkgInfo.Name == pkg {
return i
}
}
}
return -1
}
func ActionSliceRemove(actions []OperationAction, pkg, actionType string) []OperationAction {
actions = slices.DeleteFunc(actions, func(a OperationAction) bool {
if a.GetActionType() != actionType {
return false
}
if a.GetActionType() == "install" {
return a.(*InstallPackageAction).BpmPackage.PkgInfo.Name == pkg
} else if a.GetActionType() == "fetch" {
return a.(*FetchPackageAction).DatabaseEntry.Info.Name == pkg
} else if a.GetActionType() == "remove" {
return a.(*RemovePackageAction).BpmPackage.PkgInfo.Name == pkg
}
return false
})
return actions
}
+15 -15
View File
@@ -163,7 +163,7 @@ func GetPackageInfoRaw(filename string) (string, error) {
if err != nil { if err != nil {
return "", err return "", err
} }
if header.Name == "pkg.info" { if header.Name == "info.yml" {
bs, _ := io.ReadAll(tr) bs, _ := io.ReadAll(tr)
err := file.Close() err := file.Close()
if err != nil { if err != nil {
@@ -172,7 +172,7 @@ func GetPackageInfoRaw(filename string) (string, error) {
return string(bs), nil return string(bs), nil
} }
} }
return "", errors.New("pkg.info not found in archive") return "", errors.New("info.yml not found in archive")
} }
func ReadPackage(filename string) (*BPMPackage, error) { func ReadPackage(filename string) (*BPMPackage, error) {
@@ -198,13 +198,13 @@ func ReadPackage(filename string) (*BPMPackage, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
if header.Name == "pkg.info" { if header.Name == "info.yml" {
bs, _ := io.ReadAll(tr) bs, _ := io.ReadAll(tr)
pkgInfo, err = ReadPackageInfo(string(bs)) pkgInfo, err = ReadPackageInfo(string(bs))
if err != nil { if err != nil {
return nil, err return nil, err
} }
} else if header.Name == "pkg.files" { } else if header.Name == "files.txt" {
bs, _ := io.ReadAll(tr) bs, _ := io.ReadAll(tr)
for _, line := range strings.Split(string(bs), "\n") { for _, line := range strings.Split(string(bs), "\n") {
if strings.TrimSpace(line) == "" { if strings.TrimSpace(line) == "" {
@@ -212,7 +212,7 @@ func ReadPackage(filename string) (*BPMPackage, error) {
} }
stringEntry := strings.Split(strings.TrimSpace(line), " ") stringEntry := strings.Split(strings.TrimSpace(line), " ")
if len(stringEntry) < 5 { if len(stringEntry) < 5 {
return nil, errors.New("pkg.files is not formatted correctly") return nil, errors.New("files.txt is not formatted correctly")
} }
octalPerms, err := strconv.ParseUint(stringEntry[len(stringEntry)-4], 8, 32) octalPerms, err := strconv.ParseUint(stringEntry[len(stringEntry)-4], 8, 32)
if err != nil { if err != nil {
@@ -242,7 +242,7 @@ func ReadPackage(filename string) (*BPMPackage, error) {
} }
if pkgInfo == nil { if pkgInfo == nil {
return nil, errors.New("pkg.info not found in archive") return nil, errors.New("info.yml not found in archive")
} }
return &BPMPackage{ return &BPMPackage{
PkgInfo: pkgInfo, PkgInfo: pkgInfo,
@@ -703,7 +703,7 @@ func extractPackage(bpmpkg *BPMPackage, verbose bool, filename, rootDir string)
if ok := slices.ContainsFunc(MainBPMConfig.IgnorePaths, func(s string) bool { if ok := slices.ContainsFunc(MainBPMConfig.IgnorePaths, func(s string) bool {
matched, _ := filepath.Match(s, header.Name) matched, _ := filepath.Match(s, header.Name)
return matched return matched
}); ok { }); rootDir == "/" && ok {
if verbose { if verbose {
fmt.Printf("Skipping Directory: %s (Path was ignored)\n", extractFilename) fmt.Printf("Skipping Directory: %s (Path was ignored)\n", extractFilename)
} }
@@ -741,7 +741,7 @@ func extractPackage(bpmpkg *BPMPackage, verbose bool, filename, rootDir string)
if ok := slices.ContainsFunc(MainBPMConfig.IgnorePaths, func(s string) bool { if ok := slices.ContainsFunc(MainBPMConfig.IgnorePaths, func(s string) bool {
matched, _ := filepath.Match(s, header.Name) matched, _ := filepath.Match(s, header.Name)
return matched return matched
}); ok { }); rootDir == "/" && ok {
if verbose { if verbose {
fmt.Printf("Skipping File: %s (Path was ignored)\n", extractFilename) fmt.Printf("Skipping File: %s (Path was ignored)\n", extractFilename)
} }
@@ -809,7 +809,7 @@ func extractPackage(bpmpkg *BPMPackage, verbose bool, filename, rootDir string)
if ok := slices.ContainsFunc(MainBPMConfig.IgnorePaths, func(s string) bool { if ok := slices.ContainsFunc(MainBPMConfig.IgnorePaths, func(s string) bool {
matched, _ := filepath.Match(s, header.Name) matched, _ := filepath.Match(s, header.Name)
return matched return matched
}); ok { }); rootDir == "/" && ok {
if verbose { if verbose {
fmt.Printf("Skipping Symlink: %s (Path was ignored)\n", extractFilename) fmt.Printf("Skipping Symlink: %s (Path was ignored)\n", extractFilename)
} }
@@ -835,7 +835,7 @@ func extractPackage(bpmpkg *BPMPackage, verbose bool, filename, rootDir string)
if ok := slices.ContainsFunc(MainBPMConfig.IgnorePaths, func(s string) bool { if ok := slices.ContainsFunc(MainBPMConfig.IgnorePaths, func(s string) bool {
matched, _ := filepath.Match(s, header.Name) matched, _ := filepath.Match(s, header.Name)
return matched return matched
}); ok { }); rootDir == "/" && ok {
if verbose { if verbose {
fmt.Printf("Skipping Hard Link: %s (Path was ignored)\n", extractFilename) fmt.Printf("Skipping Hard Link: %s (Path was ignored)\n", extractFilename)
} }
@@ -930,7 +930,7 @@ func installPackage(filename string, installationReason InstallationReason, root
if ok := slices.ContainsFunc(MainBPMConfig.IgnorePaths, func(s string) bool { if ok := slices.ContainsFunc(MainBPMConfig.IgnorePaths, func(s string) bool {
matched, _ := filepath.Match(s, entry.Path) matched, _ := filepath.Match(s, entry.Path)
return matched return matched
}); ok { }); rootDir == "/" && ok {
if verbose { if verbose {
fmt.Printf("Skipping path: %s (Path was ignored)\n", finalPath) fmt.Printf("Skipping path: %s (Path was ignored)\n", finalPath)
} }
@@ -1034,12 +1034,12 @@ func installPackage(filename string, installationReason InstallationReason, root
return err return err
} }
f, err := os.Create(path.Join(pkgDir, "files")) f, err := os.Create(path.Join(pkgDir, "files.txt"))
if err != nil { if err != nil {
return err return err
} }
tarballFile, err := readTarballFile(filename, "pkg.files") tarballFile, err := readTarballFile(filename, "files.txt")
if err != nil { if err != nil {
return err return err
} }
@@ -1050,7 +1050,7 @@ func installPackage(filename string, installationReason InstallationReason, root
return err return err
} }
f, err = os.Create(path.Join(pkgDir, "info")) f, err = os.Create(path.Join(pkgDir, "info.yml"))
if err != nil { if err != nil {
return err return err
} }
@@ -1183,7 +1183,7 @@ func removePackage(pkg string, verbose bool, rootDir string) error {
if ok := slices.ContainsFunc(MainBPMConfig.IgnorePaths, func(s string) bool { if ok := slices.ContainsFunc(MainBPMConfig.IgnorePaths, func(s string) bool {
matched, _ := filepath.Match(s, entry.Path) matched, _ := filepath.Match(s, entry.Path)
return matched return matched
}); ok { }); rootDir == "/" && ok {
if verbose { if verbose {
fmt.Printf("Skipping path: %s (Path was ignored)\n", finalPath) fmt.Printf("Skipping path: %s (Path was ignored)\n", finalPath)
} }