2 Commits

Author SHA1 Message Date
12d83f2015 test: fix decoder and handlers tests 2025-01-14 13:04:10 +03:00
6bc6bfdcd9 refactor: migrate dlcache to struct 2025-01-14 12:59:00 +03:00
6 changed files with 90 additions and 37 deletions

View File

@@ -39,6 +39,7 @@ import (
"golang.org/x/crypto/blake2b" "golang.org/x/crypto/blake2b"
"golang.org/x/crypto/blake2s" "golang.org/x/crypto/blake2s"
"golang.org/x/exp/slices" "golang.org/x/exp/slices"
"plemya-x.ru/alr/internal/config"
"plemya-x.ru/alr/internal/dlcache" "plemya-x.ru/alr/internal/dlcache"
"plemya-x.ru/alr/pkg/loggerctx" "plemya-x.ru/alr/pkg/loggerctx"
) )
@@ -142,6 +143,9 @@ type UpdatingDownloader interface {
// Функция Download загружает файл или каталог с использованием указанных параметров // Функция Download загружает файл или каталог с использованием указанных параметров
func Download(ctx context.Context, opts Options) (err error) { func Download(ctx context.Context, opts Options) (err error) {
log := loggerctx.From(ctx) log := loggerctx.From(ctx)
cfg := config.GetInstance(ctx)
dc := dlcache.New(cfg)
normalized, err := normalizeURL(opts.URL) normalized, err := normalizeURL(opts.URL)
if err != nil { if err != nil {
return err return err
@@ -156,7 +160,7 @@ func Download(ctx context.Context, opts Options) (err error) {
} }
var t Type var t Type
cacheDir, ok := dlcache.Get(ctx, opts.URL) cacheDir, ok := dc.Get(ctx, opts.URL)
if ok { if ok {
var updated bool var updated bool
if d, ok := d.(UpdatingDownloader); ok { if d, ok := d.(UpdatingDownloader); ok {
@@ -203,7 +207,7 @@ func Download(ctx context.Context, opts Options) (err error) {
log.Info("Downloading source").Str("source", opts.Name).Str("downloader", d.Name()).Send() log.Info("Downloading source").Str("source", opts.Name).Str("downloader", d.Name()).Send()
cacheDir, err = dlcache.New(ctx, opts.URL) cacheDir, err = dc.New(ctx, opts.URL)
if err != nil { if err != nil {
return err return err
} }
@@ -299,8 +303,6 @@ func linkDir(src, dest string) error {
return nil return nil
} }
rel, err := filepath.Rel(src, path) rel, err := filepath.Rel(src, path)
if err != nil { if err != nil {
return err return err

View File

@@ -20,29 +20,41 @@ package dlcache
import ( import (
"context" "context"
"crypto/sha1"
"encoding/hex"
"io"
"os" "os"
"path/filepath" "path/filepath"
"plemya-x.ru/alr/internal/config" "plemya-x.ru/alr/internal/config"
) )
// BasePath returns the base path of the download cache type Config interface {
func BasePath(ctx context.Context) string { GetPaths(ctx context.Context) *config.Paths
return filepath.Join(config.GetPaths(ctx).CacheDir, "dl") }
type DownloadCache struct {
cfg Config
}
func New(cfg Config) *DownloadCache {
return &DownloadCache{
cfg,
}
}
func (dc *DownloadCache) BasePath(ctx context.Context) string {
return filepath.Join(
dc.cfg.GetPaths(ctx).CacheDir, "dl",
)
} }
// New creates a new directory with the given ID in the cache. // New creates a new directory with the given ID in the cache.
// If a directory with the same ID already exists, // If a directory with the same ID already exists,
// it will be deleted before creating a new one. // it will be deleted before creating a new one.
func New(ctx context.Context, id string) (string, error) { func (dc *DownloadCache) New(ctx context.Context, id string) (string, error) {
h, err := hashID(id) h, err := hashID(id)
if err != nil { if err != nil {
return "", err return "", err
} }
itemPath := filepath.Join(BasePath(ctx), h) itemPath := filepath.Join(dc.BasePath(ctx), h)
fi, err := os.Stat(itemPath) fi, err := os.Stat(itemPath)
if err == nil || (fi != nil && !fi.IsDir()) { if err == nil || (fi != nil && !fi.IsDir()) {
@@ -65,12 +77,12 @@ func New(ctx context.Context, id string) (string, error) {
// returns the directory and true. If it // returns the directory and true. If it
// does not exist, it returns an empty string // does not exist, it returns an empty string
// and false. // and false.
func Get(ctx context.Context, id string) (string, bool) { func (dc *DownloadCache) Get(ctx context.Context, id string) (string, bool) {
h, err := hashID(id) h, err := hashID(id)
if err != nil { if err != nil {
return "", false return "", false
} }
itemPath := filepath.Join(BasePath(ctx), h) itemPath := filepath.Join(dc.BasePath(ctx), h)
_, err = os.Stat(itemPath) _, err = os.Stat(itemPath)
if err != nil { if err != nil {
@@ -79,15 +91,3 @@ func Get(ctx context.Context, id string) (string, bool) {
return itemPath, true return itemPath, true
} }
// hashID hashes the input ID with SHA1
// and returns the hex string of the hashed
// ID.
func hashID(id string) (string, error) {
h := sha1.New()
_, err := io.WriteString(h, id)
if err != nil {
return "", err
}
return hex.EncodeToString(h.Sum(nil)), nil
}

View File

@@ -39,14 +39,49 @@ func init() {
config.GetPaths(context.Background()).RepoDir = dir config.GetPaths(context.Background()).RepoDir = dir
} }
type TestALRConfig struct {
CacheDir string
}
func (c *TestALRConfig) GetPaths(ctx context.Context) *config.Paths {
return &config.Paths{
CacheDir: c.CacheDir,
}
}
func prepare(t *testing.T) *TestALRConfig {
t.Helper()
dir, err := os.MkdirTemp("/tmp", "alr-dlcache-test.*")
if err != nil {
panic(err)
}
return &TestALRConfig{
CacheDir: dir,
}
}
func cleanup(t *testing.T, cfg *TestALRConfig) {
t.Helper()
os.Remove(cfg.CacheDir)
}
func TestNew(t *testing.T) { func TestNew(t *testing.T) {
cfg := prepare(t)
defer cleanup(t, cfg)
dc := dlcache.New(cfg)
ctx := context.Background()
const id = "https://example.com" const id = "https://example.com"
dir, err := dlcache.New(id) dir, err := dc.New(ctx, id)
if err != nil { if err != nil {
t.Errorf("Expected no error, got %s", err) t.Errorf("Expected no error, got %s", err)
} }
exp := filepath.Join(dlcache.BasePath(), sha1sum(id)) exp := filepath.Join(dc.BasePath(ctx), sha1sum(id))
if dir != exp { if dir != exp {
t.Errorf("Expected %s, got %s", exp, dir) t.Errorf("Expected %s, got %s", exp, dir)
} }
@@ -60,7 +95,7 @@ func TestNew(t *testing.T) {
t.Errorf("Expected cache item to be a directory") t.Errorf("Expected cache item to be a directory")
} }
dir2, ok := dlcache.Get(id) dir2, ok := dc.Get(ctx, id)
if !ok { if !ok {
t.Errorf("Expected Get() to return valid value") t.Errorf("Expected Get() to return valid value")
} }

16
internal/dlcache/utils.go Normal file
View File

@@ -0,0 +1,16 @@
package dlcache
import (
"crypto/sha1"
"encoding/hex"
"io"
)
func hashID(id string) (string, error) {
h := sha1.New()
_, err := io.WriteString(h, id)
if err != nil {
return "", err
}
return hex.EncodeToString(h.Sum(nil)), nil
}

View File

@@ -27,10 +27,10 @@ import (
"strings" "strings"
"testing" "testing"
"plemya-x.ru/alr/internal/shutils/decoder"
"plemya-x.ru/alr/pkg/distro"
"mvdan.cc/sh/v3/interp" "mvdan.cc/sh/v3/interp"
"mvdan.cc/sh/v3/syntax" "mvdan.cc/sh/v3/syntax"
"plemya-x.ru/alr/internal/shutils/decoder"
"plemya-x.ru/alr/pkg/distro"
) )
type BuildVars struct { type BuildVars struct {
@@ -56,7 +56,7 @@ const testScript = `
release=1 release=1
epoch=2 epoch=2
desc="Test package" desc="Test package"
homepage='//https://gitea.plemya-x.ru/xpamych/ALR' homepage='https://gitea.plemya-x.ru/xpamych/ALR'
maintainer='Евгений Храмов <xpamych@yandex.ru>' maintainer='Евгений Храмов <xpamych@yandex.ru>'
architectures=('arm64' 'amd64') architectures=('arm64' 'amd64')
license=('GPL-3.0-or-later') license=('GPL-3.0-or-later')

View File

@@ -23,11 +23,11 @@ import (
"strings" "strings"
"testing" "testing"
"plemya-x.ru/alr/internal/shutils/handlers"
"plemya-x.ru/alr/internal/shutils/decoder"
"plemya-x.ru/alr/pkg/distro"
"mvdan.cc/sh/v3/interp" "mvdan.cc/sh/v3/interp"
"mvdan.cc/sh/v3/syntax" "mvdan.cc/sh/v3/syntax"
"plemya-x.ru/alr/internal/shutils/decoder"
"plemya-x.ru/alr/internal/shutils/handlers"
"plemya-x.ru/alr/pkg/distro"
) )
const testScript = ` const testScript = `
@@ -89,7 +89,7 @@ func TestExecFuncs(t *testing.T) {
t.Fatalf("Expected test() function to exist") t.Fatalf("Expected test() function to exist")
} }
eh := shutils.ExecFuncs{ eh := handlers.ExecFuncs{
"test-cmd": func(hc interp.HandlerContext, name string, args []string) error { "test-cmd": func(hc interp.HandlerContext, name string, args []string) error {
if name != "test-cmd" { if name != "test-cmd" {
t.Errorf("Expected name to be 'test-cmd', got '%s'", name) t.Errorf("Expected name to be 'test-cmd', got '%s'", name)