From 5a4594c2b01cc55508788c9e2337956d77f2edf6 Mon Sep 17 00:00:00 2001 From: Jakub Majak Date: Fri, 3 Apr 2020 21:12:56 +0200 Subject: [PATCH 1/3] Add possibility to use operation execution on all array items using wildcard/asterisk character in path --- README.markdown | 2 ++ build.sbt | 2 +- .../scala/diffson/jsonpatch/JsonPatch.scala | 6 ++++++ .../src/main/resources/conformance/tests.json | 17 ++++++++++++++++- 4 files changed, 25 insertions(+), 2 deletions(-) diff --git a/README.markdown b/README.markdown index 8af4a02b..0ecdfec0 100644 --- a/README.markdown +++ b/README.markdown @@ -1,6 +1,8 @@ Gnieh Diffson [![Build Status](https://travis-ci.org/gnieh/diffson.png)](https://travis-ci.org/gnieh/diffson) [![Codacy Badge](https://api.codacy.com/project/badge/Grade/9892e2c968974ecb951d21969adbadaa)](https://www.codacy.com/app/satabin/diffson?utm_source=github.com&utm_medium=referral&utm_content=gnieh/diffson&utm_campaign=Badge_Grade) [![Code Coverage](https://codecov.io/github/gnieh/diffson/coverage.svg?branch=master)](https://codecov.io/github/gnieh/diffson?branch=master) [![Maven Central](https://img.shields.io/maven-central/v/org.gnieh/diffson-core_2.13.svg)](https://maven-badges.herokuapp.com/maven-central/org.gnieh/diffson-core_2.13) [![Scaladoc](https://javadoc.io/badge/org.gnieh/diffson-core_2.13.svg)](https://javadoc.io/doc/org.gnieh/diffson-core_2.13) ============= +Extended version of library to be able to use `*` operation on array so it is possible execute operations on all array elements. + [![Join the chat at https://gitter.im/gnieh/diffson](https://badges.gitter.im/gnieh/diffson.svg)](https://gitter.im/gnieh/diffson?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) A [scala][6] implementation of the [RFC-6901][1], [RFC-6902][2], and [RFC-7396][11]. diff --git a/build.sbt b/build.sbt index f74fde5f..51ee7edf 100644 --- a/build.sbt +++ b/build.sbt @@ -6,7 +6,7 @@ val scala213 = "2.13.1" lazy val commonSettings = Seq( organization := "org.gnieh", - scalaVersion := scala213, + scalaVersion := scala212, version := "4.0.2", description := "Json diff/patch library", licenses += ("The Apache Software License, Version 2.0" -> url("http://www.apache.org/licenses/LICENSE-2.0.txt")), diff --git a/core/src/main/scala/diffson/jsonpatch/JsonPatch.scala b/core/src/main/scala/diffson/jsonpatch/JsonPatch.scala index 9a853df0..d695ef25 100644 --- a/core/src/main/scala/diffson/jsonpatch/JsonPatch.scala +++ b/core/src/main/scala/diffson/jsonpatch/JsonPatch.scala @@ -49,6 +49,8 @@ sealed abstract class Operation[Json: Jsony] { JsArray(before ++ (updated +: after.tail)) } } + case (JsArray(elems), Inner(Left("*"), tl)) => + elems.map(action[F](_, tl, parent)).traverse(identity).map(JsArray(_)) case (_, Inner(elem, _)) => F.raiseError(new PatchException(show"element ${elem.fold(identity[String], _.toString)} does not exist at path $parent")) } @@ -97,6 +99,8 @@ case class Remove[Json: Jsony](path: Pointer, old: Option[Json] = None) extends val (before, after) = arr.splitAt(idx) F.pure(JsArray(before ++ after.tail)) } + case (JsArray(_), Leaf(Left("*"))) => + F.pure(JsArray(Vector())) case (JsArray(_), Leaf(Left("-"))) => // how could we possibly remove an element that appears after the last one? F.raiseError(new PatchException(show"element - does not exist at path $parent")) @@ -124,6 +128,8 @@ case class Replace[Json: Jsony](path: Pointer, value: Json, old: Option[Json] = F.raiseError(new PatchException(show"element $idx does not exist at path $parent")) else F.pure(JsArray(arr.updated(idx, value))) + case (JsArray(arr), Leaf(Left("*"))) => + F.pure(JsArray(arr.map(_ => value))) case (JsArray(_), Leaf(Left("-"))) => F.raiseError(new PatchException(show"element - does not exist at path $parent")) case (JsObject(obj), Leaf(ObjectField(lbl))) => diff --git a/testkit/jvm/src/main/resources/conformance/tests.json b/testkit/jvm/src/main/resources/conformance/tests.json index dd060da0..63654679 100644 --- a/testkit/jvm/src/main/resources/conformance/tests.json +++ b/testkit/jvm/src/main/resources/conformance/tests.json @@ -69,6 +69,11 @@ "patch": [{"op": "add", "path": "/baz/0/foo", "value": "world"}], "expected": {"foo": 1, "baz": [{"qux": "hello", "foo": "world"}]} }, + { "comment": "Add into all array elements", + "doc": {"foo": 1, "baz": [{"qux": "hello"}, {"qux": "bye"}]}, + "patch": [{"op": "add", "path": "/baz/*/foo", "value": "world"}], + "expected": {"foo": 1, "baz": [{"qux": "hello", "foo": "world"}, {"qux": "bye", "foo": "world"}]} }, + { "doc": {"bar": [1, 2]}, "patch": [{"op": "add", "path": "/bar/8", "value": "5"}], "error": "element 8 does not exist at path /bar" }, @@ -145,6 +150,11 @@ "patch": [{"op": "replace", "path": "/baz/0/qux", "value": "world"}], "expected": {"foo": [1, 2, 3, 4], "baz": [{"qux": "world"}]} }, + { "comment": "test handle asterisk correctly on replace array", + "doc": {"foo": [1, 2, 3, 4], "baz": [{"qux": "hello"}, {"qux": "hi"}]}, + "patch": [{"op": "replace", "path": "/baz/*/qux", "value": "newWorld"}], + "expected": {"foo": [1, 2, 3, 4], "baz": [{"qux": "newWorld"}, {"qux": "newWorld"}]} }, + { "doc": ["foo"], "patch": [{"op": "replace", "path": "/0", "value": "bar"}], "expected": ["bar"] }, @@ -264,6 +274,11 @@ "patch": [ { "op": "add", "path": "/2/1/-", "value": { "foo": [ "bar", "baz" ] } } ], "expected": [ 1, 2, [ 3, [ 4, 5, { "foo": [ "bar", "baz" ] } ] ] ]}, + { "comment": "test remove with asterisk should remove all items", + "doc": {"foo": 1, "baz": [{"qux": "hello"}, {"qux": "hello1"}]}, + "patch": [{"op": "remove", "path": "/baz/*"}], + "expected": {"foo": 1, "baz": []}}, + { "comment": "test remove with bad number should fail", "doc": {"foo": 1, "baz": [{"qux": "hello"}]}, "patch": [{"op": "remove", "path": "/baz/1e0/qux"}], @@ -346,4 +361,4 @@ "doc": {"foo": 1}, "patch": [{"op": "spam", "path": "/foo", "value": 1}], "error": "Unknown operation \"spam\"" } -] +] \ No newline at end of file From 7bd2087c8ae48575084a0442c0a281edeb14a193 Mon Sep 17 00:00:00 2001 From: Jakub Majak Date: Tue, 7 Apr 2020 11:58:54 +0200 Subject: [PATCH 2/3] Add bintray plugin and publish with changed package name --- build.sbt | 81 +++++++++++++++++++++------------------------ project/plugins.sbt | 2 ++ 2 files changed, 39 insertions(+), 44 deletions(-) diff --git a/build.sbt b/build.sbt index 51ee7edf..5ccd928f 100644 --- a/build.sbt +++ b/build.sbt @@ -4,12 +4,31 @@ import sbtcrossproject.CrossPlugin.autoImport.{crossProject, CrossType} val scala212 = "2.12.10" val scala213 = "2.13.1" + +resolvers in Global += Resolver.url("upstartcommerce", url("https://upstartcommerce.bintray.com/nochannel"))(Resolver.ivyStylePatterns) + +lazy val bintraySettings: Seq[Setting[_]] = Seq( + bintrayOmitLicense := true, + bintrayOrganization := Some("upstartcommerce"), + bintrayRepository := "generic", + bintrayReleaseOnPublish in ThisBuild := false, + publishMavenStyle := false) + +lazy val notPublishSettings = Seq( + publishArtifact := false, + skip in publish := true, + bintrayOmitLicense := false, + bintrayRelease := {}, + publishLocal := {}, + publish := {} +) + lazy val commonSettings = Seq( - organization := "org.gnieh", + organization := "com.upstartcommerce", scalaVersion := scala212, - version := "4.0.2", + version := "4.0.3", description := "Json diff/patch library", - licenses += ("The Apache Software License, Version 2.0" -> url("http://www.apache.org/licenses/LICENSE-2.0.txt")), + licenses ++= Seq("The Apache Software License, Version 2.0" -> url("http://www.apache.org/licenses/LICENSE-2.0.txt"), ("Apache-2.0", url("https://bintray.com/upstartcommerce"))), homepage := Some(url("https://github.com/gnieh/diffson")), parallelExecution := false, scalacOptions ++= PartialFunction.condOpt(CrossVersion.partialVersion(scalaVersion.value)) { @@ -46,20 +65,23 @@ lazy val commonSettings = Seq( .setPreference(DoubleIndentConstructorArguments, true) .setPreference(MultilineScaladocCommentsStartOnFirstLine, true) .setPreference(DanglingCloseParenthesis, Prevent) - }) ++ publishSettings + }) lazy val diffson = project.in(file(".")) .enablePlugins(ScoverageSbtPlugin) .settings(commonSettings: _*) + .settings(notPublishSettings: _*) .settings( name := "diffson", - packagedArtifacts := Map()) + packagedArtifacts := Map(), + ) .aggregate(core.jvm, core.js, sprayJson, circe.jvm, circe.js, playJson.jvm, playJson.js, testkit.jvm, testkit.js) lazy val core = crossProject(JSPlatform, JVMPlatform) .crossType(CrossType.Pure).in(file("core")) .enablePlugins(ScoverageSbtPlugin, ScalaUnidocPlugin) .settings(commonSettings: _*) + .settings(bintraySettings) .settings( name := "diffson-core", crossScalaVersions := Seq(scala212, scala213), @@ -69,25 +91,29 @@ lazy val core = crossProject(JSPlatform, JVMPlatform) "io.estatico" %%% "newtype" % "0.4.3", "org.scalatest" %%% "scalatest" % "3.1.1" % Test, "org.scalacheck" %%% "scalacheck" % "1.14.3" % Test - )) + ), + ) .jsSettings(coverageEnabled := false) lazy val testkit = crossProject(JSPlatform, JVMPlatform) .crossType(CrossType.Full).in(file("testkit")) .enablePlugins(ScoverageSbtPlugin) .settings(commonSettings: _*) + .settings(notPublishSettings: _*) .settings( name := "diffson-testkit", crossScalaVersions := Seq(scala212, scala213), libraryDependencies ++= Seq( "org.scalatest" %%% "scalatest" % "3.1.1", - "org.scalacheck" %%% "scalacheck" % "1.14.3")) + "org.scalacheck" %%% "scalacheck" % "1.14.3") + ) .jsSettings(coverageEnabled := false) .dependsOn(core) lazy val sprayJson = project.in(file("sprayJson")) .enablePlugins(ScoverageSbtPlugin) .settings(commonSettings: _*) + .settings(notPublishSettings: _*) .settings( name := "diffson-spray-json", crossScalaVersions := Seq(scala212, scala213), @@ -98,10 +124,12 @@ lazy val playJson = crossProject(JSPlatform, JVMPlatform) .crossType(CrossType.Full).in(file("playJson")) .enablePlugins(ScoverageSbtPlugin) .settings(commonSettings: _*) + .settings(bintraySettings) .settings( name := "diffson-play-json", libraryDependencies += "com.typesafe.play" %%% "play-json" % "2.8.1", - crossScalaVersions := Seq(scala212, scala213)) + crossScalaVersions := Seq(scala212, scala213), + ) .jsSettings(coverageEnabled := false) .dependsOn(core, testkit % Test) @@ -110,6 +138,7 @@ lazy val circe = crossProject(JSPlatform, JVMPlatform) .crossType(CrossType.Full).in(file("circe")) .enablePlugins(ScoverageSbtPlugin) .settings(commonSettings: _*) + .settings(notPublishSettings: _*) .settings( name := "diffson-circe", libraryDependencies ++= Seq( @@ -123,39 +152,3 @@ lazy val circe = crossProject(JSPlatform, JVMPlatform) libraryDependencies += "io.circe" %%% "not-java-time" % "0.2.0" ) .dependsOn(core, testkit % Test) - -lazy val publishSettings = Seq( - publishMavenStyle := true, - publishArtifact in Test := false, - // The Nexus repo we're publishing to. - publishTo := Some( - if (isSnapshot.value) - Opts.resolver.sonatypeSnapshots - else - Opts.resolver.sonatypeStaging - ), - pomIncludeRepository := { x => false }, - pomExtra := ( - - https://github.com/gnieh/diffson - scm:git:git://github.com/gnieh/diffson.git - scm:git:git@github.com:gnieh/diffson.git - HEAD - - - - satabin - Lucas Satabin - lucas.satabin@gnieh.org - - - - travis - https://travis-ci.org/#!/gnieh/diffson - - - github - https://github.com/gnieh/diffson/issues - - ) -) diff --git a/project/plugins.sbt b/project/plugins.sbt index 489e0f48..87fe9123 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -9,3 +9,5 @@ addSbtPlugin("com.codacy" % "sbt-codacy-coverage" % "3.0.2") addSbtPlugin("org.portable-scala" % "sbt-scalajs-crossproject" % "1.0.0") addSbtPlugin("org.scala-js" % "sbt-scalajs" % "0.6.32") + +addSbtPlugin("org.foundweekends" % "sbt-bintray" % "0.5.6") \ No newline at end of file From bd87415f381214c1d7bf69663ec254cac56d8206 Mon Sep 17 00:00:00 2001 From: Jakub Majak Date: Wed, 31 Mar 2021 22:06:00 +0200 Subject: [PATCH 3/3] DEV-273 Use artifactory instead of bintray --- build.sbt | 19 ++++++------------- project/plugins.sbt | 2 -- 2 files changed, 6 insertions(+), 15 deletions(-) diff --git a/build.sbt b/build.sbt index 5ccd928f..9ab379c7 100644 --- a/build.sbt +++ b/build.sbt @@ -4,21 +4,14 @@ import sbtcrossproject.CrossPlugin.autoImport.{crossProject, CrossType} val scala212 = "2.12.10" val scala213 = "2.13.1" - -resolvers in Global += Resolver.url("upstartcommerce", url("https://upstartcommerce.bintray.com/nochannel"))(Resolver.ivyStylePatterns) - -lazy val bintraySettings: Seq[Setting[_]] = Seq( - bintrayOmitLicense := true, - bintrayOrganization := Some("upstartcommerce"), - bintrayRepository := "generic", - bintrayReleaseOnPublish in ThisBuild := false, +lazy val publishSettings: Seq[Setting[_]] = Seq( + publishTo := Some(Resolver.url("upstartcommerce", url("https://upstartcommerce.jfrog.io/artifactory/generic"))(Resolver.ivyStylePatterns)), + credentials += Credentials(Path.userHome / ".sbt" / ".credentials"), publishMavenStyle := false) lazy val notPublishSettings = Seq( publishArtifact := false, skip in publish := true, - bintrayOmitLicense := false, - bintrayRelease := {}, publishLocal := {}, publish := {} ) @@ -28,7 +21,7 @@ lazy val commonSettings = Seq( scalaVersion := scala212, version := "4.0.3", description := "Json diff/patch library", - licenses ++= Seq("The Apache Software License, Version 2.0" -> url("http://www.apache.org/licenses/LICENSE-2.0.txt"), ("Apache-2.0", url("https://bintray.com/upstartcommerce"))), + licenses ++= Seq("The Apache Software License, Version 2.0" -> url("http://www.apache.org/licenses/LICENSE-2.0.txt")), homepage := Some(url("https://github.com/gnieh/diffson")), parallelExecution := false, scalacOptions ++= PartialFunction.condOpt(CrossVersion.partialVersion(scalaVersion.value)) { @@ -81,7 +74,7 @@ lazy val core = crossProject(JSPlatform, JVMPlatform) .crossType(CrossType.Pure).in(file("core")) .enablePlugins(ScoverageSbtPlugin, ScalaUnidocPlugin) .settings(commonSettings: _*) - .settings(bintraySettings) + .settings(publishSettings) .settings( name := "diffson-core", crossScalaVersions := Seq(scala212, scala213), @@ -124,7 +117,7 @@ lazy val playJson = crossProject(JSPlatform, JVMPlatform) .crossType(CrossType.Full).in(file("playJson")) .enablePlugins(ScoverageSbtPlugin) .settings(commonSettings: _*) - .settings(bintraySettings) + .settings(publishSettings) .settings( name := "diffson-play-json", libraryDependencies += "com.typesafe.play" %%% "play-json" % "2.8.1", diff --git a/project/plugins.sbt b/project/plugins.sbt index 87fe9123..489e0f48 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -9,5 +9,3 @@ addSbtPlugin("com.codacy" % "sbt-codacy-coverage" % "3.0.2") addSbtPlugin("org.portable-scala" % "sbt-scalajs-crossproject" % "1.0.0") addSbtPlugin("org.scala-js" % "sbt-scalajs" % "0.6.32") - -addSbtPlugin("org.foundweekends" % "sbt-bintray" % "0.5.6") \ No newline at end of file