#!@BASH_PATH@
#
# Copyright 2011-2025 the Pacemaker project contributors
#
# The version control history for this file may have further details.
#
# This source code is licensed under the GNU General Public License version 2
# or later (GPLv2+) WITHOUT ANY WARRANTY.
#

#
# abi-check [-u] <package-name> <version> [...]
#
# Build ABI dumps for all listed versions. If exactly two are given,
# build an ABI compatibility report for them, and if -u is given,
# upload it to the website.
#

# Where to checkout the source for a version
ABI_CHECKOUT="abi/src"

# Where to install the checkout build
ABI_INSTALL="abi/install"

# Where to build ABI dumps
ABI_DUMPS="abi/dumps"

# Where to build ABI reports
ABI_REPORTS="abi/compat_reports"

# If the argument is of form x.y.z, print Pacemaker-x.y.z,
# otherwise print the argument (presumably a commit ID) directly
tag() {
    if [[ "$1" =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3} ]]; then
        echo "Pacemaker-$1"
    else
        echo "$1"
    fi
}

# sed -i isn't portable
sed_in_place() {
    # Preserve permissions
    cp -p "$1" "$1.$$"

    sed -e "$2" "$1" > "$1.$$"
    mv "$1.$$" "$1"
}

# Strip anything up to and including a dash from the argument
version() {
    echo "$1" | sed s:.*-::
}

dumpfile() {
    local VERSION="$1"

    echo "${PACKAGE}_${VERSION}.abi.tar.gz"
}

checkout_commit() {
    local TAG="$1"

    echo "Checking out $TAG to $ABI_CHECKOUT..."
    rm -rf "$ABI_CHECKOUT"
    ( cd .. ; git archive --prefix "doc/${ABI_CHECKOUT}/" "$TAG" | tar x )
    [ $? -eq 0 ] || exit

    # Remove "doc" from SUBDIRS in Makefile (but why?)
    sed_in_place "${ABI_CHECKOUT}/Makefile.am" 's: doc::'
}

build_checkout() {
    echo "Building to $ABI_INSTALL..."
    ( cd "${ABI_CHECKOUT}" && ./autogen.sh \
        && ./configure --quiet --disable-fatal-warnings )
    make -C "${ABI_CHECKOUT}" V=0 DESTDIR="$(pwd)/$ABI_INSTALL" install
    [ $? -eq 0 ] || exit
}

# Create configuration file for ABI dumper
abi_config() {
    PACKAGE="$1"
    VERSION="$2"
    DESC="$3"

    # Create header
    DESC="${ABI_CHECKOUT}/${VERSION}.xml"
    cat <<EOF > "$DESC"
<?xml version="1.0" encoding="utf-8"?>
<descriptor>
<version>
    $VERSION
</version>
<headers>
        $(pwd)/${ABI_INSTALL}/usr/include/${PACKAGE}/crm
</headers>
<libs>
EOF

    # Add library names to configuration file
    find "$ABI_INSTALL" -name "*.so" -print >> $DESC

    # Add footer
    cat <<EOF >> "$DESC"
</libs>
</descriptor>
EOF
}

# Dump the ABI for a particular version
dump_version() {
    TAG="$1"
    VERSION="$2"

    # Reuse any previous dump unless it's for HEAD (which changes)
    DUMP="${ABI_DUMPS}/$(dumpfile "$VERSION")"
    if [ -f "$DUMP" ]; then
        if [ "$VERSION" = HEAD ]; then
            rm -f "$DUMP"
        else
            return
        fi
    fi

    checkout_commit "$TAG"
    build_checkout "$TAG"

    # Run ABI dump
    echo "Building ABI dump for $TAG"
    abi_config "$PACKAGE" "$VERSION" "$DESC"
    abi-compliance-checker -l "$PACKAGE" -dump_abi "$DESC" -dump-path "$DUMP"

    # Clean up
    rm -rf "$ABI_CHECKOUT" "$ABI_INSTALL"
}

dump_versions() {
    for arg in $*; do
        T=$(tag "$arg")
        V=$(version "$T")
        dump_version "$T" "$V"
    done
}

die() {
	echo "$@" 1>&2
	exit 1
}

# Validate environment
which git >/dev/null 2>/dev/null || die "abi-check: git must be installed"
git rev-parse --git-dir >/dev/null 2>/dev/null	\
	|| die "abi-check: must be run from git checkout"

UPLOAD=0
if [ "$1" = "-u" ]; then
    UPLOAD=1; shift
fi

PACKAGE="$1"; shift

dump_versions "$@"

# Unless exactly two versions were given, we're just dumping
if [ $# -ne 2 ]; then
    exit
fi

V1=$(version "$1")
V2=$(version "$2")

(cd abi && abi-compliance-checker -l ${PACKAGE} \
    -d1 "${ABI_DUMPS#abi/}/$(dumpfile "$V1")"   \
    -d2 "${ABI_DUMPS#abi/}/$(dumpfile "$V2")" )
if [ $? -ne 0 ]; then
    echo "WARNING: compliance checker exited $?"
fi

# Top-level rsync destination for package's file uploads (no trailing slash)
: ${RSYNC_PACKAGE_DEST:=sites.clusterlabs.org:/var/www/html/projects/$PACKAGE}

REPORT="${ABI_REPORTS}/${PACKAGE}/${V1}_to_${V2}"
if [ $UPLOAD -eq 1 ] && [ -d "$REPORT" ]; then
    rsync -azxlSD --progress "$REPORT" "${RSYNC_PACKAGE_DEST}/abi/"
fi

# vim: set expandtab tabstop=8 softtabstop=4 shiftwidth=4 textwidth=80:
