When probing settings.gradle files for applicability, changes to Gradle object persist

I found a problem that bite me between buildSrc and its enclosing project, but it could happen on other occasions where found settings.gradle files are probed also and break builds just because there is some settings.gradle file found that is totally unrelated to the build itself and breaks it.

In my case I have a settings.gradle where I do stuff like

includeFlat 'subproject1'
gradle.rootProject {
   it.project('subproject1').ext.type = 'java'
}
  includeFlat 'subproject2'
gradle.rootProject {
   it.project('subproject2').ext.type = 'doc'
}

to later use the ext-variables during the build, in this case to use subproject / allprojects to configure projects by type from one central point, the root project.

Now if you have some gradle project deeper in the file tree without a settings.gradle file (the buildSrc project in my case, but could be any build) it searches by default upward for a settings.gradle file, evaluates is, checks whether itself is contained and uses it if yes, or uses an empty settings script if not.

In my case of course an empty settings script is used finally. But during probing of the applicability, the gradle.rootProject methods were executed and the Gradle instance modified. When then the build continues with the empty settings script, the build fails with the message that the project “subproject1” is not found in the root project “buildSrc”.

During probing which settings.gradle to use, the things that can be modified by the settings.gradle like the “Gradle” instance should not be applied to the live object. Either during probing a read-only wrapper of the object should be given and after finding the right settings.gradle it then gets executed again with the actual Gradle instance, or probably better a Proxy should be provided that forwards read requests to the actual object, but write requests only if the settings.gradle file was the right one and is used futher on.

Currently as workaround I modified my settings.gradle file to be

includeFlat 'subproject1'
gradle.rootProject {
   if (it.name == 'correct-root-project') {
      it.project('subproject1').ext.type = 'java'
   }
}
  includeFlat 'subproject2'
gradle.rootProject {
   if (it.name == 'correct-root-project') {
      it.project('subproject2').ext.type = 'java'
   }
}

Another workaround would be to always tell manually not to search for settings.gradle files when calling.

But both workarounds are not too nice, because the latter is tedious and the former means you need to patch settings.gradle files of other projects to make your project not break. :-/