169 lines
3.4 KiB
Go
169 lines
3.4 KiB
Go
package taskservice
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"io"
|
|
"mime/multipart"
|
|
"os"
|
|
"path"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"github.com/cavaliergopher/rpm"
|
|
"gorm.io/gorm"
|
|
|
|
"code.aides.space/aides-infra/aides-repo-api/internal/logger"
|
|
"code.aides.space/aides-infra/aides-repo-api/internal/models"
|
|
)
|
|
|
|
type TaskUploadInput struct {
|
|
TaskID string
|
|
|
|
Files []*multipart.FileHeader
|
|
}
|
|
|
|
func (s *Service) Upload(input *TaskUploadInput) error {
|
|
log := logger.GetLogger()
|
|
|
|
taskID, err := strconv.Atoi(input.TaskID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
files := input.Files
|
|
|
|
task := models.Task{}
|
|
result := s.db.
|
|
Preload("Repo").
|
|
Where("id = ?", taskID).
|
|
First(&task).
|
|
Where("status = ?", models.StatusPending)
|
|
|
|
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
|
|
return result.Error
|
|
}
|
|
if result.Error != nil {
|
|
return result.Error
|
|
}
|
|
|
|
currentTask := &models.Task{}
|
|
result = s.db.
|
|
Model(&models.GitRepoAltRepoTask{}).
|
|
Select("tasks.*").
|
|
Joins("JOIN tasks ON tasks.id = git_repo_alt_repo_tasks.current_task_id").
|
|
Where(&models.GitRepoAltRepoTask{
|
|
ALTRepoID: task.ALTRepoID,
|
|
RepoID: task.RepoID,
|
|
}).
|
|
Preload("Files").
|
|
Limit(1).
|
|
Find(currentTask)
|
|
if result.Error != nil {
|
|
return result.Error
|
|
}
|
|
|
|
log.Debug("", map[string]interface{}{
|
|
"val": currentTask,
|
|
})
|
|
|
|
localPath := path.Join(input.TaskID)
|
|
taskFolderPath := path.Join(s.config.GetUploadDir(), "tasks", localPath)
|
|
err = os.MkdirAll(taskFolderPath, os.ModePerm)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
shouldCleanTask := true
|
|
defer func() {
|
|
if shouldCleanTask {
|
|
os.RemoveAll(taskFolderPath)
|
|
}
|
|
}()
|
|
|
|
rpmFiles := []models.RPMFile{}
|
|
|
|
for _, fileHeader := range files {
|
|
file, err := fileHeader.Open()
|
|
if err != nil {
|
|
return fmt.Errorf("can't open fileHeader %w", err)
|
|
}
|
|
defer file.Close()
|
|
|
|
if !strings.HasSuffix(fileHeader.Filename, ".rpm") {
|
|
return fmt.Errorf("invalid file type: only .rpm files are allowed")
|
|
}
|
|
|
|
// Полный путь для файла
|
|
filePath := path.Join(taskFolderPath, fileHeader.Filename)
|
|
|
|
// Удаляем файл если такой уже существует
|
|
if _, err := os.Stat(filePath); err == nil {
|
|
err = os.Remove(filePath)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
// Сохранение файла на сервере
|
|
outFile, err := os.Create(filePath)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer outFile.Close()
|
|
|
|
_, err = io.Copy(outFile, file)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
pkg, err := rpm.Open(filePath)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
f := models.RPMFile{
|
|
Filename: fileHeader.Filename,
|
|
Name: pkg.Name(),
|
|
Arch: pkg.Architecture(),
|
|
Version: pkg.Version(),
|
|
Release: pkg.Release(),
|
|
Epoch: pkg.Epoch(),
|
|
Task: task,
|
|
}
|
|
|
|
rpmFiles = append(rpmFiles, f)
|
|
}
|
|
|
|
if currentTask.ID != 0 {
|
|
groupedByName := make(map[string][]*models.RPMFile)
|
|
for _, file := range rpmFiles {
|
|
groupedByName[file.Name] = append(groupedByName[file.Name], &file)
|
|
}
|
|
for _, file := range currentTask.Files {
|
|
groupedByName[file.Name] = append(groupedByName[file.Name], &file)
|
|
}
|
|
|
|
for name, group := range groupedByName {
|
|
if len(group) > 1 {
|
|
result := rpm.Compare(
|
|
&WrapperRpmVersion{group[0]},
|
|
&WrapperRpmVersion{group[1]},
|
|
)
|
|
|
|
if result < 1 {
|
|
return &TooOldError{
|
|
Name: name,
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
result = s.db.Create(&rpmFiles)
|
|
if result.Error != nil {
|
|
return result.Error
|
|
}
|
|
|
|
task.Status = models.StatusCompleted
|
|
shouldCleanTask = false
|
|
|
|
return s.onTaskComplete(&task)
|
|
}
|