diff --git a/tools/src/com/github/condaincubator/condaenvbuilder/api/CondaStep.scala b/tools/src/com/github/condaincubator/condaenvbuilder/api/CondaStep.scala index 040106a..ad5a462 100644 --- a/tools/src/com/github/condaincubator/condaenvbuilder/api/CondaStep.scala +++ b/tools/src/com/github/condaincubator/condaenvbuilder/api/CondaStep.scala @@ -1,16 +1,19 @@ package com.github.condaincubator.condaenvbuilder.api -import CondaStep.Channel +import com.github.condaincubator.condaenvbuilder.api.CondaStep.Channel +import com.github.condaincubator.condaenvbuilder.api.Platform.Platform import io.circe.Decoder.Result import io.circe.syntax._ import io.circe.{Decoder, Encoder, HCursor, Json} +import scala.collection.mutable.ArrayBuffer + /** Specifies the conda channels and requirements for a conda environment. * * @param channels the conda channels, in priority order * @param requirements the package requirements. */ -case class CondaStep(channels: Seq[Channel]=Seq.empty, requirements: Seq[Requirement]=Seq.empty) extends StepWithDefaults { +case class CondaStep(channels: Seq[Channel]=Seq.empty, requirements: Seq[Requirement]=IndexedSeq.empty, platforms: Seq[Platform]=IndexedSeq.empty) extends StepWithDefaults { /** Inherit (in-order) channels and requirements from the given step(s). * @@ -23,6 +26,7 @@ case class CondaStep(channels: Seq[Channel]=Seq.empty, requirements: Seq[Require this.copy( channels = (steps.flatMap(_.channels) ++ this.channels).distinct, requirements = Requirement.join(parent=steps.flatMap(_.requirements), child=requirements), + platforms = (steps.flatMap(_.platforms) ++ this.platforms).distinct, ) } @@ -36,6 +40,7 @@ case class CondaStep(channels: Seq[Channel]=Seq.empty, requirements: Seq[Require this.copy( channels = (this.channels ++ _defaults.channels).distinct, requirements = Requirement.withDefaults(requirements=this.requirements, defaults=_defaults.requirements), + platforms = (this.platforms ++ _defaults.platforms).distinct, ) case _ => this } @@ -50,6 +55,10 @@ case class CondaStep(channels: Seq[Channel]=Seq.empty, requirements: Seq[Require * requirements: * - samtools * - fgbio=1.1.0 + * platforms: + * - linux-32 + * - osx-arm64 + * - win32 * }}} * * Both `channels` and `requirements` are optional. @@ -63,10 +72,13 @@ object CondaStep { /** Returns an YAML encoder for [[CondaStep]] */ def encoder: Encoder[CondaStep] = new Encoder[CondaStep] { - final def apply(step: CondaStep): Json = Json.obj( - ("channels", Json.fromValues(step.channels.map(_.asJson))), - ("requirements", Json.fromValues(step.requirements.map(_.asJson))) - ) + final def apply(step: CondaStep): Json = { + val fields = ArrayBuffer[(String, Json)]() + fields.append(("channels", Json.fromValues(step.channels.map(_.asJson)))) + fields.append(("requirements", Json.fromValues(step.requirements.map(_.asJson)))) + if (step.platforms.nonEmpty) fields.append(("platforms", Json.fromValues(step.platforms.map(_.asJson)))) + Json.obj(fields.toSeq:_*) + } } /** Returns a YAML decoder for [[CondaStep]] */ @@ -86,11 +98,17 @@ object CondaStep { else Right(Seq.empty) } + val platformResults: Result[Seq[Platform]] = { + if (keys.contains("platforms")) c.downField("platforms").as[Seq[Platform]] + else Right(Seq.empty) + } + for { channels <- channelsResults requirements <- requirementsResults + platforms <- platformResults } yield { - CondaStep(channels=channels, requirements=requirements) + CondaStep(channels=channels, requirements=requirements, platforms=platforms) } } } diff --git a/tools/src/com/github/condaincubator/condaenvbuilder/api/Platform.scala b/tools/src/com/github/condaincubator/condaenvbuilder/api/Platform.scala new file mode 100644 index 0000000..f239278 --- /dev/null +++ b/tools/src/com/github/condaincubator/condaenvbuilder/api/Platform.scala @@ -0,0 +1,6 @@ +package com.github.condaincubator.condaenvbuilder.api + +/** The name of the platform (e.g. linux-32, linux-armv7l, win-64, osx-arm64) */ +object Platform { + type Platform = String +} diff --git a/tools/test/src/com/github/condaincubator/condaenvbuilder/api/CondaStepTest.scala b/tools/test/src/com/github/condaincubator/condaenvbuilder/api/CondaStepTest.scala index a4e9534..1207fd6 100644 --- a/tools/test/src/com/github/condaincubator/condaenvbuilder/api/CondaStepTest.scala +++ b/tools/test/src/com/github/condaincubator/condaenvbuilder/api/CondaStepTest.scala @@ -15,19 +15,22 @@ object CondaStepTest extends UnitSpec { | ] |}""".stripMargin }), - // one channel, one requirement - (api.CondaStep(channels=Seq("some channel"), requirements=Seq("a==1").reqs), { + // one channel, one requirement, one platform + (api.CondaStep(channels=Seq("some channel"), requirements=Seq("a==1").reqs, platforms=Seq("linux-32")), { """{ | "channels" : [ | "some channel" | ], | "requirements" : [ | "a==1" + | ], + | "platforms" : [ + | "linux-32" | ] |}""".stripMargin }), - // multiple channels and requirements - (api.CondaStep(channels=Seq("channel 1", "channel 2"), requirements=Seq("a==1", "b==2").reqs), { + // multiple channels, requirements, and platforms + (api.CondaStep(channels=Seq("channel 1", "channel 2"), requirements=Seq("a==1", "b==2").reqs, platforms=Seq("linux-32", "win-32")), { """{ | "channels" : [ | "channel 1", @@ -36,11 +39,15 @@ object CondaStepTest extends UnitSpec { | "requirements" : [ | "a==1", | "b==2" + | ], + | "platforms" : [ + | "linux-32", + | "win-32" | ] |}""".stripMargin }), // empty requirements, empty channels - (CondaStep(channels=Seq.empty, requirements=Seq.empty), { + (CondaStep(channels=Seq.empty, requirements=Seq.empty, platforms=Seq.empty), { """{ | "channels" : [ | ], diff --git a/tools/test/src/com/github/condaincubator/condaenvbuilder/tools/ToolsTest.scala b/tools/test/src/com/github/condaincubator/condaenvbuilder/tools/ToolsTest.scala index 8f9775a..000b28c 100644 --- a/tools/test/src/com/github/condaincubator/condaenvbuilder/tools/ToolsTest.scala +++ b/tools/test/src/com/github/condaincubator/condaenvbuilder/tools/ToolsTest.scala @@ -24,6 +24,8 @@ class ToolsTest extends UnitSpec { | - python=3.6.10 | - samtools=1.10 | - yaml=0.1.7 + | platforms: + | - linux-32 | - pip: | requirements: | - defopt==5.1.0 @@ -81,6 +83,8 @@ class ToolsTest extends UnitSpec { | requirements: | - pybedtools=0.8.1 | - yaml=0.1.7 + | platforms: + | - linux-32 | - pip: | args: [] | requirements: @@ -101,6 +105,8 @@ class ToolsTest extends UnitSpec { | requirements: | - samtools=1.9 | - hisat2=2.2.0 + | platforms: + | - linux-32 | bwa: | group: alignment | steps: @@ -111,6 +117,8 @@ class ToolsTest extends UnitSpec { | requirements: | - samtools=1.9 | - bwa=0.7.17 + | platforms: + | - linux-32 | samtools: | group: alignment | steps: @@ -119,7 +127,9 @@ class ToolsTest extends UnitSpec { | - conda-forge | - bioconda | requirements: - | - samtools=1.9""".stripMargin + | - samtools=1.9 + | platforms: + | - linux-32""".stripMargin } val tabulatedString: String = { @@ -150,6 +160,8 @@ class ToolsTest extends UnitSpec { | - bioconda | requirements: | - samtools=1.9 + | platforms: + | - linux-32 | bwa: | group: alignment | steps: @@ -160,6 +172,8 @@ class ToolsTest extends UnitSpec { | requirements: | - samtools=1.9 | - bwa=0.7.17 + | platforms: + | - linux-32 | hisat2: | group: alignment | steps: @@ -170,6 +184,8 @@ class ToolsTest extends UnitSpec { | requirements: | - samtools=1.9 | - hisat2=2.2.0 + | platforms: + | - linux-32 | conda-env-builder: | group: conda-env-builder | steps: @@ -181,6 +197,8 @@ class ToolsTest extends UnitSpec { | - pybedtools=0.8.1 | - yaml=0.1.7 | - pip==default + | platforms: + | - linux-32 | - pip: | args: [] | requirements: @@ -206,6 +224,8 @@ class ToolsTest extends UnitSpec { | - bioconda | requirements: | - samtools=1.9 + | platforms: + | - linux-32 | bwa: | group: alignment | steps: @@ -216,6 +236,8 @@ class ToolsTest extends UnitSpec { | requirements: | - samtools=1.9 | - bwa=0.7.17 + | platforms: + | - linux-32 | hisat2: | group: alignment | steps: @@ -226,6 +248,8 @@ class ToolsTest extends UnitSpec { | requirements: | - samtools=1.9 | - hisat2=2.2.0 + | platforms: + | - linux-32 | conda-env-builder: | group: conda-env-builder | steps: @@ -236,6 +260,8 @@ class ToolsTest extends UnitSpec { | requirements: | - pybedtools=0.8.1 | - yaml=0.1.7 + | platforms: + | - linux-32 | - pip: | args: [] | requirements: