2022-11-10 09:20:10 -05:00
|
|
|
/*
|
|
|
|
Copyright (c) Edgeless Systems GmbH
|
|
|
|
|
|
|
|
SPDX-License-Identifier: AGPL-3.0-only
|
|
|
|
*/
|
|
|
|
|
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"context"
|
|
|
|
"crypto/sha256"
|
|
|
|
"fmt"
|
|
|
|
"go/ast"
|
|
|
|
"go/parser"
|
|
|
|
"go/printer"
|
|
|
|
"go/token"
|
|
|
|
"io"
|
|
|
|
"log"
|
|
|
|
"net/http"
|
|
|
|
"os"
|
|
|
|
|
|
|
|
"golang.org/x/tools/go/ast/astutil"
|
|
|
|
)
|
|
|
|
|
|
|
|
func mustGetHash(url string) string {
|
|
|
|
// remove quotes around url
|
|
|
|
url = url[1 : len(url)-1]
|
|
|
|
|
|
|
|
// Get the data
|
|
|
|
req, err := http.NewRequestWithContext(context.Background(), http.MethodGet, url, nil)
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
resp, err := http.DefaultClient.Do(req)
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
defer resp.Body.Close()
|
|
|
|
|
|
|
|
// Check server response
|
|
|
|
if resp.StatusCode != http.StatusOK {
|
|
|
|
panic("bad status: " + resp.Status)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Generate SHA256 hash of the file
|
|
|
|
sha := sha256.New()
|
|
|
|
if _, err := io.Copy(sha, resp.Body); err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
fileHash := sha.Sum(nil)
|
|
|
|
|
|
|
|
// Get upstream hash
|
2023-01-10 12:07:46 -05:00
|
|
|
req, err = http.NewRequestWithContext(context.Background(), http.MethodGet, url+".sha256", http.NoBody)
|
2022-11-10 09:20:10 -05:00
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
resp, err = http.DefaultClient.Do(req)
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
defer resp.Body.Close()
|
|
|
|
|
|
|
|
// Check server response
|
|
|
|
if resp.StatusCode != http.StatusOK {
|
|
|
|
panic("bad status: " + resp.Status)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Compare hashes
|
|
|
|
|
|
|
|
// Take the first 64 ascii characters = 32 bytes.
|
|
|
|
// Some .sha256 files contain additional information afterwards.
|
|
|
|
upstreamHash := make([]byte, 64)
|
|
|
|
if _, err = resp.Body.Read(upstreamHash); err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
if string(upstreamHash) != fmt.Sprintf("%x", fileHash) {
|
|
|
|
panic("hash mismatch")
|
|
|
|
}
|
|
|
|
|
|
|
|
return fmt.Sprintf("\"sha256:%x\"", fileHash)
|
|
|
|
}
|
|
|
|
|
|
|
|
func main() {
|
|
|
|
fmt.Println("Generating hashes...")
|
|
|
|
|
|
|
|
const filePath = "./versions.go"
|
|
|
|
|
|
|
|
fset := token.NewFileSet()
|
|
|
|
file, err := parser.ParseFile(fset, filePath, nil, parser.ParseComments)
|
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
|
2023-01-10 12:07:46 -05:00
|
|
|
var componentListsCtr, componentCtr int
|
|
|
|
|
2022-11-10 09:20:10 -05:00
|
|
|
newFile := astutil.Apply(file, func(cursor *astutil.Cursor) bool {
|
|
|
|
n := cursor.Node()
|
|
|
|
|
2023-01-10 12:07:46 -05:00
|
|
|
//
|
|
|
|
// Find CompositeLit of type 'components.Components'
|
|
|
|
//
|
|
|
|
comp, ok := n.(*ast.CompositeLit)
|
|
|
|
if !ok {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
selExpr, ok := comp.Type.(*ast.SelectorExpr)
|
|
|
|
if !ok {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
if selExpr.Sel.Name != "Components" {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
xIdent, ok := selExpr.X.(*ast.Ident)
|
|
|
|
if !ok {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
if xIdent.Name != "components" {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
componentListsCtr++
|
|
|
|
|
|
|
|
//
|
|
|
|
// Iterate over the components
|
|
|
|
//
|
|
|
|
for _, componentElt := range comp.Elts {
|
|
|
|
component := componentElt.(*ast.CompositeLit)
|
|
|
|
componentCtr++
|
|
|
|
|
|
|
|
var url *ast.KeyValueExpr
|
|
|
|
var hash *ast.KeyValueExpr
|
|
|
|
|
|
|
|
for _, e := range component.Elts {
|
|
|
|
kv, ok := e.(*ast.KeyValueExpr)
|
|
|
|
if !ok {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
ident, ok := kv.Key.(*ast.Ident)
|
|
|
|
if !ok {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
switch ident.Name {
|
|
|
|
case "URL":
|
|
|
|
url = kv
|
|
|
|
case "Hash":
|
|
|
|
hash = kv
|
2022-11-14 13:09:49 -05:00
|
|
|
}
|
2022-11-10 09:20:10 -05:00
|
|
|
}
|
2023-01-10 12:07:46 -05:00
|
|
|
|
|
|
|
fmt.Println("Generating hash for", url.Value.(*ast.BasicLit).Value)
|
|
|
|
hash.Value.(*ast.BasicLit).Value = mustGetHash(url.Value.(*ast.BasicLit).Value)
|
2022-11-10 09:20:10 -05:00
|
|
|
}
|
2023-01-10 12:07:46 -05:00
|
|
|
|
2022-11-10 09:20:10 -05:00
|
|
|
return true
|
|
|
|
}, nil,
|
|
|
|
)
|
|
|
|
|
|
|
|
var buf bytes.Buffer
|
|
|
|
printConfig := printer.Config{Mode: printer.UseSpaces | printer.TabIndent, Tabwidth: 8}
|
|
|
|
|
|
|
|
if err = printConfig.Fprint(&buf, fset, newFile); err != nil {
|
|
|
|
log.Fatalf("error formatting file %s: %s", filePath, err)
|
|
|
|
}
|
|
|
|
if err := os.WriteFile(filePath, buf.Bytes(), 0o644); err != nil {
|
|
|
|
log.Fatalf("error writing file %s: %s", filePath, err)
|
|
|
|
}
|
2023-01-10 12:07:46 -05:00
|
|
|
if componentCtr == 0 {
|
|
|
|
log.Fatalf("no components lists found")
|
|
|
|
}
|
|
|
|
|
2023-01-10 12:08:31 -05:00
|
|
|
fmt.Printf("Successfully generated hashes for %d components in %d component lists.\n", componentCtr, componentListsCtr)
|
2022-11-10 09:20:10 -05:00
|
|
|
}
|