#!/bin/bash

# The MIT License
#
# Copyright (c) 2011,2012 by Michael Prokop <mika@debian.org>
# Copyright (c) 2012-2024 by Christoph Berg <myon@debian.org>
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.

set -e
set -u

if [ -z "${PACKAGE:-}" ]; then
  PACKAGE="${JOB_NAME%-source*}"
fi

echo "PACKAGE=$PACKAGE"
echo "BUILD_NUMBER=${BUILD_NUMBER:-}"
echo "JOB_NAME=${JOB_NAME:-}"
echo "GIT_COMMIT=${GIT_COMMIT:-}"
echo "PG_SUPPORTED_VERSIONS=${PG_SUPPORTED_VERSIONS:=pgdg}"
echo "distribution=${distribution:=sid}"
echo "branch=${branch:-}"
echo "merge=${merge:-}"
echo "revision=${revision:-}"

# read pgapt config
for dir in . .. $HOME/apt.postgresql.org; do
  test -f $dir/pgapt.conf || continue
  . $dir/pgapt.conf
  break
done
set_dist_vars $distribution # set PGDG_DISTRIBUTION

[ -n "${DEBEMAIL:-}" ] || export DEBEMAIL="$MAILING_LIST"

export PG_SUPPORTED_VERSIONS
# tell /usr/share/postgresql-common/supported-versions which distro/release we are targeting
export DISTRO RELEASE

# prepare 'source' directory
if [ "${GIT_COMMIT:-}" ]; then # git expects the checkout in 'source' subdir
  cd source
elif [ "${apt_suite:-}" ] ; then # apt-get source specified
  rm -rf $PACKAGE* source
  schroot -c $apt_suite -- apt-get source -d $PACKAGE/$apt_suite
  dpkg-source -x $PACKAGE*.dsc source
  cd source
else # use source tree in current directory
  :
fi

set -x

# snapshot builds
case ${JOB_NAME:-} in *-source-snapshot*)
  is_snapshot="snapshot"

  # merge with upstream git
  if [ "${upstream_branch:-}" ]; then
    MSG="Merge Debian packaging repository ($branch) with upstream ($upstream_branch)."
    git merge --allow-unrelated-histories -m "$MSG" upstream/$upstream_branch
    TWEAK+=("$MSG")
  fi
  ;;
esac

# use older debhelper version
debhelper_compat ()
{
  local level="$1"
  if [ -f debian/compat ]; then
    pkglevel="$(cat debian/compat)"
  else
    pkglevel="$(grep -o 'debhelper-compat (= [0-9]*' debian/control* | sed -e 's/.* //' | head -n1)"
  fi
  if [ -z "$pkglevel" ]; then
    echo "Could not determine debhelper compat level"
    exit 1
  fi
  echo "Package is using debhelper compat level $pkglevel"
  [ "$level" -ge "$pkglevel" ] && return
  sed -i -e "s/debhelper[^,]*/debhelper (>= $level)/" debian/control*
  echo "$level" > debian/compat
  TWEAK+=("Using debhelper $level.")
}

