package spm import ( "archive/tar" "compress/gzip" "io" "os" "path/filepath" ) func DecompressToTemp(filePath string) (string, error) { UpdateProgress(0, "Decompressing package") tempDir, err := os.MkdirTemp("", "spm_decompress") if err != nil { return "", err } file, err := os.Open(filePath) if err != nil { return "", err } defer file.Close() gzr, err := gzip.NewReader(file) if err != nil { return "", err } defer gzr.Close() tarReader := tar.NewReader(gzr) var totalFiles, processedFiles int // Count total files for { _, err := tarReader.Next() if err == io.EOF { break } if err != nil { return "", err } totalFiles++ } file.Seek(0, io.SeekStart) gzr.Reset(file) tarReader = tar.NewReader(gzr) for { header, err := tarReader.Next() if err == io.EOF { break } if err != nil { return "", err } targetPath := filepath.Join(tempDir, header.Name) switch header.Typeflag { case tar.TypeDir: if err := os.MkdirAll(targetPath, os.FileMode(header.Mode)); err != nil { return "", err } case tar.TypeReg: outFile, err := os.Create(targetPath) if err != nil { return "", err } if _, err := io.Copy(outFile, tarReader); err != nil { return "", err } outFile.Close() } processedFiles++ UpdateProgress(int(float64(processedFiles)/float64(totalFiles)*100), "Decompressing package") } UpdateProgress(100, "Package decompressed") return tempDir, nil } func MoveFilesToInstallDir(tempDir, installDir string) error { // Count total files to copy var totalFiles, copiedFiles int err := filepath.Walk(tempDir, func(path string, info os.FileInfo, err error) error { if err != nil { return err } if !info.IsDir() { totalFiles++ } return nil }) if err != nil { return err } // Copy files and track progress err = filepath.Walk(tempDir, func(path string, info os.FileInfo, err error) error { if err != nil { return err } relPath, err := filepath.Rel(tempDir, path) if err != nil { return err } targetPath := filepath.Join(installDir, relPath) if info.IsDir() { // Create directories in the install directory if err := os.MkdirAll(targetPath, os.ModePerm); err != nil { return err } } else { // Copy files to the install directory if err := copyFile(path, targetPath); err != nil { return err } copiedFiles++ UpdateProgress(int(float64(copiedFiles)/float64(totalFiles)*100), "Copying files to install directory") } return nil }) if err != nil { return err } // Clean up temporary directory UpdateProgress(100, "Cleaning up temporary files") return os.RemoveAll(tempDir) } // copyFile copies the contents of the source file to the destination file. func copyFile(src, dst string) error { sourceFile, err := os.Open(src) if err != nil { return err } defer sourceFile.Close() // Create the destination file destinationFile, err := os.Create(dst) if err != nil { return err } defer destinationFile.Close() // Copy the file content if _, err := io.Copy(destinationFile, sourceFile); err != nil { return err } // Preserve file permissions info, err := sourceFile.Stat() if err != nil { return err } return os.Chmod(dst, info.Mode()) }