r11_urpm-repo/repository.go
2025-01-31 23:52:08 +03:00

143 lines
No EOL
4.2 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package main
import (
"crypto/sha256"
"encoding/hex"
"fmt"
"io"
"os"
"path/filepath"
"strings"
"os/exec"
"github.com/spf13/viper"
)
const (
ARCH_X86_64 = "x86_64"
ARCH_RISCV64 = "riscv64"
ARCH_I386 = "i386"
ARCH_AARCH64 = "aarch64"
ARCH_NOARCH = "noarch"
ARCH_SRC = "src"
)
type Repository struct {
BasePath string
}
func NewRepository() *Repository {
return &Repository{
BasePath: viper.GetString("repository.path"),
}
}
// ProcessPackage обрабатывает загруженный пакет
func (r *Repository) ProcessPackage(arch, filename string, body io.Reader) error {
// Преобразуем body к io.ReadSeeker для возможности использовать Seek
readSeeker, ok := body.(io.ReadSeeker)
if !ok {
logger.Errorf("Failed to cast body to io.ReadSeeker for file %s", filename)
return fmt.Errorf("failed to cast body to io.ReadSeeker")
}
// Вычисляем контрольную сумму загруженного файла
hash := sha256.New()
if _, err := io.Copy(hash, readSeeker); err != nil {
logger.Errorf("Error computing checksum for file %s: %v", filename, err)
return err
}
checksum := hex.EncodeToString(hash.Sum(nil))
// Возвращаемся к началу файла для записи
if _, err := readSeeker.Seek(0, 0); err != nil {
logger.Errorf("Error seeking to the beginning of file %s: %v", filename, err)
return err
}
// Проверяем, существует ли файл с такой контрольной суммой
if r.fileExistsWithChecksum(arch, filename, checksum) {
logger.Infof("File %s already exists with the same checksum, skipping upload.", filename)
return nil
}
// Сохраняем пакет
if err := r.SavePackage(arch, filename, readSeeker); err != nil {
logger.Errorf("Error saving package %s: %v", filename, err)
return err
}
return nil
}
func (r *Repository) SavePackage(arch, name string, body io.Reader) error {
logger.Infof("Saving package %s for architecture %s", name, arch)
dir := filepath.Join(r.BasePath, arch)
if err := os.MkdirAll(dir, 0755); err != nil {
logger.Errorf("Failed to create directory %s: %v", dir, err)
return err
}
filePath := filepath.Join(dir, name)
file, err := os.Create(filePath)
if err != nil {
logger.Errorf("Failed to create file %s: %v", filePath, err)
return err
}
defer file.Close()
_, err = io.Copy(file, body)
if err != nil {
logger.Errorf("Failed to copy file content to %s: %v", filePath, err)
return err
}
// Generate metadata
cmd := exec.Command("genhdlist2", "--update", "--root", dir)
logger.Infof("Generating metadata for directory %s", dir)
if err := cmd.Run(); err != nil {
logger.Errorf("Failed to generate metadata: %v", err)
return fmt.Errorf("failed to generate metadata: %w", err)
}
logger.Infof("Package %s saved successfully for architecture %s", name, arch)
return nil
}
func (r *Repository) fileExistsWithChecksum(arch, filename, checksum string) bool {
filePath := filepath.Join(r.BasePath, arch, filename)
file, err := os.Open(filePath)
if err != nil {
if os.IsNotExist(err) {
return false
}
logger.Errorf("Error opening file %s: %v", filePath, err)
return false
}
defer file.Close()
hash := sha256.New()
if _, err := io.Copy(hash, file); err != nil {
logger.Errorf("Error computing checksum for file %s: %v", filePath, err)
return false
}
existingChecksum := hex.EncodeToString(hash.Sum(nil))
return existingChecksum == checksum
}
func (r *Repository) GetArch(arch string) string {
switch strings.ToLower(arch) {
case ARCH_X86_64:
return ARCH_X86_64
case ARCH_RISCV64:
return ARCH_RISCV64
case ARCH_I386:
return ARCH_I386
case ARCH_AARCH64:
return ARCH_AARCH64
case ARCH_NOARCH:
return ARCH_NOARCH
case ARCH_SRC:
return ARCH_SRC
default:
return ""
}
}