# set LLVM version
llvm_version ()
{
  local version="$1"
  local architectures="${2:-}"

  sed -i -Ee "s/^ clang(-[0-9]*)? / clang-$version /" \
         -Ee "s/^ llvm(-[0-9]*)?-dev / llvm-$version-dev /" \
         debian/control
  if [ "$architectures" ]; then
    sed -i -Ee "s/\\[!alpha.*\\]/[$architectures]/" debian/control debian/*.install
  fi
  TWEAK+=("Use clang/llvm $version for jit support.")
}

# for postgresql server packages, move packages to a separate components
# = $PG_MAIN_VERSION: main
# < $PG_MAIN_VERSION: lib packages to N.N, rest to main
# > $PG_MAIN_VERSION: all packages to N.N
set_package_component ()
{
  PKGPREFIX="$1" # empty ok
  SECTION="$2"
  echo "Setting $PKGPREFIX* packages component to '$SECTION'"
  perl -i -000 -pe "s/^Section: (?:.+\/)?(.*)/Section: $SECTION\$1/m if (/^$PKGPREFIX/m)" \
    debian/control
}
show_package_sections ()
{
  perl -000 -ne 'if (/^(Package: .*)/m) { print "$1 "; print "$1\n" if /^(Section: .*)/m; }' \
    debian/control
}
case $PACKAGE in
  postgresql-?.?|postgresql-??|postgresql-??ee)
    PGVERSION=${PACKAGE#postgresql-}
    if dpkg --compare-versions $PGVERSION lt $PG_MAIN_VERSION; then
      set_package_component "Package: lib" "$PGVERSION\/"
      TWEAK+=("Moving lib packages to component $PGVERSION.")
    elif dpkg --compare-versions $PGVERSION gt $PG_MAIN_VERSION; then
      set_package_component "" "$PGVERSION\/"
      TWEAK+=("Moving binary packages to component $PGVERSION.")
    else
      set_package_component "" ""
    fi
    show_package_sections

    # enable cassert on sid
    if [ "$distribution" = "sid" ]; then
      sed -i -e 's/^#CASSERT_FLAGS/CASSERT_FLAGS/' debian/rules
      TWEAK+=("Enabling cassert.")
    fi
    ;;
esac

# tweaks to get packages in older dists working

# PostgreSQL server tweaks

# LLVM: default available
# trixie     16 15 17
# bookworm   14 15 16
# bullseye   11 13 (16 in pu)
# buster      7 13
# noble      17 15 16
# mantic     16 15
# lunar      15 16
# jammy      14 15
# focal      10

case $PACKAGE in
  postgresql-11) # not compatible with LLVM 16: llvmjit.so: undefined symbol: LLVMBuildGEP
    case $distribution in
      sid|trixie) llvm_version 15 ;; # downgrade to 15
      bookworm) llvm_version 15 ;;   # upgrade to 15
      oracular|noble|mantic) llvm_version 15 ;; # downgrade to 15
      jammy) llvm_version 15 ;;      # upgrade to 15
    esac
    ;;
  postgresql-1[1-9]|postgresql-1[1-9]ee|postgresql-2*)
    case $distribution in
      bookworm) llvm_version 16 ;; # upgrade to 16
      bullseye) llvm_version 13 ;; # upgrade to 13
      buster) llvm_version 13 ;;   # upgrade to 13
      noble) llvm_version 17 ;;    # downgrade to 17 <CAFj8pRACpVFr7LMdVYENUkScG5FCYMZDDdSGNU-tch+w98OxYg@mail.gmail.com>
      jammy) llvm_version 15 ;;    # upgrade to 15
    esac
    ;;
esac
case $PACKAGE in
  postgresql-9.[1-6])
    case $distribution in oracular|noble)
      # remove binary from .dsc so autopkgtest doesn't see it (package still needs -Pnopython to build)
      perl -i -000 -ne "print unless /^Package: postgresql-plpython3/m" debian/control
      TWEAK+=("Disable plpython3 package, incompatible with Python 3.12.")
      ;;
    esac
    ;;
esac
case $PACKAGE in
  postgresql-8.?|postgresql-9.?|postgresql-[1-7]?|timescaledb)
    case $distribution in bookworm|bullseye|buster|jammy|focal)
      sed -i -e '/tzdata-legacy/d' debian/control
      sed -i -e 's/tzdata.*/tzdata,/' debian/tests/control
      TWEAK+=("Remove tzdata-legacy from build and test dependencies.")
      ;;
    esac
    ;;
esac

# adjust debhelper level
# case $distribution in
#   jessie|stretch) debhelper_compat 10 ;;
#   buster) debhelper_compat 12 ;;
#   bullseye|bookworm|trixie) debhelper_compat 13 ;;
#   sid) ;;
#   xenial) debhelper_compat 9 ;;
#   bionic) debhelper_compat 11 ;;
#   eoan|focal) debhelper_compat 12 ;;
#   groovy|hirsute|impish|jammy|kinetic|lunar|mantic|noble|oracular) debhelper_compat 13 ;;
#   *) echo "debhelper compat missing for $distribution"; exit 1 ;;
# esac

# remove unsupported autopkgtest restrictions
case $distribution in buster|focal|bionic)
  if test -f debian/tests/control && grep needs-internet debian/tests/control; then
    sed -i -e 's/\(, \)\?needs-internet//' debian/tests/control
    TWEAK+=("Remove needs-internet from debian/tests/control.")
  fi
  ;;
esac

