Skip to content

Commit

Permalink
chore: refactor sha validation
Browse files Browse the repository at this point in the history
Signed-off-by: Abiola Ibrahim <[email protected]>
  • Loading branch information
abiosoft committed Dec 16, 2024
1 parent 5335a69 commit bfe02bf
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 53 deletions.
54 changes: 1 addition & 53 deletions util/downloader/download.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
"os"
"path"
"path/filepath"
"strconv"
"strings"

"github.com/abiosoft/colima/config"
Expand All @@ -19,57 +18,6 @@ type (
guestActions = environment.GuestActions
)

type SHA struct {
URL string // url to download the shasum file (if Digest is empty)
Size int // one of 256 or 512
Digest string // shasum
}

func (s SHA) validate(host hostActions, url, cacheFilename string) error {
if s.URL == "" && s.Digest == "" {
return fmt.Errorf("error validating SHA: one of Digest or URL must be set")
}

if s.Digest != "" {
s.Digest = strings.TrimPrefix(s.Digest, fmt.Sprintf("sha%d:", s.Size))
}

filename := func() string {
if url == "" {
return ""
}
split := strings.Split(url, "/")
return split[len(split)-1]
}()
dir, cacheFilename := filepath.Split(cacheFilename)

var script string

if s.Digest == "" {
script = strings.NewReplacer(
"{dir}", dir,
"{url}", s.URL,
"{filename}", filename,
"{size}", strconv.Itoa(s.Size),
"{cache_filename}", cacheFilename,
).Replace(
`cd {dir} && echo "$(curl -sL {url} | grep ' {filename}$' | awk -F' ' '{print $1}') {cache_filename}" | shasum -a {size} --check --status`,
)
} else {
script = strings.NewReplacer(
"{dir}", dir,
"{digest}", s.Digest,
"{filename}", filename,
"{size}", strconv.Itoa(s.Size),
"{cache_filename}", cacheFilename,
).Replace(
`cd {dir} && echo "{digest} {cache_filename}" | shasum -a {size} --check --status`,
)
}

return host.Run("sh", "-c", script)
}

// Request is download request
type Request struct {
URL string // request URL
Expand Down Expand Up @@ -146,7 +94,7 @@ func (d downloader) downloadFile(r Request) (err error) {

// validate download if sha is present
if r.SHA != nil {
if err := r.SHA.validate(d.host, r.URL, cacheDownloadingFilename); err != nil {
if err := r.SHA.validateDownload(d.host, r.URL, cacheDownloadingFilename); err != nil {

// move file to allow subsequent re-download
// error discarded, would not be actioned anyways
Expand Down
75 changes: 75 additions & 0 deletions util/downloader/sha.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package downloader

import (
"fmt"
"path/filepath"
"strconv"
"strings"
)

// SHA is the shasum of a file.
type SHA struct {
Digest string // shasum
URL string // url to download the shasum file (if Digest is empty)
Size int // one of 256 or 512
}

// Validate validates the SHA of the file.
func (s SHA) Validate(host hostActions, file string) error {
dir, filename := filepath.Split(file)

script := strings.NewReplacer(
"{dir}", dir,
"{digest}", s.Digest,
"{size}", strconv.Itoa(s.Size),
"{filename}", filename,
).Replace(
`cd {dir} && echo "{digest} {filename}" | shasum -a {size} --check --status`,
)

return host.Run("sh", "-c", script)
}

func (s SHA) validateDownload(host hostActions, url string, filename string) error {
if s.URL == "" && s.Digest == "" {
return fmt.Errorf("error validating SHA: one of Digest or URL must be set")
}

if s.Digest != "" {
s.Digest = strings.TrimPrefix(s.Digest, fmt.Sprintf("sha%d:", s.Size))
}

// fetch digest from URL if empty
if s.Digest == "" {
// retrieve the filename from the download url.
filename := func() string {
if url == "" {
return ""
}
split := strings.Split(url, "/")
return split[len(split)-1]
}()

digest, err := fetchSHAFromURL(host, s.URL, filename)
if err != nil {
return err
}
s.Digest = digest
}

return s.Validate(host, filename)
}

func fetchSHAFromURL(host hostActions, url, filename string) (string, error) {
script := strings.NewReplacer(
"{url}", url,
"{filename}", filename,
).Replace(
"curl -sL {url} | grep ' {filename}$' | awk -F' ' '{print $1}'",
)
sha, err := host.RunOutput("sh", "-c", script)
if err != nil {
return "", fmt.Errorf("error retrieving sha from url '%s': %w", url, err)
}
return strings.TrimSpace(sha), nil
}

0 comments on commit bfe02bf

Please sign in to comment.