aboutsummaryrefslogtreecommitdiff
path: root/tools/tools
diff options
context:
space:
mode:
authorEd Maste <emaste@FreeBSD.org>2022-02-08 19:50:50 +0000
committerEd Maste <emaste@FreeBSD.org>2022-04-28 18:02:26 +0000
commit1a50bf77af90e0ee7a80f268b2c0bf2a44e38ef2 (patch)
tree4edfbba62c3d27f6eef133d23b99dc31c157e602 /tools/tools
parentc5041b4ee8c3385cec03e6ccf73af78cadfe8d90 (diff)
downloadsrc-1a50bf77af90e0ee7a80f268b2c0bf2a44e38ef2.tar.gz
src-1a50bf77af90e0ee7a80f268b2c0bf2a44e38ef2.zip
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
Diffstat (limited to 'tools/tools')
-rw-r--r--tools/tools/git/mfc-candidates.sh163
1 files changed, 163 insertions, 0 deletions
diff --git a/tools/tools/git/mfc-candidates.sh b/tools/tools/git/mfc-candidates.sh
new file mode 100644
index 000000000000..623edc7174a1
--- /dev/null
+++ b/tools/tools/git/mfc-candidates.sh
@@ -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"