192 lines
4.6 KiB
Go
192 lines
4.6 KiB
Go
package archiver
|
|
|
|
import (
|
|
"fmt"
|
|
"sync"
|
|
|
|
"zipprine/internal/models"
|
|
)
|
|
|
|
// BatchCompressConfig holds configuration for batch compression operations
|
|
type BatchCompressConfig struct {
|
|
Configs []*models.CompressConfig
|
|
Parallel bool
|
|
MaxWorkers int
|
|
OnProgress func(index int, total int, filename string)
|
|
OnError func(index int, filename string, err error)
|
|
OnComplete func(index int, filename string)
|
|
}
|
|
|
|
// BatchCompress compresses multiple sources in batch
|
|
func BatchCompress(batchConfig *BatchCompressConfig) []error {
|
|
if batchConfig.MaxWorkers <= 0 {
|
|
batchConfig.MaxWorkers = 4
|
|
}
|
|
|
|
errors := make([]error, len(batchConfig.Configs))
|
|
|
|
if !batchConfig.Parallel {
|
|
// Sequential processing
|
|
for i, config := range batchConfig.Configs {
|
|
if batchConfig.OnProgress != nil {
|
|
batchConfig.OnProgress(i+1, len(batchConfig.Configs), config.OutputPath)
|
|
}
|
|
|
|
err := Compress(config)
|
|
errors[i] = err
|
|
|
|
if err != nil && batchConfig.OnError != nil {
|
|
batchConfig.OnError(i, config.OutputPath, err)
|
|
} else if batchConfig.OnComplete != nil {
|
|
batchConfig.OnComplete(i, config.OutputPath)
|
|
}
|
|
}
|
|
return errors
|
|
}
|
|
|
|
// Parallel processing with worker pool
|
|
var wg sync.WaitGroup
|
|
jobs := make(chan int, len(batchConfig.Configs))
|
|
|
|
// Start workers
|
|
for w := 0; w < batchConfig.MaxWorkers; w++ {
|
|
wg.Add(1)
|
|
go func() {
|
|
defer wg.Done()
|
|
for i := range jobs {
|
|
config := batchConfig.Configs[i]
|
|
|
|
if batchConfig.OnProgress != nil {
|
|
batchConfig.OnProgress(i+1, len(batchConfig.Configs), config.OutputPath)
|
|
}
|
|
|
|
err := Compress(config)
|
|
errors[i] = err
|
|
|
|
if err != nil && batchConfig.OnError != nil {
|
|
batchConfig.OnError(i, config.OutputPath, err)
|
|
} else if batchConfig.OnComplete != nil {
|
|
batchConfig.OnComplete(i, config.OutputPath)
|
|
}
|
|
}
|
|
}()
|
|
}
|
|
|
|
// Send jobs
|
|
for i := range batchConfig.Configs {
|
|
jobs <- i
|
|
}
|
|
close(jobs)
|
|
|
|
wg.Wait()
|
|
return errors
|
|
}
|
|
|
|
// BatchExtractConfig holds configuration for batch extraction operations
|
|
type BatchExtractConfig struct {
|
|
Configs []*models.ExtractConfig
|
|
Parallel bool
|
|
MaxWorkers int
|
|
OnProgress func(index int, total int, filename string)
|
|
OnError func(index int, filename string, err error)
|
|
OnComplete func(index int, filename string)
|
|
}
|
|
|
|
// BatchExtract extracts multiple archives in batch
|
|
func BatchExtract(batchConfig *BatchExtractConfig) []error {
|
|
if batchConfig.MaxWorkers <= 0 {
|
|
batchConfig.MaxWorkers = 4
|
|
}
|
|
|
|
errors := make([]error, len(batchConfig.Configs))
|
|
|
|
if !batchConfig.Parallel {
|
|
// Sequential processing
|
|
for i, config := range batchConfig.Configs {
|
|
if batchConfig.OnProgress != nil {
|
|
batchConfig.OnProgress(i+1, len(batchConfig.Configs), config.ArchivePath)
|
|
}
|
|
|
|
err := Extract(config)
|
|
errors[i] = err
|
|
|
|
if err != nil && batchConfig.OnError != nil {
|
|
batchConfig.OnError(i, config.ArchivePath, err)
|
|
} else if batchConfig.OnComplete != nil {
|
|
batchConfig.OnComplete(i, config.ArchivePath)
|
|
}
|
|
}
|
|
return errors
|
|
}
|
|
|
|
// Parallel processing with worker pool
|
|
var wg sync.WaitGroup
|
|
jobs := make(chan int, len(batchConfig.Configs))
|
|
|
|
// Start workers
|
|
for w := 0; w < batchConfig.MaxWorkers; w++ {
|
|
wg.Add(1)
|
|
go func() {
|
|
defer wg.Done()
|
|
for i := range jobs {
|
|
config := batchConfig.Configs[i]
|
|
|
|
if batchConfig.OnProgress != nil {
|
|
batchConfig.OnProgress(i+1, len(batchConfig.Configs), config.ArchivePath)
|
|
}
|
|
|
|
err := Extract(config)
|
|
errors[i] = err
|
|
|
|
if err != nil && batchConfig.OnError != nil {
|
|
batchConfig.OnError(i, config.ArchivePath, err)
|
|
} else if batchConfig.OnComplete != nil {
|
|
batchConfig.OnComplete(i, config.ArchivePath)
|
|
}
|
|
}
|
|
}()
|
|
}
|
|
|
|
// Send jobs
|
|
for i := range batchConfig.Configs {
|
|
jobs <- i
|
|
}
|
|
close(jobs)
|
|
|
|
wg.Wait()
|
|
return errors
|
|
}
|
|
|
|
// ConvertArchive converts an archive from one format to another
|
|
func ConvertArchive(sourcePath, destPath string, sourceType, destType models.ArchiveType) error {
|
|
// Create temporary directory for extraction
|
|
tmpDir := destPath + ".tmp"
|
|
|
|
// Extract source archive
|
|
extractConfig := &models.ExtractConfig{
|
|
ArchivePath: sourcePath,
|
|
DestPath: tmpDir,
|
|
ArchiveType: sourceType,
|
|
OverwriteAll: true,
|
|
PreservePerms: true,
|
|
}
|
|
|
|
if err := Extract(extractConfig); err != nil {
|
|
return fmt.Errorf("failed to extract source archive: %w", err)
|
|
}
|
|
|
|
// Compress to destination format
|
|
compressConfig := &models.CompressConfig{
|
|
SourcePath: tmpDir,
|
|
OutputPath: destPath,
|
|
ArchiveType: destType,
|
|
CompressionLevel: 5,
|
|
}
|
|
|
|
if err := Compress(compressConfig); err != nil {
|
|
return fmt.Errorf("failed to create destination archive: %w", err)
|
|
}
|
|
|
|
return nil
|
|
}
|