aides-repo-api/internal/services/reposervice/service.go

229 lines
4 KiB
Go

package reposervice
import (
"os"
"path"
"strconv"
"gorm.io/gorm"
"code.aides.space/aides-infra/aides-repo-api/internal/logger"
"code.aides.space/aides-infra/aides-repo-api/internal/models"
)
type Config interface {
GetUploadDir() string
}
type Service struct {
db *gorm.DB
config Config
}
func New(db *gorm.DB, cfg Config) *Service {
return &Service{
db: db,
config: cfg,
}
}
func (s *Service) futureRepoPathPrefix() string {
return path.Join(
s.config.GetUploadDir(),
".future_repo",
)
}
func (s *Service) currentRepoPathPrefix() string {
return path.Join(
s.config.GetUploadDir(),
"repo",
)
}
func (s *Service) oldRepoPathPrefix() string {
return path.Join(
s.config.GetUploadDir(),
".old_repo",
)
}
func (s *Service) prepareForUpdate() error {
err := os.MkdirAll(s.futureRepoPathPrefix(), os.ModePerm)
if err != nil {
return err
}
err = os.MkdirAll(s.oldRepoPathPrefix(), os.ModePerm)
if err != nil {
return err
}
err = os.MkdirAll(s.currentRepoPathPrefix(), os.ModePerm)
if err != nil {
return err
}
return nil
}
func (s *Service) cleanUpAfterUpdate() {
os.RemoveAll(s.futureRepoPathPrefix())
os.RemoveAll(s.oldRepoPathPrefix())
}
func (s *Service) Update(force bool) error {
const REPO_NAME = "aides"
const DISTRO_ID = "altlinux"
architectures := []string{
"x86_64",
"noarch",
}
repos := []string{
"Sisyphus",
}
log := logger.GetLogger()
log.Info("Start repo update")
preparedForUpdate := false
for _, r := range repos {
var tasks []models.Task
altRepo := models.ALTRepo{
Name: r,
}
if err := s.db.
Where(&altRepo).
First(&altRepo).Error; err != nil {
return err
}
var exists bool
if err := s.db.
Model(&models.GitRepoAltRepoTask{}).
Select("1").
Where("alt_repo_id = ?", altRepo.ID).
Where("last_task_id != current_task_id OR current_task_id IS NULL").
Limit(1).
Scan(&exists).Error; err != nil {
return err
}
if !force && !exists {
log.Info(
"No updates found for ALTRepo, skipping.",
map[string]interface{}{
"repo": altRepo.Name,
})
continue
}
if !preparedForUpdate {
if err := s.prepareForUpdate(); err != nil {
return err
}
defer s.cleanUpAfterUpdate()
}
preparedForUpdate = true
s.db.
Model(&models.GitRepoAltRepoTask{}).
Select("tasks.*").
Joins("JOIN tasks ON tasks.id = git_repo_alt_repo_tasks.last_task_id").
Where(&models.GitRepoAltRepoTask{
ALTRepoID: altRepo.ID,
}).
Preload("Files").
Find(&tasks)
futureRepoPath := path.Join(
s.futureRepoPathPrefix(),
DISTRO_ID,
altRepo.Name,
)
err := os.MkdirAll(
futureRepoPath,
os.ModePerm,
)
if err != nil {
return err
}
for _, arch := range architectures {
err = createRepoDirs(futureRepoPath, REPO_NAME, arch)
if err != nil {
return err
}
}
for _, el := range tasks {
for _, fileInfo := range el.Files {
localFilePath := path.Join(
strconv.FormatUint(uint64(el.ID), 10), fileInfo.Filename,
)
symLink := path.Join(
futureRepoPath,
fileInfo.Arch,
"RPMS.aides",
fileInfo.Filename,
)
targetPath := path.Join("../../../../../tasks/", localFilePath)
err := createSymlink(targetPath, symLink)
if err != nil {
return err
}
}
}
for _, arch := range architectures {
err = runGenbasedir(futureRepoPath, arch, REPO_NAME)
if err != nil {
return err
}
}
s.db.
Model(&models.GitRepoAltRepoTask{}).
Where(&models.GitRepoAltRepoTask{
ALTRepoID: altRepo.ID,
}).
Update(
"current_task_id", gorm.Expr("last_task_id"),
)
currentRepoPath := path.Join(
s.currentRepoPathPrefix(),
DISTRO_ID,
altRepo.Name,
)
oldRepoPath := path.Join(
s.oldRepoPathPrefix(),
DISTRO_ID,
altRepo.Name,
)
if err := renameIfExists(
currentRepoPath,
oldRepoPath,
); err != nil {
return err
}
if err := renameIfExists(
futureRepoPath,
currentRepoPath,
); err != nil {
return err
}
}
log.Info("Successful repo update")
return nil
}