Initial DDC release
This commit is contained in:
commit
434f6441da
57 files changed
+4606
No files matched your search
Executable
+102
@@ -0,0 +1,102 @@
|
||||
package jobs
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"ddc/internal/diskspace"
|
||||
"ddc/internal/extract"
|
||||
"ddc/internal/files"
|
||||
)
|
||||
|
||||
const maxArchiveEntries = 100000
|
||||
|
||||
var errNotArchive = errors.New("selected file is not a supported archive")
|
||||
|
||||
func (manager *Manager) download(job *Job) {
|
||||
defer job.workers.Done()
|
||||
|
||||
if !manager.slots.acquire(job.jobContext, manager.concurrencyLimit) {
|
||||
return
|
||||
}
|
||||
defer manager.slots.release()
|
||||
|
||||
job.setStatus(StatusDownloading, "")
|
||||
filePath, err := manager.downloader.Download(job.jobContext, job.sourceURL, job.directory, manager.reservedBytes(), job)
|
||||
if err != nil {
|
||||
manager.finishWithError(job, StatusFailed, "", err)
|
||||
return
|
||||
}
|
||||
job.SetFileName(filepath.Base(filePath))
|
||||
|
||||
if job.autoExtract && extract.IsArchive(filePath) {
|
||||
job.setStatus(StatusExtracting, "")
|
||||
destination, err := manager.extractArchive(job, filePath)
|
||||
if err != nil {
|
||||
manager.finishWithError(job, StatusReady, "Extraction failed: ", err)
|
||||
return
|
||||
}
|
||||
job.SetFileName(filepath.Base(destination))
|
||||
}
|
||||
|
||||
job.setStatus(StatusReady, "")
|
||||
}
|
||||
|
||||
func (manager *Manager) Extract(id, relativePath string) error {
|
||||
job, err := manager.lookup(id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
archivePath, err := files.ResolveInside(job.directory, relativePath)
|
||||
if err != nil {
|
||||
return invalid(err)
|
||||
}
|
||||
info, err := os.Stat(archivePath)
|
||||
if err != nil || !info.Mode().IsRegular() || !extract.IsArchive(archivePath) {
|
||||
return invalid(errNotArchive)
|
||||
}
|
||||
|
||||
if !job.begin(StatusReady, StatusExtracting) {
|
||||
return ErrJobBusy
|
||||
}
|
||||
go func() {
|
||||
defer job.workers.Done()
|
||||
if _, err := manager.extractArchive(job, archivePath); err != nil {
|
||||
manager.finishWithError(job, StatusReady, "Extraction failed: ", err)
|
||||
return
|
||||
}
|
||||
job.setStatus(StatusReady, "")
|
||||
}()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (manager *Manager) extractArchive(job *Job, archivePath string) (string, error) {
|
||||
available, err := diskspace.Available(job.directory)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
limit := available - manager.reservedBytes()
|
||||
if limit <= 0 {
|
||||
return "", diskspace.ErrInsufficientSpace
|
||||
}
|
||||
|
||||
directoryName := extract.DirectoryName(filepath.Base(archivePath))
|
||||
destination := files.UniquePath(filepath.Join(filepath.Dir(archivePath), directoryName))
|
||||
limits := extract.Limits{MaxBytes: limit, MaxEntries: maxArchiveEntries}
|
||||
|
||||
job.resetProgress()
|
||||
if err := extract.Archive(job.jobContext, archivePath, destination, limits, job); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return destination, os.Remove(archivePath)
|
||||
}
|
||||
|
||||
func (manager *Manager) finishWithError(job *Job, status Status, prefix string, err error) {
|
||||
if job.jobContext.Err() != nil {
|
||||
job.setStatus(StatusCancelled, "")
|
||||
return
|
||||
}
|
||||
job.setStatus(status, prefix+err.Error())
|
||||
}
|
||||
Reference in new issue
Block a user