diff --git a/README.md b/README.md index 3dcec7e..e795464 100644 --- a/README.md +++ b/README.md @@ -1,64 +1,26 @@ -Requirements ------------- +This is a clone of sbt-idea which replaces library dependencies within a project with module dependency +if artifact ids match. This is useful, for example, if you have a general purpose library A you depend +on in one of your more specific projects B, and you want to improve A as you develop B. +You can incorporate such a dependency in the B build file by using `dependsOn` between sbt projects, +but this then requires developers of B to get sources for the general purpose library A too, and place it in the file +system according to the build dependency. -* [sbt](https://github.com/harrah/xsbt/wiki) 0.11.2 or 0.11.3. -* For sbt 0.12.x version of the plugin, see [branch sbt-0.12](https://github.com/mpeltonen/sbt-idea/tree/sbt-0.12#requirements) -* For sbt 0.7.x version of the plugin, see [branch sbt-0.7](https://github.com/mpeltonen/sbt-idea/tree/sbt-0.7) +To use it set up a "workspace" sbt project that aggregates a couple of sbt projects on your local harddisk. +For example: +```scala +import sbt._ -Installation ------------- +object Workspace extends Build { + lazy val root = Project("root", file(".")) aggregate(p1,p2) + lazy val p1 = RootProject(file("../p1")) + lazy val p2 = RootProject(file("../p2")) +} +``` -Add the following line to ~/.sbt/plugins/build.sbt or PROJECT_DIR/project/plugins.sbt +Running `sbt gen-idea` in this project will create an intellij project file, as before. However, if project +`p1` has a library dependency to the artifact of `p2` (as determined by their name, org, scala version and version +settings), then the Intellij project will have a module dependency in module p1 to module p2, as opposed to +a library dependency (to the library jar in the local ivy repo). - addSbtPlugin("com.github.mpeltonen" % "sbt-idea" % "1.1.0") -To use the latest snapshot version, add also Sonatype snapshots repository resolver into the same file: - - resolvers += "Sonatype snapshots" at "http://oss.sonatype.org/content/repositories/snapshots/" - - addSbtPlugin("com.github.mpeltonen" % "sbt-idea" % "1.2.0-SNAPSHOT") - -Usage ------ - -### Basic project - -Use the `gen-idea` sbt task to create Idea project files. - -### Project with dependencies - -If you have two sbt projects A and B, and A depends on B, then use the `gen-idea` sbt task on Project A to create Idea project files for both projects. - -The projects need to be set up in the following way: - -*Project A:* - - import sbt._ - - object A extends Build { - lazy val A = Project("A", file(".")) aggregate(B) dependsOn(B) - lazy val B = RootProject(file("../B")) - } - -*Project B:* - - import sbt._ - - object B extends Build { - lazy val B = Project("B", file(".")) - } - -### Sources and javadocs - -By default, classifiers (i.e. sources and javadocs) of dependencies are loaded if found and references added to Idea project files. If you don't want to download/reference them, use command 'gen-idea no-classifiers'. - -Configuration settings ----------------------- - -TODO... - -License -------- - -Licensed under the New BSD License. See the LICENSE file for details. diff --git a/project/Build.scala b/project/Build.scala index 3b048ec..c9354dc 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -7,7 +7,7 @@ object SbtIdeaBuild extends Build { lazy val mainSettings: Seq[Project.Setting[_]] = Defaults.defaultSettings ++ ScriptedPlugin.scriptedSettings ++ Seq( sbtPlugin := true, organization := "com.github.mpeltonen", - name := "sbt-idea", + name := "sbt-idea-rc", version := "1.2.0-SNAPSHOT", publishTo := Some(Resolver.file("Github Pages", Path.userHome / "git" / "mpeltonen.github.com" / "maven" asFile)(Patterns(true, Resolver.mavenStyleBasePattern))), publishTo <<= version { (v: String) => diff --git a/src/main/scala/org/sbtidea/IdeaProjectDomain.scala b/src/main/scala/org/sbtidea/IdeaProjectDomain.scala index 64cc858..1b73add 100644 --- a/src/main/scala/org/sbtidea/IdeaProjectDomain.scala +++ b/src/main/scala/org/sbtidea/IdeaProjectDomain.scala @@ -28,11 +28,16 @@ case class Directories(sources: Seq[File], resources: Seq[File], outDir: File) { def addRes (moreResources: Seq[File]): Directories = Directories(sources, resources ++ moreResources, outDir) } +case class ArtifactId(name:String, version:String, organization:String, scalaVersion:String) { + def toFullName = organization + "_" + name + "_" + scalaVersion + "_" + version +} + case class SubProjectInfo(baseDir: File, name: String, dependencyProjects: List[String], classpathDeps: Seq[(File, Seq[File])], compileDirs: Directories, testDirs: Directories, libraries: Seq[IdeaModuleLibRef], scalaInstance: ScalaInstance, ideaGroup: Option[String], webAppPath: Option[File], basePackage: Option[String], packagePrefix: Option[String], - extraFacets: NodeSeq) + extraFacets: NodeSeq, + artifactId:ArtifactId) case class IdeaProjectInfo(baseDir: File, name: String, childProjects: List[SubProjectInfo], ideaLibs: List[IdeaLibrary]) diff --git a/src/main/scala/org/sbtidea/SbtIdeaPlugin.scala b/src/main/scala/org/sbtidea/SbtIdeaPlugin.scala index c7977af..5d114f7 100644 --- a/src/main/scala/org/sbtidea/SbtIdeaPlugin.scala +++ b/src/main/scala/org/sbtidea/SbtIdeaPlugin.scala @@ -33,9 +33,10 @@ object SbtIdeaPlugin extends Plugin { private val NoClassifiers = "no-classifiers" private val SbtClassifiers = "sbt-classifiers" + private val ReplaceLibsByModules = "replace-libs" private val NoFsc = "no-fsc" - private val args = (Space ~> NoClassifiers | Space ~> SbtClassifiers | Space ~> NoFsc).* + private val args = (Space ~> NoClassifiers | Space ~> SbtClassifiers | Space ~> NoFsc | Space ~> ReplaceLibsByModules).* private lazy val ideaCommand = Command("gen-idea")(_ => args)(doCommand) @@ -79,10 +80,15 @@ object SbtIdeaPlugin extends Plugin { } val allProjectIds = projectList.values.map(_.id).toSet - val subProjects = projectList.collect { + val subProjectsRaw = projectList.collect { case (projRef, project) if (!ignoreModule(projRef)) => projectData(projRef, project, buildStruct, state, args, allProjectIds) }.toList + val subProjects = if (args.contains(ReplaceLibsByModules)) + replaceLibDependenciesWithModuleDependencies(state, subProjectsRaw) + else + subProjectsRaw + val scalaInstances = subProjects.map(_.scalaInstance).distinct val scalaLibs = (sbtInstance :: scalaInstances).map(toIdeaLib(_)) val ideaLibs = subProjects.flatMap(_.libraries.map(modRef => modRef.library)).toList.distinct @@ -139,6 +145,20 @@ object SbtIdeaPlugin extends Plugin { state } + def replaceLibDependenciesWithModuleDependencies(state:State, subprojects: List[SubProjectInfo]) = { + val name2project = subprojects.groupBy(_.artifactId.toFullName) + for (sub <- subprojects) yield { + val libs = sub.libraries + val (replaceable, nonreplacable) = libs.partition(l => name2project.isDefinedAt(l.library.name)) + val subprojectsToUseInstead = replaceable.map(l => name2project(l.library.name).head.name).toList + val newSubProject = sub.copy(libraries = nonreplacable, dependencyProjects = sub.dependencyProjects ++ subprojectsToUseInstead) + for (lib <- replaceable) { + logger(state).info("Replacing library %s with module %s".format(lib.library.name,name2project(lib.library.name).head.name)) + } + newSubProject + } + } + def projectData(projectRef: ProjectRef, project: ResolvedProject, buildStruct: BuildStructure, state: State, args: Seq[String], allProjectIds: Set[String]): SubProjectInfo = { @@ -163,6 +183,13 @@ object SbtIdeaPlugin extends Plugin { // IDEA project name. It must be consistent with the value of SubProjectInfo#dependencyProjects. val projectName = project.id + val artifactId = ArtifactId( + name = setting(Keys.artifact, "Artifact not defined").name, + version = setting(Keys.version, "Version not defined"), + organization = setting(Keys.organization, "Org not defined"), + scalaVersion = setting(Keys.scalaVersion, "Scala version not defined") + ) + logger(state).info("Trying to create an Idea module " + projectName) val ideaGroup = optionalSetting(ideaProjectGroup) @@ -231,6 +258,8 @@ object SbtIdeaPlugin extends Plugin { } } SubProjectInfo(baseDirectory, projectName, project.uses.map(_.project).filter(isAggregate).toList, classpathDeps, compileDirectories, - testDirectories, librariesExtractor.allLibraries, scalaInstance, ideaGroup, None, basePackage, packagePrefix, extraFacets) + testDirectories, librariesExtractor.allLibraries, scalaInstance, ideaGroup, None, basePackage, packagePrefix, extraFacets, + artifactId + ) } } diff --git a/src/sbt-test/sbt-idea/dependency-with-classifier/project/plugins.sbt b/src/sbt-test/sbt-idea/dependency-with-classifier/project/plugins.sbt index 909e410..e077d35 100644 --- a/src/sbt-test/sbt-idea/dependency-with-classifier/project/plugins.sbt +++ b/src/sbt-test/sbt-idea/dependency-with-classifier/project/plugins.sbt @@ -1 +1 @@ -addSbtPlugin("com.github.mpeltonen" % "sbt-idea" % "1.2.0-SNAPSHOT") +addSbtPlugin("com.github.mpeltonen" % "sbt-idea" % "") diff --git a/src/sbt-test/sbt-idea/external-rootproject-dependency/dependency-project/project/plugins.sbt b/src/sbt-test/sbt-idea/external-rootproject-dependency/dependency-project/project/plugins.sbt index 909e410..e077d35 100644 --- a/src/sbt-test/sbt-idea/external-rootproject-dependency/dependency-project/project/plugins.sbt +++ b/src/sbt-test/sbt-idea/external-rootproject-dependency/dependency-project/project/plugins.sbt @@ -1 +1 @@ -addSbtPlugin("com.github.mpeltonen" % "sbt-idea" % "1.2.0-SNAPSHOT") +addSbtPlugin("com.github.mpeltonen" % "sbt-idea" % "") diff --git a/src/sbt-test/sbt-idea/external-rootproject-dependency/project/plugins.sbt b/src/sbt-test/sbt-idea/external-rootproject-dependency/project/plugins.sbt index 909e410..e077d35 100644 --- a/src/sbt-test/sbt-idea/external-rootproject-dependency/project/plugins.sbt +++ b/src/sbt-test/sbt-idea/external-rootproject-dependency/project/plugins.sbt @@ -1 +1 @@ -addSbtPlugin("com.github.mpeltonen" % "sbt-idea" % "1.2.0-SNAPSHOT") +addSbtPlugin("com.github.mpeltonen" % "sbt-idea" % "") diff --git a/src/sbt-test/sbt-idea/simple-project/project/plugins.sbt b/src/sbt-test/sbt-idea/simple-project/project/plugins.sbt index 909e410..e077d35 100644 --- a/src/sbt-test/sbt-idea/simple-project/project/plugins.sbt +++ b/src/sbt-test/sbt-idea/simple-project/project/plugins.sbt @@ -1 +1 @@ -addSbtPlugin("com.github.mpeltonen" % "sbt-idea" % "1.2.0-SNAPSHOT") +addSbtPlugin("com.github.mpeltonen" % "sbt-idea" % "") diff --git a/src/sbt-test/sbt-idea/with-integration-tests/project/plugins.sbt b/src/sbt-test/sbt-idea/with-integration-tests/project/plugins.sbt index 909e410..e077d35 100644 --- a/src/sbt-test/sbt-idea/with-integration-tests/project/plugins.sbt +++ b/src/sbt-test/sbt-idea/with-integration-tests/project/plugins.sbt @@ -1 +1 @@ -addSbtPlugin("com.github.mpeltonen" % "sbt-idea" % "1.2.0-SNAPSHOT") +addSbtPlugin("com.github.mpeltonen" % "sbt-idea" % "")