aboutsummaryrefslogtreecommitdiffstats
path: root/pkg/subsystem/entities.go
blob: f7c364299e2f8f1623d1d84d85008ec2f96baa1d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
// Copyright 2023 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.

package subsystem

type Subsystem struct {
	Name        string
	PathRules   []PathRule
	Syscalls    []string
	Lists       []string
	Maintainers []string
	Parents     []*Subsystem
	// If NoReminders is true, there should be no monthly reports for the subsystem.
	NoReminders bool
	// If NoIndirectCc is true, the subsystem lists are not tagged in sub-subsystem reports.
	NoIndirectCc bool
}

// ReachableParents returns the set of subsystems reachable from the current one.
func (subsystem *Subsystem) ReachableParents() map[*Subsystem]struct{} {
	ret := make(map[*Subsystem]struct{})
	var dfs func(node *Subsystem)
	dfs = func(node *Subsystem) {
		for _, p := range node.Parents {
			if p == subsystem {
				panic("loop in the parents relation")
			}
			if _, visited := ret[p]; !visited {
				ret[p] = struct{}{}
				dfs(p)
			}
		}
	}
	dfs(subsystem)
	return ret
}

// Emails returns the list of emails related to the subsystem.
func (subsystem *Subsystem) Emails() []string {
	ret := []string{}
	// For the subsystem itself, we take both lists and maintainers.
	ret = append(ret, subsystem.Lists...)
	ret = append(ret, subsystem.Maintainers...)
	// For its parent subsystems, we only take lists.
	for parent := range subsystem.ReachableParents() {
		if !parent.NoIndirectCc {
			ret = append(ret, parent.Lists...)
		}
	}
	return ret
}

func FilterList(list []*Subsystem, filter func(*Subsystem) bool) []*Subsystem {
	keep := map[*Subsystem]bool{}
	for _, item := range list {
		keep[item] = filter(item)
	}
	newList := []*Subsystem{}
	for _, item := range list {
		if !keep[item] {
			continue
		}
		newParents := []*Subsystem{}
		for _, p := range item.Parents {
			if keep[p] {
				newParents = append(newParents, p)
			}
		}
		item.Parents = newParents
		newList = append(newList, item)
	}
	return newList
}

// PathRule describes the part of the directory tree belonging to a single subsystem.
type PathRule struct {
	IncludeRegexp string
	// ExcludeRegexps are tested before IncludeRegexp.
	ExcludeRegexp string
}

func (pr *PathRule) IsEmpty() bool {
	return pr.IncludeRegexp == "" && pr.ExcludeRegexp == ""
}

type DebugInfo struct {
	ParentChildComment map[*Subsystem]map[*Subsystem]string
	FileLists          map[*Subsystem][]string
}