# Maintainer: Luke T. Shumaker <lukeshu@parabola.nu>
# Contributor: Omar Vega Ramos <ovruni@gnu.org.pe>
# Contributor: Daniel Milewski <niitotantei@riseup.net>
# Contributor: André Silva <emulatorman@hyperbola.info>
# Contributor: fauno <fauno@parabola.nu>

# Maintainer (arch): Anatol Pomozov <anatol.pomozov@gmail.com>
# Maintainer (arch): Andreas 'Segaja' Schleifer <segaja at archlinux dot org>
# Maintainer (arch): Tim Meusel <tim@bastelfreak.de>
# Contributor: Thomas Dziedzic <gostrc@gmail.com>
# Contributor: Allan McRae <allan@archlinux.org>
# Contributor: John Proctor <jproctor@prium.net>
# Contributor: Jeramy Rutley <jrutley@gmail.com>


# Parabola changes and rationale:
# libre:
#  - disable default TPPM (rubygems.org, which hosts non-free
#    packages) in ruby-default-gems-bootstrap
#    https://wiki.parabola.nu/TPPM_Liberation_Project
# policy:
#  - get check() to work without networking
# technical:
#  - incorporate
#    https://gitlab.archlinux.org/archlinux/packaging/packages/ruby/-/merge_requests/6
#    This was rejected from Arch, but LukeShu wants to keep it anyway
#    for bootstrapping purposes.
#  - disable tests that trigger qemu-arm-static bugs/limitations
#  - set options=(!strip) to avoid creating ruby-debug, because extra/ruby-debug is the 'debug' gem


# Do not de-vendor and create separate packages for default gems (see
# https://stdgems.org/), leave them vendored as part of the main
# 'ruby' package.  Creating a separate package for a default gem will
# lead to multiple problems.
#
# ... except for default gems that provide a tool in /usr/bin.  Having
# separate de-vendored packages for them is OK I guess.  (In the code
# below, this distinction is represented as _default_gems=() vs
# _default_tool_gems=()).

pkgname=(
  ruby
  ruby-docs
  ruby-default-gems
  ruby-default-gems-bootstrap
  ruby-bundled-gems
  ruby-bundled-gems-bootstrap
  ruby-stdlib
)
pkgver=3.4.8
_rubyver="${pkgver%.*}.0"
pkgrel=2
pkgdesc='An object-oriented language for quick and easy programming'
url='https://www.ruby-lang.org/en/'
arch=(x86_64)
license=(BSD-2-Clause)
makedepends=(
  doxygen
  libgcc
  gdbm
  glibc
  gmp
  graphviz
  libffi
  libxcrypt
  libyaml
  openssl
  readline
  rust
  tk
  zlib
)
checkdepends=(
  procps-ng
)
options=('!emptydirs')
source=(
  "https://cache.ruby-lang.org/pub/ruby/${pkgver%.*}/ruby-${pkgver}.tar.xz"
)

# Parabola: Mundane packaging considerations.
arch+=(armv7h i686)
pkgrel+=.parabola1

# Parabola: Disable the 'ruby-debug' package, that name is for the
# 'debug' gem, not detatched debugging symbols for /bin/ruby.  Arch
# doesn't need to do this because Arch doesn't ship -debug packages.
# We say !strip rather than !debug because we do want the debugging
# symbols to be available to those who want them.
options+=('!strip')

# Parabola: Fix check() with networking disabled.
#
# Per the comment in check(), we need to satisfy "rspec:~> 3".  Beyond
# that, these are simply the most recent versions according to
# clicking around on rubygems.org.
source+=("https://rubygems.org/downloads/rspec-3.13.2.gem"
         "https://rubygems.org/downloads/rspec-core-3.13.6.gem" # for rspec
         "https://rubygems.org/downloads/rspec-expectations-3.13.5.gem" # for rspec
         "https://rubygems.org/downloads/rspec-mocks-3.13.8.gem" # for rspec
         "https://rubygems.org/downloads/rspec-support-3.13.7.gem" # for rspec-core, rspec-expectations, rspec-mocks
         "https://rubygems.org/downloads/diff-lcs-1.6.2.gem" # for rspec-expectations, rspec-mocks
)

# Parabola: disable default TPPM
source+=(0001-FSDG-rubygems-Have-default_sources-be-empty.patch)

