From 3545a5f73be5c3285e5047dea3f52b56c7656d60 Mon Sep 17 00:00:00 2001 From: partisan Date: Sat, 21 Dec 2024 22:21:04 +0100 Subject: [PATCH] Added beter metrics for compression mechanism --- main.go | 19 ++++--- spitfire/upload.go | 126 +++++++++++++++++++++++++++------------------ 2 files changed, 86 insertions(+), 59 deletions(-) diff --git a/main.go b/main.go index 4b9a617..010ba28 100644 --- a/main.go +++ b/main.go @@ -260,18 +260,14 @@ func PackageAndUploadProcess() { log.Fatalf("Error: no valid build or upload path provided.") } - // // This is stupid, it wait for the path to exist (up to a maximum wait time) - // err := waitForPath(pathToUse, 60, 5) // Max 60 seconds, checking every 5 seconds - // if err != nil { - // log.Fatalf("Error: Build path or upload path not found: %v", err) - // } - + // Calculate and display uncompressed size uncompressedSize, err := spitfire.GetDirectorySize(pathToUse) if err != nil { log.Fatalf("Failed to calculate uncompressed size: %v", err) } - fmt.Printf("Uncompressed directory size: %d bytes\n", uncompressedSize) + fmt.Printf("Uncompressed directory size: %s\n", spitfire.BytesToHumanReadable(uncompressedSize)) + // Compress the build directory outputCompressedFile := filepath.Join(".", fmt.Sprintf("%s-%s-%s-%s.tar.gz", component, arch, release, platform)) if compress { err := spitfire.CompressDirectory(pathToUse, outputCompressedFile) @@ -281,12 +277,19 @@ func PackageAndUploadProcess() { fmt.Printf("Build directory compressed to: %s\n", outputCompressedFile) } + // Calculate and display compressed size compressedSize, err := spitfire.GetFileSize(outputCompressedFile) if err != nil { log.Fatalf("Failed to get compressed file size: %v", err) } - fmt.Printf("Compressed file size: %d bytes\n", compressedSize) + fmt.Printf("Compressed file size: %s\n", spitfire.BytesToHumanReadable(compressedSize)) + // Calculate and display compression efficiency + compressionRatio, efficiency := spitfire.CalculateCompressionEfficiency(uncompressedSize, compressedSize) + fmt.Printf("Compression ratio: %.2f:1\n", compressionRatio) + fmt.Printf("Compression efficiency: %.2f%%\n", efficiency) + + // Handle uploading if upload { config, err := spitfire.LoadConfig() if err != nil { diff --git a/spitfire/upload.go b/spitfire/upload.go index 30dc49a..26505b3 100644 --- a/spitfire/upload.go +++ b/spitfire/upload.go @@ -2,8 +2,9 @@ package spitfire import ( "archive/tar" - "crypto/rand" "compress/gzip" + "crypto/rand" + "encoding/hex" "encoding/json" "fmt" "io" @@ -11,7 +12,6 @@ import ( "os/exec" "path/filepath" "strings" - "encoding/hex" ) // Config struct to hold SourceForge configurations @@ -120,70 +120,70 @@ func CompressDirectory(srcDir, dstFile string) error { // Upload the file to SourceForge, ensuring the local directory structure is created and uploaded func Upload(config *Config, buildPath, remoteDir string) error { - // Generate a random hash for the temp directory name - randomHash, err := generateRandomHash(8) // 8 bytes = 16 hex characters - if err != nil { - return fmt.Errorf("failed to generate random hash: %v", err) - } + // Generate a random hash for the temp directory name + randomHash, err := generateRandomHash(8) // 8 bytes = 16 hex characters + if err != nil { + return fmt.Errorf("failed to generate random hash: %v", err) + } - // Create a temporary directory with the random hash appended - tmpDir, err := os.MkdirTemp("", "spitfire-upload-"+randomHash) - if err != nil { - return fmt.Errorf("failed to create temporary directory: %v", err) - } + // Create a temporary directory with the random hash appended + tmpDir, err := os.MkdirTemp("", "spitfire-upload-"+randomHash) + if err != nil { + return fmt.Errorf("failed to create temporary directory: %v", err) + } - // Create the required local directory structure inside the temporary directory - localDir := filepath.Join(tmpDir, remoteDir) - err = os.MkdirAll(localDir, os.ModePerm) - if err != nil { - return fmt.Errorf("failed to create local directory structure: %v", err) - } + // Create the required local directory structure inside the temporary directory + localDir := filepath.Join(tmpDir, remoteDir) + err = os.MkdirAll(localDir, os.ModePerm) + if err != nil { + return fmt.Errorf("failed to create local directory structure: %v", err) + } - // Move the build file to the local directory structure - destinationFile := filepath.Join(localDir, filepath.Base(buildPath)) - err = copyFile(buildPath, destinationFile) - if err != nil { - return fmt.Errorf("failed to copy file to local directory structure: %v", err) - } + // Move the build file to the local directory structure + destinationFile := filepath.Join(localDir, filepath.Base(buildPath)) + err = copyFile(buildPath, destinationFile) + if err != nil { + return fmt.Errorf("failed to copy file to local directory structure: %v", err) + } - // Upload the entire local directory structure to the remote directory - fmt.Printf("Uploading file %s to %s on SourceForge...\n", buildPath, remoteDir) - scpCmd := exec.Command("scp", "-i", config.SFKeyPath, "-r", tmpDir+"/.", fmt.Sprintf("%s@%s:%s", config.SFUser, config.SFHost, "/")) - scpCmd.Stdout = os.Stdout - scpCmd.Stderr = os.Stderr - return scpCmd.Run() + // Upload the entire local directory structure to the remote directory + fmt.Printf("Uploading file %s to %s on SourceForge...\n", buildPath, remoteDir) + scpCmd := exec.Command("scp", "-i", config.SFKeyPath, "-r", tmpDir+"/.", fmt.Sprintf("%s@%s:%s", config.SFUser, config.SFHost, "/")) + scpCmd.Stdout = os.Stdout + scpCmd.Stderr = os.Stderr + return scpCmd.Run() } // Helper function to generate a random hash func generateRandomHash(length int) (string, error) { - bytes := make([]byte, length) - _, err := rand.Read(bytes) - if err != nil { - return "", err - } - return hex.EncodeToString(bytes), nil + bytes := make([]byte, length) + _, err := rand.Read(bytes) + if err != nil { + return "", err + } + return hex.EncodeToString(bytes), nil } // Helper function to copy a file from src to dst func copyFile(src, dst string) error { - sourceFile, err := os.Open(src) - if err != nil { - return err - } - defer sourceFile.Close() + sourceFile, err := os.Open(src) + if err != nil { + return err + } + defer sourceFile.Close() - destFile, err := os.Create(dst) - if err != nil { - return err - } - defer destFile.Close() + destFile, err := os.Create(dst) + if err != nil { + return err + } + defer destFile.Close() - _, err = io.Copy(destFile, sourceFile) - if err != nil { - return err - } + _, err = io.Copy(destFile, sourceFile) + if err != nil { + return err + } - return destFile.Sync() // Ensure all writes to the file are flushed + return destFile.Sync() // Ensure all writes to the file are flushed } // Download the APPINDEX file from SourceForge @@ -244,3 +244,27 @@ func GetFileSize(filePath string) (int64, error) { } return fileInfo.Size(), nil } + +// BytesToHumanReadable converts bytes to a human-readable format (e.g., MiB, GiB) +func BytesToHumanReadable(bytes int64) string { + const unit = 1024 + if bytes < unit { + return fmt.Sprintf("%d B", bytes) + } + div, exp := int64(unit), 0 + for n := bytes / unit; n >= unit; n /= unit { + div *= unit + exp++ + } + return fmt.Sprintf("%.2f %ciB", float64(bytes)/float64(div), "KMGTPE"[exp]) +} + +// CalculateCompressionEfficiency calculates the compression ratio and efficiency percentage +func CalculateCompressionEfficiency(uncompressed, compressed int64) (float64, float64) { + if uncompressed == 0 { + return 0, 0 + } + compressionRatio := float64(uncompressed) / float64(compressed) + efficiency := 100 * (1 - float64(compressed)/float64(uncompressed)) + return compressionRatio, efficiency +}