Skip to content
Closed
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
31 changes: 20 additions & 11 deletions src/main/scala/com/typesafe/sbt/pom/MavenProjectHelper.scala
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ object MavenProjectHelper {
}
case class AggregateProject(model: PomModel, dir: File, children: Seq[ProjectTree]) extends ProjectTree
case class SimpleProject(model: PomModel, dir: File) extends ProjectTree

case class ProjectDep(x: ProjectTree, isTestScoped: Boolean)

def makeReactorProject(baseDir: File, overrideRootProjectName:Option[String] = None,
profiles: Seq[String], userProps: Map[String, String]): Seq[Project] = {
// First create a tree of how things aggregate.
Expand All @@ -51,7 +52,7 @@ object MavenProjectHelper {
// Create a mapping of all dependencies between projects.
val depMap = makeDependencyMap(projects)
// Helper to look up dependencies in the presence of absences.
def getDepsFor(project: ProjectTree): Seq[ProjectTree] =
def getDepsFor(project: ProjectTree): Seq[ProjectDep] =
depMap.getOrElse(project, Nil)
// Now, sort projects in an order that we can create them.
val sorted: Seq[ProjectTree] =
Expand All @@ -61,17 +62,18 @@ object MavenProjectHelper {
case _ => Nil
}
val deps = getDepsFor(project)
aggregates ++ deps
aggregates ++ deps.map(_.x)
}
def makeProjects(toMake: Seq[ProjectTree], made: Map[ProjectTree, Project] = Map.empty): Seq[Project] =
toMake match {
case current :: rest =>
// Make a project, and add it to the stack
val depProjects: Seq[Project] =
val depProjects: Seq[(Project, Boolean)] =
for {
dep <- getDepsFor(current)
depProject <- made.get(dep)
} yield depProject
depProject <- made.get(dep.x)
isTestScoped = dep.isTestScoped
} yield depProject -> isTestScoped
val aggregates: Seq[Project] =
current match {
case AggregateProject(_,_, children) =>
Expand All @@ -81,28 +83,33 @@ object MavenProjectHelper {
} yield depProject
case _ => Nil
}

def projectToClasspathDep(x: (Project, Boolean)): ClasspathDep[ProjectReference] = x match {
case (project, true) => project % "test->test"
case (project, false) => project
}

// TODO - Configure debugging output....
val currentProject = (
Project(makeProjectName(current.model,overrideRootProjectName),current.dir)
// First pull in settings from pom
settings(useMavenPom:_*)
// Now update depends on relationships
dependsOn(depProjects.map(x =>x: ClasspathDep[ProjectReference]):_*)
dependsOn(depProjects.map(x => projectToClasspathDep(x)):_*)
// Now fix aggregate relationships
aggregate(aggregates.map(x => x:ProjectReference):_*)
// Now remove any inter-project dependencies we pulled in from the maven pom.
// TODO - Maybe we can fix the useMavenPom settings so we don't need to
// post-filter artifacts?
settings(
Keys.libraryDependencies <<= Keys.libraryDependencies apply { deps =>
val depIds = getDepsFor(current).map(_.id).toSet
val depIds = getDepsFor(current).map(_.x.id).toSet
deps filterNot { dep =>
val id = makeId(dep.organization, dep.name, dep.revision)
depIds contains id
}
}
)

)
makeProjects(rest, made + (current -> currentProject))
case Nil => made.values.toSeq
Expand Down Expand Up @@ -132,16 +139,18 @@ object MavenProjectHelper {
Seq(agg) ++ agg.children.flatMap(allProjectsInTree)
}
// Detects dependencies between projects
def makeDependencyMap(projects: Seq[ProjectTree]): Map[ProjectTree, Seq[ProjectTree]] = {
def makeDependencyMap(projects: Seq[ProjectTree]): Map[ProjectTree, Seq[ProjectDep]] = {
val findDeps =
for(project <- projects) yield {
val deps =
for {
dep <- Option(project.model.getDependencies).map(_.asScala).getOrElse(Nil)
depId = makeId(dep.getGroupId, dep.getArtifactId, dep.getVersion)
isTestScope = dep.getScope == "test"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, does that mean anything that has a dependnecy like:

<dependency>
  <groupId>foo</group>
  <artifactId>foo</artifactId>
  <scope>test</scope>
</dependency>

Gets the test->test;compile->compile configuration string? That's not quite correct, I think what you want is:

test->compile;test->test i.e. Put all artifacts (test + compile) from the subproject on my classpath. Otherwise, your test libraries would be on your RUNTIME classpath, and leak into subprojects.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

test->compile;test->test i.e. Put all artifacts (test + compile) from the subproject on my classpath.

All I wanted to have is test classpath of subproject is available for (test-compile) on current project. So to try it changed this file to your suggested configuration. It does happen that way.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it should just be 'test->test'. What do you think ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, this won't work correctly because you won't get the compilation artifact, just the test one. You need:

test->test;test->compile.

Might help if you add a test case which checks the classpath to make sure it does the right thing.

pdep <- projects
if pdep.id == depId
} yield pdep
} yield ProjectDep(pdep, isTestScope)

project -> deps
}
findDeps.toMap
Expand Down