diff --git a/inc/Abilities/WorkspaceAbilities.php b/inc/Abilities/WorkspaceAbilities.php index d6342c97..739cc693 100644 --- a/inc/Abilities/WorkspaceAbilities.php +++ b/inc/Abilities/WorkspaceAbilities.php @@ -841,6 +841,14 @@ private function registerAbilities(): void { 'type' => 'boolean', 'description' => 'Permit mutation on the primary checkout (default false). Worktrees are always allowed.', ), + 'remote' => array( + 'type' => 'string', + 'description' => 'Remote name for pull when branch is supplied (default origin).', + ), + 'branch' => array( + 'type' => 'string', + 'description' => 'Remote branch to pull. Useful when the checkout is detached.', + ), ), 'required' => array( 'name' ), ), @@ -2991,7 +2999,9 @@ public static function gitPull( array $input ): array|\WP_Error { return $workspace->git_pull( $input['name'] ?? '', ! empty($input['allow_dirty']), - ! empty($input['allow_primary_mutation']) + ! empty($input['allow_primary_mutation']), + (string) ( $input['remote'] ?? 'origin' ), + isset($input['branch']) ? (string) $input['branch'] : null ); } diff --git a/inc/Cli/Commands/WorkspaceCommand.php b/inc/Cli/Commands/WorkspaceCommand.php index e23998f5..dd13e9f7 100644 --- a/inc/Cli/Commands/WorkspaceCommand.php +++ b/inc/Cli/Commands/WorkspaceCommand.php @@ -2554,10 +2554,10 @@ private function resolveAtFile( string $value ): string { * : Permit mutating ops (pull/add/commit/push) on the primary checkout. Default-deny — use a worktree handle (`@`) instead whenever possible. * * [--remote=] - * : Remote name for push (default: origin). + * : Remote name for pull/push (default: origin). * * [--branch=] - * : Branch override for push. + * : Branch override for pull/push. For pull, supplies an explicit remote branch when the checkout is detached. * * [--from=] * : From ref for diff. @@ -2640,6 +2640,10 @@ public function git( array $args, array $assoc_args ): void { if ( 'pull' === $operation ) { $input['allow_dirty'] = ! empty($assoc_args['allow-dirty']); + $input['remote'] = $assoc_args['remote'] ?? 'origin'; + if ( ! empty($assoc_args['branch']) ) { + $input['branch'] = (string) $assoc_args['branch']; + } } if ( 'add' === $operation ) { diff --git a/inc/Workspace/WorkspaceGitOperations.php b/inc/Workspace/WorkspaceGitOperations.php index c85bc945..4de755a6 100644 --- a/inc/Workspace/WorkspaceGitOperations.php +++ b/inc/Workspace/WorkspaceGitOperations.php @@ -77,7 +77,7 @@ public function git_status( string $handle ): array|\WP_Error { * @param bool $allow_dirty Allow pull with dirty working tree. * @return array */ - public function git_pull( string $handle, bool $allow_dirty = false, bool $allow_primary_mutation = false ): array|\WP_Error { + public function git_pull( string $handle, bool $allow_dirty = false, bool $allow_primary_mutation = false, string $remote = 'origin', ?string $branch = null ): array|\WP_Error { if ( WorkspaceAliasResolver::is_context_repository($handle) ) { return WorkspaceAliasResolver::mutation_error($handle, 'git pull'); } @@ -107,7 +107,18 @@ public function git_pull( string $handle, bool $allow_dirty = false, bool $allow return new \WP_Error('dirty_working_tree', 'Working tree is dirty. Commit/stash changes first or pass allow_dirty=true.', array( 'status' => 400 )); } - $result = $this->run_git($repo_path, 'pull --ff-only'); + $remote = trim($remote); + $branch = null !== $branch ? trim($branch) : null; + if ( '' === $remote ) { + $remote = 'origin'; + } + + $command = 'pull --ff-only'; + if ( null !== $branch && '' !== $branch ) { + $command .= ' ' . escapeshellarg($remote) . ' ' . escapeshellarg($branch); + } + + $result = $this->run_git($repo_path, $command); if ( is_wp_error($result) ) { return $result;