# After updating pkgver, run `./PARABOLA-HACKING/updvars` to update
# the `*sums` and `_*_gem` variables.
sha512sums=('b6289654685c2d381d15123cf07a131fd088edf13a5336966af5a2e8fad9adda42d14caa7bb0998331831af71e35c546091db55c82089e89b9508603ff5f92d6'
            'd666a747178cf1e2daa880f069cc501b71e7c55cc72aa4c7043938a8f5b79fa49f9906f2f7d29dcaef7cd82df08d32649190e51203e4dab48ea1194b420dc5b3'
            '8456a4505bd990a968630da475fd5222a15e0641db26d0efbf63e5d1d8edea702c7982297c4fd7e647167b7204127e4dd6d49480a9556faa65f06e0ce8ad3513'
            '4fde5ddae1c723bb3f25c65db61ec959146b1b92a08ddf09d4caf1164d25fd67e4d6d7a73b576fdb48477a3ee54763a8a2d3b93ea573ba6962d65ae80379cd03'
            '0da3eaca9ec1991d3dd8567c5375e523f31ebef8111facf9a43ba7a938f3184751518817dd01e0e88e990e0e09be8c041fdc8a621b160eab0336f675dac589e9'
            '70b8e900267285b37ee4082f2bca599cc93d614b79f0e0654f565ca9b13ad52b048adbec6cbc66979096f09f473a6eb64b71f5584d5a96710b1d082ee6f6caeb'
            '0cfaae5b02784dfb17906afe3f044aa58cedb866b4d07229fec8c0859d78c03d24eaba37a951d1a0cc85df63a4132c46a600953ff3a80cd0830ad07e687f8894'
            '490b947841884517ca9c331c0f286b8475d09206781e09f81cbe2874effff2958f6e13d8e73148b7bd13cb8e6eb6fccf78518d5c395b4683469ca65c76715aa1')
b2sums=('e40144cea391c32a4ce1e6c576884dd9ca3a31398b0110bb67e96eca90dc1d8cb0376269e691a1b48b06bbbb23b0137e67bd05ae4aeccb5c26d163fbce5cec55'
        'b50031ac41037cab9097c54e23e8bc554bd88e52dcc436367818db17c6ddf83ce32f6aa256cbd16a6d3ef551c672a0fcfda2e0119dccc3f37e243fefeaed677c'
        '0a2b83aac5c2480408fcb76aa040ea22c96fe7a0e077f0e638e97f14d919d8bcac57072a71fdf8ba94757dcbd18295f75fb6f396038b703c866756d8ec4d6f0c'
        '02c1de110b4b3d30f99a18893cd402cb863f6464feaf5e143f52884aec0453c7839d2976e1f70a200737e65a6aeb2502340bdbbb45f333c5fd992972810965a4'
        '8fee05c83fb621662e9a6a6eb65fccc5c75cee6d0ecd17dff6ddc8284ce9fa9d8a3e3d35de461aaef40d7ebf120d608cc9427aaabc58ae4620a551d14d4f77d9'
        '4aff7af5b27f91285eb7428f16256cd581eb4d4277f21eb6f5f8728308e161ea3b3937ac7fde4a0e2a2254f687bfb73580b90e32309b4b6392e3f20514ebabbd'
        'ffdc160b0034e53371d08ffa36baae341f93640c644a418bcd331bcf8c6c0d8cfa1b2421b899c5897e2083a4829437d58cfd051ae7e8d6674a444f61c87f5f52'
        '5e5d4ceb6f7688742ae396149430af308d73ac6744017847d67030cb40c78d2e5d6d156ecd377b2e3bcb7c6d65da8b50a92c17165be2d7a80762e313189fffa7')
