+
+// TransitivelyDetectedGroups returns all groups which depend on "detected"
+// groups, either directly or by depending on groups which transitively depend
+// on "detected" groups.
+func TransitivelyDetectedGroups(groups map[string][]string) map[string]bool {
+ work := make(map[string][]string)
+ for k, v := range groups {
+ work[k] = v
+ }
+
+ // Mark all groups which contain "detected" groups as long as new
+ // (transitive) "detected" groups are found.
+ detected := make(map[string]bool)
+ for {
+ change := false
+ for group, members := range work {
+ for _, x := range members {
+ if !detected[x] && !strings.HasPrefix(x,
+ GroupDetectedPrefix) {
+ continue
+ }
+ detected[strings.TrimSuffix(group,
+ GroupRemoveSuffix)] = true
+ delete(work, group)
+ change = true
+ }
+ }
+ if !change {
+ break
+ }
+ }
+ return detected
+}