dash/test/lint/git-subtree-check.sh

134 lines
3.6 KiB
Bash
Raw Permalink Normal View History

2015-04-03 02:15:29 +02:00
#!/bin/sh
# Copyright (c) 2015-2020 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
2015-04-03 02:15:29 +02:00
export LC_ALL=C
check_remote=0
while getopts "?hr" opt; do
case $opt in
'?' | h)
echo "Usage: $0 [-r] DIR [COMMIT]"
echo " $0 -?"
echo ""
echo "Checks that a certain prefix is pure subtree, and optionally whether the"
echo "referenced commit is present in any fetched remote."
echo ""
echo "DIR is the prefix within the repository to check."
echo "COMMIT is the commit to check, if it is not provided, HEAD will be used."
echo ""
echo "-r Check that subtree commit is present in repository."
echo " To do this check, fetch the subtreed remote first. Example:"
echo ""
echo " git fetch https://github.com/bitcoin-core/secp256k1.git"
echo " test/lint/git-subtree-check.sh -r src/secp256k1"
exit 1
;;
r)
check_remote=1
;;
esac
done
shift $((OPTIND-1))
if [ -z "$1" ]; then
echo "Need to provide a DIR, see $0 -?"
exit 1
fi
# Strip trailing / from directory path (in case it was added by autocomplete)
DIR="${1%/}"
2015-04-03 02:15:29 +02:00
COMMIT="$2"
if [ -z "$COMMIT" ]; then
COMMIT=HEAD
fi
# Taken from git-subtree (Copyright (C) 2009 Avery Pennarun <apenwarr@gmail.com>)
find_latest_squash()
{
dir="$1"
sq=
main=
sub=
git log --grep="^git-subtree-dir: $dir/*\$" \
--pretty=format:'START %H%n%s%n%n%b%nEND%n' "$COMMIT" |
2020-07-29 15:42:12 +02:00
while read a b _; do
2015-04-03 02:15:29 +02:00
case "$a" in
START) sq="$b" ;;
git-subtree-mainline:) main="$b" ;;
git-subtree-split:) sub="$b" ;;
END)
if [ -n "$sub" ]; then
if [ -n "$main" ]; then
# a rejoin commit?
# Pretend its sub was a squash.
sq="$sub"
fi
echo "$sq" "$sub"
break
fi
sq=
main=
sub=
;;
esac
done
}
# find latest subtree update
2015-04-03 02:15:29 +02:00
latest_squash="$(find_latest_squash "$DIR")"
if [ -z "$latest_squash" ]; then
echo "ERROR: $DIR is not a subtree" >&2
exit 2
fi
# shellcheck disable=SC2086
2015-04-03 02:15:29 +02:00
set $latest_squash
old=$1
2015-04-03 02:15:29 +02:00
rev=$2
# get the tree in the current commit
2015-04-03 02:15:29 +02:00
tree_actual=$(git ls-tree -d "$COMMIT" "$DIR" | head -n 1)
if [ -z "$tree_actual" ]; then
echo "FAIL: subtree directory $DIR not found in $COMMIT" >&2
exit 1
fi
# shellcheck disable=SC2086
2015-04-03 02:15:29 +02:00
set $tree_actual
tree_actual_type=$2
tree_actual_tree=$3
echo "$DIR in $COMMIT currently refers to $tree_actual_type $tree_actual_tree"
if [ "d$tree_actual_type" != "dtree" ]; then
echo "FAIL: subtree directory $DIR is not a tree in $COMMIT" >&2
exit 1
fi
# get the tree at the time of the last subtree update
tree_commit=$(git show -s --format="%T" "$old")
echo "$DIR in $COMMIT was last updated in commit $old (tree $tree_commit)"
# ... and compare the actual tree with it
if [ "$tree_actual_tree" != "$tree_commit" ]; then
git diff "$tree_commit" "$tree_actual_tree" >&2
echo "FAIL: subtree directory was touched without subtree merge" >&2
exit 1
fi
if [ "$check_remote" != "0" ]; then
# get the tree in the subtree commit referred to
if [ "d$(git cat-file -t "$rev" 2>/dev/null)" != dcommit ]; then
echo "subtree commit $rev unavailable: cannot compare. Did you add and fetch the remote?" >&2
exit 1
fi
tree_subtree=$(git show -s --format="%T" "$rev")
echo "$DIR in $COMMIT was last updated to upstream commit $rev (tree $tree_subtree)"
# ... and compare the actual tree with it
if [ "$tree_actual_tree" != "$tree_subtree" ]; then
echo "FAIL: subtree update commit differs from upstream tree!" >&2
exit 1
fi
2015-04-03 02:15:29 +02:00
fi
2015-04-03 02:15:29 +02:00
echo "GOOD"