refactor: migrate dlcache to struct

This commit is contained in:
Maxim Slipenko 2025-01-14 12:59:00 +03:00
parent eeb25c239b
commit 6bc6bfdcd9
4 changed files with 83 additions and 30 deletions

@ -14,7 +14,7 @@
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
*/
// Пакет dl содержит абстракции для загрузки файлов и каталогов
// из различных источников.
@ -39,6 +39,7 @@ import (
"golang.org/x/crypto/blake2b"
"golang.org/x/crypto/blake2s"
"golang.org/x/exp/slices"
"plemya-x.ru/alr/internal/config"
"plemya-x.ru/alr/internal/dlcache"
"plemya-x.ru/alr/pkg/loggerctx"
)
@ -142,6 +143,9 @@ type UpdatingDownloader interface {
// Функция Download загружает файл или каталог с использованием указанных параметров
func Download(ctx context.Context, opts Options) (err error) {
log := loggerctx.From(ctx)
cfg := config.GetInstance(ctx)
dc := dlcache.New(cfg)
normalized, err := normalizeURL(opts.URL)
if err != nil {
return err
@ -156,7 +160,7 @@ func Download(ctx context.Context, opts Options) (err error) {
}
var t Type
cacheDir, ok := dlcache.Get(ctx, opts.URL)
cacheDir, ok := dc.Get(ctx, opts.URL)
if ok {
var updated bool
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()
cacheDir, err = dlcache.New(ctx, opts.URL)
cacheDir, err = dc.New(ctx, opts.URL)
if err != nil {
return err
}
@ -299,8 +303,6 @@ func linkDir(src, dest string) error {
return nil
}
rel, err := filepath.Rel(src, path)
if err != nil {
return err

@ -20,29 +20,41 @@ package dlcache
import (
"context"
"crypto/sha1"
"encoding/hex"
"io"
"os"
"path/filepath"
"plemya-x.ru/alr/internal/config"
)
// BasePath returns the base path of the download cache
func BasePath(ctx context.Context) string {
return filepath.Join(config.GetPaths(ctx).CacheDir, "dl")
type Config interface {
GetPaths(ctx context.Context) *config.Paths
}
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.
// If a directory with the same ID already exists,
// 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)
if err != nil {
return "", err
}
itemPath := filepath.Join(BasePath(ctx), h)
itemPath := filepath.Join(dc.BasePath(ctx), h)
fi, err := os.Stat(itemPath)
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
// does not exist, it returns an empty string
// 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)
if err != nil {
return "", false
}
itemPath := filepath.Join(BasePath(ctx), h)
itemPath := filepath.Join(dc.BasePath(ctx), h)
_, err = os.Stat(itemPath)
if err != nil {
@ -79,15 +91,3 @@ func Get(ctx context.Context, id string) (string, bool) {
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
}

@ -39,14 +39,49 @@ func init() {
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) {
cfg := prepare(t)
defer cleanup(t, cfg)
dc := dlcache.New(cfg)
ctx := context.Background()
const id = "https://example.com"
dir, err := dlcache.New(id)
dir, err := dc.New(ctx, id)
if err != nil {
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 {
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")
}
dir2, ok := dlcache.Get(id)
dir2, ok := dc.Get(ctx, id)
if !ok {
t.Errorf("Expected Get() to return valid value")
}

16
internal/dlcache/utils.go Normal 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
}