@@ -25,16 +25,20 @@ import (
25
25
"os"
26
26
"os/exec"
27
27
"path/filepath"
28
+ "sort"
28
29
"strings"
29
30
31
+ flag "github.com/spf13/pflag"
32
+ "gonum.org/v1/gonum/graph"
33
+ "gonum.org/v1/gonum/graph/simple"
34
+ "gonum.org/v1/gonum/graph/topo"
35
+
30
36
"k8s.io/code-generator/pkg/util"
31
37
"k8s.io/gengo/args"
32
38
"k8s.io/gengo/generator"
33
39
"k8s.io/gengo/namer"
34
40
"k8s.io/gengo/parser"
35
41
"k8s.io/gengo/types"
36
-
37
- flag "github.com/spf13/pflag"
38
42
)
39
43
40
44
type Generator struct {
@@ -202,6 +206,18 @@ func Run(g *Generator) {
202
206
c .Verify = g .Common .VerifyOnly
203
207
c .FileTypes ["protoidl" ] = NewProtoFile ()
204
208
209
+ // order package by imports, importees first
210
+ deps := deps (c , protobufNames .packages )
211
+ order , err := importOrder (deps )
212
+ if err != nil {
213
+ log .Fatalf ("Failed to order packages by imports: %v" , err )
214
+ }
215
+ topologicalPos := map [string ]int {}
216
+ for i , p := range order {
217
+ topologicalPos [p ] = i
218
+ }
219
+ sort .Sort (positionOrder {topologicalPos , protobufNames .packages })
220
+
205
221
var vendoredOutputPackages , localOutputPackages generator.Packages
206
222
for _ , p := range protobufNames .packages {
207
223
if _ , ok := nonOutputPackages [p .Name ()]; ok {
@@ -347,3 +363,66 @@ func Run(g *Generator) {
347
363
}
348
364
}
349
365
}
366
+
367
+ func deps (c * generator.Context , pkgs []* protobufPackage ) map [string ][]string {
368
+ ret := map [string ][]string {}
369
+ for _ , p := range pkgs {
370
+ for _ , d := range c .Universe [p .PackagePath ].Imports {
371
+ ret [p .PackagePath ] = append (ret [p .PackagePath ], d .Path )
372
+ }
373
+ }
374
+ return ret
375
+ }
376
+
377
+ func importOrder (deps map [string ][]string ) ([]string , error ) {
378
+ nodes := map [string ]graph.Node {}
379
+ names := map [int64 ]string {}
380
+ g := simple .NewDirectedGraph ()
381
+ for pkg , imports := range deps {
382
+ for _ , imp := range imports {
383
+ if _ , found := nodes [pkg ]; ! found {
384
+ n := g .NewNode ()
385
+ g .AddNode (n )
386
+ nodes [pkg ] = n
387
+ names [n .ID ()] = pkg
388
+ }
389
+ if _ , found := nodes [imp ]; ! found {
390
+ n := g .NewNode ()
391
+ g .AddNode (n )
392
+ nodes [imp ] = n
393
+ names [n .ID ()] = imp
394
+ }
395
+ g .SetEdge (g .NewEdge (nodes [imp ], nodes [pkg ]))
396
+ }
397
+ }
398
+
399
+ ret := []string {}
400
+ sorted , err := topo .Sort (g )
401
+ if err != nil {
402
+ return nil , err
403
+ }
404
+ for _ , n := range sorted {
405
+ ret = append (ret , names [n .ID ()])
406
+ fmt .Println ("topological order" , names [n .ID ()])
407
+ }
408
+ return ret , nil
409
+ }
410
+
411
+ type positionOrder struct {
412
+ pos map [string ]int
413
+ elements []* protobufPackage
414
+ }
415
+
416
+ func (o positionOrder ) Len () int {
417
+ return len (o .elements )
418
+ }
419
+
420
+ func (o positionOrder ) Less (i , j int ) bool {
421
+ return o .pos [o .elements [i ].PackagePath ] < o .pos [o .elements [j ].PackagePath ]
422
+ }
423
+
424
+ func (o positionOrder ) Swap (i , j int ) {
425
+ x := o .elements [i ]
426
+ o .elements [i ] = o .elements [j ]
427
+ o .elements [j ] = x
428
+ }
0 commit comments