Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 29 additions & 11 deletions .github/scripts/ci.sh
Original file line number Diff line number Diff line change
@@ -1,21 +1,39 @@
#!/usr/bin/env bash
set -exo pipefail

export COURSIER_JNI="force"

TEST_VERSION="0.1.0-test"

echo "Running tests and eviction checks"
sbt \
+test \
+evictionCheck \
+mimaReportBinaryIssues \
'set version in ThisBuild := "'"$TEST_VERSION"'"' \
publishLocal
+evictionCheck

IS_UNIX="false"
case "$(uname -s)" in
Linux*) IS_UNIX="true";;
Darwin*) IS_UNIX="true";;
*)
esac

if [ "$IS_UNIX" == "true" ]; then
echo "Running MiMA checks"
sbt +mimaReportBinaryIssues

# test that things work from JDK 11
# not actually building things from it, running into weird proguard issues…
echo "Publishing locally"
sbt \
'set version in ThisBuild := "'"$TEST_VERSION"'"' \
publishLocal
echo "Running JDK 11 tests…"
# test that things work from JDK 11
# not actually building things from it, running into weird proguard issues…

TEST_JDK="adopt:1.11.0-7"
eval "$(cs java --jvm "$TEST_JDK" --env)"
TEST_JDK="adopt:1.11.0-7"
eval "$(cs java --jvm "$TEST_JDK" --env)"

java -Xmx32m -version
java -Xmx32m -version

export TEST_VERSION
sbt test
export TEST_VERSION
sbt test
fi
8 changes: 7 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,12 @@ on:

jobs:
test:
runs-on: ubuntu-latest
runs-on: ${{ matrix.OS }}
name: Test ${{ matrix.OS }}
strategy:
fail-fast: false
matrix:
OS: ["ubuntu-latest", "macos-latest", "windows-latest"]
steps:
- uses: actions/checkout@v2
with:
Expand All @@ -22,6 +27,7 @@ jobs:
apps: sbt
- name: Test
run: ./.github/scripts/ci.sh
shell: bash

