mirror of
https://github.com/alibaba/open-code-review.git
synced 2026-10-02 09:24:52 +08:00
The license gate listed only go/sh/js/mjs/ts/tsx, so eight Python and six CSS source files carried no SPDX header while still passing CI. Backfill those headers, and cover kt/kts before any Kotlin code lands.
125 lines
3.1 KiB
Bash
Executable File
125 lines
3.1 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
|
|
# SPDX-License-Identifier: Apache-2.0
|
|
# Copyright 2026 alibaba/open-code-review Contributors
|
|
|
|
set -euo pipefail
|
|
|
|
REPO_ROOT="$(git rev-parse --show-toplevel)"
|
|
cd "$REPO_ROOT"
|
|
|
|
MIN_YEAR=2026
|
|
SPDX_REGEX="SPDX-License-Identifier: Apache-2.0"
|
|
COPYRIGHT_REGEX="Copyright [0-9]{4} alibaba/open-code-review Contributors"
|
|
|
|
SLASH_HEADER='// SPDX-License-Identifier: Apache-2.0
|
|
// Copyright 2026 alibaba/open-code-review Contributors'
|
|
|
|
HASH_HEADER='# SPDX-License-Identifier: Apache-2.0
|
|
# Copyright 2026 alibaba/open-code-review Contributors'
|
|
|
|
# CSS has no // line comment — that is SCSS — so a block is the only option. The
|
|
# lines inside carry no prefix, matching the {{/* */}} header already in
|
|
# internal/viewer/templates/app-header.html.
|
|
BLOCK_HEADER='/*
|
|
SPDX-License-Identifier: Apache-2.0
|
|
Copyright 2026 alibaba/open-code-review Contributors
|
|
*/'
|
|
|
|
# Grouped by the comment syntax add_header gives each below: // for Go, the
|
|
# JS/TS family and Kotlin, # for shell and Python, /* */ for CSS. Extensions
|
|
# whose comment cannot simply be prepended stay out — .html would need its
|
|
# DOCTYPE kept on the first line, so it is not covered yet.
|
|
LICENSE_EXTS=(go js mjs ts tsx kt kts sh py css)
|
|
|
|
IGNORED_PATHS=(
|
|
"vendor/"
|
|
"dist/"
|
|
"node_modules/"
|
|
"testdata/"
|
|
)
|
|
|
|
is_ignored() {
|
|
local file="$1"
|
|
for ignore in "${IGNORED_PATHS[@]}"; do
|
|
if [[ "$file" == */"$ignore"* ]] || [[ "$file" == "$ignore"* ]]; then
|
|
return 0
|
|
fi
|
|
done
|
|
return 1
|
|
}
|
|
|
|
has_header() {
|
|
local header
|
|
header="$(head -20 "$1")"
|
|
# Here-string, not `echo |`: grep -q exits on the first match, so echo can die of
|
|
# SIGPIPE (141) and pipefail turns that into a false "no header", which makes
|
|
# add_header prepend a second copyright block to a file that already has one.
|
|
grep -qF "$SPDX_REGEX" <<<"$header" && grep -qE "$COPYRIGHT_REGEX" <<<"$header"
|
|
}
|
|
|
|
add_header() {
|
|
local file="$1"
|
|
local header="$2"
|
|
local tmp
|
|
tmp=$(mktemp)
|
|
if stat -f '%Lp' "$file" >/dev/null 2>&1; then
|
|
chmod "$(stat -f '%Lp' "$file")" "$tmp"
|
|
else
|
|
chmod "$(stat -c '%a' "$file")" "$tmp"
|
|
fi
|
|
|
|
local first_line
|
|
first_line="$(head -1 "$file")"
|
|
|
|
if [[ "$first_line" =~ ^//go:build ]]; then
|
|
echo "$first_line" > "$tmp"
|
|
echo "" >> "$tmp"
|
|
echo "$header" >> "$tmp"
|
|
echo "" >> "$tmp"
|
|
tail -n +2 "$file" >> "$tmp"
|
|
elif [[ "$first_line" =~ ^#! ]]; then
|
|
echo "$first_line" > "$tmp"
|
|
echo "" >> "$tmp"
|
|
echo "$header" >> "$tmp"
|
|
echo "" >> "$tmp"
|
|
tail -n +2 "$file" >> "$tmp"
|
|
else
|
|
echo "$header" > "$tmp"
|
|
echo "" >> "$tmp"
|
|
cat "$file" >> "$tmp"
|
|
fi
|
|
|
|
mv "$tmp" "$file"
|
|
}
|
|
|
|
ADDED=0
|
|
|
|
while IFS= read -r file; do
|
|
[ -z "$file" ] && continue
|
|
is_ignored "$file" && continue
|
|
|
|
ext="${file##*.}"
|
|
match=false
|
|
for e in "${LICENSE_EXTS[@]}"; do
|
|
if [[ "$ext" == "$e" ]]; then
|
|
match=true
|
|
break
|
|
fi
|
|
done
|
|
$match || continue
|
|
|
|
has_header "$file" && continue
|
|
|
|
case "$ext" in
|
|
sh | py) add_header "$file" "$HASH_HEADER" ;;
|
|
css) add_header "$file" "$BLOCK_HEADER" ;;
|
|
*) add_header "$file" "$SLASH_HEADER" ;;
|
|
esac
|
|
|
|
ADDED=$((ADDED + 1))
|
|
echo " Added: $file"
|
|
done < <(git ls-files)
|
|
|
|
echo "Done. Added license headers to $ADDED file(s)."
|