diff --git a/.drone.yml b/.drone.yml index f98649cf..8c854060 100644 --- a/.drone.yml +++ b/.drone.yml @@ -45,56 +45,7 @@ steps: branch: - master --- -kind: pipeline -name: analysis - -steps: - - name: analysis - image: ghcr.io/nextcloud/continuous-integration-android8:4 - environment: - GIT_USERNAME: - from_secret: GIT_USERNAME - GIT_TOKEN: - from_secret: GIT_TOKEN - LOG_USERNAME: - from_secret: LOG_USERNAME - LOG_PASSWORD: - from_secret: LOG_PASSWORD - commands: - - scripts/checkIfRunDrone.sh $GIT_USERNAME $GIT_TOKEN $DRONE_PULL_REQUEST || exit 0 - - export BRANCH=$(scripts/analysis/getBranchName.sh $GIT_USERNAME $GIT_TOKEN $DRONE_PULL_REQUEST) - - scripts/analysis/analysis-wrapper.sh $GIT_USERNAME $GIT_TOKEN $BRANCH $LOG_USERNAME $LOG_PASSWORD $DRONE_BUILD_NUMBER $DRONE_PULL_REQUEST - - - name: notify - image: drillster/drone-email - settings: - port: 587 - from: nextcloud-drone@kaminsky.me - recipients_only: true - username: - from_secret: EMAIL_USERNAME - password: - from_secret: EMAIL_PASSWORD - recipients: - from_secret: EMAIL_RECIPIENTS - host: - from_secret: EMAIL_HOST - when: - event: - - push - status: - - failure - branch: - - master - -trigger: - branch: - - master - event: - - push - - pull_request ---- kind: signature -hmac: 89c97c7ee551bee0d6991c56f8673c0cb04478fa87eb9f2dc88d93710fc67f77 +hmac: 3853a8f64ae3aeef0f118c1b9d1a4b29af32f744dc32f608a7020dabd31d4a0b ... diff --git a/.github/workflows/analysis.yml b/.github/workflows/analysis.yml new file mode 100644 index 00000000..d38ab46a --- /dev/null +++ b/.github/workflows/analysis.yml @@ -0,0 +1,77 @@ +# synced from @nextcloud/android-config + +# SPDX-FileCopyrightText: 2023-2024 Nextcloud GmbH and Nextcloud contributors +# SPDX-FileCopyrightText: 2025 Alper Ozturk +# SPDX-FileCopyrightText: 2023 Tobias Kaminsky +# SPDX-FileCopyrightText: 2023 Andy Scherzinger +# SPDX-FileCopyrightText: 2023 Josh Richards +# SPDX-FileCopyrightText: 2025 Marcel Hibbe +# SPDX-License-Identifier: GPL-3.0-or-later + +name: "Analysis" + +on: + pull_request: + branches: [ "master", "main", "stable-*" ] + push: + branches: [ "master", "main", "stable-*" ] + +permissions: + pull-requests: write + contents: write + +concurrency: + group: analysis-wrapper-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +jobs: + analysis: + runs-on: ubuntu-latest + steps: + - name: Disabled on forks + if: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository }} + run: | + echo 'Can not analyze PRs from forks' + exit 1 + - name: Setup variables # zizmor: ignore[template-injection] + id: get-vars + run: | + if [ -z "$GITHUB_HEAD_REF" ]; then + # push + { + echo "branch=$GITHUB_REF_NAME" + echo "pr=$GITHUB_RUN_ID" + echo "repo=${{ github.repository }}" + } >> "$GITHUB_OUTPUT" + else + # pull request + { + echo "branch=$GITHUB_HEAD_REF" + echo "pr=${{ github.event.pull_request.number }}" + echo "repo=${{ github.event.pull_request.head.repo.full_name }}" + } >> "$GITHUB_OUTPUT" + fi + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + with: + persist-credentials: false + repository: ${{ steps.get-vars.outputs.repo }} + ref: ${{ steps.get-vars.outputs.branch }} + - name: Set up JDK 17 + uses: actions/setup-java@f2beeb24e141e01a676f977032f5a29d81c9e27e # v5.1.0 + with: + distribution: "temurin" + java-version: 17 + - name: Install dependencies + run: | + sudo apt install python3-defusedxml + - name: Run analysis wrapper + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + mkdir -p "$HOME/.gradle" + { + echo "org.gradle.jvmargs=-Xmx1g -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8" + echo "org.gradle.configureondemand=true" + echo "kapt.incremental.apt=true" + } > "$HOME/.gradle/gradle.properties" + scripts/analysis/analysis-wrapper.sh "${{ steps.get-vars.outputs.branch }}" "${{ secrets.LOG_USERNAME }}" "${{ secrets.LOG_PASSWORD }}" "$GITHUB_RUN_NUMBER" "${{ steps.get-vars.outputs.pr }}" diff --git a/.github/workflows/autoApproveSync.yml b/.github/workflows/autoApproveSync.yml new file mode 100644 index 00000000..c215be0b --- /dev/null +++ b/.github/workflows/autoApproveSync.yml @@ -0,0 +1,40 @@ +# synced from @nextcloud/android-config + +# SPDX-FileCopyrightText: 2022-2024 Nextcloud GmbH and Nextcloud contributors +# SPDX-FileCopyrightText: 2023 Álvaro Brey +# SPDX-License-Identifier: GPL-3.0-or-later + +name: Auto approve sync +on: + pull_request_target: # zizmor: ignore[dangerous-triggers] + branches: + - master + - main + types: + - opened + - reopened + - synchronize + - labeled + +concurrency: + group: sync-approve-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +permissions: + pull-requests: write + +jobs: + auto-approve: + name: Auto approve sync + runs-on: ubuntu-latest + if: ${{ contains(github.event.pull_request.labels.*.name, 'sync') && github.actor == 'nextcloud-android-bot' }} + steps: + - name: Disabled on forks + if: ${{ github.event.pull_request.head.repo.full_name != github.repository }} + run: | + echo 'Can not approve PRs from forks' + exit 1 + + - uses: hmarr/auto-approve-action@f0939ea97e9205ef24d872e76833fa908a770363 # v4.0.0 + with: + github-token: "${{ secrets.GITHUB_TOKEN }}" diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml new file mode 100644 index 00000000..6dd38e90 --- /dev/null +++ b/.github/workflows/check.yml @@ -0,0 +1,41 @@ +# SPDX-FileCopyrightText: 2017-2024 Nextcloud GmbH and Nextcloud contributors +# SPDX-FileCopyrightText: 2017 Tobias Kaminsky +# SPDX-License-Identifier: GPL-3.0-or-later +name: Check + +on: + pull_request: + branches: [ master, stable-* ] + push: + branches: [ master, stable-* ] + +permissions: + contents: read + +jobs: + check: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + task: [ lib:detekt, lib:spotlessKotlinCheck, lib:lint ] + steps: + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + - name: Set up JDK 17 + uses: actions/setup-java@f2beeb24e141e01a676f977032f5a29d81c9e27e # v5.1.0 + with: + distribution: "temurin" + java-version: 17 + - name: Setup JVM options + run: | + mkdir -p "$HOME/.gradle" + echo "org.gradle.jvmargs=-Xmx2g -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError" > "$HOME/.gradle/gradle.properties" + - name: Check ${{ matrix.task }} + uses: gradle/gradle-build-action@ac2d340dc04d9e1113182899e983b5400c17cda1 # v3.5.0 + with: + arguments: ${{ matrix.task }} + - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 + if: ${{ always() }} + with: + name: ${{ matrix.task }}-report + path: library/build/reports diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 00000000..722e8346 --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,60 @@ +# synced from @nextcloud/android-config + +# SPDX-FileCopyrightText: 2022-2024 Nextcloud GmbH and Nextcloud contributors +# SPDX-FileCopyrightText: 2023-2024 Andy Scherzinger +# SPDX-FileCopyrightText: 2022 Tobias Kaminsky +# SPDX-FileCopyrightText: 2022 Álvaro Brey +# SPDX-FileCopyrightText: 2025 Marcel Hibbe +# SPDX-License-Identifier: GPL-3.0-or-later + +name: "CodeQL" + +on: + push: + branches: [ "master", "main", "stable-*" ] + pull_request: + branches: [ "master", "main" ] + schedule: + - cron: '24 18 * * 3' + +permissions: + contents: read + +jobs: + analyze: + name: Analyze + runs-on: ubuntu-latest + permissions: + actions: read + contents: read + security-events: write + strategy: + fail-fast: false + matrix: + language: [ 'java' ] + steps: + - name: Checkout repository + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + with: + persist-credentials: false + - name: Set Swap Space + if: runner.environment == 'github-hosted' + uses: pierotofy/set-swap-space@49819abfb41bd9b44fb781159c033dba90353a7c # v1.0 + with: + swap-size-gb: 10 + - name: Initialize CodeQL + uses: github/codeql-action/init@cdefb33c0f6224e58673d9004f47f7cb3e328b89 # v4.31.10 + with: + languages: ${{ matrix.language }} + - name: Set up JDK 17 + uses: actions/setup-java@f2beeb24e141e01a676f977032f5a29d81c9e27e # v5.1.0 + with: + distribution: "temurin" + java-version: 17 + - name: Assemble + run: | + mkdir -p "$HOME/.gradle" + echo "org.gradle.jvmargs=-Xmx3g -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError" > "$HOME/.gradle/gradle.properties" + ./gradlew --no-daemon assembleDebug + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@cdefb33c0f6224e58673d9004f47f7cb3e328b89 # v4.31.10 diff --git a/.github/workflows/detectNewJavaFiles.yml b/.github/workflows/detectNewJavaFiles.yml new file mode 100644 index 00000000..908e3fd2 --- /dev/null +++ b/.github/workflows/detectNewJavaFiles.yml @@ -0,0 +1,43 @@ +# synced from @nextcloud/android-config + +# SPDX-FileCopyrightText: 2022-2024 Nextcloud GmbH and Nextcloud contributors +# SPDX-FileCopyrightText: 2023 Andy Scherzinger +# SPDX-FileCopyrightText: 2022 Tobias Kaminsky +# SPDX-FileCopyrightText: 2022 Álvaro Brey +# SPDX-License-Identifier: GPL-3.0-or-later + +name: "Detect new java files" + +on: + pull_request: + branches: [ master, main, stable-* ] + +permissions: read-all + +concurrency: + group: detect-new-java-files-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +jobs: + detectNewJavaFiles: + runs-on: ubuntu-latest + steps: + - id: file_changes + uses: trilom/file-changes-action@a6ca26c14274c33b15e6499323aac178af06ad4b # v1.2.4 + with: + output: ',' + - name: Detect new java files + run: | + if [ -z '${{ steps.file_changes.outputs.files_added }}' ]; then + echo "No new files added" + exit 0 + fi + new_java=$(echo '${{ steps.file_changes.outputs.files_added }}' | tr ',' '\n' | grep '\.java$' | cat) + if [ -n "$new_java" ]; then + # shellcheck disable=SC2016 + printf 'New java files detected:\n```\n%s\n```\n' "$new_java" | tee "$GITHUB_STEP_SUMMARY" + exit 1 + else + echo "No new java files detected" + exit 0 + fi diff --git a/.github/workflows/pr-feedback.yml b/.github/workflows/pr-feedback.yml new file mode 100644 index 00000000..a3a2d129 --- /dev/null +++ b/.github/workflows/pr-feedback.yml @@ -0,0 +1,55 @@ +# This workflow is provided via the organization template repository +# +# https://github.com/nextcloud/.github +# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization + +# SPDX-FileCopyrightText: 2023-2024 Nextcloud GmbH and Nextcloud contributors +# SPDX-FileCopyrightText: 2023 Marcel Klehr +# SPDX-FileCopyrightText: 2023 Joas Schilling <213943+nickvergessen@users.noreply.github.com> +# SPDX-FileCopyrightText: 2023 Daniel Kesselberg +# SPDX-FileCopyrightText: 2023 Florian Steffens +# SPDX-License-Identifier: MIT + +name: 'Ask for feedback on PRs' +on: + schedule: + - cron: '30 1 * * *' + +permissions: + contents: read + pull-requests: write + +jobs: + pr-feedback: + if: ${{ github.repository_owner == 'nextcloud' }} + runs-on: ubuntu-latest + steps: + - name: The get-github-handles-from-website action + uses: marcelklehr/get-github-handles-from-website-action@06b2239db0a48fe1484ba0bfd966a3ab81a08308 # v1.0.1 + id: scrape + with: + website: 'https://nextcloud.com/team/' + + - name: Get blocklist + id: blocklist + run: | + blocklist=$(curl https://raw.githubusercontent.com/nextcloud/.github/master/non-community-usernames.txt | paste -s -d, -) + echo "blocklist=$blocklist" >> "$GITHUB_OUTPUT" + + - uses: nextcloud/pr-feedback-action@5227c55be184087d0aef6338bee210d8620b6297 # main + with: + feedback-message: | + Hello there, + Thank you so much for taking the time and effort to create a pull request to our Nextcloud project. + + We hope that the review process is going smooth and is helpful for you. We want to ensure your pull request is reviewed to your satisfaction. If you have a moment, our community management team would very much appreciate your feedback on your experience with this PR review process. + + Your feedback is valuable to us as we continuously strive to improve our community developer experience. Please take a moment to complete our short survey by clicking on the following link: https://cloud.nextcloud.com/apps/forms/s/i9Ago4EQRZ7TWxjfmeEpPkf6 + + Thank you for contributing to Nextcloud and we hope to hear from you soon! + + (If you believe you should not receive this message, you can add yourself to the [blocklist](https://github.com/nextcloud/.github/blob/master/non-community-usernames.txt).) + days-before-feedback: 14 + start-date: '2024-04-30' + exempt-authors: '${{ steps.blocklist.outputs.blocklist }},${{ steps.scrape.outputs.users }}' + exempt-bots: true diff --git a/.github/workflows/renovate-approve-merge.yml b/.github/workflows/renovate-approve-merge.yml new file mode 100644 index 00000000..5551b180 --- /dev/null +++ b/.github/workflows/renovate-approve-merge.yml @@ -0,0 +1,61 @@ +# This workflow is provided via the organization template repository +# +# https://github.com/nextcloud/.github +# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization +# +# SPDX-FileCopyrightText: Nextcloud GmbH and Nextcloud contributors +# SPDX-License-Identifier: MIT + +name: Auto approve renovate PRs + +on: + pull_request_target: # zizmor: ignore[dangerous-triggers] + branches: + - main + - master + - stable* + +permissions: + contents: read + +concurrency: + group: renovate-approve-merge-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +jobs: + auto-approve-merge: + if: github.event.pull_request.user.login == 'renovate[bot]' + runs-on: ubuntu-latest + permissions: + # for hmarr/auto-approve-action to approve PRs + pull-requests: write + + steps: + - name: Disabled on forks + if: ${{ github.event.pull_request.head.repo.full_name != github.repository }} + run: | + echo 'Can not approve PRs from forks' + exit 1 + + - uses: mdecoleman/pr-branch-name@55795d86b4566d300d237883103f052125cc7508 # v3.0.0 + id: branchname + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + + # GitHub actions bot approve + - uses: hmarr/auto-approve-action@f0939ea97e9205ef24d872e76833fa908a770363 # v4.0.0 + if: github.actor == 'renovate[bot]' + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + with: + ref: ${{ github.head_ref }} + + # Enable GitHub auto merge + - name: Enable Pull Request Automerge + if: github.actor == 'renovate[bot]' + run: gh pr merge --merge --auto + env: + GH_TOKEN: ${{ secrets.AUTOMERGE }} + diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml new file mode 100644 index 00000000..63e25ecd --- /dev/null +++ b/.github/workflows/scorecard.yml @@ -0,0 +1,47 @@ +# synced from @nextcloud/android-config + +# SPDX-FileCopyrightText: 2023-2024 Nextcloud GmbH and Nextcloud contributors +# SPDX-FileCopyrightText: 2023 Andy Scherzinger +# SPDX-License-Identifier: GPL-3.0-or-later + +name: Scorecard supply-chain security +on: + branch_protection_rule: + schedule: + - cron: '32 23 * * 4' + push: + branches: [ "main", "master" ] + +# Declare default permissions as read only. +permissions: read-all + +concurrency: + group: scorecard-supply-chain-security-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +jobs: + analysis: + name: Scorecard analysis + runs-on: ubuntu-latest + permissions: + # Needed to upload the results to code-scanning dashboard. + security-events: write + + steps: + - name: "Checkout code" + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + with: + persist-credentials: false + + - name: "Run analysis" + uses: ossf/scorecard-action@4eaacf0543bb3f2c246792bd56e8cdeffafb205a # v2.4.3 + with: + results_file: results.sarif + results_format: sarif + publish_results: false + + # Upload the results to GitHub's code scanning dashboard. + - name: "Upload to code-scanning" + uses: github/codeql-action/upload-sarif@cdefb33c0f6224e58673d9004f47f7cb3e328b89 # v4.31.10 + with: + sarif_file: results.sarif diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml new file mode 100644 index 00000000..fe125a9a --- /dev/null +++ b/.github/workflows/stale.yml @@ -0,0 +1,35 @@ +# synced from @nextcloud/android-config + +# SPDX-FileCopyrightText: 2023-2024 Nextcloud GmbH and Nextcloud contributors +# SPDX-FileCopyrightText: 2023 Tobias Kaminsky +# SPDX-FileCopyrightText: 2022 Álvaro Brey +# SPDX-License-Identifier: GPL-3.0-or-later + +name: 'Close stale issues' +on: + schedule: + - cron: '0 0 * * *' + +# Declare default permissions as read only. +permissions: read-all + +jobs: + stale: + runs-on: ubuntu-latest + permissions: + issues: write + pull-requests: write + steps: + - uses: actions/stale@997185467fa4f803885201cee163a9f38240193d # v10.1.1 + with: + days-before-stale: 28 + days-before-close: 14 + days-before-pr-close: -1 + only-labels: 'bug,needs info' + exempt-issue-labels: 'no-stale' + stale-issue-message: >- + This bug report did not receive an update in the last 4 weeks. + Please take a look again and update the issue with new details, + otherwise the issue will be automatically closed in 2 weeks. Thank you! + exempt-all-pr-milestones: true + labels-to-remove-when-unstale: 'needs info' diff --git a/LICENSES/MIT.txt b/LICENSES/MIT.txt new file mode 100644 index 00000000..2071b23b --- /dev/null +++ b/LICENSES/MIT.txt @@ -0,0 +1,9 @@ +MIT License + +Copyright (c) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/build.gradle b/build.gradle index be8662a2..844cbf7b 100644 --- a/build.gradle +++ b/build.gradle @@ -11,12 +11,12 @@ buildscript { } repositories { google() - maven { url = 'https://plugins.gradle.org/m2/' } + maven { url = "https://jitpack.io" } mavenCentral() + maven { url = 'https://plugins.gradle.org/m2/' } } dependencies { classpath 'com.android.tools.build:gradle:8.13.2' - classpath 'com.github.spotbugs.snom:spotbugs-gradle-plugin:6.4.8' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath "io.gitlab.arturbosch.detekt:detekt-gradle-plugin:1.23.8" } @@ -30,6 +30,5 @@ allprojects { } } -apply plugin: "com.github.spotbugs" apply plugin: "io.gitlab.arturbosch.detekt" apply plugin: 'maven-publish' // needed for JitPack.io diff --git a/gradle/verification-keyring.keys b/gradle/verification-keyring.keys index a66f1a45..f0646d57 100644 --- a/gradle/verification-keyring.keys +++ b/gradle/verification-keyring.keys @@ -505,6 +505,42 @@ mMc1ojZ9QHu9WXM+cEND6KY3m407KYw2ItiMcY3Y5fNTRdEMvu7S =hVLP -----END PGP PUBLIC KEY BLOCK----- +pub A1AE06236CA2BA62 +uid DiffPlug LLC + +sub 030DD9087C31C9AF +-----BEGIN PGP PUBLIC KEY BLOCK----- + +xsDNBGPAYVUBDADCs9PkY8zzhzE38bRZX+vTrr3LdChGNBmObV858NGRrXeZtyLu +U7YwYVF7w2vHUI/JQWrlPZc5tBFicefucfUtKt790WzAk3NBjGtX4IWpG57C1Z5t +QRI23HqWr1If0UanH2vUjy4fUgNZdYlH2KzookoU0950dIcqwA/HwiosO5RmQ9iY +HztkwwvFW9QxiJgL+lR84EcaIVN1ukr0ZKrG1a6wOJ6HLf9S2F3DMe7fQ+O+TpT/ +A11RewOZHwE9spH8cEsNYgutBouw/MttuYHjZKD7O4hN12MmzecWeMAPyrvYgTJp +PHcjQaVeD27OGLRpy5n5LonvkzJbhTzM+Ps1qEj/4of3EFVhxNjR0gdrkX+0Ub1A +XXiw3gjqAQuLQVKIbwvCbfj2go+YHrfcXN6kpKkYZU8ERPxI/VBTw230PPdXXwXP +Ux/JRQIEXOuMIuELm/91H8TXKutw6NdNRu5q+LPcUkU7W6jsv28dmQHdC+ebVHlA +vNcBOWVSY5e8IasAEQEAAbQjRGlmZlBsdWcgTExDIDxzc2xjZXJ0QGRpZmZwbHVn +LmNvbT7OwM0EY8BhVQEMAL4ZVuEVH9zbhY6AewA4T3u2XZ7k1KGOxoK74eygzYEp +fKMplWQtCxcxBXe2tboT7I8U3MrV6m7KDwcxLNVZM638fvfU3Px0yGs0jBzyjOcb +Vk6n18xX9UoNyoEqpxHhyPbTBr+U9OINcneXZ/iG9FfLURZjDxhNcQcnrnmvbUB6 +M+teZ6Gpb1Ye8ghVCJJNjRRQhFxXE7XnmX3C1pZoSoGcBx5zVspSuHjq7nTTw/rd +7OpC6sBK0ULk8GPAd2vJUfOtZcsLvOs2++bHxNULTXraTy/fYvXsTSe+PmbJo1Fd +5o3imI0eUy853UJmF/HbuWspFe8yONHjo0+uZITsAMq0jbzG8MTKMmgsXS/i/vaW +8BVUmLfhB7E+bUXJLJuQAan397NbYZqPF5agLZ1wHSki3iuYEttdMsy5PYCLeCqh +8Tv6VBNkEToKDAvNbaad4ZgBdwbBQaAIrWekWpiXSXizyGr/VTFE2hT5NC0d1BXy +sc9P2UCvHit6A1bCl7MSywARAQABwsD8BBgBCAAmFiEER5e09dzEbOphBZBxoa4G +I2yiumIFAmPAYVUCGwwFCQPCZwAACgkQoa4GI2yiumIHXwwAh4/tSXSQ9Btws4ZP +eLfihAb4ogHOsrJ8ZO+lZMyQOrEyzDK/y/1LpFVlHYEP51XS5h4u4XVivXGzsZ+r +tQoXaCS6n19dyyNeusehZx/BxxQrdV9OYEkgb3BC+05AWogdHXTP4prGdMtpSttd +gcxTuHwx9RUv/d6CsQ8DyKyjTv82hd3yuXQVl1829NwDbM7HJ8eq0uZPmez2ewbx +Ze9CxjKoOLfYSQ4k0DfcIFqz8CSqTVIz5aNLLXiY6NXPhS9B9/bXkRNAXzUgMrG4 +GmmP8XLYjBn9g8V+fAad67N0dUWDeAPzz3OXjp6bxyScgjT6OMlp55xXaE5HWW4a +aE9epjKjLuOD7LYdmv0GI1HhSrOnlqznB3TCwJgKMw6/37uGZnpsX0JoMs947ZIm +pcN1kNNR3e4aAFcpBwj2OSjds+G/DI3/WOXJj3aaRI4nBRr2/IB3TVhzLOizLTNQ +Q/IKL5Iy5doINK/iyjb/G/JLH1/TkhW9zEheiKUY6TiXeR3p +=fdmt +-----END PGP PUBLIC KEY BLOCK----- + pub A2115AE15F6B8B72 sub 6366592024774157 -----BEGIN PGP PUBLIC KEY BLOCK----- @@ -645,6 +681,24 @@ ZlI/ojefaZkRseFrtl3X =qnqR -----END PGP PUBLIC KEY BLOCK----- +pub A6EA2E2BF22E0543 +uid Tobias Warneke (for development purposes) + +-----BEGIN PGP PUBLIC KEY BLOCK----- + +xsDNBFJQhigBDADpuhND/VUQwJT0nnJxfjAIur59hyaZZ3Ph/KIgmCneyq7lzYO6 +xa1ucH8mqNBVNLLBhs4CjihBddU/ZKTX3WnZyhQKQMZr3Tg+TCNFmAR4/hnZ3NjZ +N5N5gUj/dqVI2rIvypIuxUApl88BYMsxYpn2+8FKeMd8oBJLqFRJ3WNjB4Op2tRO +XRWoxs1ypubS/IV1zkphHHpi6VSABlTyTWu4kXEj/1/GpsdtHRa9kvdWw7yKQbnM +XuwOxtzZFJcyu0P2jYVfHHvxcjxuklc9edmCGdNxgKIoo0LXZOeFIi6OWtwzD0pn +O6ovJ+PL9QscMdnQlPwsiCwjNUNue20GBv3aUIYc+Z8Gq0SqSan5V0IiKRHMJkzd +FAhnpkSFBvHhPJn07BCcb1kctqL+xnLxIdi7arq3WNA/6bJjsojc/x3FdIvORIeP +sqejhtL8mCBvbMAMHSBrFxclMp+HSz2ouHEEPIQam0KeN8t1yEqIy3/aYKMzHj9c +C3s8XOaBCbJbKpMAEQEAAbQ9VG9iaWFzIFdhcm5la2UgKGZvciBkZXZlbG9wbWVu +dCBwdXJwb3NlcykgPHQud2FybmVrZUBnbXgubmV0Pg== +=A+ij +-----END PGP PUBLIC KEY BLOCK----- + pub A929EA2321FDBF8F uid Norman Walsh (Key for signing oss.sonatype.org artifacts) @@ -718,6 +772,50 @@ yzETgE8zz59/t9SaMpJ0Wtw2iS688bZba+b0OT6AsrI= =XaPu -----END PGP PUBLIC KEY BLOCK----- +pub AE094C852B4EE5DC +uid Dave Brosius + +sub 2728E6DC4904AE9D +-----BEGIN PGP PUBLIC KEY BLOCK----- + +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 +=QicZ +-----END PGP PUBLIC KEY BLOCK----- + pub B0F3710FA64900E7 sub 7892707E9657EBD4 -----BEGIN PGP PUBLIC KEY BLOCK----- @@ -801,6 +899,84 @@ BQJKMGw7AhsMAAoJELNB3bAg/Larfc0AnAmQbEg9XnLr/t0iUS7+V7FcL5KpAJ9k =DGI6 -----END PGP PUBLIC KEY BLOCK----- +pub B6D3AB9BCC641282 +uid Eclipse Platform Project + +sub 700E4F39BC05364B +-----BEGIN PGP PUBLIC KEY BLOCK----- + +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 +=u07H +-----END PGP PUBLIC KEY BLOCK----- + pub BAC30622339994C4 sub FC9BDC25FB378008 -----BEGIN PGP PUBLIC KEY BLOCK----- @@ -2269,6 +2445,31 @@ fVJykhD1P8/4BedOSN7DqsnvIUfFaQ== =iddT -----END PGP PUBLIC KEY BLOCK----- +pub 07D3516820BCF6B1 +sub 11F4CE313A637CC1 +-----BEGIN PGP PUBLIC KEY BLOCK----- + +xsBNBF3HgdMBCAC3ET5ipFXdZ9GGMbtsCQ3HGT40saajsNDOdov2nMJxzKkVe3wk +sN3bpgbsqBU9ykVkIhX8zV5+v8DOBzkV0pJ2eLjFa9jBPvNjV+KoK2BAI5pzNzYg +sHPwo1aRXdI0MvCy+7iaIiiGF4/O16AhU4LmALHnaRQZCyuN6VOQ8rlqNvcczwUf +J2DQeLHqR/tsch7S01hGpPAptBeu19PyAlQsntYN0yLCLKoe9dFXWCDkvd1So5LF +6So+ryPqupumBbh4WxCmTp9qwDJYJItjAE0zyPe890FurOtxrFTwtRtX6d6qGKkY +/B4T3r0tTE1EiOUpmSnxmGNItMh7/l5UtnHjABEBAAHOwE0EXceB0wEIAK7dVAoq +ZqBw9twxk6psNcTmIrfQbvjasKl/+PfLCfBNklD/nwe0CLz799fFSFMezCg43ZPC +KIescCQ5t74r0D6O/QTGMpUyZD+w4JhZkMQYy2HjImfMNtPVOWb+XaLku/RloPt9 +MSG2mtA25TTp295N4mzMPKq0r1PzSa8jj4Yfn3AzzSXXLq6PwoDiljQ91IWBvJL2 +IAUAMaxSxzq3UqJnlbX2h0yMM+VC0nbSmbkK8mUNltg1EnngJKV1mKRG+Y1GDmZZ +1Es19tEwUMsV9x1gt05YlecC31woUkL0//8i1kWuWG7dqRMf/8cXaTFA1brVJ33b +/G0VQP/a03UaVd8AEQEAAcLAdgQYAQgAIBYhBGNe5ic0Xzwd1CKy4gfTUWggvPax +BQJdx4HTAhsMAAoJEAfTUWggvPaxrJIIAKJsimeWznAmR9fUH/u0ONaTaEQZlhwB +KvTGn8MPBKAnl50HK5A1AXtEe4KTSR7ohAZ/K0wsmVd4Qi7v0O+A9qTEE/mIb5zT +3kVuFG772cISRGpC+inh8Dtl2G56s7K45tbPz6jdnZHLBY9eUr4X/2ImI7+q2+Z0 +5G6KQm031XGC8BS8A1lG2XOMvb3qnRMnMapeHJ6vjoIeX9iPtO1foSmdkOCJpBs5 +ZEU5nnHzXEjv1tAPsTAPN+vBAduNAOSqGTA6hXparbf1loeHqnsZcedCQMxDQf/t +ja3Do8flUzx8MmQkoXY8i6QmtRdrToqqt1n1jGq9Ka7lRjq0xJHAZak= +=bIm3 +-----END PGP PUBLIC KEY BLOCK----- + pub 083891AD4774845A uid Eclipse Project for JAXB @@ -2474,6 +2675,31 @@ LDL7A4GNor2DcqTyOw3cjy0= =pzVO -----END PGP PUBLIC KEY BLOCK----- +pub 17A27CE7A60FF5F0 +sub E86F52398AF20855 +-----BEGIN PGP PUBLIC KEY BLOCK----- + +mQENBF/AfL8BCADpdkr7+1epRZLZJ6/si+Aj6fmELbzWHZmSSUYmRszcCgPq78xy +bsW/d0grOOEEn9I/5N22gOoEumcFAsN6hn1thjsZyXLmaBfRj+8vri/zigAqrE7W +zk7mKKK3IUuEi1rDqoEwGQbzHFP9UxiIouiWbYGhbkER0E8zDwmPlWZDXoQEzqWT +KcgxAXldiZ6l0FACtxgU3n9oOq0hNQBqfpn22BM2FPjZDrM4rEfbeSt8ztORIviw +7G9oUtYsbTbDvvADCL0wW05GcNz6BvcmDm79d+fk+5gb+GIaHurWuyTtmw5HCeXW +QcKN1S96Wfm5Dz6UMOMeXujlvK1rxmsIIl3BABEBAAG5AQ0EX8B8vwEIAOkm8U7a +QLAJ0FtUuY6ru+JQM3yHhIBA7dADpoyq+f/WN86Es9vw7gavO6tnJPnYh1IozEmQ +4/OaXfKir2G8geLR6hvCsclgXT+RUS9Z60XBFWWhYwX8OrkdfHNnZPeSM8pwiQbh +L8QGfF5AiJzG34ecIPekBWL0l0nYtVblAHQ5oKCv0h2e/cPylyBgJUGCtF0pLKuY +l/jeH44UPz6ZUfTL662zbz7AGn8yX62h5PXyH2ZVuuwA2+vuAZCeTP+cQ7OGlIj/ +EDmggsSrcjVa/G/v+O9lPw9SGnnjoEzX+Ng+tEJNUEx22gvAISajFfM+XWVxVEqs +z0B4U6PLa2feuVsAEQEAAYkBNgQYAQgAIBYhBD8F3anzFzAeknE21BeifOemD/Xw +BQJfwHy/AhsMAAoJEBeifOemD/XwJ3cH/27Z8H7Bx53msUwaNO0RbWJNz65xrecM +w5dvRVjjERYm+5UA5oQdySozlgrpWCAx8q13OMVpGRhodebFEqDZDHsjvJgm10Q7 +Q9fHkP56lCgxt68WPwmof8bkTYC8l9PmPfqdJgQlyX0zqOzxjETCfe+f1gc/m1lx +tgnUeD3/ktyTkYu1hTt8rWM1ceCnZ08bIcjwjFZJDHZl+BmQ52zxUHJ5JAExZNn3 +vWkvn9JHGWPh6M7evaCcNAdv20A9AB45/aZlYRUN8hCI6xpHiMt4/tDbiImzko74 +zzMvjuz0NEEhREM8f0ld3G/7Meh/OudSEgtQAmwJ0UMZWJWaZ0FhnLI= +=5I6i +-----END PGP PUBLIC KEY BLOCK----- + pub 1A2A1C94BDE89688 uid Michael Osipov @@ -2558,6 +2784,63 @@ lr3gBFMoyhylmt9iUQ== =vJ9r -----END PGP PUBLIC KEY BLOCK----- +pub 1AAAA7AB37293D3E +uid DiffPlug LLC (release signing key) + +sub 2C7F998F4272C851 +-----BEGIN PGP PUBLIC KEY BLOCK----- + +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 +Eg== +=k22w +-----END PGP PUBLIC KEY BLOCK----- + pub 1DA784CCB5C46DD5 uid Rafael Winterhalter @@ -3158,6 +3441,146 @@ leFIia4wM7+46n0klLF0/EH+B/oQvJU30gWxTX8T9eE/hCREmtkjUX8= =rlEj -----END PGP PUBLIC KEY BLOCK----- +pub 38EE757D69184620 +uid Lasse Collin + +sub 5923A9D358ADF744 +-----BEGIN PGP PUBLIC KEY BLOCK----- + +xsFNBEzEOZIBEACxg/IuXERlDB48JBWmF4NxNUuuup1IhJAJyFGFSKh3OGAO2Ard +sNuRLjANsFXA7m7P5eTFcG+BoHHuAVYmKnI3PPZtHVLnUt4pGItPczQZ2BE1WpcI +ayjGTBJeKItX3Npqg9D/odO9WWS1i3FQPVdrLn0YH37/BA66jeMQCRo7g7GLpaNf +IrvYGsqTbxCwsmA37rpE7oyU4Yrf74HT091WBsRIoq/MelhbxTDMR8eu/dUGZQVc +Kj3lN55RepwWwUUKyqarY0zMt4HkFJ7v7yRL+Cvzy92Ouv4Wf2FlhNtEs5LE4Tax +W0PO5AEmUoKjX87SezQK0f652018b4u6Ex52cY7p+n5TII/UyoowH6+tY8UHo9yb +fStrqgNE/mY2bhA6+AwCaOUGsFzVVPTbjtxL3HacUP/jlA1h78V8VTvTs5d55iG7 +jSqR9o05wje8rwNiXXK0xtiJahyNzL97Kn/DgPSqPIi45G+8nxWSPFM5eunBKRl9 +vAnsvwrdPRsR6YR3uMHTuVhQX9/CY891MHkaZJ6wydWtKt3yQwJLYqwo5d4DwnUX +CduUwSKv+6RmtWI5ZmTQYOcBRcZyGKml9X9Q8iSbm6cnpFXmLrNQwCJN+D3SiYGc +MtbltZo0ysPMa6Xj5xFaYqWk/BI4iLb2Gs+ByGo/+a0Eq4XYBMOpitNniQARAQAB +tCdMYXNzZSBDb2xsaW4gPGxhc3NlLmNvbGxpbkB0dWthYW5pLm9yZz7OwU0ETMQ5 +kgEQAL/FwKdjxgPxtSpgq1SMzgZtTTyLqhgGD3NZfadHWHYRIL38NDV3JeTA79Y2 +zj2dj7KQPDT+0aqeizTV2E3jP3iCQ53VOT4consBaQAgKexpptnS+T1DobtICFJ0 +GGzf0HRj6KO2zSOuOitWPWlUwbvX7M0LLI2+hqlx0jTPqbJFZ/Za6KTtbS6xdCPV +UpUqYZQpokEZcwQmUp8Q+lGoJD2sNYCZyap63X/aAOgCGr2RXYddOH5e8vGzGW+m +wtCv+WQ9Ay35mGqI5MqkbZd1Qbuv2b1647E/QEEucfRHVbJVKGGPpFMUJtcItyyI +t5jo+r9CCL4Cs47dF/9/RNwuNvpvHXUyqMBQdWNZRMx4k/NGD/WviPi9m6mIMui6 +rOQsSOaqYdcUX4Nq2Orr3Oaz2JPQdUfeI23iot1vK8hxvUCQTV3HfJghizN6spVl +0yQOKBiE8miJRgrjHilH3hTbxoo42xDkNAq+CQo3QAm1ibDxKCDq0RcWPjcCRAN/ +Q5MmpcodpdKkzV0yGIS4g7s5frVrgV/kox2r4/Yxsr8K909+4H82AjTKGX/BmsQF +CTAqBk6p7I0zxjIqJ/w33TZBQ0Pn4r3WIlUPafzY6a9/LAvN1fHRxf9SpCByJssz +D03Qu5f5TB8gthsdnVmTo7jjiordEKMtw2aEMLzdWWTQ/TNVABEBAAHCwXwEGAEK +ACYCGwwWIQQ2kMJAzlG0Zw0wrRw47nV9aRhGIAUCZ364RwUJHMSQtQAKCRA47nV9 +aRhGII2iEACMbNrtKDaiohSufHf5aUoPrFoMDt1hvXAoYULz5yXcgHVypZ8PP0ks +pKrbjL9fzdvZmEjuyt7AiEr6Ak0diqk+eOqPgtvwqkrN1hLl9UqT0BlT1C4k8Sy7 +GYdFoSaynIZldzUQAj8aLnoqrRaLCTwOrtbH9opTfPQKxsc7XiLk6clMua/fBh1C +ubL41YeLM/ir0zZRhRzd5wKEewYYg3+kYENEN7pJBiar7WElFd0blZIEfuxRwxbG ++kUZspHJvmErc9z9GEzCY2y2HsGkC8ymZy1p0jdfDUayE8BFInAV5HDhYxdfHe41 +2LAM81+5dvCxYucoFrjjr0+bOxM05lrcufqq3hx54y+EgkGNq5G/QIqVE6qaA4Qc +/dUIr03UPxLCZT+ntPIcGmu4XmamVlstXka/ERMw9q9xn0NhHoD5MLInYrwwZSuD +4Fp5RJdOkWxNXV6Gpl3zydatEhZZMN8zFvm6mD9Y08ayVQJVxX/Kk93eaV8/O9Ud +TTz/3cjyZ4vOOAYuNqvCRyGWilmekELD9tExjAa72yPKjAjNYB+fL3AVgR7aZtpB +hI1XScpe+UYIwn9VR6j2m+gNP/rQARpS3+a5vZMTpm9sAwlvMT56PwPKbFVnGBO4 +BEU+gXam5K90mcPdosxggOJteztTD3+r4/54G0UTr7hCNdRyzpgSb8LBfAQYAQoA +JgIbDBYhBDaQwkDOUbRnDTCtHDjudX1pGEYgBQJlnAmyBQka4eIgAAoJEDjudX1p +GEYguyYQAJo+5SnMMdu+d70mWfUb9PZg7P5CGRepHnckx9Sis5oR5s7NNl5j5Yy4 +J1UwsmrP+mn52ujqewkkVsCq65NGQQx7+tkwuKGvnGBkHdrI+aJk86qLMf4DlnNJ +EmN8t5jTGQfRLbFVf2I8EY6qXAzCSmL9Zs++rDUz65GOTB1EP0XmBRsuVYRfDbFe +zrPQH0JDucbXFi/2BDnl2/Mk9NBoQ0CvB4oGtLDiQZ+jV7n1VXXJ1faD9s7i0hOT +dcG6rlyIqi/LyAzdCnOYTkmv3U1kdmzkvrh1KEiejnM5fj27RE2v191vh3hgZ+X5 ++uwjNTP0QC4qP8XykQOAA8usOMVZ72lyXCAkwiUcRdrAXLN/XbIFNcQ3m4d3W6t6 +0Gk09wFlUKaEltDMlPUsxiSG3qFwFGPBP6UVh3mjJMAl1jltLrR7ybez0SczfrcA +tdCsKTvgzV9W2TzUfK2R9PBanmXTXK2M7yU3IquHt3Je4aSP7XYb5D+ajlbFNvnX +OYcai8WryfC5nLAfV4MbPX+UlRaYCqqHVhutgK93re1L5mMI3zjG5Ri5jLpUA9to +SJCIJIY5zwr/8LL/ZL4TixXlouA17yjkpY/eBjs8cNj1O3aM4jY2FKCS8UbfxOiA +Rk/5kBMRPEZ/mqpMQttzE8KVjOv6fRxy/eVE888/gToe5kb8qYwywsF7BBgBCgAm +AhsMFiEENpDCQM5RtGcNMK0cOO51fWkYRiAFAmM3DdkFCRj400cACgkQOO51fWkY +RiDWZw/4h4KT3QgVndItf6yJplAJAjNwP4vdT6vC6Iw8ZzEF+3kMFZ61l72Wawf1 +DgkePQHjCXwIjMvlT+gJz4nbCJmpYEXvDruiMzpGu64nJE3GhbKyQOIJJi1ygyKz +wSraQFia7Pgd6LgxgFNfRH8cXd0nM6181gaiUu1ri9fMy6hsFq2xam9PDRTrSQc2 +LEpHDfDrW8XKFTxpmRNIfooJGG2mTLDnQYwqhOfhQekgBkn2awWqSuXYvvdEQNY9 +LXF1L1MD+HwmNEcfcGa5j3NUdg/CR6wUM315qHeua3dVUjqvQfAFmcNZ+p8A3O/E +l2gk/5vkqJjg5rJAjknP6urO01G9rSsLL87LfaRKjsxJ/lu8MDlsXMjisWOAFeTn +yDLwc0DtsespIfm5IVI+eyKL9m+69rVPawFXNXi540IDzfvLvOtP3UHXzLmuVSAq +hQjepS6sk+Mx7dPEtba2wccs12R/Gqo404LsHv6uWqzgX8bN7WkG/zjxbhl6fZoI +glUCxnLQ7dv/nTXyzp5lqHlMtqQaktd9NrAQfp36xhUxZiQuMqc2PLkBRvfHcQaM +6jBPN+iqzIYgW3iyIIV4LDkBx7foF8kFc787JHnVMWeJsc2dQ//iXyYcMRr8WRZ+ +bABi2wJkW16CL9Hbh5PyVthdb7f0tN683nPMt+wdyy1pyDvSysLBfAQYAQoAJgIb +DBYhBDaQwkDOUbRnDTCtHDjudX1pGEYgBQJgS31gBQkXF5HOAAoJEDjudX1pGEYg +wu0P/0e4ozimeAiZy7NjDNCZ2/iPbphjKHiNWwoSZVZOJFx6ESBQiWtaQK7erN3k +0r5F61LuQnww+fMRR+Nhul0LrKsXqfWZKtlnhUkyRXZ6/ftsiBcz5anWYIAZuM3F +CeOf1FptP+CMiqYa5GcA/tGxJ45K47+A72HY+15yLPbe6yxOKUH7xxOihARBBl7o +q//O6S8v5xxJ6EsexnupV9FQCa23ycWRdcT6zyN8t+Gqy1ojb9Em7nCK1o9xczwy +fPYT3loBIBtnLR5Ci33Q+9/Tuf3K4Le255O/O+VfHeHlTfJPji0g6bMA0hCNrLVM +Z2b5EEnZljKHItrCVnY1VRddKnhBllc8DRRZsX6lvtD1x0oM0VW68YGWO55rRh3R +Paj6JsOrjcfOJf2WX6VJeT2aq9bVRwM5rFatKybUZzU72DfCofnEcCG1jwY+H/tW +ABrCyQ+SaeWQxbqlg/LOJtt4hIkvWB3WMhPrfLpqhWu02ij7BgmbbzRE5+WHj7lA +6jpAn6ObvR+RdIb+onlrz+oI9MeQlz+umQvr9MNAAlRGL1GEMALSBvjQe26xs3Ut +kQD6LRxZOZhdqn4MHhhHikCmKWlobzsz5VSiRHjGmfHu9NvYw9rsx16e+L0UQacp +dp2ZPzTfy+V/PPkYZRMyVWKf0FA9Ol0D4+lGIm8omBUN4AU6wsF8BBgBCgAmAhsM +FiEENpDCQM5RtGcNMK0cOO51fWkYRiAFAl5vxcMFCRU2lDEACgkQOO51fWkYRiAE +Tg//Z/wItCweI0pEWqyz6mRc2VbHbbSr9P824A1QsQ0ZAeyfUVeA88Zv4kTlDaT+ ++Dwpdb3b6ct4SVBlIVqRhT2IgrPTooGTvm+wyuu/Z8pXYH4FRi6ItifZd/Z4IH+y +p6MCBhP/PpwTNod54+kRGTvItwcN9zCt1EaYk3+p3i7BIMuOd6vJLj7B0GObyS+X +372aalsmq/FUEWi66nysu4NsX+jff3Mb+MFUux8Int2XJlTTOJtkmh0upSSqtnNH +KgUPSsOkSmyQ2HXUbugubWgoWUwd8a5SCte8TZE27lqeBNHAZ1EVH2uCel3L2PPv +pmwSWp3pu4Mu70AOx3CtwwXSqyxvIuEHNTewSiUbzPeMsY0aTb2vnGkX5XsDqPGq +FnKdwCYOIwFt8vkUBnyQ8Vct67hh0F6CGB8WIuIupS2ySt5sPb3tVbMWmaA4Dwl2 +NwkeHCOVCWxpmc2WRlRK+Dpw2tNLWMwRdAqkpiuLgWRHvrpYMKIwALpABkEilOqP +BgG4RB3zsCzLAKU89o6xLaTZ+liDrExvoovLBvUeBwkM9+sFNKcCmbQ7I4OHR6vq +0wRscWCEO6aKoQoDhe8mj/JgWFjZc6N7i7CV1fWmeRlqjsays4ZinDPQ2yXo4OZU +C+msu/RsE17yuhPsOCA6F/hzXHY7KgS6FMyLR+dodsjX0GfCwXwEGAEKACYCGwwW +IQQ2kMJAzlG0Zw0wrRw47nV9aRhGIAUCXERzXAUJEx22ygAKCRA47nV9aRhGIDqV +D/46sXUGfW5A2dP5vk9d0zTERwUAvgzZfZJWTJ38AERiqCbFLonVbqMF4Yj2rCat +50nSVvI8UnHO61qTSWB/nwdCjTgmHl4N/hhplWSnY/+OcMOgHJ7MF3w7aBvCZqgV +N6h/2w2oUCI18KHF/KkoWu66DrqWhOzWP0feI3UCgLuzZP7KJ6oE6yv3w0I8vV/2 +G4Mm7HSgstLur5vZyO/MyiV/x2OR33H25HhwHEzZMm0vO+EAR4FWcLqX/70rv5Qy +4QY0aLSC5EvY3X9Q4P0QxiEjmRsGgm7dh03Pxbr01JH5sIW6gnrCs0oxmdnLt8Xy +MYkvGdUdllVUe1XX0UT6buHetWNOv6RoS9g0E+GEI7I7qEl7x9z7rB3AWwOU6FFt +eggBFfXI/AmRIfBg/NUdM4Co1sIjyyyQcGgIYiq9MvyGRSey9/td9yaQpB02oITf +yqwShRY3a2CnXr6lnW4uwa0LrNA6eBDVub0GLADvJiqwagt8uJqSBq8aGQgn9xhP +UptKJlwKfKYHVdVSn95tAusFKQ9ECgW3Tteu76pmwBhgtieWqcW+fzI04+nDD2xS +ozlEaEoaDHD4Ti70wW3VWzUd2E6HDlWw+uG7Ll9E/O7fCsZ2obEIUWRjzQKb1992 +CcfUb/kuwF2CtAVVaGKSZLbWRS47D8RFJS+CAn6a3TqNLcLBfAQYAQoADwIbDAUC +V9P5zgUJD4QhvAAhCRA47nV9aRhGIBYhBDaQwkDOUbRnDTCtHDjudX1pGEYg398P +/AiAbnJg7FzG8xliT7qUU6/Wnh38TnJDVvPcdBfONtSRVhQCleHAdQ6/HVXToGdm +2n3HdvLkKeGNZk2xYwiJIEeEtdKWLQ4HEV7SccYFkQB69dT5xDJ50WYpqYIEnJnn +4QqPrB60U8CIjxnb0e77hO5MINnoaqHv9Hw2wNO4j9F8WVVkpEiS53tcB3thed/P +/0oaGMUZmCgZZijS196YcUwBOv5RWsf51+4wZEZcdzP5kzG2sY/P+kDOB8+wpRI7 +mOJTVd6KFGohJp/PpC6HrMIBiPwxLGDFEvC89kA5BN0w/n0psmoQVsKrSj4yebE6 +z0WmWdPE4ATbJS+cf3CH2lGs8JLK6+yuwLzgy4eDUiCnR6FvLed+YmC2o7ADFChS +Fq3CDmGgo4+AsBGITp5YCbJwiU14u73KLftueN3ABzNX4pe35amXKimbp4xqOF52 +H/+BiJpiHPHYVIjmoylf7O/WaYzsGAWCu0aSBL1EoYEG5DSMkZkDiTKq06hWru85 +ujkXt8VgWyzhzU/NcobbZD4vABNxfNVBo8bxkyBK+rZR8gCwSkz0jut4VC62nbn7 +QnABz9hAa0ep5GQkQ9okqMH5HbiFUmfcYeMbhqGUOpdfRvcF+m+JSVBAeTsinqCr +eI8NA0RTv+b7v1FNdxJXqHi0RhPFbsGkJOiFW3aB5/aHwsF8BBgBCgAPAhsMBQJU +w8GWBQkLwe8EACEJEDjudX1pGEYgFiEENpDCQM5RtGcNMK0cOO51fWkYRiD3mBAA +iUh7VKSPHfmyv2jMEKVF/HbsFxdfkz4PnT4rzOpN06K2PRO4AfZiDPPPKMCJerX0 +f8kGRblFwhbPLl9nWnGzdHwMLoLARzM8ZhU8Nkao6UuWymOvXksPt7xSE4r7pXAm +dOqmXPNblxgjTFUzJFI9Q85bKhhc8L6VXE//fTEr69MBNd0rP0q/jvFUN/HMQGVP +HzbAfC4pm5OutEnq6sV3WDCxVU4lWEtJCoOoFPeu7r1YGp6PdEmaDtHgFghHaIto +Up744FON23YGr79/yMz2rV/Nvx0E1YgkqAjy9UqnD944eIeuH0S7Zh1k8VWlNq1L +mvDtbONNQgWnG0QlysKA0MTKIccdgv2Io3RqKbunlrVApLD2dO6PqtAZ7fE+hSoG +eGRAhF13cMI3wVhVwL9ePzas359qIkTp33oi3Nwb0bTNAYgQslaUZmPeSFiw4DT1 +LriCowWTn9GDePBYe7EcAppOnRlPk/YxWDB2HDBLAGIXwrqgvHum2Ipe9//Zp4zr +6mRXmELaPXegDrcpUg6qx/F0qIsqLKUBhn3LNtTtivTY99g2wXYFBUvVpH+15MiW +5xBqL3+w4jitTyRvA0DdOAm5KdlZUH7iOxWHPwP6lWB0TonWoXu1QBkPWqPkAELT +UwsNzyxGzkie29l0ob7rdye9b+3AI0IYf3NMxVBM4x/CwXYEGAECAAkFAkzEOZIC +GwwAIQkQOO51fWkYRiAWIQQ2kMJAzlG0Zw0wrRw47nV9aRhGICaLD/wOlfPc3F9Q +B6qeXbSl0WvZgk77bwPsFOjOG8v4EuxFKLOhh9tqnumNYhI6k3gYB5Jg9tkxT4x8 +n1PZw0DrN7N1PimRNbK4yM7x1aK9WpyIZfNiED0cc+++SH9U0+vK3ZlGnY3PWOl3 +tofH7yIa5JF6UM/z0y1voKiY38bLTk+FlIBqTa2EX9k9wN0YUViwVWpF385UINWZ +16f20H2jEG64HrmQ+W1xfPI6KFGN7tVS2mlsK/E8wDQQ2Rmx9/rs47LkmPyA7Kc3 +aPitLjQKF0h6MAGJ5QYPGhrm0zwbyXWeWBOoHaNfvkpOZCc9UtCTWJ81fwsIfp3v +b22v0R3Fz0qhIIJvQb9ZON3gw2kjuOGMu51IXfl++yzmZrFsEQsFMatOYBwsWlE6 +jwafKSsrJ9vyVSOYpNmg6aCywVOYMgecMK3rgl5u6qBxmgtoYAYqS4B7gQyx2Ujp +/eU1MotWQOv/qdVVh0rSV5Cx8WaiG8+OgymvFL8vNR59d3KnW01k0mI4xKuCXdAD +Ep3sF9pzGf+HTd8YG93bN+tXEMlWheyc8gM1DoskZJ8Oaxob+ZGBkkS6dUsZAV7a +exWo2ZDGm0tpPO3LVm/Z0I4Sblb+lJ6QsIs94MroqZfxlVFos+Ph11EIAZkxqL5u +bSf/SyMD3cNsG1LRfTCT6Qi6k8DkpZ0rkw== +=Er2+ +-----END PGP PUBLIC KEY BLOCK----- + pub 3A1959EEF8726006 uid Eclipse Project for JAF @@ -3460,6 +3883,24 @@ FyvzRrGANIX1EyEvSOEnIq1qxw+s4n/WPtW7i04xDM61UPws1Fvg9N6T7/S1Dadq =JZti -----END PGP PUBLIC KEY BLOCK----- +pub 436902AF59EDF60E +uid Sebastian Sampaoli + +sub D94994D14B55169B +-----BEGIN PGP PUBLIC KEY BLOCK----- + +xjMEY4fp+xYJKwYBBAHaRw8BAQdArb04PVwQKvEhtUEmEu7/aASZivOWgEkZBqX0 +Tovwvq+0J1NlYmFzdGlhbiBTYW1wYW9saSA8c3NhbXBhb2xpQGVxdW8uZGV2Ps44 +BGOH6fsSCisGAQQBl1UBBQEBB0CSPWzZfBjKWyPW+D6RDRLFz5xlO9/30yGD/VhA +EPXybAMBCAfCfQQYFgoAJhYhBB0sfvitoPeUtYx8Y0NpAq9Z7fYOBQJjh+n7AhsM +BQkDwmcAAAoJEENpAq9Z7fYOTMMBAKfZb2ahnfGNBt8Hrbu1j99580a2IaFQddAk +xXZy2unHAPYyfxDLPkbTR7Mm4k8Cva8PCcXotDow4bDLm9rhwVkJwn0EGBYKACYW +IQQdLH74raD3lLWMfGNDaQKvWe32DgUCY4fp+wIbDAUJA8JnAAAKCRBDaQKvWe32 +DkzDAQCn2W9moZ3xjQbfB627tY/fefNGtiGhUHXQJMV2ctrpxwD2Mn8Qyz5G00ez +JuJPAr2vDwnF6LQ6MOGwy5va4cFZCQ== +=VAP1 +-----END PGP PUBLIC KEY BLOCK----- + pub 4604091C01C3086A uid Dave Brosius @@ -4193,6 +4634,34 @@ pjR9iVjH1oML0H5i1H4= =MfhW -----END PGP PUBLIC KEY BLOCK----- +pub 72475FD306B9CAB7 +uid Daniel Lemire + +sub 1723844CF9A045EC +-----BEGIN PGP PUBLIC KEY BLOCK----- + +xsBNBE7+huMBCADW9rfqKBXOqUSLCK5Klag5WqLFxAOddqEM7wTx/42XaIKjDiAW +gmFnV4XBKm/7Z4fwWq7+ku6NDYUjBpI4vcQ2hYJJ4SRWZHT5wWzOmqgznf+/Qwug +P7Ss3EUTRGX3LnhKhKN656XQhM0PutdsHQlUKjvnl2JOaKerEhbHCRxga/U/WWOT +KdobRO+x8v1scsrnUG83J7sTSaja0McmgUhKrhJqrgSk1Tod45SxprxOyp0cgATY +xjHrf2rkafBn7K7aFDe8a73iCJPWS77gxTZCZ72xkcnMLR0m7QI8TzFa4lRjTovA +QcTpr7jwjmyjA1+68peL6VHdVr0cdXm34mTVABEBAAG0IERhbmllbCBMZW1pcmUg +PGxlbWlyZUBnbWFpbC5jb20+zsBNBE7+huMBCADS5gJ9frZF9KUorujSdK5GmZTG +75MXhQLLR3UOczqElryVfudgwHfofBymcuiPPfwSNWpWLeylgCxs49SOrNfh2r2m +Cln7ZO1LwDOoRIfD8xUA+TTc4qbQzo0xt6M7WdEiuhLdxUGnM8s4fRsjwvN7wvA6 ++PGvgaeWIKaP+S27jZaKbVSGqR37Vuj1JkbsZV1V4BXXOb0gyNsT6s/Hcy0owWtZ +kVBIgBanYui9J2uosgRMhHeEJUO05w6ehCoAkr2ktzj0QRDmljmbGjiHEsOcO7ZD +u2JQyI25bVUCk21S1CEdIfZ4xmiV5Rj2Lwxb7LCDEe+umc+W2/7j5RtR7RWFABEB +AAHCwF8EGAECAAkFAk7+huMCGwwACgkQckdf0wa5yrcgCAgAh0VKQHRwwov6YDV2 +1H0/h0vv934brwNWxIPz46WVa0xI+fmA0wYXg+1OTQBy7rqJHWoK0I3M6qjZvvaK +o77yUUtdye16gf/SxKPUwXMyTg98ojOvq7orvDF0ktE59stzayjUs3vrR7xDh/mx +pwiCN602Jk27vCCTdg0AHbu/CsK+Cu1rkqlqa9nQ0O0No0IiGJdDK51/ZluGBhhB +73xQ+jqgAf/g1qabG0Zyv2N+5tw+Alp9sqDsfyA119B6q3xKoaJqo+9h+zQ0vpZr +NMuph0EDebGxR9VMiO2F98dacAm/Qr8QTyRj4424rkCSK2VbZtvalewylY514xg2 +lV/Shw== +=8Yuo +-----END PGP PUBLIC KEY BLOCK----- + pub 7457CA33C3CE9E15 uid Colin Decker @@ -4913,6 +5382,40 @@ DAAKCRB8fYRWKUQjuol1AJ0XC8Ne5QYXv1nChUZMxE0sWiXIyACePz9TTTp/3knC =xYLL -----END PGP PUBLIC KEY BLOCK----- +pub 7EB97D110DFADD60 +uid Niall Gallagher (www.npgall.com) + +sub DC0B7E986BD7398F +-----BEGIN PGP PUBLIC KEY BLOCK----- + +xsBNBE9/RAsBCADI/pVIFcoLmbq4LCKkqeN4i5xgGKsuQsDAf/ndFkILDUA2FaPN +7cI3EvZacWnWUA0QkkKNKpajU2OjjQlu4IyBosJht3VMtD0BJ2nL8eIDvwO6L8TS +2RRGMnMaDUc91NnoxKs/7VlQ2ySk6Cm6lH3t8KVkwaJdU59lAH1ey9UKhYyvRQuT +htenl2R63lyyDe1ZLMAlmQXi4RcCWOO+L1emChNv0q0Fsir+7go9ZNYUi6pmIEva +jKXM8bo/VtRIHrS73DsH7BVVCURYoBWexZWlRdb86KSE993dRXLvFPy5JzlRM+eu +mUY3CMKxx3nLaDN5qepf1nGzMW88xjq4z4rhABEBAAG0M05pYWxsIEdhbGxhZ2hl +ciAod3d3Lm5wZ2FsbC5jb20pIDxuaWFsbEBucGdhbGwuY29tPs7ATQRPf0QLAQgA +68HLImPvBSPnMtjUHczE+gccsVWzLEsjVYSBcOUi1j67KQHbTPcHAqzYJl19t4FA +N/yU1oOjuu/4GKVni27y8NGSavzY5elTZ22lqUqgqT6DjoOG2BTLHuOiNRIMqBmD +Gy41mEq62C9I107pqJnnbARmde4646kDiaf2vkF1BsnBx0Dp93re2eJq4rkAf803 +fDvA8iyk5uDFiGg3f70JAu7ZCAKczglD0WUjIiO5Jxncz2sWiO2OuVgdsTuZf+9T +0aODKua60Z7CLn4ZK4ZpdibbOEp66XLeaGuy5HPInTTsr4UnT2kvor/AmmPKOryp +9oBFnPvf5+wREwlQN2h/PwARAQABwsGEBBgBAgAPBQJPf0QLAhsuBQkHhh+AASkJ +EH65fREN+t1gwF0gBBkBAgAGBQJPf0QLAAoJENwLfphr1zmPJtcH/RJ5ba5m0Obq +BGbcJpJwhEjpB6tCOufdzvvJGAMMAuH0Vs5kXrASIJPyVgJ2ab4txg6U3DKIfxnE +IGjfdH9okl/oHRYrI/EDMN0PnIkE1JidhVOEOj3UWaoLUS8vvobKq0XP8B6J+P4q +NA5L3cPlBBtH7yqzVNavi6ljJcsJH3g7L5vJDQyw+xxfOvQq66y4lcO8ptAqB+nw +oHfSsfRKQQgT+Xlp4lG+acf+Kc0bLjWWUnBRgJfkhbGPVYHQ/QfnxbuLvlqohive +HEV+d/PxCwUHq4EtLC9d8V3ADCZgb3v9YE03abItwg7tnQBd/LuJ4qdOEbjAWI4c +crfZTmD74BlsewgAsOy6q3qjZwBwDjUHc4+Mq9ZwaehZ4Lau9EjyrOPZw1kSCWc7 +rcxlTbPa+2xUrv382Zc7KovIMmEos4RJ1gaFfXvreGKzCOrlsA4knXcwp9nywjZH +2Hd+p7l+/EB2YA99rMglXl/5Nfs5k2I1bTqfOb2eOXde5p8Akh1exvuIyJmRf/pR +eRA/8dXKCE/qG+KZkJOh8H9gD/8nX8n/5Qfm6Ff0iFF3mdBLM9QdBa36/qowBYQz +u25YFH0NKiziF0Y2r0pd4NQhoAirGdamVPfWKzvHhZ8XWhklr1Ve+3X9NqZIOcXQ +x1rrD3BL6LwVJtHcfQxuT3IRDnjnYXZAUOVAlQ== +=y9wj +-----END PGP PUBLIC KEY BLOCK----- + pub 7FE9900F412D622E uid Wouter van Oortmerssen diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index f42b00ef..40a0a9eb 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -11,10 +11,15 @@ + + + + @@ -57,6 +62,8 @@ + @@ -82,6 +89,7 @@ + @@ -95,6 +103,8 @@ + @@ -163,6 +173,7 @@ + @@ -202,6 +213,9 @@ + + @@ -229,6 +243,8 @@ + @@ -7524,6 +7540,12 @@ + + + + + @@ -9442,6 +9464,16 @@ + + + + + + + + @@ -11619,6 +11651,32 @@ + + + + + + + + + + + + + + + + + + + + + @@ -13472,6 +13530,11 @@ + + + + + diff --git a/lib/build.gradle b/lib/build.gradle index cf4d6a22..dfd616f6 100644 --- a/lib/build.gradle +++ b/lib/build.gradle @@ -11,11 +11,17 @@ import com.github.spotbugs.snom.Effort import com.github.spotbugs.snom.SpotBugsTask import org.jetbrains.kotlin.gradle.dsl.JvmTarget -repositories { - google() - maven { url = "https://jitpack.io" } - mavenCentral() - maven { url = 'https://plugins.gradle.org/m2/' } +buildscript { + ext { + junit_version = '4.13.2' + } + dependencies { + classpath 'com.github.spotbugs.snom:spotbugs-gradle-plugin:6.4.8' + } +} + +plugins { + id "com.diffplug.spotless" version "8.1.0" } apply plugin: "kotlin-android" @@ -86,20 +92,20 @@ android { } } -tasks.withType(SpotBugsTask).configureEach { task -> +tasks.withType(SpotBugsTask) { task -> String variantNameCap = task.name.replace("spotbugs", "") - + String variantName = variantNameCap.substring(0, 1).toLowerCase() + variantNameCap.substring(1) dependsOn "compile${variantNameCap}Sources" - excludeFilter.set(file("${project.rootDir}/spotbugs-filter.xml")) - classes = fileTree("$project.layout.buildDirectory/intermediates/javac/debug/classes/") + classes = files("$project.buildDir/intermediates/javac/${variantName}") + excludeFilter = file("${project.rootDir}/spotbugs-filter.xml") reports { xml { required = true } html { required = true - outputLocation = file("$project.layout.buildDirectory/reports/spotbugs/spotbugs.html") + outputLocation = file("$project.buildDir/reports/spotbugs/spotbugs.html") stylesheet = 'fancy.xsl' } } @@ -163,3 +169,10 @@ afterEvaluate { } } } + +spotless { + kotlin { + target "**/*.kt" + ktlint() + } +} diff --git a/lib/detekt.yml b/lib/detekt.yml index a19a46ca..b3a50bc1 100644 --- a/lib/detekt.yml +++ b/lib/detekt.yml @@ -1,526 +1,411 @@ -# Nextcloud Android Single-Sign-On Library -# SPDX-FileCopyrightText: 2021-2024 Nextcloud GmbH and Nextcloud contributors -# SPDX-FileCopyrightText: 2023 Stefan Niedermann -# SPDX-FileCopyrightText: 2021 Tobias Kaminsky -# SPDX-License-Identifier: GPL-3.0-or-later -autoCorrect: true - -test-pattern: # Configure exclusions for test sources - active: true - patterns: # Test file regexes - - '.*/test/.*' - - '.*/androidTest/.*' - - '.*Test.kt' - - '.*Spec.kt' - - '.*Spek.kt' - exclude-rule-sets: - - 'comments' - exclude-rules: - - 'NamingRules' - - 'WildcardImport' - - 'MagicNumber' - - 'MaxLineLength' - - 'LateinitUsage' - - 'StringLiteralDuplication' - - 'SpreadOperator' - - 'TooManyFunctions' - - 'ForEachOnRange' - - 'FunctionMaxLength' - - 'TooGenericExceptionCaught' - - 'InstanceOfCheckForException' - +# Nextcloud Android Library +# SPDX-FileCopyrightText: 2022-2024 Nextcloud GmbH and Nextcloud contributors +# SPDX-FileCopyrightText: 2023 Tobias Kaminsky +# SPDX-FileCopyrightText: 2022 Álvaro Brey +# SPDX-License-Identifier: MIT build: - maxIssues: 10 - weights: - # complexity: 2 - # LongParameterList: 1 - # style: 1 - # comments: 1 + maxIssues: 0 + weights: + # complexity: 2 + # LongParameterList: 1 + # style: 1 + # comments: 1 processors: - active: true - exclude: - # - 'FunctionCountProcessor' - # - 'PropertyCountProcessor' - # - 'ClassCountProcessor' - # - 'PackageCountProcessor' - # - 'KtFileCountProcessor' + active: true + exclude: + # - 'FunctionCountProcessor' + # - 'PropertyCountProcessor' + # - 'ClassCountProcessor' + # - 'PackageCountProcessor' + # - 'KtFileCountProcessor' console-reports: - active: true - exclude: - # - 'ProjectStatisticsReport' - # - 'ComplexityReport' - # - 'NotificationReport' - # - 'FindingsReport' - # - 'BuildFailureReport' + active: true + exclude: + # - 'ProjectStatisticsReport' + # - 'ComplexityReport' + # - 'NotificationReport' + # - 'FindingsReport' + # - 'BuildFailureReport' comments: - active: true - CommentOverPrivateFunction: - active: false - CommentOverPrivateProperty: - active: false - EndOfSentenceFormat: - active: false - endOfSentenceFormat: ([.?!][ \t\n\r\f<])|([.?!]$) - UndocumentedPublicClass: - active: false - searchInNestedClass: true - searchInInnerClass: true - searchInInnerObject: true - searchInInnerInterface: true - UndocumentedPublicFunction: - active: false + active: true + CommentOverPrivateFunction: + active: false + CommentOverPrivateProperty: + active: false + EndOfSentenceFormat: + active: false + endOfSentenceFormat: ([.?!][ \t\n\r\f<])|([.?!]$) + UndocumentedPublicClass: + active: false + searchInNestedClass: true + searchInInnerClass: true + searchInInnerObject: true + searchInInnerInterface: true + UndocumentedPublicFunction: + active: false complexity: - active: true - ComplexCondition: - active: true - threshold: 4 - ComplexInterface: - active: false - threshold: 10 - includeStaticDeclarations: false - ComplexMethod: - active: true - threshold: 10 - ignoreSingleWhenExpression: false - ignoreSimpleWhenEntries: false - LabeledExpression: - active: false - ignoredLabels: "" - LargeClass: - active: true - threshold: 600 - LongMethod: - active: true - threshold: 60 - LongParameterList: - active: true - threshold: 6 - ignoreDefaultParameters: false - MethodOverloading: - active: false - threshold: 6 - NestedBlockDepth: active: true - threshold: 4 - StringLiteralDuplication: - active: false - threshold: 3 - ignoreAnnotation: true - excludeStringsWithLessThan5Characters: true - ignoreStringsRegex: '$^' - TooManyFunctions: - active: true - thresholdInFiles: 11 - thresholdInClasses: 11 - thresholdInInterfaces: 11 - thresholdInObjects: 11 - thresholdInEnums: 11 - ignoreDeprecated: false - ignorePrivate: false - ignoreOverridden: false + ComplexCondition: + active: true + threshold: 4 + ComplexInterface: + active: false + threshold: 10 + includeStaticDeclarations: false + ComplexMethod: + active: true + threshold: 10 + ignoreSingleWhenExpression: false + ignoreSimpleWhenEntries: false + LabeledExpression: + active: false + ignoredLabels: "" + LargeClass: + active: true + threshold: 600 + LongMethod: + active: true + threshold: 60 + LongParameterList: + active: true + functionThreshold: 6 + constructorThreshold: 6 + ignoreDefaultParameters: false + MethodOverloading: + active: false + threshold: 6 + NestedBlockDepth: + active: true + threshold: 4 + StringLiteralDuplication: + active: false + threshold: 3 + ignoreAnnotation: true + excludeStringsWithLessThan5Characters: true + ignoreStringsRegex: '$^' + TooManyFunctions: + active: true + thresholdInFiles: 15 + thresholdInClasses: 15 + thresholdInInterfaces: 15 + thresholdInObjects: 15 + thresholdInEnums: 11 + ignoreDeprecated: true + ignorePrivate: false + ignoreOverridden: true empty-blocks: - active: true - EmptyCatchBlock: - active: true - allowedExceptionNameRegex: "^(_|(ignore|expected).*)" - EmptyClassBlock: - active: true - EmptyDefaultConstructor: - active: true - EmptyDoWhileBlock: - active: true - EmptyElseBlock: - active: true - EmptyFinallyBlock: - active: true - EmptyForBlock: - active: true - EmptyFunctionBlock: - active: true - ignoreOverriddenFunctions: false - EmptyIfBlock: - active: true - EmptyInitBlock: - active: true - EmptyKtFile: - active: true - EmptySecondaryConstructor: - active: true - EmptyWhenBlock: - active: true - EmptyWhileBlock: active: true + EmptyCatchBlock: + active: true + allowedExceptionNameRegex: "^(_|(ignore|expected).*)" + EmptyClassBlock: + active: true + EmptyDefaultConstructor: + active: true + EmptyDoWhileBlock: + active: true + EmptyElseBlock: + active: true + EmptyFinallyBlock: + active: true + EmptyForBlock: + active: true + EmptyFunctionBlock: + active: true + ignoreOverridden: false + EmptyIfBlock: + active: true + EmptyInitBlock: + active: true + EmptyKtFile: + active: true + EmptySecondaryConstructor: + active: true + EmptyWhenBlock: + active: true + EmptyWhileBlock: + active: true exceptions: - active: true - ExceptionRaisedInUnexpectedLocation: - active: false - methodNames: 'toString,hashCode,equals,finalize' - InstanceOfCheckForException: - active: false - NotImplementedDeclaration: - active: false - PrintStackTrace: - active: false - RethrowCaughtException: - active: false - ReturnFromFinally: - active: false - SwallowedException: - active: false - ignoredExceptionTypes: 'InterruptedException,NumberFormatException,ParseException,MalformedURLException' - ThrowingExceptionFromFinally: - active: false - ThrowingExceptionInMain: - active: false - ThrowingExceptionsWithoutMessageOrCause: - active: false - exceptions: 'IllegalArgumentException,IllegalStateException,IOException' - ThrowingNewInstanceOfSameException: - active: false - TooGenericExceptionCaught: - active: true - exceptionNames: - - ArrayIndexOutOfBoundsException - - Error - - Exception - - IllegalMonitorStateException - - NullPointerException - - IndexOutOfBoundsException - - RuntimeException - - Throwable - allowedExceptionNameRegex: "^(_|(ignore|expected).*)" - TooGenericExceptionThrown: active: true - exceptionNames: - - Error - - Exception - - Throwable - - RuntimeException - -formatting: - active: true - android: false - autoCorrect: true - ChainWrapping: - active: true - autoCorrect: true - CommentSpacing: - active: true - autoCorrect: true - Filename: - active: true - FinalNewline: - active: true - autoCorrect: true - ImportOrdering: - active: false - Indentation: - active: true - autoCorrect: true - indentSize: 4 - continuationIndentSize: 4 - MaximumLineLength: - active: true - maxLineLength: 120 - ModifierOrdering: - active: true - autoCorrect: true - NoBlankLineBeforeRbrace: - active: true - autoCorrect: true - NoConsecutiveBlankLines: - active: true - autoCorrect: true - NoEmptyClassBody: - active: true - autoCorrect: true - NoItParamInMultilineLambda: - active: false - NoLineBreakAfterElse: - active: true - autoCorrect: true - NoLineBreakBeforeAssignment: - active: true - autoCorrect: true - NoMultipleSpaces: - active: true - autoCorrect: true - NoSemicolons: - active: true - autoCorrect: true - NoTrailingSpaces: - active: true - autoCorrect: true - NoUnitReturn: - active: true - autoCorrect: true - NoUnusedImports: - active: true - autoCorrect: true - NoWildcardImports: - active: true - autoCorrect: true - PackageName: - active: true - autoCorrect: true - ParameterListWrapping: - active: true - autoCorrect: true - indentSize: 4 - SpacingAroundColon: - active: true - autoCorrect: true - SpacingAroundComma: - active: true - autoCorrect: true - SpacingAroundCurly: - active: true - autoCorrect: true - SpacingAroundKeyword: - active: true - autoCorrect: true - SpacingAroundOperators: - active: true - autoCorrect: true - SpacingAroundParens: - active: true - autoCorrect: true - SpacingAroundRangeOperator: - active: true - autoCorrect: true - StringTemplate: - active: true - autoCorrect: true + ExceptionRaisedInUnexpectedLocation: + active: false + methodNames: 'toString,hashCode,equals,finalize' + InstanceOfCheckForException: + active: false + NotImplementedDeclaration: + active: false + PrintStackTrace: + active: false + RethrowCaughtException: + active: false + ReturnFromFinally: + active: false + SwallowedException: + active: false + ignoredExceptionTypes: 'InterruptedException,NumberFormatException,ParseException,MalformedURLException' + ThrowingExceptionFromFinally: + active: false + ThrowingExceptionInMain: + active: false + ThrowingExceptionsWithoutMessageOrCause: + active: false + exceptions: 'IllegalArgumentException,IllegalStateException,IOException' + ThrowingNewInstanceOfSameException: + active: false + TooGenericExceptionCaught: + active: true + exceptionNames: + - ArrayIndexOutOfBoundsException + - Error + - Exception + - IllegalMonitorStateException + - NullPointerException + - IndexOutOfBoundsException + - RuntimeException + - Throwable + allowedExceptionNameRegex: "^(_|(ignore|expected).*)" + TooGenericExceptionThrown: + active: true + exceptionNames: + - Error + - Exception + - Throwable + - RuntimeException naming: - active: true - ClassNaming: - active: true - classPattern: '[A-Z$][a-zA-Z0-9$]*' - ConstructorParameterNaming: - active: true - parameterPattern: '[a-z][A-Za-z0-9]*' - privateParameterPattern: '[a-z][A-Za-z0-9]*' - excludeClassPattern: '$^' - EnumNaming: - active: true - enumEntryPattern: '^[A-Z][_a-zA-Z0-9]*' - ForbiddenClassName: - active: false - forbiddenName: '' - FunctionMaxLength: - active: false - maximumFunctionNameLength: 30 - FunctionMinLength: - active: false - minimumFunctionNameLength: 3 - FunctionNaming: - active: true - functionPattern: '^([a-z$][a-zA-Z$0-9]*)|(`.*`)$' - excludeClassPattern: '$^' - ignoreOverridden: true - FunctionParameterNaming: active: true - parameterPattern: '[a-z][A-Za-z0-9]*' - excludeClassPattern: '$^' - ignoreOverriddenFunctions: true - MatchingDeclarationName: - active: true - MemberNameEqualsClassName: - active: false - ignoreOverriddenFunction: true - ObjectPropertyNaming: - active: true - constantPattern: '[A-Za-z][_A-Za-z0-9]*' - propertyPattern: '[A-Za-z][_A-Za-z0-9]*' - privatePropertyPattern: '(_)?[A-Za-z][_A-Za-z0-9]*' - PackageNaming: - active: true - packagePattern: '^[a-z]+(\.[a-z][A-Za-z0-9]*)*$' - TopLevelPropertyNaming: - active: true - constantPattern: '[A-Z][_A-Z0-9]*' - propertyPattern: '[A-Za-z][_A-Za-z0-9]*' - privatePropertyPattern: '(_)?[A-Za-z][A-Za-z0-9]*' - VariableMaxLength: - active: false - maximumVariableNameLength: 64 - VariableMinLength: - active: false - minimumVariableNameLength: 1 - VariableNaming: - active: true - variablePattern: '[a-z][A-Za-z0-9]*' - privateVariablePattern: '(_)?[a-z][A-Za-z0-9]*' - excludeClassPattern: '$^' - ignoreOverridden: true + ClassNaming: + active: true + classPattern: '[A-Z$][a-zA-Z0-9$]*' + ConstructorParameterNaming: + active: true + parameterPattern: '[a-z][A-Za-z0-9]*' + privateParameterPattern: '[a-z][A-Za-z0-9]*' + excludeClassPattern: '$^' + EnumNaming: + active: true + enumEntryPattern: '^[A-Z][_a-zA-Z0-9]*' + ForbiddenClassName: + active: false + forbiddenName: '' + FunctionMaxLength: + active: false + maximumFunctionNameLength: 30 + FunctionMinLength: + active: false + minimumFunctionNameLength: 3 + FunctionNaming: + active: true + functionPattern: '^([a-z$][a-zA-Z$0-9]*)|(`.*`)$' + excludeClassPattern: '$^' + ignoreOverridden: true + excludes: "**/*Test.kt" + FunctionParameterNaming: + active: true + parameterPattern: '[a-z][A-Za-z0-9]*' + excludeClassPattern: '$^' + ignoreOverridden: true + MatchingDeclarationName: + active: true + MemberNameEqualsClassName: + active: false + ignoreOverridden: true + ObjectPropertyNaming: + active: true + constantPattern: '[A-Za-z][_A-Za-z0-9]*' + propertyPattern: '[A-Za-z][_A-Za-z0-9]*' + privatePropertyPattern: '(_)?[A-Za-z][_A-Za-z0-9]*' + PackageNaming: + active: true + packagePattern: '^[a-z]+(\.[a-z][A-Za-z0-9]*)*$' + TopLevelPropertyNaming: + active: true + constantPattern: '[A-Z][_A-Z0-9]*' + propertyPattern: '[A-Za-z][_A-Za-z0-9]*' + privatePropertyPattern: '(_)?[A-Za-z][A-Za-z0-9]*' + VariableMaxLength: + active: false + maximumVariableNameLength: 64 + VariableMinLength: + active: false + minimumVariableNameLength: 1 + VariableNaming: + active: true + variablePattern: '[a-z][A-Za-z0-9]*' + privateVariablePattern: '(_)?[a-z][A-Za-z0-9]*' + excludeClassPattern: '$^' + ignoreOverridden: true performance: - active: true - ArrayPrimitive: - active: false - ForEachOnRange: - active: true - SpreadOperator: - active: true - UnnecessaryTemporaryInstantiation: active: true + ArrayPrimitive: + active: false + ForEachOnRange: + active: true + SpreadOperator: + active: true + UnnecessaryTemporaryInstantiation: + active: true potential-bugs: - active: true - DuplicateCaseInWhenExpression: - active: true - EqualsAlwaysReturnsTrueOrFalse: - active: false - EqualsWithHashCodeExist: - active: true - ExplicitGarbageCollectionCall: - active: true - InvalidRange: - active: false - IteratorHasNextCallsNextMethod: - active: false - IteratorNotThrowingNoSuchElementException: - active: false - LateinitUsage: - active: false - excludeAnnotatedProperties: "" - ignoreOnClassesPattern: "" - UnconditionalJumpStatementInLoop: - active: false - UnreachableCode: active: true - UnsafeCallOnNullableType: - active: false - UnsafeCast: - active: false - UselessPostfixExpression: - active: false - WrongEqualsTypeParameter: - active: false + DuplicateCaseInWhenExpression: + active: true + EqualsAlwaysReturnsTrueOrFalse: + active: false + EqualsWithHashCodeExist: + active: true + ExplicitGarbageCollectionCall: + active: true + InvalidRange: + active: false + IteratorHasNextCallsNextMethod: + active: false + IteratorNotThrowingNoSuchElementException: + active: false + LateinitUsage: + active: false + ignoreAnnotated: [ ] + ignoreOnClassesPattern: "" + UnconditionalJumpStatementInLoop: + active: false + UnreachableCode: + active: true + UnsafeCallOnNullableType: + active: false + UnsafeCast: + active: false + UselessPostfixExpression: + active: false + WrongEqualsTypeParameter: + active: false style: - active: true - CollapsibleIfStatements: - active: false - DataClassContainsFunctions: - active: false - conversionFunctionPrefix: 'to' - EqualsNullCall: - active: false - EqualsOnSignatureLine: - active: false - ExplicitItLambdaParameter: - active: false - ExpressionBodySyntax: - active: false - includeLineWrapping: false - ForbiddenComment: - active: true - values: 'TODO:,FIXME:,STOPSHIP:' - ForbiddenImport: - active: false - imports: '' - FunctionOnlyReturningConstant: - active: false - ignoreOverridableFunction: true - excludedFunctions: 'describeContents' - LoopWithTooManyJumpStatements: - active: false - maxJumpCount: 1 - MagicNumber: - active: true - ignoreNumbers: '-1,0,1,2' - ignoreHashCodeFunction: true - ignorePropertyDeclaration: false - ignoreConstantDeclaration: true - ignoreCompanionObjectPropertyDeclaration: true - ignoreAnnotation: false - ignoreNamedArgument: true - ignoreEnums: false - MandatoryBracesIfStatements: - active: false - MaxLineLength: - active: true - maxLineLength: 120 - excludePackageStatements: true - excludeImportStatements: true - excludeCommentStatements: false - MayBeConst: - active: false - ModifierOrder: - active: true - NestedClassesVisibility: - active: false - NewLineAtEndOfFile: - active: true - NoTabs: - active: false - OptionalAbstractKeyword: - active: true - OptionalUnit: - active: false - OptionalWhenBraces: - active: false - PreferToOverPairSyntax: - active: false - ProtectedMemberInFinalClass: - active: false - RedundantVisibilityModifierRule: - active: false - ReturnCount: - active: true - max: 2 - excludedFunctions: "equals" - excludeLabeled: false - excludeReturnFromLambda: true - SafeCast: - active: true - SerialVersionUIDInSerializableClass: - active: false - SpacingBetweenPackageAndImports: - active: false - ThrowsCount: - active: true - max: 2 - TrailingWhitespace: - active: false - UnderscoresInNumericLiterals: - active: false - acceptableDecimalLength: 5 - UnnecessaryAbstractClass: - active: false - excludeAnnotatedClasses: "dagger.Module" - UnnecessaryApply: - active: false - UnnecessaryInheritance: - active: false - UnnecessaryLet: - active: false - UnnecessaryParentheses: - active: false - UntilInsteadOfRangeTo: - active: false - UnusedImports: - active: false - UnusedPrivateClass: - active: false - UnusedPrivateMember: - active: false - allowedNames: "(_|ignored|expected|serialVersionUID)" - UseDataClass: - active: false - excludeAnnotatedClasses: "" - UtilityClassWithPublicConstructor: - active: false - VarCouldBeVal: - active: false - WildcardImport: active: true - excludeImports: 'java.util.*,kotlinx.android.synthetic.*' + CollapsibleIfStatements: + active: false + DataClassContainsFunctions: + active: false + conversionFunctionPrefix: 'to' + EqualsNullCall: + active: false + EqualsOnSignatureLine: + active: false + ExplicitItLambdaParameter: + active: false + ExpressionBodySyntax: + active: false + includeLineWrapping: false + ForbiddenComment: + active: true + values: 'TODO:,FIXME:,STOPSHIP:' + ForbiddenImport: + active: false + imports: '' + ForbiddenVoid: + active: false + FunctionOnlyReturningConstant: + active: false + ignoreOverridableFunction: true + excludedFunctions: 'describeContents' + LoopWithTooManyJumpStatements: + active: false + maxJumpCount: 1 + MagicNumber: + active: true + ignoreNumbers: '-1,0,1,2' + ignoreHashCodeFunction: true + ignorePropertyDeclaration: false + ignoreConstantDeclaration: true + ignoreCompanionObjectPropertyDeclaration: true + ignoreAnnotation: false + ignoreNamedArgument: true + ignoreEnums: false + excludes: "**/*Test.kt" + MandatoryBracesIfStatements: + active: false + MaxLineLength: + active: true + maxLineLength: 120 + excludePackageStatements: true + excludeImportStatements: true + excludeCommentStatements: false + MayBeConst: + active: false + ModifierOrder: + active: true + NestedClassesVisibility: + active: false + NewLineAtEndOfFile: + active: true + NoTabs: + active: false + OptionalAbstractKeyword: + active: true + OptionalUnit: + active: false + OptionalWhenBraces: + active: false + PreferToOverPairSyntax: + active: false + ProtectedMemberInFinalClass: + active: false + RedundantVisibilityModifierRule: + active: false + ReturnCount: + active: true + max: 2 + excludedFunctions: "equals" + excludeLabeled: false + excludeReturnFromLambda: true + SafeCast: + active: true + SerialVersionUIDInSerializableClass: + active: false + SpacingBetweenPackageAndImports: + active: false + ThrowsCount: + active: true + max: 2 + TrailingWhitespace: + active: false + UnderscoresInNumericLiterals: + active: false + acceptableDecimalLength: 5 + UnnecessaryAbstractClass: + active: false + ignoreAnnotated: + - "dagger.Module" + UnnecessaryApply: + active: false + UnnecessaryInheritance: + active: false + UnnecessaryLet: + active: false + UnnecessaryParentheses: + active: false + UntilInsteadOfRangeTo: + active: false + UnusedImports: + active: false + UnusedPrivateClass: + active: false + UnusedPrivateMember: + active: false + allowedNames: "(_|ignored|expected|serialVersionUID)" + UseDataClass: + active: false + ignoreAnnotated: [ ] + UtilityClassWithPublicConstructor: + active: false + VarCouldBeVal: + active: false + WildcardImport: + active: true + excludeImports: 'java.util.*,kotlinx.android.synthetic.*' diff --git a/lib/src/main/java/com/nextcloud/android/sso/helper/Retrofit2Helper.java b/lib/src/main/java/com/nextcloud/android/sso/helper/Retrofit2Helper.java index 0099526e..0e68a214 100644 --- a/lib/src/main/java/com/nextcloud/android/sso/helper/Retrofit2Helper.java +++ b/lib/src/main/java/com/nextcloud/android/sso/helper/Retrofit2Helper.java @@ -10,8 +10,6 @@ */ package com.nextcloud.android.sso.helper; -import androidx.annotation.NonNull; - import com.nextcloud.android.sso.aidl.NextcloudRequest; import com.nextcloud.android.sso.api.AidlNetworkRequest; import com.nextcloud.android.sso.api.NextcloudAPI; @@ -21,9 +19,11 @@ import java.util.Arrays; import java.util.HashSet; import java.util.List; +import java.util.Locale; import java.util.Optional; import java.util.Set; +import androidx.annotation.NonNull; import okhttp3.Headers; import okhttp3.Protocol; import okhttp3.Request; @@ -140,7 +140,7 @@ public static Headers buildHeaders(List plainHea final String value = header.getValue(); // Create a unique key for name:value combination - final String key = name.toLowerCase() + ":" + value; + final String key = name.toLowerCase(Locale.US) + ":" + value; // Only add if we haven't seen this exact name:value combination before if (!seen.contains(key)) { diff --git a/lint.xml b/lint.xml index c86350ec..8917d0d3 100644 --- a/lint.xml +++ b/lint.xml @@ -13,7 +13,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/scripts/analysis/analysis-wrapper.sh b/scripts/analysis/analysis-wrapper.sh index 775395d4..6000319f 100755 --- a/scripts/analysis/analysis-wrapper.sh +++ b/scripts/analysis/analysis-wrapper.sh @@ -4,164 +4,82 @@ # SPDX-FileCopyrightText: 2017 Tobias Kaminsky # SPDX-License-Identifier: GPL-3.0-or-later -#1: GIT_USERNAME -#2: GIT_TOKEN -#3: BRANCH -#4: LOG_USERNAME -#5: LOG_PASSWORD -#6: DRONE_BUILD_NUMBER -#7: PULL_REQUEST_NUMBER - -stableBranch="master" +BRANCH=$1 +LOG_USERNAME=$2 +LOG_PASSWORD=$3 +BUILD_NUMBER=$4 +PR_NUMBER=$5 + +stableBranch="main" repository="android-singleSignOn" codacyProject=160903 -ruby scripts/analysis/lint-up.rb $1 $2 $3 -lintValue=$? - -ruby scripts/analysis/findbugs-up.rb $1 $2 $3 -findbugsValue=$? - - -./gradlew lib:ktlint -ktlintValue=$? - -./gradlew lib:detekt -detektValue=$? +curl "https://www.kaminsky.me/nc-dev/$repository-findbugs/$stableBranch.xml" -o "/tmp/$stableBranch.xml" +ruby scripts/analysis/spotbugs-up.rb "$stableBranch" +spotbugsValue=$? # exit codes: # 0: count was reduced # 1: count was increased # 2: count stayed the same -echo "Branch: $3" +source scripts/lib.sh -if [ $3 = $stableBranch ]; then - echo "New findbugs result for $stableBranch at: https://www.kaminsky.me/nc-dev/$repository-findbugs/$stableBranch.html" - curl -u $4:$5 -X PUT https://nextcloud.kaminsky.me/remote.php/webdav/$repository-findbugs/$stableBranch.html --upload-file lib/build/reports/spotbugs/spotbugs.html +echo "Branch: $BRANCH" - summary=$(sed -n "/

