mirror of
https://github.com/aptly-dev/aptly.git
synced 2026-06-07 05:42:42 +00:00
Rework HTTP downloader retry logic
Apply retries as global, config-level option `downloadRetries` so that it can be applied to any aptly command which downloads objects. Unwrap `errors.Wrap` which is used in downloader. Unwrap `*url.Error` which should be the actual error returned from the HTTP client, catch more cases, be more specific around failures.
This commit is contained in:
committed by
Andrey Smirnov
parent
2e7f624b34
commit
f0a370db24
+1
-1
@@ -127,7 +127,7 @@ type Downloader interface {
|
|||||||
// Download starts new download task
|
// Download starts new download task
|
||||||
Download(ctx context.Context, url string, destination string) error
|
Download(ctx context.Context, url string, destination string) error
|
||||||
// DownloadWithChecksum starts new download task with checksum verification
|
// DownloadWithChecksum starts new download task with checksum verification
|
||||||
DownloadWithChecksum(ctx context.Context, url string, destination string, expected *utils.ChecksumInfo, ignoreMismatch bool, maxTries int) error
|
DownloadWithChecksum(ctx context.Context, url string, destination string, expected *utils.ChecksumInfo, ignoreMismatch bool) error
|
||||||
// GetProgress returns Progress object
|
// GetProgress returns Progress object
|
||||||
GetProgress() Progress
|
GetProgress() Progress
|
||||||
// GetLength returns size by heading object with url
|
// GetLength returns size by heading object with url
|
||||||
|
|||||||
@@ -41,7 +41,6 @@ func aptlyMirrorUpdate(cmd *commander.Command, args []string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ignoreMismatch := context.Flags().Lookup("ignore-checksums").Value.Get().(bool)
|
ignoreMismatch := context.Flags().Lookup("ignore-checksums").Value.Get().(bool)
|
||||||
maxTries := context.Flags().Lookup("max-tries").Value.Get().(int)
|
|
||||||
|
|
||||||
verifier, err := getVerifier(context.Flags())
|
verifier, err := getVerifier(context.Flags())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -54,7 +53,7 @@ func aptlyMirrorUpdate(cmd *commander.Command, args []string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
context.Progress().Printf("Downloading & parsing package files...\n")
|
context.Progress().Printf("Downloading & parsing package files...\n")
|
||||||
err = repo.DownloadPackageIndexes(context.Progress(), context.Downloader(), verifier, context.CollectionFactory(), ignoreMismatch, maxTries)
|
err = repo.DownloadPackageIndexes(context.Progress(), context.Downloader(), verifier, context.CollectionFactory(), ignoreMismatch)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to update: %s", err)
|
return fmt.Errorf("unable to update: %s", err)
|
||||||
}
|
}
|
||||||
@@ -173,8 +172,7 @@ func aptlyMirrorUpdate(cmd *commander.Command, args []string) error {
|
|||||||
repo.PackageURL(task.File.DownloadURL()).String(),
|
repo.PackageURL(task.File.DownloadURL()).String(),
|
||||||
task.TempDownPath,
|
task.TempDownPath,
|
||||||
&task.File.Checksums,
|
&task.File.Checksums,
|
||||||
ignoreMismatch,
|
ignoreMismatch)
|
||||||
maxTries)
|
|
||||||
if e != nil {
|
if e != nil {
|
||||||
pushError(e)
|
pushError(e)
|
||||||
continue
|
continue
|
||||||
|
|||||||
+9
-1
@@ -213,7 +213,15 @@ func (context *AptlyContext) Downloader() aptly.Downloader {
|
|||||||
if downloadLimit == 0 {
|
if downloadLimit == 0 {
|
||||||
downloadLimit = context.config().DownloadLimit
|
downloadLimit = context.config().DownloadLimit
|
||||||
}
|
}
|
||||||
context.downloader = http.NewDownloader(downloadLimit*1024, context._progress())
|
maxTries := context.config().DownloadRetries + 1
|
||||||
|
maxTriesFlag := context.flags.Lookup("max-tries")
|
||||||
|
if maxTriesFlag != nil {
|
||||||
|
maxTriesFlagValue := maxTriesFlag.Value.Get().(int)
|
||||||
|
if maxTriesFlagValue > maxTries {
|
||||||
|
maxTries = maxTriesFlagValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
context.downloader = http.NewDownloader(downloadLimit*1024, maxTries, context._progress())
|
||||||
}
|
}
|
||||||
|
|
||||||
return context.downloader
|
return context.downloader
|
||||||
|
|||||||
+2
-2
@@ -423,7 +423,7 @@ ok:
|
|||||||
|
|
||||||
// DownloadPackageIndexes downloads & parses package index files
|
// DownloadPackageIndexes downloads & parses package index files
|
||||||
func (repo *RemoteRepo) DownloadPackageIndexes(progress aptly.Progress, d aptly.Downloader, verifier pgp.Verifier, collectionFactory *CollectionFactory,
|
func (repo *RemoteRepo) DownloadPackageIndexes(progress aptly.Progress, d aptly.Downloader, verifier pgp.Verifier, collectionFactory *CollectionFactory,
|
||||||
ignoreMismatch bool, maxTries int) error {
|
ignoreMismatch bool) error {
|
||||||
if repo.packageList != nil {
|
if repo.packageList != nil {
|
||||||
panic("packageList != nil")
|
panic("packageList != nil")
|
||||||
}
|
}
|
||||||
@@ -456,7 +456,7 @@ func (repo *RemoteRepo) DownloadPackageIndexes(progress aptly.Progress, d aptly.
|
|||||||
|
|
||||||
for _, info := range packagesPaths {
|
for _, info := range packagesPaths {
|
||||||
path, kind, component, architecture := info[0], info[1], info[2], info[3]
|
path, kind, component, architecture := info[0], info[1], info[2], info[3]
|
||||||
packagesReader, packagesFile, err := http.DownloadTryCompression(gocontext.TODO(), d, repo.IndexesRootURL(), path, repo.ReleaseFiles, ignoreMismatch, maxTries)
|
packagesReader, packagesFile, err := http.DownloadTryCompression(gocontext.TODO(), d, repo.IndexesRootURL(), path, repo.ReleaseFiles, ignoreMismatch)
|
||||||
|
|
||||||
isInstaller := kind == PackageTypeInstaller
|
isInstaller := kind == PackageTypeInstaller
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
+13
-13
@@ -276,7 +276,7 @@ func (s *RemoteRepoSuite) TestDownload(c *C) {
|
|||||||
s.downloader.ExpectError("http://mirror.yandex.ru/debian/dists/squeeze/main/binary-i386/Packages.gz", &http.Error{Code: 404})
|
s.downloader.ExpectError("http://mirror.yandex.ru/debian/dists/squeeze/main/binary-i386/Packages.gz", &http.Error{Code: 404})
|
||||||
s.downloader.ExpectResponse("http://mirror.yandex.ru/debian/dists/squeeze/main/binary-i386/Packages", examplePackagesFile)
|
s.downloader.ExpectResponse("http://mirror.yandex.ru/debian/dists/squeeze/main/binary-i386/Packages", examplePackagesFile)
|
||||||
|
|
||||||
err = s.repo.DownloadPackageIndexes(s.progress, s.downloader, nil, s.collectionFactory, false, 1)
|
err = s.repo.DownloadPackageIndexes(s.progress, s.downloader, nil, s.collectionFactory, false)
|
||||||
c.Assert(err, IsNil)
|
c.Assert(err, IsNil)
|
||||||
c.Assert(s.downloader.Empty(), Equals, true)
|
c.Assert(s.downloader.Empty(), Equals, true)
|
||||||
|
|
||||||
@@ -303,7 +303,7 @@ func (s *RemoteRepoSuite) TestDownload(c *C) {
|
|||||||
s.downloader.ExpectError("http://mirror.yandex.ru/debian/dists/squeeze/main/binary-i386/Packages.gz", &http.Error{Code: 404})
|
s.downloader.ExpectError("http://mirror.yandex.ru/debian/dists/squeeze/main/binary-i386/Packages.gz", &http.Error{Code: 404})
|
||||||
s.downloader.ExpectResponse("http://mirror.yandex.ru/debian/dists/squeeze/main/binary-i386/Packages", examplePackagesFile)
|
s.downloader.ExpectResponse("http://mirror.yandex.ru/debian/dists/squeeze/main/binary-i386/Packages", examplePackagesFile)
|
||||||
|
|
||||||
err = s.repo.DownloadPackageIndexes(s.progress, s.downloader, nil, s.collectionFactory, false, 1)
|
err = s.repo.DownloadPackageIndexes(s.progress, s.downloader, nil, s.collectionFactory, false)
|
||||||
c.Assert(err, IsNil)
|
c.Assert(err, IsNil)
|
||||||
c.Assert(s.downloader.Empty(), Equals, true)
|
c.Assert(s.downloader.Empty(), Equals, true)
|
||||||
|
|
||||||
@@ -324,7 +324,7 @@ func (s *RemoteRepoSuite) TestDownload(c *C) {
|
|||||||
s.downloader.ExpectError("http://mirror.yandex.ru/debian/dists/squeeze/main/binary-i386/Packages.gz", &http.Error{Code: 404})
|
s.downloader.ExpectError("http://mirror.yandex.ru/debian/dists/squeeze/main/binary-i386/Packages.gz", &http.Error{Code: 404})
|
||||||
s.downloader.ExpectResponse("http://mirror.yandex.ru/debian/dists/squeeze/main/binary-i386/Packages", examplePackagesFile)
|
s.downloader.ExpectResponse("http://mirror.yandex.ru/debian/dists/squeeze/main/binary-i386/Packages", examplePackagesFile)
|
||||||
|
|
||||||
err = s.repo.DownloadPackageIndexes(s.progress, s.downloader, nil, s.collectionFactory, false, 1)
|
err = s.repo.DownloadPackageIndexes(s.progress, s.downloader, nil, s.collectionFactory, false)
|
||||||
c.Assert(err, IsNil)
|
c.Assert(err, IsNil)
|
||||||
c.Assert(s.downloader.Empty(), Equals, true)
|
c.Assert(s.downloader.Empty(), Equals, true)
|
||||||
|
|
||||||
@@ -351,7 +351,7 @@ func (s *RemoteRepoSuite) TestDownloadWithInstaller(c *C) {
|
|||||||
s.downloader.ExpectResponse("http://mirror.yandex.ru/debian/dists/squeeze/main/installer-i386/current/images/SHA256SUMS", exampleInstallerHashSumFile)
|
s.downloader.ExpectResponse("http://mirror.yandex.ru/debian/dists/squeeze/main/installer-i386/current/images/SHA256SUMS", exampleInstallerHashSumFile)
|
||||||
s.downloader.ExpectResponse("http://mirror.yandex.ru/debian/dists/squeeze/main/installer-i386/current/images/MANIFEST", exampleInstallerManifestFile)
|
s.downloader.ExpectResponse("http://mirror.yandex.ru/debian/dists/squeeze/main/installer-i386/current/images/MANIFEST", exampleInstallerManifestFile)
|
||||||
|
|
||||||
err = s.repo.DownloadPackageIndexes(s.progress, s.downloader, nil, s.collectionFactory, false, 1)
|
err = s.repo.DownloadPackageIndexes(s.progress, s.downloader, nil, s.collectionFactory, false)
|
||||||
c.Assert(err, IsNil)
|
c.Assert(err, IsNil)
|
||||||
c.Assert(s.downloader.Empty(), Equals, true)
|
c.Assert(s.downloader.Empty(), Equals, true)
|
||||||
|
|
||||||
@@ -395,7 +395,7 @@ func (s *RemoteRepoSuite) TestDownloadWithSources(c *C) {
|
|||||||
s.downloader.ExpectError("http://mirror.yandex.ru/debian/dists/squeeze/main/source/Sources.gz", &http.Error{Code: 404})
|
s.downloader.ExpectError("http://mirror.yandex.ru/debian/dists/squeeze/main/source/Sources.gz", &http.Error{Code: 404})
|
||||||
s.downloader.ExpectResponse("http://mirror.yandex.ru/debian/dists/squeeze/main/source/Sources", exampleSourcesFile)
|
s.downloader.ExpectResponse("http://mirror.yandex.ru/debian/dists/squeeze/main/source/Sources", exampleSourcesFile)
|
||||||
|
|
||||||
err = s.repo.DownloadPackageIndexes(s.progress, s.downloader, nil, s.collectionFactory, false, 1)
|
err = s.repo.DownloadPackageIndexes(s.progress, s.downloader, nil, s.collectionFactory, false)
|
||||||
c.Assert(err, IsNil)
|
c.Assert(err, IsNil)
|
||||||
c.Assert(s.downloader.Empty(), Equals, true)
|
c.Assert(s.downloader.Empty(), Equals, true)
|
||||||
|
|
||||||
@@ -439,7 +439,7 @@ func (s *RemoteRepoSuite) TestDownloadWithSources(c *C) {
|
|||||||
s.downloader.ExpectError("http://mirror.yandex.ru/debian/dists/squeeze/main/source/Sources.gz", &http.Error{Code: 404})
|
s.downloader.ExpectError("http://mirror.yandex.ru/debian/dists/squeeze/main/source/Sources.gz", &http.Error{Code: 404})
|
||||||
s.downloader.ExpectResponse("http://mirror.yandex.ru/debian/dists/squeeze/main/source/Sources", exampleSourcesFile)
|
s.downloader.ExpectResponse("http://mirror.yandex.ru/debian/dists/squeeze/main/source/Sources", exampleSourcesFile)
|
||||||
|
|
||||||
err = s.repo.DownloadPackageIndexes(s.progress, s.downloader, nil, s.collectionFactory, false, 1)
|
err = s.repo.DownloadPackageIndexes(s.progress, s.downloader, nil, s.collectionFactory, false)
|
||||||
c.Assert(err, IsNil)
|
c.Assert(err, IsNil)
|
||||||
c.Assert(s.downloader.Empty(), Equals, true)
|
c.Assert(s.downloader.Empty(), Equals, true)
|
||||||
|
|
||||||
@@ -464,7 +464,7 @@ func (s *RemoteRepoSuite) TestDownloadWithSources(c *C) {
|
|||||||
s.downloader.ExpectError("http://mirror.yandex.ru/debian/dists/squeeze/main/source/Sources.gz", &http.Error{Code: 404})
|
s.downloader.ExpectError("http://mirror.yandex.ru/debian/dists/squeeze/main/source/Sources.gz", &http.Error{Code: 404})
|
||||||
s.downloader.ExpectResponse("http://mirror.yandex.ru/debian/dists/squeeze/main/source/Sources", exampleSourcesFile)
|
s.downloader.ExpectResponse("http://mirror.yandex.ru/debian/dists/squeeze/main/source/Sources", exampleSourcesFile)
|
||||||
|
|
||||||
err = s.repo.DownloadPackageIndexes(s.progress, s.downloader, nil, s.collectionFactory, false, 1)
|
err = s.repo.DownloadPackageIndexes(s.progress, s.downloader, nil, s.collectionFactory, false)
|
||||||
c.Assert(err, IsNil)
|
c.Assert(err, IsNil)
|
||||||
c.Assert(s.downloader.Empty(), Equals, true)
|
c.Assert(s.downloader.Empty(), Equals, true)
|
||||||
|
|
||||||
@@ -488,7 +488,7 @@ func (s *RemoteRepoSuite) TestDownloadFlat(c *C) {
|
|||||||
err := s.flat.Fetch(downloader, nil)
|
err := s.flat.Fetch(downloader, nil)
|
||||||
c.Assert(err, IsNil)
|
c.Assert(err, IsNil)
|
||||||
|
|
||||||
err = s.flat.DownloadPackageIndexes(s.progress, downloader, nil, s.collectionFactory, true, 1)
|
err = s.flat.DownloadPackageIndexes(s.progress, downloader, nil, s.collectionFactory, true)
|
||||||
c.Assert(err, IsNil)
|
c.Assert(err, IsNil)
|
||||||
c.Assert(downloader.Empty(), Equals, true)
|
c.Assert(downloader.Empty(), Equals, true)
|
||||||
|
|
||||||
@@ -516,7 +516,7 @@ func (s *RemoteRepoSuite) TestDownloadFlat(c *C) {
|
|||||||
err = s.flat.Fetch(downloader, nil)
|
err = s.flat.Fetch(downloader, nil)
|
||||||
c.Assert(err, IsNil)
|
c.Assert(err, IsNil)
|
||||||
|
|
||||||
err = s.flat.DownloadPackageIndexes(s.progress, downloader, nil, s.collectionFactory, true, 1)
|
err = s.flat.DownloadPackageIndexes(s.progress, downloader, nil, s.collectionFactory, true)
|
||||||
c.Assert(err, IsNil)
|
c.Assert(err, IsNil)
|
||||||
c.Assert(downloader.Empty(), Equals, true)
|
c.Assert(downloader.Empty(), Equals, true)
|
||||||
|
|
||||||
@@ -538,7 +538,7 @@ func (s *RemoteRepoSuite) TestDownloadFlat(c *C) {
|
|||||||
err = s.flat.Fetch(downloader, nil)
|
err = s.flat.Fetch(downloader, nil)
|
||||||
c.Assert(err, IsNil)
|
c.Assert(err, IsNil)
|
||||||
|
|
||||||
err = s.flat.DownloadPackageIndexes(s.progress, downloader, nil, s.collectionFactory, true, 1)
|
err = s.flat.DownloadPackageIndexes(s.progress, downloader, nil, s.collectionFactory, true)
|
||||||
c.Assert(err, IsNil)
|
c.Assert(err, IsNil)
|
||||||
c.Assert(downloader.Empty(), Equals, true)
|
c.Assert(downloader.Empty(), Equals, true)
|
||||||
|
|
||||||
@@ -569,7 +569,7 @@ func (s *RemoteRepoSuite) TestDownloadWithSourcesFlat(c *C) {
|
|||||||
err := s.flat.Fetch(downloader, nil)
|
err := s.flat.Fetch(downloader, nil)
|
||||||
c.Assert(err, IsNil)
|
c.Assert(err, IsNil)
|
||||||
|
|
||||||
err = s.flat.DownloadPackageIndexes(s.progress, downloader, nil, s.collectionFactory, true, 1)
|
err = s.flat.DownloadPackageIndexes(s.progress, downloader, nil, s.collectionFactory, true)
|
||||||
c.Assert(err, IsNil)
|
c.Assert(err, IsNil)
|
||||||
c.Assert(downloader.Empty(), Equals, true)
|
c.Assert(downloader.Empty(), Equals, true)
|
||||||
|
|
||||||
@@ -615,7 +615,7 @@ func (s *RemoteRepoSuite) TestDownloadWithSourcesFlat(c *C) {
|
|||||||
err = s.flat.Fetch(downloader, nil)
|
err = s.flat.Fetch(downloader, nil)
|
||||||
c.Assert(err, IsNil)
|
c.Assert(err, IsNil)
|
||||||
|
|
||||||
err = s.flat.DownloadPackageIndexes(s.progress, downloader, nil, s.collectionFactory, true, 1)
|
err = s.flat.DownloadPackageIndexes(s.progress, downloader, nil, s.collectionFactory, true)
|
||||||
c.Assert(err, IsNil)
|
c.Assert(err, IsNil)
|
||||||
c.Assert(downloader.Empty(), Equals, true)
|
c.Assert(downloader.Empty(), Equals, true)
|
||||||
|
|
||||||
@@ -641,7 +641,7 @@ func (s *RemoteRepoSuite) TestDownloadWithSourcesFlat(c *C) {
|
|||||||
err = s.flat.Fetch(downloader, nil)
|
err = s.flat.Fetch(downloader, nil)
|
||||||
c.Assert(err, IsNil)
|
c.Assert(err, IsNil)
|
||||||
|
|
||||||
err = s.flat.DownloadPackageIndexes(s.progress, downloader, nil, s.collectionFactory, true, 1)
|
err = s.flat.DownloadPackageIndexes(s.progress, downloader, nil, s.collectionFactory, true)
|
||||||
c.Assert(err, IsNil)
|
c.Assert(err, IsNil)
|
||||||
c.Assert(downloader.Empty(), Equals, true)
|
c.Assert(downloader.Empty(), Equals, true)
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -39,7 +39,7 @@ var compressionMethods = []struct {
|
|||||||
|
|
||||||
// DownloadTryCompression tries to download from URL .bz2, .gz and raw extension until
|
// DownloadTryCompression tries to download from URL .bz2, .gz and raw extension until
|
||||||
// it finds existing file.
|
// it finds existing file.
|
||||||
func DownloadTryCompression(ctx context.Context, downloader aptly.Downloader, baseURL *url.URL, path string, expectedChecksums map[string]utils.ChecksumInfo, ignoreMismatch bool, maxTries int) (io.Reader, *os.File, error) {
|
func DownloadTryCompression(ctx context.Context, downloader aptly.Downloader, baseURL *url.URL, path string, expectedChecksums map[string]utils.ChecksumInfo, ignoreMismatch bool) (io.Reader, *os.File, error) {
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
for _, method := range compressionMethods {
|
for _, method := range compressionMethods {
|
||||||
@@ -63,7 +63,7 @@ func DownloadTryCompression(ctx context.Context, downloader aptly.Downloader, ba
|
|||||||
|
|
||||||
if foundChecksum {
|
if foundChecksum {
|
||||||
expected := expectedChecksums[bestSuffix]
|
expected := expectedChecksums[bestSuffix]
|
||||||
file, err = DownloadTempWithChecksum(ctx, downloader, tryURL.String(), &expected, ignoreMismatch, maxTries)
|
file, err = DownloadTempWithChecksum(ctx, downloader, tryURL.String(), &expected, ignoreMismatch)
|
||||||
} else {
|
} else {
|
||||||
if !ignoreMismatch {
|
if !ignoreMismatch {
|
||||||
continue
|
continue
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ func (s *CompressionSuite) TestDownloadTryCompression(c *C) {
|
|||||||
buf = make([]byte, 4)
|
buf = make([]byte, 4)
|
||||||
d := NewFakeDownloader()
|
d := NewFakeDownloader()
|
||||||
d.ExpectResponse("http://example.com/file.bz2", bzipData)
|
d.ExpectResponse("http://example.com/file.bz2", bzipData)
|
||||||
r, file, err := DownloadTryCompression(s.ctx, d, s.baseURL, "file", expectedChecksums, false, 1)
|
r, file, err := DownloadTryCompression(s.ctx, d, s.baseURL, "file", expectedChecksums, false)
|
||||||
c.Assert(err, IsNil)
|
c.Assert(err, IsNil)
|
||||||
defer file.Close()
|
defer file.Close()
|
||||||
io.ReadFull(r, buf)
|
io.ReadFull(r, buf)
|
||||||
@@ -56,7 +56,7 @@ func (s *CompressionSuite) TestDownloadTryCompression(c *C) {
|
|||||||
d = NewFakeDownloader()
|
d = NewFakeDownloader()
|
||||||
d.ExpectError("http://example.com/file.bz2", &Error{Code: 404})
|
d.ExpectError("http://example.com/file.bz2", &Error{Code: 404})
|
||||||
d.ExpectResponse("http://example.com/file.gz", gzipData)
|
d.ExpectResponse("http://example.com/file.gz", gzipData)
|
||||||
r, file, err = DownloadTryCompression(s.ctx, d, s.baseURL, "file", expectedChecksums, false, 1)
|
r, file, err = DownloadTryCompression(s.ctx, d, s.baseURL, "file", expectedChecksums, false)
|
||||||
c.Assert(err, IsNil)
|
c.Assert(err, IsNil)
|
||||||
defer file.Close()
|
defer file.Close()
|
||||||
io.ReadFull(r, buf)
|
io.ReadFull(r, buf)
|
||||||
@@ -69,7 +69,7 @@ func (s *CompressionSuite) TestDownloadTryCompression(c *C) {
|
|||||||
d.ExpectError("http://example.com/file.bz2", &Error{Code: 404})
|
d.ExpectError("http://example.com/file.bz2", &Error{Code: 404})
|
||||||
d.ExpectError("http://example.com/file.gz", &Error{Code: 404})
|
d.ExpectError("http://example.com/file.gz", &Error{Code: 404})
|
||||||
d.ExpectResponse("http://example.com/file.xz", xzData)
|
d.ExpectResponse("http://example.com/file.xz", xzData)
|
||||||
r, file, err = DownloadTryCompression(s.ctx, d, s.baseURL, "file", expectedChecksums, false, 1)
|
r, file, err = DownloadTryCompression(s.ctx, d, s.baseURL, "file", expectedChecksums, false)
|
||||||
c.Assert(err, IsNil)
|
c.Assert(err, IsNil)
|
||||||
defer file.Close()
|
defer file.Close()
|
||||||
io.ReadFull(r, buf)
|
io.ReadFull(r, buf)
|
||||||
@@ -83,7 +83,7 @@ func (s *CompressionSuite) TestDownloadTryCompression(c *C) {
|
|||||||
d.ExpectError("http://example.com/file.gz", &Error{Code: 404})
|
d.ExpectError("http://example.com/file.gz", &Error{Code: 404})
|
||||||
d.ExpectError("http://example.com/file.xz", &Error{Code: 404})
|
d.ExpectError("http://example.com/file.xz", &Error{Code: 404})
|
||||||
d.ExpectResponse("http://example.com/file", rawData)
|
d.ExpectResponse("http://example.com/file", rawData)
|
||||||
r, file, err = DownloadTryCompression(s.ctx, d, s.baseURL, "file", expectedChecksums, false, 1)
|
r, file, err = DownloadTryCompression(s.ctx, d, s.baseURL, "file", expectedChecksums, false)
|
||||||
c.Assert(err, IsNil)
|
c.Assert(err, IsNil)
|
||||||
defer file.Close()
|
defer file.Close()
|
||||||
io.ReadFull(r, buf)
|
io.ReadFull(r, buf)
|
||||||
@@ -94,7 +94,7 @@ func (s *CompressionSuite) TestDownloadTryCompression(c *C) {
|
|||||||
d = NewFakeDownloader()
|
d = NewFakeDownloader()
|
||||||
d.ExpectError("http://example.com/file.bz2", &Error{Code: 404})
|
d.ExpectError("http://example.com/file.bz2", &Error{Code: 404})
|
||||||
d.ExpectResponse("http://example.com/file.gz", "x")
|
d.ExpectResponse("http://example.com/file.gz", "x")
|
||||||
_, _, err = DownloadTryCompression(s.ctx, d, s.baseURL, "file", nil, true, 1)
|
_, _, err = DownloadTryCompression(s.ctx, d, s.baseURL, "file", nil, true)
|
||||||
c.Assert(err, ErrorMatches, "unexpected EOF")
|
c.Assert(err, ErrorMatches, "unexpected EOF")
|
||||||
c.Assert(d.Empty(), Equals, true)
|
c.Assert(d.Empty(), Equals, true)
|
||||||
}
|
}
|
||||||
@@ -112,7 +112,7 @@ func (s *CompressionSuite) TestDownloadTryCompressionLongestSuffix(c *C) {
|
|||||||
buf = make([]byte, 4)
|
buf = make([]byte, 4)
|
||||||
d := NewFakeDownloader()
|
d := NewFakeDownloader()
|
||||||
d.ExpectResponse("http://example.com/subdir/file.bz2", bzipData)
|
d.ExpectResponse("http://example.com/subdir/file.bz2", bzipData)
|
||||||
r, file, err := DownloadTryCompression(s.ctx, d, s.baseURL, "subdir/file", expectedChecksums, false, 1)
|
r, file, err := DownloadTryCompression(s.ctx, d, s.baseURL, "subdir/file", expectedChecksums, false)
|
||||||
c.Assert(err, IsNil)
|
c.Assert(err, IsNil)
|
||||||
defer file.Close()
|
defer file.Close()
|
||||||
io.ReadFull(r, buf)
|
io.ReadFull(r, buf)
|
||||||
@@ -122,7 +122,7 @@ func (s *CompressionSuite) TestDownloadTryCompressionLongestSuffix(c *C) {
|
|||||||
|
|
||||||
func (s *CompressionSuite) TestDownloadTryCompressionErrors(c *C) {
|
func (s *CompressionSuite) TestDownloadTryCompressionErrors(c *C) {
|
||||||
d := NewFakeDownloader()
|
d := NewFakeDownloader()
|
||||||
_, _, err := DownloadTryCompression(s.ctx, d, s.baseURL, "file", nil, true, 1)
|
_, _, err := DownloadTryCompression(s.ctx, d, s.baseURL, "file", nil, true)
|
||||||
c.Assert(err, ErrorMatches, "unexpected request.*")
|
c.Assert(err, ErrorMatches, "unexpected request.*")
|
||||||
|
|
||||||
d = NewFakeDownloader()
|
d = NewFakeDownloader()
|
||||||
@@ -130,7 +130,7 @@ func (s *CompressionSuite) TestDownloadTryCompressionErrors(c *C) {
|
|||||||
d.ExpectError("http://example.com/file.gz", &Error{Code: 404})
|
d.ExpectError("http://example.com/file.gz", &Error{Code: 404})
|
||||||
d.ExpectError("http://example.com/file.xz", &Error{Code: 404})
|
d.ExpectError("http://example.com/file.xz", &Error{Code: 404})
|
||||||
d.ExpectError("http://example.com/file", errors.New("403"))
|
d.ExpectError("http://example.com/file", errors.New("403"))
|
||||||
_, _, err = DownloadTryCompression(s.ctx, d, s.baseURL, "file", nil, true, 1)
|
_, _, err = DownloadTryCompression(s.ctx, d, s.baseURL, "file", nil, true)
|
||||||
c.Assert(err, ErrorMatches, "403")
|
c.Assert(err, ErrorMatches, "403")
|
||||||
|
|
||||||
d = NewFakeDownloader()
|
d = NewFakeDownloader()
|
||||||
@@ -144,6 +144,6 @@ func (s *CompressionSuite) TestDownloadTryCompressionErrors(c *C) {
|
|||||||
"file.xz": {Size: 7},
|
"file.xz": {Size: 7},
|
||||||
"file": {Size: 7},
|
"file": {Size: 7},
|
||||||
}
|
}
|
||||||
_, _, err = DownloadTryCompression(s.ctx, d, s.baseURL, "file", expectedChecksums, false, 1)
|
_, _, err = DownloadTryCompression(s.ctx, d, s.baseURL, "file", expectedChecksums, false)
|
||||||
c.Assert(err, ErrorMatches, "checksums don't match.*")
|
c.Assert(err, ErrorMatches, "checksums don't match.*")
|
||||||
}
|
}
|
||||||
|
|||||||
+36
-4
@@ -6,6 +6,7 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -28,12 +29,13 @@ var (
|
|||||||
type downloaderImpl struct {
|
type downloaderImpl struct {
|
||||||
progress aptly.Progress
|
progress aptly.Progress
|
||||||
aggWriter io.Writer
|
aggWriter io.Writer
|
||||||
|
maxTries int
|
||||||
client *http.Client
|
client *http.Client
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewDownloader creates new instance of Downloader which specified number
|
// NewDownloader creates new instance of Downloader which specified number
|
||||||
// of threads and download limit in bytes/sec
|
// of threads and download limit in bytes/sec
|
||||||
func NewDownloader(downLimit int64, progress aptly.Progress) aptly.Downloader {
|
func NewDownloader(downLimit int64, maxTries int, progress aptly.Progress) aptly.Downloader {
|
||||||
transport := http.Transport{}
|
transport := http.Transport{}
|
||||||
transport.Proxy = http.DefaultTransport.(*http.Transport).Proxy
|
transport.Proxy = http.DefaultTransport.(*http.Transport).Proxy
|
||||||
transport.ResponseHeaderTimeout = 30 * time.Second
|
transport.ResponseHeaderTimeout = 30 * time.Second
|
||||||
@@ -45,6 +47,7 @@ func NewDownloader(downLimit int64, progress aptly.Progress) aptly.Downloader {
|
|||||||
|
|
||||||
downloader := &downloaderImpl{
|
downloader := &downloaderImpl{
|
||||||
progress: progress,
|
progress: progress,
|
||||||
|
maxTries: maxTries,
|
||||||
client: &http.Client{
|
client: &http.Client{
|
||||||
Transport: &transport,
|
Transport: &transport,
|
||||||
},
|
},
|
||||||
@@ -71,7 +74,19 @@ func (downloader *downloaderImpl) GetLength(ctx context.Context, url string) (in
|
|||||||
return -1, err
|
return -1, err
|
||||||
}
|
}
|
||||||
|
|
||||||
resp, err := downloader.client.Do(req)
|
var resp *http.Response
|
||||||
|
|
||||||
|
maxTries := downloader.maxTries
|
||||||
|
for maxTries > 0 {
|
||||||
|
resp, err = downloader.client.Do(req)
|
||||||
|
if err != nil && retryableError(err) {
|
||||||
|
maxTries--
|
||||||
|
} else {
|
||||||
|
// stop retrying
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return -1, errors.Wrap(err, url)
|
return -1, errors.Wrap(err, url)
|
||||||
}
|
}
|
||||||
@@ -89,10 +104,25 @@ func (downloader *downloaderImpl) GetLength(ctx context.Context, url string) (in
|
|||||||
|
|
||||||
// Download starts new download task
|
// Download starts new download task
|
||||||
func (downloader *downloaderImpl) Download(ctx context.Context, url string, destination string) error {
|
func (downloader *downloaderImpl) Download(ctx context.Context, url string, destination string) error {
|
||||||
return downloader.DownloadWithChecksum(ctx, url, destination, nil, false, 1)
|
return downloader.DownloadWithChecksum(ctx, url, destination, nil, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func retryableError(err error) bool {
|
func retryableError(err error) bool {
|
||||||
|
// unwrap errors.Wrap
|
||||||
|
err = errors.Cause(err)
|
||||||
|
|
||||||
|
// unwrap *url.Error
|
||||||
|
if wrapped, ok := err.(*url.Error); ok {
|
||||||
|
err = wrapped.Err
|
||||||
|
}
|
||||||
|
|
||||||
|
switch err {
|
||||||
|
case io.EOF:
|
||||||
|
return true
|
||||||
|
case io.ErrUnexpectedEOF:
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
switch err.(type) {
|
switch err.(type) {
|
||||||
case *net.OpError:
|
case *net.OpError:
|
||||||
return true
|
return true
|
||||||
@@ -101,6 +131,7 @@ func retryableError(err error) bool {
|
|||||||
case net.Error:
|
case net.Error:
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -123,7 +154,7 @@ func (downloader *downloaderImpl) newRequest(ctx context.Context, method, url st
|
|||||||
|
|
||||||
// DownloadWithChecksum starts new download task with checksum verification
|
// DownloadWithChecksum starts new download task with checksum verification
|
||||||
func (downloader *downloaderImpl) DownloadWithChecksum(ctx context.Context, url string, destination string,
|
func (downloader *downloaderImpl) DownloadWithChecksum(ctx context.Context, url string, destination string,
|
||||||
expected *utils.ChecksumInfo, ignoreMismatch bool, maxTries int) error {
|
expected *utils.ChecksumInfo, ignoreMismatch bool) error {
|
||||||
|
|
||||||
if downloader.progress != nil {
|
if downloader.progress != nil {
|
||||||
downloader.progress.Printf("Downloading %s...\n", url)
|
downloader.progress.Printf("Downloading %s...\n", url)
|
||||||
@@ -131,6 +162,7 @@ func (downloader *downloaderImpl) DownloadWithChecksum(ctx context.Context, url
|
|||||||
req, err := downloader.newRequest(ctx, "GET", url)
|
req, err := downloader.newRequest(ctx, "GET", url)
|
||||||
|
|
||||||
var temppath string
|
var temppath string
|
||||||
|
maxTries := downloader.maxTries
|
||||||
for maxTries > 0 {
|
for maxTries > 0 {
|
||||||
temppath, err = downloader.download(req, url, destination, expected, ignoreMismatch)
|
temppath, err = downloader.download(req, url, destination, expected, ignoreMismatch)
|
||||||
|
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ func (s *DownloaderSuiteBase) SetUpTest(c *C) {
|
|||||||
s.progress = console.NewProgress()
|
s.progress = console.NewProgress()
|
||||||
s.progress.Start()
|
s.progress.Start()
|
||||||
|
|
||||||
s.d = NewDownloader(0, s.progress)
|
s.d = NewDownloader(0, 1, s.progress)
|
||||||
s.ctx = context.Background()
|
s.ctx = context.Background()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,32 +78,32 @@ func (s *DownloaderSuite) TestDownloadOK(c *C) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *DownloaderSuite) TestDownloadWithChecksum(c *C) {
|
func (s *DownloaderSuite) TestDownloadWithChecksum(c *C) {
|
||||||
c.Assert(s.d.DownloadWithChecksum(s.ctx, s.url+"/test", s.tempfile.Name(), &utils.ChecksumInfo{}, false, 1),
|
c.Assert(s.d.DownloadWithChecksum(s.ctx, s.url+"/test", s.tempfile.Name(), &utils.ChecksumInfo{}, false),
|
||||||
ErrorMatches, ".*size check mismatch 12 != 0")
|
ErrorMatches, ".*size check mismatch 12 != 0")
|
||||||
|
|
||||||
c.Assert(s.d.DownloadWithChecksum(s.ctx, s.url+"/test", s.tempfile.Name(), &utils.ChecksumInfo{Size: 12, MD5: "abcdef"}, false, 1),
|
c.Assert(s.d.DownloadWithChecksum(s.ctx, s.url+"/test", s.tempfile.Name(), &utils.ChecksumInfo{Size: 12, MD5: "abcdef"}, false),
|
||||||
ErrorMatches, ".*md5 hash mismatch \"a1acb0fe91c7db45ec4d775192ec5738\" != \"abcdef\"")
|
ErrorMatches, ".*md5 hash mismatch \"a1acb0fe91c7db45ec4d775192ec5738\" != \"abcdef\"")
|
||||||
|
|
||||||
c.Assert(s.d.DownloadWithChecksum(s.ctx, s.url+"/test", s.tempfile.Name(), &utils.ChecksumInfo{Size: 12, MD5: "abcdef"}, true, 1),
|
c.Assert(s.d.DownloadWithChecksum(s.ctx, s.url+"/test", s.tempfile.Name(), &utils.ChecksumInfo{Size: 12, MD5: "abcdef"}, true),
|
||||||
IsNil)
|
IsNil)
|
||||||
|
|
||||||
c.Assert(s.d.DownloadWithChecksum(s.ctx, s.url+"/test", s.tempfile.Name(), &utils.ChecksumInfo{Size: 12, MD5: "a1acb0fe91c7db45ec4d775192ec5738"}, false, 1),
|
c.Assert(s.d.DownloadWithChecksum(s.ctx, s.url+"/test", s.tempfile.Name(), &utils.ChecksumInfo{Size: 12, MD5: "a1acb0fe91c7db45ec4d775192ec5738"}, false),
|
||||||
IsNil)
|
IsNil)
|
||||||
|
|
||||||
c.Assert(s.d.DownloadWithChecksum(s.ctx, s.url+"/test", s.tempfile.Name(), &utils.ChecksumInfo{Size: 12, MD5: "a1acb0fe91c7db45ec4d775192ec5738", SHA1: "abcdef"}, false, 1),
|
c.Assert(s.d.DownloadWithChecksum(s.ctx, s.url+"/test", s.tempfile.Name(), &utils.ChecksumInfo{Size: 12, MD5: "a1acb0fe91c7db45ec4d775192ec5738", SHA1: "abcdef"}, false),
|
||||||
ErrorMatches, ".*sha1 hash mismatch \"921893bae6ad6fd818401875d6779254ef0ff0ec\" != \"abcdef\"")
|
ErrorMatches, ".*sha1 hash mismatch \"921893bae6ad6fd818401875d6779254ef0ff0ec\" != \"abcdef\"")
|
||||||
|
|
||||||
c.Assert(s.d.DownloadWithChecksum(s.ctx, s.url+"/test", s.tempfile.Name(), &utils.ChecksumInfo{Size: 12, MD5: "a1acb0fe91c7db45ec4d775192ec5738",
|
c.Assert(s.d.DownloadWithChecksum(s.ctx, s.url+"/test", s.tempfile.Name(), &utils.ChecksumInfo{Size: 12, MD5: "a1acb0fe91c7db45ec4d775192ec5738",
|
||||||
SHA1: "921893bae6ad6fd818401875d6779254ef0ff0ec"}, false, 1),
|
SHA1: "921893bae6ad6fd818401875d6779254ef0ff0ec"}, false),
|
||||||
IsNil)
|
IsNil)
|
||||||
|
|
||||||
c.Assert(s.d.DownloadWithChecksum(s.ctx, s.url+"/test", s.tempfile.Name(), &utils.ChecksumInfo{Size: 12, MD5: "a1acb0fe91c7db45ec4d775192ec5738",
|
c.Assert(s.d.DownloadWithChecksum(s.ctx, s.url+"/test", s.tempfile.Name(), &utils.ChecksumInfo{Size: 12, MD5: "a1acb0fe91c7db45ec4d775192ec5738",
|
||||||
SHA1: "921893bae6ad6fd818401875d6779254ef0ff0ec", SHA256: "abcdef"}, false, 1),
|
SHA1: "921893bae6ad6fd818401875d6779254ef0ff0ec", SHA256: "abcdef"}, false),
|
||||||
ErrorMatches, ".*sha256 hash mismatch \"b3c92ee1246176ed35f6e8463cd49074f29442f5bbffc3f8591cde1dcc849dac\" != \"abcdef\"")
|
ErrorMatches, ".*sha256 hash mismatch \"b3c92ee1246176ed35f6e8463cd49074f29442f5bbffc3f8591cde1dcc849dac\" != \"abcdef\"")
|
||||||
|
|
||||||
checksums := utils.ChecksumInfo{Size: 12, MD5: "a1acb0fe91c7db45ec4d775192ec5738",
|
checksums := utils.ChecksumInfo{Size: 12, MD5: "a1acb0fe91c7db45ec4d775192ec5738",
|
||||||
SHA1: "921893bae6ad6fd818401875d6779254ef0ff0ec", SHA256: "b3c92ee1246176ed35f6e8463cd49074f29442f5bbffc3f8591cde1dcc849dac"}
|
SHA1: "921893bae6ad6fd818401875d6779254ef0ff0ec", SHA256: "b3c92ee1246176ed35f6e8463cd49074f29442f5bbffc3f8591cde1dcc849dac"}
|
||||||
c.Assert(s.d.DownloadWithChecksum(s.ctx, s.url+"/test", s.tempfile.Name(), &checksums, false, 1),
|
c.Assert(s.d.DownloadWithChecksum(s.ctx, s.url+"/test", s.tempfile.Name(), &checksums, false),
|
||||||
IsNil)
|
IsNil)
|
||||||
// download backfills missing checksums
|
// download backfills missing checksums
|
||||||
c.Check(checksums.SHA512, Equals, "bac18bf4e564856369acc2ed57300fecba3a2c1af5ae8304021e4252488678feb18118466382ee4e1210fe1f065080210e453a80cfb37ccb8752af3269df160e")
|
c.Check(checksums.SHA512, Equals, "bac18bf4e564856369acc2ed57300fecba3a2c1af5ae8304021e4252488678feb18118466382ee4e1210fe1f065080210e453a80cfb37ccb8752af3269df160e")
|
||||||
|
|||||||
+2
-2
@@ -89,7 +89,7 @@ func (f *FakeDownloader) getExpectedRequest(url string) (*expectedRequest, error
|
|||||||
}
|
}
|
||||||
|
|
||||||
// DownloadWithChecksum performs fake download by matching against first expectation in the queue or any expectation, with cheksum verification
|
// DownloadWithChecksum performs fake download by matching against first expectation in the queue or any expectation, with cheksum verification
|
||||||
func (f *FakeDownloader) DownloadWithChecksum(ctx context.Context, url string, filename string, expected *utils.ChecksumInfo, ignoreMismatch bool, maxTries int) error {
|
func (f *FakeDownloader) DownloadWithChecksum(ctx context.Context, url string, filename string, expected *utils.ChecksumInfo, ignoreMismatch bool) error {
|
||||||
expectation, err := f.getExpectedRequest(url)
|
expectation, err := f.getExpectedRequest(url)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -130,7 +130,7 @@ func (f *FakeDownloader) DownloadWithChecksum(ctx context.Context, url string, f
|
|||||||
|
|
||||||
// Download performs fake download by matching against first expectation in the queue
|
// Download performs fake download by matching against first expectation in the queue
|
||||||
func (f *FakeDownloader) Download(ctx context.Context, url string, filename string) error {
|
func (f *FakeDownloader) Download(ctx context.Context, url string, filename string) error {
|
||||||
return f.DownloadWithChecksum(ctx, url, filename, nil, false, 1)
|
return f.DownloadWithChecksum(ctx, url, filename, nil, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetProgress returns Progress object
|
// GetProgress returns Progress object
|
||||||
|
|||||||
+3
-3
@@ -14,13 +14,13 @@ import (
|
|||||||
//
|
//
|
||||||
// Temporary file would be already removed, so no need to cleanup
|
// Temporary file would be already removed, so no need to cleanup
|
||||||
func DownloadTemp(ctx context.Context, downloader aptly.Downloader, url string) (*os.File, error) {
|
func DownloadTemp(ctx context.Context, downloader aptly.Downloader, url string) (*os.File, error) {
|
||||||
return DownloadTempWithChecksum(ctx, downloader, url, nil, false, 1)
|
return DownloadTempWithChecksum(ctx, downloader, url, nil, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DownloadTempWithChecksum is a DownloadTemp with checksum verification
|
// DownloadTempWithChecksum is a DownloadTemp with checksum verification
|
||||||
//
|
//
|
||||||
// Temporary file would be already removed, so no need to cleanup
|
// Temporary file would be already removed, so no need to cleanup
|
||||||
func DownloadTempWithChecksum(ctx context.Context, downloader aptly.Downloader, url string, expected *utils.ChecksumInfo, ignoreMismatch bool, maxTries int) (*os.File, error) {
|
func DownloadTempWithChecksum(ctx context.Context, downloader aptly.Downloader, url string, expected *utils.ChecksumInfo, ignoreMismatch bool) (*os.File, error) {
|
||||||
tempdir, err := ioutil.TempDir(os.TempDir(), "aptly")
|
tempdir, err := ioutil.TempDir(os.TempDir(), "aptly")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -34,7 +34,7 @@ func DownloadTempWithChecksum(ctx context.Context, downloader aptly.Downloader,
|
|||||||
defer downloader.GetProgress().ShutdownBar()
|
defer downloader.GetProgress().ShutdownBar()
|
||||||
}
|
}
|
||||||
|
|
||||||
err = downloader.DownloadWithChecksum(ctx, url, tempfile, expected, ignoreMismatch, maxTries)
|
err = downloader.DownloadWithChecksum(ctx, url, tempfile, expected, ignoreMismatch)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -38,12 +38,12 @@ func (s *TempSuite) TestDownloadTemp(c *C) {
|
|||||||
|
|
||||||
func (s *TempSuite) TestDownloadTempWithChecksum(c *C) {
|
func (s *TempSuite) TestDownloadTempWithChecksum(c *C) {
|
||||||
f, err := DownloadTempWithChecksum(s.ctx, s.d, s.url+"/test", &utils.ChecksumInfo{Size: 12, MD5: "a1acb0fe91c7db45ec4d775192ec5738",
|
f, err := DownloadTempWithChecksum(s.ctx, s.d, s.url+"/test", &utils.ChecksumInfo{Size: 12, MD5: "a1acb0fe91c7db45ec4d775192ec5738",
|
||||||
SHA1: "921893bae6ad6fd818401875d6779254ef0ff0ec", SHA256: "b3c92ee1246176ed35f6e8463cd49074f29442f5bbffc3f8591cde1dcc849dac"}, false, 1)
|
SHA1: "921893bae6ad6fd818401875d6779254ef0ff0ec", SHA256: "b3c92ee1246176ed35f6e8463cd49074f29442f5bbffc3f8591cde1dcc849dac"}, false)
|
||||||
c.Assert(err, IsNil)
|
c.Assert(err, IsNil)
|
||||||
|
|
||||||
c.Assert(f.Close(), IsNil)
|
c.Assert(f.Close(), IsNil)
|
||||||
|
|
||||||
_, err = DownloadTempWithChecksum(s.ctx, s.d, s.url+"/test", &utils.ChecksumInfo{Size: 13}, false, 1)
|
_, err = DownloadTempWithChecksum(s.ctx, s.d, s.url+"/test", &utils.ChecksumInfo{Size: 13}, false)
|
||||||
c.Assert(err, ErrorMatches, ".*size check mismatch 12 != 13")
|
c.Assert(err, ErrorMatches, ".*size check mismatch 12 != 13")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+8
-6
@@ -1,10 +1,12 @@
|
|||||||
all: prepare generate
|
RUBYBINPATH=$(shell ruby -r rubygems -e 'puts Gem.user_dir')/bin
|
||||||
|
|
||||||
prepare:
|
all: $(RUBYBINPATH)/ronn generate
|
||||||
gem install specific_install
|
|
||||||
gem specific_install -l smira/ronn
|
$(RUBYBINPATH)/ronn:
|
||||||
|
gem install --user-install specific_install
|
||||||
|
gem specific_install --user-install -l smira/ronn
|
||||||
|
|
||||||
generate:
|
generate:
|
||||||
go run ../_man/gen.go
|
PATH=$(RUBYBINPATH):$(PATH) go run ../_man/gen.go
|
||||||
|
|
||||||
.PHONY: prepare generate
|
.PHONY: generate
|
||||||
|
|||||||
+13
-2
@@ -1,7 +1,7 @@
|
|||||||
.\" generated with Ronn/v0.7.3
|
.\" generated with Ronn/v0.7.3
|
||||||
.\" http://github.com/rtomayko/ronn/tree/0.7.3
|
.\" http://github.com/rtomayko/ronn/tree/0.7.3
|
||||||
.
|
.
|
||||||
.TH "APTLY" "1" "September 2018" "" ""
|
.TH "APTLY" "1" "August 2019" "" ""
|
||||||
.
|
.
|
||||||
.SH "NAME"
|
.SH "NAME"
|
||||||
\fBaptly\fR \- Debian repository management tool
|
\fBaptly\fR \- Debian repository management tool
|
||||||
@@ -38,6 +38,7 @@ Configuration file is stored in JSON format (default values shown below):
|
|||||||
"rootDir": "$HOME/\.aptly",
|
"rootDir": "$HOME/\.aptly",
|
||||||
"downloadConcurrency": 4,
|
"downloadConcurrency": 4,
|
||||||
"downloadSpeedLimit": 0,
|
"downloadSpeedLimit": 0,
|
||||||
|
"downloadRetries": 0,
|
||||||
"architectures": [],
|
"architectures": [],
|
||||||
"dependencyFollowSuggests": false,
|
"dependencyFollowSuggests": false,
|
||||||
"dependencyFollowRecommends": false,
|
"dependencyFollowRecommends": false,
|
||||||
@@ -114,7 +115,11 @@ is a number of parallel download threads to use when downloading packages
|
|||||||
.
|
.
|
||||||
.TP
|
.TP
|
||||||
\fBdownloadSpeedLimit\fR
|
\fBdownloadSpeedLimit\fR
|
||||||
limit in kbytes/sec on download speed while mirroring remote repositieis
|
limit in kbytes/sec on download speed while mirroring remote repositories
|
||||||
|
.
|
||||||
|
.TP
|
||||||
|
\fBdownloadRetries\fR
|
||||||
|
number of retries for download attempts
|
||||||
.
|
.
|
||||||
.TP
|
.TP
|
||||||
\fBarchitectures\fR
|
\fBarchitectures\fR
|
||||||
@@ -2050,5 +2055,11 @@ Strajan Sebastian (https://github\.com/strajansebastian)
|
|||||||
.IP "\[ci]" 4
|
.IP "\[ci]" 4
|
||||||
Artem Smirnov (https://github\.com/urpylka)
|
Artem Smirnov (https://github\.com/urpylka)
|
||||||
.
|
.
|
||||||
|
.IP "\[ci]" 4
|
||||||
|
William Manley (https://github\.com/wmanley)
|
||||||
|
.
|
||||||
|
.IP "\[ci]" 4
|
||||||
|
Shengjing Zhu (https://github\.com/zhsj)
|
||||||
|
.
|
||||||
.IP "" 0
|
.IP "" 0
|
||||||
|
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ Configuration file is stored in JSON format (default values shown below):
|
|||||||
"rootDir": "$HOME/.aptly",
|
"rootDir": "$HOME/.aptly",
|
||||||
"downloadConcurrency": 4,
|
"downloadConcurrency": 4,
|
||||||
"downloadSpeedLimit": 0,
|
"downloadSpeedLimit": 0,
|
||||||
|
"downloadRetries": 0,
|
||||||
"architectures": [],
|
"architectures": [],
|
||||||
"dependencyFollowSuggests": false,
|
"dependencyFollowSuggests": false,
|
||||||
"dependencyFollowRecommends": false,
|
"dependencyFollowRecommends": false,
|
||||||
@@ -99,7 +100,10 @@ Options:
|
|||||||
is a number of parallel download threads to use when downloading packages
|
is a number of parallel download threads to use when downloading packages
|
||||||
|
|
||||||
* `downloadSpeedLimit`:
|
* `downloadSpeedLimit`:
|
||||||
limit in kbytes/sec on download speed while mirroring remote repositieis
|
limit in kbytes/sec on download speed while mirroring remote repositories
|
||||||
|
|
||||||
|
* `downloadRetries`:
|
||||||
|
number of retries for download attempts
|
||||||
|
|
||||||
* `architectures`:
|
* `architectures`:
|
||||||
is a list of architectures to process; if left empty defaults to all available architectures; could be
|
is a list of architectures to process; if left empty defaults to all available architectures; could be
|
||||||
|
|||||||
@@ -98,6 +98,7 @@ class BaseTest(object):
|
|||||||
"rootDir": "%s/.aptly" % os.environ["HOME"],
|
"rootDir": "%s/.aptly" % os.environ["HOME"],
|
||||||
"downloadConcurrency": 4,
|
"downloadConcurrency": 4,
|
||||||
"downloadSpeedLimit": 0,
|
"downloadSpeedLimit": 0,
|
||||||
|
"downloadRetries": 5,
|
||||||
"architectures": [],
|
"architectures": [],
|
||||||
"dependencyFollowSuggests": False,
|
"dependencyFollowSuggests": False,
|
||||||
"dependencyFollowRecommends": False,
|
"dependencyFollowRecommends": False,
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
"rootDir": "${HOME}/.aptly",
|
"rootDir": "${HOME}/.aptly",
|
||||||
"downloadConcurrency": 4,
|
"downloadConcurrency": 4,
|
||||||
"downloadSpeedLimit": 0,
|
"downloadSpeedLimit": 0,
|
||||||
|
"downloadRetries": 5,
|
||||||
"architectures": [],
|
"architectures": [],
|
||||||
"dependencyFollowSuggests": false,
|
"dependencyFollowSuggests": false,
|
||||||
"dependencyFollowRecommends": false,
|
"dependencyFollowRecommends": false,
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
"rootDir": "${HOME}/.aptly",
|
"rootDir": "${HOME}/.aptly",
|
||||||
"downloadConcurrency": 4,
|
"downloadConcurrency": 4,
|
||||||
"downloadSpeedLimit": 0,
|
"downloadSpeedLimit": 0,
|
||||||
|
"downloadRetries": 0,
|
||||||
"architectures": [],
|
"architectures": [],
|
||||||
"dependencyFollowSuggests": false,
|
"dependencyFollowSuggests": false,
|
||||||
"dependencyFollowRecommends": false,
|
"dependencyFollowRecommends": false,
|
||||||
|
|||||||
@@ -6,6 +6,6 @@ gpgv: Good signature from "Package Maintainer (PagerDuty, Inc.) <packages@pagerd
|
|||||||
Downloading & parsing package files...
|
Downloading & parsing package files...
|
||||||
Downloading http://packages.pagerduty.com/pdagent/deb/Packages.gz...
|
Downloading http://packages.pagerduty.com/pdagent/deb/Packages.gz...
|
||||||
Building download queue...
|
Building download queue...
|
||||||
Download queue: 15 items (1.87 MiB)
|
Download queue: 16 items (2.08 MiB)
|
||||||
|
|
||||||
Mirror `pagerduty` has been successfully updated.
|
Mirror `pagerduty` has been successfully updated.
|
||||||
|
|||||||
@@ -6,6 +6,6 @@ openpgp: Good signature from "Package Maintainer (PagerDuty, Inc.) <packages@pag
|
|||||||
Downloading & parsing package files...
|
Downloading & parsing package files...
|
||||||
Downloading http://packages.pagerduty.com/pdagent/deb/Packages.gz...
|
Downloading http://packages.pagerduty.com/pdagent/deb/Packages.gz...
|
||||||
Building download queue...
|
Building download queue...
|
||||||
Download queue: 15 items (1.87 MiB)
|
Download queue: 16 items (2.08 MiB)
|
||||||
|
|
||||||
Mirror `pagerduty` has been successfully updated.
|
Mirror `pagerduty` has been successfully updated.
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ type ConfigStructure struct { // nolint: maligned
|
|||||||
RootDir string `json:"rootDir"`
|
RootDir string `json:"rootDir"`
|
||||||
DownloadConcurrency int `json:"downloadConcurrency"`
|
DownloadConcurrency int `json:"downloadConcurrency"`
|
||||||
DownloadLimit int64 `json:"downloadSpeedLimit"`
|
DownloadLimit int64 `json:"downloadSpeedLimit"`
|
||||||
|
DownloadRetries int `json:"downloadRetries"`
|
||||||
Architectures []string `json:"architectures"`
|
Architectures []string `json:"architectures"`
|
||||||
DepFollowSuggests bool `json:"dependencyFollowSuggests"`
|
DepFollowSuggests bool `json:"dependencyFollowSuggests"`
|
||||||
DepFollowRecommends bool `json:"dependencyFollowRecommends"`
|
DepFollowRecommends bool `json:"dependencyFollowRecommends"`
|
||||||
|
|||||||
@@ -57,6 +57,7 @@ func (s *ConfigSuite) TestSaveConfig(c *C) {
|
|||||||
" \"rootDir\": \"/tmp/aptly\",\n"+
|
" \"rootDir\": \"/tmp/aptly\",\n"+
|
||||||
" \"downloadConcurrency\": 5,\n"+
|
" \"downloadConcurrency\": 5,\n"+
|
||||||
" \"downloadSpeedLimit\": 0,\n"+
|
" \"downloadSpeedLimit\": 0,\n"+
|
||||||
|
" \"downloadRetries\": 0,\n"+
|
||||||
" \"architectures\": null,\n"+
|
" \"architectures\": null,\n"+
|
||||||
" \"dependencyFollowSuggests\": false,\n"+
|
" \"dependencyFollowSuggests\": false,\n"+
|
||||||
" \"dependencyFollowRecommends\": false,\n"+
|
" \"dependencyFollowRecommends\": false,\n"+
|
||||||
|
|||||||
Reference in New Issue
Block a user