publish:
needs: test
Expand Down
26 changes: 23 additions & 3 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ lazy val interface = project
val dest = orig.getParentFile / s"${orig.getName.stripSuffix(".jar")}-with-renaming-test.jar"
if (!dest.exists() || dest.lastModified() < origLastModified) {
val tmpDest = orig.getParentFile / s"${orig.getName.stripSuffix(".jar")}-with-renaming-test-0.jar"
val tmpDest1 = orig.getParentFile / s"${orig.getName.stripSuffix(".jar")}-with-renaming-test-1.jar"

def rename(from: String, to: String): Rule = {
val rule = new Rule
Expand Down Expand Up @@ -76,14 +77,28 @@ lazy val interface = project
assert(directoriesToBeRemoved.forall(_.endsWith("/")))
ZipUtil.removeFromZip(
tmpDest,
dest,
tmpDest1,
name =>
toBeRemoved(name) || directoriesToBeRemoved.exists(dir =>
name.startsWith(dir)
)
)

tmpDest.delete()

val serviceContent =
ZipUtil.zipEntryContent(orig, "META-INF/services/coursier.jniutils.NativeApi").getOrElse {
sys.error(s"META-INF/services/coursier.jniutils.NativeApi not found in $orig")
}

ZipUtil.addToZip(
tmpDest1,
dest,
Seq(
"META-INF/services/coursierapi.shaded.coursier.jniutils.NativeApi" -> serviceContent
)
)

tmpDest1.delete()
}
Check.onlyNamespace("coursierapi", dest)
dest
Expand Down Expand Up @@ -123,6 +138,7 @@ lazy val interface = project
Proguard / proguardInputFilter := { file =>
file.name match {
case n if n.startsWith("interface") => None // keep META-INF from main JAR
case n if n.startsWith("windows-jni-utils") => Some("!META-INF/MANIFEST.MF")
case n if n.startsWith("coursier-core") => Some("!META-INF/**,!coursier.properties,!coursier/coursier.properties")
case n if n.startsWith("scala-xml") => Some("!META-INF/**,!scala-xml.properties")
case n if n.startsWith("scala-library") => Some("!META-INF/**,!library.properties,!rootdoc.txt")
Expand All @@ -146,7 +162,10 @@ lazy val interface = project

Settings.shared,
Settings.mima(),
libraryDependencies += "io.get-coursier" %% "coursier" % "2.1.0-M2-1",
libraryDependencies ++= Seq(
"io.get-coursier" %% "coursier" % "2.1.0-M2-1",
"io.get-coursier.jniutils" % "windows-jni-utils-coursierapi" % "0.3.2"
),

libraryDependencies += "com.lihaoyi" %% "utest" % "0.7.10" % Test,
testFrameworks += new TestFramework("utest.runner.Framework"),
Expand Down Expand Up @@ -245,4 +264,5 @@ lazy val `interface-test` = project
)

publish / skip := true
Settings.shared
disablePlugins(MimaPlugin)
3 changes: 1 addition & 2 deletions interface/src/main/java/coursierapi/error/CoursierError.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ public abstract class CoursierError extends Exception {
}

public static CoursierError of(String message) {
return new CoursierError(message) {
};
return new SimpleCoursierError(message);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package coursierapi.error;

class SimpleCoursierError extends CoursierError {

SimpleCoursierError(String message) {
super(message);
}
}
96 changes: 70 additions & 26 deletions project/ZipUtil.scala
Original file line number Diff line number Diff line change
@@ -1,50 +1,76 @@

import java.util.zip.{ZipEntry, ZipInputStream, ZipOutputStream}
import java.io.{ByteArrayOutputStream, File, FileInputStream, FileOutputStream, InputStream}
import java.util.zip.{ZipEntry, ZipFile, ZipInputStream, ZipOutputStream}

object ZipUtil {

private def readFullySync(is: InputStream) = {
val buffer = new ByteArrayOutputStream
val data = Array.ofDim[Byte](16384)

var nRead = is.read(data, 0, data.length)
while (nRead != -1) {
buffer.write(data, 0, nRead)
nRead = is.read(data, 0, data.length)
}

buffer.flush()
buffer.toByteArray
}

private def zipEntries(zipStream: ZipInputStream): Iterator[(ZipEntry, Array[Byte])] =
new Iterator[(ZipEntry, Array[Byte])] {
private var nextEntry = Option.empty[ZipEntry]
private def update() =
nextEntry = Option(zipStream.getNextEntry)

update()

def hasNext = nextEntry.nonEmpty
def next() = {
val ent = nextEntry.get
val data = readFullySync(zipStream)

update()

(ent, data)
}
}

def removeFromZip(sourceZip: File, destZip: File, remove: String => Boolean): Unit = {

val is = new FileInputStream(sourceZip)
val os = new FileOutputStream(destZip)
val bootstrapZip = new ZipInputStream(is)
val outputZip = new ZipOutputStream(os)

def readFullySync(is: InputStream) = {
val buffer = new ByteArrayOutputStream
val data = Array.ofDim[Byte](16384)
for ((ent, data) <- zipEntries(bootstrapZip) if !remove(ent.getName)) {

var nRead = is.read(data, 0, data.length)
while (nRead != -1) {
buffer.write(data, 0, nRead)
nRead = is.read(data, 0, data.length)
}
// Same workaround as https://github.com/spring-projects/spring-boot/issues/13720
// (https://github.com/spring-projects/spring-boot/commit/a50646b7cc3ad941e748dfb450077e3a73706205#diff-2ff64cd06c0b25857e3e0dfdb6733174R144)
ent.setCompressedSize(-1L)

buffer.flush()
buffer.toByteArray
outputZip.putNextEntry(ent)
outputZip.write(data)
outputZip.closeEntry()
}

def zipEntries(zipStream: ZipInputStream): Iterator[(ZipEntry, Array[Byte])] =
new Iterator[(ZipEntry, Array[Byte])] {
private var nextEntry = Option.empty[ZipEntry]
private def update() =
nextEntry = Option(zipStream.getNextEntry)
outputZip.finish()
outputZip.close()

update()
is.close()
os.close()

def hasNext = nextEntry.nonEmpty
def next() = {
val ent = nextEntry.get
val data = readFullySync(zipStream)
}

update()
def addToZip(sourceZip: File, destZip: File, toAdd: Seq[(String, Array[Byte])]): Unit = {

(ent, data)
}
}
val is = new FileInputStream(sourceZip)
val os = new FileOutputStream(destZip)
val bootstrapZip = new ZipInputStream(is)
val outputZip = new ZipOutputStream(os)

for ((ent, data) <- zipEntries(bootstrapZip) if !remove(ent.getName)) {
for ((ent, data) <- zipEntries(bootstrapZip)) {

// Same workaround as https://github.com/spring-projects/spring-boot/issues/13720
// (https://github.com/spring-projects/spring-boot/commit/a50646b7cc3ad941e748dfb450077e3a73706205#diff-2ff64cd06c0b25857e3e0dfdb6733174R144)
Expand All @@ -55,11 +81,29 @@ object ZipUtil {
outputZip.closeEntry()
}

for ((name, content) <- toAdd) {
val ent = new ZipEntry(name)
outputZip.putNextEntry(ent)
outputZip.write(content)
outputZip.closeEntry()
}

outputZip.finish()
outputZip.close()

is.close()
os.close()

}

def zipEntryContent(sourceZip: File, entryName: String): Option[Array[Byte]] = {
val zf = new ZipFile(sourceZip)
val entryOpt = Option(zf.getEntry(entryName))
val content = entryOpt.map { entry =>
readFullySync(zf.getInputStream(entry))
}
zf.close()
content
}

}