Skip to content

Apply String targetExclude patterns as tree excludes to avoid walking the project dir - #3171

Open
Pankraz76 wants to merge 1 commit into
diffplug:mainfrom
Pankraz76:fix/3147-target-exclude-cc-walk
Open

Pankraz76 wants to merge 1 commit into
diffplug:mainfrom
Pankraz76:fix/3147-target-exclude-cc-walk

Conversation

@Pankraz76

Copy link
Copy Markdown

Fixes #3147. A String targetExclude became fileTree(projectDir).include(pattern) and the task target was target.minus(targetExclude). A leading ** can't be pruned, so resolving the exclude walked the whole project directory. With the configuration cache the default GIT_ATTRIBUTES_FAST_ALLSAME line endings resolve the target during serialisation, which made the walk a configuration input and slowed down both CC store and reuse.

String excludes ending in a ** segment are now applied as exclude patterns on the String target trees (same root, so the same relative paths), letting Gradle prune the excluded directories while walking the target. Only for those patterns does a tree exclude remove exactly the same files as subtracting fileTree.include(pattern), so every other pattern and every non-String exclude, as well as user-provided target collections, keep using minus().

With 60k unrelated files: CC store ~1060 -> ~160 ms, reuse ~920 -> ~150 ms.

Claude-Session: https://claude.ai/code/session_01MTr23zHsJ17K1kvSQYF4AH

Please DO NOT FORCE PUSH. Don't worry about messy history, it's easier to do code review if we can tell what happened after the review, and force pushing breaks that.

Please make sure that your PR allows edits from maintainers. Sometimes it's faster for us to just fix something than it is to describe how to fix it.

Allow edits from maintainers

After creating the PR, please add a commit that adds a bullet-point under the [Unreleased] section of CHANGES.md, plugin-gradle/CHANGES.md, and plugin-maven/CHANGES.md which includes:

  • a summary of the change
  • either
    • a link to the issue you are resolving (for small changes)
    • a link to the PR you just created (for big changes likely to have discussion)

If your change only affects a build plugin, and not the lib, then you only need to update the plugin-foo/CHANGES.md for that plugin.

If your change affects lib in an end-user-visible way (fixing a bug, updating a version) then you need to update CHANGES.md for both the lib and all build plugins. Users of a build plugin shouldn't have to refer to lib to see changes that affect them.

This makes it easier for the maintainers to quickly release your changes :)

…ng the project dir

Fixes diffplug#3147. A String targetExclude became fileTree(projectDir).include(pattern)
and the task target was target.minus(targetExclude). A leading `**` can't be
pruned, so resolving the exclude walked the whole project directory. With the
configuration cache the default GIT_ATTRIBUTES_FAST_ALLSAME line endings resolve
the target during serialisation, which made the walk a configuration input and
slowed down both CC store and reuse.

String excludes ending in a `**` segment are now applied as exclude patterns on
the String target trees (same root, so the same relative paths), letting Gradle
prune the excluded directories while walking the target. Only for those
patterns does a tree exclude remove exactly the same files as subtracting
fileTree.include(pattern), so every other pattern and every non-String exclude,
as well as user-provided target collections, keep using minus().

With 60k unrelated files: CC store ~1060 -> ~160 ms, reuse ~920 -> ~150 ms.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MTr23zHsJ17K1kvSQYF4AH
@Pankraz76

Pankraz76 commented Nov 7, 2026 •

Copy link
Copy Markdown
Author

Thanks a lot @Goooler for the excellent report: the TestKit timings, the exact code locations and the stack trace made the root cause easy to confirm, and the note that filter { !contains(it) } isn't enough saved a dead end.

String targetExclude patterns ending in /** (like **/build/**) are now applied as exclude patterns on the String target trees, so Gradle prunes them while walking the target instead of subtracting a fileTree that walks the whole project dir. This matches the fileTree { include …; exclude … } workaround from the issue. Other patterns and non-String excludes keep the existing minus() path, so behaviour is unchanged.

With CC on, the default line endings and 60k unrelated files, store went from ~1060 to ~160 ms and reuse from ~920 to ~150 ms.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant