Compare commits

..

No commits in common. "master" and "1.4.0" have entirely different histories.

24 changed files with 387 additions and 366 deletions

View file

@ -17,7 +17,7 @@ jobs:
build: build:
strategy: strategy:
matrix: matrix:
java-version: [8, 11, 17, 21] java-version: [ 11, 17, 20 ]
os: os:
- macos-latest - macos-latest
- ubuntu-latest - ubuntu-latest
@ -28,25 +28,27 @@ jobs:
GRADLE_OPTS: "-Dorg.gradle.jvmargs=-XX:MaxMetaspaceSize=512m" GRADLE_OPTS: "-Dorg.gradle.jvmargs=-XX:MaxMetaspaceSize=512m"
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v3
- name: Set up JDK ${{ matrix.java-version }} - name: Set up JDK ${{ matrix.java-version }}
uses: actions/setup-java@v4 uses: actions/setup-java@v3
with: with:
distribution: "zulu" distribution: 'zulu'
java-version: ${{ matrix.java-version }} java-version: ${{ matrix.java-version }}
- name: Validate Gradle wrapper - name: Validate Gradle wrapper
uses: gradle/wrapper-validation-action@v2 uses: gradle/wrapper-validation-action@v1
- name: Cache Kotlin Konan - name: Cache Kotlin Konan
uses: actions/cache@v4 id: cache-kotlin-konan
uses: actions/cache@v3
with: with:
path: ~/.konan/**/* path: |
~/.konan/**/*
key: kotlin-konan-${{ runner.os }} key: kotlin-konan-${{ runner.os }}
- name: Set up Gradle - name: Test with Gradle
uses: gradle/actions/setup-gradle@v3 uses: gradle/gradle-build-action@v2
with:
- name: Publish gradle-home-cache-cleanup: true
run: ./gradlew check build --stacktrace -PtestsBadgeApiKey=${{ secrets.TESTS_BADGE_API_KEY }} arguments: build check --stacktrace -PtestsBadgeApiKey=${{ secrets.TESTS_BADGE_API_KEY }}

View file

@ -4,41 +4,90 @@ on:
workflow_dispatch: workflow_dispatch:
env: env:
JAVA_VERSION: 11
JAVA_DISTRIBUTION: 'zulu'
ORG_GRADLE_PROJECT_ossrhUsername: ${{ secrets.OSSRH_USERNAME}} ORG_GRADLE_PROJECT_ossrhUsername: ${{ secrets.OSSRH_USERNAME}}
ORG_GRADLE_PROJECT_ossrhPassword: ${{ secrets.OSSRH_PASSWORD}} ORG_GRADLE_PROJECT_ossrhPassword: ${{ secrets.OSSRH_PASSWORD}}
ORG_GRADLE_PROJECT_signingKey: ${{ secrets.SIGN_SECRET_KEY }} ORG_GRADLE_PROJECT_signingKey: ${{ secrets.SIGN_SECRET_KEY }}
ORG_GRADLE_PROJECT_signingPassword: ${{ secrets.SIGN_SECRET_PWD }} ORG_GRADLE_PROJECT_signingPassword: ${{ secrets.SIGN_SECRET_PWD }}
concurrency:
group: "${{ github.workflow }} @ ${{ github.event.pull_request.head.label || github.head_ref || github.ref }}"
# Don't cancel midway through publishing if another workflow is triggered, it might cause partial publications
cancel-in-progress: false
jobs: jobs:
publish: publish-base:
runs-on: macos-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@v3
- name: Set up JDK - name: Set up JDK ${{ env.JAVA_VERSION }}
uses: actions/setup-java@v4 uses: actions/setup-java@v3
with: with:
java-version: "21" java-version: ${{ env.JAVA_VERSION }}
distribution: "zulu" distribution: ${{ env.JAVA_DISTRIBUTION }}
- name: Validate Gradle wrapper - uses: gradle/gradle-build-action@v2
uses: gradle/wrapper-validation-action@v2
- name: Cache Kotlin Konan - name: Publish Multiplatform release
uses: actions/cache@v4 run: ./gradlew publishKotlinMultiplatformPublicationToOSSRHRepository
- name: Publish JVM release
run: ./gradlew publishJvmPublicationToOSSRHRepository
- name: Publish JS release
run: ./gradlew publishJsPublicationToOSSRHRepository
publish-linux:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Set up JDK ${{ env.JAVA_VERSION }}
uses: actions/setup-java@v3
with: with:
path: ~/.konan/**/* java-version: ${{ env.JAVA_VERSION }}
key: kotlin-konan-${{ runner.os }} distribution: ${{ env.JAVA_DISTRIBUTION }}
- name: Set up Gradle - uses: gradle/gradle-build-action@v2
uses: gradle/actions/setup-gradle@v3
- name: Publish Linux x64 release
run: ./gradlew publishLinuxX64PublicationToOSSRHRepository
publish-mac:
runs-on: macos-latest
strategy:
max-parallel: 6
matrix:
target:
- publishMacosArm64PublicationToOSSRHRepository
- publishMacosX64PublicationToOSSRHRepository
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Set up JDK ${{ env.JAVA_VERSION }}
uses: actions/setup-java@v3
with:
java-version: ${{ env.JAVA_VERSION }}
distribution: ${{ env.JAVA_DISTRIBUTION }}
- uses: gradle/gradle-build-action@v2
- name: Publish - name: Publish
run: ./gradlew publish --no-parallel --stacktrace run: ./gradlew ${{ matrix.target }}
publish-windows:
runs-on: windows-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Set up JDK ${{ env.JAVA_VERSION }}
uses: actions/setup-java@v3
with:
java-version: ${{ env.JAVA_VERSION }}
distribution: ${{ env.JAVA_DISTRIBUTION }}
- uses: gradle/gradle-build-action@v2
- name: Publish MinGW x64 release
run: ./gradlew publishMingwX64PublicationToOSSRHRepository

