package owners // print tree of owners files + dirs they cover import ( "context" "flag" "fmt" "io/fs" "path/filepath" "strings" "slices" "github.com/peterbourgon/ff/v3" "github.com/peterbourgon/ff/v3/ffcli" "edge-infra.dev/pkg/lib/text/drawing" ) type list struct { *owners dir string } func newList(o *owners) *ffcli.Command { l := &list{owners: o} fs := flag.NewFlagSet("hack owners list", flag.ExitOnError) l.owners.RegisterFlags(fs) fs.StringVar(&l.dir, "directory", "", "verify that the policy-bot config is valid") return &ffcli.Command{ Name: "list", FlagSet: fs, Exec: l.Exec, Options: []ff.Option{ ff.WithEnvVarNoPrefix(), }, } } // print all paths and their owners func (l *list) Exec(_ context.Context, _ []string) error { // collect the list of paths names, _, err := l.collectOwners() if err != nil { return err } // if a user defined a spefic dir attempt to print the structure if l.dir != "" { if slices.Contains(names, l.dir) { return listDir(l.dir) } return fmt.Errorf("directory provided by user doesnt have an OWNERS file") } // otherwise print everything for _, name := range names { err := listDir(name) if err != nil { return err } } return nil } func listDir(name string) error { ownerName := fmt.Sprintf("%s/%s", name, "OWNERS") rootNode := &drawing.StringTree{ Data: "/", } nodes := map[string]*drawing.StringTree{} err := filepath.WalkDir(name, func(path string, info fs.DirEntry, err error) error { if err != nil { return err } for _, x := range ignoreList { if strings.Contains(path, x) { return filepath.SkipDir } } // check if the current dir is in the ignore list if info.IsDir() && slices.Contains(ignore, path) { // fmt.Println("skipping ignored", path) return filepath.SkipDir } d, f := filepath.Split(path) d = strings.TrimSuffix(d, "/") if d == "" { // pkg/ cmd/ node := &drawing.StringTree{ Data: f, } rootNode.Children = append(rootNode.Children, node) nodes[f] = node return nil } dNode, ok := nodes[d] // cmd pkg/edge if !ok { dNode = &drawing.StringTree{ Data: d, } rootNode.Children = append(rootNode.Children, dNode) nodes[d] = dNode } fNode, ok := nodes[path] if !ok { fNode = &drawing.StringTree{ Data: f, } if path != name && path != ownerName { fNode.Labels = map[string]string{ownerName: ""} } nodes[path] = fNode } dNode.Children = append(dNode.Children, fNode) return nil }) if err != nil { return fmt.Errorf("failed to walk filesystem: %w", err) } rootNode.Print() return nil }