Skip to content

Commit

Permalink
Improve remove.go
Browse files Browse the repository at this point in the history
  • Loading branch information
xplshn committed Oct 6, 2024
1 parent 5497a27 commit 679b7d1
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 46 deletions.
108 changes: 68 additions & 40 deletions remove.go
Original file line number Diff line number Diff line change
@@ -1,64 +1,92 @@
// remove.go // This file implements the functionality of "remove" //>
package main

import (
"fmt"
"os"
"path/filepath"
"strings"
"sync"

"github.com/pkg/xattr"
)

// removeCommand handles the removal of one or more binaries based on the verbosity level.
// removeCommand handles the overall flow, passing binaries to removeBinaries and ensuring tracker cleanup.
func removeCommand(binaries []string, installDir, trackerFile string, verbosityLevel Verbosity) error {
if len(binaries) == 1 {
err := removeBinary(binaries[0], installDir, verbosityLevel)
if err != nil {
return err
}
} else if len(binaries) > 1 {
// Remove duplicates before processing
binaries = removeDuplicates(binaries)
err := multipleRemove(binaries, installDir, verbosityLevel)
if err != nil {
return err
}
// Call removeBinaries to handle the actual removal process
err := removeBinaries(removeDuplicates(binaries), installDir, verbosityLevel)
if err != nil {
return err
}

// Cleanup the tracker file after removal
err := cleanupTrackerFile(trackerFile, installDir)
// Cleanup the tracker file after all binaries are removed
err = cleanupTrackerFile(trackerFile, installDir)
if err != nil {
return fmt.Errorf("error cleaning up tracker file: %w", err)
}

return nil
}

// removeBinary removes a single binary and logs the operation based on verbosity level.
func removeBinary(binaryName, installDir string, verbosityLevel Verbosity) error {
installPath := filepath.Join(installDir, filepath.Base(binaryName))
err := os.Remove(installPath)
if err != nil {
if os.IsNotExist(err) {
if verbosityLevel >= normalVerbosity {
fmt.Fprintf(os.Stderr, "Warning: '%s' does not exist in %s\n", binaryName, installDir)
}
} else {
if verbosityLevel >= silentVerbosityWithErrors {
fmt.Fprintf(os.Stderr, "error: failed to remove '%s' from %s. %v\n", binaryName, installDir, err)
}
return err
// removeBinaries processes each binary, removing only those that pass validation.
func removeBinaries(binaries []string, installDir string, verbosityLevel Verbosity) error {
var wg sync.WaitGroup
var removeErrors []string
var mutex sync.Mutex

// Inline function to check if a binary is ours
validate := func(file string) bool {
if isSymlink(file) {
return false
}
} else if verbosityLevel <= extraVerbose {
fmt.Printf("'%s' removed from %s\n", binaryName, installDir)
managedBy, err := xattr.Get(file, "user.ManagedBy")
if err != nil || string(managedBy) != "dbin" {
return false
}
return true
}
return nil
}

// multipleRemove removes multiple binaries and logs the operations based on verbosity level.
func multipleRemove(binaries []string, installDir string, verbosityLevel Verbosity) error {
// Loop over the binaries and remove the valid ones
for _, binaryName := range binaries {
if err := removeBinary(binaryName, installDir, verbosityLevel); err != nil {
return err
}
wg.Add(1)
go func(binaryName string) {
defer wg.Done()

installPath := filepath.Join(installDir, filepath.Base(binaryName))

if !validate(installPath) {
if verbosityLevel >= normalVerbosity {
fmt.Fprintf(os.Stderr, "Skipping '%s': it was not installed by dbin\n", binaryName)
}
return
}

err := os.Remove(installPath)
if err != nil {
if os.IsNotExist(err) {
if verbosityLevel >= normalVerbosity {
fmt.Fprintf(os.Stderr, "Warning: '%s' does not exist in %s\n", binaryName, installDir)
}
} else {
if verbosityLevel >= silentVerbosityWithErrors {
fmt.Fprintf(os.Stderr, "error: failed to remove '%s' from %s. %v\n", binaryName, installDir, err)
}
// Add error to the list in a thread-safe way, i guess
mutex.Lock()
removeErrors = append(removeErrors, fmt.Sprintf("failed to remove '%s' from %s: %v", binaryName, installDir, err))
mutex.Unlock()
}
} else if verbosityLevel <= extraVerbose {
fmt.Printf("'%s' removed from %s\n", binaryName, installDir)
}
}(binaryName)
}

// Wait for all goroutines to finish
wg.Wait()

// Return concatenated errors if any occurred
if len(removeErrors) > 0 {
return fmt.Errorf(strings.Join(removeErrors, "\n"))
}

return nil
}
11 changes: 5 additions & 6 deletions utility.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,12 +86,6 @@ func validateProgramsFrom(installDir, trackerFile string, metadataURLs, programs
programsToValidate = removeDuplicates(programsToValidate)
validPrograms := make([]string, 0, len(programsToValidate))

// Inline function to check if a file is a symlink
isSymlink := func(filePath string) bool {
fileInfo, err := os.Lstat(filePath)
return err == nil && fileInfo.Mode()&os.ModeSymlink != 0
}

// Inline function to get the binary name or fall back to the original name
getBinaryName := func(file string) string {
binaryName, err := getBinaryNameFromTrackerFile(trackerFile, file)
Expand Down Expand Up @@ -406,3 +400,8 @@ func calculateChecksum(filePath string) (string, error) {

return fmt.Sprintf("%x", hasher.Sum(nil)), nil
}

func isSymlink(filePath string) bool {
fileInfo, err := os.Lstat(filePath)
return err == nil && fileInfo.Mode()&os.ModeSymlink != 0
}

0 comments on commit 679b7d1

Please sign in to comment.