GetModules returns all modules in the given scope/namespace. For example, a scope of "foo" returns modules named "foo.bar", "foo.loo", but not "bar", "foo.bar.loo", etc. An empty scope returns top-level modules, for example "foo" or "bar". Partial scopes are not matched (i.e. scope "foo.ba" does not
(scope string)
| 202 | // Because modules are registered to a map under the hood, the |
| 203 | // returned slice will be sorted to keep it deterministic. |
| 204 | func GetModules(scope string) []ModuleInfo { |
| 205 | modulesMu.RLock() |
| 206 | defer modulesMu.RUnlock() |
| 207 | |
| 208 | scopeParts := strings.Split(scope, ".") |
| 209 | |
| 210 | // handle the special case of an empty scope, which |
| 211 | // should match only the top-level modules |
| 212 | if scope == "" { |
| 213 | scopeParts = []string{} |
| 214 | } |
| 215 | |
| 216 | var mods []ModuleInfo |
| 217 | iterateModules: |
| 218 | for id, m := range modules { |
| 219 | modParts := strings.Split(id, ".") |
| 220 | |
| 221 | // match only the next level of nesting |
| 222 | if len(modParts) != len(scopeParts)+1 { |
| 223 | continue |
| 224 | } |
| 225 | |
| 226 | // specified parts must be exact matches |
| 227 | for i := range scopeParts { |
| 228 | if modParts[i] != scopeParts[i] { |
| 229 | continue iterateModules |
| 230 | } |
| 231 | } |
| 232 | |
| 233 | mods = append(mods, m) |
| 234 | } |
| 235 | |
| 236 | // make return value deterministic |
| 237 | sort.Slice(mods, func(i, j int) bool { |
| 238 | return mods[i].ID < mods[j].ID |
| 239 | }) |
| 240 | |
| 241 | return mods |
| 242 | } |
| 243 | |
| 244 | // Modules returns the names of all registered modules |
| 245 | // in ascending lexicographical order. |
no outgoing calls