Skip to content

Commit

Permalink
Support usage in projects using Gradle 8.10 by avoiding using Project…
Browse files Browse the repository at this point in the history
….equals (#257)

* Replace usage of Set<Project> with Map<ProjectPath, Project> to avoid Project inequivalence in newer Gradle versions

* Fix compilation error in sample project
  • Loading branch information
anthonycr committed Aug 23, 2024
1 parent cd343a9 commit d89407b
Show file tree
Hide file tree
Showing 5 changed files with 183 additions and 67 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,12 @@ import java.io.File
*/
enum class ProjectSubset { DEPENDENT_PROJECTS, CHANGED_PROJECTS, ALL_AFFECTED_PROJECTS, NONE }

/**
* An identifier for a project, ensuring that projects are always identified by their path.
*/
@JvmInline
value class ProjectPath(val path: String)

/**
* A utility class that can discover which files are changed based on git history.
*
Expand Down Expand Up @@ -344,7 +350,7 @@ class AffectedModuleDetectorImpl constructor(
}

private val allProjects by lazy {
rootProject.subprojects.toSet()
rootProject.subprojects.associateBy { it.projectPath }
}

private val projectGraph by lazy {
Expand All @@ -369,7 +375,7 @@ class AffectedModuleDetectorImpl constructor(

override fun shouldInclude(project: Project): Boolean {
val isRootProject = project.isRoot
val isProjectAffected = affectedProjects.contains(project)
val isProjectAffected = affectedProjects.contains(project.projectPath)
val isProjectProvided = isProjectProvided2(project)
val isModuleExcludedByName = config.excludedModules.contains(project.name)
val isModuleExcludedByRegex = config.excludedModules.any { project.path.matches(it.toRegex()) }
Expand All @@ -390,10 +396,10 @@ class AffectedModuleDetectorImpl constructor(

override fun getSubset(project: Project): ProjectSubset {
return when {
changedProjects.contains(project) -> {
changedProjects.contains(project.projectPath) -> {
ProjectSubset.CHANGED_PROJECTS
}
dependentProjects.contains(project) -> {
dependentProjects.contains(project.projectPath) -> {
ProjectSubset.DEPENDENT_PROJECTS
}
else -> {
Expand All @@ -410,7 +416,7 @@ class AffectedModuleDetectorImpl constructor(
private fun findChangedProjects(
top: Sha,
includeUncommitted: Boolean = true
): Set<Project> {
): Map<ProjectPath, Project> {
git.findChangedFiles(
top = top,
includeUncommitted = includeUncommitted
Expand All @@ -421,7 +427,7 @@ class AffectedModuleDetectorImpl constructor(
changedFiles.add(fileName)
}

val changedProjects = mutableSetOf<Project>()
val changedProjects = mutableMapOf<ProjectPath, Project>()

for (filePath in changedFiles) {
val containingProject = findContainingProject(filePath)
Expand All @@ -432,7 +438,7 @@ class AffectedModuleDetectorImpl constructor(
"Adding to unknownFiles."
)
} else {
changedProjects.add(containingProject)
changedProjects[containingProject.projectPath] = containingProject
logger?.info(
"For file $filePath containing project is $containingProject. " +
"Adding to changedProjects."
Expand All @@ -447,10 +453,10 @@ class AffectedModuleDetectorImpl constructor(
* Gets all dependent projects from the set of changedProjects. This doesn't include the
* original changedProjects. Always build is still here to ensure at least 1 thing is built
*/
private fun findDependentProjects(): Set<Project> {
return changedProjects.flatMap {
dependencyTracker.findAllDependents(it)
}.toSet()
private fun findDependentProjects(): Map<ProjectPath, Project> {
return changedProjects.flatMap { (_, project) ->
dependencyTracker.findAllDependents(project).entries
}.associate { it.key to it.value }
}

/**
Expand All @@ -466,7 +472,7 @@ class AffectedModuleDetectorImpl constructor(
* Also detects modules whose tests are codependent at runtime.
*/
@Suppress("ComplexMethod")
private fun findAffectedProjects(): Set<Project> {
private fun findAffectedProjects(): Map<ProjectPath, Project> {
// In this case we don't care about any of the logic below, we're only concerned with
// running the changed projects in this test runner
if (projectSubset == ProjectSubset.CHANGED_PROJECTS) {
Expand Down Expand Up @@ -525,3 +531,5 @@ class AffectedModuleDetectorImpl constructor(
}

val Project.isRoot get() = this == rootProject

val Project.projectPath: ProjectPath get() = ProjectPath(path)
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ class AffectedModuleDetectorPlugin : Plugin<Project> {
val tracker = DependencyTracker(project, null)
project.tasks.configureEach { task ->
if (task.name.contains(ANDROID_TEST_PATTERN)) {
tracker.findAllDependents(project).forEach { dependentProject ->
tracker.findAllDependents(project).forEach { (_, dependentProject) ->
dependentProject.tasks.forEach { dependentTask ->
AffectedModuleDetector.configureTaskGuard(dependentTask)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,21 +54,22 @@ class DependencyTracker constructor(
result
}

fun findAllDependents(project: Project): Set<Project> {
fun findAllDependents(project: Project): Map<ProjectPath, Project> {
logger?.info("finding dependents of ${project.path}")
val result = mutableSetOf<Project>()
val result = mutableMapOf<ProjectPath, Project>()
fun addAllDependents(project: Project) {
if (result.add(project)) {
if (result.put(project.projectPath, project) == null) {
dependentList[project]?.forEach(::addAllDependents)
}
}
addAllDependents(project)
logger?.info(
"dependents of ${project.path} is ${result.map {
it.path
"dependents of ${project.path} is ${result.map { (path, _) ->
path.path
}}"
)
// the project isn't a dependent of itself
return result.minus(project)
result.remove(project.projectPath)
return result
}
}
Loading

0 comments on commit d89407b

Please sign in to comment.