Switch to new BPM file structure #8
@ -14,6 +14,7 @@ import (
|
|||||||
"path"
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"slices"
|
"slices"
|
||||||
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
@ -148,6 +149,7 @@ func ReadPackage(filename string) (*BPMPackage, error) {
|
|||||||
var pkgFiles []*PackageFileEntry
|
var pkgFiles []*PackageFileEntry
|
||||||
|
|
||||||
if _, err := os.Stat(filename); os.IsNotExist(err) {
|
if _, err := os.Stat(filename); os.IsNotExist(err) {
|
||||||
|
fmt.Println("a")
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -468,34 +470,33 @@ func CreateReadableInfo(showArchitecture, showType, showPackageRelations bool, p
|
|||||||
return strings.Join(ret, "\n")
|
return strings.Join(ret, "\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
func extractPackage(bpmpkg *BPMPackage, verbose bool, filename, rootDir string) (error, []string) {
|
func extractPackage(bpmpkg *BPMPackage, verbose bool, filename, rootDir string) error {
|
||||||
var files []string
|
|
||||||
if !IsPackageInstalled(bpmpkg.PkgInfo.Name, rootDir) {
|
if !IsPackageInstalled(bpmpkg.PkgInfo.Name, rootDir) {
|
||||||
err := ExecutePackageScripts(filename, rootDir, Install, false)
|
err := ExecutePackageScripts(filename, rootDir, Install, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err, nil
|
return err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
err := ExecutePackageScripts(filename, rootDir, Update, false)
|
err := ExecutePackageScripts(filename, rootDir, Update, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err, nil
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
seenHardlinks := make(map[string]string)
|
seenHardlinks := make(map[string]string)
|
||||||
file, err := os.Open(filename)
|
file, err := os.Open(filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err, nil
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
tarballFile, err := ReadTarballContent(filename, "files.tar.gz")
|
tarballFile, err := ReadTarballContent(filename, "files.tar.gz")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err, nil
|
return err
|
||||||
}
|
}
|
||||||
defer tarballFile.file.Close()
|
defer tarballFile.file.Close()
|
||||||
|
|
||||||
archive, err := gzip.NewReader(tarballFile.tarReader)
|
archive, err := gzip.NewReader(tarballFile.tarReader)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err, nil
|
return err
|
||||||
}
|
}
|
||||||
packageFilesReader := tar.NewReader(archive)
|
packageFilesReader := tar.NewReader(archive)
|
||||||
for {
|
for {
|
||||||
@ -504,15 +505,14 @@ func extractPackage(bpmpkg *BPMPackage, verbose bool, filename, rootDir string)
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err, nil
|
return err
|
||||||
}
|
}
|
||||||
extractFilename := path.Join(rootDir, header.Name)
|
extractFilename := path.Join(rootDir, header.Name)
|
||||||
switch header.Typeflag {
|
switch header.Typeflag {
|
||||||
case tar.TypeDir:
|
case tar.TypeDir:
|
||||||
files = append(files, strings.TrimPrefix(header.Name, "./"))
|
|
||||||
if err := os.Mkdir(extractFilename, 0755); err != nil {
|
if err := os.Mkdir(extractFilename, 0755); err != nil {
|
||||||
if !os.IsExist(err) {
|
if !os.IsExist(err) {
|
||||||
return err, nil
|
return err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if verbose {
|
if verbose {
|
||||||
@ -526,18 +526,16 @@ func extractPackage(bpmpkg *BPMPackage, verbose bool, filename, rootDir string)
|
|||||||
if strings.HasSuffix(k, "/") {
|
if strings.HasSuffix(k, "/") {
|
||||||
if strings.HasPrefix(header.Name, k) {
|
if strings.HasPrefix(header.Name, k) {
|
||||||
if verbose {
|
if verbose {
|
||||||
fmt.Println("Skipping File: " + extractFilename + " (Containing directory is set to be kept during installs/updates)")
|
fmt.Println("Skipping File: " + extractFilename + " (Containing directory is set to be kept during reinstalls/updates)")
|
||||||
}
|
}
|
||||||
files = append(files, strings.TrimPrefix(header.Name, "./"))
|
|
||||||
skip = true
|
skip = true
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if header.Name == k {
|
if header.Name == k {
|
||||||
if verbose {
|
if verbose {
|
||||||
fmt.Println("Skipping File: " + extractFilename + " (File is configured to be kept during installs/updates)")
|
fmt.Println("Skipping File: " + extractFilename + " (File is configured to be kept during reinstalls/updates)")
|
||||||
}
|
}
|
||||||
files = append(files, strings.TrimPrefix(header.Name, "./"))
|
|
||||||
skip = true
|
skip = true
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -549,51 +547,48 @@ func extractPackage(bpmpkg *BPMPackage, verbose bool, filename, rootDir string)
|
|||||||
}
|
}
|
||||||
err := os.Remove(extractFilename)
|
err := os.Remove(extractFilename)
|
||||||
if err != nil && !os.IsNotExist(err) {
|
if err != nil && !os.IsNotExist(err) {
|
||||||
return err, nil
|
return err
|
||||||
}
|
}
|
||||||
outFile, err := os.Create(extractFilename)
|
outFile, err := os.Create(extractFilename)
|
||||||
if verbose {
|
if verbose {
|
||||||
fmt.Println("Creating File: " + extractFilename)
|
fmt.Println("Creating File: " + extractFilename)
|
||||||
}
|
}
|
||||||
files = append(files, strings.TrimPrefix(header.Name, "./"))
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err, nil
|
return err
|
||||||
}
|
}
|
||||||
if _, err := io.Copy(outFile, packageFilesReader); err != nil {
|
if _, err := io.Copy(outFile, packageFilesReader); err != nil {
|
||||||
return err, nil
|
return err
|
||||||
}
|
}
|
||||||
if err := os.Chmod(extractFilename, header.FileInfo().Mode()); err != nil {
|
if err := os.Chmod(extractFilename, header.FileInfo().Mode()); err != nil {
|
||||||
return err, nil
|
return err
|
||||||
}
|
}
|
||||||
err = outFile.Close()
|
err = outFile.Close()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err, nil
|
return err
|
||||||
}
|
}
|
||||||
case tar.TypeSymlink:
|
case tar.TypeSymlink:
|
||||||
if verbose {
|
if verbose {
|
||||||
fmt.Println("Creating Symlink: " + extractFilename + " -> " + header.Linkname)
|
fmt.Println("Creating Symlink: " + extractFilename + " -> " + header.Linkname)
|
||||||
}
|
}
|
||||||
files = append(files, strings.TrimPrefix(header.Name, "./"))
|
|
||||||
err := os.Remove(extractFilename)
|
err := os.Remove(extractFilename)
|
||||||
if err != nil && !os.IsNotExist(err) {
|
if err != nil && !os.IsNotExist(err) {
|
||||||
return err, nil
|
return err
|
||||||
}
|
}
|
||||||
err = os.Symlink(header.Linkname, extractFilename)
|
err = os.Symlink(header.Linkname, extractFilename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err, nil
|
return err
|
||||||
}
|
}
|
||||||
case tar.TypeLink:
|
case tar.TypeLink:
|
||||||
if verbose {
|
if verbose {
|
||||||
fmt.Println("Detected Hard Link: " + extractFilename + " -> " + path.Join(rootDir, strings.TrimPrefix(header.Linkname, "files/")))
|
fmt.Println("Detected Hard Link: " + extractFilename + " -> " + path.Join(rootDir, strings.TrimPrefix(header.Linkname, "files/")))
|
||||||
}
|
}
|
||||||
files = append(files, strings.TrimPrefix(header.Name, "./"))
|
|
||||||
seenHardlinks[extractFilename] = path.Join(strings.TrimPrefix(header.Linkname, "files/"))
|
seenHardlinks[extractFilename] = path.Join(strings.TrimPrefix(header.Linkname, "files/"))
|
||||||
err := os.Remove(extractFilename)
|
err := os.Remove(extractFilename)
|
||||||
if err != nil && !os.IsNotExist(err) {
|
if err != nil && !os.IsNotExist(err) {
|
||||||
return err, nil
|
return err
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
return errors.New("unknown type (" + strconv.Itoa(int(header.Typeflag)) + ") in " + extractFilename), nil
|
return errors.New("unknown type (" + strconv.Itoa(int(header.Typeflag)) + ") in " + extractFilename)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for extractFilename, destination := range seenHardlinks {
|
for extractFilename, destination := range seenHardlinks {
|
||||||
@ -602,12 +597,12 @@ func extractPackage(bpmpkg *BPMPackage, verbose bool, filename, rootDir string)
|
|||||||
}
|
}
|
||||||
err := os.Link(path.Join(rootDir, destination), extractFilename)
|
err := os.Link(path.Join(rootDir, destination), extractFilename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err, nil
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
defer archive.Close()
|
defer archive.Close()
|
||||||
defer file.Close()
|
defer file.Close()
|
||||||
return nil, files
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func isSplitPackage(filename string) bool {
|
func isSplitPackage(filename string) bool {
|
||||||
@ -1054,17 +1049,103 @@ func InstallPackage(filename, rootDir string, verbose, force, binaryPkgFromSrc,
|
|||||||
if _, err := os.Stat(filename); os.IsNotExist(err) {
|
if _, err := os.Stat(filename); os.IsNotExist(err) {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
var oldFiles []string
|
|
||||||
var files []string
|
|
||||||
bpmpkg, err := ReadPackage(filename)
|
bpmpkg, err := ReadPackage(filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
packageInstalled := IsPackageInstalled(bpmpkg.PkgInfo.Name, rootDir)
|
packageInstalled := IsPackageInstalled(bpmpkg.PkgInfo.Name, rootDir)
|
||||||
|
// Check if package is installed and remove current files
|
||||||
if packageInstalled {
|
if packageInstalled {
|
||||||
|
// Fetching and reversing package file entry list
|
||||||
fileEntries := GetPackageFiles(bpmpkg.PkgInfo.Name, rootDir)
|
fileEntries := GetPackageFiles(bpmpkg.PkgInfo.Name, rootDir)
|
||||||
|
sort.Slice(fileEntries, func(i, j int) bool {
|
||||||
|
return fileEntries[i].Path < fileEntries[j].Path
|
||||||
|
})
|
||||||
|
slices.Reverse(fileEntries)
|
||||||
|
files, err := GetAllPackageFiles(rootDir, bpmpkg.PkgInfo.Name)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Removing old package files
|
||||||
|
if verbose {
|
||||||
|
fmt.Printf("Removing old files for package (%s)...\n", bpmpkg.PkgInfo.Name)
|
||||||
|
}
|
||||||
for _, entry := range fileEntries {
|
for _, entry := range fileEntries {
|
||||||
files = append(files, entry.Path)
|
file := path.Join(rootDir, entry.Path)
|
||||||
|
stat, err := os.Lstat(file)
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if len(files[entry.Path]) != 0 {
|
||||||
|
if verbose {
|
||||||
|
fmt.Println("Skipping path: " + file + " (Path is managed by multiple packages)")
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
shouldContinue := false
|
||||||
|
for _, value := range bpmpkg.PkgInfo.Keep {
|
||||||
|
if strings.HasSuffix(value, "/") {
|
||||||
|
if strings.HasPrefix(entry.Path, value) || entry.Path == strings.TrimSuffix(value, "/") {
|
||||||
|
if verbose {
|
||||||
|
fmt.Println("Skipping path: " + file + " (Path is set to be kept during reinstalls/updates)")
|
||||||
|
}
|
||||||
|
shouldContinue = true
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if entry.Path == value {
|
||||||
|
if verbose {
|
||||||
|
fmt.Println("Skipping path: " + file + " (Path is set to be kept during reinstalls/updates)")
|
||||||
|
}
|
||||||
|
shouldContinue = true
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if shouldContinue {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if stat.Mode()&os.ModeSymlink != 0 {
|
||||||
|
if verbose {
|
||||||
|
fmt.Println("Removing: " + file)
|
||||||
|
}
|
||||||
|
err := os.Remove(file)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if stat.IsDir() {
|
||||||
|
dir, err := os.ReadDir(file)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if len(dir) != 0 {
|
||||||
|
if verbose {
|
||||||
|
fmt.Println("Skipping non-empty directory: " + file)
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if verbose {
|
||||||
|
fmt.Println("Removing: " + file)
|
||||||
|
}
|
||||||
|
err = os.Remove(file)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if verbose {
|
||||||
|
fmt.Println("Removing: " + file)
|
||||||
|
}
|
||||||
|
err := os.Remove(file)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !force {
|
if !force {
|
||||||
@ -1072,30 +1153,27 @@ func InstallPackage(filename, rootDir string, verbose, force, binaryPkgFromSrc,
|
|||||||
return errors.New("cannot install a package with a different architecture")
|
return errors.New("cannot install a package with a different architecture")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if verbose {
|
||||||
|
fmt.Printf("Extracting files for package (%s)...\n", bpmpkg.PkgInfo.Name)
|
||||||
|
}
|
||||||
|
|
||||||
if bpmpkg.PkgInfo.Type == "binary" {
|
if bpmpkg.PkgInfo.Type == "binary" {
|
||||||
err, i := extractPackage(bpmpkg, verbose, filename, rootDir)
|
err := extractPackage(bpmpkg, verbose, filename, rootDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
files = i
|
|
||||||
} else if bpmpkg.PkgInfo.Type == "source" {
|
} else if bpmpkg.PkgInfo.Type == "source" {
|
||||||
if isSplitPackage(filename) {
|
if isSplitPackage(filename) {
|
||||||
return errors.New("BPM is unable to install split source packages")
|
return errors.New("BPM is unable to install split source packages")
|
||||||
}
|
}
|
||||||
err, i := compilePackage(bpmpkg, filename, rootDir, verbose, binaryPkgFromSrc, skipCheck, keepTempDir)
|
err, _ := compilePackage(bpmpkg, filename, rootDir, verbose, binaryPkgFromSrc, skipCheck, keepTempDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
files = i
|
|
||||||
} else {
|
} else {
|
||||||
return errors.New("unknown package type: " + bpmpkg.PkgInfo.Type)
|
return errors.New("unknown package type: " + bpmpkg.PkgInfo.Type)
|
||||||
}
|
}
|
||||||
slices.Sort(files)
|
|
||||||
slices.Reverse(files)
|
|
||||||
|
|
||||||
filesDiff := slices.DeleteFunc(oldFiles, func(f string) bool {
|
|
||||||
return slices.Contains(files, f)
|
|
||||||
})
|
|
||||||
|
|
||||||
installedDir := path.Join(rootDir, "var/lib/bpm/installed/")
|
installedDir := path.Join(rootDir, "var/lib/bpm/installed/")
|
||||||
err = os.MkdirAll(installedDir, 0755)
|
err = os.MkdirAll(installedDir, 0755)
|
||||||
@ -1164,79 +1242,6 @@ func InstallPackage(filename, rootDir string, verbose, force, binaryPkgFromSrc,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(filesDiff) != 0 {
|
|
||||||
fmt.Println("Removing obsolete files...")
|
|
||||||
var symlinks []string
|
|
||||||
for _, f := range filesDiff {
|
|
||||||
f = path.Join(rootDir, f)
|
|
||||||
lstat, err := os.Lstat(f)
|
|
||||||
if os.IsNotExist(err) {
|
|
||||||
continue
|
|
||||||
} else if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if lstat.Mode()&os.ModeSymlink != 0 {
|
|
||||||
symlinks = append(symlinks, f)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
stat, err := os.Stat(f)
|
|
||||||
if os.IsNotExist(err) {
|
|
||||||
continue
|
|
||||||
} else if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if stat.IsDir() {
|
|
||||||
dir, err := os.ReadDir(f)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if len(dir) == 0 {
|
|
||||||
if verbose {
|
|
||||||
fmt.Println("Removing: " + f)
|
|
||||||
}
|
|
||||||
err := os.Remove(f)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if verbose {
|
|
||||||
fmt.Println("Removing: " + f)
|
|
||||||
}
|
|
||||||
err := os.Remove(f)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
removals := -1
|
|
||||||
for len(symlinks) > 0 && removals != 0 {
|
|
||||||
removals = 0
|
|
||||||
for i := len(symlinks) - 1; i >= 0; i-- {
|
|
||||||
f := symlinks[i]
|
|
||||||
f = path.Join(rootDir, f)
|
|
||||||
_, err := os.Lstat(f)
|
|
||||||
if os.IsNotExist(err) {
|
|
||||||
continue
|
|
||||||
} else if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
_, err = filepath.EvalSymlinks(f)
|
|
||||||
if os.IsNotExist(err) {
|
|
||||||
err := os.Remove(f)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
removals++
|
|
||||||
if verbose {
|
|
||||||
fmt.Println("Removing: " + f)
|
|
||||||
}
|
|
||||||
} else if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !packageInstalled {
|
if !packageInstalled {
|
||||||
err = ExecutePackageScripts(filename, rootDir, Install, true)
|
err = ExecutePackageScripts(filename, rootDir, Install, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -1400,7 +1405,7 @@ func GetPackageFiles(pkg, rootDir string) []*PackageFileEntry {
|
|||||||
stringEntry := strings.Split(strings.TrimSpace(line), " ")
|
stringEntry := strings.Split(strings.TrimSpace(line), " ")
|
||||||
if len(stringEntry) < 5 {
|
if len(stringEntry) < 5 {
|
||||||
pkgFiles = append(pkgFiles, &PackageFileEntry{
|
pkgFiles = append(pkgFiles, &PackageFileEntry{
|
||||||
Path: line,
|
Path: strings.TrimSuffix(line, "/"),
|
||||||
OctalPerms: 0,
|
OctalPerms: 0,
|
||||||
UserID: 0,
|
UserID: 0,
|
||||||
GroupID: 0,
|
GroupID: 0,
|
||||||
@ -1425,7 +1430,7 @@ func GetPackageFiles(pkg, rootDir string) []*PackageFileEntry {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
pkgFiles = append(pkgFiles, &PackageFileEntry{
|
pkgFiles = append(pkgFiles, &PackageFileEntry{
|
||||||
Path: strings.Join(stringEntry[:len(stringEntry)-4], " "),
|
Path: strings.TrimSuffix(strings.Join(stringEntry[:len(stringEntry)-4], " "), "/"),
|
||||||
OctalPerms: uint32(octalPerms),
|
OctalPerms: uint32(octalPerms),
|
||||||
UserID: int(uid),
|
UserID: int(uid),
|
||||||
GroupID: int(gid),
|
GroupID: int(gid),
|
||||||
@ -1472,6 +1477,34 @@ func GetPackage(pkg, rootDir string) *BPMPackage {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetAllPackageFiles(rootDir string, excludePackages ...string) (map[string][]*BPMPackage, error) {
|
||||||
|
ret := make(map[string][]*BPMPackage)
|
||||||
|
|
||||||
|
pkgNames, err := GetInstalledPackages(rootDir)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, pkgName := range pkgNames {
|
||||||
|
if slices.Contains(excludePackages, pkgName) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
bpmpkg := GetPackage(pkgName, rootDir)
|
||||||
|
if bpmpkg == nil {
|
||||||
|
return nil, errors.New(fmt.Sprintf("could not get BPM package (%s)", pkgName))
|
||||||
|
}
|
||||||
|
for _, entry := range bpmpkg.PkgFiles {
|
||||||
|
if _, ok := ret[entry.Path]; ok {
|
||||||
|
ret[entry.Path] = append(ret[entry.Path], bpmpkg)
|
||||||
|
} else {
|
||||||
|
ret[entry.Path] = []*BPMPackage{bpmpkg}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret, nil
|
||||||
|
}
|
||||||
|
|
||||||
func RemovePackage(pkg string, verbose bool, rootDir string) error {
|
func RemovePackage(pkg string, verbose bool, rootDir string) error {
|
||||||
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)
|
||||||
@ -1479,8 +1512,19 @@ func RemovePackage(pkg string, verbose bool, rootDir string) error {
|
|||||||
if pkgInfo == nil {
|
if pkgInfo == nil {
|
||||||
return errors.New("could not get package info")
|
return errors.New("could not get package info")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fetching and reversing package file entry list
|
||||||
fileEntries := GetPackageFiles(pkg, rootDir)
|
fileEntries := GetPackageFiles(pkg, rootDir)
|
||||||
var symlinks []string
|
sort.Slice(fileEntries, func(i, j int) bool {
|
||||||
|
return fileEntries[i].Path < fileEntries[j].Path
|
||||||
|
})
|
||||||
|
slices.Reverse(fileEntries)
|
||||||
|
files, err := GetAllPackageFiles(rootDir, pkg)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Removing package files
|
||||||
for _, entry := range fileEntries {
|
for _, entry := range fileEntries {
|
||||||
file := path.Join(rootDir, entry.Path)
|
file := path.Join(rootDir, entry.Path)
|
||||||
lstat, err := os.Lstat(file)
|
lstat, err := os.Lstat(file)
|
||||||
@ -1490,8 +1534,20 @@ func RemovePackage(pkg string, verbose bool, rootDir string) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if len(files[entry.Path]) != 0 {
|
||||||
|
if verbose {
|
||||||
|
fmt.Println("Skipping path: " + file + "(Path is managed by multiple packages)")
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
if lstat.Mode()&os.ModeSymlink != 0 {
|
if lstat.Mode()&os.ModeSymlink != 0 {
|
||||||
symlinks = append(symlinks, file)
|
if verbose {
|
||||||
|
fmt.Println("Removing: " + file)
|
||||||
|
}
|
||||||
|
err := os.Remove(file)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
stat, err := os.Stat(file)
|
stat, err := os.Stat(file)
|
||||||
@ -1506,14 +1562,18 @@ func RemovePackage(pkg string, verbose bool, rootDir string) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if len(dir) == 0 {
|
if len(dir) != 0 {
|
||||||
if verbose {
|
if verbose {
|
||||||
fmt.Println("Removing: " + file)
|
fmt.Println("Skipping non-empty directory: " + file)
|
||||||
}
|
|
||||||
err := os.Remove(file)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if verbose {
|
||||||
|
fmt.Println("Removing: " + file)
|
||||||
|
}
|
||||||
|
err = os.Remove(file)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if verbose {
|
if verbose {
|
||||||
@ -1525,33 +1585,8 @@ func RemovePackage(pkg string, verbose bool, rootDir string) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
removals := -1
|
|
||||||
for len(symlinks) > 0 && removals != 0 {
|
// Executing post_remove script
|
||||||
removals = 0
|
|
||||||
for i := len(symlinks) - 1; i >= 0; i-- {
|
|
||||||
file := symlinks[i]
|
|
||||||
file = path.Join(rootDir, file)
|
|
||||||
_, err := os.Lstat(file)
|
|
||||||
if os.IsNotExist(err) {
|
|
||||||
continue
|
|
||||||
} else if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
_, err = filepath.EvalSymlinks(file)
|
|
||||||
if os.IsNotExist(err) {
|
|
||||||
err := os.Remove(file)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
removals++
|
|
||||||
if verbose {
|
|
||||||
fmt.Println("Removing: " + file)
|
|
||||||
}
|
|
||||||
} else if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if _, err := os.Stat(path.Join(pkgDir, "post_remove.sh")); err == nil {
|
if _, err := os.Stat(path.Join(pkgDir, "post_remove.sh")); err == nil {
|
||||||
cmd := exec.Command("/bin/bash", path.Join(pkgDir, "post_remove.sh"))
|
cmd := exec.Command("/bin/bash", path.Join(pkgDir, "post_remove.sh"))
|
||||||
if !BPMConfig.SilentCompilation {
|
if !BPMConfig.SilentCompilation {
|
||||||
@ -1586,12 +1621,15 @@ func RemovePackage(pkg string, verbose bool, rootDir string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
err := os.RemoveAll(pkgDir)
|
|
||||||
if err != nil {
|
// Removing package directory
|
||||||
return err
|
|
||||||
}
|
|
||||||
if verbose {
|
if verbose {
|
||||||
fmt.Println("Removing: " + pkgDir)
|
fmt.Println("Removing: " + pkgDir)
|
||||||
}
|
}
|
||||||
|
err = os.RemoveAll(pkgDir)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user