Summary<\/h1>/,/

Warnings<\/h1>/p" lib/build/reports/spotbugs/spotbugs.html | head -n-1 | sed s'/<\/a>//'g | sed s'///'g | sed s"/Summary/SpotBugs ($stableBranch)/" | tr "\"" "\'" | tr -d "\r\n") - curl -u $4:$5 -X PUT -d "$summary" https://nextcloud.kaminsky.me/remote.php/webdav/$repository-findbugs/findbugs-summary-$stableBranch.html - - if [ $lintValue -ne 1 ]; then - echo "New lint result for $stableBranch at: https://www.kaminsky.me/nc-dev/$repository-lint/$stableBranch.html" - curl -u $4:$5 -X PUT https://nextcloud.kaminsky.me/remote.php/webdav/$repository-lint/$stableBranch.html --upload-file lib/build/reports/lint/lint.html - exit 0 - fi +if [ "$BRANCH" = $stableBranch ]; then + echo "New spotbugs result for $stableBranch at: https://www.kaminsky.me/nc-dev/$repository-findbugs/$stableBranch.html" + curl -u "${LOG_USERNAME}:${LOG_PASSWORD}" -X PUT https://nextcloud.kaminsky.me/remote.php/webdav/$repository-findbugs/$stableBranch.html --upload-file library/build/reports/spotbugs/spotbugs.html + curl 2>/dev/null -u "${LOG_USERNAME}:${LOG_PASSWORD}" -X PUT "https://nextcloud.kaminsky.me/remote.php/webdav/$repository-findbugs/$stableBranch.xml" --upload-file library/build/reports/spotbugs/debug.xml else - if [ -e $6 ]; then - name=$stableBranch"-"$(date +%F) - else - name=$6; + if [ -e "${BUILD_NUMBER}" ]; then + 6=$stableBranch"-"$(date +%F) fi - echo "New lint results at https://www.kaminsky.me/nc-dev/$repository-lint/$name.html" - curl 2>/dev/null -u $4:$5 -X PUT https://nextcloud.kaminsky.me/remote.php/webdav/$repository-lint/$name.html --upload-file lib/build/reports/lint/lint.html - echo "New findbugs results at https://www.kaminsky.me/nc-dev/$repository-findbugs/$name.html" - curl 2>/dev/null -u $4:$5 -X PUT https://nextcloud.kaminsky.me/remote.php/webdav/$repository-findbugs/$name.html --upload-file lib/build/reports/spotbugs/spotbugs.html + echo "New spotbugs results at https://www.kaminsky.me/nc-dev/$repository-findbugs/${BUILD_NUMBER}.html" + curl 2>/dev/null -u "${LOG_USERNAME}:${LOG_PASSWORD}" -X PUT "https://nextcloud.kaminsky.me/remote.php/webdav/$repository-findbugs/${BUILD_NUMBER}.html" --upload-file library/build/reports/spotbugs/spotbugs.html # delete all old comments, starting with Codacy - oldComments=$(curl 2>/dev/null -u $1:$2 -X GET https://api.github.com/repos/nextcloud/$repository/issues/$7/comments | jq '.[] | (.id |tostring) + "|" + (.user.login | test("nextcloud-android-bot") | tostring) + "|" + (.body | test("

