Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F14024598
D16921.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
14 KB
Referenced Files
None
Subscribers
None
D16921.diff
View Options
diff --git a/.gitignore b/.gitignore
--- a/.gitignore
+++ b/.gitignore
@@ -7,6 +7,7 @@
# libphutil
/src/.phutil_module_cache
+/src/.cache
# User extensions
/externals/includes/*
diff --git a/scripts/arcanist.php b/scripts/arcanist.php
--- a/scripts/arcanist.php
+++ b/scripts/arcanist.php
@@ -36,6 +36,10 @@
'help' => pht('Use a specific authentication token.'),
),
array(
+ 'name' => 'anonymous',
+ 'help' => pht('Run workflow as a public user, without authenticating.'),
+ ),
+ array(
'name' => 'conduit-version',
'param' => 'version',
'help' => pht(
@@ -64,6 +68,7 @@
$conduit_timeout = $base_args->getArg('conduit-timeout');
$skip_arcconfig = $base_args->getArg('skip-arcconfig');
$custom_arcrc = $base_args->getArg('arcrc-file');
+$is_anonymous = $base_args->getArg('anonymous');
$load = $base_args->getArg('load-phutil-library');
$help = $base_args->getArg('help');
$args = array_values($base_args->getUnconsumedArgumentVector());
@@ -324,6 +329,10 @@
$conduit_token = $force_token;
}
+ if ($is_anonymous) {
+ $conduit_token = null;
+ }
+
$description = implode(' ', $original_argv);
$credentials = array(
'user' => $user_name,
@@ -333,6 +342,23 @@
);
$workflow->setConduitCredentials($credentials);
+ $basic_user = $configuration_manager->getConfigFromAnySource(
+ 'http.basicauth.user');
+ $basic_pass = $configuration_manager->getConfigFromAnySource(
+ 'http.basicauth.pass');
+
+ $engine = id(new ArcanistConduitEngine())
+ ->setConduitURI($conduit_uri)
+ ->setConduitToken($conduit_token)
+ ->setBasicAuthUser($basic_user)
+ ->setBasicAuthPass($basic_pass);
+
+ if ($conduit_timeout) {
+ $engine->setConduitTimeout($conduit_timeout);
+ }
+
+ $workflow->setConduitEngine($engine);
+
if ($need_auth) {
if ((!$user_name || !$certificate) && (!$conduit_token)) {
$arc = 'arc';
@@ -409,7 +435,7 @@
fwrite(STDERR, phutil_console_format(
"**%s** %s\n",
pht('Usage Exception:'),
- $ex->getMessage()));
+ rtrim($ex->getMessage())));
}
if ($config) {
diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -82,6 +82,8 @@
'ArcanistComprehensiveLintEngine' => 'lint/engine/ArcanistComprehensiveLintEngine.php',
'ArcanistConcatenationOperatorXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistConcatenationOperatorXHPASTLinterRule.php',
'ArcanistConcatenationOperatorXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistConcatenationOperatorXHPASTLinterRuleTestCase.php',
+ 'ArcanistConduitCall' => 'conduit/ArcanistConduitCall.php',
+ 'ArcanistConduitEngine' => 'conduit/ArcanistConduitEngine.php',
'ArcanistConfiguration' => 'configuration/ArcanistConfiguration.php',
'ArcanistConfigurationDrivenLintEngine' => 'lint/engine/ArcanistConfigurationDrivenLintEngine.php',
'ArcanistConfigurationDrivenUnitTestEngine' => 'unit/engine/ArcanistConfigurationDrivenUnitTestEngine.php',
@@ -496,6 +498,8 @@
'ArcanistComprehensiveLintEngine' => 'ArcanistLintEngine',
'ArcanistConcatenationOperatorXHPASTLinterRule' => 'ArcanistXHPASTLinterRule',
'ArcanistConcatenationOperatorXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase',
+ 'ArcanistConduitCall' => 'Phobject',
+ 'ArcanistConduitEngine' => 'Phobject',
'ArcanistConfiguration' => 'Phobject',
'ArcanistConfigurationDrivenLintEngine' => 'ArcanistLintEngine',
'ArcanistConfigurationDrivenUnitTestEngine' => 'ArcanistUnitTestEngine',
diff --git a/src/conduit/ArcanistConduitCall.php b/src/conduit/ArcanistConduitCall.php
new file mode 100644
--- /dev/null
+++ b/src/conduit/ArcanistConduitCall.php
@@ -0,0 +1,155 @@
+<?php
+
+final class ArcanistConduitCall
+ extends Phobject {
+
+ private $key;
+ private $engine;
+ private $method;
+ private $parameters;
+ private $future;
+
+ public function setKey($key) {
+ $this->key = $key;
+ return $this;
+ }
+
+ public function getKey() {
+ return $this->key;
+ }
+
+ public function setEngine(ArcanistConduitEngine $engine) {
+ $this->engine = $engine;
+ return $this;
+ }
+
+ public function getEngine() {
+ return $this->engine;
+ }
+
+ public function setMethod($method) {
+ $this->method = $method;
+ return $this;
+ }
+
+ public function getMethod() {
+ return $this->method;
+ }
+
+ public function setParameters(array $parameters) {
+ $this->parameters = $parameters;
+ return $this;
+ }
+
+ public function getParameters() {
+ return $this->parameters;
+ }
+
+ private function newFuture() {
+ if ($this->future) {
+ throw new Exception(
+ pht(
+ 'Call has previously generated a future. Create a '.
+ 'new call object for each API method invocation.'));
+ }
+
+ $method = $this->getMethod();
+ $parameters = $this->getParameters();
+ $future = $this->getEngine()->newFuture($this);
+ $this->future = $future;
+
+ return $this->future;
+ }
+
+ public function resolve() {
+ if (!$this->future) {
+ $this->newFuture();
+ }
+
+ $this->getEngine()->resolveFuture($this->getKey());
+
+ return $this->resolveFuture();
+ }
+
+ private function resolveFuture() {
+ $future = $this->future;
+
+ try {
+ $result = $future->resolve();
+ } catch (ConduitClientException $ex) {
+ switch ($ex->getErrorCode()) {
+ case 'ERR-INVALID-SESSION':
+ if (!$this->getEngine()->getConduitToken()) {
+ $this->raiseLoginRequired();
+ }
+ break;
+ case 'ERR-INVALID-AUTH':
+ $this->raiseInvalidAuth();
+ break;
+ }
+
+ throw $ex;
+ }
+
+ return $result;
+ }
+
+ private function raiseLoginRequired() {
+ $conduit_uri = $this->getEngine()->getConduitURI();
+ $conduit_uri = new PhutilURI($conduit_uri);
+ $conduit_uri->setPath('/');
+
+ $conduit_domain = $conduit_uri->getDomain();
+
+ $block = id(new PhutilConsoleBlock())
+ ->addParagraph(
+ tsprintf(
+ '**<bg:red> %s </bg>**',
+ pht('LOGIN REQUIRED')))
+ ->addParagraph(
+ pht(
+ 'You are trying to connect to a server ("%s") that you do not '.
+ 'have any stored credentials for, but the command you are '.
+ 'running requires authentication.',
+ $conduit_domain))
+ ->addParagraph(
+ pht(
+ 'To login and save credentials for this server, run this '.
+ 'command:'))
+ ->addParagraph(
+ tsprintf(
+ " $ arc install-certificate %s\n",
+ $conduit_uri));
+
+ throw new ArcanistUsageException($block->drawConsoleString());
+ }
+
+ private function raiseInvalidAuth() {
+ $conduit_uri = $this->getEngine()->getConduitURI();
+ $conduit_uri = new PhutilURI($conduit_uri);
+ $conduit_uri->setPath('/');
+
+ $conduit_domain = $conduit_uri->getDomain();
+
+ $block = id(new PhutilConsoleBlock())
+ ->addParagraph(
+ tsprintf(
+ '**<bg:red> %s </bg>**',
+ pht('INVALID CREDENTIALS')))
+ ->addParagraph(
+ pht(
+ 'Your stored credentials for this server ("%s") are not valid.',
+ $conduit_domain))
+ ->addParagraph(
+ pht(
+ 'To login and save valid credentials for this server, run this '.
+ 'command:'))
+ ->addParagraph(
+ tsprintf(
+ " $ arc install-certificate %s\n",
+ $conduit_uri));
+
+ throw new ArcanistUsageException($block->drawConsoleString());
+ }
+
+}
diff --git a/src/conduit/ArcanistConduitEngine.php b/src/conduit/ArcanistConduitEngine.php
new file mode 100644
--- /dev/null
+++ b/src/conduit/ArcanistConduitEngine.php
@@ -0,0 +1,162 @@
+<?php
+
+final class ArcanistConduitEngine
+ extends Phobject {
+
+ private $conduitURI;
+ private $conduitToken;
+
+ private $conduitTimeout;
+ private $basicAuthUser;
+ private $basicAuthPass;
+
+ private $client;
+ private $callKey = 0;
+ private $activeFutures = array();
+ private $resolvedFutures = array();
+
+ public function isCallable() {
+ return ($this->conduitURI !== null);
+ }
+
+ public function setConduitURI($conduit_uri) {
+ $this->conduitURI = $conduit_uri;
+ return $this;
+ }
+
+ public function getConduitURI() {
+ return $this->conduitURI;
+ }
+
+ public function setConduitToken($conduit_token) {
+ $this->conduitToken = $conduit_token;
+ return $this;
+ }
+
+ public function getConduitToken() {
+ 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();
+ }
+
+ $next_key = ++$this->callKey;
+
+ return id(new ArcanistConduitCall())
+ ->setKey($next_key)
+ ->setEngine($this)
+ ->setMethod($method)
+ ->setParameters($parameters);
+ }
+
+ public function newFuture(ArcanistConduitCall $call) {
+ $method = $call->getMethod();
+ $parameters = $call->getParameters();
+
+ $future = $this->getClient()->callMethod($method, $parameters);
+ $this->activeFutures[$call->getKey()] = $future;
+ return $future;
+ }
+
+ private function getClient() {
+ if (!$this->client) {
+ $conduit_uri = $this->getConduitURI();
+
+ $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());
+ }
+ }
+
+ return $client;
+ }
+
+ public function resolveFuture($key) {
+ if (isset($this->resolvedFutures[$key])) {
+ return;
+ }
+
+ if (!isset($this->activeFutures[$key])) {
+ throw new Exception(
+ pht(
+ 'No future with key "%s" is present in pool.',
+ $key));
+ }
+
+ $iterator = new FutureIterator($this->activeFutures);
+ foreach ($iterator as $future_key => $future) {
+ $this->resolvedFutures[$future_key] = $future;
+ unset($this->activeFutures[$future_key]);
+ if ($future_key == $key) {
+ break;
+ }
+ }
+
+ return;
+ }
+
+ private function raiseURIException() {
+ $list = id(new PhutilConsoleList())
+ ->addItem(
+ pht(
+ 'Run in a working copy with "phabricator.uri" set in ".arcconfig".'))
+ ->addItem(
+ pht(
+ 'Set a default URI with `arc set-config default <uri>`.'))
+ ->addItem(
+ pht(
+ 'Specify a URI explicitly with `--conduit-uri=<uri>`.'));
+
+ $block = id(new PhutilConsoleBlock())
+ ->addParagraph(
+ pht(
+ 'This command needs to communicate with Phabricator, but no '.
+ 'Phabricator URI is configured.'))
+ ->addList($list);
+
+ throw new ArcanistUsageException($block->drawConsoleString());
+ }
+
+}
diff --git a/src/workflow/ArcanistBrowseWorkflow.php b/src/workflow/ArcanistBrowseWorkflow.php
--- a/src/workflow/ArcanistBrowseWorkflow.php
+++ b/src/workflow/ArcanistBrowseWorkflow.php
@@ -53,19 +53,13 @@
return true;
}
- public function requiresConduit() {
- return true;
- }
-
- public function requiresAuthentication() {
- return true;
- }
-
public function desiresRepositoryAPI() {
return true;
}
public function run() {
+ $conduit = $this->getConduitEngine();
+
$console = PhutilConsole::getConsole();
$is_force = $this->getArgument('force');
@@ -80,11 +74,13 @@
}
$things = array_fuse($things);
- $objects = $this->getConduit()->callMethodSynchronous(
- 'phid.lookup',
- array(
- 'names' => array_keys($things),
- ));
+ $method = 'phid.lookup';
+ $params = array(
+ 'names' => array_keys($things),
+ );
+
+ $objects = $conduit->newCall($method, $params)
+ ->resolve();
$uris = array();
foreach ($objects as $name => $object) {
@@ -123,12 +119,15 @@
}
if ($commits) {
- $commit_info = $this->getConduit()->callMethodSynchronous(
- 'diffusion.querycommits',
- array(
- 'repositoryPHID' => $this->getRepositoryPHID(),
- 'names' => array_keys($commits),
- ));
+ $method = 'diffusion.querycommits';
+
+ $params = array(
+ 'repositoryPHID' => $this->getRepositoryPHID(),
+ 'names' => array_keys($commits),
+ );
+
+ $commit_info = $conduit->newCall($method, $params)
+ ->resolve();
foreach ($commit_info['identifierMap'] as $ckey => $cphid) {
$thing = $commits[$ckey];
diff --git a/src/workflow/ArcanistWorkflow.php b/src/workflow/ArcanistWorkflow.php
--- a/src/workflow/ArcanistWorkflow.php
+++ b/src/workflow/ArcanistWorkflow.php
@@ -69,6 +69,7 @@
private $repositoryVersion;
private $changeCache = array();
+ private $conduitEngine;
public function __construct() {}
@@ -1767,9 +1768,9 @@
}
try {
- $results = $this->getConduit()->callMethodSynchronous(
- 'repository.query',
- $query);
+ $method = 'repository.query';
+ $results = $this->getConduitEngine()->newCall($method, $query)
+ ->resolve();
} catch (ConduitClientException $ex) {
if ($ex->getErrorCode() == 'ERR-CONDUIT-CALL') {
$reasons[] = pht(
@@ -2062,5 +2063,14 @@
return $map;
}
+ final public function setConduitEngine(
+ ArcanistConduitEngine $conduit_engine) {
+ $this->conduitEngine = $conduit_engine;
+ return $this;
+ }
+
+ final public function getConduitEngine() {
+ return $this->conduitEngine;
+ }
}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, Nov 8, 11:02 AM (7 h, 45 m ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
6713186
Default Alt Text
D16921.diff (14 KB)
Attached To
Mode
D16921: Begin modernizing the Arcanist interaction with Conduit
Attached
Detach File
Event Timeline
Log In to Comment