Skip to content

Commit 615c7c1

Browse files
progggaJay Conrod
authored and
Jay Conrod
committed
cmd/buildid: move and reuse duplicated HashToString code to cmd/internal/buildid/buildid
Change-Id: I1e1ac770d4aac12d7d7ec57ef95f77a3e14a678c GitHub-Last-Rev: c01db43 GitHub-Pull-Request: #42052 Reviewed-on: https://go-review.googlesource.com/c/go/+/263418 Run-TryBot: Jay Conrod <[email protected]> TryBot-Result: Go Bot <[email protected]> Reviewed-by: Jay Conrod <[email protected]> Trust: Jay Conrod <[email protected]> Trust: Michael Matloob <[email protected]>
1 parent 49a210e commit 615c7c1

File tree

3 files changed

+32
-51
lines changed

3 files changed

+32
-51
lines changed

src/cmd/buildid/buildid.go

Lines changed: 2 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -22,21 +22,6 @@ func usage() {
2222

2323
var wflag = flag.Bool("w", false, "write build ID")
2424

25-
// taken from cmd/go/internal/work/buildid.go
26-
func hashToString(h [32]byte) string {
27-
const b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"
28-
const chunks = 5
29-
var dst [chunks * 4]byte
30-
for i := 0; i < chunks; i++ {
31-
v := uint32(h[3*i])<<16 | uint32(h[3*i+1])<<8 | uint32(h[3*i+2])
32-
dst[4*i+0] = b64[(v>>18)&0x3F]
33-
dst[4*i+1] = b64[(v>>12)&0x3F]
34-
dst[4*i+2] = b64[(v>>6)&0x3F]
35-
dst[4*i+3] = b64[v&0x3F]
36-
}
37-
return string(dst[:])
38-
}
39-
4025
func main() {
4126
log.SetPrefix("buildid: ")
4227
log.SetFlags(0)
@@ -63,12 +48,12 @@ func main() {
6348
log.Fatal(err)
6449
}
6550
matches, hash, err := buildid.FindAndHash(f, id, 0)
51+
f.Close()
6652
if err != nil {
6753
log.Fatal(err)
6854
}
69-
f.Close()
7055

71-
newID := id[:strings.LastIndex(id, "/")] + "/" + hashToString(hash)
56+
newID := id[:strings.LastIndex(id, "/")] + "/" + buildid.HashToString(hash)
7257
if len(newID) != len(id) {
7358
log.Fatalf("%s: build ID length mismatch %q vs %q", file, id, newID)
7459
}

src/cmd/go/internal/work/buildid.go

Lines changed: 5 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ import (
3131
//
3232
// actionID/[.../]contentID
3333
//
34-
// where the actionID and contentID are prepared by hashToString below.
34+
// where the actionID and contentID are prepared by buildid.HashToString below.
3535
// and are found by looking for the first or last slash.
3636
// Usually the buildID is simply actionID/contentID, but see below for an
3737
// exception.
@@ -108,31 +108,6 @@ func contentID(buildID string) string {
108108
return buildID[strings.LastIndex(buildID, buildIDSeparator)+1:]
109109
}
110110

111-
// hashToString converts the hash h to a string to be recorded
112-
// in package archives and binaries as part of the build ID.
113-
// We use the first 120 bits of the hash (5 chunks of 24 bits each) and encode
114-
// it in base64, resulting in a 20-byte string. Because this is only used for
115-
// detecting the need to rebuild installed files (not for lookups
116-
// in the object file cache), 120 bits are sufficient to drive the
117-
// probability of a false "do not need to rebuild" decision to effectively zero.
118-
// We embed two different hashes in archives and four in binaries,
119-
// so cutting to 20 bytes is a significant savings when build IDs are displayed.
120-
// (20*4+3 = 83 bytes compared to 64*4+3 = 259 bytes for the
121-
// more straightforward option of printing the entire h in base64).
122-
func hashToString(h [cache.HashSize]byte) string {
123-
const b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"
124-
const chunks = 5
125-
var dst [chunks * 4]byte
126-
for i := 0; i < chunks; i++ {
127-
v := uint32(h[3*i])<<16 | uint32(h[3*i+1])<<8 | uint32(h[3*i+2])
128-
dst[4*i+0] = b64[(v>>18)&0x3F]
129-
dst[4*i+1] = b64[(v>>12)&0x3F]
130-
dst[4*i+2] = b64[(v>>6)&0x3F]
131-
dst[4*i+3] = b64[v&0x3F]
132-
}
133-
return string(dst[:])
134-
}
135-
136111
// toolID returns the unique ID to use for the current copy of the
137112
// named tool (asm, compile, cover, link).
138113
//
@@ -404,7 +379,7 @@ func (b *Builder) fileHash(file string) string {
404379
if err != nil {
405380
return ""
406381
}
407-
return hashToString(sum)
382+
return buildid.HashToString(sum)
408383
}
409384

410385
// useCache tries to satisfy the action a, which has action ID actionHash,
@@ -427,7 +402,7 @@ func (b *Builder) useCache(a *Action, actionHash cache.ActionID, target string)
427402
// the actionID half; if it also appeared in the input that would be like an
428403
// engineered 120-bit partial SHA256 collision.
429404
a.actionID = actionHash
430-
actionID := hashToString(actionHash)
405+
actionID := buildid.HashToString(actionHash)
431406
if a.json != nil {
432407
a.json.ActionID = actionID
433408
}
@@ -480,7 +455,7 @@ func (b *Builder) useCache(a *Action, actionHash cache.ActionID, target string)
480455
// build IDs of completed actions.
481456
oldBuildID := a.buildID
482457
a.buildID = id[1] + buildIDSeparator + id[2]
483-
linkID := hashToString(b.linkActionID(a.triggers[0]))
458+
linkID := buildid.HashToString(b.linkActionID(a.triggers[0]))
484459
if id[0] == linkID {
485460
// Best effort attempt to display output from the compile and link steps.
486461
// If it doesn't work, it doesn't work: reusing the cached binary is more
@@ -654,7 +629,7 @@ func (b *Builder) updateBuildID(a *Action, target string, rewrite bool) error {
654629
if err != nil {
655630
return err
656631
}
657-
newID := a.buildID[:strings.LastIndex(a.buildID, buildIDSeparator)] + buildIDSeparator + hashToString(hash)
632+
newID := a.buildID[:strings.LastIndex(a.buildID, buildIDSeparator)] + buildIDSeparator + buildid.HashToString(hash)
658633
if len(newID) != len(a.buildID) {
659634
return fmt.Errorf("internal error: build ID length mismatch %q vs %q", a.buildID, newID)
660635
}

src/cmd/internal/buildid/buildid.go

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,8 @@ import (
1717
)
1818

1919
var (
20-
errBuildIDToolchain = fmt.Errorf("build ID only supported in gc toolchain")
2120
errBuildIDMalformed = fmt.Errorf("malformed object file")
22-
errBuildIDUnknown = fmt.Errorf("lost build ID")
23-
)
2421

25-
var (
2622
bangArch = []byte("!<arch>")
2723
pkgdef = []byte("__.PKGDEF")
2824
goobject = []byte("go object ")
@@ -320,3 +316,28 @@ func readRaw(name string, data []byte) (id string, err error) {
320316
}
321317
return id, nil
322318
}
319+
320+
// HashToString converts the hash h to a string to be recorded
321+
// in package archives and binaries as part of the build ID.
322+
// We use the first 120 bits of the hash (5 chunks of 24 bits each) and encode
323+
// it in base64, resulting in a 20-byte string. Because this is only used for
324+
// detecting the need to rebuild installed files (not for lookups
325+
// in the object file cache), 120 bits are sufficient to drive the
326+
// probability of a false "do not need to rebuild" decision to effectively zero.
327+
// We embed two different hashes in archives and four in binaries,
328+
// so cutting to 20 bytes is a significant savings when build IDs are displayed.
329+
// (20*4+3 = 83 bytes compared to 64*4+3 = 259 bytes for the
330+
// more straightforward option of printing the entire h in base64).
331+
func HashToString(h [32]byte) string {
332+
const b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"
333+
const chunks = 5
334+
var dst [chunks * 4]byte
335+
for i := 0; i < chunks; i++ {
336+
v := uint32(h[3*i])<<16 | uint32(h[3*i+1])<<8 | uint32(h[3*i+2])
337+
dst[4*i+0] = b64[(v>>18)&0x3F]
338+
dst[4*i+1] = b64[(v>>12)&0x3F]
339+
dst[4*i+2] = b64[(v>>6)&0x3F]
340+
dst[4*i+3] = b64[v&0x3F]
341+
}
342+
return string(dst[:])
343+
}

0 commit comments

Comments
 (0)