tidy our build ID hash code a bit

First, rename "component" to "hash", since it's shorter and more useful.
A full build ID is two or four hashes joined with slashes.

Second, add sanity checks that buildIDHashLength is being followed.
Otherwise the use of []byte could lead to human error.

Third, move all the hash encoding and decoding logic together.
pull/745/head
Daniel Martí 1 year ago
parent 0c9a59127a
commit 414e3b7f70

@ -20,26 +20,40 @@ import (
const buildIDSeparator = "/"
// splitActionID returns the action ID half of a build ID, the first component.
// splitActionID returns the action ID half of a build ID, the first hash.
func splitActionID(buildID string) string {
return buildID[:strings.Index(buildID, buildIDSeparator)]
}
// splitContentID returns the content ID half of a build ID, the last component.
// splitContentID returns the content ID half of a build ID, the last hash.
func splitContentID(buildID string) string {
return buildID[strings.LastIndex(buildID, buildIDSeparator)+1:]
}
// decodeHash is the opposite of hashToString, with a panic for error handling
// since it should never happen.
func decodeHash(str string) []byte {
// buildIDHashLength is the number of bytes each build ID hash takes,
// such as an action ID or a content ID.
const buildIDHashLength = 15
// decodeBuildIDHash decodes a build ID hash in base64, just like cmd/go does.
func decodeBuildIDHash(str string) []byte {
h, err := base64.RawURLEncoding.DecodeString(str)
if err != nil {
panic(fmt.Sprintf("invalid hash %q: %v", str, err))
}
if len(h) != buildIDHashLength {
panic(fmt.Sprintf("decodeHash expects to result in a hash of length %d, got %d", buildIDHashLength, len(h)))
}
return h
}
// encodeBuildIDHash encodes a build ID hash in base64, just like cmd/go does.
func encodeBuildIDHash(h []byte) string {
if len(h) != buildIDHashLength {
panic(fmt.Sprintf("hashToString expects a hash of length %d, got %d", buildIDHashLength, len(h)))
}
return base64.RawURLEncoding.EncodeToString(h)
}
func alterToolVersion(tool string, args []string) error {
cmd := exec.Command(args[0], args[1:]...)
out, err := cmd.Output()
@ -57,7 +71,7 @@ func alterToolVersion(tool string, args []string) error {
var toolID []byte
if f[2] == "devel" {
// On the development branch, use the content ID part of the build ID.
toolID = decodeHash(splitContentID(f[len(f)-1]))
toolID = decodeBuildIDHash(splitContentID(f[len(f)-1]))
} else {
// For a release, the output is like: "compile version go1.9.1 X:framepointer".
// Use the whole line, as we can assume it's unique.
@ -70,9 +84,9 @@ func alterToolVersion(tool string, args []string) error {
// the action (build) or not. Since cmd/go parses the last word in the
// output as "buildID=...", we simply add "+garble buildID=_/_/_/${hash}".
// The slashes let us imitate a full binary build ID, but we assume that
// the other components such as the action ID are not necessary, since the
// the other hashes such as the action ID are not necessary, since the
// only reader here is cmd/go and it only consumes the content ID.
fmt.Printf("%s +garble buildID=_/_/_/%s\n", line, hashToString(contentID))
fmt.Printf("%s +garble buildID=_/_/_/%s\n", line, encodeBuildIDHash(contentID))
return nil
}
@ -106,7 +120,7 @@ func addGarbleToHash(inputHash []byte) []byte {
// addGarbleToHash returns the sum buffer, so we need a new copy.
// Otherwise the next use of the global sumBuffer would conflict.
sumBuffer := make([]byte, 0, sha256.Size)
return hasher.Sum(sumBuffer)[:buildIDComponentLength]
return hasher.Sum(sumBuffer)[:buildIDHashLength]
}
// appendFlags writes garble's own flags to w in string form.
@ -151,16 +165,6 @@ func appendFlags(w io.Writer, forBuildHash bool) {
}
}
// buildIDComponentLength is the number of bytes each build ID component takes,
// such as an action ID or a content ID.
const buildIDComponentLength = 15
// hashToString encodes the first 120 bits of a sha256 sum in base64, the same
// format used for components in a build ID.
func hashToString(h []byte) string {
return base64.RawURLEncoding.EncodeToString(h[:buildIDComponentLength])
}
func buildidOf(path string) (string, error) {
cmd := exec.Command("go", "tool", "buildid", path)
out, err := cmd.Output()

@ -536,7 +536,7 @@ This command wraps "go %s". Below is its help:
if err != nil {
return nil, err
}
sharedCache.BinaryContentID = decodeHash(splitContentID(binaryBuildID))
sharedCache.BinaryContentID = decodeBuildIDHash(splitContentID(binaryBuildID))
if err := appendListedPackages(args, true); err != nil {
return nil, err
@ -1015,7 +1015,7 @@ func transformCompile(args []string) ([]string, error) {
// as we end up with extra near-duplicate cached artifacts.
if i == 0 {
src = append(src, fmt.Sprintf(
"\nvar garbleActionID = %q\n", hashToString(curPkg.GarbleActionID),
"\nvar garbleActionID = %q\n", encodeBuildIDHash(curPkg.GarbleActionID),
)...)
}
@ -1331,7 +1331,7 @@ func garbleExportFile(pkg *listedPackage) string {
if trimmed == pkg.Export {
panic(fmt.Sprintf("unexpected export path of %s: %q", pkg.ImportPath, pkg.Export))
}
return trimmed + "-garble-" + hashToString(pkg.GarbleActionID) + "-d"
return trimmed + "-garble-" + encodeBuildIDHash(pkg.GarbleActionID) + "-d"
}
func loadCachedOutputs() error {

@ -319,7 +319,7 @@ func appendListedPackages(packages []string, mainBuild bool) error {
return fmt.Errorf("duplicate package: %q", pkg.ImportPath)
}
if pkg.BuildID != "" {
actionID := decodeHash(splitActionID(pkg.BuildID))
actionID := decodeBuildIDHash(splitActionID(pkg.BuildID))
pkg.GarbleActionID = addGarbleToHash(actionID)
}

Loading…
Cancel
Save