From 55e425a883f4c5693a6e023c19374749eb4b01a4 Mon Sep 17 00:00:00 2001 From: Fabio Alessandrelli Date: Sun, 5 Jul 2026 16:33:27 +0200 Subject: [PATCH] CI: Sync pre-commit scripts and actions with Godot Apply style --- .../actions/godot-cache-restore/action.yml | 39 +++++++ .github/actions/godot-cache-save/action.yml | 22 ++++ .github/actions/godot-cache/action.yml | 22 ---- .github/workflows/build_release.yml | 46 ++++---- .pre-commit-config.yaml | 91 +++++++++++++++ README.md | 2 +- SConstruct | 17 ++- bin/thirdparty/.gitignore | 2 - misc/scripts/black_format.sh | 26 ----- misc/scripts/clang_format.sh | 53 --------- misc/scripts/copyright_headers.py | 53 ++++----- misc/scripts/file_format.py | 50 ++++++++ misc/scripts/file_format.sh | 91 --------------- misc/scripts/gitignore_check.sh | 28 +++++ misc/scripts/header_guards.py | 87 ++++++++++++++ misc/scripts/package_release.sh | 2 +- misc/scripts/purge_cache.py | 47 ++++++++ pyproject.toml | 107 ++++++++++++++++++ src/WebRTCLibDataChannel.hpp | 5 +- src/WebRTCLibPeerConnection.hpp | 5 +- src/net/WebRTCDataChannelNative.hpp | 5 +- src/net/WebRTCPeerConnectionNative.hpp | 5 +- 22 files changed, 531 insertions(+), 274 deletions(-) create mode 100644 .github/actions/godot-cache-restore/action.yml create mode 100644 .github/actions/godot-cache-save/action.yml delete mode 100644 .github/actions/godot-cache/action.yml create mode 100644 .pre-commit-config.yaml delete mode 100644 bin/thirdparty/.gitignore delete mode 100755 misc/scripts/black_format.sh delete mode 100755 misc/scripts/clang_format.sh create mode 100755 misc/scripts/file_format.py delete mode 100755 misc/scripts/file_format.sh create mode 100755 misc/scripts/gitignore_check.sh create mode 100755 misc/scripts/header_guards.py create mode 100755 misc/scripts/purge_cache.py create mode 100644 pyproject.toml diff --git a/.github/actions/godot-cache-restore/action.yml b/.github/actions/godot-cache-restore/action.yml new file mode 100644 index 0000000..5d5b9b8 --- /dev/null +++ b/.github/actions/godot-cache-restore/action.yml @@ -0,0 +1,39 @@ +name: Restore Godot build cache +description: Restore Godot build cache. +inputs: + cache-name: + description: The cache base name (job name by default). + default: ${{ github.job }} + scons-cache: + description: The SCons cache path. + default: ${{ github.workspace }}/.scons_cache/ + +runs: + using: composite + steps: + - name: Restore default cache + uses: actions/cache/restore@v5 + id: cache-ping + with: + path: ${{ inputs.scons-cache }} + key: ${{ inputs.cache-name }}|${{ github.event.repository.default_branch }}|${{ github.sha }} + restore-keys: ${{ inputs.cache-name }}|${{ github.event.repository.default_branch }} + + - name: Log default cache files + if: steps.cache-ping.outputs.cache-matched-key && github.ref_name != github.event.repository.default_branch + shell: sh + run: find "${{ inputs.scons-cache }}" >> redundant.txt + + # This is done after pulling the default cache so that PRs can integrate any potential changes + # from the default branch without conflicting with whatever local changes were already made. + - name: Restore local cache + uses: actions/cache/restore@v5 + if: github.ref_name != github.event.repository.default_branch + with: + path: ${{ inputs.scons-cache }} + key: ${{ inputs.cache-name }}|${{ github.ref_name }}|${{ github.sha }} + restore-keys: ${{ inputs.cache-name }}|${{ github.ref_name }} + + - name: Store unix timestamp + shell: sh + run: echo "CACHE_TIMESTAMP=$(date +%s)" >> $GITHUB_ENV diff --git a/.github/actions/godot-cache-save/action.yml b/.github/actions/godot-cache-save/action.yml new file mode 100644 index 0000000..4cb96fe --- /dev/null +++ b/.github/actions/godot-cache-save/action.yml @@ -0,0 +1,22 @@ +name: Save Godot build cache +description: Save Godot build cache. +inputs: + cache-name: + description: The cache base name (job name by default). + default: ${{ github.job }} + scons-cache: + description: The SCons cache path. + default: ${{ github.workspace }}/.scons_cache/ + +runs: + using: composite + steps: + - name: Purge files before timestamp + shell: sh + run: misc/scripts/purge_cache.py ${{ env.CACHE_TIMESTAMP }} "${{ inputs.scons-cache }}" + + - name: Save SCons cache directory + uses: actions/cache/save@v5 + with: + path: ${{ inputs.scons-cache }} + key: ${{ inputs.cache-name }}|${{ github.ref_name }}|${{ github.sha }} diff --git a/.github/actions/godot-cache/action.yml b/.github/actions/godot-cache/action.yml deleted file mode 100644 index e54e606..0000000 --- a/.github/actions/godot-cache/action.yml +++ /dev/null @@ -1,22 +0,0 @@ -name: Setup Godot build cache -description: Setup Godot build cache. -inputs: - cache-name: - description: The cache base name (job name by default). - default: "${{github.job}}" - scons-cache: - description: The scons cache path. - default: "${{github.workspace}}/.scons-cache/" -runs: - using: "composite" - steps: - # Upload cache on completion and check it out now - - name: Load .scons_cache directory - uses: actions/cache@v4 - with: - path: ${{inputs.scons-cache}} - key: ${{inputs.cache-name}}-${{env.GODOT_BASE_BRANCH}}-${{github.ref}}-${{github.sha}} - restore-keys: | - ${{inputs.cache-name}}-${{env.GODOT_BASE_BRANCH}}-${{github.ref}}-${{github.sha}} - ${{inputs.cache-name}}-${{env.GODOT_BASE_BRANCH}}-${{github.ref}} - ${{inputs.cache-name}}-${{env.GODOT_BASE_BRANCH}} diff --git a/.github/workflows/build_release.yml b/.github/workflows/build_release.yml index 2bb9e6e..9adba11 100644 --- a/.github/workflows/build_release.yml +++ b/.github/workflows/build_release.yml @@ -12,34 +12,24 @@ env: jobs: static-checks: name: 馃搳 Static Checks (clang-format, black format, file format) - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 + timeout-minutes: 30 steps: - name: Checkout uses: actions/checkout@v6 + with: + fetch-depth: 0 # Treeless clone. Slightly less performant than a shallow clone, but makes finding diffs instantaneous. + filter: tree:0 # See: https://github.blog/open-source/git/get-up-to-speed-with-partial-clone-and-shallow-clone/ - - name: Install dependencies - run: | - # Add clang repository (so we have clang-format-14) - wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add - - sudo apt-add-repository "deb http://apt.llvm.org/focal/ llvm-toolchain-focal-14 main" - sudo apt-get update - # Install required deps - sudo apt-get install -qq dos2unix moreutils recode clang-format-14 - sudo update-alternatives --remove-all clang-format - sudo update-alternatives --install /usr/bin/clang-format clang-format /usr/bin/clang-format-14 100 - sudo pip3 install black==22.3.0 pygments - - - name: File formatting checks (file_format.sh) - run: | - bash ./misc/scripts/file_format.sh - - - name: Style checks via clang-format (clang_format.sh) + # This needs to happen before Python and npm execution; it must happen before any extra files are written. + - name: .gitignore checks (gitignore_check.sh) run: | - bash ./misc/scripts/clang_format.sh + bash ./misc/scripts/gitignore_check.sh - - name: Python style checks via black (black_format.sh) - run: | - bash ./misc/scripts/black_format.sh + - name: Style checks via prek + uses: j178/prek-action@v2 + with: + extra-args: "-a" build: runs-on: ${{ matrix.os }} @@ -148,10 +138,11 @@ jobs: with: submodules: recursive - - name: Setup Godot build cache - uses: ./.github/actions/godot-cache + - name: Restore Godot build cache + uses: ./.github/actions/godot-cache-restore with: cache-name: ${{ matrix.cache-name }} + scons-cache: ${{ env.SCONS_CACHE }} continue-on-error: true - name: Setup Windows MinGW toolchain cache @@ -253,6 +244,13 @@ jobs: run: | scons target=release generate_bindings=yes ${{ matrix.gdnative_flags }} godot_version=3 + - name: Save Godot build cache + uses: ./.github/actions/godot-cache-save + with: + cache-name: ${{ matrix.cache-name }} + scons-cache: ${{ env.SCONS_CACHE }} + continue-on-error: true + - uses: actions/upload-artifact@v7 with: name: ${{ github.job }}-${{ matrix.platform }}-${{ matrix.arch }} diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..e74861a --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,91 @@ +default_language_version: + python: python3 + +exclude: | + (?x)^( + .*thirdparty/.*| + .*misc/patches/.*| + )$ + +repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v6.0.0 + hooks: + - id: check-executables-have-shebangs + - id: check-shebang-scripts-are-executable + exclude: (SConstruct|SCsub)$ # SCons files use shebangs for syntax highlighting only. + + - repo: https://github.com/pre-commit/mirrors-clang-format + rev: v22.1.5 + hooks: + - id: clang-format + files: \.(c|h|cpp|hpp|cc|hh|cxx|hxx|m|mm|inc|java)$ + types_or: [text] + - id: clang-format + name: clang-format-glsl + files: \.glsl$ + types_or: [text] + args: [-style=file:misc/utility/clang_format_glsl.yml] + + - repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.15.20 + hooks: + - id: ruff-check + args: [--color=always] + files: (\.py|SConstruct|SCsub)$ + types_or: [text] + - id: ruff-format + args: [--color=always] + files: (\.py|SConstruct|SCsub)$ + types_or: [text] + + - repo: https://github.com/pre-commit/mirrors-mypy + rev: v1.19.1 + hooks: + - id: mypy + files: \.py$ + types_or: [text] + + - repo: https://github.com/codespell-project/codespell + rev: v2.4.2 + hooks: + - id: codespell + additional_dependencies: [tomli] + + - repo: local + hooks: + - id: header-guards + name: header-guards + language: python + entry: python misc/scripts/header_guards.py + files: \.(h|hpp|hh|hxx)$ + + - id: file-format + name: file-format + language: python + entry: python misc/scripts/file_format.py + types_or: [text] + exclude: | + (?x)^( + .*\.test\.txt| + .*\.svg| + .*\.patch| + .*\.out| + modules/gdscript/tests/scripts/parser/features/mixed_indentation_on_blank_lines\.gd| + modules/gdscript/tests/scripts/parser/warnings/empty_file_newline_comment\.norun\.gd| + modules/gdscript/tests/scripts/parser/warnings/empty_file_newline\.norun\.gd| + tests/data/.*\.bin + )$ + +# +# End of upstream Godot pre-commit hooks. +# +# Keep this separation to let downstream forks add their own hooks to this file, +# without running into merge conflicts when rebasing on latest upstream. +# +# Start of downstream pre-commit hooks. +# +# This is still the "repo: local" scope, so new local hooks can be defined directly at this indentation: +# - id: new-local-hook +# To add external repo hooks, bring the indentation back to: +# - repo: my-remote-hook diff --git a/README.md b/README.md index b10db0b..c34aa37 100644 --- a/README.md +++ b/README.md @@ -51,4 +51,4 @@ You simply need to copy that folder to the root folder of your project. Note tha ### License -The `webrtc-native` plugin is licensed under the MIT license (see [LICENSE](https://github.com/godotengine/webrtc-native/blob/master/LICENSE)), while `libdatachannel` and its dependencies are licensed under other permissive open source licences. Please see [`thirdparty/README.md`](thirdparty/README.md) for more informations. +The `webrtc-native` plugin is licensed under the MIT license (see [LICENSE](https://github.com/godotengine/webrtc-native/blob/master/LICENSE)), while `libdatachannel` and its dependencies are licensed under other permissive open source licenses. Please see [`thirdparty/README.md`](thirdparty/README.md) for more information. diff --git a/SConstruct b/SConstruct index 2932151..cd8c4f1 100644 --- a/SConstruct +++ b/SConstruct @@ -1,7 +1,8 @@ #!python +# ruff: noqa: F821 -import os, sys, platform, json, subprocess -import SCons +import os +import sys def add_sources(sources, dirpath, extension): @@ -46,7 +47,7 @@ if "macos_deployment_target" not in ARGUMENTS: ARGUMENTS["macos_deployment_target"] = "11.0" if "android_api_level" not in ARGUMENTS: ARGUMENTS["android_api_level"] = "28" -# Godot CPP (4.3+) default API verison +# Godot CPP (4.3+) default API version if "api_version" not in ARGUMENTS: ARGUMENTS["api_version"] = "4.3" @@ -169,12 +170,10 @@ else: env.Append(CPPPATH=["src/"]) env.Append(CPPDEFINES=["RTC_STATIC"]) sources = [] -sources.append( - [ - "src/WebRTCLibDataChannel.cpp", - "src/WebRTCLibPeerConnection.cpp", - ] -) +sources.append([ + "src/WebRTCLibDataChannel.cpp", + "src/WebRTCLibPeerConnection.cpp", +]) if env["godot_version"] == "3": env.Append(CPPDEFINES=["GDNATIVE_WEBRTC"]) sources.append("src/init_gdnative.cpp") diff --git a/bin/thirdparty/.gitignore b/bin/thirdparty/.gitignore deleted file mode 100644 index d6b7ef3..0000000 --- a/bin/thirdparty/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -* -!.gitignore diff --git a/misc/scripts/black_format.sh b/misc/scripts/black_format.sh deleted file mode 100755 index 3a64284..0000000 --- a/misc/scripts/black_format.sh +++ /dev/null @@ -1,26 +0,0 @@ -#!/usr/bin/env bash - -# This script runs black on all Python files in the repo. - -set -uo pipefail - -# Apply black. -echo -e "Formatting Python files..." -PY_FILES=$(git ls-files -- '*SConstruct' '*SCsub' '*.py' ':!:.git/*' ':!:thirdparty/*') -black -l 120 $PY_FILES - -diff=$(git diff --color) - -# If no diff has been generated all is OK, clean up, and exit. -if [ -z "$diff" ] ; then - printf "\e[1;32m*** Files in this commit comply with the black style rules.\e[0m\n" - exit 0 -fi - -# A diff has been created, notify the user, clean up, and exit. -printf "\n\e[1;33m*** The following changes must be made to comply with the formatting rules:\e[0m\n\n" -# Perl commands replace trailing spaces with `路` and tabs with ``. -printf "$diff\n" | perl -pe 's/(.*[^ ])( +)(\e\[m)$/my $spaces="路" x length($2); sprintf("$1$spaces$3")/ge' | perl -pe 's/(.*[^\t])(\t+)(\e\[m)$/my $tabs="" x length($2); sprintf("$1$tabs$3")/ge' - -printf "\n\e[1;91m*** Please fix your commit(s) with 'git commit --amend' or 'git rebase -i '\e[0m\n" -exit 1 diff --git a/misc/scripts/clang_format.sh b/misc/scripts/clang_format.sh deleted file mode 100755 index 74a8e1a..0000000 --- a/misc/scripts/clang_format.sh +++ /dev/null @@ -1,53 +0,0 @@ -#!/usr/bin/env bash - -# This script runs clang-format and fixes copyright headers on all relevant files in the repo. -# This is the primary script responsible for fixing style violations. - -set -uo pipefail - -if [ $# -eq 0 ]; then - # Loop through all code files tracked by Git. - files=$(git ls-files -- '*.c' '*.h' '*.cpp' '*.hpp' '*.cc' '*.hh' '*.cxx' '*.m' '*.mm' '*.inc' '*.java' '*.glsl' \ - ':!:.git/*' ':!:thirdparty/*' ':!:*/thirdparty/*' ':!:platform/android/java/lib/src/com/google/*' \ - ':!:*-so_wrap.*' ':!:tests/python_build/*') -else - # $1 should be a file listing file paths to process. Used in CI. - files=$(cat "$1" | grep -v "thirdparty/" | grep -E "\.(c|h|cpp|hpp|cc|hh|cxx|m|mm|inc|java|glsl)$" | grep -v "platform/android/java/lib/src/com/google/" | grep -v "\-so_wrap\." | grep -v "tests/python_build/") -fi - -if [ ! -z "$files" ]; then - clang-format --Wno-error=unknown -i $files -fi - -# Fix copyright headers, but not all files get them. -for f in $files; do - if [[ "$f" == *"inc" ]]; then - continue - elif [[ "$f" == *"glsl" ]]; then - continue - elif [[ "$f" == "platform/android/java/lib/src/org/godotengine/godot/gl/GLSurfaceView"* ]]; then - continue - elif [[ "$f" == "platform/android/java/lib/src/org/godotengine/godot/gl/EGLLogWrapper"* ]]; then - continue - elif [[ "$f" == "platform/android/java/lib/src/org/godotengine/godot/utils/ProcessPhoenix"* ]]; then - continue - fi - - python misc/scripts/copyright_headers.py "$f" -done - -diff=$(git diff --color) - -# If no diff has been generated all is OK, clean up, and exit. -if [ -z "$diff" ] ; then - printf "\e[1;32m*** Files in this commit comply with the clang-format style rules.\e[0m\n" - exit 0 -fi - -# A diff has been created, notify the user, clean up, and exit. -printf "\n\e[1;33m*** The following changes must be made to comply with the formatting rules:\e[0m\n\n" -# Perl commands replace trailing spaces with `路` and tabs with ``. -printf "$diff\n" | perl -pe 's/(.*[^ ])( +)(\e\[m)$/my $spaces="路" x length($2); sprintf("$1$spaces$3")/ge' | perl -pe 's/(.*[^\t])(\t+)(\e\[m)$/my $tabs="" x length($2); sprintf("$1$tabs$3")/ge' - -printf "\n\e[1;91m*** Please fix your commit(s) with 'git commit --amend' or 'git rebase -i '\e[0m\n" -exit 1 diff --git a/misc/scripts/copyright_headers.py b/misc/scripts/copyright_headers.py index a5e2f0c..f95bc58 100755 --- a/misc/scripts/copyright_headers.py +++ b/misc/scripts/copyright_headers.py @@ -4,35 +4,30 @@ import sys header = """\ -/**************************************************************************/ -/* $filename */ -/**************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/**************************************************************************/ -/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ -/* */ -/* 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. */ -/**************************************************************************/ +/****************************************************************************/ +/* $filename */ +/****************************************************************************/ +/* Copyright (c) 2020-present Fabio Alessandrelli, Tim Erskine, Maffle LLC. */ +/* */ +/* 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. */ +/****************************************************************************/ """ fname = sys.argv[1] diff --git a/misc/scripts/file_format.py b/misc/scripts/file_format.py new file mode 100755 index 0000000..9906faf --- /dev/null +++ b/misc/scripts/file_format.py @@ -0,0 +1,50 @@ +#!/usr/bin/env python3 + +import sys + +if len(sys.argv) < 2: + print("Invalid usage of file_format.py, it should be called with a path to one or multiple files.") + sys.exit(1) + +BOM = b"\xef\xbb\xbf" + +changed = [] +invalid = [] + +for file in sys.argv[1:]: + try: + with open(file, "rt", encoding="utf-8") as f: + original = f.read() + except UnicodeDecodeError: + invalid.append(file) + continue + + if original == "": + continue + + EOL = "\r\n" if file.endswith((".csproj", ".sln", ".bat")) or file.startswith("misc/msvs") else "\n" + WANTS_BOM = file.endswith((".csproj", ".sln")) + + revamp = EOL.join([line.rstrip("\n\r\t ") for line in original.splitlines(True)]).rstrip(EOL) + EOL + + new_raw = revamp.encode(encoding="utf-8") + if not WANTS_BOM and new_raw.startswith(BOM): + new_raw = new_raw[len(BOM) :] + elif WANTS_BOM and not new_raw.startswith(BOM): + new_raw = BOM + new_raw + + with open(file, "rb") as f: + old_raw = f.read() + + if old_raw != new_raw: + changed.append(file) + with open(file, "wb") as f: + f.write(new_raw) + +if changed: + for file in changed: + print(f"FIXED: {file}") +if invalid: + for file in invalid: + print(f"REQUIRES MANUAL CHANGES: {file}") + sys.exit(1) diff --git a/misc/scripts/file_format.sh b/misc/scripts/file_format.sh deleted file mode 100755 index f89e534..0000000 --- a/misc/scripts/file_format.sh +++ /dev/null @@ -1,91 +0,0 @@ -#!/usr/bin/env bash - -# This script ensures proper POSIX text file formatting and a few other things. -# This is supplementary to clang_format.sh and black_format.sh, but should be -# run before them. - -# We need dos2unix and isutf8. -if [ ! -x "$(command -v dos2unix)" -o ! -x "$(command -v isutf8)" ]; then - printf "Install 'dos2unix' and 'isutf8' (moreutils package) to use this script.\n" - exit 1 -fi - -set -uo pipefail - -if [ $# -eq 0 ]; then - # Loop through all code files tracked by Git. - mapfile -d '' files < <(git grep -zIl '') -else - # $1 should be a file listing file paths to process. Used in CI. - mapfile -d ' ' < <(cat "$1") -fi - -for f in "${files[@]}"; do - # Exclude some types of files. - if [[ "$f" == *"csproj" ]]; then - continue - elif [[ "$f" == *"sln" ]]; then - continue - elif [[ "$f" == *".bat" ]]; then - continue - elif [[ "$f" == *".out" ]]; then - # GDScript integration testing files. - continue - elif [[ "$f" == *"patch" ]]; then - continue - elif [[ "$f" == *"pot" ]]; then - continue - elif [[ "$f" == *"po" ]]; then - continue - elif [[ "$f" == "thirdparty/"* ]]; then - continue - elif [[ "$f" == "misc/patches/"* ]]; then - continue - elif [[ "$f" == *"/thirdparty/"* ]]; then - continue - elif [[ "$f" == "platform/android/java/lib/src/com/google"* ]]; then - continue - elif [[ "$f" == *"-so_wrap."* ]]; then - continue - elif [[ "$f" == *".test.txt" ]]; then - continue - fi - # Ensure that files are UTF-8 formatted. - isutf8 "$f" >> utf8-validation.txt 2>&1 - # Ensure that files have LF line endings and do not contain a BOM. - dos2unix "$f" 2> /dev/null - # Remove trailing space characters and ensures that files end - # with newline characters. -l option handles newlines conveniently. - perl -i -ple 's/\s*$//g' "$f" -done - -diff=$(git diff --color) - -if [ ! -s utf8-validation.txt ] && [ -z "$diff" ] ; then - # If no UTF-8 violations were collected (the file is empty) and - # no diff has been generated all is OK, clean up, and exit. - printf "\e[1;32m*** Files in this commit comply with the file formatting rules.\e[0m\n" - rm -f utf8-validation.txt - exit 0 -fi - -if [ -s utf8-validation.txt ] -then - # If the file has content and is not empty, violations - # detected, notify the user, clean up, and exit. - printf "\n\e[1;33m*** The following files contain invalid UTF-8 character sequences:\e[0m\n\n" - cat utf8-validation.txt -fi - -rm -f utf8-validation.txt - -if [ ! -z "$diff" ] -then - # A diff has been created, notify the user, clean up, and exit. - printf "\n\e[1;33m*** The following changes must be made to comply with the formatting rules:\e[0m\n\n" - # Perl commands replace trailing spaces with `路` and tabs with ``. - printf "$diff\n" | perl -pe 's/(.*[^ ])( +)(\e\[m)$/my $spaces="路" x length($2); sprintf("$1$spaces$3")/ge' | perl -pe 's/(.*[^\t])(\t+)(\e\[m)$/my $tabs="" x length($2); sprintf("$1$tabs$3")/ge' -fi - -printf "\n\e[1;91m*** Please fix your commit(s) with 'git commit --amend' or 'git rebase -i '\e[0m\n" -exit 1 diff --git a/misc/scripts/gitignore_check.sh b/misc/scripts/gitignore_check.sh new file mode 100755 index 0000000..d69c559 --- /dev/null +++ b/misc/scripts/gitignore_check.sh @@ -0,0 +1,28 @@ +#!/usr/bin/env sh + +set -uo pipefail +shopt -s globstar + +echo -e ".gitignore validation..." + +# Get a list of files that exist in the repo but are ignored. + +# The --verbose flag also includes files un-ignored via ! prefixes. +# We filter those out with a somewhat awkward `awk` directive. + # (Explanation: Split each line by : delimiters, + # see if the actual gitignore line shown in the third field starts with !, + # if it doesn't, print it.) + +# ignorecase for the sake of Windows users. + +output=$(git -c core.ignorecase=true check-ignore --verbose --no-index **/* | \ + awk -F ':' '{ if ($3 !~ /^!/) print $0 }') + +# Then we take this result and return success if it's empty. +if [ -z "$output" ]; then + exit 0 +else + # And print the result if it isn't. + echo "$output" + exit 1 +fi diff --git a/misc/scripts/header_guards.py b/misc/scripts/header_guards.py new file mode 100755 index 0000000..cd7ffe2 --- /dev/null +++ b/misc/scripts/header_guards.py @@ -0,0 +1,87 @@ +#!/usr/bin/env python3 + +import sys + +if len(sys.argv) < 2: + print("Invalid usage of header_guards.py, it should be called with a path to one or multiple files.") + sys.exit(1) + +changed = [] +invalid = [] + +for file in sys.argv[1:]: + header_start = -1 + header_end = -1 + + with open(file.strip(), "rt", encoding="utf-8", newline="\n") as f: + lines = f.readlines() + + for idx, line in enumerate(lines): + sline = line.strip() + + if header_start < 0: + if sline == "": # Skip empty lines at the top. + continue + + if sline.startswith("/**********"): # Godot header starts this way. + header_start = idx + else: + header_end = 0 # There is no Godot header. + break + else: + if not sline.startswith(("*", "/*")): # Not in the Godot header anymore. + header_end = idx + 1 # The guard should be two lines below the Godot header. + break + + if (HEADER_CHECK_OFFSET := header_end) < 0 or HEADER_CHECK_OFFSET >= len(lines): + invalid.append(file) + continue + + if lines[HEADER_CHECK_OFFSET].startswith("#pragma once"): + continue + + # Might be using legacy header guards. + HEADER_BEGIN_OFFSET = HEADER_CHECK_OFFSET + 1 + HEADER_END_OFFSET = len(lines) - 1 + + if HEADER_BEGIN_OFFSET >= HEADER_END_OFFSET: + invalid.append(file) + continue + + if ( + lines[HEADER_CHECK_OFFSET].startswith("#ifndef") + and lines[HEADER_BEGIN_OFFSET].startswith("#define") + and lines[HEADER_END_OFFSET].startswith("#endif") + ): + lines[HEADER_CHECK_OFFSET] = "#pragma once" + lines[HEADER_BEGIN_OFFSET] = "\n" + lines.pop() + with open(file, "wt", encoding="utf-8", newline="\n") as f: + f.writelines(lines) + changed.append(file) + continue + + # Verify `#pragma once` doesn't exist at invalid location. + misplaced = False + for line in lines: + if line.startswith("#pragma once"): + misplaced = True + break + + if misplaced: + invalid.append(file) + continue + + # Assume that we're simply missing a guard entirely. + lines.insert(HEADER_CHECK_OFFSET, "#pragma once\n\n") + with open(file, "wt", encoding="utf-8", newline="\n") as f: + f.writelines(lines) + changed.append(file) + +if changed: + for file in changed: + print(f"FIXED: {file}") +if invalid: + for file in invalid: + print(f"REQUIRES MANUAL CHANGES: {file}") + sys.exit(1) diff --git a/misc/scripts/package_release.sh b/misc/scripts/package_release.sh index c3cf553..42fc798 100755 --- a/misc/scripts/package_release.sh +++ b/misc/scripts/package_release.sh @@ -4,7 +4,7 @@ set -e set -x ARTIFACTS=${ARTIFACTS:-"artifacts"} -DESTINATION=${DESTIONATION:-"release"} +DESTINATION=${DESTINATION:-"release"} VERSION=${VERSION:-"extension"} TYPE=${TYPE:-"webrtc"} diff --git a/misc/scripts/purge_cache.py b/misc/scripts/purge_cache.py new file mode 100755 index 0000000..5f9b584 --- /dev/null +++ b/misc/scripts/purge_cache.py @@ -0,0 +1,47 @@ +#!/usr/bin/env python3 + +import argparse +import glob +import os + +if __name__ != "__main__": + raise ImportError(f"{__name__} should not be used as a module.") + + +def main(): + parser = argparse.ArgumentParser(description="Cleanup old cache files") + parser.add_argument("timestamp", type=int, help="Unix timestamp cutoff") + parser.add_argument("directory", help="Path to cache directory") + args = parser.parse_args() + + ret = 0 + + # TODO: Convert to non-hardcoded path + if os.path.exists("redundant.txt"): + with open("redundant.txt") as redundant: + for item in map(str.strip, redundant): + if os.path.isfile(item): + try: + os.remove(item) + except OSError: + print(f'Failed to handle "{item}"; skipping.') + ret += 1 + + for file in glob.glob(os.path.join(args.directory, "*", "*")): + try: + if os.path.getatime(file) < args.timestamp: + os.remove(file) + except OSError: + print(f'Failed to handle "{file}"; skipping.') + ret += 1 + + return ret + + +try: + raise SystemExit(main()) +except KeyboardInterrupt: + import signal + + signal.signal(signal.SIGINT, signal.SIG_DFL) + os.kill(os.getpid(), signal.SIGINT) diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..6b50797 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,107 @@ +[tool.mypy] +disallow_any_generics = true +explicit_package_bases = true +ignore_missing_imports = true +namespace_packages = true +no_implicit_optional = true +pretty = true +show_column_numbers = true +warn_redundant_casts = true +warn_return_any = true +warn_unreachable = true +exclude = ["thirdparty/"] +python_version = "3.9" + +[tool.ruff] +extend-exclude = ["thirdparty"] +extend-include = ["*SConstruct", "*SCsub"] +target-version = "py39" +line-length = 120 +preview = true +fix = true + +[tool.ruff.lint] +# NOTE: Starting with `0.15.2`, ruff uses a SIGNIFICANTLY expanded set of default rules for +# preview builds. While expanding into these new rulesets is something we're interested in, +# we'll adopt them gradually, depending on our needs. As such, our base `select` utilizes the +# legacy defaults. +select = ["E4", "E7", "E9", "F"] +extend-select = [ + "FA", # flake8-future-annotations. + "I", # isort. + "UP006", # Use {to} instead of {from} for type annotation. + "UP007", # Use `X | Y` for type annotations. + "UP037", # Remove quotes from type annotation. +] +extend-safe-fixes = ["FA", "UP006", "UP007"] + +[tool.ruff.lint.per-file-ignores] +"{SConstruct,SCsub}" = [ + "E402", # Module level import not at top of file. + "F403", # Undefined local with import star. + "F405", # Undefined local with import star usage. +] + +[tool.ruff.lint.isort] +sections = { metadata = ["misc.utility.scons_hints"] } +section-order = [ + "future", + "metadata", + "standard-library", + "third-party", + "first-party", + "local-folder", +] + +[tool.codespell] +enable-colors = true +write-changes = true +check-hidden = true +quiet-level = 3 +builtin = ["clear", "rare", "en-GB_to_en-US"] +skip = [ + ".mailmap", + "*.desktop", + "*.gitignore", + "*.po", + "*.pot", + "*.rc", + "AUTHORS.md", + "COPYRIGHT.txt", + "core/input/gamecontrollerdb.txt", + "core/string/locales.h", + "DONORS.md", + "editor/import/unicode_ranges.inc", + "editor/project_converter_3_to_4.cpp", + "platform/android/java/lib/src/main/java/com/*", + "platform/web/package-lock.json", +] +ignore-words-list = [ + "breaked", + "cancelled", + "checkin", + "colour", + "curvelinear", + "doubleclick", + "expct", + "findn", + "gird", + "hel", + "inout", + "labelin", + "lod", + "masia", + "mis", + "nd", + "numer", + "ot", + "outin", + "parm", + "pEvent", + "requestor", + "streamin", + "te", + "textin", + "thirdparty", + "vai", +] diff --git a/src/WebRTCLibDataChannel.hpp b/src/WebRTCLibDataChannel.hpp index 3524e02..7d23246 100644 --- a/src/WebRTCLibDataChannel.hpp +++ b/src/WebRTCLibDataChannel.hpp @@ -28,8 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /**************************************************************************/ -#ifndef WEBRTC_DATA_CHANNEL_H -#define WEBRTC_DATA_CHANNEL_H +#pragma once #ifdef GDNATIVE_WEBRTC #include // Godot.hpp must go first, or windows builds breaks @@ -110,5 +109,3 @@ class WebRTCLibDataChannel : public godot::WebRTCDataChannelExtension { }; } // namespace godot_webrtc - -#endif // WEBRTC_DATA_CHANNEL_H diff --git a/src/WebRTCLibPeerConnection.hpp b/src/WebRTCLibPeerConnection.hpp index c2de7e9..fa0037d 100644 --- a/src/WebRTCLibPeerConnection.hpp +++ b/src/WebRTCLibPeerConnection.hpp @@ -28,8 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /**************************************************************************/ -#ifndef WEBRTC_PEER_H -#define WEBRTC_PEER_H +#pragma once #ifdef GDNATIVE_WEBRTC #include // Godot.hpp must go first, or windows builds breaks @@ -137,5 +136,3 @@ class WebRTCLibPeerConnection : public godot::WebRTCPeerConnectionExtension { }; } // namespace godot_webrtc - -#endif // WEBRTC_PEER_H diff --git a/src/net/WebRTCDataChannelNative.hpp b/src/net/WebRTCDataChannelNative.hpp index e595311..bf11419 100644 --- a/src/net/WebRTCDataChannelNative.hpp +++ b/src/net/WebRTCDataChannelNative.hpp @@ -28,8 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /**************************************************************************/ -#ifndef WEBRTC_DATA_CHANNEL_NATIVE -#define WEBRTC_DATA_CHANNEL_NATIVE +#pragma once #include #include @@ -139,5 +138,3 @@ class WebRTCDataChannelNative : public godot::WebRTCDataChannelGDNative { }; }; // namespace godot - -#endif // WEBRTC_DATA_CHANNEL_NATIVE diff --git a/src/net/WebRTCPeerConnectionNative.hpp b/src/net/WebRTCPeerConnectionNative.hpp index d62497a..0d618f5 100644 --- a/src/net/WebRTCPeerConnectionNative.hpp +++ b/src/net/WebRTCPeerConnectionNative.hpp @@ -28,8 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /**************************************************************************/ -#ifndef WEBRTC_PEER_NATIVE -#define WEBRTC_PEER_NATIVE +#pragma once #include #include @@ -113,5 +112,3 @@ class WebRTCPeerConnectionNative : public godot::WebRTCPeerConnectionGDNative { }; }; // namespace godot - -#endif // WEBRTC_PEER_NATIVE