Skip to content
Merged
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
64 changes: 49 additions & 15 deletions inc/Abilities/WorkspaceAbilities.php
Original file line number Diff line number Diff line change
Expand Up @@ -2559,9 +2559,11 @@ public static function showRepo( array $input ): array|\WP_Error {
* @return array Result.
*/
public static function readFile( array $input ): array|\WP_Error {
$input = self::normalize_mounted_workspace_path_input($input, array( 'repo' ));
if ( RemoteWorkspaceBackend::should_handle() ) {
return ( new RemoteWorkspaceBackend() )->read_file(
$input = self::normalize_mounted_workspace_path_input($input, array( 'repo' ));
$workspace = new Workspace();
$reader = new WorkspaceReader($workspace);
if ( RemoteWorkspaceBackend::should_handle() && null !== self::showLocalWorkspaceHandleIfPresent($workspace, (string) ( $input['repo'] ?? '' )) ) {
return $reader->read_file(
$input['repo'] ?? '',
$input['path'] ?? '',
isset($input['max_size']) ? (int) $input['max_size'] : Workspace::MAX_READ_SIZE,
Expand All @@ -2570,8 +2572,18 @@ public static function readFile( array $input ): array|\WP_Error {
);
}

$workspace = new Workspace();
$reader = new WorkspaceReader($workspace);
if ( RemoteWorkspaceBackend::should_handle() ) {
$result = ( new RemoteWorkspaceBackend() )->read_file(
$input['repo'] ?? '',
$input['path'] ?? '',
isset($input['max_size']) ? (int) $input['max_size'] : Workspace::MAX_READ_SIZE,
isset($input['offset']) ? (int) $input['offset'] : null,
isset($input['limit']) ? (int) $input['limit'] : null
);
if ( ! self::shouldFallbackToLocalWorkspace($result) ) {
return $result;
}
}

return $reader->read_file(
$input['repo'] ?? '',
Expand All @@ -2589,16 +2601,25 @@ public static function readFile( array $input ): array|\WP_Error {
* @return array Result.
*/
public static function listDirectory( array $input ): array|\WP_Error {
$input = self::normalize_mounted_workspace_path_input($input, array( 'repo' ));
if ( RemoteWorkspaceBackend::should_handle() ) {
return ( new RemoteWorkspaceBackend() )->list_directory(
$input = self::normalize_mounted_workspace_path_input($input, array( 'repo' ));
$workspace = new Workspace();
$reader = new WorkspaceReader($workspace);
if ( RemoteWorkspaceBackend::should_handle() && null !== self::showLocalWorkspaceHandleIfPresent($workspace, (string) ( $input['repo'] ?? '' )) ) {
return $reader->list_directory(
$input['repo'] ?? '',
$input['path'] ?? null
);
}

$workspace = new Workspace();
$reader = new WorkspaceReader($workspace);
if ( RemoteWorkspaceBackend::should_handle() ) {
$result = ( new RemoteWorkspaceBackend() )->list_directory(
$input['repo'] ?? '',
$input['path'] ?? null
);
if ( ! self::shouldFallbackToLocalWorkspace($result) ) {
return $result;
}
}

return $reader->list_directory(
$input['repo'] ?? '',
Expand All @@ -2613,9 +2634,11 @@ public static function listDirectory( array $input ): array|\WP_Error {
* @return array Result.
*/
public static function grepFiles( array $input ): array|\WP_Error {
$input = self::normalize_mounted_workspace_path_input($input, array( 'repo' ));
if ( RemoteWorkspaceBackend::should_handle() ) {
return ( new RemoteWorkspaceBackend() )->grep(
$input = self::normalize_mounted_workspace_path_input($input, array( 'repo' ));
$workspace = new Workspace();
$reader = new WorkspaceReader($workspace);
if ( RemoteWorkspaceBackend::should_handle() && null !== self::showLocalWorkspaceHandleIfPresent($workspace, (string) ( $input['repo'] ?? '' )) ) {
return $reader->grep(
$input['repo'] ?? '',
$input['pattern'] ?? '',
$input['path'] ?? null,
Expand All @@ -2625,8 +2648,19 @@ public static function grepFiles( array $input ): array|\WP_Error {
);
}

$workspace = new Workspace();
$reader = new WorkspaceReader($workspace);
if ( RemoteWorkspaceBackend::should_handle() ) {
$result = ( new RemoteWorkspaceBackend() )->grep(
$input['repo'] ?? '',
$input['pattern'] ?? '',
$input['path'] ?? null,
$input['include'] ?? null,
isset($input['max_results']) ? (int) $input['max_results'] : 100,
isset($input['context_lines']) ? (int) $input['context_lines'] : 0
);
if ( ! self::shouldFallbackToLocalWorkspace($result) ) {
return $result;
}
}

return $reader->grep(
$input['repo'] ?? '',
Expand Down
1 change: 1 addition & 0 deletions tests/smoke-workspace-grep.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ function size_format( $bytes ): string
}

include __DIR__ . '/../inc/Support/PathSecurity.php';
include __DIR__ . '/../inc/Workspace/WorkspaceAliasResolver.php';
include __DIR__ . '/../inc/Workspace/Workspace.php';
include __DIR__ . '/../inc/Workspace/WorkspaceReader.php';

Expand Down
1 change: 1 addition & 0 deletions tests/smoke-workspace-list-directory.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ function size_format( $bytes ): string
}

include __DIR__ . '/../inc/Support/PathSecurity.php';
include __DIR__ . '/../inc/Workspace/WorkspaceAliasResolver.php';
include __DIR__ . '/../inc/Workspace/Workspace.php';
include __DIR__ . '/../inc/Workspace/WorkspaceReader.php';

Expand Down
175 changes: 175 additions & 0 deletions tests/smoke-workspace-local-fallback.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,14 @@ class GitHubAbilities
class RemoteWorkspaceBackend
{
public static array $show_input = array();
public static array $read_input = array();
public static array $list_input = array();
public static array $grep_input = array();
public static array $worktree_input = array();
public static bool $show_returns_remote_success = false;
public static bool $read_returns_remote_success = false;
public static bool $list_returns_remote_success = false;
public static bool $grep_returns_remote_success = false;
public static bool $worktree_returns_remote_success = false;

public static function should_handle(): bool
Expand Down Expand Up @@ -65,6 +71,65 @@ public function worktree_add( string $repo_name, string $branch, ?string $from =
'Remote workspace repository "wpcom-codebox" is not registered. Call workspace_clone first.'
);
}

public function read_file( string $handle, string $path, int $max_size, ?int $offset = null, ?int $limit = null ): array|\WP_Error
{
self::$read_input = compact('handle', 'path', 'max_size', 'offset', 'limit');
if ( self::$read_returns_remote_success ) {
return array(
'success' => true,
'backend' => 'github_api',
'content' => 'remote file',
'path' => $path,
'size' => 11,
);
}

return new \WP_Error(
'remote_workspace_repo_not_found',
'Remote workspace repository "wpcom-codebox" is not registered. Call workspace_clone first.'
);
}

public function list_directory( string $handle, ?string $path = null ): array|\WP_Error
{
self::$list_input = compact('handle', 'path');
if ( self::$list_returns_remote_success ) {
return array(
'success' => true,
'backend' => 'github_api',
'repo' => $handle,
'path' => $path ?? '/',
'entries' => array(),
);
}

return new \WP_Error(
'remote_workspace_repo_not_found',
'Remote workspace repository "wpcom-codebox" is not registered. Call workspace_clone first.'
);
}

public function grep( string $handle, string $pattern, ?string $path = null, ?string $include_pattern = null, int $max_results = 100, int $context_lines = 0 ): array|\WP_Error
{
self::$grep_input = compact('handle', 'pattern', 'path', 'include_pattern', 'max_results', 'context_lines');
if ( self::$grep_returns_remote_success ) {
return array(
'success' => true,
'backend' => 'github_api',
'repo' => $handle,
'path' => $path ?? '/',
'pattern' => $pattern,
'matches' => array(),
'count' => 0,
);
}

return new \WP_Error(
'remote_workspace_repo_not_found',
'Remote workspace repository "wpcom-codebox" is not registered. Call workspace_clone first.'
);
}
}

class Workspace
Expand Down Expand Up @@ -111,6 +176,64 @@ public function worktree_add(
);
}
}

class WorkspaceReader
{
public static array $read_input = array();
public static array $list_input = array();
public static array $grep_input = array();

public function __construct( private Workspace $workspace )
{
}

public function read_file( string $name, string $path, int $max_size, ?int $offset = null, ?int $limit = null ): array
{
self::$read_input = compact('name', 'path', 'max_size', 'offset', 'limit');
return array(
'success' => true,
'content' => 'local file',
'path' => $path,
'size' => 10,
);
}

public function list_directory( string $name, ?string $path = null ): array
{
self::$list_input = compact('name', 'path');
return array(
'success' => true,
'repo' => $name,
'path' => $path ?? '/',
'entries' => array(
array(
'name' => 'README.md',
'type' => 'file',
'size' => 10,
),
),
);
}

public function grep( string $name, string $pattern, ?string $path = null, ?string $include_pattern = null, int $max_results = 100, int $context_lines = 0 ): array
{
self::$grep_input = compact('name', 'pattern', 'path', 'include_pattern', 'max_results', 'context_lines');
return array(
'success' => true,
'repo' => $name,
'path' => $path ?? '/',
'pattern' => $pattern,
'matches' => array(
array(
'file' => 'README.md',
'line' => 1,
'text' => 'local file',
),
),
'count' => 1,
);
}
}
}

namespace DataMachineCode\Support {
Expand Down Expand Up @@ -201,6 +324,58 @@ function is_wp_error( $value ): bool
$assert('workspace path returns local worktree when duplicate remote exists', is_array($duplicate_path) && '/Users/chubes/Developer/wpcom-codebox@fix-listed-primary-resolution' === ( $duplicate_path['path'] ?? '' ));
$assert('workspace path marks local worktree handle as existing', is_array($duplicate_path) && true === ( $duplicate_path['exists'] ?? null ));

\DataMachineCode\Workspace\RemoteWorkspaceBackend::$read_returns_remote_success = true;
\DataMachineCode\Workspace\RemoteWorkspaceBackend::$read_input = array();
\DataMachineCode\Workspace\WorkspaceReader::$read_input = array();
$read = \DataMachineCode\Abilities\WorkspaceAbilities::readFile(
array(
'repo' => 'wpcom-codebox',
'path' => 'README.md',
'max_size' => 500,
'offset' => 2,
'limit' => 3,
)
);

$assert('remote read is not consulted when local primary exists', array() === \DataMachineCode\Workspace\RemoteWorkspaceBackend::$read_input);
$assert('local read attempted for local primary', 'wpcom-codebox' === ( \DataMachineCode\Workspace\WorkspaceReader::$read_input['name'] ?? '' ));
$assert('read preserves options locally', 500 === ( \DataMachineCode\Workspace\WorkspaceReader::$read_input['max_size'] ?? null ) && 2 === ( \DataMachineCode\Workspace\WorkspaceReader::$read_input['offset'] ?? null ) && 3 === ( \DataMachineCode\Workspace\WorkspaceReader::$read_input['limit'] ?? null ));
$assert('read returns local file result', is_array($read) && 'local file' === ( $read['content'] ?? '' ));

\DataMachineCode\Workspace\RemoteWorkspaceBackend::$list_returns_remote_success = true;
\DataMachineCode\Workspace\RemoteWorkspaceBackend::$list_input = array();
\DataMachineCode\Workspace\WorkspaceReader::$list_input = array();
$list = \DataMachineCode\Abilities\WorkspaceAbilities::listDirectory(
array(
'repo' => 'wpcom-codebox',
'path' => 'inc',
)
);

$assert('remote list is not consulted when local primary exists', array() === \DataMachineCode\Workspace\RemoteWorkspaceBackend::$list_input);
$assert('local list attempted for local primary', 'wpcom-codebox' === ( \DataMachineCode\Workspace\WorkspaceReader::$list_input['name'] ?? '' ));
$assert('list preserves path locally', 'inc' === ( \DataMachineCode\Workspace\WorkspaceReader::$list_input['path'] ?? '' ));
$assert('list returns local entries', is_array($list) && 'README.md' === ( $list['entries'][0]['name'] ?? '' ));

\DataMachineCode\Workspace\RemoteWorkspaceBackend::$grep_returns_remote_success = true;
\DataMachineCode\Workspace\RemoteWorkspaceBackend::$grep_input = array();
\DataMachineCode\Workspace\WorkspaceReader::$grep_input = array();
$grep = \DataMachineCode\Abilities\WorkspaceAbilities::grepFiles(
array(
'repo' => 'wpcom-codebox',
'pattern' => 'local',
'path' => 'inc',
'include' => '*.php',
'max_results' => 7,
'context_lines' => 2,
)
);

$assert('remote grep is not consulted when local primary exists', array() === \DataMachineCode\Workspace\RemoteWorkspaceBackend::$grep_input);
$assert('local grep attempted for local primary', 'wpcom-codebox' === ( \DataMachineCode\Workspace\WorkspaceReader::$grep_input['name'] ?? '' ));
$assert('grep preserves options locally', '*.php' === ( \DataMachineCode\Workspace\WorkspaceReader::$grep_input['include_pattern'] ?? '' ) && 7 === ( \DataMachineCode\Workspace\WorkspaceReader::$grep_input['max_results'] ?? null ) && 2 === ( \DataMachineCode\Workspace\WorkspaceReader::$grep_input['context_lines'] ?? null ));
$assert('grep returns local matches', is_array($grep) && 1 === ( $grep['count'] ?? null ));

\DataMachineCode\Workspace\RemoteWorkspaceBackend::$worktree_returns_remote_success = true;
\DataMachineCode\Workspace\RemoteWorkspaceBackend::$worktree_input = array();
$worktree = \DataMachineCode\Abilities\WorkspaceAbilities::worktreeAdd(
Expand Down
Loading