2020-04-24 23:36:52 +00:00
{ stdenv , buildPackages , lib
, fetchurl , fetchpatch , fetchFromSavannah , fetchFromGitHub
2022-09-14 18:05:37 +00:00
, zlib , gdbm , ncurses , readline , groff , libyaml , libffi , jemalloc , autoreconfHook , bison
2020-04-24 23:36:52 +00:00
, autoconf , libiconv , libobjc , libunwind , Foundation
2023-05-24 13:37:59 +00:00
, buildEnv , bundler , bundix , cargo , rustPlatform , rustc
2023-03-15 16:39:30 +00:00
, makeBinaryWrapper , buildRubyGem , defaultGemConfig , removeReferencesTo
2022-09-14 18:05:37 +00:00
, openssl , openssl_1_1
2023-03-27 19:17:25 +00:00
, linuxPackages , libsystemtap
2020-04-24 23:36:52 +00:00
} @ args :
let
op = lib . optional ;
ops = lib . optionals ;
opString = lib . optionalString ;
config = import ./config.nix { inherit fetchFromSavannah ; } ;
2021-07-17 21:14:59 +00:00
rubygems = import ./rubygems { inherit stdenv lib fetchurl ; } ;
2020-04-24 23:36:52 +00:00
2023-05-24 13:37:59 +00:00
openssl3Gem = fetchFromGitHub {
owner = " r u b y " ;
repo = " o p e n s s l " ;
rev = " v 3 . 0 . 2 " ;
hash = " s h a 2 5 6 - K h u K R P 1 J k M J v 7 C a g G R Q 0 K K G O d 5 O h 0 F P 0 f b j 0 V Z 4 u t G o = " ;
} ;
2020-04-24 23:36:52 +00:00
# Contains the ruby version heuristics
rubyVersion = import ./ruby-version.nix { inherit lib ; } ;
2023-03-27 19:17:25 +00:00
generic = { version , sha256 , cargoSha256 ? null }: let
2020-04-24 23:36:52 +00:00
ver = version ;
2021-03-19 17:17:44 +00:00
atLeast30 = lib . versionAtLeast ver . majMin " 3 . 0 " ;
2023-03-27 19:17:25 +00:00
atLeast31 = lib . versionAtLeast ver . majMin " 3 . 1 " ;
atLeast32 = lib . versionAtLeast ver . majMin " 3 . 2 " ;
2023-05-24 13:37:59 +00:00
# https://github.com/ruby/ruby/blob/v3_2_2/yjit.h#L21
yjitSupported = atLeast32 && ( stdenv . hostPlatform . isx86_64 || ( ! stdenv . hostPlatform . isWindows && stdenv . hostPlatform . isAarch64 ) ) ;
2020-04-24 23:36:52 +00:00
self = lib . makeOverridable (
{ stdenv , buildPackages , lib
, fetchurl , fetchpatch , fetchFromSavannah , fetchFromGitHub
, rubygemsSupport ? true
, zlib , zlibSupport ? true
2022-09-14 18:05:37 +00:00
, openssl , openssl_1_1 , opensslSupport ? true
2020-04-24 23:36:52 +00:00
, gdbm , gdbmSupport ? true
, ncurses , readline , cursesSupport ? true
, groff , docSupport ? true
, libyaml , yamlSupport ? true
, libffi , fiddleSupport ? true
2021-02-17 17:02:09 +00:00
, jemalloc , jemallocSupport ? false
2023-03-27 19:17:25 +00:00
, linuxPackages , systemtap ? linuxPackages . systemtap , libsystemtap , dtraceSupport ? false
2020-11-19 00:13:47 +00:00
# By default, ruby has 3 observed references to stdenv.cc:
#
# - If you run:
# ruby -e "puts RbConfig::CONFIG['configure_args']"
# - In:
2021-03-15 08:37:03 +00:00
# $out/${passthru.libPath}/${stdenv.hostPlatform.system}/rbconfig.rb
2020-11-19 00:13:47 +00:00
# Or (usually):
# $(nix-build -A ruby)/lib/ruby/2.6.0/x86_64-linux/rbconfig.rb
# - In $out/lib/libruby.so and/or $out/lib/libruby.dylib
2023-03-27 19:17:25 +00:00
, removeReferencesTo , jitSupport ? yjitSupport
2023-05-24 13:37:59 +00:00
, cargo , rustPlatform , rustc , yjitSupport ? yjitSupported
2020-04-24 23:36:52 +00:00
, autoreconfHook , bison , autoconf
, buildEnv , bundler , bundix
, libiconv , libobjc , libunwind , Foundation
2023-03-15 16:39:30 +00:00
, makeBinaryWrapper , buildRubyGem , defaultGemConfig
2023-04-29 16:46:19 +00:00
, baseRuby ? buildPackages . ruby . override {
2022-01-13 20:06:32 +00:00
docSupport = false ;
rubygemsSupport = false ;
}
2023-03-27 19:17:25 +00:00
, useBaseRuby ? stdenv . hostPlatform != stdenv . buildPlatform
2020-04-24 23:36:52 +00:00
} :
stdenv . mkDerivation rec {
pname = " r u b y " ;
inherit version ;
2022-04-27 09:35:20 +00:00
src = fetchurl {
2020-04-24 23:36:52 +00:00
url = " h t t p s : / / c a c h e . r u b y - l a n g . o r g / p u b / r u b y / ${ ver . majMin } / r u b y - ${ ver } . t a r . g z " ;
2022-04-27 09:35:20 +00:00
inherit sha256 ;
2020-04-24 23:36:52 +00:00
} ;
# Have `configure' avoid `/usr/bin/nroff' in non-chroot builds.
NROFF = if docSupport then " ${ groff } / b i n / n r o f f " else null ;
outputs = [ " o u t " ] ++ lib . optional docSupport " d e v d o c " ;
2023-03-27 19:17:25 +00:00
strictDeps = true ;
2020-04-24 23:36:52 +00:00
nativeBuildInputs = [ autoreconfHook bison ]
++ ( op docSupport groff )
2023-03-27 19:17:25 +00:00
++ ( ops ( dtraceSupport && stdenv . isLinux ) [ systemtap libsystemtap ] )
2023-05-24 13:37:59 +00:00
++ ops yjitSupport [ rustPlatform . cargoSetupHook cargo rustc ]
2022-01-13 20:06:32 +00:00
++ op useBaseRuby baseRuby ;
2020-04-24 23:36:52 +00:00
buildInputs = [ autoconf ]
++ ( op fiddleSupport libffi )
++ ( ops cursesSupport [ ncurses readline ] )
++ ( op zlibSupport zlib )
2023-05-24 13:37:59 +00:00
++ ( op ( atLeast30 && opensslSupport ) openssl )
++ ( op ( ! atLeast30 && opensslSupport ) openssl_1_1 )
2020-04-24 23:36:52 +00:00
++ ( op gdbmSupport gdbm )
++ ( op yamlSupport libyaml )
# Looks like ruby fails to build on darwin without readline even if curses
# support is not enabled, so add readline to the build inputs if curses
# support is disabled (if it's enabled, we already have it) and we're
# running on darwin
++ op ( ! cursesSupport && stdenv . isDarwin ) readline
++ ops stdenv . isDarwin [ libiconv libobjc libunwind Foundation ] ;
2022-06-16 17:23:12 +00:00
propagatedBuildInputs = op jemallocSupport jemalloc ;
2020-04-24 23:36:52 +00:00
enableParallelBuilding = true ;
2023-03-27 19:17:25 +00:00
# /build/ruby-2.7.7/lib/fileutils.rb:882:in `chmod':
# No such file or directory @ apply2files - ...-ruby-2.7.7-devdoc/share/ri/2.7.0/system/ARGF/inspect-i.ri (Errno::ENOENT)
# make: *** [uncommon.mk:373: do-install-all] Error 1
enableParallelInstalling = false ;
patches = op ( lib . versionOlder ver . majMin " 3 . 1 " ) ./do-not-regenerate-revision.h.patch
++ op ( atLeast30 && useBaseRuby ) (
if atLeast32 then ./do-not-update-gems-baseruby-3.2.patch
else ./do-not-update-gems-baseruby.patch
)
2023-03-04 12:14:45 +00:00
++ ops ( ver . majMin == " 3 . 0 " ) [
# Ruby 3.0 adds `-fdeclspec` to $CC instead of $CFLAGS. Fixed in later versions.
( fetchpatch {
url = " h t t p s : / / g i t h u b . c o m / r u b y / r u b y / c o m m i t / 0 a c c 0 5 c a f 7 5 1 8 c d 0 d 6 3 a b 0 2 b f a 0 3 6 4 5 5 a d d 0 2 3 4 6 . p a t c h " ;
sha256 = " s h a 2 5 6 - 4 3 h I 9 L 6 b X f e u j g m g K F V m i W h g 7 O X v s h P C C t Q 4 T x q K 1 z k = " ;
} )
2023-05-24 13:37:59 +00:00
]
2022-04-27 09:35:20 +00:00
++ ops ( ! atLeast30 && rubygemsSupport ) [
# We upgrade rubygems to a version that isn't compatible with the
# ruby 2.7 installer. Backport the upstream fix.
./rbinstall-new-rubygems-compat.patch
# Ruby prior to 3.0 has a bug the installer (tools/rbinstall.rb) but
# the resulting error was swallowed. Newer rubygems no longer swallows
# this error. We upgrade rubygems when rubygemsSupport is enabled, so
# we have to fix this bug to prevent the install step from failing.
# See https://github.com/ruby/ruby/pull/2930
2021-05-20 23:08:51 +00:00
( fetchpatch {
url = " h t t p s : / / g i t h u b . c o m / r u b y / r u b y / c o m m i t / 2 6 1 d 8 d d 2 0 a f d 2 6 f e b 0 5 f 0 0 a 5 6 0 a b d 9 9 2 2 7 2 6 9 c 1 c . p a t c h " ;
sha256 = " 0 w r i i 2 5 c x c z 2 v 8 b g k r f 7 i b c a n j l x w c l z h a y i n 5 7 8 b f 0 q y d x d m 9 q y " ;
2022-04-27 09:35:20 +00:00
} )
2023-03-27 19:17:25 +00:00
]
++ ops atLeast31 [
# When using a baseruby, ruby always sets "libdir" to the build
# directory, which nix rejects due to a reference in to /build/ in
# the final product. Removing this reference doesn't seem to break
# anything and fixes cross compliation.
./dont-refer-to-build-dir.patch
2022-04-27 09:35:20 +00:00
] ;
2020-04-24 23:36:52 +00:00
2023-03-27 19:17:25 +00:00
cargoRoot = opString yjitSupport " y j i t " ;
cargoDeps = if yjitSupport then rustPlatform . fetchCargoTarball {
inherit src ;
sourceRoot = " ${ pname } - ${ version } / ${ cargoRoot } " ;
sha256 = cargoSha256 ;
} else null ;
2020-04-24 23:36:52 +00:00
postUnpack = opString rubygemsSupport ''
rm - rf $ sourceRoot / { lib , test } /rubygems *
cp - r $ { rubygems } /lib/rubygems * $ sourceRoot/lib
cp - r $ { rubygems } /test/rubygems $ sourceRoot/test
2023-05-24 13:37:59 +00:00
'' + o p S t r i n g ( v e r . m a j M i n = = " 3 . 0 " & & o p e n s s l S u p p o r t ) ''
# Replace the Gem by a OpenSSL3-compatible one.
echo " H o t p a t c h i n g t h e O p e n S S L g e m w i t h a 3 . x s e r i e s f o r O p e n S S L 3 s u p p o r t . . . "
cp - vr $ { openssl3Gem } /ext/openssl $ sourceRoot/ext /
cp - vr $ { openssl3Gem } /lib / $ sourceRoot/ext/openssl /
cp - vr $ { openssl3Gem } / { History . md , openssl . gemspec } $ sourceRoot/ext/openssl /
2020-04-24 23:36:52 +00:00
'' ;
postPatch = ''
sed - i configure . ac - e ' /config.guess/d '
cp - - remove-destination $ { config } /config.guess tool /
cp - - remove-destination $ { config } /config.sub tool /
2021-03-19 17:17:44 +00:00
'' + o p S t r i n g ( ! a t L e a s t 3 0 ) ''
2020-11-12 09:05:59 +00:00
# Make the build reproducible for ruby <= 2.7
# See https://github.com/ruby/io-console/commit/679a941d05d869f5e575730f6581c027203b7b26#diff-d8422f096931c58d4463e2489f62a228b0f24f0492950ba88c8c89a0d741cfe6
sed - i ext/io/console/io-console.gemspec - e ' /s \ .date/d '
2020-04-24 23:36:52 +00:00
'' ;
2022-01-13 20:06:32 +00:00
configureFlags = [
( lib . enableFeature ( ! stdenv . hostPlatform . isStatic ) " s h a r e d " )
( lib . enableFeature true " p t h r e a d " )
( lib . withFeatureAs true " s o n a m e " " r u b y - ${ version } " )
( lib . withFeatureAs useBaseRuby " b a s e r u b y " " ${ baseRuby } / b i n / r u b y " )
2023-03-27 19:17:25 +00:00
( lib . enableFeature dtraceSupport " d t r a c e " )
2022-01-13 20:06:32 +00:00
( lib . enableFeature jitSupport " j i t - s u p p o r t " )
2023-03-27 19:17:25 +00:00
( lib . enableFeature yjitSupport " y j i t " )
2022-01-13 20:06:32 +00:00
( lib . enableFeature docSupport " i n s t a l l - d o c " )
( lib . withFeature jemallocSupport " j e m a l l o c " )
( lib . withFeatureAs docSupport " r i d i r " " ${ placeholder " d e v d o c " } / s h a r e / r i " )
2022-07-14 12:49:19 +00:00
# ruby enables -O3 for gcc, however our compiler hardening wrapper
# overrides that by enabling `-O2` which is the minimum optimization
# needed for `_FORTIFY_SOURCE`.
] ++ lib . optional stdenv . cc . isGNU " C F L A G S = - O 3 " ++ [
2022-01-13 20:06:32 +00:00
] ++ ops stdenv . isDarwin [
# on darwin, we have /usr/include/tk.h -- so the configure script detects
# that tk is installed
" - - w i t h - o u t - e x t = t k "
# on yosemite, "generating encdb.h" will hang for a very long time without this flag
" - - w i t h - s e t j m p - t y p e = s e t j m p "
] ;
2020-04-24 23:36:52 +00:00
preConfigure = opString docSupport ''
2021-03-19 17:17:44 +00:00
# rdoc creates XDG_DATA_DIR (defaulting to $HOME/.local/share) even if
# it's not going to be used.
export HOME = $ TMPDIR
2020-04-24 23:36:52 +00:00
'' ;
# fails with "16993 tests, 2229489 assertions, 105 failures, 14 errors, 89 skips"
# mostly TZ- and patch-related tests
# TZ- failures are caused by nix sandboxing, I didn't investigate others
doCheck = false ;
preInstall = ''
# Ruby installs gems here itself now.
mkdir - pv " $ o u t / ${ passthru . gemPath } "
export GEM_HOME = " $ o u t / ${ passthru . gemPath } "
'' ;
2021-02-05 17:12:51 +00:00
installFlags = lib . optional docSupport " i n s t a l l - d o c " ;
2020-04-24 23:36:52 +00:00
# Bundler tries to create this directory
postInstall = ''
2021-05-20 23:08:51 +00:00
rbConfig = $ ( find $ out/lib/ruby - name rbconfig . rb )
2022-02-10 20:34:41 +00:00
# Remove references to the build environment from the closure
sed - i ' / ^ CONFIG \ [ " \( B A S E R U B Y \| S H E L L \| G R E P \| E G R E P \| M K D I R _ P \| M A K E D I R S \| I N S T A L L \) " \ ] /d ' $ rbConfig
2020-04-24 23:36:52 +00:00
# Remove unnecessary groff reference from runtime closure, since it's big
2021-05-20 23:08:51 +00:00
sed - i ' /NROFF/d ' $ rbConfig
2020-04-24 23:36:52 +00:00
$ {
2020-11-19 00:13:47 +00:00
lib . optionalString ( ! jitSupport ) ''
2020-04-24 23:36:52 +00:00
# Get rid of the CC runtime dependency
$ { removeReferencesTo } /bin/remove-references-to \
- t $ { stdenv . cc } \
$ out/lib/libruby *
2020-11-19 00:13:47 +00:00
$ { removeReferencesTo } /bin/remove-references-to \
- t $ { stdenv . cc } \
2021-05-20 23:08:51 +00:00
$ rbConfig
sed - i ' /CC_VERSION_MESSAGE/d ' $ rbConfig
2020-04-24 23:36:52 +00:00
''
}
2023-01-20 10:41:00 +00:00
# Allow to override compiler. This is important for cross compiling as
# we need to set a compiler that is different from the build one.
2023-03-04 12:14:45 +00:00
sed - i ' s/CONFIG \ [ " C C " \ ] = " \( . * \) " /CONFIG [ " C C " ] = if ENV [ " C C " ] . nil ? || ENV [ " C C " ] . empty ? then " \1 " else ENV [ " C C " ] end / ' " $ r b C o n f i g "
2023-01-20 10:41:00 +00:00
2022-04-27 09:35:20 +00:00
# Remove unnecessary external intermediate files created by gems
2022-12-17 10:02:37 +00:00
extMakefiles = $ ( find $ out / $ { passthru . gemPath } - name Makefile )
2022-04-27 09:35:20 +00:00
for makefile in $ extMakefiles ; do
make - C " $ ( d i r n a m e " $ makefile " ) " distclean
done
2023-03-27 19:17:25 +00:00
find " $ o u t / ${ passthru . gemPath } " \ ( - name gem_make . out - o - name mkmf . log \ ) - delete
2020-04-24 23:36:52 +00:00
# Bundler tries to create this directory
mkdir - p $ out/nix-support
cat > $ out/nix-support/setup-hook < < EOF
addGemPath ( ) {
addToSearchPath GEM_PATH \ $ 1 / $ { passthru . gemPath }
}
addRubyLibPath ( ) {
addToSearchPath RUBYLIB \ $ 1/lib/ruby/site_ruby
addToSearchPath RUBYLIB \ $ 1/lib/ruby/site_ruby / $ { ver . libDir }
2021-03-15 08:37:03 +00:00
addToSearchPath RUBYLIB \ $ 1/lib/ruby/site_ruby / $ { ver . libDir } / $ { stdenv . hostPlatform . system }
2020-04-24 23:36:52 +00:00
}
addEnvHooks " $ h o s t O f f s e t " addGemPath
addEnvHooks " $ h o s t O f f s e t " addRubyLibPath
EOF
'' + o p S t r i n g d o c S u p p o r t ''
# Prevent the docs from being included in the closure
sed - i " s | \$ ( D E S T D I R ) $ d e v d o c | \$ ( d a t a r o o t d i r ) / \$ ( R I _ B A S E _ N A M E ) | " $ rbConfig
sed - i " s | ' - - w i t h - r i d i r = $ d e v d o c / s h a r e / r i ' | | " $ rbConfig
# Add rbconfig shim so ri can find docs
mkdir - p $ devdoc/lib/ruby/site_ruby
cp $ { ./rbconfig.rb } $ devdoc/lib/ruby/site_ruby/rbconfig.rb
2022-01-13 20:06:32 +00:00
'' + o p S t r i n g u s e B a s e R u b y ''
2020-04-24 23:36:52 +00:00
# Prevent the baseruby from being included in the closure.
2022-01-13 20:06:32 +00:00
$ { removeReferencesTo } /bin/remove-references-to \
- t $ { baseRuby } \
$ rbConfig $ out/lib/libruby *
2020-04-24 23:36:52 +00:00
'' ;
2023-03-04 12:14:45 +00:00
installCheckPhase = ''
overriden_cc = $ ( CC = foo $ out/bin/ruby - rrbconfig - e ' puts RbConfig::CONFIG [ " C C " ] ' )
if [ [ " $ o v e r r i d e n _ c c " != " f o o " ] ] ; then
echo " C C c a n n o t b e o v e r w r i t t e n : $ o v e r r i d e n _ c c ! = f o o " > & 2
false
fi
fallback_cc = $ ( unset CC ; $ out/bin/ruby - rrbconfig - e ' puts RbConfig::CONFIG [ " C C " ] ' )
if [ [ " $ f a l l b a c k _ c c " != " $ C C " ] ] ; then
echo " C C = ' $ f a l l b a c k _ c c ' s h o u l d b e ' $ C C ' b y d e f a u l t " > & 2
false
fi
'' ;
doInstallCheck = true ;
2022-01-13 20:06:32 +00:00
disallowedRequisites = op ( ! jitSupport ) stdenv . cc . cc
++ op useBaseRuby baseRuby ;
2020-11-21 19:51:51 +00:00
2021-02-05 17:12:51 +00:00
meta = with lib ; {
2022-09-09 14:08:57 +00:00
description = " A n o b j e c t - o r i e n t e d l a n g u a g e f o r q u i c k a n d e a s y p r o g r a m m i n g " ;
homepage = " h t t p s : / / w w w . r u b y - l a n g . o r g / " ;
2020-04-24 23:36:52 +00:00
license = licenses . ruby ;
2020-10-07 09:15:18 +00:00
maintainers = with maintainers ; [ vrthra manveru marsam ] ;
2020-04-24 23:36:52 +00:00
platforms = platforms . all ;
2023-05-24 13:37:59 +00:00
knownVulnerabilities = op ( lib . versionOlder ver . majMin " 3 . 0 " ) " T h i s R u b y r e l e a s e h a s r e a c h e d i t s e n d o f l i f e . S e e h t t p s : / / w w w . r u b y - l a n g . o r g / e n / d o w n l o a d s / b r a n c h e s / . " ;
2020-04-24 23:36:52 +00:00
} ;
passthru = rec {
version = ver ;
rubyEngine = " r u b y " ;
libPath = " l i b / ${ rubyEngine } / ${ ver . libDir } " ;
gemPath = " l i b / ${ rubyEngine } / g e m s / ${ ver . libDir } " ;
devEnv = import ./dev.nix {
inherit buildEnv bundler bundix ;
ruby = self ;
} ;
2023-03-27 19:17:25 +00:00
inherit rubygems ;
2020-04-24 23:36:52 +00:00
inherit ( import ../../ruby-modules/with-packages {
2023-03-15 16:39:30 +00:00
inherit lib stdenv makeBinaryWrapper buildRubyGem buildEnv ;
2020-04-24 23:36:52 +00:00
gemConfig = defaultGemConfig ;
ruby = self ;
2023-01-11 07:51:40 +00:00
} ) withPackages buildGems gems ;
2020-04-24 23:36:52 +00:00
2022-01-13 20:06:32 +00:00
} // lib . optionalAttrs useBaseRuby {
inherit baseRuby ;
2020-04-24 23:36:52 +00:00
} ;
}
) args ; in self ;
in {
2022-07-14 12:49:19 +00:00
mkRubyVersion = rubyVersion ;
mkRuby = generic ;
2020-04-24 23:36:52 +00:00
ruby_2_7 = generic {
2023-04-12 12:48:02 +00:00
version = rubyVersion " 2 " " 7 " " 8 " " " ;
sha256 = " s h a 2 5 6 - w t q 2 P L y P K g V S Y Q i t Q Z 7 6 Y 6 Z + 1 A d N u 8 + f w r H K Z k y 0 W 6 A = " ;
2020-04-24 23:36:52 +00:00
} ;
2021-03-19 17:17:44 +00:00
ruby_3_0 = generic {
2023-04-12 12:48:02 +00:00
version = rubyVersion " 3 " " 0 " " 6 " " " ;
sha256 = " s h a 2 5 6 - b m y 9 S Q A w 1 5 E M D / I O 3 v q 0 K U 3 8 0 Q R v D 4 9 H 9 4 t Z e Y e s a D 4 = " ;
2021-03-19 17:17:44 +00:00
} ;
2022-01-13 20:06:32 +00:00
ruby_3_1 = generic {
2023-04-12 12:48:02 +00:00
version = rubyVersion " 3 " " 1 " " 4 " " " ;
sha256 = " s h a 2 5 6 - o 9 V Y e a D f q x 1 x Q f 3 x D S K g f b + O X N x E F d o b 3 g Y S f V z D x 7 Y = " ;
2023-03-27 19:17:25 +00:00
} ;
ruby_3_2 = generic {
2023-04-12 12:48:02 +00:00
version = rubyVersion " 3 " " 2 " " 2 " " " ;
sha256 = " s h a 2 5 6 - l s V 1 W I c a Z 0 j e W 8 n y d O k / S 1 q t B s 2 P N 7 7 6 D o 2 U 5 7 i k I 7 w = " ;
2023-03-27 19:17:25 +00:00
cargoSha256 = " s h a 2 5 6 - 6 d u 7 R J o 0 D H + e Y M O o h 3 L 3 1 F 3 a q f R 5 + i G 1 i K a u S V 1 u N c Q = " ;
2022-01-13 20:06:32 +00:00
} ;
2020-04-24 23:36:52 +00:00
}