Skip to content

Commit dcef2d1

Browse files
committed
Some of the DownloadResource functions are now class methods
Slightly refactored also the way those methods are used.
1 parent f49bd85 commit dcef2d1

File tree

2 files changed

+81
-52
lines changed

2 files changed

+81
-52
lines changed

common/releases/checksums.go

Lines changed: 63 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ import (
3535
"crypto/sha256"
3636
"encoding/hex"
3737
"encoding/json"
38-
"errors"
3938
"fmt"
4039
"hash"
4140
"io"
@@ -45,65 +44,93 @@ import (
4544
"strings"
4645
)
4746

48-
func getHashAlgoAndComponent(checksum string) (hash.Hash, []byte) {
49-
components := strings.SplitN(checksum, ":", 2)
50-
hashAlgo := components[0]
51-
hashMid, err := hex.DecodeString(components[1])
47+
// IsCached returns a bool representing if the release has already been downloaded
48+
func (r *DownloadResource) IsCached() (bool, error) {
49+
archivePath, err := r.ArchivePath()
5250
if err != nil {
53-
return nil, nil
51+
return false, fmt.Errorf("getting archive path: %s", err)
5452
}
5553

56-
hash := []byte(hashMid)
57-
switch hashAlgo {
54+
_, err = os.Stat(archivePath)
55+
if err != nil && !os.IsNotExist(err) {
56+
return false, fmt.Errorf("checking archive existence: %s", err)
57+
}
58+
59+
return !os.IsNotExist(err), nil
60+
}
61+
62+
// TestLocalArchiveChecksum test if the checksum of the local archive match the checksum of the DownloadResource
63+
func (r *DownloadResource) TestLocalArchiveChecksum() (bool, error) {
64+
split := strings.SplitN(r.Checksum, ":", 2)
65+
if len(split) != 2 {
66+
return false, fmt.Errorf("invalid checksum format: %s", r.Checksum)
67+
}
68+
digest, err := hex.DecodeString(split[1])
69+
if err != nil {
70+
return false, fmt.Errorf("invalid hash '%s': %s", split[1], err)
71+
}
72+
73+
// names based on: https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#MessageDigest
74+
var algo hash.Hash
75+
switch split[0] {
5876
case "SHA-256":
59-
return crypto.SHA256.New(), hash
60-
case "SHA1":
61-
return crypto.SHA1.New(), hash
77+
algo = crypto.SHA256.New()
78+
case "SHA-1":
79+
algo = crypto.SHA1.New()
6280
case "MD5":
63-
return crypto.MD5.New(), hash
81+
algo = crypto.MD5.New()
6482
default:
65-
return nil, nil
83+
return false, fmt.Errorf("unsupported hash algorithm: %s", split[0])
6684
}
67-
}
6885

69-
// ChecksumMatches checks the checksum of a DownloadResource archive, in compliance with
70-
// What Checksum is expected.
71-
func checksumMatches(r *DownloadResource) bool {
72-
hash, content := getHashAlgoAndComponent(r.Checksum)
7386
filePath, err := r.ArchivePath()
7487
if err != nil {
75-
return false
88+
return false, fmt.Errorf("getting archive path: %s", err)
7689
}
7790

7891
file, err := os.Open(filePath)
7992
if err != nil {
80-
return false
93+
return false, fmt.Errorf("opening archive file: %s", err)
8194
}
8295
defer file.Close()
83-
io.Copy(hash, file)
84-
return bytes.Compare(hash.Sum(nil), content) == 0
96+
if _, err := io.Copy(algo, file); err != nil {
97+
return false, fmt.Errorf("computing hash: %s", err)
98+
}
99+
return bytes.Compare(algo.Sum(nil), digest) == 0, nil
85100
}
86101

87-
// checkLocalArchive check for integrity of the local archive.
88-
func checkLocalArchive(release *DownloadResource) error {
89-
archivePath, err := release.ArchivePath()
102+
// TestLocalArchiveSize test if the local archive size match the DownloadResource size
103+
func (r *DownloadResource) TestLocalArchiveSize() (bool, error) {
104+
filePath, err := r.ArchivePath()
90105
if err != nil {
91-
return err
92-
}
93-
stats, err := os.Stat(archivePath)
94-
if os.IsNotExist(err) {
95-
return errors.New("Archive does not exist")
106+
return false, fmt.Errorf("getting archive path: %s", err)
96107
}
108+
info, err := os.Stat(filePath)
97109
if err != nil {
98-
return err
110+
return false, fmt.Errorf("getting archive info: %s", err)
111+
}
112+
return info.Size() != r.Size, nil
113+
}
114+
115+
// TestLocalArchiveIntegrity checks for integrity of the local archive.
116+
func (r *DownloadResource) TestLocalArchiveIntegrity() (bool, error) {
117+
if cached, err := r.IsCached(); err != nil {
118+
return false, fmt.Errorf("testing if archive is cached: %s", err)
119+
} else if !cached {
120+
return false, nil
99121
}
100-
if stats.Size() > release.Size {
101-
return errors.New("Archive size does not match with specification of this release, assuming corruption")
122+
123+
if ok, err := r.TestLocalArchiveSize(); err != nil {
124+
return false, fmt.Errorf("teting archive size: %s", err)
125+
} else if !ok {
126+
return false, nil
102127
}
103-
if !checksumMatches(release) {
104-
return errors.New("Checksum does not match, assuming corruption")
128+
129+
ok, err := r.TestLocalArchiveChecksum()
130+
if err != nil {
131+
return false, fmt.Errorf("testing archive checksum: %s", err)
105132
}
106-
return nil
133+
return ok, nil
107134
}
108135

109136
const (

common/releases/helpers.go

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -39,17 +39,6 @@ import (
3939
"github.com/sirupsen/logrus"
4040
)
4141

42-
// IsCached returns a bool representing if the release has already been downloaded
43-
func IsCached(release *DownloadResource) bool {
44-
archivePath, err := release.ArchivePath()
45-
if err != nil {
46-
return false
47-
}
48-
49-
_, err = os.Stat(archivePath)
50-
return !os.IsNotExist(err)
51-
}
52-
5342
// downloadRelease downloads a generic release.
5443
//
5544
// PARAMS:
@@ -72,8 +61,11 @@ func downloadRelease(item *DownloadResource, progressChangedHandler common.Downl
7261
if err != nil {
7362
return err
7463
}
75-
err = checkLocalArchive(item)
64+
ok, err := item.TestLocalArchiveIntegrity()
7665
if err != nil {
66+
return fmt.Errorf("testing local archive integrity: %s", err)
67+
}
68+
if !ok {
7769
return errors.New("Archive has been downloaded, but it seems corrupted. Try again to redownload it")
7870
}
7971
return nil
@@ -126,9 +118,19 @@ func ParallelDownload(items map[string]*DownloadResource, forced bool,
126118
logrus.Info(fmt.Sprintf("Initiating parallel download of %d resources", len(items)))
127119

128120
for itemName, item := range items {
129-
cached := IsCached(item)
130-
releaseNotNil := item != nil
131-
if forced || releaseNotNil && (!cached || checkLocalArchive(item) != nil) {
121+
if item == nil {
122+
continue
123+
}
124+
cached := false
125+
if !forced {
126+
if c, err := item.IsCached(); err != nil {
127+
res[itemName] = &DownloadResult{Error: fmt.Errorf("detecting if item is cached:%s", err)}
128+
continue
129+
} else {
130+
cached = c
131+
}
132+
}
133+
if forced || !cached {
132134
// Notify the progress handler of the new task
133135
if progressHandler != nil {
134136
progressHandler.OnNewDownloadTask(itemName, item.Size)
@@ -146,7 +148,7 @@ func ParallelDownload(items map[string]*DownloadResource, forced bool,
146148
}
147149

148150
tasks[itemName] = downloadTask(item, getProgressHandler(itemName))
149-
} else if !forced && releaseNotNil && cached {
151+
} else {
150152
// Item already downloaded
151153
res[itemName] = &DownloadResult{AlreadyDownloaded: true}
152154
}

0 commit comments

Comments
 (0)