Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support usage in projects using Gradle 8.10 by avoiding using Project.equals #257

Merged
merged 2 commits into from
Aug 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading