[license-header] refactor: excludes, updating, better logic (#2780)
All checks were successful
GitHub Actions [CI] Build succeeded

Rewrite of license-header.sh. Lots of new goodies:
- Fully POSIX compliant
- supports dash arguments (-u/--update, -c/--commit, -uc for both)
- can update year or malformed headers in-place now
- accounts for shell scripts
- exclusion of external files (e.g. sse2neon, my CMake modules/scripts)
- better, more extensible logic all around

Reviewed-on: #2780
This commit is contained in:
crueter 2025-10-20 02:59:43 +02:00
parent df653d6ca4
commit d7cd7c6313
Signed by: crueter
GPG key ID: 425ACD2D4830EBC6
6 changed files with 195 additions and 139 deletions

View file

@ -1,47 +0,0 @@
#!/usr/bin/ruby
# frozen_string_literal: true
license_header = <<~EOF
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
EOF
print 'Getting branch changes...'
branch_name = `git rev-parse --abbrev-ref HEAD`.chomp
branch_commits = `git log #{branch_name} --not master --pretty=format:"%h"`.split("\n")
branch_commit_range = "#{branch_commits[-1]}^..#{branch_commits[0]}"
branch_changed_files = `git diff-tree --no-commit-id --name-only #{branch_commit_range} -r`.split("\n")
puts 'done'
print 'Checking files...'
issue_files = []
branch_changed_files.each do |file_name|
if file_name.end_with?('.cpp', '.h', '.kt', '.kts') and File.file?(file_name)
file_content = File.read(file_name)
if not file_content.start_with?(license_header)
issue_files.push(file_name)
end
end
end
puts 'done'
if issue_files.empty?
puts "\nAll changed files have correct headers"
exit 0
end
puts <<-EOF
The following #{issue_files.length} files have incorrect license headers:
#{issue_files.join("\n")}
The following license header should be added to the start of all offending files:
=== BEGIN ===
#{license_header}
=== END ===
If some of the code in this PR is not being contributed by the original author, the files which have been exclusively changed by that code can be ignored.
If this happens, this PR requirement can be bypassed once all other files are addressed.
EOF
exit 1

View file

@ -1,74 +1,152 @@
#!/bin/sh -e #!/bin/sh -e
HEADER="$(cat "$PWD/.ci/license/header.txt")" # SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
HEADER_HASH="$(cat "$PWD/.ci/license/header-hash.txt")" # SPDX-License-Identifier: GPL-3.0-or-later
echo "Getting branch changes" # specify full path if dupes may exist
EXCLUDE_FILES="CPM.cmake CPMUtil.cmake GetSCMRev.cmake sse2neon.h renderdoc_app.h tools/cpm externals/stb externals/glad externals/getopt externals/gamemode externals/FidelityFX-FSR externals/demangle externals/bc_decoder"
# BRANCH=`git rev-parse --abbrev-ref HEAD` # license header constants, please change when needed :))))
# COMMITS=`git log ${BRANCH} --not master --pretty=format:"%h"` YEAR=2025
# RANGE="${COMMITS[${#COMMITS[@]}-1]}^..${COMMITS[0]}" HOLDER="Eden Emulator Project"
# FILES=`git diff-tree --no-commit-id --name-only ${RANGE} -r` LICENSE="GPL-3.0-or-later"
BASE=`git merge-base master HEAD` usage() {
FILES=`git diff --name-only $BASE` cat << EOF
Usage: $0 [uc]
Compares the current HEAD to the master branch to check for license
header discrepancies. Each file changed in a branch MUST have a
license header, and this script attempts to enforce that.
#FILES=$(git diff --name-only master) Options:
-u, --update Fix license headers, if applicable;
if the license header exists but has the incorrect
year or is otherwise malformed, it will be fixed.
echo "Done" -c, --commit Commit changes to Git (requires --update)
Copyright $YEAR $HOLDER
Licensed under $LICENSE
The following files/directories are marked as external
and thus will not have license headers asserted:
EOF
for file in $EXCLUDE_FILES; do
echo "- $file"
done
exit 0
}
while true; do
case "$1" in
(-uc) UPDATE=true; COMMIT=true ;;
(-u|--update) UPDATE=true ;;
(-c|--commit) COMMIT=true ;;
("$0") break ;;
("") break ;;
(*) usage ;;
esac
shift
done
# human-readable header string
header() {
header_line1 "$1"
header_line2 "$1"
}
header_line1() {
echo "$1 SPDX-FileCopyrightText: Copyright $YEAR $HOLDER"
}
header_line2() {
echo "$1 SPDX-License-Identifier: $LICENSE"
}
# PCRE header string
pcre_header() {
begin="$1"
echo "(?s)$(header_line1 "$begin").*$(header_line2 "$begin")"
}
check_header() { check_header() {
CONTENT="`head -n3 < $1`" begin="$1"
case "$CONTENT" in file="$2"
"$HEADER"*) ;; content="$(head -n5 < "$2")"
*) BAD_FILES="$BAD_FILES $1" ;;
esac header="$(pcre_header "$begin")"
if ! echo "$content" | grep -Pzo "$header" > /dev/null; then
# SRC_FILES is Kotlin/C++
# OTHER_FILES is sh, CMake
case "$begin" in
"//")
SRC_FILES="$SRC_FILES $file"
;;
"#")
OTHER_FILES="$OTHER_FILES $file"
;;
esac
fi
} }
check_cmake_header() { BASE=$(git merge-base master HEAD)
CONTENT="`head -n3 < $1`" FILES=$(git diff --name-only "$BASE")
case "$CONTENT" in
"$HEADER_HASH"*) ;;
*)
BAD_CMAKE="$BAD_CMAKE $1" ;;
esac
}
for file in $FILES; do for file in $FILES; do
[ -f "$file" ] || continue [ -f "$file" ] || continue
if [ `basename -- "$file"` = "CMakeLists.txt" ]; then # skip files that are third party (crueter's CMake modules, sse2neon, etc)
check_cmake_header "$file" for pattern in $EXCLUDE_FILES; do
continue case "$file" in
fi *"$pattern"*)
excluded=true
continue
;;
*)
excluded=false
;;
esac
done
EXTENSION="${file##*.}" [ "$excluded" = "true" ] && continue
case "$EXTENSION" in
kts|kt|cpp|h) case "$file" in
check_header "$file" *.cmake|*.sh|CMakeLists.txt)
;; begin="#"
cmake) ;;
check_cmake_header "$file" *.kt*|*.cpp|*.h)
;; begin="//"
;;
*)
continue
;;
esac esac
check_header "$begin" "$file"
done done
if [ "$BAD_FILES" = "" ] && [ "$BAD_CMAKE" = "" ]; then if [ -z "$SRC_FILES" ] && [ -z "$OTHER_FILES" ]; then
echo echo "-- All good."
echo "All good."
exit exit
fi fi
if [ "$BAD_FILES" != "" ]; then echo
echo "The following source files have incorrect license headers:"
echo
for file in $BAD_FILES; do echo $file; done if [ "$SRC_FILES" != "" ]; then
echo "-- The following source files have incorrect license headers:"
HEADER=$(header "//")
for file in $SRC_FILES; do echo "-- * $file"; done
cat << EOF cat << EOF
The following license header should be added to the start of all offending SOURCE files: -- The following license header should be added to the start of these offending files:
=== BEGIN === === BEGIN ===
$HEADER $HEADER
@ -78,18 +156,19 @@ EOF
fi fi
if [ "$BAD_CMAKE" != "" ]; then if [ "$OTHER_FILES" != "" ]; then
echo "The following CMake files have incorrect license headers:" echo "-- The following CMake and shell scripts have incorrect license headers:"
echo
for file in $BAD_CMAKE; do echo $file; done HEADER=$(header "#")
for file in $OTHER_FILES; do echo "-- * $file"; done
cat << EOF cat << EOF
The following license header should be added to the start of all offending CMake files: -- The following license header should be added to the start of these offending files:
=== BEGIN === === BEGIN ===
$HEADER_HASH $HEADER
=== END === === END ===
EOF EOF
@ -97,50 +176,76 @@ EOF
fi fi
cat << EOF cat << EOF
If some of the code in this PR is not being contributed by the original author, If some of the code in this PR is not being contributed by the original author,
the files which have been exclusively changed by that code can be ignored. the files which have been exclusively changed by that code can be ignored.
If this happens, this PR requirement can be bypassed once all other files are addressed. If this happens, this PR requirement can be bypassed once all other files are addressed.
EOF EOF
if [ "$FIX" = "true" ]; then if [ "$UPDATE" = "true" ]; then
echo TMP_DIR=$(mktemp -d)
echo "FIX set to true. Fixing headers." echo "-- Fixing headers..."
echo
for file in $BAD_FILES; do for file in $SRC_FILES $OTHER_FILES; do
cat $file > $file.bak case $(basename -- "$file") in
*.cmake|CMakeLists.txt)
begin="#"
shell="false"
;;
*.sh)
begin="#"
shell=true
;;
*.kt*|*.cpp|*.h)
begin="//"
shell="false"
;;
esac
cat .ci/license/header.txt > $file # This is fun
echo >> $file match="$begin SPDX-FileCopyrightText.*$HOLDER"
cat $file.bak >> $file
rm $file.bak # basically if the copyright holder is already defined we can just replace the year
if head -n5 < "$file" | grep -e "$match" >/dev/null; then
replace=$(header_line1 "$begin")
sed "s|$match|$replace|" "$file" > "$file".bak
mv "$file".bak "$file"
else
header "$begin" > "$TMP_DIR"/header
git add $file if [ "$shell" = "true" ]; then
done # grab shebang
head -n1 "$file" > "$TMP_DIR/shebang"
echo >> "$TMP_DIR/shebang"
for file in $BAD_CMAKE; do # remove shebang
cat $file > $file.bak sed '1d' "$file" > "$file".bak
mv "$file".bak "$file"
cat .ci/license/header-hash.txt > $file # add to header
echo >> $file cat "$TMP_DIR"/shebang "$TMP_DIR"/header > "$TMP_DIR"/new-header
cat $file.bak >> $file mv "$TMP_DIR"/new-header "$TMP_DIR"/header
else
echo >> "$TMP_DIR/header"
fi
rm $file.bak cat "$TMP_DIR"/header "$file" > "$file".bak
mv "$file".bak "$file"
fi
git add $file [ "$shell" = "true" ] && chmod a+x "$file"
done [ "$COMMIT" = "true" ] && git add "$file"
echo "License headers fixed." done
if [ "$COMMIT" = "true" ]; then echo "-- Done"
echo
echo "COMMIT set to true. Committing changes."
echo
git commit -m "Fix license headers"
echo "Changes committed. You may now push."
fi
else
exit 1
fi fi
if [ "$COMMIT" = "true" ]; then
echo "-- Committing changes"
git commit -m "Fix license headers"
echo "-- Changes committed. You may now push."
fi
[ -d "$TMP_DIR" ] && rm -rf "$TMP_DIR"

