83 lines
2.2 KiB
Go
83 lines
2.2 KiB
Go
package core
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"log"
|
|
"path/filepath"
|
|
|
|
"github.com/syonad/clonepack/internal/clone/rpm"
|
|
"github.com/syonad/clonepack/internal/store"
|
|
)
|
|
|
|
var ErrCloneAlreadyRunning = errors.New("a clone job is already running for this repo")
|
|
|
|
type CloneService struct {
|
|
repoStore store.RepoStore
|
|
jobStore store.CloneJobStore
|
|
dataDir string
|
|
}
|
|
|
|
func NewCloneService(repoStore store.RepoStore, jobStore store.CloneJobStore, dataDir string) *CloneService {
|
|
return &CloneService{repoStore: repoStore, jobStore: jobStore, dataDir: dataDir}
|
|
}
|
|
|
|
func (s *CloneService) StartClone(ctx context.Context, repoID int64) (int64, error) {
|
|
repo, err := s.repoStore.GetRepo(ctx, repoID)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
if repo.Type != "rpm" {
|
|
return 0, fmt.Errorf("clone is only supported for rpm repositories")
|
|
}
|
|
|
|
running, err := s.jobStore.HasRunningCloneJob(ctx, repoID)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
if running {
|
|
return 0, ErrCloneAlreadyRunning
|
|
}
|
|
|
|
jobID, err := s.jobStore.CreateCloneJob(ctx, repoID)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
|
|
go s.runClone(repoID, jobID, repo.SourceURL, repo.Type)
|
|
return jobID, nil
|
|
}
|
|
|
|
func (s *CloneService) GetLatestCloneJob(ctx context.Context, repoID int64) (*store.CloneJob, error) {
|
|
return s.jobStore.GetLatestCloneJob(ctx, repoID)
|
|
}
|
|
|
|
func (s *CloneService) runClone(repoID, jobID int64, sourceURL, repoType string) {
|
|
ctx := context.Background()
|
|
|
|
if err := s.jobStore.MarkCloneJobStarted(ctx, jobID); err != nil {
|
|
log.Printf("clone job %d: failed to mark started: %v", jobID, err)
|
|
return
|
|
}
|
|
|
|
destDir := filepath.Join(s.dataDir, "repos", fmt.Sprintf("%d", repoID), repoType)
|
|
cloner := rpm.New(sourceURL, destDir)
|
|
cloner.OnProgress = func(p rpm.Progress) {
|
|
log.Printf("clone job %d: %s (%d bytes)", jobID, p.File, p.BytesDone)
|
|
}
|
|
|
|
if err := cloner.Clone(ctx); err != nil {
|
|
errMsg := err.Error()
|
|
_ = s.jobStore.MarkCloneJobFinished(ctx, jobID, store.CloneJobFailed, &errMsg)
|
|
log.Printf("clone job %d: failed: %v", jobID, err)
|
|
return
|
|
}
|
|
|
|
if err := rpm.RegenerateMetadata(destDir); err != nil {
|
|
log.Printf("clone job %d: metadata regeneration failed: %v", jobID, err)
|
|
}
|
|
|
|
_ = s.jobStore.MarkCloneJobFinished(ctx, jobID, store.CloneJobCompleted, nil)
|
|
log.Printf("clone job %d: completed", jobID)
|
|
}
|