#!/bin/bash

# Slackware build script for cargo-auditable

# Ioannis Anagnostakis 2025
# All rights reserved.
#
# Redistribution and use of this script, with or without modification, is
# permitted provided that the following conditions are met:
#
# 1. Redistributions of this script must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
#
#  THIS SOFTWARE IS PROVIDED BY THE AUTHOR "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 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.

cd $(dirname $0) ; CWD=$(pwd)

PRGNAM=cargo-auditable
VERSION=${VERSION:-0.7.4}
BUILD=${BUILD:-1}
TAG=${TAG:-_SBo}
PKGTYPE=${PKGTYPE:-tgz}

if [ -z "$ARCH" ]; then
  case "$( uname -m )" in
    i?86) ARCH=i586 ;;
    arm*) ARCH=arm ;;
       *) ARCH=$( uname -m ) ;;
  esac
fi

if [ ! -z "${PRINT_PACKAGE_NAME}" ]; then
  echo "$PRGNAM-$VERSION-$ARCH-$BUILD$TAG.$PKGTYPE"
  exit 0
fi

TMP=${TMP:-/tmp/SBo}
PKG=$TMP/package-$PRGNAM
OUTPUT=${OUTPUT:-/tmp}

if [ "$ARCH" = "i586" ]; then
  SLKCFLAGS="-O2 -march=i586 -mtune=i686"
  LIBDIRSUFFIX=""
elif [ "$ARCH" = "i686" ]; then
  SLKCFLAGS="-O2 -march=i686 -mtune=i686"
  LIBDIRSUFFIX=""
elif [ "$ARCH" = "x86_64" ]; then
  SLKCFLAGS="-O2 -fPIC"
  LIBDIRSUFFIX="64"
elif [ "$ARCH" = "aarch64" ]; then
  SLKCFLAGS="-O2 -fPIC"
  LIBDIRSUFFIX="64"
else
  SLKCFLAGS="-O2"
  LIBDIRSUFFIX=""
fi

set -e

rm -rf $PKG
mkdir -p $TMP $PKG $OUTPUT
cd $TMP
rm -rf $PRGNAM-$VERSION
tar xvf $CWD/$PRGNAM-$VERSION.tar.gz
cd $PRGNAM-$VERSION
chown -R root:root .
find . -type f \( -perm -4000 -o -perm -2000 \) -exec chmod -s {} +
find . ! -type l -type d ! -perm 755 -exec chmod -f 755 {} +
find . ! -type l -type f -perm /111 ! -perm 755 -exec chmod -f 755 {} +
find . ! -type l -type f ! -perm /111 ! -perm 644 -exec chmod -f 644 {} +

export PATH="/opt/rust/bin:$PATH"
if [ -z "$LD_LIBRARY_PATH" ]; then
  export LD_LIBRARY_PATH="/opt/rust/lib$LIBDIRSUFFIX"
else
  export LD_LIBRARY_PATH="/opt/rust/lib$LIBDIRSUFFIX:$LD_LIBRARY_PATH"
fi

  # Create vendor directory and extract all crates
mkdir -p vendor
pushd $CWD
mkdir -p crates
mv *.crate crates
for crate in ./crates/*.crate; do
  tar xf "$crate" -C $TMP/$PRGNAM-$VERSION/vendor
done
popd
# Create .cargo-ok and .cargo-checksum.json for each vendored crate
for cratedir in vendor/*/; do
  # Create .cargo-ok
  touch "${cratedir}/.cargo-ok"

  # Calculate checksums for all files and the original .crate
  cratename=$(basename "$cratedir")

  # Generate .cargo-checksum.json
  python3 -c "
import json
import os
from hashlib import sha256
from pathlib import Path

crate_dir = Path('${cratedir}')
crate_file = Path('$CWD/crates/${cratename}.crate')

# Calculate file checksums
files = {}
for file in crate_dir.rglob('*'):
    if file.is_file() and file.name not in ['.cargo-ok', '.cargo-checksum.json']:
        rel_path = str(file.relative_to(crate_dir))
        with open(file, 'rb') as f:
            files[rel_path] = sha256(f.read()).hexdigest()

# Calculate package checksum
with open(crate_file, 'rb') as f:
    package_hash = sha256(f.read()).hexdigest()

# Write checksum file
with open(crate_dir / '.cargo-checksum.json', 'w') as f:
    json.dump({'files': files, 'package': package_hash}, f)
"
done

# Create Cargo config for vendored sources
mkdir -p .cargo
cat > .cargo/config.toml << EOF
[source.crates-io]
registry = 'https://github.com/rust-lang/crates.io-index'
replace-with = 'vendored-sources'

[source.vendored-sources]
directory = 'vendor'
EOF

# Build with Cargo
CARGO_HOME=.cargo \
    cargo build --release --frozen --offline
echo ""
echo "=== Rebuilding now with cargo-auditable itself ==="
echo ""
PATH="$PATH:./target/release" \
CARGO_HOME=.cargo \
    cargo auditable build --release --frozen --offline

# Install the binary
mkdir -p $PKG/usr/bin
install -m 0755 target/release/cargo-auditable $PKG/usr/bin/
install -Dm644 cargo-auditable/cargo-auditable.1 -t "$PKG"/usr/man/man1/

# Strip binaries and libraries
find $PKG -print0 | xargs -0 file | grep -e "executable" -e "shared object" | grep ELF \
  | cut -f 1 -d : | xargs strip --strip-unneeded 2> /dev/null || true


  # Compress man pages if they exist
if [ -d $PKG/usr/man ]; then
  find $PKG/usr/man -type f -exec gzip -9 {} \;
  for i in $( find $PKG/usr/man -type l ) ; do ln -s $( readlink $i ).gz $i.gz ; rm $i ; done
fi

# Documentation
mkdir -p $PKG/usr/doc/$PRGNAM-$VERSION
cp -a \
  LICENSE* *.md "$PRGNAM"/*.md \
  $PKG/usr/doc/$PRGNAM-$VERSION
cat $CWD/$PRGNAM.SlackBuild > $PKG/usr/doc/$PRGNAM-$VERSION/$PRGNAM.SlackBuild

mkdir -p $PKG/install
cat $CWD/slack-desc > $PKG/install/slack-desc

cd $PKG
/sbin/makepkg -l y -c n $OUTPUT/$PRGNAM-$VERSION-$ARCH-$BUILD$TAG.$PKGTYPE
