diff --git a/coverage-badge.svg b/coverage-badge.svg
index 9b2fae3..82fd6fa 100644
--- a/coverage-badge.svg
+++ b/coverage-badge.svg
@@ -11,7 +11,7 @@
coverage
coverage
- 14.4%
- 14.4%
+ 18.2%
+ 18.2%
diff --git a/internal/dl/dl.go b/internal/dl/dl.go
index 3415e25..4a91fcb 100644
--- a/internal/dl/dl.go
+++ b/internal/dl/dl.go
@@ -42,9 +42,6 @@ import (
"golang.org/x/crypto/blake2b"
"golang.org/x/crypto/blake2s"
"golang.org/x/exp/slices"
-
- "gitea.plemya-x.ru/Plemya-x/ALR/internal/config"
- "gitea.plemya-x.ru/Plemya-x/ALR/internal/dlcache"
)
// Константа для имени файла манифеста кэша
@@ -83,6 +80,11 @@ func (t Type) String() string {
return ""
}
+type DlCache interface {
+ Get(context.Context, string) (string, bool)
+ New(context.Context, string) (string, error)
+}
+
// Структура Options содержит параметры для загрузки файлов и каталогов
type Options struct {
Hash []byte
@@ -94,6 +96,7 @@ type Options struct {
PostprocDisabled bool
Progress io.Writer
LocalDir string
+ DlCache DlCache
}
// Метод для создания нового хеша на основе указанного алгоритма хеширования
@@ -145,9 +148,6 @@ type UpdatingDownloader interface {
// Функция Download загружает файл или каталог с использованием указанных параметров
func Download(ctx context.Context, opts Options) (err error) {
- cfg := config.GetInstance(ctx)
- dc := dlcache.New(cfg)
-
normalized, err := normalizeURL(opts.URL)
if err != nil {
return err
@@ -162,7 +162,7 @@ func Download(ctx context.Context, opts Options) (err error) {
}
var t Type
- cacheDir, ok := dc.Get(ctx, opts.URL)
+ cacheDir, ok := opts.DlCache.Get(ctx, opts.URL)
if ok {
var updated bool
if d, ok := d.(UpdatingDownloader); ok {
@@ -221,7 +221,7 @@ func Download(ctx context.Context, opts Options) (err error) {
slog.Info(gotext.Get("Downloading source"), "source", opts.Name, "downloader", d.Name())
- cacheDir, err = dc.New(ctx, opts.URL)
+ cacheDir, err = opts.DlCache.New(ctx, opts.URL)
if err != nil {
return err
}
diff --git a/internal/dl/dl_test.go b/internal/dl/dl_test.go
new file mode 100644
index 0000000..b5f425a
--- /dev/null
+++ b/internal/dl/dl_test.go
@@ -0,0 +1,139 @@
+// ALR - Any Linux Repository
+// Copyright (C) 2025 Евгений Храмов
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+package dl_test
+
+import (
+ "context"
+ "net/http"
+ "net/http/httptest"
+ "os"
+ "path"
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+
+ "gitea.plemya-x.ru/Plemya-x/ALR/internal/config"
+ "gitea.plemya-x.ru/Plemya-x/ALR/internal/dl"
+ "gitea.plemya-x.ru/Plemya-x/ALR/internal/dlcache"
+)
+
+func TestDownloadFileWithoutCache(t *testing.T) {
+ type testCase struct {
+ name string
+ expectedErr error
+ }
+
+ for _, tc := range []testCase{
+ {
+ name: "simple download",
+ expectedErr: nil,
+ },
+ } {
+ t.Run(tc.name, func(t *testing.T) {
+ server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ switch {
+ case r.URL.Path == "/file":
+ w.WriteHeader(http.StatusOK)
+ w.Write([]byte("Hello, World!"))
+ default:
+ w.WriteHeader(http.StatusNotFound)
+ }
+ }))
+ defer server.Close()
+
+ tmpdir, err := os.MkdirTemp("", "test-download")
+ assert.NoError(t, err)
+ defer os.RemoveAll(tmpdir)
+
+ opts := dl.Options{
+ CacheDisabled: true,
+ URL: server.URL + "/file",
+ Destination: tmpdir,
+ }
+
+ err = dl.Download(context.Background(), opts)
+ assert.ErrorIs(t, err, tc.expectedErr)
+ _, err = os.Stat(path.Join(tmpdir, "file"))
+ assert.NoError(t, err)
+ })
+ }
+}
+
+type TestALRConfig struct{}
+
+func (c *TestALRConfig) GetPaths(ctx context.Context) *config.Paths {
+ return &config.Paths{
+ CacheDir: "/tmp",
+ }
+}
+
+func TestDownloadFileWithCache(t *testing.T) {
+ type testCase struct {
+ name string
+ expectedErr error
+ }
+
+ for _, tc := range []testCase{
+ {
+ name: "simple download",
+ expectedErr: nil,
+ },
+ } {
+ t.Run(tc.name, func(t *testing.T) {
+ called := 0
+
+ server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ switch {
+ case r.URL.Path == "/file":
+ called += 1
+ w.WriteHeader(http.StatusOK)
+ w.Write([]byte("Hello, World!"))
+ default:
+ w.WriteHeader(http.StatusNotFound)
+ }
+ }))
+ defer server.Close()
+
+ tmpdir, err := os.MkdirTemp("", "test-download")
+ assert.NoError(t, err)
+ defer os.RemoveAll(tmpdir)
+
+ cfg := &TestALRConfig{}
+
+ opts := dl.Options{
+ CacheDisabled: false,
+ URL: server.URL + "/file",
+ Destination: tmpdir,
+ DlCache: dlcache.New(cfg),
+ }
+
+ outputFile := path.Join(tmpdir, "file")
+
+ err = dl.Download(context.Background(), opts)
+ assert.ErrorIs(t, err, tc.expectedErr)
+ _, err = os.Stat(outputFile)
+ assert.NoError(t, err)
+
+ err = os.Remove(outputFile)
+ assert.NoError(t, err)
+
+ err = dl.Download(context.Background(), opts)
+ assert.NoError(t, err)
+ assert.Equal(t, 1, called)
+ })
+ }
+}
diff --git a/internal/dl/file.go b/internal/dl/file.go
index 56405dd..521ca50 100644
--- a/internal/dl/file.go
+++ b/internal/dl/file.go
@@ -143,7 +143,7 @@ func (FileDownloader) Download(ctx context.Context, opts Options) (Type, string,
return 0, "", err
}
r.Close()
- out.Close()
+ // out.Close()
// Проверка контрольной суммы
if opts.Hash != nil {
diff --git a/internal/translations/default.pot b/internal/translations/default.pot
index 28de0ef..b0cc59f 100644
--- a/internal/translations/default.pot
+++ b/internal/translations/default.pot
@@ -293,81 +293,81 @@ msgstr ""
msgid "Error while running app"
msgstr ""
-#: pkg/build/build.go:107
+#: pkg/build/build.go:108
msgid "Failed to prompt user to view build script"
msgstr ""
-#: pkg/build/build.go:111
+#: pkg/build/build.go:112
msgid "Building package"
msgstr ""
-#: pkg/build/build.go:155
+#: pkg/build/build.go:156
msgid "Downloading sources"
msgstr ""
-#: pkg/build/build.go:167
+#: pkg/build/build.go:168
msgid "Building package metadata"
msgstr ""
-#: pkg/build/build.go:189
+#: pkg/build/build.go:190
msgid "Compressing package"
msgstr ""
-#: pkg/build/build.go:315
+#: pkg/build/build.go:316
msgid ""
"Your system's CPU architecture doesn't match this package. Do you want to "
"build anyway?"
msgstr ""
-#: pkg/build/build.go:326
+#: pkg/build/build.go:327
msgid "This package is already installed"
msgstr ""
-#: pkg/build/build.go:354
+#: pkg/build/build.go:355
msgid "Installing build dependencies"
msgstr ""
-#: pkg/build/build.go:396
+#: pkg/build/build.go:397
msgid "Installing dependencies"
msgstr ""
-#: pkg/build/build.go:442
+#: pkg/build/build.go:443
msgid "Executing version()"
msgstr ""
-#: pkg/build/build.go:462
+#: pkg/build/build.go:463
msgid "Updating version"
msgstr ""
-#: pkg/build/build.go:467
+#: pkg/build/build.go:468
msgid "Executing prepare()"
msgstr ""
-#: pkg/build/build.go:477
+#: pkg/build/build.go:478
msgid "Executing build()"
msgstr ""
-#: pkg/build/build.go:487
+#: pkg/build/build.go:488
msgid "Executing package()"
msgstr ""
-#: pkg/build/build.go:509
+#: pkg/build/build.go:510
msgid "Executing files()"
msgstr ""
-#: pkg/build/build.go:587
+#: pkg/build/build.go:588
msgid "AutoProv is not implemented for this package format, so it's skipped"
msgstr ""
-#: pkg/build/build.go:598
+#: pkg/build/build.go:599
msgid "AutoReq is not implemented for this package format, so it's skipped"
msgstr ""
-#: pkg/build/build.go:705
+#: pkg/build/build.go:706
msgid "Would you like to remove the build dependencies?"
msgstr ""
-#: pkg/build/build.go:811
+#: pkg/build/build.go:812
msgid "The checksums array must be the same length as sources"
msgstr ""
diff --git a/internal/translations/po/ru/default.po b/internal/translations/po/ru/default.po
index fde74bf..3d5e548 100644
--- a/internal/translations/po/ru/default.po
+++ b/internal/translations/po/ru/default.po
@@ -307,27 +307,27 @@ msgstr ""
msgid "Error while running app"
msgstr "Ошибка при запуске приложения"
-#: pkg/build/build.go:107
+#: pkg/build/build.go:108
msgid "Failed to prompt user to view build script"
msgstr "Не удалось предложить пользователю просмотреть скрипт сборки"
-#: pkg/build/build.go:111
+#: pkg/build/build.go:112
msgid "Building package"
msgstr "Сборка пакета"
-#: pkg/build/build.go:155
+#: pkg/build/build.go:156
msgid "Downloading sources"
msgstr "Скачивание источников"
-#: pkg/build/build.go:167
+#: pkg/build/build.go:168
msgid "Building package metadata"
msgstr "Сборка метаданных пакета"
-#: pkg/build/build.go:189
+#: pkg/build/build.go:190
msgid "Compressing package"
msgstr "Сжатие пакета"
-#: pkg/build/build.go:315
+#: pkg/build/build.go:316
msgid ""
"Your system's CPU architecture doesn't match this package. Do you want to "
"build anyway?"
@@ -335,57 +335,57 @@ msgstr ""
"Архитектура процессора вашей системы не соответствует этому пакету. Вы все "
"равно хотите выполнить сборку?"
-#: pkg/build/build.go:326
+#: pkg/build/build.go:327
msgid "This package is already installed"
msgstr "Этот пакет уже установлен"
-#: pkg/build/build.go:354
+#: pkg/build/build.go:355
msgid "Installing build dependencies"
msgstr "Установка зависимостей сборки"
-#: pkg/build/build.go:396
+#: pkg/build/build.go:397
msgid "Installing dependencies"
msgstr "Установка зависимостей"
-#: pkg/build/build.go:442
+#: pkg/build/build.go:443
msgid "Executing version()"
msgstr "Исполнение версия()"
-#: pkg/build/build.go:462
+#: pkg/build/build.go:463
msgid "Updating version"
msgstr "Обновление версии"
-#: pkg/build/build.go:467
+#: pkg/build/build.go:468
msgid "Executing prepare()"
msgstr "Исполнение prepare()"
-#: pkg/build/build.go:477
+#: pkg/build/build.go:478
msgid "Executing build()"
msgstr "Исполнение build()"
-#: pkg/build/build.go:487
+#: pkg/build/build.go:488
msgid "Executing package()"
msgstr "Исполнение package()"
-#: pkg/build/build.go:509
+#: pkg/build/build.go:510
msgid "Executing files()"
msgstr "Исполнение files()"
-#: pkg/build/build.go:587
+#: pkg/build/build.go:588
msgid "AutoProv is not implemented for this package format, so it's skipped"
msgstr ""
"AutoProv не реализовано для этого формата пакета, поэтому будет пропущено"
-#: pkg/build/build.go:598
+#: pkg/build/build.go:599
msgid "AutoReq is not implemented for this package format, so it's skipped"
msgstr ""
"AutoReq не реализовано для этого формата пакета, поэтому будет пропущено"
-#: pkg/build/build.go:705
+#: pkg/build/build.go:706
msgid "Would you like to remove the build dependencies?"
msgstr "Хотели бы вы удалить зависимости сборки?"
-#: pkg/build/build.go:811
+#: pkg/build/build.go:812
msgid "The checksums array must be the same length as sources"
msgstr "Массив контрольных сумм должен быть той же длины, что и источники"
diff --git a/pkg/build/build.go b/pkg/build/build.go
index 9a30e1a..62be0a0 100644
--- a/pkg/build/build.go
+++ b/pkg/build/build.go
@@ -54,6 +54,7 @@ import (
"gitea.plemya-x.ru/Plemya-x/ALR/internal/cpu"
"gitea.plemya-x.ru/Plemya-x/ALR/internal/db"
"gitea.plemya-x.ru/Plemya-x/ALR/internal/dl"
+ "gitea.plemya-x.ru/Plemya-x/ALR/internal/dlcache"
"gitea.plemya-x.ru/Plemya-x/ALR/internal/overrides"
"gitea.plemya-x.ru/Plemya-x/ALR/internal/shutils/decoder"
"gitea.plemya-x.ru/Plemya-x/ALR/internal/shutils/handlers"
@@ -842,6 +843,9 @@ func getSources(ctx context.Context, dirs types.Directories, bv *types.BuildVars
}
}
+ cfg := config.GetInstance(ctx)
+ opts.DlCache = dlcache.New(cfg)
+
err := dl.Download(ctx, opts)
if err != nil {
return err