Codacy.*") | tostring)' | grep "true|true" | tr -d "\"" | cut -f1 -d"|") + oldComments=$(curl_gh -X GET "https://api.github.com/repos/nextcloud/$repository/issues/${PR_NUMBER}/comments" | jq '.[] | select((.user.login | contains("github-actions")) and (.body | test("

Codacy.*"))) | .id') - echo $oldComments | while read comment ; do - curl 2>/dev/null -u $1:$2 -X DELETE https://api.github.com/repos/nextcloud/$repository/issues/comments/$comment + echo "$oldComments" | while read -r comment ; do + curl_gh -X DELETE "https://api.github.com/repos/nextcloud/$repository/issues/comments/$comment" done - # lint and findbugs file must exist - if [ ! -s lib/build/reports/lint/lint.html ] ; then - echo "lint.html file is missing!" - exit 1 - fi - - if [ ! -s lib/build/reports/spotbugs/spotbugs.html ] ; then + # spotbugs file must exist + if [ ! -s library/build/reports/spotbugs/spotbugs.html ] ; then echo "spotbugs.html file is missing!" exit 1 fi # add comment with results - lintResultNew=$(grep "Lint Report.* [0-9]* warning" lib/build/reports/lint/lint.html | cut -f2 -d':' |cut -f1 -d'<') - - lintErrorNew=$(echo $lintResultNew | grep "[0-9]* error" -o | cut -f1 -d" ") - if ( [ -z $lintErrorNew ] ); then - lintErrorNew=0 - fi - - lintWarningNew=$(echo $lintResultNew | grep "[0-9]* warning" -o | cut -f1 -d" ") - if ( [ -z $lintWarningNew ] ); then - lintWarningNew=0 - fi + spotbugsResult="

SpotBugs

$(scripts/analysis/spotbugsComparison.py "/tmp/$stableBranch.xml" library/build/reports/spotbugs/debug.xml --link-new "https://www.kaminsky.me/nc-dev/$repository-findbugs/${BUILD_NUMBER}.html" --link-base "https://www.kaminsky.me/nc-dev/$repository-findbugs/$stableBranch.html")" - lintResultOld=$(curl 2>/dev/null https://raw.githubusercontent.com/nextcloud/$repository/$stableBranch/scripts/analysis/lint-results.txt) - lintErrorOld=$(echo $lintResultOld | grep "[0-9]* error" -o | cut -f1 -d" ") - if ( [ -z $lintErrorOld ] ); then - lintErrorOld=0 + if ( [ $spotbugsValue -eq 1 ] ) ; then + spotbugsMessage="

SpotBugs increased!

" fi - - lintWarningOld=$(echo $lintResultOld | grep "[0-9]* warning" -o | cut -f1 -d" ") - if ( [ -z $lintWarningOld ] ); then - lintWarningOld=0 + + # check for NotNull + if [[ $(grep org.jetbrains.annotations library/src/main/* -irl | wc -l) -gt 0 ]] ; then + notNull="org.jetbrains.annotations.* is used. Please use androidx.annotation.* instead.

" fi - if [ $stableBranch = "master" ] ; then - codacyValue=$(curl 2>/dev/null https://app.codacy.com/dashboards/breakdown\?projectId\=$codacyProject | grep "total issues" | cut -d">" -f3 | cut -d"<" -f1) - codacyResult="

Codacy

$codacyValue" - else - codacyResult="" - fi - - lintResult="

Lint

Type$stableBranchPR
Warnings"$lintWarningOld""$lintWarningNew"
Errors"$lintErrorOld""$lintErrorNew"
" - findbugsResultNew=$(sed -n "/

Summary<\/h1>/,/

Warnings<\/h1>/p" lib/build/reports/spotbugs/spotbugs.html |head -n-1 | sed s'/<\/a>//'g | sed s'///'g | sed s"#Summary#SpotBugs (new)#" | tr "\"" "\'" | tr -d "\n") - findbugsResultOld=$(curl 2>/dev/null https://www.kaminsky.me/nc-dev/$repository-findbugs/findbugs-summary-$stableBranch.html | tr "\"" "\'" | tr -d "\r\n" | sed s"#SpotBugs#SpotBugs#" | tr "\"" "\'" | tr -d "\n") - - - if ( [ $lintValue -eq 1 ] ) ; then - lintMessage="

Lint increased!

" - fi - - if ( [ $findbugsValue -eq 1 ] ) ; then - findbugsMessage="

SpotBugs increased!

" - fi - - if ( [ $ktlintValue -eq 1 ] ) ; then - sed -i ':a;N;$!ba;s#\n#
#g;s#^
##g' lib/build/ktlint.txt - curl -u $4:$5 -X PUT https://nextcloud.kaminsky.me/remote.php/webdav/$repository-ktlint/$name.html --upload-file lib/build/ktlint.txt - ktlintMessage="

Kotlin lint found errors

Lint" - fi - - if ( [ $detektValue -eq 1 ] ) ; then - curl -u $4:$5 -X PUT https://nextcloud.kaminsky.me/remote.php/webdav/$repository-detekt/$name.html --upload-file lib/build/reports/detekt/detekt.html - detektMessage="

Detekt errors found

Lint" - fi - - # check gplay limitation: all changelog files must only have 500 chars - gplayLimitation=$(scripts/checkGplayLimitation.sh) + bodyContent="$spotbugsResult $spotbugsMessage $gplayLimitation $notNull" + echo "$bodyContent" >> "$GITHUB_STEP_SUMMARY" + payload="{ \"body\" : \"$bodyContent\" }" + curl_gh -X POST "https://api.github.com/repos/nextcloud/$repository/issues/${PR_NUMBER}/comments" -d "$payload" if [ ! -z "$gplayLimitation" ]; then - gplayLimitation="

Following files are beyond 500 char limit:



"$gplayLimitation - fi - - curl -u $1:$2 -X POST https://api.github.com/repos/nextcloud/$repository/issues/$7/comments -d "{ \"body\" : \"$codacyResult $lintResult $findbugsResultNew $findbugsResultOld $lintMessage $findbugsMessage $ktlintMessage $detektMessage $gplayLimitation \" }" - - if [ ! -z "$gplayLimitation" ]; then - exit 1 - fi - - if [ ! $lintValue -eq 2 ]; then - exit $lintValue - fi - - - if [ $ktlintValue -eq 1 ]; then exit 1 fi - if [ $detektValue -eq 1 ]; then + if [ -n "$notNull" ]; then exit 1 fi - if [ $findbugsValue -eq 2 ]; then + if [ $spotbugsValue -eq 2 ]; then exit 0 else - exit $findbugsValue + exit $spotbugsValue fi fi diff --git a/scripts/analysis/findbugs-up.rb b/scripts/analysis/findbugs-up.rb deleted file mode 100755 index 6956d08b..00000000 --- a/scripts/analysis/findbugs-up.rb +++ /dev/null @@ -1,136 +0,0 @@ -## Script from https://github.com/tir38/android-lint-entropy-reducer at 07.05.2017 -# adapts to drone, use git username / token as parameter - -# SPDX-FileCopyrightText: 2017-2024 Nextcloud GmbH and Nextcloud contributors -# SPDX-FileCopyrightText: 2017 Jason Atwood -# SPDX-FileCopyrightText: 2017 Tobias Kaminsky -# SPDX-License-Identifier: GPL-3.0-or-later - -Encoding.default_external = Encoding::UTF_8 -Encoding.default_internal = Encoding::UTF_8 - -puts "=================== starting Android FindBugs Entropy Reducer ====================" - -# get args -git_user, git_token, git_branch = ARGV - -# ======================== SETUP ============================ - -# User name for git commits made by this script. -TRAVIS_GIT_USERNAME = String.new("Drone CI server") - -# File name and relative path of generated FindBugs report. Must match build.gradle file: -# lintOptions { -# htmlOutput file("[FILE_NAME].html") -# } -FINDBUGS_REPORT_FILE = String.new("lib/build/reports/spotbugs/spotbugs.html") - -# File name and relative path of previous results of this script. -PREVIOUS_FINDBUGS_RESULTS_FILE=String.new("scripts/analysis/findbugs-results.txt") - -# Flag to evaluate warnings. true = check warnings; false = ignore warnings -CHECK_WARNINGS = true - -# File name and relative path to custom FindBugs rules; Can be null or "". -CUSTOM_FINDBUGS_FILE = String.new("") - -# ================ SETUP DONE; DON'T TOUCH ANYTHING BELOW ================ - -require 'fileutils' -require 'pathname' -require 'open3' - -# since we need the xml-simple gem, and we want this script self-contained, let's grab it just when we need it -begin - gem "xml-simple" - rescue LoadError - system("gem install xml-simple") - Gem.clear_paths -end - -require 'xmlsimple' - -# run FindBugs -puts "running FindBugs..." -system './gradlew lib:assembleDebug' -system './gradlew lib:spotbugsDebug' - -# find FindBugs report file -findbugs_reports = Dir.glob(FINDBUGS_REPORT_FILE) -if findbugs_reports.length == 0 - puts "Findbugs HTML report not found." - exit 1 -end -findbugs_report = String.new(findbugs_reports[0]) - -# find number of warnings -current_warning_count = `grep -A 3 "Total" build/reports/spotbugs/spotbugs.html | tail -n1 | cut -f2 -d">" | cut -f1 -d"<"`.to_i -puts "found warnings: " + current_warning_count.to_s - -# get warning counts from last successful build - -previous_results = false - -previous_findbugs_reports = Dir.glob(PREVIOUS_FINDBUGS_RESULTS_FILE) -if previous_findbugs_reports.nil? || previous_findbugs_reports.length == 0 - previous_findbugs_report = File.new(PREVIOUS_FINDBUGS_RESULTS_FILE, "w") # create for writing to later -else - previous_findbugs_report = String.new(previous_findbugs_reports[0]) - - previous_warning_count = File.open(previous_findbugs_report, &:readline).match(/[0-9]*/)[0].to_i - - if previous_warning_count.nil? - previous_results = false - else - previous_results = true - - puts "previous warnings: " + previous_warning_count.to_s - end -end - -# compare previous warning count with current warning count -if previous_results == true && current_warning_count > previous_warning_count - puts "FAIL: warning count increased" - exit 1 -end - -# check if warning and error count stayed the same -if previous_results == true && current_warning_count == previous_warning_count - puts "SUCCESS: count stayed the same" - exit 2 -end - -# warning count DECREASED -puts "SUCCESS: count decreased from " + previous_warning_count.to_s + " to " + current_warning_count.to_s - -# write new results to file (will overwrite existing, or create new) -File.write(previous_findbugs_report, current_warning_count) - -# push changes to github (if this script is run locally, we don't want to overwrite git username and email, so save temporarily) -previous_git_username, _ = Open3.capture2('git config user.name') -previous_git_username = previous_git_username.strip - -previous_git_email, _ = Open3.capture3('git config user.email') -previous_git_email = previous_git_email.strip - -# update git user name and email for this script -system ("git config --local user.name '" + git_user + "'") -system ("git config --local user.email 'android@nextcloud.com'") -system ("git remote rm origin") -system ("git remote add origin https://" + git_user + ":" + git_token + "@github.com/nextcloud/android-singlesignon") - -# add previous FindBugs result file to git -system ('git add ' + PREVIOUS_FINDBUGS_RESULTS_FILE) - -# commit changes; Add "skip ci" so that we don't accidentally trigger another Drone build -system ('git commit -sm "Drone: update FindBugs results to reflect reduced error/warning count [skip ci]" ') - -# push to origin -system ('git push origin HEAD:' + git_branch) - -# restore previous git user name and email -system("git config --local user.name '#{previous_git_username}'") -system("git config --local user.email '#{previous_git_email}'") - -puts "SUCCESS: count was reduced" -exit 0 # success diff --git a/scripts/analysis/lint-results.txt b/scripts/analysis/lint-results.txt deleted file mode 100644 index b50d2cfb..00000000 --- a/scripts/analysis/lint-results.txt +++ /dev/null @@ -1,2 +0,0 @@ -DO NOT TOUCH; GENERATED BY DRONE - Lint Report: No errors or warnings diff --git a/scripts/analysis/lint-up.rb b/scripts/analysis/lint-up.rb deleted file mode 100755 index 5f9dca0c..00000000 --- a/scripts/analysis/lint-up.rb +++ /dev/null @@ -1,205 +0,0 @@ -## Script from https://github.com/tir38/android-lint-entropy-reducer at 07.05.2017 -# adapts to drone, use git username / token as parameter - -# SPDX-FileCopyrightText: 2017-2024 Nextcloud GmbH and Nextcloud contributors -# SPDX-FileCopyrightText: 2017 Jason Atwood -# SPDX-FileCopyrightText: 2017 Tobias Kaminsky -# SPDX-License-Identifier: GPL-3.0-or-later - - -Encoding.default_external = Encoding::UTF_8 -Encoding.default_internal = Encoding::UTF_8 - -puts "=================== starting Android Lint Entropy Reducer ====================" - -# get args -git_user, git_token, git_branch = ARGV - -# ======================== SETUP ============================ - -# User name for git commits made by this script. -TRAVIS_GIT_USERNAME = String.new("Drone CI server") - -# File name and relative path of generated Lint report. Must match build.gradle file: -# lintOptions { -# htmlOutput file("[FILE_NAME].html") -# } -LINT_REPORT_FILE = String.new("lib/build/reports/lint/lint.html") - -# File name and relative path of previous results of this script. -PREVIOUS_LINT_RESULTS_FILE=String.new("scripts/analysis/lint-results.txt") - -# Flag to evaluate warnings. true = check warnings; false = ignore warnings -CHECK_WARNINGS = true - -# File name and relative path to custom lint rules; Can be null or "". -CUSTOM_LINT_FILE = String.new("") - -# ================ SETUP DONE; DON'T TOUCH ANYTHING BELOW ================ - -require 'fileutils' -require 'pathname' -require 'open3' - -# since we need the xml-simple gem, and we want this script self-contained, let's grab it just when we need it -begin - gem "xml-simple" - rescue LoadError - system("gem install xml-simple") - Gem.clear_paths -end - -require 'xmlsimple' - -# add custom Lint jar -if !CUSTOM_LINT_FILE.nil? && - CUSTOM_LINT_FILE.length > 0 - - ENV["ANDROID_LINT_JARS"] = Dir.pwd + "/" + CUSTOM_LINT_FILE - puts "adding custom lint rules to default set: " - puts ENV["ANDROID_LINT_JARS"] -end - -# run Lint -puts "running Lint..." -system './gradlew clean lib:lint' - -# confirm that Lint ran w/out error -result = $?.to_i -if result != 0 - puts "FAIL: failed to run ./gradlew clean lint" - exit 1 -end - -# find Lint report file -lint_reports = Dir.glob(LINT_REPORT_FILE) -if lint_reports.length == 0 - puts "Lint HTML report not found." - exit 1 -end -lint_report = String.new(lint_reports[0]) - -# find error/warning count string in HTML report -error_warning_string = "" -File.open lint_report do |file| - error_warning_string = file.find { |line| line =~ /([0-9]* error[s]? and )?[0-9]* warning[s]?/ } -end - -# find number of errors -error_string = error_warning_string.match(/[0-9]* error[s]?/) - -if (error_string.nil?) - current_error_count = 0 -else - current_error_count = error_string[0].match(/[0-9]*/)[0].to_i -end - -puts "found errors: " + current_error_count.to_s - -# find number of warnings -if CHECK_WARNINGS == true - warning_string = error_warning_string.match(/[0-9]* warning[s]?/)[0] - current_warning_count = warning_string.match(/[0-9]*/)[0].to_i - puts "found warnings: " + current_warning_count.to_s -end - -# get previous error and warning counts from last successful build - -previous_results = false - -previous_lint_reports = Dir.glob(PREVIOUS_LINT_RESULTS_FILE) -if previous_lint_reports.nil? || - previous_lint_reports.length == 0 - - previous_lint_report = File.new(PREVIOUS_LINT_RESULTS_FILE, "w") # create for writing to later -else - previous_lint_report = String.new(previous_lint_reports[0]) - - previous_error_warning_string = "" - File.open previous_lint_report do |file| - previous_error_warning_string = file.find { |line| line =~ /([0-9]* error[s]? and )?[0-9]* warning[s]?/ } - end - - unless previous_error_warning_string.nil? - previous_results = true - - previous_error_string = previous_error_warning_string.match(/[0-9]* error[s]?/) - if previous_error_string.nil? - previous_error_string = "0 errors" - else - previous_error_string = previous_error_string[0] - end - previous_error_count = previous_error_string.match(/[0-9]*/)[0].to_i - puts "previous errors: " + previous_error_count.to_s - - if CHECK_WARNINGS == true - previous_warning_string = previous_error_warning_string.match(/[0-9]* warning[s]?/) - if previous_warning_string.nil? - previous_warning_string = "0 warnings" - else - previous_warning_string = previous_warning_string[0] - end - previous_warning_count = previous_warning_string.match(/[0-9]*/)[0].to_i - puts "previous warnings: " + previous_warning_count.to_s - end - end -end - -# compare previous error count with current error count -if previous_results == true && - current_error_count > previous_error_count - puts "FAIL: error count increased" - exit 1 -end - -# compare previous warning count with current warning count -if CHECK_WARNINGS == true && - previous_results == true && - current_warning_count > previous_warning_count - - puts "FAIL: warning count increased" - exit 1 -end - -# check if warning and error count stayed the same -if previous_results == true && - current_error_count == previous_error_count && - current_warning_count == previous_warning_count - - puts "SUCCESS: count stayed the same" - exit 2 -end - -# either error count or warning count DECREASED - -# write new results to file (will overwrite existing, or create new) -File.write(previous_lint_report, "DO NOT TOUCH; GENERATED BY DRONE\n" + error_warning_string) - -# push changes to github (if this script is run locally, we don't want to overwrite git username and email, so save temporarily) -previous_git_username, _ = Open3.capture2('git config user.name') -previous_git_username = previous_git_username.strip - -previous_git_email, _ = Open3.capture3('git config user.email') -previous_git_email = previous_git_email.strip - -# update git user name and email for this script -system ("git config --local user.name '" + git_user + "'") -system ("git config --local user.email 'android@nextcloud.com'") -system ("git remote rm origin") -system ("git remote add origin https://" + git_user + ":" + git_token + "@github.com/nextcloud/android-singlesignon") - -# add previous Lint result file to git -system ('git add ' + PREVIOUS_LINT_RESULTS_FILE) - -# commit changes; Add "skip ci" so that we don't accidentally trigger another Drone build -system ('git commit -sm "Drone: update Lint results to reflect reduced error/warning count [skip ci]" ') - -# push to origin -system ('git push origin HEAD:' + git_branch) - -# restore previous git user name and email -system("git config --local user.name '#{previous_git_username}'") -system("git config --local user.email '#{previous_git_email}'") - -puts "SUCCESS: count was reduced" -exit 0 # success diff --git a/scripts/analysis/spotbugs-up.rb b/scripts/analysis/spotbugs-up.rb new file mode 100644 index 00000000..77827dc0 --- /dev/null +++ b/scripts/analysis/spotbugs-up.rb @@ -0,0 +1,53 @@ +## Script originally from https://github.com/tir38/android-lint-entropy-reducer at 07.05.2017 +# heavily modified since then + +# SPDX-FileCopyrightText: 2017-2024 Nextcloud GmbH and Nextcloud contributors +# SPDX-FileCopyrightText: 2017 Jason Atwood +# SPDX-FileCopyrightText: 2017 Tobias Kaminsky +# SPDX-License-Identifier: GPL-3.0-or-later + +Encoding.default_external = Encoding::UTF_8 +Encoding.default_internal = Encoding::UTF_8 + +puts "=================== starting Android Spotbugs Entropy Reducer ====================" + +# get args +base_branch = ARGV[0] + +require 'fileutils' +require 'pathname' +require 'open3' + +# run Spotbugs +puts "running Spotbugs..." +system './gradlew spotbugsDebug' + +# find number of warnings +current_warning_count = `./scripts/analysis/spotbugsSummary.py --file library/build/reports/spotbugs/debug.xml --total`.to_i +puts "found warnings: " + current_warning_count.to_s + +# get warning counts from target branch +previous_xml = "/tmp/#{base_branch}.xml" +previous_results = File.file?(previous_xml) + +if previous_results == true + previous_warning_count = `./scripts/analysis/spotbugsSummary.py --total --file #{previous_xml}`.to_i + puts "previous warnings: " + previous_warning_count.to_s +end + +# compare previous warning count with current warning count +if previous_results == true && current_warning_count > previous_warning_count + puts "FAIL: warning count increased" + exit 1 +end + +# check if warning and error count stayed the same +if previous_results == true && current_warning_count == previous_warning_count + puts "SUCCESS: count stayed the same" + exit 0 +end + +# warning count DECREASED +if previous_results == true && current_warning_count < previous_warning_count + puts "SUCCESS: count decreased from " + previous_warning_count.to_s + " to " + current_warning_count.to_s +end diff --git a/scripts/analysis/spotbugsComparison.py b/scripts/analysis/spotbugsComparison.py new file mode 100755 index 00000000..c0ba0f4f --- /dev/null +++ b/scripts/analysis/spotbugsComparison.py @@ -0,0 +1,57 @@ +#!/usr/bin/env python3 +# SPDX-FileCopyrightText: 2017-2024 Nextcloud GmbH and Nextcloud contributors +# SPDX-FileCopyrightText: 2017 Tobias Kaminsky +# SPDX-License-Identifier: GPL-3.0-or-later +import argparse +import defusedxml.ElementTree as ET + +import spotbugsSummary + + +def print_comparison(old: dict, new: dict, link_base: str, link_new: str): + all_keys = sorted(set(list(old.keys()) + list(new.keys()))) + + output = "" + old_header = f"Base" if link_base is not None else "Base" + output += f"" + new_header = f"New" if link_new is not None else "New" + output += f"" + output += "" + + for category in all_keys: + category_count_old = old[category] if category in old else 0 + category_count_new = new[category] if category in new else 0 + new_str = f"{category_count_new}" if category_count_new != category_count_old else str( + category_count_new) + output += "" + output += f"" + output += f"" + output += f"" + output += "" + + output += "" + output += "" + output += f"" + output += f"" + output += "" + + output += "
Category{old_header}{new_header}
{category}{category_count_old}{new_str}
Total{sum(old.values())}{sum(new.values())}
" + + print(output) + + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument("base_file", help="base file for comparison") + parser.add_argument("new_file", help="new file for comparison") + parser.add_argument("--link-base", help="http link to base html report") + parser.add_argument("--link-new", help="http link to new html report") + args = parser.parse_args() + + base_tree = ET.parse(args.base_file) + base_summary = spotbugsSummary.get_counts(base_tree) + + new_tree = ET.parse(args.new_file) + new_summary = spotbugsSummary.get_counts(new_tree) + + print_comparison(base_summary, new_summary, args.link_base, args.link_new) diff --git a/scripts/analysis/spotbugsSummary.py b/scripts/analysis/spotbugsSummary.py new file mode 100755 index 00000000..b5d85034 --- /dev/null +++ b/scripts/analysis/spotbugsSummary.py @@ -0,0 +1,65 @@ +#!/usr/bin/env python3 +# SPDX-FileCopyrightText: 2017-2024 Nextcloud GmbH and Nextcloud contributors +# SPDX-FileCopyrightText: 2017 Tobias Kaminsky +# SPDX-License-Identifier: GPL-3.0-or-later +import argparse +import defusedxml.ElementTree as ET + + +def get_counts(tree): + category_counts = {} + category_names = {} + for child in tree.getroot(): + if child.tag == "BugInstance": + category = child.attrib['category'] + if category in category_counts: + category_counts[category] = category_counts[category] + 1 + else: + category_counts[category] = 1 + elif child.tag == "BugCategory": + category = child.attrib['category'] + category_names[category] = child[0].text + + summary = {} + for category in category_counts.keys(): + summary[category_names[category]] = category_counts[category] + return summary + + +def print_html(summary): + output = "" + + categories = sorted(summary.keys()) + for category in categories: + output += "" + output += f"" + output += f"" + output += "" + + output += "" + output += "" + output += f"" + output += "" + + output += "
CategoryCount
{category}{summary[category]}
Total{sum(summary.values())}
" + + print(output) + + +def print_total(summary): + print(sum(summary.values())) + + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument("--total", help="print total count instead of summary HTML", + action="store_true") + parser.add_argument("--file", help="file to parse", + default="app/build/reports/spotbugs/gplayDebug.xml") + args = parser.parse_args() + tree = ET.parse(args.file) + summary = get_counts(tree) + if args.total: + print_total(summary) + else: + print_html(summary) diff --git a/scripts/lib.sh b/scripts/lib.sh new file mode 100644 index 00000000..b0688963 --- /dev/null +++ b/scripts/lib.sh @@ -0,0 +1,27 @@ +#!/usr/bin/env bash +# +# Nextcloud Android Library +# SPDX-FileCopyrightText: 2022-2024 Nextcloud GmbH and Nextcloud contributors +# SPDX-FileCopyrightText: 2022 Álvaro Brey +# SPDX-License-Identifier: MIT + +## This file is intended to be sourced by other scripts + + +function err() { + echo >&2 "$@" +} + + +function curl_gh() { + if [[ -n "$GITHUB_TOKEN" ]] + then + curl \ + --silent \ + --header "Authorization: token $GITHUB_TOKEN" \ + "$@" + else + err "WARNING: No GITHUB_TOKEN found. Skipping API call" + fi + +}