# tweaks for other packages
case $PACKAGE in
  postgis)
    case ${distribution:-} in
      buster|stretch|focal|eoan|bionic|xenial)
        sed -i -e '/proj-7.0.1.patch/d' debian/patches/series
        TWEAK+=("Disable proj-7.0.1.patch.")
        ;;
    esac
    ;;

  prometheus-sql-exporter)
    case ${distribution:-} in
      bookworm|noble|mantic|jammy)
        sed -i -e '/fix-missing-new-collector/d' debian/patches/series
        TWEAK+=("Disable fix-missing-new-collector.")
        ;;
    esac
    ;;

  repmgr)
    # Add libedit-dev to support building with postgres < 13
    sed -i -e 's/libreadline-dev,/libreadline-dev,\n libedit-dev,/' debian/control*
    TWEAK+=("Add libedit-dev dependency")
    ;;

  vip-manager)
    case ${distribution:-} in
      bullseye|buster|kinetic|jammy|focal|bionic)
        sed -i -e 's/^#\(.*consul\)/\1/' debian/control
        sed -i -e '/disable-consul/d' debian/patches/series
        TWEAK+=("Re-enable consul.")
        ;;
    esac
    case ${distribution:-} in
      bullseye|jammy)
        sed -i -e '/netip-port/d' debian/patches/series
        TWEAK+=("Remove netip-port patch.")
        ;;
    esac
    case ${distribution:-} in
      bookworm|bullseye|noble|mantic)
        sed -i -e '/etcd-3.5-build-fixes.patch/d' debian/patches/series
        TWEAK+=("Disable etcd-3.5-build-fixes patch.")
    esac
    ;;
  vip-manager2)
    case ${distribution:-} in
      bookworm|bullseye|noble|mantic|jammy)
        sed -i -e 's/^#etcd-3.4-build-fixes.patch/etcd-3.4-build-fixes.patch/' debian/patches/series
        TWEAK+=("Enable etcd-3.4-build-fixes patch.")
        ;;
    esac
    ;;
esac

# remove artifacts from last build (-r because sometimes uscan leaves temp directories behind)
rm -rf ../*.*

# get orig tarball and unpack it in case it's a debian/ only checkout
origtargz --tar-only --path ../result --path=$HOME/tarballs || orig_fail="$?"

CL_VERSION=$(dpkg-parsechangelog -SVersion)
CL_DISTRIBUTION=$(dpkg-parsechangelog -SDistribution)
case $CL_DISTRIBUTION in
  *UNRELEASED*) is_unreleased=UNRELEASED ;;
esac

if [ "${is_snapshot:-}" ] || [ "${is_unreleased:-}" ]; then
  if [ "${orig_fail:-}" ]; then
    if test -d debian/patches; then
      QUILT_PATCHES=debian/patches quilt push -a || [ $? = 2 ]
    fi
    echo "1.0" > debian/source/format
    TWEAK+=("Using source format 1.0 as orig tarball is missing.")
  fi
  DATE="$(date -u +%Y%m%d.%H%M)"
  GIT_REVISION=$(echo ${GIT_COMMIT:-xxxxxxx} | cut -c 1-7)
  PGDG_REVISION="~$DATE.g$GIT_REVISION"
  DPKG_SOURCE_FLAGS="--include-binaries --auto-commit"
else
  if [ "${orig_fail:-}" ]; then
    echo "Orig tarball is missing, bailing out"
    exit 1
  fi
  PGDG_REVISION="${revision:-1}"
fi

# update changelog
# $DOT defaults to '.', but can be set to '~'
VERSION_STRING="$CL_VERSION${DOT:-.}$PGDG_DISTRIBUTION+$PGDG_REVISION"
DATE=$(dpkg-parsechangelog -SDate)
cat > debian/changelog.tmp <<EOT
$PACKAGE ($VERSION_STRING) $distribution$REPO_DIST_SUFFIX; urgency=medium

  * Rebuild for $distribution$REPO_DIST_SUFFIX.
EOT
if [ "${TWEAK:-}" ]; then
  echo "  * Changes applied by generate-pgdg-source:" >> debian/changelog.tmp
  for tweak in "${TWEAK[@]}"; do
    echo "    + $tweak" >> debian/changelog.tmp
  done
else
  echo "  * No source changes." >> debian/changelog.tmp
fi
cat - debian/changelog >> debian/changelog.tmp <<EOT

 -- $MAILING_LIST  $DATE

EOT
mv debian/changelog.tmp debian/changelog
sed -ne '1,/^ --/p' debian/changelog

if [ -f debian/control.in ]; then
  case $PACKAGE in
    postgis|postgis-2.5) debian/rules debian/control ;; # has its own update rule
    *) pg_buildext checkcontrol ;;
  esac
fi
if ! [ -f debian/control ] ; then
  make -f debian/rules debian/control
fi

# build source package and move it to 'result' for archiving
echo "$VERSION_STRING" > ../version.txt
dpkg-source -i -I ${DPKG_SOURCE_FLAGS:-} --build .
dpkg-genchanges --build=source -sa > ../${PACKAGE}_${VERSION_STRING}_source.changes
cd ..
rm -rf result buildinfo.tmp
mkdir result
dcmd mv -v ${PACKAGE}_*.changes result

# clean up generated 'source' directory
if [ "${apt_suite:-}" ]; then
  rm -rf source
elif [ "${GIT_COMMIT:-}" ]; then
  rm -rf source/* # remove everything except .git
fi

# vim:foldmethod=marker ts=2 ft=sh ai expandtab sw=2
