params: add DependencyOrder function

This commit is contained in:
Felix Lange 2025-07-24 12:30:40 +02:00
parent 13d14f5ab8
commit cf8af42646
2 changed files with 64 additions and 0 deletions

View file

@ -75,6 +75,43 @@ func (f *Fork) MarshalText() ([]byte, error) {
return []byte(f.configName), nil return []byte(f.configName), nil
} }
// DependencyOrder computes an ordering of the given forks, according to their dependencies.
// Note the resulting ordering may not be unique!
func DependencyOrder(list []Fork) []Fork {
var (
inList = make(map[Fork]bool, len(list))
visiting = make(map[Fork]bool, len(list))
mark = make(map[Fork]bool, len(list))
result = make([]Fork, 0, len(list))
)
for _, f := range list {
inList[f] = true
}
var visit func(Fork)
visit = func(f Fork) {
if mark[f] {
return
}
if visiting[f] {
// This can't happen because we check for cycles at definition time.
panic("fork dependency cycle")
}
visiting[f] = true
for _, dep := range f.directDeps {
visit(dep)
}
mark[f] = true
if inList[f] {
result = append(result, f)
}
}
for _, l := range list {
visit(l)
}
return result
}
type forkProperties struct { type forkProperties struct {
name string name string
configName string configName string

View file

@ -17,6 +17,7 @@
package forks package forks
import ( import (
"slices"
"testing" "testing"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
@ -48,3 +49,29 @@ func TestForkName(t *testing.T) {
t.Fatal("wrong fork found by name cancun") t.Fatal("wrong fork found by name cancun")
} }
} }
func TestForkDependencyOrder(t *testing.T) {
tests := []struct {
list, result []Fork
}{
{
list: []Fork{},
result: []Fork{},
},
{
list: []Fork{BPO2, Homestead, Cancun, London, Paris},
result: []Fork{Homestead, London, Paris, Cancun, BPO2},
},
{
list: []Fork{BPO3, Osaka, Cancun, Prague, BPO1, BPO2},
result: []Fork{Cancun, Prague, Osaka, BPO1, BPO2, BPO3},
},
}
for _, test := range tests {
res := DependencyOrder(test.list)
if !slices.Equal(res, test.result) {
t.Errorf("DependencyOrder(%v) -> %v\n want: %v", test.list, res, test.result)
}
}
}