Explain how includeGroup, includeGroupByRegex, and excludeGroup combine within a repository's content block. What is the precedence?
answer
- include = allowlist mode
- exclude = subtract on top
- no rules = serve everything
- regex dots must be escaped
- exclude beats include for same coord
basics
~10 sAny include* rule flips the repo to allowlist mode — only matching coordinates are served. exclude* rules then subtract from what remains. With no rules at all, the repo serves everything.
solid answer
~40 sA `content {}` block has two families of rules. If you declare **any** `include*` rule (`includeGroup`, `includeGroupByRegex`, `includeModule`, `includeVersion`, etc.), the repository switches to allowlist behavior: it may serve **only** coordinates that match at least one include rule; everything unmatched is implicitly excluded. `exclude*` rules are blocklist subtractions applied on top — they remove coordinates from what the repo would otherwise serve. With **no** rules, the repo serves any module (the default search-all behavior). Regex variants (`includeGroupByRegex`, `excludeGroupByRegex`) match the group string against a Java regex, which is handy for group prefixes like `com\.mycompany\..*`. Multiple include rules are OR-ed; an exclude on a matched coordinate wins, so excludes effectively take precedence over includes for the same coordinate.
code
kotlin · 7 linesmaven {
url = uri("https://repo.mycompany.com/all")
content {
includeGroupByRegex("com\\.mycompany\\..*")
excludeModule("com.mycompany.legacy", "oldlib")
}
}go deeper
Know includeGroup pins a group to a repo and excludeGroup keeps it out; details of precedence are stretch.
Articulate the allowlist-on-first-include semantics, OR-ed includes, exclude-wins precedence, and the regex escaping trap.
Discuss combining filters with centralized settings and how filters are evaluated pre-network for speed.
Define conventions (escaped-prefix regexes, group-naming standards) so org builds filter consistently and safely.
## Two modes, one block The `content {}` DSL on a repository accepts filter rules. The mental model: 1. **No rules** → repository is a candidate for *every* module (Gradle's default). 2. **At least one `include*` rule** → repository becomes an **allowlist**: a module is a candidate only if it matches some include rule. 3. **`exclude*` rules** → always subtract: even a module that matches an include (or the no-include default) is removed if it matches an exclude. So for a given coordinate the decision is: `served = (noIncludeRules OR matchesSomeInclude) AND NOT matchesSomeExclude`. ## The rule families Include side (allowlist): - `includeGroup("com.acme")` — exact group. - `includeGroupByRegex("com\\.acme\\..*")` — group matches Java regex. - `includeModule("com.acme", "lib")` — exact group+name. - `includeModuleByRegex("com\\.acme", ".*-core")`. - `includeVersion("com.acme", "lib", "1.0")` / `includeVersionByRegex(...)`. Exclude side (blocklist) mirrors each: `excludeGroup`, `excludeGroupByRegex`, `excludeModule`, `excludeModuleByRegex`, `excludeVersion`, `excludeVersionByRegex`. ## Precedence example ```kotlin maven { url = uri("https://repo.mycompany.com/all") content { includeGroupByRegex("com\\.mycompany\\..*") // allowlist: only our groups excludeModule("com.mycompany.legacy", "oldlib") // ...but not this one artifact } } ``` Here `com.mycompany.web:app` is served (matches the include, not the exclude). `com.mycompany.legacy:oldlib` is **not** served even though it matches the include, because the exclude subtracts it. `org.springframework:spring-core` is not served because no include matches it. ## Regex gotchas The argument is a Java regex string, so dots are wildcards unless escaped. `includeGroupByRegex("com.acme")` matches `comXacme` too. Write `"com\\.acme(\\..*)?"` to mean the group and its subgroups. In Kotlin DSL remember the string-level escaping of backslashes. ## Performance vs correctness Gradle can apply these filters *before* hitting the network, so a non-matching repo is skipped entirely — that is where the speed-up comes from. The same rules also give correctness guarantees (a public repo with `excludeGroup` for your internal group can never accidentally serve a confused artifact).
- You wrote includeGroupByRegex("com.acme") and it matched more than expected. Why?The dot is a regex metacharacter matching any character, so it also matched groups like 'comXacme'. Escape it: "com\\.acme".
- Are multiple includeGroup calls AND-ed or OR-ed?OR-ed — a coordinate served if it matches any include rule. AND-ing would make most coordinates impossible to match.
- If both an include and an exclude match the same module, which wins?The exclude wins; the module is filtered out of that repository.
saying these in an interview costs you the question
- Thinking include rules are additive with the default 'serve all' — they are not; the first include flips to allowlist.
- Forgetting to escape '.' in the *ByRegex variants.
- Believing excludeGroup makes the repo serve everything except — it does, but only because there are no include rules narrowing it.