Skip to content

Commit e98ba5e

Browse files
authored
Merge pull request #719 from Extra-Chill/fix/715-local-read-routing-20260615
Fix local workspace reads when remote state exists
2 parents ce6adc7 + 94a6092 commit e98ba5e

4 files changed

Lines changed: 226 additions & 15 deletions

File tree

inc/Abilities/WorkspaceAbilities.php

Lines changed: 49 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2559,9 +2559,11 @@ public static function showRepo( array $input ): array|\WP_Error {
25592559
* @return array Result.
25602560
*/
25612561
public static function readFile( array $input ): array|\WP_Error {
2562-
$input = self::normalize_mounted_workspace_path_input($input, array( 'repo' ));
2563-
if ( RemoteWorkspaceBackend::should_handle() ) {
2564-
return ( new RemoteWorkspaceBackend() )->read_file(
2562+
$input = self::normalize_mounted_workspace_path_input($input, array( 'repo' ));
2563+
$workspace = new Workspace();
2564+
$reader = new WorkspaceReader($workspace);
2565+
if ( RemoteWorkspaceBackend::should_handle() && null !== self::showLocalWorkspaceHandleIfPresent($workspace, (string) ( $input['repo'] ?? '' )) ) {
2566+
return $reader->read_file(
25652567
$input['repo'] ?? '',
25662568
$input['path'] ?? '',
25672569
isset($input['max_size']) ? (int) $input['max_size'] : Workspace::MAX_READ_SIZE,
@@ -2570,8 +2572,18 @@ public static function readFile( array $input ): array|\WP_Error {
25702572
);
25712573
}
25722574

2573-
$workspace = new Workspace();
2574-
$reader = new WorkspaceReader($workspace);
2575+
if ( RemoteWorkspaceBackend::should_handle() ) {
2576+
$result = ( new RemoteWorkspaceBackend() )->read_file(
2577+
$input['repo'] ?? '',
2578+
$input['path'] ?? '',
2579+
isset($input['max_size']) ? (int) $input['max_size'] : Workspace::MAX_READ_SIZE,
2580+
isset($input['offset']) ? (int) $input['offset'] : null,
2581+
isset($input['limit']) ? (int) $input['limit'] : null
2582+
);
2583+
if ( ! self::shouldFallbackToLocalWorkspace($result) ) {
2584+
return $result;
2585+
}
2586+
}
25752587

25762588
return $reader->read_file(
25772589
$input['repo'] ?? '',
@@ -2589,16 +2601,25 @@ public static function readFile( array $input ): array|\WP_Error {
25892601
* @return array Result.
25902602
*/
25912603
public static function listDirectory( array $input ): array|\WP_Error {
2592-
$input = self::normalize_mounted_workspace_path_input($input, array( 'repo' ));
2593-
if ( RemoteWorkspaceBackend::should_handle() ) {
2594-
return ( new RemoteWorkspaceBackend() )->list_directory(
2604+
$input = self::normalize_mounted_workspace_path_input($input, array( 'repo' ));
2605+
$workspace = new Workspace();
2606+
$reader = new WorkspaceReader($workspace);
2607+
if ( RemoteWorkspaceBackend::should_handle() && null !== self::showLocalWorkspaceHandleIfPresent($workspace, (string) ( $input['repo'] ?? '' )) ) {
2608+
return $reader->list_directory(
25952609
$input['repo'] ?? '',
25962610
$input['path'] ?? null
25972611
);
25982612
}
25992613

2600-
$workspace = new Workspace();
2601-
$reader = new WorkspaceReader($workspace);
2614+
if ( RemoteWorkspaceBackend::should_handle() ) {
2615+
$result = ( new RemoteWorkspaceBackend() )->list_directory(
2616+
$input['repo'] ?? '',
2617+
$input['path'] ?? null
2618+
);
2619+
if ( ! self::shouldFallbackToLocalWorkspace($result) ) {
2620+
return $result;
2621+
}
2622+
}
26022623

26032624
return $reader->list_directory(
26042625
$input['repo'] ?? '',
@@ -2613,9 +2634,11 @@ public static function listDirectory( array $input ): array|\WP_Error {
26132634
* @return array Result.
26142635
*/
26152636
public static function grepFiles( array $input ): array|\WP_Error {
2616-
$input = self::normalize_mounted_workspace_path_input($input, array( 'repo' ));
2617-
if ( RemoteWorkspaceBackend::should_handle() ) {
2618-
return ( new RemoteWorkspaceBackend() )->grep(
2637+
$input = self::normalize_mounted_workspace_path_input($input, array( 'repo' ));
2638+
$workspace = new Workspace();
2639+
$reader = new WorkspaceReader($workspace);
2640+
if ( RemoteWorkspaceBackend::should_handle() && null !== self::showLocalWorkspaceHandleIfPresent($workspace, (string) ( $input['repo'] ?? '' )) ) {
2641+
return $reader->grep(
26192642
$input['repo'] ?? '',
26202643
$input['pattern'] ?? '',
26212644
$input['path'] ?? null,
@@ -2625,8 +2648,19 @@ public static function grepFiles( array $input ): array|\WP_Error {
26252648
);
26262649
}
26272650

2628-
$workspace = new Workspace();
2629-
$reader = new WorkspaceReader($workspace);
2651+
if ( RemoteWorkspaceBackend::should_handle() ) {
2652+
$result = ( new RemoteWorkspaceBackend() )->grep(
2653+
$input['repo'] ?? '',
2654+
$input['pattern'] ?? '',
2655+
$input['path'] ?? null,
2656+
$input['include'] ?? null,
2657+
isset($input['max_results']) ? (int) $input['max_results'] : 100,
2658+
isset($input['context_lines']) ? (int) $input['context_lines'] : 0
2659+
);
2660+
if ( ! self::shouldFallbackToLocalWorkspace($result) ) {
2661+
return $result;
2662+
}
2663+
}
26302664

26312665
return $reader->grep(
26322666
$input['repo'] ?? '',

tests/smoke-workspace-grep.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ function size_format( $bytes ): string
5353
}
5454

5555
include __DIR__ . '/../inc/Support/PathSecurity.php';
56+
include __DIR__ . '/../inc/Workspace/WorkspaceAliasResolver.php';
5657
include __DIR__ . '/../inc/Workspace/Workspace.php';
5758
include __DIR__ . '/../inc/Workspace/WorkspaceReader.php';
5859

tests/smoke-workspace-list-directory.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ function size_format( $bytes ): string
5353
}
5454

5555
include __DIR__ . '/../inc/Support/PathSecurity.php';
56+
include __DIR__ . '/../inc/Workspace/WorkspaceAliasResolver.php';
5657
include __DIR__ . '/../inc/Workspace/Workspace.php';
5758
include __DIR__ . '/../inc/Workspace/WorkspaceReader.php';
5859

tests/smoke-workspace-local-fallback.php

Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,14 @@ class GitHubAbilities
2121
class RemoteWorkspaceBackend
2222
{
2323
public static array $show_input = array();
24+
public static array $read_input = array();
25+
public static array $list_input = array();
26+
public static array $grep_input = array();
2427
public static array $worktree_input = array();
2528
public static bool $show_returns_remote_success = false;
29+
public static bool $read_returns_remote_success = false;
30+
public static bool $list_returns_remote_success = false;
31+
public static bool $grep_returns_remote_success = false;
2632
public static bool $worktree_returns_remote_success = false;
2733

2834
public static function should_handle(): bool
@@ -65,6 +71,65 @@ public function worktree_add( string $repo_name, string $branch, ?string $from =
6571
'Remote workspace repository "wpcom-codebox" is not registered. Call workspace_clone first.'
6672
);
6773
}
74+
75+
public function read_file( string $handle, string $path, int $max_size, ?int $offset = null, ?int $limit = null ): array|\WP_Error
76+
{
77+
self::$read_input = compact('handle', 'path', 'max_size', 'offset', 'limit');
78+
if ( self::$read_returns_remote_success ) {
79+
return array(
80+
'success' => true,
81+
'backend' => 'github_api',
82+
'content' => 'remote file',
83+
'path' => $path,
84+
'size' => 11,
85+
);
86+
}
87+
88+
return new \WP_Error(
89+
'remote_workspace_repo_not_found',
90+
'Remote workspace repository "wpcom-codebox" is not registered. Call workspace_clone first.'
91+
);
92+
}
93+
94+
public function list_directory( string $handle, ?string $path = null ): array|\WP_Error
95+
{
96+
self::$list_input = compact('handle', 'path');
97+
if ( self::$list_returns_remote_success ) {
98+
return array(
99+
'success' => true,
100+
'backend' => 'github_api',
101+
'repo' => $handle,
102+
'path' => $path ?? '/',
103+
'entries' => array(),
104+
);
105+
}
106+
107+
return new \WP_Error(
108+
'remote_workspace_repo_not_found',
109+
'Remote workspace repository "wpcom-codebox" is not registered. Call workspace_clone first.'
110+
);
111+
}
112+
113+
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
114+
{
115+
self::$grep_input = compact('handle', 'pattern', 'path', 'include_pattern', 'max_results', 'context_lines');
116+
if ( self::$grep_returns_remote_success ) {
117+
return array(
118+
'success' => true,
119+
'backend' => 'github_api',
120+
'repo' => $handle,
121+
'path' => $path ?? '/',
122+
'pattern' => $pattern,
123+
'matches' => array(),
124+
'count' => 0,
125+
);
126+
}
127+
128+
return new \WP_Error(
129+
'remote_workspace_repo_not_found',
130+
'Remote workspace repository "wpcom-codebox" is not registered. Call workspace_clone first.'
131+
);
132+
}
68133
}
69134

70135
class Workspace
@@ -111,6 +176,64 @@ public function worktree_add(
111176
);
112177
}
113178
}
179+
180+
class WorkspaceReader
181+
{
182+
public static array $read_input = array();
183+
public static array $list_input = array();
184+
public static array $grep_input = array();
185+
186+
public function __construct( private Workspace $workspace )
187+
{
188+
}
189+
190+
public function read_file( string $name, string $path, int $max_size, ?int $offset = null, ?int $limit = null ): array
191+
{
192+
self::$read_input = compact('name', 'path', 'max_size', 'offset', 'limit');
193+
return array(
194+
'success' => true,
195+
'content' => 'local file',
196+
'path' => $path,
197+
'size' => 10,
198+
);
199+
}
200+
201+
public function list_directory( string $name, ?string $path = null ): array
202+
{
203+
self::$list_input = compact('name', 'path');
204+
return array(
205+
'success' => true,
206+
'repo' => $name,
207+
'path' => $path ?? '/',
208+
'entries' => array(
209+
array(
210+
'name' => 'README.md',
211+
'type' => 'file',
212+
'size' => 10,
213+
),
214+
),
215+
);
216+
}
217+
218+
public function grep( string $name, string $pattern, ?string $path = null, ?string $include_pattern = null, int $max_results = 100, int $context_lines = 0 ): array
219+
{
220+
self::$grep_input = compact('name', 'pattern', 'path', 'include_pattern', 'max_results', 'context_lines');
221+
return array(
222+
'success' => true,
223+
'repo' => $name,
224+
'path' => $path ?? '/',
225+
'pattern' => $pattern,
226+
'matches' => array(
227+
array(
228+
'file' => 'README.md',
229+
'line' => 1,
230+
'text' => 'local file',
231+
),
232+
),
233+
'count' => 1,
234+
);
235+
}
236+
}
114237
}
115238

116239
namespace DataMachineCode\Support {
@@ -201,6 +324,58 @@ function is_wp_error( $value ): bool
201324
$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'] ?? '' ));
202325
$assert('workspace path marks local worktree handle as existing', is_array($duplicate_path) && true === ( $duplicate_path['exists'] ?? null ));
203326

327+
\DataMachineCode\Workspace\RemoteWorkspaceBackend::$read_returns_remote_success = true;
328+
\DataMachineCode\Workspace\RemoteWorkspaceBackend::$read_input = array();
329+
\DataMachineCode\Workspace\WorkspaceReader::$read_input = array();
330+
$read = \DataMachineCode\Abilities\WorkspaceAbilities::readFile(
331+
array(
332+
'repo' => 'wpcom-codebox',
333+
'path' => 'README.md',
334+
'max_size' => 500,
335+
'offset' => 2,
336+
'limit' => 3,
337+
)
338+
);
339+
340+
$assert('remote read is not consulted when local primary exists', array() === \DataMachineCode\Workspace\RemoteWorkspaceBackend::$read_input);
341+
$assert('local read attempted for local primary', 'wpcom-codebox' === ( \DataMachineCode\Workspace\WorkspaceReader::$read_input['name'] ?? '' ));
342+
$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 ));
343+
$assert('read returns local file result', is_array($read) && 'local file' === ( $read['content'] ?? '' ));
344+
345+
\DataMachineCode\Workspace\RemoteWorkspaceBackend::$list_returns_remote_success = true;
346+
\DataMachineCode\Workspace\RemoteWorkspaceBackend::$list_input = array();
347+
\DataMachineCode\Workspace\WorkspaceReader::$list_input = array();
348+
$list = \DataMachineCode\Abilities\WorkspaceAbilities::listDirectory(
349+
array(
350+
'repo' => 'wpcom-codebox',
351+
'path' => 'inc',
352+
)
353+
);
354+
355+
$assert('remote list is not consulted when local primary exists', array() === \DataMachineCode\Workspace\RemoteWorkspaceBackend::$list_input);
356+
$assert('local list attempted for local primary', 'wpcom-codebox' === ( \DataMachineCode\Workspace\WorkspaceReader::$list_input['name'] ?? '' ));
357+
$assert('list preserves path locally', 'inc' === ( \DataMachineCode\Workspace\WorkspaceReader::$list_input['path'] ?? '' ));
358+
$assert('list returns local entries', is_array($list) && 'README.md' === ( $list['entries'][0]['name'] ?? '' ));
359+
360+
\DataMachineCode\Workspace\RemoteWorkspaceBackend::$grep_returns_remote_success = true;
361+
\DataMachineCode\Workspace\RemoteWorkspaceBackend::$grep_input = array();
362+
\DataMachineCode\Workspace\WorkspaceReader::$grep_input = array();
363+
$grep = \DataMachineCode\Abilities\WorkspaceAbilities::grepFiles(
364+
array(
365+
'repo' => 'wpcom-codebox',
366+
'pattern' => 'local',
367+
'path' => 'inc',
368+
'include' => '*.php',
369+
'max_results' => 7,
370+
'context_lines' => 2,
371+
)
372+
);
373+
374+
$assert('remote grep is not consulted when local primary exists', array() === \DataMachineCode\Workspace\RemoteWorkspaceBackend::$grep_input);
375+
$assert('local grep attempted for local primary', 'wpcom-codebox' === ( \DataMachineCode\Workspace\WorkspaceReader::$grep_input['name'] ?? '' ));
376+
$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 ));
377+
$assert('grep returns local matches', is_array($grep) && 1 === ( $grep['count'] ?? null ));
378+
204379
\DataMachineCode\Workspace\RemoteWorkspaceBackend::$worktree_returns_remote_success = true;
205380
\DataMachineCode\Workspace\RemoteWorkspaceBackend::$worktree_input = array();
206381
$worktree = \DataMachineCode\Abilities\WorkspaceAbilities::worktreeAdd(

0 commit comments

Comments
 (0)