Reassigning project(String) method on a project's metaClass property has no effect

Here’s a bit of background on why I’m trying to override things through the metaclass. Maybe there’s a more idiomatic way to approach this?

I have several independent Gradle projects, each with its own settings.gradle and root build.gradle and possibly with subprojects. Here’s the directory structure:

Earth/
   Moon/
Mars
   Phobos/
   Deimos/

and here’s the submodule structure:

Root project 'Earth'
\--- Project ':Moon'
Root project 'Mars'
+--- Project ':Phobos'
\--- Project ':Deimos'

I’d like to add these independent projects as subprojects of a new top-level project.

Root project 'Sun'
+--- Project ':Earth'
|
  \--- Project ':Earth:Moon'
\--- Project ':Mars'
     +--- Project ':Mars:Phobos'
     \--- Project ':Mars:Deimos'

The caveat is that I cannot touch the existing structure or files of the independent projects.

The problem comes when a ‘Project.project(String)’ dependency is referenced in an independent project:

// Sun/Mars/Phobos/build.gradle
  dependencies {
   // This should now be ':Mars:Deimos'
   compile project(':Deimos')
}

I tried to monkey-patch the ‘Project.project(String)’ method

// Sun/build.gradle
  subprojects.each { project ->
   project.metaClass.project = { String path ->
      println "Monkey-patching"
      String newPath = "${project.path}$path"
      delegate.&project(newPath)
   }
}

but it is not picked up in ‘Sun/Mars/Phobos/build.gradle’ (i.e. the line “Monkey-patching” is never printed out)

Using metaprogramming to override core Gradle behavior is definitely not recommended. It could have unforeseen consequences with other core Gradle code acting on that ‘Project’ instance, as well as plugins that are applied to your project. What I would probably recommend is simply defining a custom function that normalizes your project path based on some condition and then call that function in your ‘dependencies {…}’ blocks.

dependencies {

compile findProject(’:Deimos’)

}

def findProject= { String path ->

// determine if path should be altered

return project(newPath)

}

Thanks Mark. I chose to go with an approach similar to what you suggested.