#!/usr/bin/env bash
# Determine CODEOWNERS of the files given in argument
# For a given commit range:
# git diff --name-only -z COMMIT1 COMMIT2 | xargs -0 dev/tools/check-owners.sh [opts]
# NB: gitignore files will be messed up if you interrupt the script.
# You should be able to just move the .gitignore.bak files back manually.
usage() {
{ echo "usage: $0 [--show-patterns] [--owner OWNER] [FILE]..."
echo " --show-patterns: instead of printing file names print the matching patterns (more compact)"
echo " --owner: show only files/patterns owned by OWNER (use Nobody to see only non-owned files)"
} >&2
}
case "$1" in
"--help"|"-h")
usage
if [ $# = 1 ]; then exit 0; else exit 1; fi
esac
if ! [ -e .github/CODEOWNERS ]; then
>&2 echo "No CODEOWNERS set up or calling from wrong directory."
exit 1
fi
files=()
show_patterns=false
target_owner=""
while [[ "$#" -gt 0 ]]; do
case "$1" in
"--show-patterns")
show_patterns=true
shift;;
"--owner")
if [[ "$#" = 1 ]]; then
>&2 echo "Missing argument to --owner"
usage
exit 1
elif [[ "$target_owner" != "" ]]; then
>&2 echo "Only one --owner allowed"
usage
exit 1
fi
target_owner="$2"
shift 2;;
*)
files+=("$@")
break;;
esac
done
# CODEOWNERS uses .gitignore patterns so we want to use git to parse it
# The only available tool for that is git check-ignore
# However it provides no way to use alternate .gitignore files
# so we rename them temporarily
find . -name .gitignore -print0 | while IFS= read -r -d '' f; do
if [ -e "$f.bak" ]; then
>&2 echo "$f.bak exists!"
exit 1
else
mv "$f" "$f.bak"
fi
done
# CODEOWNERS is not quite .gitignore patterns:
# after the pattern is the owner (space separated)
# git would interpret that as a big pattern containing spaces
# so we create a valid .gitignore by removing all but the first field
while read -r pat _; do
printf '%s\n' "$pat" >> .gitignore
done < .github/CODEOWNERS
# associative array [file => owner]
declare -A owners
for f in "${files[@]}"; do
data=$(git check-ignore --verbose --no-index "./$f")
code=$?
if [[ "$code" = 1 ]] || ! [[ "$data" =~ .gitignore:.* ]] ; then
# no match, or match from non tracked gitignore (eg global gitignore)
if [ "$target_owner" != "" ] && [ "$target_owner" != Nobody ] ; then
owner=""
else
owner="Nobody"
pat="$f" # no patterns for unowned files
fi
else
# data looks like [.gitignore:$line:$pattern $file]
# extract the line to look it up in CODEOWNERS
data=${data#'.gitignore:'}
line=${data%%:*}
# NB: supports multiple owners
# Does not support secondary owners declared in comment
read -r pat fowners < <(sed "${line}q;d" .github/CODEOWNERS)
owner=""
if [ "$target_owner" != "" ]; then
for o in $fowners; do # do not quote: multiple owners possible
if [ "$o" = "$target_owner" ]; then
owner="$o"
fi
done
else
owner="$fowners"
fi
fi
if [ "$owner" != "" ]; then
if $show_patterns; then
owners[$pat]="$owner"
else
owners[$f]="$owner"
fi
fi
done
for f in "${!owners[@]}"; do
printf '%s: %s\n' "$f" "${owners[$f]}"
done | sort -k 2 -k 1 # group by owner
# restore gitignore files
rm .gitignore
find . -name .gitignore.bak -print0 | while IFS= read -r -d '' f; do
base=${f%.bak}
if [ -e "$base" ]; then
>&2 echo "$base exists!"
else
mv "$f" "$base"
fi
done
¤ Dauer der Verarbeitung: 0.15 Sekunden
(vorverarbeitet)
¤
|
Haftungshinweis
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.
|