_bundled_gems=(
  abbrev=0.1.2
  base64=0.2.0
  bigdecimal=3.1.8
  csv=3.3.2
  debug=1.11.0
  drb=2.2.1
  getoptlong=0.2.1
  matrix=0.4.2
  minitest=5.25.4
  mutex_m=0.3.0
  net-ftp=0.3.8
  net-imap=0.5.8
  net-pop=0.1.2
  net-smtp=0.5.1
  nkf=0.2.0
  observer=0.1.2
  power_assert=2.0.5
  prime=0.1.3
  racc=1.8.1
  rake=13.2.1
  rbs=3.8.0
  repl_type_completor=0.1.9
  resolv-replace=0.1.1
  rexml=3.4.4
  rinda=0.2.0
  rss=0.3.1
  syslog=0.2.0
  test-unit=3.6.7
  typeprof=0.30.1
)
_default_gems=(
  benchmark
  cgi
  date
  delegate
  did_you_mean
  digest
  english
  error_highlight
  etc
  fcntl
  fiddle
  fileutils
  find
  forwardable
  io-console
  io-nonblock
  io-wait
  ipaddr
  json
  logger
  net-http
  net-protocol
  open-uri
  open3
  openssl
  optparse
  ostruct
  pathname
  pp
  prettyprint
  prism
  pstore
  psych
  readline
  reline
  resolv
  ruby2_keywords
  securerandom
  set
  shellwords
  singleton
  stringio
  strscan
  syntax_suggest
  tempfile
  time
  timeout
  tmpdir
  tsort
  un
  uri
  weakref
  yaml
  zlib
)
_default_tool_gems=(
  bundler
  erb
  irb
  rdoc
  rubygems
)

prepare() {
  cd "ruby-${pkgver}"

  # Parabola: disable default TPPM
  patch -Np1 -i ../0001-FSDG-rubygems-Have-default_sources-be-empty.patch

  autoreconf -fiv
}

build() {
  cd "ruby-${pkgver}"

  # this uses malloc_usable_size, which is incompatible with fortification level 3
  export CFLAGS="${CFLAGS/_FORTIFY_SOURCE=3/_FORTIFY_SOURCE=2}"
  export CXXFLAGS="${CXXFLAGS/_FORTIFY_SOURCE=3/_FORTIFY_SOURCE=2}"

  ./configure \
    --prefix=/usr \
    --sysconfdir=/etc \
    --localstatedir=/var \
    --sharedstatedir=/var/lib \
    --libexecdir=/usr/lib/ruby \
    --enable-shared \
    --disable-rpath \
    --with-dbm-type=gdbm_compat

  make
  make rdoc capi
}

