diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index a7e43553..acb3b605 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -139,6 +139,7 @@ phutil_register_library_map(array( 'ArcanistConcatenationOperatorXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistConcatenationOperatorXHPASTLinterRuleTestCase.php', 'ArcanistConduitCall' => 'conduit/ArcanistConduitCall.php', 'ArcanistConduitEngine' => 'conduit/ArcanistConduitEngine.php', + 'ArcanistConduitException' => 'conduit/ArcanistConduitException.php', 'ArcanistConfigOption' => 'config/option/ArcanistConfigOption.php', 'ArcanistConfigurationDrivenLintEngine' => 'lint/engine/ArcanistConfigurationDrivenLintEngine.php', 'ArcanistConfigurationDrivenUnitTestEngine' => 'unit/engine/ArcanistConfigurationDrivenUnitTestEngine.php', @@ -341,6 +342,7 @@ phutil_register_library_map(array( 'ArcanistNoLintLinterTestCase' => 'lint/linter/__tests__/ArcanistNoLintLinterTestCase.php', 'ArcanistNoParentScopeXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistNoParentScopeXHPASTLinterRule.php', 'ArcanistNoParentScopeXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistNoParentScopeXHPASTLinterRuleTestCase.php', + 'ArcanistNoURIConduitException' => 'conduit/ArcanistNoURIConduitException.php', 'ArcanistNoneLintRenderer' => 'lint/renderer/ArcanistNoneLintRenderer.php', 'ArcanistObjectOperatorSpacingXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistObjectOperatorSpacingXHPASTLinterRule.php', 'ArcanistObjectOperatorSpacingXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistObjectOperatorSpacingXHPASTLinterRuleTestCase.php', @@ -1163,7 +1165,7 @@ phutil_register_library_map(array( 'ArcanistAnoidWorkflow' => 'ArcanistWorkflow', 'ArcanistArcConfigurationEngineExtension' => 'ArcanistConfigurationEngineExtension', 'ArcanistArcToolset' => 'ArcanistToolset', - 'ArcanistArcWorkflow' => 'ArcanistWorkflow', + 'ArcanistArcWorkflow' => 'Phobject', 'ArcanistArrayCombineXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistArrayCombineXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistArrayIndexSpacingXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', @@ -1242,6 +1244,7 @@ phutil_register_library_map(array( 'ArcanistConcatenationOperatorXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistConduitCall' => 'Phobject', 'ArcanistConduitEngine' => 'Phobject', + 'ArcanistConduitException' => 'Exception', 'ArcanistConfigOption' => 'Phobject', 'ArcanistConfigurationDrivenLintEngine' => 'ArcanistLintEngine', 'ArcanistConfigurationDrivenUnitTestEngine' => 'ArcanistUnitTestEngine', @@ -1444,6 +1447,7 @@ phutil_register_library_map(array( 'ArcanistNoLintLinterTestCase' => 'ArcanistLinterTestCase', 'ArcanistNoParentScopeXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistNoParentScopeXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', + 'ArcanistNoURIConduitException' => 'ArcanistConduitException', 'ArcanistNoneLintRenderer' => 'ArcanistLintRenderer', 'ArcanistObjectOperatorSpacingXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistObjectOperatorSpacingXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', diff --git a/src/conduit/ArcanistConduitEngine.php b/src/conduit/ArcanistConduitEngine.php index d05859a2..4d4a3349 100644 --- a/src/conduit/ArcanistConduitEngine.php +++ b/src/conduit/ArcanistConduitEngine.php @@ -6,10 +6,6 @@ final class ArcanistConduitEngine private $conduitURI; private $conduitToken; - private $conduitTimeout; - private $basicAuthUser; - private $basicAuthPass; - private $client; private $callKey = 0; private $activeFutures = array(); @@ -37,33 +33,6 @@ final class ArcanistConduitEngine return $this->conduitToken; } - public function setConduitTimeout($conduit_timeout) { - $this->conduitTimeout = $conduit_timeout; - return $this; - } - - public function getConduitTimeout() { - return $this->conduitTimeout; - } - - public function setBasicAuthUser($basic_auth_user) { - $this->basicAuthUser = $basic_auth_user; - return $this; - } - - public function getBasicAuthUser() { - return $this->basicAuthUser; - } - - public function setBasicAuthPass($basic_auth_pass) { - $this->basicAuthPass = $basic_auth_pass; - return $this; - } - - public function getBasicAuthPass() { - return $this->basicAuthPass; - } - public function newCall($method, array $parameters) { if ($this->conduitURI == null) { $this->raiseURIException(); @@ -97,17 +66,6 @@ final class ArcanistConduitEngine $client = new ConduitClient($conduit_uri); - $timeout = $this->getConduitTimeout(); - if ($timeout) { - $client->setTimeout($timeout); - } - - $basic_user = $this->getBasicAuthUser(); - $basic_pass = $this->getBasicAuthPass(); - if ($basic_user !== null || $basic_pass !== null) { - $client->setBasicAuthCredentials($basic_user, $basic_pass); - } - $token = $this->getConduitToken(); if ($token) { $client->setConduitToken($this->getConduitToken()); diff --git a/src/conduit/ArcanistConduitException.php b/src/conduit/ArcanistConduitException.php new file mode 100644 index 00000000..f17e2ae8 --- /dev/null +++ b/src/conduit/ArcanistConduitException.php @@ -0,0 +1,3 @@ + pht('Command to use to invoke a web browser.'), 'example' => '"gnome-www-browser"', ), - 'http.basicauth.user' => array( - 'type' => 'string', - 'help' => pht('Username to use for basic auth over HTTP transports.'), - 'example' => '"bob"', - ), - 'http.basicauth.pass' => array( - 'type' => 'string', - 'help' => pht('Password to use for basic auth over HTTP transports.'), - 'example' => '"bobhasasecret"', - ), - */ diff --git a/src/future/http/HTTPSFuture.php b/src/future/http/HTTPSFuture.php index 255e7f68..3161a93b 100644 --- a/src/future/http/HTTPSFuture.php +++ b/src/future/http/HTTPSFuture.php @@ -321,7 +321,8 @@ final class HTTPSFuture extends BaseHTTPFuture { // work, give up and yell at the user. if (!$this->getCABundle()) { - $caroot = dirname(phutil_get_library_root('phutil')).'/resources/ssl/'; + $arcanist_root = dirname(phutil_get_library_root('arcanist')); + $caroot = $arcanist_root.'/resources/ssl/'; $ini_val = ini_get('curl.cainfo'); if (self::getGlobalCABundle()) { $this->setCABundleFromPath(self::getGlobalCABundle()); diff --git a/src/toolset/ArcanistWorkflow.php b/src/toolset/ArcanistWorkflow.php index 58f11acb..a8d6c3f7 100644 --- a/src/toolset/ArcanistWorkflow.php +++ b/src/toolset/ArcanistWorkflow.php @@ -7,6 +7,7 @@ abstract class ArcanistWorkflow extends Phobject { private $arguments; private $configurationEngine; private $configurationSourceList; + private $conduitEngine; /** * Return the command used to invoke this workflow from the command like, @@ -48,7 +49,6 @@ abstract class ArcanistWorkflow extends Phobject { return null; } - public function newPhutilWorkflow() { $arguments = $this->getWorkflowArguments(); assert_instances_of($arguments, 'ArcanistWorkflowArgument'); @@ -164,4 +164,25 @@ abstract class ArcanistWorkflow extends Phobject { return new ArcanistWorkflowInformation(); } + final protected function getConduitEngine() { + if (!$this->conduitEngine) { + $conduit_uri = $this->getConfig('phabricator.uri'); + + if (!strlen($conduit_uri)) { + throw new ArcanistNoURIConduitException( + pht( + 'This workflow is trying to connect to the Phabricator API, but '. + 'no Phabricator URI is configured. Run "arc help connect" for '. + 'guidance.')); + } + + $conduit_engine = id(new ArcanistConduitEngine()) + ->setConduitURI($conduit_uri); + + $this->conduitEngine = $conduit_engine; + } + + return $this->conduitEngine; + } + } diff --git a/src/workflow/ArcanistArcWorkflow.php b/src/workflow/ArcanistArcWorkflow.php index c0503fde..af3c0709 100644 --- a/src/workflow/ArcanistArcWorkflow.php +++ b/src/workflow/ArcanistArcWorkflow.php @@ -33,7 +33,7 @@ * @task scratch Scratch Files * @task phabrep Phabricator Repositories */ -abstract class ArcanistArcWorkflow extends ArcanistWorkflow { +abstract class ArcanistArcWorkflow extends Phobject { const COMMIT_DISABLE = 0; const COMMIT_ALLOW = 1; diff --git a/src/workflow/ArcanistCallConduitWorkflow.php b/src/workflow/ArcanistCallConduitWorkflow.php index c6d3a464..92273037 100644 --- a/src/workflow/ArcanistCallConduitWorkflow.php +++ b/src/workflow/ArcanistCallConduitWorkflow.php @@ -9,63 +9,54 @@ final class ArcanistCallConduitWorkflow extends ArcanistWorkflow { return 'call-conduit'; } - public function getCommandSynopses() { - return phutil_console_format(<<newWorkflowInformation() + ->addExample(pht('**call-conduit** __method__')) + ->setHelp($help); } - public function getCommandHelp() { - return phutil_console_format(<< 'method', + $this->newWorkflowArgument('argv') + ->setWildcard(true), ); } - protected function shouldShellComplete() { - return false; - } + public function runWorkflow() { + $argv = $this->getArgument('argv'); - public function requiresConduit() { - return true; - } - - public function requiresAuthentication() { - return true; - } - - public function run() { - $method = $this->getArgument('method', array()); - if (count($method) !== 1) { - throw new ArcanistUsageException( - pht('Provide exactly one Conduit method name.')); + if (!$argv) { + // TOOLSETS: We should call "conduit.query" and list available methods + // here. + throw new PhutilArgumentUsageException( + pht( + 'Provide the name of the Conduit method you want to call on the '. + 'command line.')); + } else if (count($argv) > 1) { + throw new PhutilArgumentUsageException( + pht( + 'Provide the name of only one method to call.')); } - $method = reset($method); - $console = PhutilConsole::getConsole(); + $method = head($argv); + if (!function_exists('posix_isatty') || posix_isatty(STDIN)) { - $console->writeErr( - "%s\n", - pht('Waiting for JSON parameters on stdin...')); + fprintf( + STDERR, + tsprintf( + "%s\n", + pht('Waiting for JSON parameters on stdin...'))); } + $params = @file_get_contents('php://stdin'); try { $params = phutil_json_decode($params); @@ -77,20 +68,24 @@ EOTEXT $error = null; $error_message = null; try { - $result = $this->getConduit()->callMethodSynchronous( - $method, - $params); + $result = $this->getConduitEngine()->resolveCall($method, $params); } catch (ConduitClientException $ex) { + + // TOOLSETS: We should use "conduit.query" to suggest similar calls if + // it looks like the user called a method which does not exist. + $error = $ex->getErrorCode(); $error_message = $ex->getMessage(); $result = null; } - echo json_encode(array( - 'error' => $error, - 'errorMessage' => $error_message, - 'response' => $result, - ))."\n"; + echo id(new PhutilJSON()) + ->encodeFormatted( + array( + 'error' => $error, + 'errorMessage' => $error_message, + 'response' => $result, + )); return 0; } diff --git a/support/ArcanistRuntime.php b/support/ArcanistRuntime.php index 2fd61c05..44333500 100644 --- a/support/ArcanistRuntime.php +++ b/support/ArcanistRuntime.php @@ -21,6 +21,13 @@ final class ArcanistRuntime { try { return $this->executeCore($argv); + } catch (ArcanistConduitException $ex) { + fwrite( + STDERR, + tsprintf( + "**%s:** %s\n", + pht('Conduit Exception'), + $ex->getMessage())); } catch (PhutilArgumentUsageException $ex) { fwrite( STDERR,