Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions features/shell.feature
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,38 @@ Feature: WordPress REPL
"""
And STDERR should be empty

Scenario: Use SHELL environment variable as fallback for bash
Given a WP install

And a session file:
"""
return true;
"""

# SHELL pointing to bash should work (when bash is available).
When I try `SHELL=/bin/bash wp shell --basic < session`
Then STDOUT should contain:
"""
bool(true)
"""
And STDERR should be empty

# SHELL pointing to non-bash binary should be ignored and fall back to /bin/bash.
When I try `SHELL=/bin/sh wp shell --basic < session`
Then STDOUT should contain:
"""
bool(true)
"""
And STDERR should be empty

# SHELL pointing to invalid path should be ignored and fall back to /bin/bash.
When I try `SHELL=/nonsense/path wp shell --basic < session`
Then STDOUT should contain:
"""
bool(true)
"""
And STDERR should be empty

Scenario: Input starting with dash
Given a WP install
And a session file:
Expand Down
24 changes: 23 additions & 1 deletion src/WP_CLI/Shell/REPL.php
Original file line number Diff line number Diff line change
Expand Up @@ -122,8 +122,15 @@ private static function create_prompt_cmd( $prompt, $history_path ) {
$history_path = escapeshellarg( $history_path );
if ( getenv( 'WP_CLI_CUSTOM_SHELL' ) ) {
$shell_binary = getenv( 'WP_CLI_CUSTOM_SHELL' );
} else {
} elseif ( is_file( '/bin/bash' ) && is_readable( '/bin/bash' ) ) {
// Prefer /bin/bash when available since we use bash-specific commands.
$shell_binary = '/bin/bash';
} elseif ( getenv( 'SHELL' ) && self::is_bash_shell( getenv( 'SHELL' ) ) ) {
// Only use SHELL as fallback if it's bash (we use bash-specific commands).
$shell_binary = getenv( 'SHELL' );
} else {
// Final fallback for systems without /bin/bash.
$shell_binary = 'bash';
}

if ( ! is_file( $shell_binary ) || ! is_readable( $shell_binary ) ) {
Expand All @@ -144,6 +151,21 @@ private static function create_prompt_cmd( $prompt, $history_path ) {
return "{$shell_binary} -c " . escapeshellarg( $cmd );
}

/**
* Check if a shell binary is bash or bash-compatible.
*
* @param string $shell_path Path to the shell binary.
* @return bool True if the shell is bash, false otherwise.
*/
private static function is_bash_shell( $shell_path ) {
if ( ! is_file( $shell_path ) || ! is_readable( $shell_path ) ) {
return false;
}
// Check if the basename is exactly 'bash' or starts with 'bash' followed by a version/variant.
$basename = basename( $shell_path );
return 'bash' === $basename || 0 === strpos( $basename, 'bash-' );
}

private function set_history_file() {
$data = getcwd() . get_current_user();

Expand Down