check() {
  cd "ruby-${pkgver}"

  # this uses malloc_usable_size, which is incompatible with fortification level 3
  export CFLAGS="${CFLAGS/_FORTIFY_SOURCE=3/_FORTIFY_SOURCE=2}"
  export CXXFLAGS="${CXXFLAGS/_FORTIFY_SOURCE=3/_FORTIFY_SOURCE=2}"

  # Parabola: Fix check() with networking disabled.
  #
  # Preempt the `gem install` that `make test-syntax-suggest-prepare`
  # will do:
  #
  #     yes-test-syntax-suggest-prepare: yes-test-syntax-suggest-precheck
  #         $(XRUBY) -C "$(srcdir)" bin/gem install --no-document \
  #             --install-dir .bundle --conservative "rspec:~> 3"
  local xruby=(./miniruby tool/runruby.rb --extout=.ext --)
  ln -s ../*.gem .
  "${xruby[@]}" bin/gem install --no-document \
    --install-dir .bundle --conservative --local rspec-3.*.gem
  rm *.gem
  # Disable tests in the `make test-spec` suite that require
  # networking:
  MSPECOPT+=" --exclude='connect fails with timeout'"
  export MSPECOPT

  # Parabola: Disable checks that fail in cross-arch chroots.
  # These are bugs/limitations in `qemu-arm-static`.
  if grep -q [q]emu /proc/$$/cmdline; then
    # The `make test-all` suite.
    echo >>test/.excludes/TestIO.rb          "exclude :test_io_select_with_many_files     , 'qemu-arm-static SIGABRTs instead of returning EINVAL'"
    echo >>test/.excludes/TestProcess.rb     "exclude :test_daemon_no_threads             , 'qemu-arm-static adds extra threads'"
    echo >>test/.excludes/TestSignal.rb      "exclude :test_ignored_interrupt             , 'qemu-arm-static does signal handlers wrong'"
    echo >>test/.excludes/TestRubyOptions.rb "exclude /test_set(proctitle|_program_name)/ , 'qemu-arm-static does not support adjusting argv at runtime'"
    echo >>test/.excludes/TestRubyOptions.rb "exclude :test_crash_report                  , 'qemu-arm-static does signal handlers wrong'"
    echo >>test/.excludes/TestRubyOptions.rb "exclude :test_crash_report_script           , 'qemu-arm-static does signal handlers wrong'"
    echo >>test/.excludes/TestRubyOptions.rb "exclude :test_crash_report_executable_path  , 'qemu-arm-static does signal handlers wrong'"
    echo >>test/.excludes/TestRubyOptions.rb "exclude :test_crash_report_script_path      , 'qemu-arm-static does signal handlers wrong'"
    export RUBY_TEST_TIMEOUT_SCALE=10 # emulation is slow, increase timeouts by 10x

    # The `make test-spec` suite.
    # qemu-arm-static does not support adjusting argv at runtime
    MSPECOPT+=" --exclude='Process.setproctitle should set the process title'"
    MSPECOPT+=" --exclude='actually sets the program name'"
    export MSPECOPT

    # The `make test-syntax-suggest` suite.
    # The default timeout is 1s, bump it to 30s because emulation is slow.
    export SYNTAX_SUGGEST_TIMEOUT=30
  fi

  make check
}

_pick() {
  local p="$1" f d; shift
  for f; do
    [[ -e $f ]] || continue
    d="$srcdir/$p/${f#$pkgdir/}"
    mkdir -p "$(dirname "$d")"
    mv "$f" "$d"
    rmdir -p --ignore-fail-on-non-empty "$(dirname "$f")"
  done
}

_list_bins() {
  local gemspec="${1?}"
  # Note that unlike .gemspec files in the sources, installed
  # gemspec files have been normalized, and so are much more
  # regular and easy to parse with simple expressions like this.
  cat "$gemspec" |
    # extract the `...` from `s.executables=[...]` lines
    sed -En 's/^\s*s\.executables\s*=\s*\[([^]]+)\]\s*$/\1/p' |
    # dequote; turn `"bundle".freeze, "bundler".freeze` into `bundle\nbundler`
    sed -e 's/^\s*"//' -e 's/"\.freeze,\s*"/\n/g' -e 's/"\.freeze\s*$//'
}

_pick_gems() {
  local typ="${1?}"
  local gems=("${@:2}")
  local dst="${typ}-gems"

  local gem bins bin
  for gem in "${gems[@]}"; do
    msg2 "removing ${typ} gem ${gem}"

    case "$typ" in
      default)
        if [[ "$gem" == rubygems ]]; then
          # For some reason ruby doesn't ship the rubygems gemspec.
          bins=(gem)
        else
          readarray -t bins < <(_list_bins "${pkgdir}/usr/lib/ruby/gems/${_rubyver}/specifications/default/${gem}"-*.gemspec)
          _pick "$dst" "${pkgdir}/usr/lib/ruby/gems/${_rubyver}/specifications/default/${gem}"-*.gemspec
        fi

        _pick "$dst" "${pkgdir}/usr/lib/ruby/${_rubyver}"/*-linux/"${gem}"
        _pick "$dst" "${pkgdir}/usr/lib/ruby/${_rubyver}/${gem}"*
        ;;
      bundled)
        readarray -t bins < <(_list_bins "${pkgdir}/usr/lib/ruby/gems/${_rubyver}/specifications/${gem}"-*.gemspec)
        _pick "$dst" "${pkgdir}/usr/lib/ruby/gems/${_rubyver}/specifications/${gem}"-*.gemspec

        _pick "$dst" "${pkgdir}/usr/lib/ruby/gems/${_rubyver}/extensions"/*-linux/"${_rubyver}/${gem}"-*
        ;;
    esac
    _pick "$dst" "${pkgdir}/usr/lib/ruby/gems/${_rubyver}/gems/${gem}"-*
    for bin in "${bins[@]}"; do
      _pick "$dst" "${pkgdir}/usr/bin/${bin}"
      _pick "$dst" "${pkgdir}/usr/bin/${bin}.lock"
      _pick "$dst" "${pkgdir}/usr/share/man/man1/${bin}.1"
    done
  done
}

package_ruby() {
  depends=(
    libgcc
    gdbm
    glibc
    gmp
    libffi
    libxcrypt
    libyaml
    openssl
    readline
    zlib
  )
  optdepends=(
    'tk: for Ruby/TK'
    'ruby-docs: Documentation for Ruby'
    'ruby-default-gems: Default gems which are part of Ruby StdLib'
    'ruby-bundled-gems: Bundled gems which are part of Ruby StdLib'
    'ruby-stdlib: Full Ruby StdLib including default gems, bundled gems and tools'
  )
  provides=(
    libruby.so
  )
  replaces=("${_default_gems[@]/#/ruby-}")
  conflicts=("${_default_gems[@]/#/ruby-}")
  provides+=("${_default_gems[@]/#/ruby-}")

  cd "ruby-${pkgver}"

  make DESTDIR="${pkgdir}" install-nodoc

  install --verbose -D --mode=0644 BSDL COPYING --target-directory "${pkgdir}/usr/share/licenses/${pkgname}"
  install --verbose -D --mode=0644 *.md --target-directory "${pkgdir}/usr/share/doc/${pkgname}"

  # remove unrepreducible files
  rm --recursive --verbose \
    "${pkgdir}/usr/lib/ruby/gems/${_rubyver}/cache"

  # remove de-vendored parts
  _pick_gems default "${_default_tool_gems[@]}"
  _pick_gems bundled "${_bundled_gems[@]%=*}"
  # Most of the _default_tool_gems are in optdepends via
  # ruby-default-gems, but some of them need to be non-optional.
  depends+=(
    rubygems
  )
}

package_ruby-docs() {
  pkgdesc='Documentation files for Ruby'

  cd "ruby-${pkgver}"
  make DESTDIR="${pkgdir}" install-doc install-capi
  install --verbose -D --mode=0644 BSDL COPYING --target-directory "${pkgdir}/usr/share/licenses/${pkgname}"
}

package_ruby-bundled-gems() {
  pkgdesc='Depends on optional gems that are installed by default with Ruby'
  replaces=(ruby-bundledgems)
  conflicts=(ruby-bundledgems)
  depends=($(printf '%s\n' "${_bundled_gems[@]}" | sed -e 's/^/ruby-/' -e 's/=/>=/'))

  cd "ruby-${pkgver}"
  install --verbose -D --mode=0644 BSDL COPYING --target-directory "${pkgdir}/usr/share/licenses/${pkgname}"
}

package_ruby-bundled-gems-bootstrap() {
  pkgdesc='The versions of ruby-bundled-gems that are distributed with the Ruby source release'
  depends=("ruby=${pkgver}")
  provides=("${_bundled_gems[@]/#/ruby-}")
  conflicts=($(printf '%s\n' "${_bundled_gems[@]}" | sed -e 's/^/ruby-/' -e 's/=.*//'))

  mv -v "${srcdir}/bundled-gems"/* "$pkgdir"

  cd "ruby-${pkgver}"
  install --verbose -D --mode=0644 BSDL COPYING --target-directory "${pkgdir}/usr/share/licenses/${pkgname}"
}

package_ruby-default-gems() {
  pkgdesc='Depends on gems that are a part of Ruby and can always be required directly'
  # We only need to depend on default gems that we've de-vendored, not all of the default gems.
  depends=("${_default_tool_gems[@]/#/ruby-}")

  cd "ruby-${pkgver}"
  install --verbose -D --mode=0644 BSDL COPYING --target-directory "${pkgdir}/usr/share/licenses/${pkgname}"
}

package_ruby-default-gems-bootstrap() {
  pkgdesc='The versions of ruby-default-gems that are distributed with the Ruby source release'
  depends=("ruby=${pkgver}")
  provides=("${_default_tool_gems[@]/#/ruby-}" rubygems)
  conflicts=("${_default_tool_gems[@]/#/ruby-}" rubygems)

  # Parabola: ruby-bootstraplib was added in ruby-3.0.6-1.parabola2
  # (2024-05-29) and removed in ruby-3.2.5-1.parabola1 (2024-08-31).
  replaces+=(ruby-bootstraplib)
  conflicts+=(ruby-bootstraplib)

  mv -v "${srcdir}/default-gems"/* "$pkgdir"

  cd "ruby-${pkgver}"
  install --verbose -D --mode=0644 BSDL COPYING --target-directory "${pkgdir}/usr/share/licenses/${pkgname}"
}

package_ruby-stdlib() {
  pkgdesc='Depends on the full Ruby standard library; both default gems and bundled gems'
  depends=(ruby-default-gems ruby-bundled-gems)

  cd "ruby-${pkgver}"
  install --verbose -D --mode=0644 BSDL COPYING --target-directory "${pkgdir}/usr/share/licenses/${pkgname}"
}

# vim: tabstop=2 shiftwidth=2 expandtab:
