Add a tool to find MFC candidates
usage: mfc-candidates.sh [-ah] [-f from_branch] [-t to_branch] [-u user] [-X exclude_file] [path ...] This tool compares git commit hashes that are in from_branch and not in to_branch with hashes listed in "cherry picked from" lines, finding commits that may be MFC candidates. By default it searches for commits by ${USER} but that can be overridden with -u for a specific user or -a for all. gonzo@'s MFC tracker is a web application that presents this sort of information in a more convenient way, and unlike this script it tracks "MFC After" status and timing. However, it is sometimes useful to be able to perform an offline search against a local repo. Reviewed by: jhb Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D34208
This commit is contained in:
parent
c5041b4ee8
commit
1a50bf77af
163
tools/tools/git/mfc-candidates.sh
Normal file
163
tools/tools/git/mfc-candidates.sh
Normal file
@ -0,0 +1,163 @@
|
||||
#!/bin/sh
|
||||
|
||||
#-
|
||||
# SPDX-License-Identifier: BSD-2-Clause-FreeBSD
|
||||
#
|
||||
# Copyright 2022 The FreeBSD Foundation
|
||||
#
|
||||
# This software was developed by Ed Maste
|
||||
# under sponsorship from the FreeBSD Foundation.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted providing that the following conditions
|
||||
# are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
# SUCH DAMAGE.
|
||||
|
||||
from_branch=freebsd/main
|
||||
to_branch=freebsd/stable/13
|
||||
author="${USER}"
|
||||
|
||||
# If pwd is a stable or release branch tree, default to it.
|
||||
cur_branch=$(git symbolic-ref --short HEAD 2>/dev/null)
|
||||
case $cur_branch in
|
||||
stable/*)
|
||||
to_branch=$cur_branch
|
||||
;;
|
||||
releng/*)
|
||||
to_branch=$cur_branch
|
||||
major=${cur_branch#releng/}
|
||||
major=${major%.*}
|
||||
from_branch=freebsd/stable/$major
|
||||
esac
|
||||
|
||||
params()
|
||||
{
|
||||
echo "from: $from_branch"
|
||||
echo "to: $to_branch"
|
||||
if [ -n "$author" ]; then
|
||||
echo "author/committer: $author"
|
||||
else
|
||||
echo "author/committer: <all>"
|
||||
fi
|
||||
}
|
||||
|
||||
usage()
|
||||
{
|
||||
echo "usage: $(basename $0) [-ah] [-f from_branch] [-t to_branch] [-u user] [-X exclude_file] [path ...]"
|
||||
echo
|
||||
params
|
||||
exit 0
|
||||
}
|
||||
|
||||
while getopts "af:ht:u:vX:" opt; do
|
||||
case $opt in
|
||||
a)
|
||||
# All authors/committers
|
||||
author=
|
||||
;;
|
||||
f)
|
||||
from_branch=$OPTARG
|
||||
;;
|
||||
h)
|
||||
usage
|
||||
;;
|
||||
t)
|
||||
to_branch=$OPTARG
|
||||
;;
|
||||
u)
|
||||
author=$OPTARG
|
||||
;;
|
||||
v)
|
||||
verbose=1
|
||||
;;
|
||||
X)
|
||||
if [ ! -r "$OPTARG" ]; then
|
||||
echo "Exclude file $OPTARG not readable" >&2
|
||||
exit 1
|
||||
fi
|
||||
exclude_file=$OPTARG
|
||||
;;
|
||||
esac
|
||||
done
|
||||
shift $(($OPTIND - 1))
|
||||
|
||||
if [ $verbose ]; then
|
||||
params
|
||||
echo
|
||||
fi
|
||||
|
||||
authorarg=
|
||||
if [ -n "$author" ]; then
|
||||
# Match user ID in the email portion of author or committer
|
||||
authorarg="--author <${author}@ --committer <${author}@"
|
||||
fi
|
||||
|
||||
# Commits in from_branch after branch point
|
||||
commits_from()
|
||||
{
|
||||
git rev-list --first-parent $authorarg $to_branch..$from_branch "$@" |\
|
||||
sort
|
||||
}
|
||||
|
||||
# "cherry picked from" hashes from commits in to_branch after branch point
|
||||
commits_to()
|
||||
{
|
||||
git log $from_branch..$to_branch --grep 'cherry picked from' "$@" |\
|
||||
sed -E -n 's/^[[:space:]]*\(cherry picked from commit ([0-9a-f]+)\)[[:space:]]*$/\1/p' |\
|
||||
sort
|
||||
}
|
||||
|
||||
# Turn a list of short hashes (and optional descriptions) into a list of full
|
||||
# hashes.
|
||||
canonicalize_hashes()
|
||||
{
|
||||
while read hash rest; do
|
||||
if ! git show --pretty=%H --no-patch $hash; then
|
||||
echo "error parsing hash list" >&2
|
||||
exit 1
|
||||
fi
|
||||
done | sort
|
||||
}
|
||||
|
||||
workdir=$(mktemp -d /tmp/find-mfc.XXXXXXXXXX)
|
||||
from_list=$workdir/commits-from
|
||||
to_list=$workdir/commits-to
|
||||
candidate_list=$workdir/candidates
|
||||
|
||||
if [ -n "$exclude_file" ]; then
|
||||
exclude_list=$workdir/commits-exclude
|
||||
canonicalize_hashes < $exclude_file > $exclude_list
|
||||
fi
|
||||
|
||||
commits_from "$@" > $from_list
|
||||
commits_to "$@" > $to_list
|
||||
|
||||
comm -23 $from_list $to_list > $candidate_list
|
||||
|
||||
if [ -n "$exclude_file" ]; then
|
||||
mv $candidate_list $candidate_list.bak
|
||||
comm -23 $candidate_list.bak $exclude_list > $candidate_list
|
||||
fi
|
||||
|
||||
# Sort by (but do not print) commit time
|
||||
while read hash; do
|
||||
git show --pretty='%ct %h %s' --no-patch $hash
|
||||
done < $candidate_list | sort -n | cut -d ' ' -f 2-
|
||||
|
||||
rm -rf "$workdir"
|
Loading…
Reference in New Issue
Block a user