View file

@ -1,2 +0,0 @@
# SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
# SPDX-License-Identifier: GPL-3.0-or-later

View file

@ -1,2 +0,0 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later

View file

@ -6,19 +6,21 @@ All commits must have proper license header accreditation.
You can easily add all necessary license headers by running: You can easily add all necessary license headers by running:
```sh ```sh
git fetch origin master:master git fetch origin master:master
FIX=true COMMIT=true .ci/license-header.sh .ci/license-header.sh -u -c
git push git push
``` ```
Alternatively, you may omit `COMMIT=true` and do an amend commit: Alternatively, you may omit `-c` and do an amend commit:
```sh ```sh
git fetch origin master:master git fetch origin master:master
FIX=true .ci/license-header.sh .ci/license-header.sh
git commit --amend -a --no-edit git commit --amend -a --no-edit
``` ```
If the work is licensed/vendored from other people or projects, you may omit the license headers. Additionally, if you wish to retain authorship over a piece of code, you may attribute it to yourself; however, the code may be changed at any given point and brought under the attribution of Eden. If the work is licensed/vendored from other people or projects, you may omit the license headers. Additionally, if you wish to retain authorship over a piece of code, you may attribute it to yourself; however, the code may be changed at any given point and brought under the attribution of Eden.
For more information on the license header script, run `.ci/license-header.sh -h`.
## Pull Requests ## Pull Requests
Pull requests are only to be merged by core developers when properly tested and discussions conclude on Discord or other communication channels. Labels are recommended but not required. However, all PRs MUST be namespaced and optionally typed: Pull requests are only to be merged by core developers when properly tested and discussions conclude on Discord or other communication channels. Labels are recommended but not required. However, all PRs MUST be namespaced and optionally typed:
``` ```

0
tools/cpm-fetch-all.sh Normal file → Executable file
View file