View file

@ -1,5 +1,5 @@
[![License](https://img.shields.io/badge/license-Apache%20License%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) [![License](https://img.shields.io/badge/license-Apache%20License%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
[![Kotlin](https://img.shields.io/badge/kotlin-1.6%2B-blue)](https://kotlinlang.org/) [![Kotlin](https://img.shields.io/badge/kotlin-1.9.0-blue)](https://kotlinlang.org/)
[![Nexus Snapshot](https://img.shields.io/nexus/s/net.thauvin.erik.urlencoder/urlencoder-lib?label=snapshot&server=https%3A%2F%2Foss.sonatype.org%2F)](https://oss.sonatype.org/content/repositories/snapshots/net/thauvin/erik/urlencoder/) [![Nexus Snapshot](https://img.shields.io/nexus/s/net.thauvin.erik.urlencoder/urlencoder-lib?label=snapshot&server=https%3A%2F%2Foss.sonatype.org%2F)](https://oss.sonatype.org/content/repositories/snapshots/net/thauvin/erik/urlencoder/)
[![Release](https://img.shields.io/github/release/ethauvin/urlencoder.svg)](https://github.com/ethauvin/urlencoder/releases/latest) [![Release](https://img.shields.io/github/release/ethauvin/urlencoder.svg)](https://github.com/ethauvin/urlencoder/releases/latest)
[![Maven Central](https://img.shields.io/maven-central/v/net.thauvin.erik.urlencoder/urlencoder-lib)](https://central.sonatype.com/search?namespace=net.thauvin.erik.urlencoder) [![Maven Central](https://img.shields.io/maven-central/v/net.thauvin.erik.urlencoder/urlencoder-lib)](https://central.sonatype.com/search?namespace=net.thauvin.erik.urlencoder)
@ -32,17 +32,18 @@ optimizations have a significantly beneficial impact on performance of encoding
compared to other solutions like the standard `URLEncoder` in the JDK or compared to other solutions like the standard `URLEncoder` in the JDK or
`UriUtils` in Spring. `UriUtils` in Spring.
## Examples (TL;DR) ## Examples (TL;DR)
```kotlin ```kotlin
UrlEncoderUtil.encode("a test &") // -> a%20test%20%26 UrlEncoder.encode("a test &") // -> a%20test%20%26
UrlEncoderUtil.encode("%#okékÉȢ smile!😁") // -> %25%23ok%C3%A9k%C3%89%C8%A2%20smile%21%F0%9F%98%81 UrlEncoder.encode("%#okékÉȢ smile!😁") // -> %25%23ok%C3%A9k%C3%89%C8%A2%20smile%21%F0%9F%98%81
UrlEncoderUtil.encode("?test=a test", allow = "?=") // -> ?test=a%20test UrlEncoder.encode("?test=a test", allow = "?=") // -> ?test=a%20test
UrlEncoderUtil.endode("foo bar", spaceToPlus = true) // -> foo+bar UrlEncoder.endode("foo bar", spaceToPlus = true) // -> foo+bar
UrlEncoderUtil.decode("a%20test%20%26") // -> a test & UrlEncoder.decode("a%20test%20%26") // -> a test &
UrlEncoderUtil.decode("%25%23ok%C3%A9k%C3%89%C8%A2%20smile%21%F0%9F%98%81") // -> %#okékÉȢ smile!😁 UrlEncoder.decode("%25%23ok%C3%A9k%C3%89%C8%A2%20smile%21%F0%9F%98%81") // -> %#okékÉȢ smile!😁
UrlEncoderUtil.decode("foo+bar", plusToSpace = true) // -> foo bar UrlEncoder.decode("foo+bar", plusToSpace = true) // -> foo bar
``` ```
## Gradle, Maven, etc. ## Gradle, Maven, etc.
@ -60,7 +61,7 @@ repositories {
} }
dependencies { dependencies {
implementation("net.thauvin.erik.urlencoder:urlencoder-lib:1.6.0") implementation("net.thauvin.erik.urlencoder:urlencoder-lib:1.4.0")
} }
``` ```
@ -71,7 +72,7 @@ to the artifact URL.
<dependency> <dependency>
<groupId>net.thauvin.erik.urlencoder</groupId> <groupId>net.thauvin.erik.urlencoder</groupId>
<artifactId>urlencoder-lib-jvm</artifactId> <artifactId>urlencoder-lib-jvm</artifactId>
<version>1.6.0</version> <version>1.4.0</version>
</dependency> </dependency>
``` ```
@ -89,7 +90,7 @@ You have two options:
The usage is as follows: The usage is as follows:
```console ```
Encode and decode URL components defensively. Encode and decode URL components defensively.
-e encode (default) -e encode (default)
-d decode -d decode
@ -97,7 +98,7 @@ Encode and decode URL components defensively.
### Running with Gradle ### Running with Gradle
```console ```shell
./gradlew run --quiet --args="-e 'a test &'" # -> a%20test%20%26 ./gradlew run --quiet --args="-e 'a test &'" # -> a%20test%20%26
./gradlew run --quiet --args="%#okékÉȢ" # -> %25%23ok%C3%A9k%C3%89%C8%A2 ./gradlew run --quiet --args="%#okékÉȢ" # -> %25%23ok%C3%A9k%C3%89%C8%A2
@ -108,13 +109,13 @@ Encode and decode URL components defensively.
First build the jar file: First build the jar file:
```console ```shell
./gradlew fatJar ./gradlew fatJar
``` ```
Then run it: Then run it:
```console ```shell
java -jar urlencoder-app/build/libs/urlencoder-*all.jar -e "a test &" # -> a%20test%20%26 java -jar urlencoder-app/build/libs/urlencoder-*all.jar -e "a test &" # -> a%20test%20%26
java -jar urlencoder-app/build/libs/urlencoder-*all.jar "%#okékÉȢ" # -> %25%23ok%C3%A9k%C3%89%C8%A2 java -jar urlencoder-app/build/libs/urlencoder-*all.jar "%#okékÉȢ" # -> %25%23ok%C3%A9k%C3%89%C8%A2

View file

@ -4,7 +4,7 @@ plugins {
} }
group = "net.thauvin.erik.urlencoder" group = "net.thauvin.erik.urlencoder"
version = "1.6.0" version = "1.4.0"
dependencies { dependencies {
kover(projects.urlencoderLib) kover(projects.urlencoderLib)

View file

@ -3,10 +3,9 @@ plugins {
} }
dependencies { dependencies {
implementation("com.github.ben-manes:gradle-versions-plugin:0.51.0") implementation("com.github.ben-manes:gradle-versions-plugin:0.48.0")
implementation("io.gitlab.arturbosch.detekt:detekt-gradle-plugin:1.23.7") implementation("io.gitlab.arturbosch.detekt:detekt-gradle-plugin:1.23.1")
implementation("org.jetbrains.dokka:dokka-gradle-plugin:1.9.20") implementation("org.jetbrains.dokka:dokka-gradle-plugin:1.9.0")
implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.24") implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.0")
implementation("org.jetbrains.kotlinx:kover-gradle-plugin:0.8.3") implementation("org.jetbrains.kotlinx:kover-gradle-plugin:0.7.3")
implementation("org.apache.httpcomponents:httpclient:4.5.13")
} }

View file

@ -3,9 +3,7 @@ package buildsrc.conventions.lang
import buildsrc.utils.Rife2TestListener import buildsrc.utils.Rife2TestListener
import org.gradle.api.tasks.testing.logging.TestExceptionFormat import org.gradle.api.tasks.testing.logging.TestExceptionFormat
import org.gradle.api.tasks.testing.logging.TestLogEvent import org.gradle.api.tasks.testing.logging.TestLogEvent
import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi
import org.jetbrains.kotlin.gradle.dsl.JvmTarget import org.jetbrains.kotlin.gradle.dsl.JvmTarget
import org.jetbrains.kotlin.gradle.dsl.KotlinVersion
import org.jetbrains.kotlin.gradle.targets.jvm.KotlinJvmTarget import org.jetbrains.kotlin.gradle.targets.jvm.KotlinJvmTarget
import org.jetbrains.kotlin.gradle.tasks.KotlinJvmCompile import org.jetbrains.kotlin.gradle.tasks.KotlinJvmCompile
@ -26,31 +24,39 @@ plugins {
kotlin { kotlin {
//jvmToolchain(11) //jvmToolchain(11)
applyDefaultHierarchyTemplate() targets.configureEach {
compilations.configureEach {
@OptIn(ExperimentalKotlinGradlePluginApi::class) kotlinOptions {
compilerOptions { languageVersion = "1.6"
languageVersion = KotlinVersion.KOTLIN_1_6 }
}
} }
// configure all Kotlin/JVM Tests to use JUnit // configure all Kotlin/JVM Tests to use JUnit
targets.withType<KotlinJvmTarget>().configureEach { targets.withType<KotlinJvmTarget>().configureEach {
testRuns.configureEach { testRuns.configureEach {
executionTask.configure { executionTask.configure {
useJUnitPlatform() // useJUnitPlatform()
} }
} }
} }
sourceSets.configureEach {
languageSettings {
// languageVersion =
// apiVersion =
}
}
} }
tasks { tasks {
withType<JavaCompile>().configureEach { withType<JavaCompile>().configureEach {
sourceCompatibility = JavaVersion.VERSION_1_8.toString() sourceCompatibility = JavaVersion.VERSION_11.toString()
targetCompatibility = JavaVersion.VERSION_1_8.toString() targetCompatibility = JavaVersion.VERSION_11.toString()
} }
withType<KotlinJvmCompile>().configureEach { withType<KotlinJvmCompile>().configureEach {
compilerOptions.jvmTarget.set(JvmTarget.JVM_1_8) compilerOptions.jvmTarget.set(JvmTarget.JVM_11)
} }
withType<Test>().configureEach { withType<Test>().configureEach {

View file

@ -1,7 +1,5 @@
package buildsrc.conventions.lang package buildsrc.conventions.lang
import org.jetbrains.kotlin.gradle.targets.js.dsl.ExperimentalWasmDsl
/** conventions for a Kotlin/JS subproject */ /** conventions for a Kotlin/JS subproject */
plugins { plugins {
@ -9,38 +7,12 @@ plugins {
} }
kotlin { kotlin {
targets {
js(IR) { js(IR) {
browser() browser()
nodejs() nodejs()
} }
@OptIn(ExperimentalWasmDsl::class)
wasmJs {
browser()
nodejs()
}
@OptIn(ExperimentalWasmDsl::class)
wasmWasi {
nodejs()
} }
} }
relocateKotlinJsStore() relocateKotlinJsStore()
//region FIXME: WORKAROUND https://youtrack.jetbrains.com/issue/KT-65864
rootProject.plugins.withType<org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin> {
rootProject.extensions.configure<org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootExtension> {
// Use a Node.js version current enough to support Kotlin/Wasm
nodeVersion = "22.0.0-nightly2024010568c8472ed9"
logger.lifecycle("Using Node.js $nodeVersion to support Kotlin/Wasm")
nodeDownloadBaseUrl = "https://nodejs.org/download/nightly"
}
}
rootProject.tasks.withType<org.jetbrains.kotlin.gradle.targets.js.npm.tasks.KotlinNpmInstallTask>().configureEach {
// Prevent Yarn from complaining about newer Node.js versions.
args.add("--ignore-engines")
}
//endregion

View file

@ -7,26 +7,94 @@ plugins {
} }
kotlin { kotlin {
// Native targets all extend commonMain and commonTest.
//
// Some targets (ios, tvos, watchos) are shortcuts provided by the Kotlin DSL, that
// provide additional targets, except for 'simulators' which must be defined manually.
// https://kotlinlang.org/docs/multiplatform-share-on-platforms.html#use-target-shortcuts
//
// common/
// └── native/
// ├── linuxX64
// ├── mingwX64
// ├── macosX64
// ├── macosArm64
// ├── ios/ (shortcut)
// │ ├── iosArm64
// │ ├── iosX64
// │ └── iosSimulatorArm64
// ├── tvos/ (shortcut)
// │ ├── tvosArm64
// │ ├── tvosX64
// │ └── tvosSimulatorArm64Main
// └── watchos/ (shortcut)
// ├── watchosArm32
// ├── watchosArm64
// ├── watchosX64
// └── watchosSimulatorArm64Main
linuxX64() linuxX64()
mingwX64() mingwX64()
linuxArm64()
macosX64() macosX64()
macosArm64() macosArm64()
iosArm64() // https://kotlinlang.org/docs/multiplatform-share-on-platforms.html#use-target-shortcuts
iosX64() ios() // iosArm64, iosX64
watchos() // watchosArm32, watchosArm64, watchosX64
tvos() // tvosArm64, tvosX64
iosSimulatorArm64() iosSimulatorArm64()
watchosArm32()
watchosArm64()
watchosX64()
watchosSimulatorArm64()
watchosDeviceArm64()
tvosArm64()
tvosX64()
tvosSimulatorArm64() tvosSimulatorArm64()
watchosSimulatorArm64()
@Suppress("UNUSED_VARIABLE")
sourceSets {
val commonMain by getting {}
val commonTest by getting {}
val nativeMain by creating { dependsOn(commonMain) }
val nativeTest by creating { dependsOn(commonTest) }
// Linux
val linuxX64Main by getting { dependsOn(nativeMain) }
val linuxX64Test by getting { dependsOn(nativeTest) }
// Windows - MinGW
val mingwX64Main by getting { dependsOn(nativeMain) }
val mingwX64Test by getting { dependsOn(nativeTest) }
// Apple - macOS
val macosArm64Main by getting { dependsOn(nativeMain) }
val macosArm64Test by getting { dependsOn(nativeTest) }
val macosX64Main by getting { dependsOn(nativeMain) }
val macosX64Test by getting { dependsOn(nativeTest) }
// Apple - iOS
val iosMain by getting { dependsOn(nativeMain) }
val iosTest by getting { dependsOn(nativeTest) }
// val iosSimulatorArm64Main by getting { dependsOn(iosMain) }
// val iosSimulatorArm64Test by getting { dependsOn(iosTest) }
// // Apple - tvOS
// val tvosMain by getting { dependsOn(nativeMain) }
// val tvosTest by getting { dependsOn(nativeTest) }
// val tvosSimulatorArm64Main by getting { dependsOn(tvosMain) }
// val tvosSimulatorArm64Test by getting { dependsOn(tvosTest) }
// // Apple - watchOS
// val watchosMain by getting { dependsOn(nativeMain) }
// val watchosTest by getting { dependsOn(nativeTest) }
// val watchosSimulatorArm64Main by getting { dependsOn(watchosMain) }
// val watchosSimulatorArm64Test by getting { dependsOn(watchosTest) }
// val iosArm32Main by getting { dependsOn(desktopMain) }
// val iosArm32Test by getting { dependsOn(nativeTest) }
}
} }

View file

@ -1,3 +1,19 @@
/*
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
* Copyright 2022-2023 Erik C. Thauvin (erik@thauvin.net)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package buildsrc.conventions package buildsrc.conventions
plugins { plugins {
@ -82,12 +98,10 @@ signing {
}) })
} }
tasks { tasks.withType<Sign>().configureEach {
withType<Sign>().configureEach {
val signingRequiredPredicate = provider { signing.isRequired } val signingRequiredPredicate = provider { signing.isRequired }
onlyIf { signingRequiredPredicate.get() } onlyIf { signingRequiredPredicate.get() }
} }
}
// https://youtrack.jetbrains.com/issue/KT-46466 // https://youtrack.jetbrains.com/issue/KT-46466
val signingTasks = tasks.withType<Sign>() val signingTasks = tasks.withType<Sign>()

View file

@ -1,11 +1,12 @@
/* /*
* Copyright 2001-2024 the original author or authors. * Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
* Copyright 2022-2023 Erik C. Thauvin (erik@thauvin.net)
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* https://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
@ -16,13 +17,14 @@
package buildsrc.utils package buildsrc.utils
import org.apache.http.client.methods.HttpPost
import org.apache.http.impl.client.HttpClients
import org.apache.http.util.EntityUtils
import org.gradle.api.provider.Provider import org.gradle.api.provider.Provider
import org.gradle.api.tasks.testing.TestDescriptor import org.gradle.api.tasks.testing.TestDescriptor
import org.gradle.api.tasks.testing.TestListener import org.gradle.api.tasks.testing.TestListener
import org.gradle.api.tasks.testing.TestResult import org.gradle.api.tasks.testing.TestResult
import java.net.URI
import java.net.http.HttpClient
import java.net.http.HttpRequest
import java.net.http.HttpResponse
class Rife2TestListener( class Rife2TestListener(
private val testBadgeApiKey: Provider<String> private val testBadgeApiKey: Provider<String>
@ -40,23 +42,23 @@ class Rife2TestListener(
if (apiKey != null) { if (apiKey != null) {
println(apiKey) println(apiKey)
val url = "https://rife2.com/tests-badge/update/net.thauvin.erik/urlencoder?" + val response: HttpResponse<String> = HttpClient.newHttpClient()
.send(
HttpRequest.newBuilder()
.uri(
URI(
"https://rife2.com/tests-badge/update/net.thauvin.erik/urlencoder?" +
"apiKey=$apiKey&" + "apiKey=$apiKey&" +
"passed=$passed&" + "passed=$passed&" +
"failed=$failed&" + "failed=$failed&" +
"skipped=$skipped" "skipped=$skipped"
)
val client = HttpClients.createDefault() )
val post = HttpPost(url) .POST(HttpRequest.BodyPublishers.noBody())
.build(), HttpResponse.BodyHandlers.ofString()
val response = client.execute(post) )
val entity = response.entity println("RESPONSE: ${response.statusCode()}")
println(response.body())
val statusCode = response.statusLine.statusCode
val responseBody = EntityUtils.toString(entity, "UTF-8")
println("RESPONSE: $statusCode")
println(responseBody)
} }
} }
} }

Binary file not shown.

View file

@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-bin.zip
networkTimeout=10000 networkTimeout=10000
validateDistributionUrl=true validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME

21
gradlew vendored
View file

@ -15,8 +15,6 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
# #
# SPDX-License-Identifier: Apache-2.0
#
############################################################################## ##############################################################################
# #
@ -57,7 +55,7 @@
# Darwin, MinGW, and NonStop. # Darwin, MinGW, and NonStop.
# #
# (3) This script is generated from the Groovy template # (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project. # within the Gradle project.
# #
# You can find Gradle at https://github.com/gradle/gradle/. # You can find Gradle at https://github.com/gradle/gradle/.
@ -86,8 +84,7 @@ done
# shellcheck disable=SC2034 # shellcheck disable=SC2034
APP_BASE_NAME=${0##*/} APP_BASE_NAME=${0##*/}
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
' "$PWD" ) || exit
# Use the maximum available, or set MAX_FD != -1 to use that value. # Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum MAX_FD=maximum
@ -148,7 +145,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #( case $MAX_FD in #(
max*) max*)
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC2039,SC3045 # shellcheck disable=SC3045
MAX_FD=$( ulimit -H -n ) || MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit" warn "Could not query maximum file descriptor limit"
esac esac
@ -156,7 +153,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
'' | soft) :;; #( '' | soft) :;; #(
*) *)
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC2039,SC3045 # shellcheck disable=SC3045
ulimit -n "$MAX_FD" || ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD" warn "Could not set maximum file descriptor limit to $MAX_FD"
esac esac
@ -205,11 +202,11 @@ fi
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Collect all arguments for the java command: # Collect all arguments for the java command;
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, # * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
# and any embedded shellness will be escaped. # shell script including quotes and variable substitutions, so put them in
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be # double quotes to make sure that they get re-expanded; and
# treated as '${Hostname}' itself on the command line. # * put everything else in single quotes, so that it's not re-expanded.
set -- \ set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \ "-Dorg.gradle.appname=$APP_BASE_NAME" \

22
gradlew.bat vendored
View file

@ -13,8 +13,6 @@
@rem See the License for the specific language governing permissions and @rem See the License for the specific language governing permissions and
@rem limitations under the License. @rem limitations under the License.
@rem @rem
@rem SPDX-License-Identifier: Apache-2.0
@rem
@if "%DEBUG%"=="" @echo off @if "%DEBUG%"=="" @echo off
@rem ########################################################################## @rem ##########################################################################
@ -45,11 +43,11 @@ set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1 %JAVA_EXE% -version >NUL 2>&1
if %ERRORLEVEL% equ 0 goto execute if %ERRORLEVEL% equ 0 goto execute
echo. 1>&2 echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo. 1>&2 echo.
echo Please set the JAVA_HOME variable in your environment to match the 1>&2 echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation. 1>&2 echo location of your Java installation.
goto fail goto fail
@ -59,11 +57,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute if exist "%JAVA_EXE%" goto execute
echo. 1>&2 echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo. 1>&2 echo.
echo Please set the JAVA_HOME variable in your environment to match the 1>&2 echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation. 1>&2 echo location of your Java installation.
goto fail goto fail

View file

@ -20,23 +20,14 @@ dependencyResolutionManagement {
// Declare the Node.js & Yarn download repositories // Declare the Node.js & Yarn download repositories
exclusiveContent { exclusiveContent {
forRepositories( forRepository {
ivy("https://nodejs.org/dist/") { ivy("https://nodejs.org/dist/") {
name = "Node Distributions at $url" name = "Node Distributions at $url"
patternLayout { artifact("v[revision]/[artifact](-v[revision]-[classifier]).[ext]") } patternLayout { artifact("v[revision]/[artifact](-v[revision]-[classifier]).[ext]") }
metadataSources { artifact() } metadataSources { artifact() }
}, content { includeModule("org.nodejs", "node") }
ivy("https://nodejs.org/download/v8-canary/") { }
name = "Node Canary Distributions at $url" }
patternLayout { artifact("v[revision]/[artifact](-v[revision]-[classifier]).[ext]") }
metadataSources { artifact() }
},
ivy("https://nodejs.org/download/nightly/") {
name = "Node Nightly Distributions at $url"
patternLayout { artifact("v[revision]/[artifact](-v[revision]-[classifier]).[ext]") }
metadataSources { artifact() }
},
)
filter { includeGroup("org.nodejs") } filter { includeGroup("org.nodejs") }
} }
@ -46,6 +37,7 @@ dependencyResolutionManagement {
name = "Yarn Distributions at $url" name = "Yarn Distributions at $url"
patternLayout { artifact("v[revision]/[artifact](-v[revision]).[ext]") } patternLayout { artifact("v[revision]/[artifact](-v[revision]).[ext]") }
metadataSources { artifact() } metadataSources { artifact() }
content { includeModule("com.yarnpkg", "yarn") }
} }
} }
filter { includeGroup("com.yarnpkg") } filter { includeGroup("com.yarnpkg") }

View file

@ -1,21 +1,17 @@
import org.jetbrains.dokka.gradle.DokkaTask import org.jetbrains.dokka.gradle.DokkaTask
import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi
plugins { plugins {
buildsrc.conventions.lang.`kotlin-multiplatform-jvm` buildsrc.conventions.lang.`kotlin-multiplatform-jvm`
// buildsrc.conventions.lang.`kotlin-multiplatform-js`
// buildsrc.conventions.lang.`kotlin-multiplatform-native`
buildsrc.conventions.publishing buildsrc.conventions.publishing
id("application")
id("com.github.ben-manes.versions") id("com.github.ben-manes.versions")
} }
val urlEncoderMainClass = "net.thauvin.erik.urlencoder.UrlEncoder" val urlEncoderMainClass = "net.thauvin.erik.urlencoder.UrlEncoder"
kotlin { kotlin {
jvm {
@OptIn(ExperimentalKotlinGradlePluginApi::class)
mainRun {
mainClass.set(urlEncoderMainClass)
}
}
sourceSets { sourceSets {
commonMain { commonMain {
dependencies { dependencies {
@ -36,6 +32,10 @@ base {
archivesName.set(rootProject.name) archivesName.set(rootProject.name)
} }
application {
mainClass.set(urlEncoderMainClass)
}
tasks { tasks {
jvmJar { jvmJar {
manifest { manifest {
@ -45,13 +45,14 @@ tasks {
val fatJar by registering(Jar::class) { val fatJar by registering(Jar::class) {
group = LifecycleBasePlugin.BUILD_GROUP group = LifecycleBasePlugin.BUILD_GROUP
dependsOn.addAll(listOf("compileJava", "compileKotlinJvm", "processResources"))
archiveClassifier.set("all") archiveClassifier.set("all")
duplicatesStrategy = DuplicatesStrategy.EXCLUDE duplicatesStrategy = DuplicatesStrategy.EXCLUDE
manifest { attributes(mapOf("Main-Class" to urlEncoderMainClass)) } manifest { attributes(mapOf("Main-Class" to application.mainClass)) }
from(sourceSets.main.map { it.output }) from(sourceSets.main.get().output)
dependsOn(configurations.jvmRuntimeClasspath) dependsOn(configurations.jvmRuntimeClasspath)
from(configurations.jvmRuntimeClasspath.map { classpath -> from(configurations.jvmRuntimeClasspath.map { classpath ->
classpath.filter { it.name.endsWith(".jar") }.map { zipTree(it) } classpath.incoming.artifacts.artifactFiles.files.filter { it.name.endsWith("jar") }.map { zipTree(it) }
}) })
} }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright 2001-2024 the original author or authors. * Copyright 2001-2023 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.

View file

@ -1,5 +1,5 @@
/* /*
* Copyright 2001-2024 the original author or authors. * Copyright 2001-2023 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.

View file

@ -1,5 +1,5 @@
/* /*
* Copyright 2001-2024 the original author or authors. * Copyright 2001-2023 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.

View file

@ -1,5 +1,5 @@
/* /*
* Copyright 2001-2024 the original author or authors. * Copyright 2001-2023 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.

View file

@ -1,43 +0,0 @@
/*
* Copyright 2001-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.thauvin.erik.urlencoder
import kotlin.jvm.JvmField
const val standardContent = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVQXYZ0123456789-_."
val invalidContent = listOf("sdkjfh%", "sdkjfh%6", "sdkjfh%xx", "sdfjfh%-1")
/**
* List of unencoded content paired with the encoded content.
*/
val decodedToEncoded = listOf(
TestData("a test &", "a%20test%20%26"),
TestData(
"!abcdefghijklmnopqrstuvwxyz%%ABCDEFGHIJKLMNOPQRSTUVQXYZ0123456789-_.~=",
"%21abcdefghijklmnopqrstuvwxyz%25%25ABCDEFGHIJKLMNOPQRSTUVQXYZ0123456789-_.%7E%3D"
),
TestData("%#okékÉȢ smile!😁", "%25%23ok%C3%A9k%C3%89%C8%A2%20smile%21%F0%9F%98%81"),
TestData("\uD808\uDC00\uD809\uDD00\uD808\uDF00\uD808\uDD00", "%F0%92%80%80%F0%92%94%80%F0%92%8C%80%F0%92%84%80"),
)
data class TestData(
@JvmField
val unencoded: String,
@JvmField
val encoded: String,
)

View file

@ -1,5 +1,5 @@
/* /*
* Copyright 2001-2024 the original author or authors. * Copyright 2001-2023 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -23,17 +23,30 @@ import kotlin.test.DefaultAsserter.assertEquals
import kotlin.test.DefaultAsserter.assertSame import kotlin.test.DefaultAsserter.assertSame
class UrlEncoderUtilTest { class UrlEncoderUtilTest {
private val same = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVQXYZ0123456789-_."
companion object {
val invalid = listOf("sdkjfh%", "sdkjfh%6", "sdkjfh%xx", "sdfjfh%-1")
val validMap = listOf(
"a test &" to "a%20test%20%26",
"!abcdefghijklmnopqrstuvwxyz%%ABCDEFGHIJKLMNOPQRSTUVQXYZ0123456789-_.~=" to
"%21abcdefghijklmnopqrstuvwxyz%25%25ABCDEFGHIJKLMNOPQRSTUVQXYZ0123456789-_.%7E%3D",
"%#okékÉȢ smile!😁" to "%25%23ok%C3%A9k%C3%89%C8%A2%20smile%21%F0%9F%98%81",
"\uD808\uDC00\uD809\uDD00\uD808\uDF00\uD808\uDD00" to "%F0%92%80%80%F0%92%94%80%F0%92%8C%80%F0%92%84%80",
)
}
@Test @Test
fun decodeURL() { fun decodeURL() {
for ((unencoded, encoded) in decodedToEncoded) { for (m in validMap) {
assertEquals(unencoded, decode(encoded)) assertEquals(m.first, decode(m.second))
} }
} }
@Test @Test
fun decodeWithException() { fun decodeWithException() {
for (source in invalidContent) { for (source in invalid) {
assertFailsWith<IllegalArgumentException>( assertFailsWith<IllegalArgumentException>(
message = "decode($source)", message = "decode($source)",
block = { decode(source) } block = { decode(source) }
@ -43,7 +56,7 @@ class UrlEncoderUtilTest {
@Test @Test
fun decodeWhenNoneNeeded() { fun decodeWhenNoneNeeded() {
assertSame(standardContent, decode(standardContent)) assertSame(same, decode(same))
assertEquals("decode('')", decode(""), "") assertEquals("decode('')", decode(""), "")
assertEquals("decode(' ')", decode(" "), " ") assertEquals("decode(' ')", decode(" "), " ")
} }
@ -59,8 +72,8 @@ class UrlEncoderUtilTest {
@Test @Test
fun encodeURL() { fun encodeURL() {
for ((unencoded, encoded) in decodedToEncoded) { for (m in validMap) {
assertEquals(encoded, encode(unencoded)) assertEquals(m.second, encode(m.first))
} }
} }
@ -73,8 +86,8 @@ class UrlEncoderUtilTest {
@Test @Test
fun encodeWhenNoneNeeded() { fun encodeWhenNoneNeeded() {
assertSame(encode(standardContent), standardContent) assertSame(encode(same), same)
assertSame("with empty allow", encode(standardContent, allow = ""), standardContent) assertSame("with empty allow", encode(same, allow = ""), same)
} }
@Test @Test

View file

@ -1,50 +0,0 @@
/*
* Copyright 2001-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.thauvin.erik.urlencoder;
import org.junit.jupiter.api.Test;
import static net.thauvin.erik.urlencoder.TestDataKt.getDecodedToEncoded;
import static net.thauvin.erik.urlencoder.UrlEncoderUtil.decode;
import static net.thauvin.erik.urlencoder.UrlEncoderUtil.encode;
import static org.junit.jupiter.api.Assertions.assertAll;
import static org.junit.jupiter.api.Assertions.assertEquals;
class UrlEncoderJavaTest {
@Test
public void decodeURL() {
assertAll(
getDecodedToEncoded()
.stream()
.map(data ->
() -> assertEquals(data.unencoded, decode(data.encoded))
)
);
}
@Test
public void encodeURL() {
assertAll(
getDecodedToEncoded()
.stream()
.map(data ->
() -> assertEquals(data.encoded, encode(data.unencoded))
)
);
}
}