Newer
Older
#
# dim - drm inglorious maintainer script
#
# Copyright © 2012-2018 Intel Corporation
#
# 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 (including the next
# paragraph) 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.
#
# Authors:
# Daniel Vetter <daniel.vetter@ffwll.ch>
# Jani Nikula <jani.nikula@intel.com>
# User configuration. Global DIM_ prefixed uppercase variables. Set in
# environment or configuration file. See dimrc.sample for an example.
DIM_CACHE_DIR=${XDG_CACHE_HOME:-$HOME/.cache}/dim
DIM_CONF_DIR=${XDG_CONFIG_HOME:-$HOME/.config}/dim
# dim configuration file
if [[ -n $DIM_CONFIG ]] && [ -r $DIM_CONFIG ]; then
# shellcheck source=/dev/null
. $DIM_CONFIG
elif [ -r $DIM_CONF_DIR/dimrc ]; then
# shellcheck source=/dev/null
. $DIM_CONF_DIR/dimrc
# shellcheck source=/dev/null
. $HOME/.dimrc
fi
# prefix for repo directories
DIM_PREFIX=${DIM_PREFIX:-$HOME/linux}
# location of another dim setup used to speedup clones; default
# to something that doesn't exist so no cache is used
DIM_KERNEL_PREFIX=${DIM_KERNEL_REFERENCE:-/dev/fd/-1}
# main maintainer repo under $DIM_PREFIX
# mail user agent. must support a subset of mutt(1) command line options:
# usage: $DIM_MUA [-s subject] [-i file] [-c cc-addr] to-addr [...]
DIM_MUA=${DIM_MUA:-mutt}
# make options (not used for C=1)
DIM_MAKE_OPTIONS=${DIM_MAKE_OPTIONS:--j20}
Ander Conselvan de Oliveira
committed
# command to run after dim apply
DIM_POST_APPLY_ACTION=${DIM_POST_APPLY_ACTION:-}
# greetings pull request template
DIM_TEMPLATE_HELLO=${DIM_TEMPLATE_HELLO:-$HOME/.dim.template.hello}
# signature pull request template
DIM_TEMPLATE_SIGNATURE=${DIM_TEMPLATE_SIGNATURE:-$HOME/.dim.template.signature}
# GPG key id for signing tags. If unset, don't sign.
DIM_GPG_KEYID=${DIM_GPG_KEYID:+-u $DIM_GPG_KEYID}
# Internal configuration. Global dim_ prefixed variables.
dim=$(basename $0)
dim_timestamp="$(date --utc +%Yy-%mm-%dd-%Hh-%Mm-%Ss) UTC"
dim_fdo_cookie="--push-option fdo.pushedWithDim=this-was-pushed-with-dim-and-not-manually"
maintainer_tools_https=https://gitlab.freedesktop.org/drm/maintainer-tools.git
# Recipients for all dim based pull requests.
# Add To: lines to the end, Cc: lines in the beginning with -c.
dim_pull_request_recipients=(
-c "Jani Nikula <jani.nikula@linux.intel.com>"
-c "Joonas Lahtinen <joonas.lahtinen@linux.intel.com>"
-c "Tvrtko Ursulin <tvrtko.ursulin@linux.intel.com>"
-c "Rodrigo Vivi <rodrigo.vivi@intel.com>"
-c "Thomas Zimmermann <tzimmermann@suse.de>"
-c "Maarten Lankhorst <maarten.lankhorst@linux.intel.com>"
-c "Thomas Hellström <thomas.hellstrom@linux.intel.com>"
-c "Oded Gabbay <ogabbay@kernel.org>"
-c "Lucas De Marchi <lucas.demarchi@intel.com>"
-c "dri-devel@lists.freedesktop.org"
-c "intel-gfx@lists.freedesktop.org"
-c "dim-tools@lists.freedesktop.org"
"Dave Airlie <airlied@gmail.com>"
"Daniel Vetter <daniel.vetter@ffwll.ch>"
dim_integration_config=nightly.conf
dim_last_path_file=$DIM_CACHE_DIR/last-path
dim_extract_tags_marker="# *** extracted tags ***"
#
# Only function and alias definitions until the command line argument parsing
# and subcommand handling at the end.
#
function read_integration_config
{
# clear everything first to allow configuration reload
unset drm_tip_repos drm_tip_config
declare -g -A drm_tip_repos
declare -g -a drm_tip_config
if [ -r $DIM_PREFIX/drm-rerere/$dim_integration_config ]; then
# shellcheck source=/dev/null
source $DIM_PREFIX/drm-rerere/$dim_integration_config
if [[ "${#drm_tip_repos[@]}" = "0" ]] || [[ "${#drm_tip_config[@]}" = "0" ]]; then
echoerr "$dim_integration_config not set up correctly, please fix manually"
echoerr "$dim_integration_config is missing, please check your configuration and/or run dim setup"
fi
dim_branches=
for conf in "${drm_tip_config[@]}"; do
local repo branch override
if [[ $repo = drm-* ]] || [[ $branch = topic/* ]]; then
dim_branches="$dim_branches $branch"
fi
done
}
function warn_or_fail
{
if [[ $FORCE ]] ; then
echoerr "WARNING: $1, but continuing"
elif [[ $DRY ]] ; then
echoerr "WARNING: $1, but continuing dry-run"
echoerr "ERROR: $1, aborting"
function pause
{
read -rsp "Press any key to continue..." -n1 key2
echo
}
function ask_user
{
if [ $ASK_USER_ASSUME_YES -eq 1 ]; then
return 0
fi
read -n 1 -rsp "$prompt"
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
return 0
else
return 1
fi
}
#
# Variable naming convetion:
#
# repo:
# symbolic git repository name from $dim_integration_config
# remote:
# local remote name in the git repository for the current path
# branch:
# git branch name - dim assumes that the remote and local name match
# url:
# url to a repo, using ssh:// protocol
# git_url:
# url to a repo, but using anonymous git:// protocol
#
# The below functions map between these.
#
function url_to_repo # url [url ...]
{
local url
url=$1
for repo in "${!drm_tip_repos[@]}"; do
if [[ ${drm_tip_repos[$repo]} == *"$url"* ]]; then
echo $repo
break
fi
done
}
function url_to_remote # url [url ...]
local url remote
if [[ "$#" = "0" ]]; then
echoerr "url_to_remote without URLs"
return 1
for url; do
remote=$(git remote -v | grep -m 1 "$url/\? (" | cut -f 1)
if [[ -n "$remote" ]]; then
echo "$remote"
return 0
fi
done
echoerr "No git remote for any of the URLs $* found in $(pwd)"
url=$1
# default remote to the repo name, but fallback for when bootstrapping
# the environment: we may still not have drm-rerere to get the repo
# name. In that case, rely on the url
remote=$(url_to_repo "$url")
if [ -z "$remote" ]; then
remote=${url%.git}
remote=${remote##*/}
fi
if [ $ASK_USER_ASSUME_YES -ne 1 ]; then
read -r -i "$remote" -e -p "Enter a name to auto-add this remote, leave blank to abort: " remote
fi
if [[ -z "$remote" ]]; then
echoerr "Please set it up yourself using:"
echoerr " $ git remote add <name> $url"
echoerr "with a name of your choice."
git remote add $remote $url
echo $remote
return 0
function pick_protocol_url # (git|ssh|https|whatever) url [url ...]
{
local url protocol protocol_url
if [[ "$#" -lt "2" ]]; then
echoerr "pick_protocol_url without protocol or URLs"
return 1
fi
protocol=$1
shift
# Find the URL that has given protocol
for url; do
case $url in
${protocol}://*)
protocol_url=$url
break
;;
esac
done
if [[ -z "$protocol_url" ]]; then
echoerr "No $protocol URL in any of the URLs: $*"
return 1
fi
echo $protocol_url
}
function branch_to_remote # branch
{
repo=$(branch_to_repo $branch)
if [[ -z "$repo" ]] ; then
# fallback for special branches like rerere-cache
remote=$(git rev-parse --abbrev-ref --symbolic-full-name "$branch@{upstream}")
remote=${remote%%/*}
else
remote=$(repo_to_remote $repo)
fi
local repo url_list
repo=$1
url_list=${drm_tip_repos[$repo]}
if [[ -z "$url_list" ]]; then
echoerr "unknown repo $repo"
return 1
fi
url_to_remote $url_list
function branch_to_repo # branch
{
for conf in "${drm_tip_config[@]}"; do
local repo branch override
if [[ "$branch" == "$1" ]] ; then
echo $repo
fi
done
echo ""
}
function dim_version
{
local using
using="${BASH_SOURCE[0]}"
if [[ ! -e "$using" ]]; then
echoerr "could not figure out the version being used ($using)."
fi
if [[ ! -e "$DIM_PREFIX/maintainer-tools/.git" ]]; then
echoerr "could not find the upstream repo for $dim."
git --git-dir=$DIM_PREFIX/maintainer-tools/.git fetch -q
if ! git --git-dir=$DIM_PREFIX/maintainer-tools/.git show "@{upstream}:dim" |\
diff "$using" - >& /dev/null; then
echoerr "not running upstream version of the script."
function git_fetch_helper # remote
{
local remote
remote=$1
# old git versions returned 128 if there was nothing to fetch
if [[ $? -ne "128" ]] ; then
echoerr "Failed to fetch $remote"
return 1
fi
fi
}
function git_current_branch
{
git symbolic-ref -q --short HEAD
}
function git_is_current_branch # branch
{
test "$(git_current_branch)" = "$1"
function git_branch_exists # branch
{
if [[ "$(git branch --list $1)" == "" ]] ; then
false
else
true
fi
}
# $1: branch
# $2: upstream
function git_unmerged_tags
{
local branch upstream
branch=$1
upstream=$2
# assume branch based tag names, ensure space separated list
git log --decorate --pretty=%D "$branch@{upstream}" ^$upstream |\
grep -o "tag: $branch-[0-9-]\+" |\
sed -e "s/^tag: //" |\
tr "\n" " "
}
function git_committer_email
{
if ! committer_email=$(git config --get user.email) ; then
fi
echo $committer_email
}
function git_push
{
git push $dim_fdo_cookie $DRY_RUN "$@"
}
function check_for_updates
{
local stamp stampfile
stampfile=$DIM_CACHE_DIR/update-check-timestamp
mkdir -p $(dirname $stampfile)
# daily check for updates based on file timestamp
stamp=$(stat --printf=%Y $stampfile 2>/dev/null || echo -n 0)
if [[ $((stamp + 24*60*60)) -lt $(date +%s) ]]; then
dim_uptodate || true
touch $stampfile
fi
}
function check_git_version
{
local min_version="git version 2.8"
if ! echo -e "$min_version\n$(git version)" | sort -VC; then
echoerr "WARNING: recommended minimum $min_version, you have $(git version)"
fi
}
function check_dim_version
{
if [[ -n "$DIM_MIN_VERSION" ]] && [[ "$(dim_version)" < "$DIM_MIN_VERSION" ]]; then
echoerr "ERROR: required minimum dim version $DIM_MIN_VERSION, you have $(dim_version)"
exit 1
fi
}
function check_dim_config
{
if [[ "$DIM_REPO" == "drm-tip" || "$DIM_REPO" == "drm-rerere" || "$DIM_REPO" == "maintainer-tools" ]]; then
echoerr "WARNING: setting $DIM_REPO for DIM_REPO not allowed"
exit 1
fi
}
# get message id from file
# $1 = file
message_get_id ()
{
import email
f = open('$1', 'rb')
msg = email.message_from_binary_file(f)
message_id = msg['message-id']
if message_id is not None:
print(message_id.strip('<> \n'))
msg = email.message_from_binary_file(file)
for part in msg.walk():
if part.get_content_type() == 'text/plain':
print(part.get_payload(decode=True).decode(part.get_content_charset(failobj='us-ascii'), 'replace'))
# append all arguments as tags at the end of the commit message of HEAD
function dim_commit_add_tag
for arg; do
# the first sed deletes all trailing blank lines at the end
git log -1 --pretty=%B | \
sed -e :a -e '/^\n*$/{$d;N;ba' -e '}' | \
sed "\$a${arg}" | \
git commit --amend -F-
done
# $1: branch [optional]
function git_find_tip
{
git log $1 -1 --format=%H --grep="^drm-tip: .* integration manifest$"
}
# $1: branch [optional]
function dim_retip
{
local branch upstream new_upstream
if [ -n "$branch" ] ; then
shift
else
branch=$(git symbolic-ref --short HEAD)
fi
if repo_to_remote drm-tip &> /dev/null ; then
new_upstream=$(repo_to_remote drm-tip)/drm-tip
else
new_upstream=$(git branch -r | grep '/drm-tip$')
upstream=$(git_find_tip "$branch")
if [[ -z "$upstream" ]]; then
echoerr "$branch is not based on drm-tip"
return 1
fi
git rebase --onto $new_upstream $upstream $branch "$@"
function dim_range_diff
{
local branch
branch=${1:-@\{1\}}
if [[ $(git rev-parse $branch | wc -l) -eq 1 ]] ; then
if [[ $(git rev-parse $branch) == "$branch" ]] ; then
branch="@{1}"
else
shift || true
fi
git range-diff $branch...HEAD "$@"
else
git range-diff "$@"
fi
}
# update for-linux-next* branches
function update_linux_next # branch next next-fixes fixes [for-linux-next] [for-linux-next-fixes]
local branch linux_next linux_next_fixes linux_fixes for_linux_next for_linux_next_fixes repo remote
branch=$1
linux_next=$2
linux_next_fixes=$3
linux_fixes=$4
for_linux_next=${5:-for-linux-next}
for_linux_next_fixes=${6:-for-linux-next-fixes}
if [[ $repo != $(branch_to_repo $linux_next) ]] ; then
if [ -n "$for_linux_next_fixes" ] ; then
echo -n "Pushing $linux_fixes to $for_linux_next_fixes... "
git_push $remote +$remote/$linux_fixes:$for_linux_next_fixes
if git merge-base --is-ancestor $remote/$linux_next_fixes $remote/$linux_fixes ; then
# -fixes has caught up to dinf, i.e. we're out of the merge
# window. Push the next queue.
echo -n "Out of merge window. Pushing $linux_next to $for_linux_next... "
git_push $remote +$remote/$linux_next:$for_linux_next
# dinf is ahead of -fixes, i.e. drm-next has already closed for
# the next merge window and we've started to gather new fixes
# for the current -next cycle. Push dinf
echo -n "Pushing $linux_next_fixes to $for_linux_next... "
git_push $remote +$remote/$linux_next_fixes:$for_linux_next
function check_conflicts # tree
if git diff | grep -q '\(<<<<<<<\|=======\|>>>>>>>\||||||||\)' ; then
# we need an empty line to make it look pretty
echoerr ""
echoerr "FAILURE: Could not merge $1"
git -C ${1:-$PWD} rev-parse --absolute-git-dir
if ! git_is_current_branch rerere-cache; then
echo "Fail: Branch setup for the rerere-cache is borked."
exit 1
fi
if ! git pull -q ; then
# We raced with someone else hitting the same conflict, or the
# erratic git gc for rr-cache entries nuke a few entries we
# still want to keep. Clean up and try, but only when the
# initial pull fails since otherwise there's no way to keep new
# resolutions around.
echo "Conflict in the rr-cache, cleaning up"
git clean -fdx rr-cache/
git checkout -f ':(glob)rr-cache/**'
if ! git pull -q ; then
echoerr "Failed to update the rerere cache."
echoerr "Please manually run"
echoerr " $ cd $DIM_PREFIX/drm-rerere ; git pull"
echoerr "and fixup any issues."
cd - > /dev/null
}
function update_rerere_cache
{
echo -n "Updating rerere cache... "
pull_rerere_cache
cd $DIM_PREFIX/drm-tip/
rr_cache_dir=$(git rev-parse --git-common-dir)/rr-cache
if [ ! -L $rr_cache_dir ] ; then
if [ -d $rr_cache_dir ] ; then
rm -Rf $rr_cache_dir
ln -s "$DIM_PREFIX/drm-rerere/rr-cache" $rr_cache_dir
echo "Done."
}
function commit_rerere_cache
{
local remote file commit_message
cd $DIM_PREFIX/drm-rerere/
remote=$(branch_to_remote rerere-cache)
git add ./*.patch >& /dev/null || true
git add fixups/*.patch >& /dev/null || true
for file in $(git ls-files -- rr-cache); do
if ! git log --since="60 days ago" --name-only -- $file | grep $file &> /dev/null; then
git rm $file &> /dev/null || true
find rr-cache/ -mtime -1 -type f -not -name "thisimage*" -print0 | xargs -0 git add &> /dev/null || true
git rm rr-cache/rr-cache &> /dev/null || true
commit_message=$(mktemp)
cat > $commit_message <<-EOF
$dim_timestamp: $integration_branch rerere cache update
$(git --version)
EOF
if git commit -F $commit_message >& /dev/null; then
echo -n "Pushing rerere cache... "
git_push $remote HEAD >& /dev/null && echo "$DONE_OR_SKIP"
function fetch_all
{
for repo in "${!drm_tip_repos[@]}"; do
remote=$(repo_to_remote $repo)
if [[ "$repo" = "$remote" ]]; then
echo -n "Fetching $repo... "
else
echo -n "Fetching $repo (local remote $remote)... "
fi
git_fetch_helper $remote
echo "Done."
done
}
function find_fixup_file # repo branch
{
local file_paths repo branch rerere
repo=$1
branch=$2
rerere=$DIM_PREFIX/drm-rerere
file_paths="$rerere/${repo}-${branch//\//-}-fixup.patch
$rerere/fixups/${branch//\//-}.patch"
for file_path in $file_paths; do
[ -f "$file_path" ] && break
done
echo "$file_path"
}
function dim_rebuild_tip # local_branch
local integration_branch specfile first rerere repo remote local_branch
local_branch=$1
integration_branch=drm-tip
first=1
rerere=$DIM_PREFIX/drm-rerere
if git status --porcelain | grep -v "^.. rr-cache" | grep -q -v "^[ ?][ ?]"; then
warn_or_fail "integration configuration file $dim_integration_config not committed"
echo -n "Reloading $dim_integration_config... "
read_integration_config
cd $DIM_PREFIX/$integration_branch
if ! git_is_current_branch $integration_branch ; then
echo "Branch setup for the integration repo is borked"
exit 1
fi
# rerere uses sha1 of the diff to identify conflicts, we must ensure
# that they look the same for everyone
git config merge.conflictstyle merge
for conf in "${drm_tip_config[@]}"; do
local branch override sha1 fixup_file
remote=$(repo_to_remote $repo)
sha1=$remote/$branch
if [[ $DRY_RUN ]] && [[ "$local_branch" = "$branch" ]]; then
echo -n "Merging (local) $branch... "
sha1=$(git rev-parse $branch)
elif [[ "$repo" = "$remote" ]]; then
echo -n "Merging $repo/$branch... "
else
echo -n "Merging $repo/$branch (local remote $remote)... "
fi
if [[ -n "$override" ]]; then
sha1=$override
echo -n "Using override sha1: $sha1... "
git reset --hard $sha1 &> /dev/null
elif git merge --rerere-autoupdate --ff-only $sha1 >& /dev/null ; then
# nothing to do if just fast-forward
fixup_file=$(find_fixup_file $repo $branch)
echo $branch > .fixup_branch
git merge --rerere-autoupdate --no-commit $sha1 >& /dev/null || true
# normalize conflict markers
if git grep -l '^>>>>>>> ' &> /dev/null ; then
git grep -l '^>>>>>>> ' | xargs sed -e "s|^>>>>>>> .*$|>>>>>>> $repo\/$branch|" -i
echo -n "Applying manual fixup patch for $integration_branch merge... "
if ! check_conflicts "$repo/$branch" ; then
echoerr "See the section \"Resolving Conflicts when Rebuilding drm-tip\""
echoerr "in the drm-tip.rst documentation for how to handle this situation."
return 1
fi
# because we filter out fast-forward merges there will
# always be something to commit
if ! git commit --no-edit --quiet --no-verify ; then
echoerr "Commit failed, missing topic branch?"
return 1
fi
echo -e "$repo $branch $(git rev-parse $sha1)\n\t$(git log -1 $sha1 --pretty=format:%s)" >> $specfile
echo -n "Adding integration manifest $integration_branch: $dim_timestamp... "
mv $specfile integration-manifest
git add integration-manifest
git commit --quiet -m "$integration_branch: $dim_timestamp integration manifest"
remote=$(repo_to_remote drm-tip)
echo -n "Pushing $integration_branch... "
git_push $remote +HEAD >& /dev/null && echo "$DONE_OR_SKIP"
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
function checkpatch_fixes_tag
{
local sha1 fixes_lines cite rv fline
sha1=$1
rv=0
fixes_lines=$(git log -1 --format='%B' "$sha1" | grep -i '^[[:space:]]*Fixes:')
cite=$(dim_cite $sha1)
echo "$fixes_lines" | ( local rv; rv=0 ; while read -r fline; do
local fixes_sha1 fixes_subject orig_subject
if [[ -z "$fline" ]] ; then
continue
fi
[[ "$fline" =~ ^[[:space:]]*[Ff][Ii][Xx][Ee][Ss]:[[:space:]]*(.*)$ ]]
fline="${BASH_REMATCH[1]}"
if [[ ! "$fline" =~ ^[[:space:]]*([[:xdigit:]]{5,})[[:space:]]*(.*)$ ]]; then
echoerr "$cite: Malformed fixes line:"
echoerr " $fline"
rv=1
continue
fi
fixes_sha1="${BASH_REMATCH[1]}"
fixes_subject="${BASH_REMATCH[2]}"
if ! git rev-parse --verify -q $fixes_sha1 > /dev/null ; then
echoerr "$cite: SHA1 in fixes line not found:"
echoerr " $fline"
rv=1
continue
fi
if ! git merge-base --is-ancestor $fixes_sha1 $sha1 ; then
echoerr "$cite: Fixes: SHA1 in not pointing at an ancestor:"
echoerr " $fline"
rv=1
continue
fi
if ! echo $fixes_sha1 | grep -q '[[:xdigit:]]\{12\}' ; then
echoerr "$cite: Fixes: SHA1 needs at least 12 digits:"
echoerr " $fline"
rv=1
continue
fi
orig_subject=$(git show -s $fixes_sha1 --format="format:%s")
if [[ "$fixes_subject" != "(\"$orig_subject\")" ]] ; then
echoerr "$cite: Subject in fixes line doesn't match referenced commit:"
echoerr " $fline"
rv=1
continue
fi
done ; exit $rv )
rv=$?
return $rv
}
# additional patch checks before pushing, e.g. for r-b tags
function checkpatch_commit_push
{
local sha1 managed_branch rv author committer author_outlook cite
cite=$(dim_cite $sha1)
# use real names for people with many different email addresses
author=$(git show -s $sha1 --format="format:%an")
author_email=$(git show -s $sha1 --format="format:%ae")
committer=$(git show -s $sha1 --format="format:%cn")
# outlook mangles mails into "Last, First"
author_outlook=$(git show -s $sha1 --format="format:%an" | sed -e 's/\([^ ]*\) \(.*\)/\2, \1/')
author_translit=$(echo $author | iconv -t ASCII//TRANSLIT)
# check for fd.o mailman From: mangling
if git show -s $sha1 --format="format:%ae %ce"| grep -q '@lists\.freedesktop\.org' ; then
echoerr "$cite: mailman wrangled email address detected."
rv=1
fi
# check for author sign-off
if ! git show -s $sha1 | grep -qi "Signed-off-by:.*\\($author\\|$author_outlook\\|$author_translit\\|$author_email\\)" ; then
echoerr "$cite: author Signed-off-by missing."
fi
# check for committer sign-off
if ! git show -s $sha1 | grep -qi "Signed-off-by:.*$committer" ; then
echoerr "$cite: committer Signed-off-by missing."
fi
# check for Link tag
if [[ "$managed_branch" = "1" ]] && ! git show -s $sha1 | grep -qi 'Link:' ; then
echoerr "$cite: Link tag missing."
if ! git show -s $sha1 | grep -qi '\(reviewed\|acked\)\S*-by:' && \
! [[ "$committer" != "$author" ]]; then
echoerr "$cite: mandatory review missing."
# check for leftover dim extract-tags marker
if git show -s $sha1 | grep -qF "$dim_extract_tags_marker" ; then
echoerr "$cite: leftover dim extract-tags marker."
rv=1
fi
if ! checkpatch_fixes_tag $sha1 ; then
rv=1
fi