|
| 1 | +#!/usr/bin/env bash |
| 2 | +set -euo pipefail |
| 3 | + |
| 4 | +ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" |
| 5 | +WP_DIR="$ROOT_DIR/wordpress" |
| 6 | +COMPOSE_OVERRIDE="$WP_DIR/docker-compose.override.yml" |
| 7 | +RUNTIME_DIR="$ROOT_DIR/tmp-native-extension" |
| 8 | +EXTENSION_SOURCE_VOLUME=" - ../packages/mysql-on-sqlite/ext/wp-mysql-parser:/var/native-parser-extension-src" |
| 9 | +EXTENSION_RUNTIME_VOLUME=" - ../tmp-native-extension:/var/native-parser-extension:ro" |
| 10 | +EXTENSION_INI_VOLUME=" - ../tmp-native-extension/wp-mysql-parser.ini:/usr/local/etc/php/conf.d/wp-mysql-parser.ini:ro" |
| 11 | + |
| 12 | +if [ ! -f "$COMPOSE_OVERRIDE" ]; then |
| 13 | + echo "Missing $COMPOSE_OVERRIDE. Run composer run wp-setup first." >&2 |
| 14 | + exit 1 |
| 15 | +fi |
| 16 | + |
| 17 | +add_volume_to_service() { |
| 18 | + local service="$1" |
| 19 | + local volume="$2" |
| 20 | + |
| 21 | + node - "$COMPOSE_OVERRIDE" "$service" "$volume" <<'NODE' |
| 22 | +const fs = require( 'fs' ); |
| 23 | +
|
| 24 | +const file = process.argv[2]; |
| 25 | +const service = process.argv[3]; |
| 26 | +const volume = process.argv[4]; |
| 27 | +const lines = fs.readFileSync( file, 'utf8' ).split( '\n' ); |
| 28 | +
|
| 29 | +if ( lines.some( line => line.trim() === volume.trim() ) ) { |
| 30 | + process.exit( 0 ); |
| 31 | +} |
| 32 | +
|
| 33 | +const serviceIndex = lines.findIndex( line => line === ` ${ service }:` ); |
| 34 | +if ( serviceIndex === -1 ) { |
| 35 | + throw new Error( `Service ${ service } not found in ${ file }.` ); |
| 36 | +} |
| 37 | +
|
| 38 | +let volumesIndex = -1; |
| 39 | +for ( let i = serviceIndex + 1; i < lines.length; i++ ) { |
| 40 | + if ( /^ [A-Za-z0-9_-]+:/.test( lines[i] ) ) { |
| 41 | + break; |
| 42 | + } |
| 43 | +
|
| 44 | + if ( lines[i].trim() === 'volumes:' ) { |
| 45 | + volumesIndex = i; |
| 46 | + break; |
| 47 | + } |
| 48 | +} |
| 49 | +
|
| 50 | +if ( volumesIndex === -1 ) { |
| 51 | + throw new Error( `Service ${ service } has no volumes list in ${ file }.` ); |
| 52 | +} |
| 53 | +
|
| 54 | +let insertAt = volumesIndex + 1; |
| 55 | +while ( insertAt < lines.length && /^\s{6}- /.test( lines[insertAt] ) ) { |
| 56 | + insertAt++; |
| 57 | +} |
| 58 | +
|
| 59 | +lines.splice( insertAt, 0, volume ); |
| 60 | +fs.writeFileSync( file, lines.join( '\n' ) ); |
| 61 | +NODE |
| 62 | +} |
| 63 | + |
| 64 | +add_volume_to_service php "$EXTENSION_SOURCE_VOLUME" |
| 65 | +add_volume_to_service cli "$EXTENSION_SOURCE_VOLUME" |
| 66 | + |
| 67 | +cat > "$WP_DIR/native-build-extension.sh" <<'EOF' |
| 68 | +#!/bin/sh |
| 69 | +set -eu |
| 70 | +
|
| 71 | +apt-get update |
| 72 | +apt-get install -y --no-install-recommends ca-certificates curl build-essential clang libclang-dev pkg-config |
| 73 | +
|
| 74 | +if [ ! -x "$HOME/.cargo/bin/cargo" ]; then |
| 75 | + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --profile minimal --default-toolchain stable |
| 76 | +fi |
| 77 | +
|
| 78 | +. "$HOME/.cargo/env" |
| 79 | +
|
| 80 | +PHP_CONFIG="$(command -v php-config)" |
| 81 | +export PHP_CONFIG |
| 82 | +
|
| 83 | +LIBCLANG_SO="$(find /usr/lib /usr/local/lib -name 'libclang.so*' 2>/dev/null | head -n 1)" |
| 84 | +if [ -z "$LIBCLANG_SO" ]; then |
| 85 | + echo "Unable to locate libclang.so after installing libclang-dev." >&2 |
| 86 | + exit 1 |
| 87 | +fi |
| 88 | +
|
| 89 | +LIBCLANG_PATH="$(dirname "$LIBCLANG_SO")" |
| 90 | +export LIBCLANG_PATH |
| 91 | +
|
| 92 | +cd /var/native-parser-extension-src |
| 93 | +cargo build |
| 94 | +EOF |
| 95 | + |
| 96 | +chmod +x "$WP_DIR/native-build-extension.sh" |
| 97 | + |
| 98 | +cd "$WP_DIR" |
| 99 | +node tools/local-env/scripts/docker.js run --rm php sh /var/www/native-build-extension.sh |
| 100 | + |
| 101 | +mkdir -p "$RUNTIME_DIR" |
| 102 | +cp "$ROOT_DIR/packages/mysql-on-sqlite/ext/wp-mysql-parser/target/debug/libwp_mysql_parser.so" "$RUNTIME_DIR/libwp_mysql_parser.so" |
| 103 | +printf '%s\n' 'extension=/var/native-parser-extension/libwp_mysql_parser.so' > "$RUNTIME_DIR/wp-mysql-parser.ini" |
| 104 | + |
| 105 | +add_volume_to_service php "$EXTENSION_RUNTIME_VOLUME" |
| 106 | +add_volume_to_service cli "$EXTENSION_RUNTIME_VOLUME" |
| 107 | +add_volume_to_service php "$EXTENSION_INI_VOLUME" |
| 108 | +add_volume_to_service cli "$EXTENSION_INI_VOLUME" |
| 109 | + |
| 110 | +node tools/local-env/scripts/docker.js run --rm php php -m | grep -qx 'wp_mysql_parser' |
| 111 | +node tools/local-env/scripts/docker.js run --rm php php -r ' |
| 112 | +require "/var/www/src/wp-content/plugins/sqlite-database-integration/wp-includes/database/load.php"; |
| 113 | +$lexer = new WP_MySQL_Lexer( "SELECT 1" ); |
| 114 | +if ( ! method_exists( $lexer, "native_token_stream" ) ) { |
| 115 | + fwrite( STDERR, "Native token stream is not available in the WordPress PHP test container.\n" ); |
| 116 | + exit( 1 ); |
| 117 | +} |
| 118 | +$driver = new WP_PDO_MySQL_On_SQLite( "mysql-on-sqlite:path=:memory:;dbname=wp;" ); |
| 119 | +$parser = $driver->create_parser( "SELECT 1" ); |
| 120 | +$parser->next_query(); |
| 121 | +$ast = $parser->get_query_ast(); |
| 122 | +$property = ( new ReflectionClass( $ast ) )->getProperty( "native_ast" ); |
| 123 | +$property->setAccessible( true ); |
| 124 | +$native_ast = $property->getValue( $ast ); |
| 125 | +if ( ! is_object( $native_ast ) || "WP_MySQL_Native_Ast" !== get_class( $native_ast ) ) { |
| 126 | + fwrite( STDERR, "WordPress PHP test container did not select the native-backed AST.\n" ); |
| 127 | + exit( 1 ); |
| 128 | +} |
| 129 | +' |
0 commit comments