package taskservice import ( "errors" "fmt" "io" "mime/multipart" "os" "path" "strconv" "strings" "github.com/cavaliergopher/rpm" "gorm.io/gorm" "code.alt-gnome.ru/aides-infra/aides-repo-api/internal/logger" "code.alt-gnome.ru/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) }