diff --git a/.scalafmt.conf b/.scalafmt.conf new file mode 100644 index 0000000..213dea4 --- /dev/null +++ b/.scalafmt.conf @@ -0,0 +1,23 @@ +version = 2.3.2 +edition = 2019-10 +maxColumn = 100 +project.git = true +project.excludeFilters = [ "\\Wsbt-test\\W", "\\Winput_sources\\W", "\\Wcontraband-scala\\W" ] +lineEndings = preserve + +# https://docs.scala-lang.org/style/scaladoc.html recommends the JavaDoc style. +# scala/scala is written that way too https://github.com/scala/scala/blob/v2.12.2/src/library/scala/Predef.scala +docstrings = JavaDoc + +# This also seems more idiomatic to include whitespace in import x.{ yyy } +spaces.inImportCurlyBraces = true + +# This is more idiomatic Scala. +# https://docs.scala-lang.org/style/indentation.html#methods-with-numerous-arguments +align.openParenCallSite = false +align.openParenDefnSite = false + +# For better code clarity +danglingParentheses = true + +trailingCommas = preserve diff --git a/.travis.yml b/.travis.yml index 792c470..759f632 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,8 +1,16 @@ language: scala -sudo: false -scala: - - 2.12.10 - - 2.11.12 - - 2.10.7 -jdk: - - openjdk8 +jdk: openjdk8 + +script: sbt +test scalafmtCheckAll + +before_cache: + - find $HOME/.cache/coursier/v1 -name "ivydata-*.properties" -delete + - find $HOME/.ivy2 -name "ivydata-*.properties" -delete + - find $HOME/.sbt -name "*.lock" -delete + - rm -r $(find $HOME/.sbt/boot -name "*-SNAPSHOT") || true + +cache: + directories: + - $HOME/.cache/coursier/v1 + - $HOME/.ivy2/cache + - $HOME/.sbt/boot diff --git a/build.sbt b/build.sbt index 93aa039..2317dc9 100644 --- a/build.sbt +++ b/build.sbt @@ -1,19 +1,20 @@ -lazy val dispatchVersion = SettingKey[String]("dispatchVersion") -lazy val unusedWarnings = Seq("-Ywarn-unused-import", "-Ywarn-unused") +ThisBuild / version := "0.5.3-SNAPSHOT" +ThisBuild / organization := "org.foundweekends" +ThisBuild / homepage := Some(url(s"https://github.com/sbt/${name.value}/#readme")) +ThisBuild / description := "your packages, delivered fresh" +ThisBuild / developers := List( + Developer("softprops", "Doug Tangren", "@softprops", url("https://github.com/softprops")) +) +ThisBuild / scmInfo := Some(ScmInfo(url(s"https://github.com/sbt/${name.value}"), s"git@github.com:sbt/{name.value}.git")) +ThisBuild / crossScalaVersions := Seq("2.12.12", "2.13.3") +ThisBuild / scalaVersion := (ThisBuild / crossScalaVersions).value.last + +lazy val dispatchVersion = settingKey[String]("") +lazy val unusedWarnings = Seq("-Ywarn-unused") lazy val commonSettings: Seq[Setting[_]] = Seq( - version in ThisBuild := "0.5.3-SNAPSHOT", - organization in ThisBuild := "org.foundweekends", - homepage in ThisBuild := Some(url(s"https://github.com/sbt/${name.value}/#readme")), - licenses in ThisBuild := Seq("MIT" -> + licenses := Seq("MIT" -> url(s"https://github.com/sbt/${name.value}/blob/${version.value}/LICENSE")), - description in ThisBuild := "your packages, delivered fresh", - developers in ThisBuild := List( - Developer("softprops", "Doug Tangren", "@softprops", url("https://github.com/softprops")) - ), - scmInfo in ThisBuild := Some(ScmInfo(url(s"https://github.com/sbt/${name.value}"), s"git@github.com:sbt/{name.value}.git")), - crossScalaVersions in ThisBuild := Seq("2.10.7", "2.11.12", "2.12.10"), - scalaVersion in ThisBuild := (crossScalaVersions in ThisBuild).value.last, scalacOptions ++= Seq(Opts.compile.deprecation, "-Xlint", "-feature"), scalacOptions ++= PartialFunction.condOpt(CrossVersion.partialVersion(scalaVersion.value)){ case Some((2, v)) if v >= 11 => unusedWarnings @@ -36,15 +37,11 @@ lazy val root = (project in file(".")) .settings( name := "bintry", description := "your packages, delivered fresh", - dispatchVersion := { - CrossVersion.partialVersion(scalaVersion.value) match { - case Some((2, 10)) => "0.11.2" // !WARNING! Don't upgrade! See sbt/sbt-bintray#104 - case _ => "0.12.0" - } - }, + dispatchVersion := "1.2.0", libraryDependencies ++= Seq( - "net.databinder.dispatch" %% "dispatch-json4s-native" % dispatchVersion.value, - "org.scalatest" %% "scalatest" % "3.0.0" % "test" + "org.dispatchhttp" %% "dispatch-json4s-native" % dispatchVersion.value, + "com.eed3si9n.verify" %% "verify" % "0.2.0" % Test, ), + testFrameworks += new TestFramework("verify.runner.Framework"), initialCommands := "import scala.concurrent.ExecutionContext.Implicits.global;" ) diff --git a/project/build.properties b/project/build.properties index 133a8f1..08e4d79 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=0.13.17 +sbt.version=1.4.1 diff --git a/project/plugins.sbt b/project/plugins.sbt index cefa8ec..f0f0523 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1 +1,2 @@ -addSbtPlugin("com.jsuereth" % "sbt-pgp" % "1.1.0-M1") +addSbtPlugin("com.jsuereth" % "sbt-pgp" % "2.0.1") +addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.3.0") diff --git a/src/main/scala/Attrs.scala b/src/main/scala/Attrs.scala index 45f2c06..7f2ea58 100644 --- a/src/main/scala/Attrs.scala +++ b/src/main/scala/Attrs.scala @@ -20,8 +20,8 @@ object AttrsSearchJson { pair match { case (name, query) => (name -> (query match { - case AttrOneOf(values) => values.toList.map(AttrsToJson(_)) - case AttrIs(value) => AttrsToJson.apply(value) :: Nil + case AttrOneOf(values) => values.toList.map(AttrsToJson(_)) + case AttrIs(value) => AttrsToJson.apply(value) :: Nil })) } @@ -30,23 +30,23 @@ object AttrsSearchJson { } object AttrsToJson { - def apply[A <: Attr[_]](a: A): JValue = - a match { - case Attr.String(value) => JString(value) - case Attr.Number(value) => JInt(value) - case Attr.Boolean(value) => JBool(value) - case Attr.Date(value) => JString(Iso8601(value)) - case Attr.Version(value) => JString(value) - } - def apply[A <: Attr[_]](attrs: Iterable[(String, Iterable[A])]): JValue = - attrs.map { - case (name, values) => - (("name" -> name) ~ { - val tpe = values.headOption.map(_.tpe).getOrElse("string") - ("type" -> tpe) ~ ("values" -> - values.map(apply(_))) - }) - } + def apply[A <: Attr[_]](a: A): JValue = + a match { + case Attr.String(value) => JString(value) + case Attr.Number(value) => JInt(value) + case Attr.Boolean(value) => JBool(value) + case Attr.Date(value) => JString(Iso8601(value)) + case Attr.Version(value) => JString(value) + } + def apply[A <: Attr[_]](attrs: Iterable[(String, Iterable[A])]): JValue = + attrs.map { + case (name, values) => + (("name" -> name) ~ { + val tpe = values.headOption.map(_.tpe).getOrElse("string") + ("type" -> tpe) ~ ("values" -> + values.map(apply(_))) + }) + } } trait AttrQuery[A <: Attr[_]] @@ -59,7 +59,6 @@ sealed trait Attr[T] { def value: T } - object Attr { import java.lang.{ String => JString, Boolean => JBoolean } type AttrMap = Map[JString, Iterable[Attr[_]]] @@ -69,5 +68,3 @@ object Attr { case class Boolean(value: JBoolean) extends Attr[JBoolean] case class Version(value: JString) extends Attr[JString] } - - diff --git a/src/main/scala/Client.scala b/src/main/scala/Client.scala index 0013974..ff44414 100644 --- a/src/main/scala/Client.scala +++ b/src/main/scala/Client.scala @@ -1,19 +1,17 @@ package bintry -import com.ning.http.client.{ AsyncHandler, Response } +import org.asynchttpclient.{ AsyncHandler, Response } import dispatch.{ FunctionHandler, Http, Req } import scala.concurrent.{ ExecutionContext, Future } object Client { type Handler[T] = AsyncHandler[T] - case class Error(code: Int, message: Message) - extends RuntimeException(message.message) + case class Error(code: Int, message: Message) extends RuntimeException(message.message) abstract class Completion[T: Rep] { - def apply[TT] - (handler: Client.Handler[TT]): Future[TT] + def apply[TT](handler: Client.Handler[TT]): Future[TT] def apply(): Future[T] = apply(implicitly[Rep[T]].map(_)) @@ -22,38 +20,37 @@ object Client { apply(new FunctionHandler(f) { override def onCompleted(response: Response) = if (response.getStatusCode / 100 == 2) f(response) - else throw Error( - response.getStatusCode, - if (response.hasResponseBody) Message(response.getResponseBody) - else Message.empty) + else + throw Error( + response.getStatusCode, + if (response.hasResponseBody) Message(response.getResponseBody) + else Message.empty + ) }) } } -abstract class Requests( - credentials: Credentials, http: Http) - (implicit ec: ExecutionContext) - extends DefaultHosts - with Methods { +abstract class Requests(credentials: Credentials, http: Http)(implicit ec: ExecutionContext) + extends DefaultHosts + with Methods { - def request[T] - (req: Req) - (handler: Client.Handler[T]): Future[T] = - http(credentials.sign(req) > handler) + def request[T](req: Req)(handler: Client.Handler[T]): Future[T] = + http(credentials.sign(req) > handler) def complete[A: Rep](req: Req): Client.Completion[A] = new Client.Completion[A] { - override def apply[T] - (handler: Client.Handler[T]) = - request(req)(handler) + override def apply[T](handler: Client.Handler[T]) = + request(req)(handler) } } case class Client( - user: String, token: String, - private val http: Http = new Http) - (implicit ec: ExecutionContext) - extends Requests(Credentials.BasicAuth(user, token), http) { + user: String, + token: String, + private val http: Http = Http(Http.defaultClientBuilder) +)(implicit ec: ExecutionContext) + extends Requests(Credentials.BasicAuth(user, token), http) { + /** releases http resources. once closed, this client may no longer be used */ def close(): Unit = http.shutdown() } diff --git a/src/main/scala/Licenses.scala b/src/main/scala/Licenses.scala index 5443cbc..9f2ec51 100644 --- a/src/main/scala/Licenses.scala +++ b/src/main/scala/Licenses.scala @@ -1,5 +1,127 @@ package bintry object Licenses { - val Names = Set("AFL-3.0","AGPL-V3","APL-1.0","Apache-1.0","Apache-1.1","APSL-2.0","Artistic-License-2.0","Attribution","BSL-1.0","CA-TOSL-1.1","CPAL-1.0","CPOL-1.02","CUAOFFICE-1.0","Day-Addendum","EUDATAGRID","Historical","IBMPL-1.0","IPAFont-1.0","ISC","Lucent-1.02","MirOS","MS-PL","MS-RL","MIT","BSD","GPL-2.0","JTidy","CPL-1.0","JA-SIG","JSON","Motosoto-0.9.1","ECL2","Eiffel-2.0","Entessa-1.0","EUPL-1.1","Fair","Frameworx-1.0","GPL-2.0+CE","Multics","NASA-1.3","NTP","NAUMEN","Nethack","Nokia-1.0a","NOSL-3.0","OCLC-2.0","Openfont-1.1","Opengroup","OSL-3.0","PHP-3.0","PostgreSQL","Public Domain - SUN","PythonPL","PythonSoftFoundation","QTPL-1.0","Real-1.0","RPL-1.5","RicohPL","SimPL-2.0","Sleepycat","SUNPublic-1.0","Sybase-1.0","UoI-NCSA","IU-Extreme-1.1.1","VovidaPL-1.0","wxWindows","Xnet","ZPL-2.0","ZLIB","Codehaus","TMate","WTFPL","MPL-2.0","Public Domain","Bouncy-Castle","Apache-2.0","BSD Simplified","BSD New","LGPL-3.0","GPL-3.0","CDDL-1.0","HSQLDB","Day","Mozilla-1.1","LGPL-2.1","W3C","Unlicense","BSD 2-Clause","NUnit-Test-Adapter-2.6.3","BSD 3-Clause","CDDL-1.1","Facebook-Platform","NUnit-2.6.3","OpenSSL","Scala","CeCILL-C","AFL-2.1","CC0-1.0","Go","CeCILL-2","Libpng","ImageMagick","VIM License","CeCILL-B","Copyfree","CeCILL-2.1","CeCILL-1","CPOL","LPPL-1.0","EPL-1.0","OpenLDAP","EPL-2.0","Unicode-DFS-2015","LGPL-2.0","EUPL-1.2","IJG","NCSA","UPL-1.0","GPL-3.0-only","GPL-3.0-or-later","Mulan PSL v1") + val Names = Set( + "AFL-3.0", + "AGPL-V3", + "APL-1.0", + "Apache-1.0", + "Apache-1.1", + "APSL-2.0", + "Artistic-License-2.0", + "Attribution", + "BSL-1.0", + "CA-TOSL-1.1", + "CPAL-1.0", + "CPOL-1.02", + "CUAOFFICE-1.0", + "Day-Addendum", + "EUDATAGRID", + "Historical", + "IBMPL-1.0", + "IPAFont-1.0", + "ISC", + "Lucent-1.02", + "MirOS", + "MS-PL", + "MS-RL", + "MIT", + "BSD", + "GPL-2.0", + "JTidy", + "CPL-1.0", + "JA-SIG", + "JSON", + "Motosoto-0.9.1", + "ECL2", + "Eiffel-2.0", + "Entessa-1.0", + "EUPL-1.1", + "Fair", + "Frameworx-1.0", + "GPL-2.0+CE", + "Multics", + "NASA-1.3", + "NTP", + "NAUMEN", + "Nethack", + "Nokia-1.0a", + "NOSL-3.0", + "OCLC-2.0", + "Openfont-1.1", + "Opengroup", + "OSL-3.0", + "PHP-3.0", + "PostgreSQL", + "Public Domain - SUN", + "PythonPL", + "PythonSoftFoundation", + "QTPL-1.0", + "Real-1.0", + "RPL-1.5", + "RicohPL", + "SimPL-2.0", + "Sleepycat", + "SUNPublic-1.0", + "Sybase-1.0", + "UoI-NCSA", + "IU-Extreme-1.1.1", + "VovidaPL-1.0", + "wxWindows", + "Xnet", + "ZPL-2.0", + "ZLIB", + "Codehaus", + "TMate", + "WTFPL", + "MPL-2.0", + "Public Domain", + "Bouncy-Castle", + "Apache-2.0", + "BSD Simplified", + "BSD New", + "LGPL-3.0", + "GPL-3.0", + "CDDL-1.0", + "HSQLDB", + "Day", + "Mozilla-1.1", + "LGPL-2.1", + "W3C", + "Unlicense", + "BSD 2-Clause", + "NUnit-Test-Adapter-2.6.3", + "BSD 3-Clause", + "CDDL-1.1", + "Facebook-Platform", + "NUnit-2.6.3", + "OpenSSL", + "Scala", + "CeCILL-C", + "AFL-2.1", + "CC0-1.0", + "Go", + "CeCILL-2", + "Libpng", + "ImageMagick", + "VIM License", + "CeCILL-B", + "Copyfree", + "CeCILL-2.1", + "CeCILL-1", + "CPOL", + "LPPL-1.0", + "EPL-1.0", + "OpenLDAP", + "EPL-2.0", + "Unicode-DFS-2015", + "LGPL-2.0", + "EUPL-1.2", + "IJG", + "NCSA", + "UPL-1.0", + "GPL-3.0-only", + "GPL-3.0-or-later", + "Mulan PSL v1" + ) } diff --git a/src/main/scala/Methods.scala b/src/main/scala/Methods.scala index 61e890d..afc157b 100644 --- a/src/main/scala/Methods.scala +++ b/src/main/scala/Methods.scala @@ -1,12 +1,13 @@ package bintry -import com.ning.http.client.Response +import org.asynchttpclient.Response import bintry.Util.appendPath import dispatch.Req import org.json4s.JValue import org.json4s.JsonDSL._ import org.json4s.native.JsonMethods.{ compact, render } import java.io.File +import java.nio.charset.StandardCharsets import bintry.Client.Completion @@ -14,22 +15,21 @@ trait Methods { self: Requests => object json { private[this] val Type = "application/json" - private[this] val Encoding = "UTF-8" + private[this] val Encoding = StandardCharsets.UTF_8 def content(r: Req) = r.setContentType(Type, Encoding) def str(jv: JValue) = compact(render(jv)) } /** All methods relating to a given repo */ - case class Repo(subject: String, repo: String) - extends Client.Completion[bintry.Repo] { + case class Repo(subject: String, repo: String) extends Client.Completion[bintry.Repo] { case class PackageCreate( - name: String, - _desc: Option[String] = None, - _labels: List[String] = Nil, - _licenses: List[String] = Nil, - _vcs: Option[String] = None) - extends Client.Completion[bintry.Package] { + name: String, + _desc: Option[String] = None, + _labels: List[String] = Nil, + _licenses: List[String] = Nil, + _vcs: Option[String] = None + ) extends Client.Completion[bintry.Package] { def desc(d: String) = copy(_desc = Some(d)) def labels(ls: String*) = copy(_labels = ls.toList) @@ -38,67 +38,70 @@ trait Methods { self: Requests => /** https://bintray.com/docs/api/#_create_package */ override def apply[T](handler: Client.Handler[T]) = - request((json.content(apiHost / "packages" / subject / repo).POST) - << body)(handler) - - def body = json.str( - ("name" -> name) ~ - ("desc" -> _desc) ~ - ("licenses" -> _licenses) ~ - ("labels" -> _labels) ~ - ("vcs_url" -> _vcs)) + request( + (json.content(apiHost / "packages" / subject / repo).POST) + << body + )(handler) + + def body = + json.str( + ("name" -> name) ~ + ("desc" -> _desc) ~ + ("licenses" -> _licenses) ~ + ("labels" -> _labels) ~ + ("vcs_url" -> _vcs) + ) } /** Package methods */ - case class Package(name: String) - extends Client.Completion[bintry.Package] { + case class Package(name: String) extends Client.Completion[bintry.Package] { object Attrs { private def pkgAttrBase = (apiHost / "packages" / - subject / repo / name / "attributes") + subject / repo / name / "attributes") /** https://bintray.com/docs/api/#_get_attributes */ def apply(names: String*) = complete[Attr.AttrMap]( (if (names.isEmpty) pkgAttrBase else pkgAttrBase) - < names.mkString(","))) + < names.mkString(",")) + ) /** https://bintray.com/docs/api/#_set_attributes */ def set[A <: Attr[_]](attrs: (String, Iterable[A])*) = complete[Attr.AttrMap]( json.content(pkgAttrBase.POST) - << json.str(AttrsToJson(attrs))) + << json.str(AttrsToJson(attrs)) + ) /** https://bintray.com/docs/api/#_update_attributes */ def update[A <: Attr[_]](attrs: (String, Iterable[A])*) = complete[Attr.AttrMap]( json.content(pkgAttrBase.PATCH) - << json.str(AttrsToJson(attrs))) + << json.str(AttrsToJson(attrs)) + ) /** https://bintray.com/docs/api/#_delete_attributes */ def delete(names: String*) = complete[Message]( (if (names.isEmpty) pkgAttrBase.DELETE else pkgAttrBase.DELETE) - < names.mkString(","))) + < names.mkString(",")) + ) } - private[this] def publishPath( - path: String, publish: Boolean, replace: Boolean) = - "%s;publish=%s;override=%s".format( - path, - if (publish) 1 else 0, - if (replace) 1 else 0) + private[this] def publishPath(path: String, publish: Boolean, replace: Boolean) = + "%s;publish=%s;override=%s".format(path, if (publish) 1 else 0, if (replace) 1 else 0) /** https://bintray.com/docs/api/#_create_version */ case class CreateVersion( - version: String, - _desc: Option[String] = None, - _vcsTag: Option[String] = None, - _ghNotesFile: Option[String] = None, - _useGhTagReleaseNotes: Option[Boolean] = None) - extends Client.Completion[bintry.Version] { + version: String, + _desc: Option[String] = None, + _vcsTag: Option[String] = None, + _ghNotesFile: Option[String] = None, + _useGhTagReleaseNotes: Option[Boolean] = None + ) extends Client.Completion[bintry.Version] { def desc(d: String) = copy(_desc = Some(d)) @@ -109,58 +112,65 @@ trait Methods { self: Requests => def useGithubTagReleaseNotes(use: Boolean) = copy(_useGhTagReleaseNotes = Some(use)) def apply[T](handler: Client.Handler[T]) = - request(json.content(pkgBase.POST) / "versions" - << body)(handler) - - def body = json.str( - ("name" -> version) ~ - ("desc" -> _desc) ~ - ("github_release_notes_file" -> _ghNotesFile) ~ - ("github_use_tag_release_notes" -> _useGhTagReleaseNotes) ~ - ("vcs_tag" -> _vcsTag)) + request( + json.content(pkgBase.POST) / "versions" + << body + )(handler) + + def body = + json.str( + ("name" -> version) ~ + ("desc" -> _desc) ~ + ("github_release_notes_file" -> _ghNotesFile) ~ + ("github_use_tag_release_notes" -> _useGhTagReleaseNotes) ~ + ("vcs_tag" -> _vcsTag) + ) } /** Package version methods */ - case class Version(version: String) - extends Client.Completion[bintry.Version] { + case class Version(version: String) extends Client.Completion[bintry.Version] { /** version attr interface */ object Attrs { private def versionAttrBase = (apiHost / "packages" / - subject / repo / name / "versions" / version / "attributes") + subject / repo / name / "versions" / version / "attributes") /** https://bintray.com/docs/api/#_get_attributes */ def apply(names: String*) = complete[Attr.AttrMap]( (if (names.isEmpty) versionAttrBase else versionAttrBase) - < names.mkString(","))) + < names.mkString(",")) + ) /** https://bintray.com/docs/api/#_set_attributes */ def set[A <: Attr[_]](attrs: (String, Iterable[A])*) = complete[Attr.AttrMap]( - json.content(versionAttrBase.POST) << json.str(AttrsToJson(attrs))) + json.content(versionAttrBase.POST) << json.str(AttrsToJson(attrs)) + ) /** https://bintray.com/docs/api/#_update_attributes */ def update[A <: Attr[_]](attrs: (String, Iterable[A])*) = complete[Attr.AttrMap]( - json.content(versionAttrBase.PATCH) << json.str(AttrsToJson(attrs))) + json.content(versionAttrBase.PATCH) << json.str(AttrsToJson(attrs)) + ) /** https://bintray.com/docs/api/#_delete_attributes */ def delete(names: String*) = complete[Message]( (if (names.isEmpty) versionAttrBase.DELETE else versionAttrBase.DELETE) - < names.mkString(","))) + < names.mkString(",")) + ) } /** version upload interface * https://bintray.com/docs/api/#_upload_content */ case class Upload( - _artifact: (String, File), - _publish: Boolean = false, - _replace: Boolean = false) - extends Client.Completion[Response] { // todo: Rep + _artifact: (String, File), + _publish: Boolean = false, + _replace: Boolean = false + ) extends Client.Completion[Response] { // todo: Rep def artifact(path: String, content: File) = copy( _artifact = (path, content) @@ -171,17 +181,17 @@ trait Methods { self: Requests => def replace(rep: Boolean) = copy(_replace = rep) def apply[T](handler: Client.Handler[T]) = - request(appendPath( - contentBase.PUT, - publishPath(_artifact._1, _publish, _replace)) <:< Map( - "X-Bintray-Package" -> name, - "X-Bintray-Version" -> version - ) <<< _artifact._2)(handler) + request( + appendPath(contentBase.PUT, publishPath(_artifact._1, _publish, _replace)) <:< Map( + "X-Bintray-Package" -> name, + "X-Bintray-Version" -> version + ) <<< _artifact._2 + )(handler) } private[this] def versionBase = (apiHost / "packages" / - subject / repo / name / "versions" / version) + subject / repo / name / "versions" / version) private[this] def contentBase = apiHost / "content" / subject / repo @@ -196,21 +206,29 @@ trait Methods { self: Requests => def sign(passphrase: String) = complete[Response]( json.content(apiHost.POST) / "gpg" / subject / repo / name / "versions" / version - << json.str(("passphrase" -> passphrase))) + << json.str(("passphrase" -> passphrase)) + ) /** https://bintray.com/docs/api/#_sync_version_artifacts_to_maven_central * see also http://blog.bintray.com/2014/02/11/bintray-as-pain-free-gateway-to-maven-central/ * see also https://docs.sonatype.org/display/Repository/Central+Sync+Requirements */ - def mavenCentralSync(sonatypeUser: String, sonatypePassword: String, close: Boolean = true) = + def mavenCentralSync( + sonatypeUser: String, + sonatypePassword: String, + close: Boolean = true + ) = complete[Response]( json.content(apiHost.POST) / "maven_central_sync" / subject / repo / name / "versions" / version << json.str( ("username" -> sonatypeUser) ~ - ("password" -> sonatypePassword) ~ - ("close" -> (if (close) "1" else "0")))) + ("password" -> sonatypePassword) ~ + ("close" -> (if (close) "1" + else "0")) + ) + ) /** https://bintray.com/docs/api/#_delete_version */ def delete = @@ -222,18 +240,23 @@ trait Methods { self: Requests => update(desc = Some(desc)) /** https://bintray.com/docs/api/#_update_version */ - def update(desc: Option[String] = None, - githubReleaseNotesFile: Option[String] = None, - githubUseTagReleaseNotes: Option[Boolean] = None, - vcsTag: Option[String] = None, - released: Option[String] = None): Completion[Message] = - complete[Message](json.content(versionBase.PATCH) << - json.str( - ("desc" -> desc) ~ - ("github_release_notes_file" -> githubReleaseNotesFile) ~ - ("github_use_tag_release_notes" -> githubUseTagReleaseNotes) ~ - ("vcs_tag" -> vcsTag) ~ - ("released" -> released))) + def update( + desc: Option[String] = None, + githubReleaseNotesFile: Option[String] = None, + githubUseTagReleaseNotes: Option[Boolean] = None, + vcsTag: Option[String] = None, + released: Option[String] = None + ): Completion[Message] = + complete[Message]( + json.content(versionBase.PATCH) << + json.str( + ("desc" -> desc) ~ + ("github_release_notes_file" -> githubReleaseNotesFile) ~ + ("github_use_tag_release_notes" -> githubUseTagReleaseNotes) ~ + ("vcs_tag" -> vcsTag) ~ + ("released" -> released) + ) + ) def attrs = Attrs @@ -248,7 +271,8 @@ trait Methods { self: Requests => def discard = complete[Response]( json.content(contentBase.POST) / name / version / "publish" - << json.str("discard" -> true)) + << json.str("discard" -> true) + ) } /** Logs interface @@ -278,9 +302,11 @@ trait Methods { self: Requests => def update(desc: String, labels: String*) = complete[Message]( json.content(pkgBase.PATCH) - << json.str( - ("desc" -> desc) ~ - ("labels" -> labels.toList))) + << json.str( + ("desc" -> desc) ~ + ("labels" -> labels.toList) + ) + ) def attrs = Attrs @@ -296,10 +322,10 @@ trait Methods { self: Requests => /** https://bintray.com/docs/api/#_maven_upload */ case class MvnUpload( - _artifact: (String, File), - _publish: Boolean = false, - _exploded: Boolean = false) - extends Client.Completion[Response] { // todo: Rep + _artifact: (String, File), + _publish: Boolean = false, + _exploded: Boolean = false + ) extends Client.Completion[Response] { // todo: Rep def artifact(path: String, content: File) = copy(_artifact = (path, content)) @@ -313,9 +339,12 @@ trait Methods { self: Requests => def apply[T](handler: Client.Handler[T]) = _artifact match { case (path, file) => - request(appendPath( - apiHost.PUT / "maven" / subject / repo / name, - publishPath(path, _publish, _exploded)) <<< file)(handler) + request( + appendPath( + apiHost.PUT / "maven" / subject / repo / name, + publishPath(path, _publish, _exploded) + ) <<< file + )(handler) } } @@ -352,8 +381,6 @@ trait Methods { self: Requests => } }*/ - - /** https://bintray.com/docs/api/#_maven_upload * path should be in standard mvn format * i.e. com/org/name/version/name-version.pom @@ -378,10 +405,11 @@ trait Methods { self: Requests => /** https://bintray.com/docs/api/#_get_repository */ def packages(pos: Int = 0, prefix: Option[String] = None) = complete[List[PackageSummary]]( - base / "packages" < pos.toString) ++ prefix.map(("start_name" -> _))) + base / "packages" < pos.toString) ++ prefix.map(("start_name" -> _)) + ) /** https://bintray.com/docs/api/#_link_package */ - def link(subject: String, repo: String, pkg: String) = + def link(subject: String, repo: String, pkg: String) = complete[Response](linkBase.PUT / subject / repo / pkg) /** https://bintray.com/docs/api/#_unlink_package */ @@ -404,12 +432,12 @@ trait Methods { self: Requests => def sign(passphrase: String, path: String) = complete[Response]( appendPath(json.content(apiHost.POST) / "gpg" / subject / repo, path) - << json.str(("passphrase" -> passphrase))) + << json.str(("passphrase" -> passphrase)) + ) } /** User methods */ - case class User(user: String) - extends Client.Completion[bintry.User] { + case class User(user: String) extends Client.Completion[bintry.User] { private[this] def userBase = apiHost / "users" / user /** https://bintray.com/docs/api/#_get_user */ @@ -422,10 +450,8 @@ trait Methods { self: Requests => } /** Webhook methods */ - case class Webhooks( - subject: String, - repo: Option[String] = None) - extends Client.Completion[Response] { // todo: Rep + case class Webhooks(subject: String, repo: Option[String] = None) + extends Client.Completion[Response] { // todo: Rep private[this] def hookBase = { val hooks = apiHost / "webhooks" / subject @@ -436,12 +462,15 @@ trait Methods { self: Requests => override def apply[T](handler: Client.Handler[T]) = request(hookBase)(handler) - /** https://bintray.com/docs/api/#_register_a_webhook */ - def create(pkg: String, url: String, method: Webhook.Method) = + /** https://bintray.com/docs/api/#_register_a_webhook */ + def create(pkg: String, url: String, method: Webhook.Method) = complete[Response]( json.content(hookBase.POST) / pkg - << json.str(("url" -> url) ~ - ("method" -> method.name))) + << json.str( + ("url" -> url) ~ + ("method" -> method.name) + ) + ) /** https://bintray.com/docs/api/#_delete_a_webhook */ def delete(pkg: String) = @@ -460,20 +489,21 @@ trait Methods { self: Requests => private[this] def attrSearchBase = apiHost / "search" / "attributes" case class SearchTarget( - endpoint: Req, - _queries: Seq[(String, AttrQuery[_])] = - Seq.empty[(String, AttrQuery[_])]) - extends Client.Completion[Response] { // todo: Rep + endpoint: Req, + _queries: Seq[(String, AttrQuery[_])] = Seq.empty[(String, AttrQuery[_])] + ) extends Client.Completion[Response] { // todo: Rep def is[A <: Attr[_]](name: String, attr: A) = copy(_queries = (name, AttrIs(attr)) +: _queries) def oneOf[A <: Attr[_]](name: String, attrs: A*) = copy(_queries = (name, AttrOneOf(attrs)) +: _queries) - + override def apply[T](handler: Client.Handler[T]) = - request(json.content(endpoint.POST) << - json.str(AttrsSearchJson(_queries)))(handler) + request( + json.content(endpoint.POST) << + json.str(AttrsSearchJson(_queries)) + )(handler) } def ofPackageVersions(subject: String, repo: String, pkg: String) = @@ -483,27 +513,27 @@ trait Methods { self: Requests => SearchTarget(attrSearchBase / subject / repo) } - case class RepoSearch( - _name: Option[String] = None, - _desc: Option[String] = None, - _pos: Int = 0) extends Client.Completion[Response] { // todo: Rep + case class RepoSearch(_name: Option[String] = None, _desc: Option[String] = None, _pos: Int = 0) + extends Client.Completion[Response] { // todo: Rep def name(n: String) = copy(_name = Some(n)) def desc(d: String) = copy(_desc = Some(d)) def startPos(start: Int) = copy(_pos = start) def apply[T](handler: Client.Handler[T]) = request(searchBase / "repos" < _pos.toString) ++ - _name.map("name" -> _) ++ - _desc.map("desc" -> _) + def query = + Map("start_pos" -> _pos.toString) ++ + _name.map("name" -> _) ++ + _desc.map("desc" -> _) } case class PackageSearch( - _pos: Int = 0, - _name: Option[String] = None, - _desc: Option[String] = None, - _subject: Option[String] = None, - _repo: Option[String] = None) extends Client.Completion[List[bintry.Package]] { + _pos: Int = 0, + _name: Option[String] = None, + _desc: Option[String] = None, + _subject: Option[String] = None, + _repo: Option[String] = None + ) extends Client.Completion[List[bintry.Package]] { def name(pkg: String) = copy(_name = Some(pkg)) def desc(d: String) = copy(_desc = Some(d)) def subject(sub: String) = copy(_subject = Some(sub)) @@ -512,55 +542,46 @@ trait Methods { self: Requests => override def apply[T](handler: Client.Handler[T]) = request(searchBase / "packages" < _pos.toString) ++ - _name.map("name" -> _) ++ - _desc.map("desc" -> _) ++ - _subject.map("subject" -> _) ++ - _repo.map("repo" -> _) + def query = + Map("start_pos" -> _pos.toString) ++ + _name.map("name" -> _) ++ + _desc.map("desc" -> _) ++ + _subject.map("subject" -> _) ++ + _repo.map("repo" -> _) } - case class FileSearch( - _file: String, - _repo: Option[String] = None, - _pos: Int = 0) extends Client.Completion[Response] { // todo: Rep + case class FileSearch(_file: String, _repo: Option[String] = None, _pos: Int = 0) + extends Client.Completion[Response] { // todo: Rep def file(f: String) = copy(_file = f) def repo(r: String) = copy(_repo = Some(r)) def startPos(start: Int) = copy(_pos = start) override def apply[T](handler: Client.Handler[T]) = request(searchBase / "file" < _file, - "start_pos" -> _pos.toString) ++ - _repo.map(("repo" -> _)) + def query = + Map("name" -> _file, "start_pos" -> _pos.toString) ++ + _repo.map(("repo" -> _)) } - case class ShaSearch( - _sha: String, - _repo: Option[String] = None, - _pos: Int = 0) extends Client.Completion[Response] { // todo: Rep + case class ShaSearch(_sha: String, _repo: Option[String] = None, _pos: Int = 0) + extends Client.Completion[Response] { // todo: Rep def sha(s: String) = copy(_sha = s) def repo(r: String) = copy(_repo = Some(r)) def startPos(start: Int) = copy(_pos = start) override def apply[T](handler: Client.Handler[T]) = request(searchBase / "file" < _sha, - "start_pos" -> _pos.toString) ++ - _repo.map(("repo" -> _)) + def query = + Map("sha" -> _sha, "start_pos" -> _pos.toString) ++ + _repo.map(("repo" -> _)) } - case class UserSearch( - _name: String, - _pos: Int = 0) extends Client.Completion[Response] { // todo: Rep + case class UserSearch(_name: String, _pos: Int = 0) extends Client.Completion[Response] { // todo: Rep def name(n: String) = copy(_name = n) def startPos(start: Int) = copy(_pos = start) override def apply[T](handler: Client.Handler[T]) = request(searchBase / "users" < _name, - "start_pos" -> _pos.toString) + def query = Map("name" -> _name, "start_pos" -> _pos.toString) } /** https://bintray.com/docs/api/#_repository_search */ diff --git a/src/main/scala/Rep.scala b/src/main/scala/Rep.scala index 010a6ab..214edcb 100644 --- a/src/main/scala/Rep.scala +++ b/src/main/scala/Rep.scala @@ -1,6 +1,6 @@ package bintry -import com.ning.http.client.Response +import org.asynchttpclient.Response import dispatch.as import org.json4s._ @@ -13,63 +13,63 @@ case class Message(message: String) case class RepoSummary(name: String, owner: String) case class Repo( - name: String, - owner: String, - desc: String, - labels: List[String], - created: String, - packages: Int + name: String, + owner: String, + desc: String, + labels: List[String], + created: String, + packages: Int ) case class PackageSummary(name: String, linked: Boolean) case class Package( - name: String, - repo: String, - owner: String, - desc: Option[String], - labels: List[String], - attrNames: List[String], - followers: Int, - created: String, - updated: String, - web: Option[String], - issueTracker: Option[String], - githubRepo: Option[String], - vcs: Option[String], - githubReleaseNotes: String, - publicDownloadNumbers: Boolean, - links: List[String], - versions: List[String], - latestVersion: Option[String], - rating: Int, - systemIds: List[String] + name: String, + repo: String, + owner: String, + desc: Option[String], + labels: List[String], + attrNames: List[String], + followers: Int, + created: String, + updated: String, + web: Option[String], + issueTracker: Option[String], + githubRepo: Option[String], + vcs: Option[String], + githubReleaseNotes: String, + publicDownloadNumbers: Boolean, + links: List[String], + versions: List[String], + latestVersion: Option[String], + rating: Int, + systemIds: List[String] ) case class Version( - name: String, - desc: Option[String], - pkg: String, - repo: String, - owner: String, - labels: List[String], - attrNames: List[String], - created: String, - updated: String, - released: String, - ordinal: Int, - vcsTag: Option[String] + name: String, + desc: Option[String], + pkg: String, + repo: String, + owner: String, + labels: List[String], + attrNames: List[String], + created: String, + updated: String, + released: String, + ordinal: Int, + vcsTag: Option[String] ) case class User( - name: String, - fullName: String, - gravatar: String, - repos: List[String], - organizations: List[String], - followerCount: Int, - registered: String, - bytesUsed: Long + name: String, + fullName: String, + gravatar: String, + repos: List[String], + organizations: List[String], + followerCount: Int, + registered: String, + bytesUsed: Long ) case class Name(name: String) @@ -109,190 +109,192 @@ object Rep { implicit val messages: Rep[Message] = new JsonRep[Message] { - def map(json: JValue) = (for { - JObject(msg) <- json - ("message", JString(message)) <- msg - } yield Message(message)).head + def map(json: JValue) = + (for { + JObject(msg) <- json + ("message", JString(message)) <- msg + } yield Message(message)).head } implicit val attributes: Rep[Attr.AttrMap] = new JsonRep[Attr.AttrMap] { def map(json: JValue): Attr.AttrMap = (for { - JArray(ary) <- json - JObject(fs) <- ary - ("name", JString(name)) <- fs - ("type", JString(tpe)) <- fs + JArray(ary) <- json + JObject(fs) <- ary + ("name", JString(name)) <- fs + ("type", JString(tpe)) <- fs ("values", JArray(values)) <- fs - } yield - (name, (tpe match { - case "string" => for { JString(str) <- values } yield Attr.String(str) - case "number" => for { JInt(num) <- values } yield Attr.Number(num.toInt) - case "date" => for { JString(date) <- values } yield Attr.Date(Iso8601(date)) - case "version" => for { JString(ver) <- values } yield Attr.Version(ver) - case "boolean" => for { JBool(bool) <- values } yield Attr.Boolean(bool) - case _ => Nil - }): Iterable[Attr[_]])).toMap - } + } yield (name, (tpe match { + case "string" => for { JString(str) <- values } yield Attr.String(str) + case "number" => for { JInt(num) <- values } yield Attr.Number(num.toInt) + case "date" => for { JString(date) <- values } yield Attr.Date(Iso8601(date)) + case "version" => for { JString(ver) <- values } yield Attr.Version(ver) + case "boolean" => for { JBool(bool) <- values } yield Attr.Boolean(bool) + case _ => Nil + }): Iterable[Attr[_]])).toMap + } implicit val repoSummaries: Rep[List[RepoSummary]] = new JsonRep[List[RepoSummary]] { - def map(json: JValue): List[RepoSummary] = for { - JArray(repos) <- json - JObject(repo) <- repos - ("name", JString(name)) <- repo - ("owner", JString(owner)) <- repo - } yield RepoSummary(name, owner) + def map(json: JValue): List[RepoSummary] = + for { + JArray(repos) <- json + JObject(repo) <- repos + ("name", JString(name)) <- repo + ("owner", JString(owner)) <- repo + } yield RepoSummary(name, owner) } implicit val repoDetails: Rep[Repo] = new JsonRep[Repo] { def map(json: JValue): Repo = (for { - JObject(repo) <- json - ("name", JString(name)) <- repo - ("owner", JString(owner)) <- repo - ("desc", JString(desc)) <- repo - ("labels", labels) <- repo - ("created", JString(created)) <- repo + JObject(repo) <- json + ("name", JString(name)) <- repo + ("owner", JString(owner)) <- repo + ("desc", JString(desc)) <- repo + ("labels", labels) <- repo + ("created", JString(created)) <- repo ("package_count", JInt(pkgCount)) <- repo - } yield Repo( - name, - owner, - desc, - strs(labels), - created, - pkgCount.toInt) - ).head + } yield Repo(name, owner, desc, strs(labels), created, pkgCount.toInt)).head } implicit val packages: Rep[List[Package]] = new JsonRep[List[Package]] { - def map(json: JValue): List[Package] = for { - JArray(pkgs) <- json - pkg <- pkgs - } yield packageDetails.one(pkg).get + def map(json: JValue): List[Package] = + for { + JArray(pkgs) <- json + pkg <- pkgs + } yield packageDetails.one(pkg).get } implicit object packageDetails extends JsonRep[Package] { - def one(js: JValue): Option[Package] = (for { - JObject(pkg) <- js - ("name", JString(name)) <- pkg - ("repo", JString(repo)) <- pkg - ("owner", JString(owner)) <- pkg - ("desc", desc) <- pkg - ("labels", labels) <- pkg - ("attribute_names", attrs) <- pkg - ("followers_count", JInt(followers)) <- pkg - ("created", JString(created)) <- pkg - ("website_url", web) <- pkg - ("issue_tracker_url", issues) <- pkg - ("github_repo", github) <- pkg - ("github_release_notes_file", JString(releaseNotes)) <- pkg - ("public_download_numbers", JBool(downloadNums)) <- pkg - ("linked_to_repos", links) <- pkg - ("versions", versions) <- pkg - ("latest_version", latestVersion) <- pkg - ("updated", JString(updated)) <- pkg - ("rating_count", JInt(rating)) <- pkg - ("system_ids", sysIds) <- pkg - ("vcs_url", vcs) <- pkg - } yield Package( - name, - repo, - owner, - str(desc), - strs(labels), - strs(attrs), - followers.toInt, - created, - updated, - str(web), - str(issues), - str(github), - str(vcs), - releaseNotes, - downloadNums, - strs(links), - strs(versions), - str(latestVersion), - rating.toInt, - strs(sysIds))).headOption + def one(js: JValue): Option[Package] = + (for { + JObject(pkg) <- js + ("name", JString(name)) <- pkg + ("repo", JString(repo)) <- pkg + ("owner", JString(owner)) <- pkg + ("desc", desc) <- pkg + ("labels", labels) <- pkg + ("attribute_names", attrs) <- pkg + ("followers_count", JInt(followers)) <- pkg + ("created", JString(created)) <- pkg + ("website_url", web) <- pkg + ("issue_tracker_url", issues) <- pkg + ("github_repo", github) <- pkg + ("github_release_notes_file", JString(releaseNotes)) <- pkg + ("public_download_numbers", JBool(downloadNums)) <- pkg + ("linked_to_repos", links) <- pkg + ("versions", versions) <- pkg + ("latest_version", latestVersion) <- pkg + ("updated", JString(updated)) <- pkg + ("rating_count", JInt(rating)) <- pkg + ("system_ids", sysIds) <- pkg + ("vcs_url", vcs) <- pkg + } yield Package( + name, + repo, + owner, + str(desc), + strs(labels), + strs(attrs), + followers.toInt, + created, + updated, + str(web), + str(issues), + str(github), + str(vcs), + releaseNotes, + downloadNums, + strs(links), + strs(versions), + str(latestVersion), + rating.toInt, + strs(sysIds) + )).headOption def map(json: JValue): Package = one(json).get } implicit val packageSummaries: Rep[List[PackageSummary]] = new JsonRep[List[PackageSummary]] { - def map(json: JValue): List[PackageSummary] = for { - JArray(pkgs) <- json - JObject(pkg) <- pkgs - ("name", JString(name)) <- pkg - ("linked", JBool(linked)) <- pkg - } yield PackageSummary(name, linked) + def map(json: JValue): List[PackageSummary] = + for { + JArray(pkgs) <- json + JObject(pkg) <- pkgs + ("name", JString(name)) <- pkg + ("linked", JBool(linked)) <- pkg + } yield PackageSummary(name, linked) } implicit val versions: JsonRep[Version] = new JsonRep[Version] { - def map(json: JValue): Version = (for { - JObject(ver) <- json - ("name", JString(name)) <- ver - ("desc", desc) <- ver - ("package", JString(pkg)) <- ver - ("repo", JString(repo)) <- ver - ("owner", JString(owner)) <- ver - ("labels", labels) <- ver - ("attribute_names", attrs) <- ver - ("created", JString(created)) <- ver - ("updated", JString(updated)) <- ver - ("released", JString(released)) <- ver - ("ordinal", JDecimal(ord)) <- ver - ("vcs_tag", tag) <- ver - } yield Version( - name, - str(desc), - pkg, - repo, - owner, - strs(labels), - strs(attrs), - created, - updated, - released, - ord.toInt, - str(tag))).head + def map(json: JValue): Version = + (for { + JObject(ver) <- json + ("name", JString(name)) <- ver + ("desc", desc) <- ver + ("package", JString(pkg)) <- ver + ("repo", JString(repo)) <- ver + ("owner", JString(owner)) <- ver + ("labels", labels) <- ver + ("attribute_names", attrs) <- ver + ("created", JString(created)) <- ver + ("updated", JString(updated)) <- ver + ("released", JString(released)) <- ver + ("ordinal", JDecimal(ord)) <- ver + ("vcs_tag", tag) <- ver + } yield Version( + name, + str(desc), + pkg, + repo, + owner, + strs(labels), + strs(attrs), + created, + updated, + released, + ord.toInt, + str(tag) + )).head } implicit val names: Rep[List[Name]] = new JsonRep[List[Name]] { - def map(json: JValue): List[Name] = for { - JArray(xs) <- json - JObject(name) <- xs - ("name", JString(n)) <- name - } yield Name(n) + def map(json: JValue): List[Name] = + for { + JArray(xs) <- json + JObject(name) <- xs + ("name", JString(n)) <- name + } yield Name(n) } implicit val user: Rep[User] = new JsonRep[User] { - def map(json: JValue): User = (for { - JObject(u) <- json - ("name", JString(name)) <- u - ("full_name", JString(fullname)) <- u - ("gravatar_id", JString(gravatar)) <- u - ("repos", repos) <- u - ("organizations", orgs) <- u - ("followers_count", JInt(followers)) <- u - ("registered", JString(reg)) <- u - ("quota_used_bytes", JInt(bytes)) <- u - } yield User( - name, - fullname, - gravatar, - strs(repos), - strs(orgs), - followers.toInt, - reg, - bytes.toLong - )).head + def map(json: JValue): User = + (for { + JObject(u) <- json + ("name", JString(name)) <- u + ("full_name", JString(fullname)) <- u + ("gravatar_id", JString(gravatar)) <- u + ("repos", repos) <- u + ("organizations", orgs) <- u + ("followers_count", JInt(followers)) <- u + ("registered", JString(reg)) <- u + ("quota_used_bytes", JInt(bytes)) <- u + } yield User( + name, + fullname, + gravatar, + strs(repos), + strs(orgs), + followers.toInt, + reg, + bytes.toLong + )).head } } diff --git a/src/test/scala/JsonVersionLibSpec.scala b/src/test/scala/JsonVersionLibSpec.scala index e73b777..d422915 100644 --- a/src/test/scala/JsonVersionLibSpec.scala +++ b/src/test/scala/JsonVersionLibSpec.scala @@ -1,56 +1,52 @@ import org.json4s.JsonDSL._ import org.json4s.native.JsonMethods -import org.scalatest.{MustMatchers, WordSpec} +import verify._ -class JsonVersionLibSpec extends WordSpec with MustMatchers { +object JsonVersionLibSpec extends BasicTestSuite { val jsonMethods = new JsonMethods {} - - "Stringifying json" should { + test("Stringifying json should work all values") { println(s"Scala version tested is: ${scala.util.Properties.versionString}") - - "should work all values" in { - - val rendered = jsonMethods.compact( - jsonMethods.render( - ("name" -> "randomName") ~ - ("desc" -> Option("basicDescription")) ~ + val rendered = jsonMethods.compact( + jsonMethods.render( + ("name" -> "randomName") ~ + ("desc" -> Option("basicDescription")) ~ ("licenses" -> List("Apache", "MIT")) ~ - ("labels" -> List("label1", "label2")) ~ - ("vcs_url" -> Option("vcs")) - ) + ("labels" -> List("label1", "label2")) ~ + ("vcs_url" -> Option("vcs")) ) + ) - rendered must be( + assert( + rendered == "{" + """"name":"randomName",""" + """"desc":"basicDescription",""" + """"licenses":["Apache","MIT"],""" + """"labels":["label1","label2"],""" + """"vcs_url":"vcs"""" + - "}" - ) - } - - "should work with some values omitted" in { + "}" + ) + } - val rendered = jsonMethods.compact( - jsonMethods.render( - ("name" -> "randomName") ~ - ("desc" -> (None : Option[String])) ~ - ("licenses" -> List[String]()) ~ - ("labels" -> List[String]()) ~ - ("vcs_url" -> (None : Option[String])) - ) + test("Stringifying json should work with some values omitted") { + val rendered = jsonMethods.compact( + jsonMethods.render( + ("name" -> "randomName") ~ + ("desc" -> (None: Option[String])) ~ + ("licenses" -> List[String]()) ~ + ("labels" -> List[String]()) ~ + ("vcs_url" -> (None: Option[String])) ) + ) - rendered must be( + assert( + rendered == "{" + """"name":"randomName",""" + """"licenses":[],""" + """"labels":[]""" + "}" - ) - } + ) } } diff --git a/src/test/scala/LicensesSpec.scala b/src/test/scala/LicensesSpec.scala index 56cec41..fa0a53a 100644 --- a/src/test/scala/LicensesSpec.scala +++ b/src/test/scala/LicensesSpec.scala @@ -2,23 +2,34 @@ import bintry.Licenses import dispatch._ import org.json4s._ import org.json4s.native.JsonMethods._ -import org.scalatest.AsyncFlatSpec +import verify._ -class LicensesSpec extends AsyncFlatSpec { +object LicensesSpec extends BasicTestSuite { val bintrayOssLicensesUrl = url("https://api.bintray.com/licenses/oss_licenses") - "Licenses in bintry" should "equal licenses available in Bintray" in { - Http(bintrayOssLicensesUrl OK as.String) + testAsync("Licenses in bintry should equal licenses available in Bintray") { + import scala.concurrent.ExecutionContext.Implicits._ + + Http + .default(bintrayOssLicensesUrl OK as.String) .map(parse(_)) - .map{ json => { - for { - JObject(license) <- json - JField("name", JString(name)) <- license - } yield name - }.toSet} - .map{ names => - assert(names.diff(Licenses.Names).isEmpty, "not all licenses available in Bintray are in bintry") - assert(Licenses.Names.diff(names).isEmpty, "not all licenses in bintry are available in Bintray") + .map { json => + { + for { + JObject(license) <- json + JField("name", JString(name)) <- license + } yield name + }.toSet + } + .map { names => + assert( + names.diff(Licenses.Names).isEmpty, + "not all licenses available in Bintray are in bintry" + ) + assert( + Licenses.Names.diff(names).isEmpty, + "not all licenses in bintry are available in Bintray" + ) } } }