Skip to content

Commit

Permalink
Merge pull request #3 from Project-Cepi/master
Browse files Browse the repository at this point in the history
Fix up dependency getter, and use Path instead of File
  • Loading branch information
jglrxavpok authored Oct 30, 2021
2 parents 90201e8 + af69651 commit 066247f
Show file tree
Hide file tree
Showing 12 changed files with 113 additions and 125 deletions.
23 changes: 2 additions & 21 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,27 +21,7 @@ gradle-app.setting
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839

# User-specific stuff
.idea/**/workspace.xml
.idea/**/tasks.xml
.idea/**/usage.statistics.xml
.idea/**/dictionaries
.idea/**/shelf

# Generated files
.idea/**/contentModel.xml

# Sensitive or high-churn files
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml
.idea/**/dbnavigator.xml

# Gradle
.idea/**/gradle.xml
.idea/**/libraries
.idea/

# Gradle and Maven with auto-import
# When using Gradle or Maven with auto-import, you should exclude module files,
Expand Down Expand Up @@ -114,3 +94,4 @@ fabric.properties
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*

test_output
24 changes: 0 additions & 24 deletions build.gradle

This file was deleted.

32 changes: 32 additions & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
plugins {
// Apply the Kotlin JVM plugin to add support for Kotlin.
id("org.jetbrains.kotlin.jvm") version "1.5.31"

java
}
group = "net.minestom"
version = "1.0.0"

repositories {
mavenCentral()
}

dependencies {

// Use the Kotlin JDK 8 standard library.
implementation(kotlin("stdlib", "1.5.0"))

// Add shrinkwrap resolver
implementation("org.jboss.shrinkwrap.resolver:shrinkwrap-resolver-depchain:3.1.4")

// Use the kotlin test library
testImplementation("io.kotest:kotest-assertions-core:4.6.3")
testImplementation("io.kotest:kotest-runner-junit5:4.6.3")
}

tasks {
withType<Test> { useJUnitPlatform() }
}

val compileKotlin: org.jetbrains.kotlin.gradle.tasks.KotlinCompile by tasks
compileKotlin.kotlinOptions.jvmTarget = JavaVersion.VERSION_16.toString()
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.3-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
3 changes: 0 additions & 3 deletions settings.gradle

This file was deleted.

3 changes: 3 additions & 0 deletions settings.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@

rootProject.name = "DependencyGetter"

13 changes: 6 additions & 7 deletions src/main/kotlin/net/minestom/dependencies/DependencyGetter.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,30 +3,29 @@ package net.minestom.dependencies
import net.minestom.dependencies.maven.MavenRepository
import net.minestom.dependencies.maven.MavenResolver
import java.io.File
import java.nio.file.Path

class DependencyGetter {

private val resolverList = mutableListOf<DependencyResolver>()
val resolvers: List<DependencyResolver> get()= resolvers

fun addResolver(resolver: DependencyResolver): DependencyGetter {
resolverList += resolver
return this
}
fun addResolver(resolver: DependencyResolver)
= apply { resolverList += resolver }

/**
* Shorthand to add a MavenResolver with the given repositories
*/
fun addMavenResolver(repositories: List<MavenRepository>) = addResolver(MavenResolver(repositories))

fun get(id: String, targetFolder: File): ResolvedDependency {
for(resolver in resolverList) {
fun get(id: String, targetFolder: Path): ResolvedDependency {
resolverList.forEach { resolver ->
try {
return resolver.resolve(id, targetFolder)
} catch (e: UnresolvedDependencyException) {
// silence and go to next resolver
}
}

throw UnresolvedDependencyException("Could not find $id inside resolver list: ${resolverList.joinToString { it.toString() }}")
}
}
21 changes: 3 additions & 18 deletions src/main/kotlin/net/minestom/dependencies/DependencyResolver.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package net.minestom.dependencies

import java.io.File
import java.net.URL
import java.nio.file.Path
import kotlin.jvm.Throws

/**
Expand All @@ -15,20 +15,5 @@ interface DependencyResolver {
* @throws UnresolvedDependencyException if the dependency could not be resolved via this resolver
*/
@Throws(UnresolvedDependencyException::class)
fun resolve(id: String, targetFolder: File): ResolvedDependency
}

/**
* Resolved Dependency.
* Holds its coordinates (group, artifact, version), which are allowed to be empty if needed
*
* The contentsLocation URL represents the location of the dependency, on local storage.
*/
data class ResolvedDependency(val group: String, val name: String, val version: String, val contentsLocation: URL, val subdependencies: List<ResolvedDependency>) {
fun printTree(indent: String = "") {
println("$indent- $group:$name:$version ($contentsLocation)")
for (dep in subdependencies) {
dep.printTree("$indent ")
}
}
}
fun resolve(id: String, targetFolder: Path): ResolvedDependency
}
19 changes: 19 additions & 0 deletions src/main/kotlin/net/minestom/dependencies/ResolvedDependency.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package net.minestom.dependencies

