Skip to content

Commit 1dcaf8f

Browse files
committed
fix: combine outputs when using bit -D deps
Previously each output had a complete copy of identical inputs for the sam target.
1 parent 77368bc commit 1dcaf8f

File tree

3 files changed

+47
-5
lines changed

3 files changed

+47
-5
lines changed

cmd/bit/main.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"path/filepath"
99
"runtime"
1010
"runtime/pprof"
11+
"sort"
1112
"strings"
1213

1314
"github.com/alecthomas/kong"
@@ -81,6 +82,7 @@ func main() {
8182

8283
case cli.Describe == "deps":
8384
deps := eng.Deps()
85+
deps = mergeDepsWithCommonInputs(deps)
8486
for in, deps := range deps {
8587
w := len(in) + 1
8688
fmt.Printf("%s:", in)
@@ -93,6 +95,7 @@ func main() {
9395
fmt.Printf(" %s", dep)
9496
}
9597
fmt.Println()
98+
fmt.Println()
9699
}
97100

98101
case cli.Describe == "files":
@@ -153,3 +156,18 @@ func reportError(file *os.File, logger *logging.Logger, err error) {
153156
}
154157
os.Exit(1)
155158
}
159+
func mergeDepsWithCommonInputs(deps map[string][]string) map[string][]string {
160+
inputHashes := map[engine.Hasher][]string{}
161+
for output, inputs := range deps {
162+
sort.Strings(inputs)
163+
hasher := engine.NewHasher()
164+
engine.HashSlice(&hasher, inputs)
165+
inputHashes[hasher] = append(inputHashes[hasher], output)
166+
}
167+
merged := map[string][]string{}
168+
for _, outputs := range inputHashes {
169+
key := strings.Join(outputs, " \\\n")
170+
merged[key] = deps[outputs[0]]
171+
}
172+
return merged
173+
}

engine/engine.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -542,7 +542,7 @@ func (e *Engine) dbRefHasher(target *Target, ref *parser.Ref) (Hasher, error) {
542542
// Hash real files.
543543
func (e *Engine) realRefHasher(target *Target, ref *parser.Ref) (Hasher, error) {
544544
h := NewHasher()
545-
h.string(ref.Text)
545+
h.Str(ref.Text)
546546

547547
// If we have a hash function, use that for every reference.
548548
if target.hashFunc != nil {

engine/hasher.go

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,33 @@ const prime64 = 1099511628211
1010

1111
type Hasher uint64
1212

13+
// HashSlice hashes a slice of strings, uint64s, byte slices or Hashers.
14+
func HashSlice[T string | uint64 | []byte | Hasher](hasher *Hasher, slice []T) {
15+
switch slice := any(slice).(type) {
16+
case []string:
17+
for _, s := range slice {
18+
hasher.Str(s)
19+
}
20+
case []uint64:
21+
for _, s := range slice {
22+
hasher.Int(s)
23+
}
24+
case [][]byte:
25+
for _, s := range slice {
26+
hasher.Bytes(s)
27+
}
28+
case []Hasher:
29+
for _, s := range slice {
30+
hasher.Update(s)
31+
}
32+
default:
33+
panic(fmt.Sprintf("unexpected type %T", slice))
34+
}
35+
}
36+
1337
func NewHasher() Hasher { return offset64 }
1438

15-
// Update the hash with a uint64.
39+
// Int updates the hash with a uint64.
1640
func (h *Hasher) Int(data uint64) {
1741
f := *h
1842
f ^= Hasher(data)
@@ -28,8 +52,8 @@ func (h *Hasher) Update(other Hasher) {
2852
*h = f
2953
}
3054

31-
// Update the hash with a string.
32-
func (h *Hasher) string(data string) {
55+
// Str updates the hash with a Str.
56+
func (h *Hasher) Str(data string) {
3357
f := *h
3458
for _, c := range data {
3559
f ^= Hasher(c)
@@ -38,7 +62,7 @@ func (h *Hasher) string(data string) {
3862
*h = f
3963
}
4064

41-
// Update the hash with a byte slice.
65+
// Bytes updates the hash with a byte slice.
4266
func (h *Hasher) Bytes(data []byte) {
4367
f := *h
4468
for _, c := range data {

0 commit comments

Comments
 (0)