Commit 3164edc1 authored by Gerald Pape's avatar Gerald Pape Committed by Silvano Cerza

Make archive validation error messages friendlier (#1188)

* Make archive validation error messages friendlier

* change behaviour a little + fix tests
parent d977fc22
...@@ -34,6 +34,9 @@ import ( ...@@ -34,6 +34,9 @@ import (
// TestLocalArchiveChecksum test if the checksum of the local archive match the checksum of the DownloadResource // TestLocalArchiveChecksum test if the checksum of the local archive match the checksum of the DownloadResource
func (r *DownloadResource) TestLocalArchiveChecksum(downloadDir *paths.Path) (bool, error) { func (r *DownloadResource) TestLocalArchiveChecksum(downloadDir *paths.Path) (bool, error) {
if r.Checksum == "" {
return false, fmt.Errorf("missing checksum for: %s", r.ArchiveFileName)
}
split := strings.SplitN(r.Checksum, ":", 2) split := strings.SplitN(r.Checksum, ":", 2)
if len(split) != 2 { if len(split) != 2 {
return false, fmt.Errorf("invalid checksum format: %s", r.Checksum) return false, fmt.Errorf("invalid checksum format: %s", r.Checksum)
...@@ -69,7 +72,12 @@ func (r *DownloadResource) TestLocalArchiveChecksum(downloadDir *paths.Path) (bo ...@@ -69,7 +72,12 @@ func (r *DownloadResource) TestLocalArchiveChecksum(downloadDir *paths.Path) (bo
if _, err := io.Copy(algo, file); err != nil { if _, err := io.Copy(algo, file); err != nil {
return false, fmt.Errorf("computing hash: %s", err) return false, fmt.Errorf("computing hash: %s", err)
} }
return bytes.Compare(algo.Sum(nil), digest) == 0, nil
if bytes.Compare(algo.Sum(nil), digest) != 0 {
return false, fmt.Errorf("archive hash differs from hash in index")
}
return true, nil
} }
// TestLocalArchiveSize test if the local archive size match the DownloadResource size // TestLocalArchiveSize test if the local archive size match the DownloadResource size
...@@ -82,7 +90,11 @@ func (r *DownloadResource) TestLocalArchiveSize(downloadDir *paths.Path) (bool, ...@@ -82,7 +90,11 @@ func (r *DownloadResource) TestLocalArchiveSize(downloadDir *paths.Path) (bool,
if err != nil { if err != nil {
return false, fmt.Errorf("getting archive info: %s", err) return false, fmt.Errorf("getting archive info: %s", err)
} }
return info.Size() == r.Size, nil if info.Size() != r.Size {
return false, fmt.Errorf("fetched archive size differs from size specified in index")
}
return true, nil
} }
// TestLocalArchiveIntegrity checks for integrity of the local archive. // TestLocalArchiveIntegrity checks for integrity of the local archive.
...@@ -94,7 +106,7 @@ func (r *DownloadResource) TestLocalArchiveIntegrity(downloadDir *paths.Path) (b ...@@ -94,7 +106,7 @@ func (r *DownloadResource) TestLocalArchiveIntegrity(downloadDir *paths.Path) (b
} }
if ok, err := r.TestLocalArchiveSize(downloadDir); err != nil { if ok, err := r.TestLocalArchiveSize(downloadDir); err != nil {
return false, fmt.Errorf("teting archive size: %s", err) return false, fmt.Errorf("testing archive size: %s", err)
} else if !ok { } else if !ok {
return false, nil return false, nil
} }
...@@ -163,5 +175,9 @@ func CheckDirChecksum(root string) (bool, error) { ...@@ -163,5 +175,9 @@ func CheckDirChecksum(root string) (bool, error) {
if err != nil { if err != nil {
return false, err return false, err
} }
return file.Checksum == checksum, nil if file.Checksum != checksum {
return false, fmt.Errorf("Checksum differs from checksum in package.json")
}
return true, nil
} }
...@@ -44,27 +44,24 @@ func (r *DownloadResource) IsCached(downloadDir *paths.Path) (bool, error) { ...@@ -44,27 +44,24 @@ func (r *DownloadResource) IsCached(downloadDir *paths.Path) (bool, error) {
// Download a DownloadResource. // Download a DownloadResource.
func (r *DownloadResource) Download(downloadDir *paths.Path, config *downloader.Config) (*downloader.Downloader, error) { func (r *DownloadResource) Download(downloadDir *paths.Path, config *downloader.Config) (*downloader.Downloader, error) {
cached, err := r.TestLocalArchiveIntegrity(downloadDir)
if err != nil {
return nil, fmt.Errorf("testing local archive integrity: %s", err)
}
if cached {
// File is cached, nothing to do here
return nil, nil
}
path, err := r.ArchivePath(downloadDir) path, err := r.ArchivePath(downloadDir)
if err != nil { if err != nil {
return nil, fmt.Errorf("getting archive path: %s", err) return nil, fmt.Errorf("getting archive path: %s", err)
} }
if stats, err := path.Stat(); os.IsNotExist(err) { if _, err := path.Stat(); os.IsNotExist(err) {
// normal download // normal download
} else if err == nil && stats.Size() > r.Size { } else if err == nil {
// file is bigger than expected, retry download... // check local file integrity
ok, err := r.TestLocalArchiveIntegrity(downloadDir)
if err != nil || !ok {
if err := path.Remove(); err != nil { if err := path.Remove(); err != nil {
return nil, fmt.Errorf("removing corrupted archive file: %s", err) return nil, fmt.Errorf("removing corrupted archive file: %s", err)
} }
} else {
// File is cached, nothing to do here
return nil, nil
}
} else if err == nil { } else if err == nil {
// resume download // resume download
} else { } else {
......
...@@ -26,19 +26,21 @@ import ( ...@@ -26,19 +26,21 @@ import (
) )
func TestDownloadAndChecksums(t *testing.T) { func TestDownloadAndChecksums(t *testing.T) {
testFileName := "core.zip"
tmp, err := paths.MkTempDir("", "") tmp, err := paths.MkTempDir("", "")
require.NoError(t, err) require.NoError(t, err)
defer tmp.RemoveAll() defer tmp.RemoveAll()
testFile := tmp.Join("cache", "index.html") testFile := tmp.Join("cache", testFileName)
// taken from test/testdata/test_index.json
r := &DownloadResource{ r := &DownloadResource{
ArchiveFileName: "index.html", ArchiveFileName: testFileName,
CachePath: "cache", CachePath: "cache",
Checksum: "SHA-256:e021e1a223d03069d5f08dea25a58ca445a7376d9bdf980f756034f118449e66", Checksum: "SHA-256:6a338cf4d6d501176a2d352c87a8d72ac7488b8c5b82cdf2a4e2cef630391092",
Size: 1119, Size: 486,
URL: "https://downloads.arduino.cc/index.html", URL: "https://raw.githubusercontent.com/arduino/arduino-cli/master/test/testdata/core.zip",
} }
digest, err := hex.DecodeString("e021e1a223d03069d5f08dea25a58ca445a7376d9bdf980f756034f118449e66") digest, err := hex.DecodeString("6a338cf4d6d501176a2d352c87a8d72ac7488b8c5b82cdf2a4e2cef630391092")
require.NoError(t, err) require.NoError(t, err)
downloadAndTestChecksum := func() { downloadAndTestChecksum := func() {
...@@ -73,10 +75,14 @@ func TestDownloadAndChecksums(t *testing.T) { ...@@ -73,10 +75,14 @@ func TestDownloadAndChecksums(t *testing.T) {
// Download if cached file has less data (resume) // Download if cached file has less data (resume)
data, err = testFile.ReadFile() data, err = testFile.ReadFile()
require.NoError(t, err) require.NoError(t, err)
err = testFile.WriteFile(data[:1000]) err = testFile.WriteFile(data[:100])
require.NoError(t, err) require.NoError(t, err)
downloadAndTestChecksum() downloadAndTestChecksum()
r.Checksum = ""
_, err = r.TestLocalArchiveChecksum(tmp)
require.Error(t, err)
r.Checksum = "BOH:12312312312313123123123123123123" r.Checksum = "BOH:12312312312313123123123123123123"
_, err = r.TestLocalArchiveChecksum(tmp) _, err = r.TestLocalArchiveChecksum(tmp)
require.Error(t, err) require.Error(t, err)
...@@ -89,21 +95,16 @@ func TestDownloadAndChecksums(t *testing.T) { ...@@ -89,21 +95,16 @@ func TestDownloadAndChecksums(t *testing.T) {
_, err = r.TestLocalArchiveChecksum(tmp) _, err = r.TestLocalArchiveChecksum(tmp)
require.Error(t, err) require.Error(t, err)
r.Checksum = "SHA-1:c007e47637cc6ad6176e7d94aeffc232ee34c1c1" r.Checksum = "SHA-1:16e1495aff482f2650733e1661d5f7c69040ec13"
res, err := r.TestLocalArchiveChecksum(tmp) res, err := r.TestLocalArchiveChecksum(tmp)
require.NoError(t, err) require.NoError(t, err)
require.True(t, res) require.True(t, res)
r.Checksum = "MD5:2e388576eefd92a15967868d5f566f29" r.Checksum = "MD5:3bcc3aab6842ff124df6a5cfba678ca1"
res, err = r.TestLocalArchiveChecksum(tmp) res, err = r.TestLocalArchiveChecksum(tmp)
require.NoError(t, err) require.NoError(t, err)
require.True(t, res) require.True(t, res)
r.Checksum = "MD5:12312312312312312312313131231231"
res, err = r.TestLocalArchiveChecksum(tmp)
require.NoError(t, err)
require.False(t, res)
_, err = r.TestLocalArchiveChecksum(paths.New("/not-existent")) _, err = r.TestLocalArchiveChecksum(paths.New("/not-existent"))
require.Error(t, err) require.Error(t, err)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment