# -*- coding: utf-8; mode: tcl; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- vim:fenc=utf-8:ft=tcl:et:sw=4:ts=4:sts=4

PortSystem              1.0

name                    mysql-innovation
version                 26.7.0

categories              databases

homepage                https://dev.mysql.com

maintainers             {gmail.com:herby.gillot @herbygillot} \
                        openmaintainer

# Set revision_client and revision_server to 0 on version bump.
set revision_client     0
set revision_server     0

set name_mysql          ${name}
set version_branch      [join [lrange [split ${version} .] 0 1] .]

# Oracle has not yet published supported platforms for 26.7; for 9.7 it listed
# macOS 14 and 15, arm64 only. This floor is six majors lower, inherited from
# mysql9 on the strength of a shared codebase: all four patches below apply to
# 26.7.0 unchanged, and the build shape is otherwise identical. The 10.14
# evidence behind it is 9.7.2's rather than this release's, which suits a track
# whose releases are superseded quarterly.
platforms               {darwin >= 17}

if {$subport eq $name} {
    PortGroup           muniversal                  1.0
    PortGroup           cmake                       1.1
    PortGroup           select                      1.0
    PortGroup           openssl                     1.0
    PortGroup           legacysupport               1.1

    description         Multithreaded SQL database server, Innovation release
    long_description    MySQL is an open-source, multi-threaded SQL database. \
                        This port follows MySQL's Innovation track, which ships \
                        quarterly under calendar versioning and carries each \
                        release only until the next one arrives. The port rolls \
                        forward with it rather than staying on any one release. \
                        For a release under long-term support, see the mysql9 \
                        and mysql8 ports.
    # https://downloads.mysql.com/docs/licenses/mysqld-26.7-gpl-en.pdf
    license             {GPL-2 OpenSSLException}

    revision            ${revision_client}

    master_sites        mysql:MySQL-${version_branch}:mysql

    distname            mysql-${version}

    distfiles           ${distname}${extract.suffix}:mysql

    checksums           ${distname}${extract.suffix} \
                        rmd160  fd00fe558b8e7340ad07fdb0b0d07cc129b9b6b4 \
                        sha256  95e949183b94bbe39e70c6355e6c90d2a640a62ede996ca5f7a6a3e0827a3260 \
                        size    459475424

    depends_build-append \
                        path:bin/pkg-config:pkgconfig  \
                        port:bison

    depends_lib-append  path:lib/pkgconfig/icu-uc.pc:icu \
                        port:curl           \
                        port:cyrus-sasl2    \
                        port:libedit        \
                        port:libfido2       \
                        path:lib/libldap.dylib:openldap       \
                        port:lz4            \
                        port:protobuf3-cpp  \
                        port:zlib           \
                        port:zstd

    depends_run-append  port:mysql_select

    select.group        mysql
    select.file         ${filespath}/${name_mysql}

    use_parallel_build  yes

    compiler.cxx_standard 2023

    # Apple clang 15 lacks P0960 parenthesized aggregate initialisation and
    # fails 22 objects in on libs/mysql/strconv/decode/parse_options.h.
    # cxx_standard will not exclude it, having no C++23 row and mapping
    # anything >= 2020 onto the same clang 16 minimum, so blacklist it and let
    # those hosts take a MacPorts clang.
    compiler.blacklist-append {clang < 1600}

    cmake.build_type    Release

    # MySQL uses std::is_trivial_v and std::nothrow in files that include
    # neither <type_traits> nor <new>, relying on another header to drag them
    # in. Newer libc++ does not: 21 drops <type_traits>, 22 drops <new> too.
    # 26.7 fixed the first case in libs/mysql/gtid/tag_plain.h but not the
    # second, which remains in sql/server_component/mysql_file_imp.cc and
    # components/keyrings/common/data_file/reader.cc. Which libc++ applies
    # follows the compiler rather than the OS, since a MacPorts clang puts its
    # own headers ahead of the SDK's, so force both everywhere.
    #
    # Never force <sstream>. It defines stdin, and MySQL guards includes of its
    # own on #ifndef stdin (storage/myisammrg/myrg_static.cc), so forcing it
    # drops those headers.
    configure.cxxflags-append -include type_traits -include new

    configure.args-append \
        -DWITH_UNIT_TESTS=OFF \
        -DINSTALL_MYSQLTESTDIR=

    # cmake substitutes FIND_PROC into mysqld_safe, which uses it to test a
    # stale pid file against the process list. It sets FIND_PROC outright only
    # for Linux and Solaris; elsewhere it probes with ps, and on Darwin comes
    # up empty, leaving the generated script a bare `if` that will not parse.
    # The SysV form it would otherwise use is wrong here too, matching the bare
    # pid in any ps column, so set a Darwin-compatible test of our own: ask
    # about the one pid, and match only its command.
    configure.args-append \
        -DFIND_PROC='ps -p \$PID -o command= | grep -v mysqld_safe | grep -- \$MYSQLD > /dev/null'

    # Disable MySQL NDB (Network Database) Cluster. Note that -DWITH_NDB=OFF
    # does not do this; it is already off, and storage/ndb is pulled in as a
    # plugin regardless.
    configure.args-append \
        -DWITHOUT_NDBCLUSTER_STORAGE_ENGINE=1

    # MySQL installs its libraries into a private, per-port directory
    # (lib/${name_mysql}/mysql) and manages its own per-target RPATHs, whereas
    # the cmake PortGroup assumes everything lives in ${prefix}/lib. Override the
    # two PortGroup defaults built on that assumption. These go on configure.args
    # (evaluated after configure.pre_args on the cmake command line), so for both
    # cache variables the last -D wins:
    #   - build against the build tree, not the not-yet-installed RPATH, since
    #     MySQL runs freshly-built tools during its own build; and
    #   - give the installed dylibs their real install-name directory.
    configure.args-append \
        -DCMAKE_BUILD_WITH_INSTALL_RPATH:BOOL=OFF \
        -DCMAKE_INSTALL_NAME_DIR:PATH=${prefix}/lib/${name_mysql}/mysql

    # Build configuration
    configure.args-append \
        -DBISON_EXECUTABLE="${prefix}/bin/bison" \
        -DFORCE_UNSUPPORTED_COMPILER=ON \
        -DINSTALL_LAYOUT:STRING=MACPORTS \
        -DMYSQL_DATADIR:PATH="${prefix}/var/db/${name_mysql}" \
        -DMYSQL_UNIX_ADDR:PATH="${prefix}/var/run/${name_mysql}/mysqld.sock" \
        -DSYSCONFDIR:PATH="${prefix}/etc/${name_mysql}" \
        -DWITH_CURL=system      \
        -DWITH_EDITLINE=system  \
        -DWITH_FIDO=system      \
        -DWITH_ICU=system       \
        -DWITH_LDAP=system      \
        -DWITH_LZ4=system       \
        -DWITH_PROTOBUF=system  \
        -DWITH_SASL=system      \
        -DWITH_ZLIB=system      \
        -DWITH_ZSTD=system

    # WITH_SSL=system makes MySQL use the openssl / libcrypto libraries in place
    # rather than copying them into its own tree. The openssl PortGroup already
    # injects -DOPENSSL_ROOT_DIR=[openssl::install_area] (kept; the pre-configure
    # block below only trims the PortGroup's other ssl flags), which cmake's
    # FindOpenSSL uses to locate the MacPorts openssl -- so no separate
    # CMAKE_PREFIX_PATH is needed here.
    configure.args-append \
        -DWITH_SSL=system

    configure.args-append \
        -DWITH_ROUTER:BOOL=OFF

    patch.pre_args-replace  -p0 -p1
    patchfiles      patch-cmake-install_layout.cmake.diff \
                    patch-CMakeLists-no-homebrew.diff \
                    patch-no_warn_duplicate_libraries.diff \
                    patch-no-test-components.diff

    post-extract {
        file mkdir ${cmake.build_dir}/macports
        copy ${filespath}/macports-default.cnf \
            ${filespath}/my.cnf \
            ${cmake.build_dir}/macports/
    }

    pre-configure {
        # Drop the two openssl PortGroup flags that would put MySQL into its
        # copy-into-the-build-tree SSL mode; OPENSSL_ROOT_DIR is deliberately left
        # in place (see WITH_SSL=system above).
        configure.args-delete \
            -DOPENSSL_INCLUDE_DIR=[openssl::include_dir] \
            -DWITH_SSL=[openssl::install_area]
    }

    post-patch {
        reinplace "s|@NAME@|${name_mysql}|g" \
            ${worksrcpath}/cmake/install_layout.cmake
        reinplace "s|@NAME@|${name_mysql}|g" \
            ${cmake.build_dir}/macports/macports-default.cnf \
            ${cmake.build_dir}/macports/my.cnf
        reinplace "s|@PREFIX@|${prefix}|g" \
            ${cmake.build_dir}/macports/macports-default.cnf \
            ${cmake.build_dir}/macports/my.cnf
    }

    post-destroot {
        # proc portdestroot::destroot_finish fails to find and compress our man pages
        # so borrow the compress command and run on our files now.
        set gzip [findBinary gzip ${portutil::autoconf::gzip_path}]

        foreach manpage [glob -type f ${destroot}${prefix}/share/man/${name_mysql}/man\[1-9\]/*] {
            # Fix paths in manpages
            reinplace -q "s|/etc/|${prefix}/etc/${name_mysql}/|g" ${manpage}
            # Compress all manpages with gzip
            system "$gzip -9vf ${manpage}"
        }

        xinstall -m 0755 -o root -d ${destroot}${prefix}/etc/${name_mysql}

        copy ${cmake.build_dir}/macports/macports-default.cnf \
            ${destroot}${prefix}/etc/${name_mysql}/

        xinstall -m 0755 -o root -d \
            ${destroot}${prefix}/share/${name_mysql}/support-files/macports

        copy ${cmake.build_dir}/macports/my.cnf \
            ${destroot}${prefix}/share/${name_mysql}/support-files/macports/
    }

    post-install {
        if {![file exists ${prefix}/etc/LaunchDaemons/org.macports.${name_mysql}-server/org.macports.${name_mysql}-server.plist]} {
            ui_msg "The ${name_mysql} client has been installed."
            ui_msg "To install the ${name_mysql} server, install the ${name_mysql}-server port."
        }
    }

    post-activate {
        if {![file exists ${prefix}/etc/${name_mysql}/my.cnf]} {
            copy ${prefix}/share/${name_mysql}/support-files/macports/my.cnf \
                ${prefix}/etc/${name_mysql}/
        }
    }

    notes "
On activation if no ${prefix}/etc/${name_mysql}/my.cnf file exists one
will be created which loads
${prefix}/etc/${name_mysql}/macports-default.cnf.

If a ${prefix}/etc/${name_mysql}/my.cnf file exists MacPorts does not
touch it and any changes you make to ${prefix}/etc/${name_mysql}/my.cnf
will be preserved (e.g., during port upgrades, deactivations or
activations). ${prefix}/etc/${name_mysql}/my.cnf is a good place to
customize your ${name_mysql} installation.

Any changes made to ${prefix}/etc/${name_mysql}/macports-default.cnf
will be lost during port upgrades, deactivations or activations so you
are advised to not make changes here. Currently
${prefix}/etc/${name_mysql}/macports-default.cnf contains only one
directive; to disable networking. With disabled networking it is
possible to install and have running all the MacPorts mysql ports
simultaneously.

To set ${name_mysql} as your preferred version of MySQL, use `port select`,
as follows:

\$ sudo port select mysql ${name_mysql}
"

    # dev.mysql.com 403s automated fetches and the download CDN offers no
    # directory listing, so neither can drive livecheck. Scan the official
    # mysql-server GitHub tags instead. This port rolls forward across release
    # series rather than tracking one, so match any calendar version: a
    # two-digit major separates them from the sequential 5.x, 8.x and 9.x tags,
    # and livecheck takes the highest of what matches.
    livecheck.type      regex
    livecheck.url       https://api.github.com/repos/mysql/mysql-server/git/matching-refs/tags/mysql-
    livecheck.regex     {mysql-([2-9][0-9]\.[0-9.]+)}
}

subport ${name_mysql}-server {
    revision            ${revision_server}
    license             BSD
    description         Run ${name_mysql} as server
    long_description    {*}${description}

    supported_archs     noarch
    distfiles

    depends_run         port:${name_mysql}

    set mysqluser       _mysql
    add_users ${mysqluser} group=${mysqluser} realname=MySQL\ Server

    set log_file ${prefix}/var/log/${name_mysql}/mysql.log

    use_configure       no

    build {}

    startupitem.create      yes
    startupitem.executable  ${prefix}/lib/${name_mysql}/bin/mysqld
    startupitem.user        ${mysqluser}
    startupitem.group       ${mysqluser}
    startupitem.logfile     ${log_file}

    destroot {
        xinstall -d -m 0755 -o ${mysqluser} -g ${mysqluser} \
            [file dirname ${destroot}${log_file}]

        touch ${destroot}${log_file}
        file attributes ${destroot}${log_file} -o ${mysqluser} -g ${mysqluser}

        xinstall -m 0755 -o root -d \
            ${destroot}${prefix}/var/run

        xinstall -m 0755 -o ${mysqluser} -g ${mysqluser} -d \
            ${destroot}${prefix}/etc/${name_mysql} \
            ${destroot}${prefix}/var/db/${name_mysql} \
            ${destroot}${prefix}/var/log/${name_mysql} \
            ${destroot}${prefix}/var/run/${name_mysql}

        xinstall -m 0700 -o ${mysqluser} -g ${mysqluser} -d \
            ${destroot}${prefix}/var/db/${name_mysql}-files \
            ${destroot}${prefix}/var/db/${name_mysql}-keyring

        destroot.keepdirs-append  \
            ${destroot}${prefix}/var/db/${name_mysql} \
            ${destroot}${prefix}/var/db/${name_mysql}-files \
            ${destroot}${prefix}/var/db/${name_mysql}-keyring \
            ${destroot}${prefix}/var/log/${name_mysql} \
            ${destroot}${prefix}/var/run/${name_mysql}
    }

    notes "
A new install must be initialized before the server will start. Run:

\$ sudo ${prefix}/lib/${name_mysql}/bin/mysqld --initialize --user=${mysqluser}
\$ sudo port load ${name_mysql}-server
\$ ${prefix}/lib/${name_mysql}/bin/mysql_secure_installation

The first command creates the necessary files for the MySQL database service.
(Remember to make a note of the auto-generated root password from this step.)
Without it the server exits at startup reporting that it cannot open
ibdata1. The second command starts the MySQL service. The last command helps
to improve the security of your running MySQL instance.

If you are upgrading your ${subport} installation instead of a fresh install,
then the running server from the previous version is stopped. So post-upgrade
of ${subport}, please run the following to start the updated server:

\$ sudo port load ${name_mysql}-server

Your databases in ${prefix}/var/db/${name_mysql} are left untouched by an
upgrade.

Once enabled, the MySQL logs can be found in:
[file dirname $log_file]
"

    livecheck.type          none
}
