Skip to content

Commit 0b20a53

Browse files
committed
Fix listed primary workspace fallback
1 parent 4057301 commit 0b20a53

2 files changed

Lines changed: 212 additions & 11 deletions

File tree

inc/Abilities/WorkspaceAbilities.php

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2494,7 +2494,10 @@ public static function getCapabilities( array $input ): array { // phpcs:ignor
24942494
*/
24952495
public static function showRepo( array $input ): array|\WP_Error {
24962496
if ( RemoteWorkspaceBackend::should_handle() ) {
2497-
return ( new RemoteWorkspaceBackend() )->show($input['name'] ?? '');
2497+
$result = ( new RemoteWorkspaceBackend() )->show($input['name'] ?? '');
2498+
if ( ! self::shouldFallbackToLocalWorkspace($result) ) {
2499+
return $result;
2500+
}
24982501
}
24992502

25002503
$workspace = new Workspace();
@@ -3398,16 +3401,6 @@ public static function prRebase( array $input ): array|\WP_Error {
33983401
* @return array
33993402
*/
34003403
public static function worktreeAdd( array $input ): array|\WP_Error {
3401-
if ( RemoteWorkspaceBackend::should_handle() ) {
3402-
$result = ( new RemoteWorkspaceBackend() )->worktree_add(
3403-
$input['repo'] ?? '',
3404-
$input['branch'] ?? '',
3405-
$input['from'] ?? null
3406-
);
3407-
return self::decorate_remote_workspace_result('worktree_add', $result);
3408-
}
3409-
3410-
$workspace = new Workspace();
34113404
// Default inject_context=true; only false when explicitly provided.
34123405
$inject_context = array_key_exists('inject_context', $input) ? (bool) $input['inject_context'] : true;
34133406
// Default bootstrap=true; only false when explicitly provided.
@@ -3424,6 +3417,19 @@ public static function worktreeAdd( array $input ): array|\WP_Error {
34243417
if ( isset($input['task_ref']) && '' !== trim( (string) $input['task_ref']) ) {
34253418
$task['task_ref'] = (string) $input['task_ref'];
34263419
}
3420+
3421+
if ( RemoteWorkspaceBackend::should_handle() ) {
3422+
$result = ( new RemoteWorkspaceBackend() )->worktree_add(
3423+
$input['repo'] ?? '',
3424+
$input['branch'] ?? '',
3425+
$input['from'] ?? null
3426+
);
3427+
if ( ! self::shouldFallbackToLocalWorkspace($result) ) {
3428+
return self::decorate_remote_workspace_result('worktree_add', $result);
3429+
}
3430+
}
3431+
3432+
$workspace = new Workspace();
34273433
return $workspace->worktree_add(
34283434
$input['repo'] ?? '',
34293435
$input['branch'] ?? '',
@@ -3437,6 +3443,13 @@ public static function worktreeAdd( array $input ): array|\WP_Error {
34373443
);
34383444
}
34393445

3446+
/**
3447+
* Whether a remote-backend lookup miss should be retried against local workspace discovery.
3448+
*/
3449+
private static function shouldFallbackToLocalWorkspace( mixed $result ): bool {
3450+
return is_wp_error($result) && 'remote_workspace_repo_not_found' === $result->get_error_code();
3451+
}
3452+
34403453
/**
34413454
* Refresh a worktree's injected context from the originating site.
34423455
*
Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
<?php
2+
/**
3+
* Pure-PHP smoke for local workspace fallback when remote state exists.
4+
*
5+
* Run: php tests/smoke-workspace-local-fallback.php
6+
*/
7+
8+
declare( strict_types=1 );
9+
10+
namespace DataMachineCode\Abilities {
11+
class AbilityRegistry
12+
{
13+
}
14+
15+
class GitHubAbilities
16+
{
17+
}
18+
}
19+
20+
namespace DataMachineCode\Workspace {
21+
class RemoteWorkspaceBackend
22+
{
23+
public static array $show_input = array();
24+
public static array $worktree_input = array();
25+
26+
public static function should_handle(): bool
27+
{
28+
return true;
29+
}
30+
31+
public function show( string $handle ): \WP_Error
32+
{
33+
self::$show_input = compact('handle');
34+
return new \WP_Error(
35+
'remote_workspace_repo_not_found',
36+
'Remote workspace repository "wpcom-codebox" is not registered. Call workspace_clone first.'
37+
);
38+
}
39+
40+
public function worktree_add( string $repo_name, string $branch, ?string $from = null ): \WP_Error
41+
{
42+
self::$worktree_input = compact('repo_name', 'branch', 'from');
43+
return new \WP_Error(
44+
'remote_workspace_repo_not_found',
45+
'Remote workspace repository "wpcom-codebox" is not registered. Call workspace_clone first.'
46+
);
47+
}
48+
}
49+
50+
class Workspace
51+
{
52+
public static array $show_input = array();
53+
public static array $worktree_input = array();
54+
55+
public function show_repo( string $handle ): array
56+
{
57+
self::$show_input = compact('handle');
58+
return array(
59+
'success' => true,
60+
'name' => $handle,
61+
'repo' => $handle,
62+
'is_worktree' => false,
63+
'path' => '/Users/chubes/Developer/' . $handle,
64+
'branch' => 'main',
65+
'remote' => 'git@github.a8c.com:Automattic/wpcom-codebox.git',
66+
'commit' => 'abc123 listed primary',
67+
'dirty' => 0,
68+
);
69+
}
70+
71+
public function worktree_add(
72+
string $repo,
73+
string $branch,
74+
?string $from = null,
75+
bool $inject_context = true,
76+
bool $bootstrap = true,
77+
bool $allow_stale = false,
78+
bool $rebase_base = false,
79+
bool $force = false,
80+
array $task = array()
81+
): array {
82+
self::$worktree_input = compact('repo', 'branch', 'from', 'inject_context', 'bootstrap', 'allow_stale', 'rebase_base', 'force', 'task');
83+
return array(
84+
'success' => true,
85+
'handle' => $repo . '@' . str_replace('/', '-', $branch),
86+
'path' => '/Users/chubes/Developer/' . $repo . '@' . str_replace('/', '-', $branch),
87+
);
88+
}
89+
}
90+
}
91+
92+
namespace DataMachineCode\Support {
93+
class RuntimeCapabilities
94+
{
95+
}
96+
97+
class GitRunner
98+
{
99+
}
100+
}
101+
102+
namespace {
103+
if ( ! defined('ABSPATH') ) {
104+
define('ABSPATH', __DIR__);
105+
}
106+
107+
class WP_Error
108+
{
109+
public function __construct( private string $code, private string $message, private array $data = array() )
110+
{
111+
}
112+
113+
public function get_error_code(): string
114+
{
115+
return $this->code;
116+
}
117+
118+
public function get_error_message(): string
119+
{
120+
return $this->message;
121+
}
122+
123+
public function get_error_data(): array
124+
{
125+
return $this->data;
126+
}
127+
}
128+
129+
function is_wp_error( $value ): bool
130+
{
131+
return $value instanceof WP_Error;
132+
}
133+
134+
require __DIR__ . '/../inc/Abilities/WorkspaceAbilities.php';
135+
136+
$failures = array();
137+
$assert = function ( string $label, bool $condition ) use ( &$failures ): void {
138+
if ( $condition ) {
139+
echo " ok {$label}\n";
140+
return;
141+
}
142+
143+
$failures[] = $label;
144+
echo " fail {$label}\n";
145+
};
146+
147+
echo "Workspace local fallback - smoke\n";
148+
149+
$show = \DataMachineCode\Abilities\WorkspaceAbilities::showRepo(
150+
array(
151+
'name' => 'wpcom-codebox',
152+
)
153+
);
154+
155+
$assert('remote show attempted first', 'wpcom-codebox' === ( \DataMachineCode\Workspace\RemoteWorkspaceBackend::$show_input['handle'] ?? '' ));
156+
$assert('local show fallback attempted', 'wpcom-codebox' === ( \DataMachineCode\Workspace\Workspace::$show_input['handle'] ?? '' ));
157+
$assert('show returns local listed primary', is_array($show) && '/Users/chubes/Developer/wpcom-codebox' === ( $show['path'] ?? '' ));
158+
159+
$worktree = \DataMachineCode\Abilities\WorkspaceAbilities::worktreeAdd(
160+
array(
161+
'repo' => 'wpcom-codebox',
162+
'branch' => 'fix/listed-primary-resolution',
163+
'from' => 'origin/main',
164+
'inject_context' => false,
165+
'bootstrap' => false,
166+
'allow_stale' => true,
167+
'rebase_base' => true,
168+
'force' => true,
169+
'task_url' => 'https://github.com/Extra-Chill/data-machine-code/issues/635',
170+
)
171+
);
172+
173+
$assert('remote worktree add attempted first', 'wpcom-codebox' === ( \DataMachineCode\Workspace\RemoteWorkspaceBackend::$worktree_input['repo_name'] ?? '' ));
174+
$assert('local worktree add fallback attempted', 'wpcom-codebox' === ( \DataMachineCode\Workspace\Workspace::$worktree_input['repo'] ?? '' ));
175+
$assert('worktree add preserves base ref', 'origin/main' === ( \DataMachineCode\Workspace\Workspace::$worktree_input['from'] ?? '' ));
176+
$assert('worktree add preserves local options', false === ( \DataMachineCode\Workspace\Workspace::$worktree_input['inject_context'] ?? null ) && true === ( \DataMachineCode\Workspace\Workspace::$worktree_input['allow_stale'] ?? null ));
177+
$assert('worktree add returns local worktree result', is_array($worktree) && 'wpcom-codebox@fix-listed-primary-resolution' === ( $worktree['handle'] ?? '' ));
178+
179+
if ( $failures ) {
180+
echo "\nFailures:\n";
181+
foreach ( $failures as $failure ) {
182+
echo " - {$failure}\n";
183+
}
184+
exit(1);
185+
}
186+
187+
echo "\nOK\n";
188+
}

0 commit comments

Comments
 (0)