57 lines
1.4 KiB
Go
57 lines
1.4 KiB
Go
package nix
|
|
|
|
import (
|
|
"path"
|
|
"slices"
|
|
)
|
|
|
|
// this is pretty close to zero copy for the test case
|
|
const collectFromDerivationsInitialCap = 1 << 17
|
|
|
|
// CollectFromDerivations returns a deduplicated slice of store paths collected from derivations.
|
|
func CollectFromDerivations(derivations DerivationMap) []string {
|
|
var setpointSize, growToCap int
|
|
collective := make([]string, 0, collectFromDerivationsInitialCap)
|
|
for p, drv := range derivations {
|
|
if drv == nil {
|
|
// should be unreachable
|
|
continue
|
|
}
|
|
|
|
// another exponentially growing buffer here because range over map is expensive
|
|
setpointSize = len(collective) + len(drv.InputSources) +
|
|
// only map keys
|
|
len(drv.InputDerivations) +
|
|
// only Output.Path
|
|
len(drv.Outputs) +
|
|
// self, builder
|
|
2
|
|
if setpointSize > cap(collective) {
|
|
growToCap = cap(collective) << 1
|
|
tryGrow:
|
|
if setpointSize > growToCap {
|
|
// unlikely to be reached
|
|
growToCap <<= 1
|
|
goto tryGrow
|
|
}
|
|
|
|
collective = slices.Grow(collective, growToCap-cap(collective))
|
|
}
|
|
|
|
collective = append(collective, drv.InputSources...)
|
|
for s := range drv.InputDerivations {
|
|
collective = append(collective, s)
|
|
}
|
|
for _, out := range drv.Outputs {
|
|
collective = append(collective, out.Path)
|
|
}
|
|
collective = append(collective, p)
|
|
if path.IsAbs(drv.Builder) { // so builtins don't get collected
|
|
collective = append(collective, drv.Builder)
|
|
}
|
|
}
|
|
|
|
slices.Sort(collective)
|
|
return slices.Compact(collective)
|
|
}
|