From 9124056440f3618d93fb70bdc6711e1c144c55c9 Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Fri, 1 Aug 2014 17:23:51 -0400 Subject: [PATCH] Fixes NullPointerException during update. Fixes #1484 --- ivy/src/main/scala/sbt/IvyRetrieve.scala | 33 ++++++++++++------- main/src/main/scala/sbt/Defaults.scala | 12 ++++++- notes/0.13.6.md | 5 +++ .../conflict-manager-with-org/build.sbt | 5 +++ .../conflict-manager-with-org/test | 1 + 5 files changed, 44 insertions(+), 12 deletions(-) create mode 100644 sbt/src/sbt-test/dependency-management/conflict-manager-with-org/build.sbt create mode 100644 sbt/src/sbt-test/dependency-management/conflict-manager-with-org/test diff --git a/ivy/src/main/scala/sbt/IvyRetrieve.scala b/ivy/src/main/scala/sbt/IvyRetrieve.scala index b3bf04563..b83b924a9 100644 --- a/ivy/src/main/scala/sbt/IvyRetrieve.scala +++ b/ivy/src/main/scala/sbt/IvyRetrieve.scala @@ -58,6 +58,13 @@ object IvyRetrieve { moduleIds map { moduleDetail } } + private[sbt] def nonEmptyString(s: String): Option[String] = + s match { + case null => None + case x if x.trim == "" => None + case x => Some(x.trim) + } + private[sbt] def moduleRevisionDetail(confReport: ConfigurationResolveReport, dep: IvyNode): ModuleReport = { def toExtraAttributes(ea: ju.Map[_, _]): Map[String, String] = Map(ea.entrySet.toArray collect { @@ -71,25 +78,29 @@ object IvyRetrieve { } val revId = dep.getResolvedId val moduleId = toModuleID(revId) - val branch = Option(revId.getBranch) + val branch = nonEmptyString(revId.getBranch) val (status, publicationDate, resolver, artifactResolver) = dep.isLoaded match { case true => - (Option(dep.getDescriptor.getStatus), + (nonEmptyString(dep.getDescriptor.getStatus), Some(new ju.Date(dep.getPublication)), - Option(dep.getModuleRevision.getResolver.getName), - Option(dep.getModuleRevision.getArtifactResolver.getName)) + nonEmptyString(dep.getModuleRevision.getResolver.getName), + nonEmptyString(dep.getModuleRevision.getArtifactResolver.getName)) case _ => (None, None, None, None) } val (evicted, evictedData, evictedReason) = dep.isEvicted(confReport.getConfiguration) match { case true => - val ed = dep.getEvictedData(confReport.getConfiguration) - (true, - Some(Option(ed.getConflictManager) map { _.toString } getOrElse { "transitive" }), - Option(ed.getDetail)) + val edOpt = Option(dep.getEvictedData(confReport.getConfiguration)) + edOpt match { + case Some(ed) => + (true, + nonEmptyString(Option(ed.getConflictManager) map { _.toString } getOrElse { "transitive" }), + nonEmptyString(ed.getDetail)) + case None => (true, None, None) + } case _ => (false, None, None) } val problem = dep.hasProblem match { - case true => Option(dep.getProblem.getMessage) + case true => nonEmptyString(dep.getProblem.getMessage) case _ => None } val mdOpt = for { @@ -98,7 +109,7 @@ object IvyRetrieve { } yield md val homepage = mdOpt match { case Some(md) => - Option(md.getHomePage) + nonEmptyString(md.getHomePage) case _ => None } val extraAttributes: Map[String, String] = toExtraAttributes(mdOpt match { @@ -110,7 +121,7 @@ object IvyRetrieve { val licenses: Seq[(String, Option[String])] = mdOpt match { case Some(md) => md.getLicenses.toArray.toVector collect { case lic: IvyLicense => - (lic.getName, Option(lic.getUrl)) + (lic.getName, nonEmptyString(lic.getUrl)) } case _ => Nil } diff --git a/main/src/main/scala/sbt/Defaults.scala b/main/src/main/scala/sbt/Defaults.scala index c6996918c..12dbb1387 100755 --- a/main/src/main/scala/sbt/Defaults.scala +++ b/main/src/main/scala/sbt/Defaults.scala @@ -1286,7 +1286,17 @@ object Classpaths { case (_, Some(out)) if uptodate(inChanged, out) => out case _ => work(in) } - outCache(in) + try { + outCache(in) + } catch { + case e: NullPointerException => + val r = work(in) + log.warn("Update task has failed to cache the report due to null.") + log.warn("Report the following output to sbt:") + r.toString.lines foreach { log.warn(_) } + log.trace(e) + r + } } val f = if (skip && !force) skipWork else doWork f(module.owner.configuration :+: module.moduleSettings :+: config :+: HNil) diff --git a/notes/0.13.6.md b/notes/0.13.6.md index 6794ed72d..dfffccac2 100644 --- a/notes/0.13.6.md +++ b/notes/0.13.6.md @@ -33,6 +33,7 @@ [1467]: https://github.com/sbt/sbt/pull/1467 [1476]: https://github.com/sbt/sbt/pull/1476 [1477]: https://github.com/sbt/sbt/pull/1477 + [1484]: https://github.com/sbt/sbt/issues/1484 [1486]: https://github.com/sbt/sbt/pull/1486 [@dansanduleac]: https://github.com/dansanduleac [@2m]: https://github.com/2m @@ -48,6 +49,10 @@ [@henrikengstrom]: https://github.com/henrikengstrom [@puffnfresh]: https://github.com/puffnfresh +### Changes since 0.13.6-M1 + +- Fixes `NullPointerException` during `update`. [#1484][1484] by [@eed3si9n][@eed3si9n] + ### Fixes with compatibility implications - `ThisProject` used to resolve to the root project in a build even when it's place in `subproj/build.sbt`. sbt 0.13.6 fixes it to resolve to the sub project. [#1194][1194]/[#1358][1358] by [@dansanduleac][@dansanduleac] diff --git a/sbt/src/sbt-test/dependency-management/conflict-manager-with-org/build.sbt b/sbt/src/sbt-test/dependency-management/conflict-manager-with-org/build.sbt new file mode 100644 index 000000000..01013eaa4 --- /dev/null +++ b/sbt/src/sbt-test/dependency-management/conflict-manager-with-org/build.sbt @@ -0,0 +1,5 @@ +scalaVersion := "2.10.4" + +conflictManager := ConflictManager.strict.copy(organization = "^(?!org\\.scala-lang).*$") + +libraryDependencies += "org.specs2" %% "specs2" % "2.3.10-scalaz-7.1.0-M6" % "test" diff --git a/sbt/src/sbt-test/dependency-management/conflict-manager-with-org/test b/sbt/src/sbt-test/dependency-management/conflict-manager-with-org/test new file mode 100644 index 000000000..103bd8d2f --- /dev/null +++ b/sbt/src/sbt-test/dependency-management/conflict-manager-with-org/test @@ -0,0 +1 @@ +> update