import java.net.URL

/**
* Resolved Dependency.
* Holds its coordinates (group, artifact, version), which are allowed to be empty if needed
*
* The contentsLocation URL represents the location of the dependency, on local storage.
*/
data class ResolvedDependency(
val group: String, val name: String, val version: String,
val contentsLocation: URL, val subdependencies: List<ResolvedDependency>
) {
fun printTree(indent: String = "") {
println("$indent- $group:$name:$version ($contentsLocation)")
subdependencies.forEach { it.printTree("$indent ") }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,5 @@ import java.lang.Exception
/**
* Thrown when a given dependency could not be found inside the given resolvers
*/
class UnresolvedDependencyException(msg: String, cause: Throwable?): Exception(msg, cause) {
constructor(msg: String): this(msg, null)
}
class UnresolvedDependencyException @JvmOverloads constructor(msg: String, cause: Throwable? = null)
: Exception(msg, cause)
53 changes: 25 additions & 28 deletions src/main/kotlin/net/minestom/dependencies/maven/MavenResolver.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import org.jboss.shrinkwrap.resolver.api.CoordinateParseException
import org.jboss.shrinkwrap.resolver.api.NoResolvedResultException
import org.jboss.shrinkwrap.resolver.api.maven.Maven
import org.jboss.shrinkwrap.resolver.api.maven.MavenResolvedArtifact
import java.io.File
import java.util.logging.LogManager
import java.nio.file.Files
import java.nio.file.Path

/**
* Resolves maven dependencies.
Expand All @@ -24,12 +24,12 @@ class MavenResolver(val repositories: List<MavenRepository>): DependencyResolver
/**
* Resolves and downloads maven artifacts related to the given id.
*/
override fun resolve(id: String, targetFolder: File): ResolvedDependency {
val tmpFolder = File(targetFolder, ".tmp")
override fun resolve(id: String, targetFolder: Path): ResolvedDependency {
val tmpFolder = targetFolder.resolve(".tmp")
try {
// create a temporary settings file to change the local maven repository and remote repositories
tmpFolder.mkdirs()
val settingsFile = File(tmpFolder, "settings.xml")
Files.createDirectories(tmpFolder)
val settingsFile = tmpFolder.resolve("settings.xml")
val repoList =
(repositories.joinToString("") { repo -> """
<repository>
Expand All @@ -40,38 +40,35 @@ class MavenResolver(val repositories: List<MavenRepository>): DependencyResolver
</repository>
""" })
// create the temporary settings.xml file
settingsFile.writeText("""
<settings xmlns="http://maven.apache.org/SETTINGS/1.1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.1.0 http://maven.apache.org/xsd/settings-1.1.0.xsd">
<localRepository>${targetFolder.absolutePath}</localRepository>
<profiles>
<profile>
<id>dependency-getter-auto</id>
<repositories>
$repoList
</repositories>
</profile>
</profiles>
<activeProfiles>
<activeProfile>dependency-getter-auto</activeProfile>
</activeProfiles>
</settings>
""")
Files.writeString(settingsFile, """
<settings xmlns="http://maven.apache.org/SETTINGS/1.1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.1.0 http://maven.apache.org/xsd/settings-1.1.0.xsd">
<localRepository>${targetFolder.toAbsolutePath()}</localRepository>
<profiles>
<profile>
<id>dependency-getter-auto</id>
<repositories>
$repoList
</repositories>
</profile>
</profiles>
<activeProfiles>
<activeProfile>dependency-getter-auto</activeProfile>
</activeProfiles>
</settings>
""".trimIndent())
// ShrinkWrap Resolver either always uses Central, or never, even if it is in the remote repositories
val hasMavenCentral = repositories.any { it.url.sameFile(MavenRepository.Central.url) }
val resolver = Maven.configureResolver().withMavenCentralRepo(hasMavenCentral).fromFile(settingsFile)
val resolver = Maven.configureResolver().withMavenCentralRepo(hasMavenCentral).fromFile(settingsFile.toFile())
val artifacts = resolver.resolve(id).withTransitivity().asResolvedArtifact()
val dependencies = mutableListOf<ResolvedDependency>()
for(dep in artifacts.drop(1)) { // [0] is the 'root' because we always resolve one artifact at once
dependencies += convertToDependency(dep)
}
val dependencies = artifacts.drop(1).map(::convertToDependency)
val coords = artifacts[0].coordinate
return ResolvedDependency(coords.groupId, coords.artifactId, coords.version, artifacts[0].asFile().toURI().toURL(), dependencies)
} catch(e: CoordinateParseException) {
throw UnresolvedDependencyException("Failed to resolve $id (not a Maven coordinate)", e)
} catch(e: NoResolvedResultException) {
throw UnresolvedDependencyException("Failed to resolve $id", e)
} finally {
tmpFolder.deleteRecursively() // ensure the temporary settings.xml is actually temporary
Files.walk(tmpFolder).sorted(Comparator.reverseOrder()).forEach(Files::delete) // ensure the temporary settings.xml is actually temporary
}
}

Expand Down
40 changes: 20 additions & 20 deletions src/test/kotlin/Tests.kt
Original file line number Diff line number Diff line change
@@ -1,30 +1,30 @@
import io.kotest.assertions.throwables.shouldThrow
import io.kotest.core.spec.style.AnnotationSpec
import io.kotest.matchers.shouldBe
import net.minestom.dependencies.DependencyGetter
import net.minestom.dependencies.DependencyResolver
import net.minestom.dependencies.ResolvedDependency
import net.minestom.dependencies.UnresolvedDependencyException
import net.minestom.dependencies.maven.MavenRepository
import net.minestom.dependencies.maven.MavenResolver
import org.junit.jupiter.api.AfterAll
import org.junit.jupiter.api.Assertions.*
import org.junit.jupiter.api.BeforeAll
import org.junit.jupiter.api.Test
import java.io.File
import java.nio.file.Files
import java.nio.file.Path

class Tests {
class Tests : AnnotationSpec() {

companion object {
private val targetFolder = File(".", "test_output/")
private val targetFolder = Path.of(".", "test_output/")

@BeforeAll
@JvmStatic
fun init() {
targetFolder.mkdirs()
Files.createDirectories(targetFolder)
}

@AfterAll
@JvmStatic
fun cleanup() {
targetFolder.deleteRecursively()
Files.walk(targetFolder).sorted(Comparator.reverseOrder()).forEach(Files::delete)
}

}
Expand All @@ -37,10 +37,10 @@ class Tests {
val resolver = MavenResolver(repositories)
val resolved = resolver.resolve("com.google.guava:guava:30.0-jre", targetFolder)
resolved.printTree()
assertEquals("com.google.guava", resolved.group)
assertEquals("guava", resolved.name)
assertEquals("30.0-jre", resolved.version)
assertEquals(File(targetFolder, "com/google/guava/guava/30.0-jre/guava-30.0-jre.jar").toURI().toURL().toExternalForm(), resolved.contentsLocation.toExternalForm())
resolved.group shouldBe "com.google.guava"
resolved.name shouldBe "guava"
resolved.version shouldBe "30.0-jre"
resolved.contentsLocation.toExternalForm() shouldBe targetFolder.resolve( "com/google/guava/guava/30.0-jre/guava-30.0-jre.jar").toUri().toURL().toExternalForm()
}

@Test
Expand All @@ -55,26 +55,26 @@ class Tests {
val resolver = MavenResolver(repositories)
val resolved = resolver.resolve("com.github.Minestom:Minestom:32d13dcbd1", targetFolder)
resolved.printTree()
assertEquals("com.github.Minestom", resolved.group)
assertEquals("Minestom", resolved.name)
assertEquals("32d13dcbd1", resolved.version)
resolved.group shouldBe "com.github.Minestom"
resolved.name shouldBe "Minestom"
resolved.version shouldBe "32d13dcbd1"
}

@Test
fun throwIfNotFound() {
assertThrows(UnresolvedDependencyException::class.java) {
shouldThrow<UnresolvedDependencyException> {
val repositories = listOf(
MavenRepository.Jitpack,
)
val resolver = MavenResolver(repositories)
val resolved = resolver.resolve("com.google.guava:guava:30.0-jre", targetFolder)
resolver.resolve("com.google.guava:guava:30.0-jre", targetFolder)
}
}

@Test
fun helloDependency() {
class MyResolver: DependencyResolver {
override fun resolve(id: String, targetFolder: File): ResolvedDependency {
override fun resolve(id: String, targetFolder: Path): ResolvedDependency {
throw UnresolvedDependencyException(id)
}
}
Expand All @@ -90,7 +90,7 @@ class Tests {
))
val resolved = dependencyGetter.get("com.github.Minestom:Minestom:32d13dcbd1", targetFolder)
resolved.printTree()
assertThrows(UnresolvedDependencyException::class.java) {
shouldThrow<UnresolvedDependencyException> {
dependencyGetter.get("somethingthatdoesnotexist.xyz", targetFolder)
}
}
Expand Down

0 comments on commit 066247f

Please sign in to comment.