Page MenuHomePhabricator

D21104.id50266.diff
No OneTemporary

D21104.id50266.diff

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
@@ -189,9 +189,7 @@
'ArcanistFileConfigurationSource' => 'config/source/ArcanistFileConfigurationSource.php',
'ArcanistFileDataRef' => 'upload/ArcanistFileDataRef.php',
'ArcanistFileRef' => 'ref/file/ArcanistFileRef.php',
- 'ArcanistFileSymbolHardpointQuery' => 'ref/file/ArcanistFileSymbolHardpointQuery.php',
'ArcanistFileSymbolRef' => 'ref/file/ArcanistFileSymbolRef.php',
- 'ArcanistFileSymbolRefInspector' => 'ref/file/ArcanistFileSymbolRefInspector.php',
'ArcanistFileUploader' => 'upload/ArcanistFileUploader.php',
'ArcanistFilenameLinter' => 'lint/linter/ArcanistFilenameLinter.php',
'ArcanistFilenameLinterTestCase' => 'lint/linter/__tests__/ArcanistFilenameLinterTestCase.php',
@@ -361,6 +359,8 @@
'ArcanistParenthesesSpacingXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistParenthesesSpacingXHPASTLinterRuleTestCase.php',
'ArcanistParseStrUseXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistParseStrUseXHPASTLinterRule.php',
'ArcanistParseStrUseXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistParseStrUseXHPASTLinterRuleTestCase.php',
+ 'ArcanistPasteRef' => 'ref/paste/ArcanistPasteRef.php',
+ 'ArcanistPasteSymbolRef' => 'ref/paste/ArcanistPasteSymbolRef.php',
'ArcanistPasteWorkflow' => 'workflow/ArcanistPasteWorkflow.php',
'ArcanistPatchWorkflow' => 'workflow/ArcanistPatchWorkflow.php',
'ArcanistPhpLinter' => 'lint/linter/ArcanistPhpLinter.php',
@@ -401,9 +401,7 @@
'ArcanistRevisionCommitMessageHardpointQuery' => 'ref/revision/ArcanistRevisionCommitMessageHardpointQuery.php',
'ArcanistRevisionRef' => 'ref/revision/ArcanistRevisionRef.php',
'ArcanistRevisionRefSource' => 'ref/ArcanistRevisionRefSource.php',
- 'ArcanistRevisionSymbolHardpointQuery' => 'ref/revision/ArcanistRevisionSymbolHardpointQuery.php',
'ArcanistRevisionSymbolRef' => 'ref/revision/ArcanistRevisionSymbolRef.php',
- 'ArcanistRevisionSymbolRefInspector' => 'ref/revision/ArcanistRevisionSymbolRefInspector.php',
'ArcanistRuboCopLinter' => 'lint/linter/ArcanistRuboCopLinter.php',
'ArcanistRuboCopLinterTestCase' => 'lint/linter/__tests__/ArcanistRuboCopLinterTestCase.php',
'ArcanistRubyLinter' => 'lint/linter/ArcanistRubyLinter.php',
@@ -424,6 +422,9 @@
'ArcanistSetting' => 'configuration/ArcanistSetting.php',
'ArcanistSettings' => 'configuration/ArcanistSettings.php',
'ArcanistShellCompleteWorkflow' => 'toolset/workflow/ArcanistShellCompleteWorkflow.php',
+ 'ArcanistSimpleSymbolHardpointQuery' => 'ref/simple/ArcanistSimpleSymbolHardpointQuery.php',
+ 'ArcanistSimpleSymbolRef' => 'ref/simple/ArcanistSimpleSymbolRef.php',
+ 'ArcanistSimpleSymbolRefInspector' => 'ref/simple/ArcanistSimpleSymbolRefInspector.php',
'ArcanistSingleLintEngine' => 'lint/engine/ArcanistSingleLintEngine.php',
'ArcanistSlownessXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistSlownessXHPASTLinterRule.php',
'ArcanistSlownessXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistSlownessXHPASTLinterRuleTestCase.php',
@@ -439,6 +440,8 @@
'ArcanistSymbolRef' => 'ref/symbol/ArcanistSymbolRef.php',
'ArcanistSyntaxErrorXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistSyntaxErrorXHPASTLinterRule.php',
'ArcanistSystemConfigurationSource' => 'config/source/ArcanistSystemConfigurationSource.php',
+ 'ArcanistTaskRef' => 'ref/task/ArcanistTaskRef.php',
+ 'ArcanistTaskSymbolRef' => 'ref/task/ArcanistTaskSymbolRef.php',
'ArcanistTasksWorkflow' => 'workflow/ArcanistTasksWorkflow.php',
'ArcanistTautologicalExpressionXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistTautologicalExpressionXHPASTLinterRule.php',
'ArcanistTautologicalExpressionXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistTautologicalExpressionXHPASTLinterRuleTestCase.php',
@@ -1171,9 +1174,7 @@
'ArcanistRef',
'ArcanistDisplayRefInterface',
),
- 'ArcanistFileSymbolHardpointQuery' => 'ArcanistRuntimeHardpointQuery',
- 'ArcanistFileSymbolRef' => 'ArcanistSymbolRef',
- 'ArcanistFileSymbolRefInspector' => 'ArcanistRefInspector',
+ 'ArcanistFileSymbolRef' => 'ArcanistSimpleSymbolRef',
'ArcanistFileUploader' => 'Phobject',
'ArcanistFilenameLinter' => 'ArcanistLinter',
'ArcanistFilenameLinterTestCase' => 'ArcanistLinterTestCase',
@@ -1343,7 +1344,12 @@
'ArcanistParenthesesSpacingXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase',
'ArcanistParseStrUseXHPASTLinterRule' => 'ArcanistXHPASTLinterRule',
'ArcanistParseStrUseXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase',
- 'ArcanistPasteWorkflow' => 'ArcanistWorkflow',
+ 'ArcanistPasteRef' => array(
+ 'ArcanistRef',
+ 'ArcanistDisplayRefInterface',
+ ),
+ 'ArcanistPasteSymbolRef' => 'ArcanistSimpleSymbolRef',
+ 'ArcanistPasteWorkflow' => 'ArcanistArcWorkflow',
'ArcanistPatchWorkflow' => 'ArcanistWorkflow',
'ArcanistPhpLinter' => 'ArcanistExternalLinter',
'ArcanistPhpLinterTestCase' => 'ArcanistExternalLinterTestCase',
@@ -1386,9 +1392,7 @@
'ArcanistDisplayRefInterface',
),
'ArcanistRevisionRefSource' => 'Phobject',
- 'ArcanistRevisionSymbolHardpointQuery' => 'ArcanistRuntimeHardpointQuery',
- 'ArcanistRevisionSymbolRef' => 'ArcanistSymbolRef',
- 'ArcanistRevisionSymbolRefInspector' => 'ArcanistRefInspector',
+ 'ArcanistRevisionSymbolRef' => 'ArcanistSimpleSymbolRef',
'ArcanistRuboCopLinter' => 'ArcanistExternalLinter',
'ArcanistRuboCopLinterTestCase' => 'ArcanistExternalLinterTestCase',
'ArcanistRubyLinter' => 'ArcanistExternalLinter',
@@ -1408,6 +1412,9 @@
'ArcanistSetting' => 'Phobject',
'ArcanistSettings' => 'Phobject',
'ArcanistShellCompleteWorkflow' => 'ArcanistWorkflow',
+ 'ArcanistSimpleSymbolHardpointQuery' => 'ArcanistRuntimeHardpointQuery',
+ 'ArcanistSimpleSymbolRef' => 'ArcanistSymbolRef',
+ 'ArcanistSimpleSymbolRefInspector' => 'ArcanistRefInspector',
'ArcanistSingleLintEngine' => 'ArcanistLintEngine',
'ArcanistSlownessXHPASTLinterRule' => 'ArcanistXHPASTLinterRule',
'ArcanistSlownessXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase',
@@ -1423,6 +1430,11 @@
'ArcanistSymbolRef' => 'ArcanistRef',
'ArcanistSyntaxErrorXHPASTLinterRule' => 'ArcanistXHPASTLinterRule',
'ArcanistSystemConfigurationSource' => 'ArcanistFilesystemConfigurationSource',
+ 'ArcanistTaskRef' => array(
+ 'ArcanistRef',
+ 'ArcanistDisplayRefInterface',
+ ),
+ 'ArcanistTaskSymbolRef' => 'ArcanistSimpleSymbolRef',
'ArcanistTasksWorkflow' => 'ArcanistWorkflow',
'ArcanistTautologicalExpressionXHPASTLinterRule' => 'ArcanistXHPASTLinterRule',
'ArcanistTautologicalExpressionXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase',
diff --git a/src/conduit/ConduitSearchFuture.php b/src/conduit/ConduitSearchFuture.php
--- a/src/conduit/ConduitSearchFuture.php
+++ b/src/conduit/ConduitSearchFuture.php
@@ -6,6 +6,7 @@
private $conduitEngine;
private $method;
private $constraints;
+ private $attachments;
private $objects = array();
private $cursor;
@@ -28,7 +29,7 @@
return $this->method;
}
- public function setConstraints($constraints) {
+ public function setConstraints(array $constraints) {
$this->constraints = $constraints;
return $this;
}
@@ -37,6 +38,15 @@
return $this->constraints;
}
+ public function setAttachments(array $attachments) {
+ $this->attachments = $attachments;
+ return $this;
+ }
+
+ public function getAttachments() {
+ return $this->attachments;
+ }
+
public function isReady() {
if ($this->hasResult()) {
return true;
@@ -86,6 +96,10 @@
'constraints' => $constraints,
);
+ if ($this->attachments) {
+ $parameters['attachments'] = $this->attachments;
+ }
+
if ($this->cursor !== null) {
$parameters['after'] = (string)$this->cursor;
}
diff --git a/src/inspector/ArcanistRefInspector.php b/src/inspector/ArcanistRefInspector.php
--- a/src/inspector/ArcanistRefInspector.php
+++ b/src/inspector/ArcanistRefInspector.php
@@ -6,11 +6,24 @@
abstract public function getInspectFunctionName();
abstract public function newInspectRef(array $argv);
+ protected function newInspectors() {
+ return array($this);
+ }
+
final public static function getAllInspectors() {
- return id(new PhutilClassMapQuery())
+ $base_inspectors = id(new PhutilClassMapQuery())
->setAncestorClass(__CLASS__)
- ->setUniqueMethod('getInspectFunctionName')
->execute();
+
+ $results = array();
+
+ foreach ($base_inspectors as $base_inspector) {
+ foreach ($base_inspector->newInspectors() as $inspector) {
+ $results[] = $inspector;
+ }
+ }
+
+ return mpull($results, null, 'getInspectFunctionName');
}
}
diff --git a/src/log/ArcanistLogEngine.php b/src/log/ArcanistLogEngine.php
--- a/src/log/ArcanistLogEngine.php
+++ b/src/log/ArcanistLogEngine.php
@@ -92,4 +92,14 @@
->setMessage($message));
}
+ public function writeWaitingForInput() {
+ if (!phutil_is_interactive()) {
+ return;
+ }
+
+ $this->writeStatus(
+ pht('INPUT'),
+ pht('Waiting for input on stdin...'));
+ }
+
}
diff --git a/src/ref/ArcanistDisplayRef.php b/src/ref/ArcanistDisplayRef.php
--- a/src/ref/ArcanistDisplayRef.php
+++ b/src/ref/ArcanistDisplayRef.php
@@ -6,6 +6,7 @@
ArcanistTerminalStringInterface {
private $ref;
+ private $uri;
public function setRef(ArcanistRef $ref) {
$this->ref = $ref;
@@ -16,6 +17,15 @@
return $this->ref;
}
+ public function setURI($uri) {
+ $this->uri = $uri;
+ return $this;
+ }
+
+ public function getURI() {
+ return $this->uri;
+ }
+
public function newTerminalString() {
$ref = $this->getRef();
@@ -60,9 +70,20 @@
}
$ref = $this->getRef();
- return tsprintf(
+ $output = array();
+
+ $output[] = tsprintf(
"<bg:cyan>** * **</bg> %s\n",
$display_text);
+
+ $uri = $this->getURI();
+ if ($uri !== null) {
+ $output[] = tsprintf(
+ "<bg:cyan>** :// **</bg> __%s__\n",
+ $uri);
+ }
+
+ return $output;
}
}
diff --git a/src/ref/file/ArcanistFileSymbolRef.php b/src/ref/file/ArcanistFileSymbolRef.php
--- a/src/ref/file/ArcanistFileSymbolRef.php
+++ b/src/ref/file/ArcanistFileSymbolRef.php
@@ -1,47 +1,30 @@
<?php
final class ArcanistFileSymbolRef
- extends ArcanistSymbolRef {
-
- private $type;
-
- const TYPE_ID = 'id';
- const TYPE_PHID = 'phid';
+ extends ArcanistSimpleSymbolRef {
public function getRefDisplayName() {
return pht('File Symbol "%s"', $this->getSymbol());
}
- protected function newCacheKeyParts() {
- return array(
- sprintf('type(%s)', $this->type),
- );
+ protected function getSimpleSymbolPrefixPattern() {
+ return '[Ff]?';
+ }
+
+ protected function getSimpleSymbolPHIDType() {
+ return 'FILE';
+ }
+
+ public function getSimpleSymbolConduitSearchMethodName() {
+ return 'file.search';
}
- public function getSymbolType() {
- return $this->type;
+ public function getSimpleSymbolInspectFunctionName() {
+ return 'file';
}
- protected function resolveSymbol($symbol) {
- $matches = null;
-
- $is_id = preg_match('/^[Ff]?([1-9]\d*)\z/', $symbol, $matches);
- if ($is_id) {
- $this->type = self::TYPE_ID;
- return (int)$matches[1];
- }
-
- $is_phid = preg_match('/^PHID-FILE-\S+\z/', $symbol, $matches);
- if ($is_phid) {
- $this->type = self::TYPE_PHID;
- return $matches[0];
- }
-
- throw new PhutilArgumentUsageException(
- pht(
- 'The format of file symbol "%s" is unrecognized. Expected a '.
- 'monogram like "F123", or an ID like "123", or a file PHID.',
- $symbol));
+ public function newSimpleSymbolObjectRef() {
+ return new ArcanistFileRef();
}
}
diff --git a/src/ref/file/ArcanistFileSymbolRefInspector.php b/src/ref/file/ArcanistFileSymbolRefInspector.php
deleted file mode 100644
--- a/src/ref/file/ArcanistFileSymbolRefInspector.php
+++ /dev/null
@@ -1,22 +0,0 @@
-<?php
-
-final class ArcanistFileSymbolRefInspector
- extends ArcanistRefInspector {
-
- public function getInspectFunctionName() {
- return 'file';
- }
-
- public function newInspectRef(array $argv) {
- if (count($argv) !== 1) {
- throw new PhutilArgumentUsageException(
- pht(
- 'Expected exactly one argument to "file(...)" with a '.
- 'file symbol.'));
- }
-
- return id(new ArcanistFileSymbolRef())
- ->setSymbol($argv[0]);
- }
-
-}
diff --git a/src/ref/paste/ArcanistPasteRef.php b/src/ref/paste/ArcanistPasteRef.php
new file mode 100644
--- /dev/null
+++ b/src/ref/paste/ArcanistPasteRef.php
@@ -0,0 +1,52 @@
+<?php
+
+final class ArcanistPasteRef
+ extends ArcanistRef
+ implements
+ ArcanistDisplayRefInterface {
+
+ private $parameters;
+
+ public function getRefDisplayName() {
+ return pht('Paste "%s"', $this->getMonogram());
+ }
+
+ public static function newFromConduit(array $parameters) {
+ $ref = new self();
+ $ref->parameters = $parameters;
+ return $ref;
+ }
+
+ public function getID() {
+ return idx($this->parameters, 'id');
+ }
+
+ public function getPHID() {
+ return idx($this->parameters, 'phid');
+ }
+
+ public function getTitle() {
+ return idxv($this->parameters, array('fields', 'title'));
+ }
+
+ public function getURI() {
+ return idxv($this->parameters, array('fields', 'uri'));
+ }
+
+ public function getContent() {
+ return idxv($this->parameters, array('attachments', 'content', 'content'));
+ }
+
+ public function getMonogram() {
+ return 'P'.$this->getID();
+ }
+
+ public function getDisplayRefObjectName() {
+ return $this->getMonogram();
+ }
+
+ public function getDisplayRefTitle() {
+ return $this->getTitle();
+ }
+
+}
diff --git a/src/ref/paste/ArcanistPasteSymbolRef.php b/src/ref/paste/ArcanistPasteSymbolRef.php
new file mode 100644
--- /dev/null
+++ b/src/ref/paste/ArcanistPasteSymbolRef.php
@@ -0,0 +1,36 @@
+<?php
+
+final class ArcanistPasteSymbolRef
+ extends ArcanistSimpleSymbolRef {
+
+ public function getRefDisplayName() {
+ return pht('Paste Symbol "%s"', $this->getSymbol());
+ }
+
+ protected function getSimpleSymbolPrefixPattern() {
+ return '[Pp]?';
+ }
+
+ protected function getSimpleSymbolPHIDType() {
+ return 'PSTE';
+ }
+
+ public function getSimpleSymbolConduitSearchMethodName() {
+ return 'paste.search';
+ }
+
+ public function getSimpleSymbolConduitSearchAttachments() {
+ return array(
+ 'content' => true,
+ );
+ }
+
+ public function getSimpleSymbolInspectFunctionName() {
+ return 'paste';
+ }
+
+ public function newSimpleSymbolObjectRef() {
+ return new ArcanistPasteRef();
+ }
+
+}
diff --git a/src/ref/revision/ArcanistRevisionSymbolHardpointQuery.php b/src/ref/revision/ArcanistRevisionSymbolHardpointQuery.php
deleted file mode 100644
--- a/src/ref/revision/ArcanistRevisionSymbolHardpointQuery.php
+++ /dev/null
@@ -1,40 +0,0 @@
-<?php
-
-final class ArcanistRevisionSymbolHardpointQuery
- extends ArcanistRuntimeHardpointQuery {
-
- public function getHardpoints() {
- return array(
- ArcanistRevisionSymbolRef::HARDPOINT_OBJECT,
- );
- }
-
- protected function canLoadRef(ArcanistRef $ref) {
- return ($ref instanceof ArcanistRevisionSymbolRef);
- }
-
- public function loadHardpoint(array $refs, $hardpoint) {
- $id_map = mpull($refs, 'getSymbol');
- $id_set = array_fuse($id_map);
-
- $revisions = (yield $this->yieldConduitSearch(
- 'differential.revision.search',
- array(
- 'ids' => array_values($id_set),
- )));
-
- $refs = array();
- foreach ($revisions as $revision) {
- $ref = ArcanistRevisionRef::newFromConduit($revision);
- $refs[$ref->getID()] = $ref;
- }
-
- $results = array();
- foreach ($id_map as $key => $id) {
- $results[$key] = idx($refs, $id);
- }
-
- yield $this->yieldMap($results);
- }
-
-}
diff --git a/src/ref/revision/ArcanistRevisionSymbolRef.php b/src/ref/revision/ArcanistRevisionSymbolRef.php
--- a/src/ref/revision/ArcanistRevisionSymbolRef.php
+++ b/src/ref/revision/ArcanistRevisionSymbolRef.php
@@ -1,25 +1,30 @@
<?php
final class ArcanistRevisionSymbolRef
- extends ArcanistSymbolRef {
+ extends ArcanistSimpleSymbolRef {
public function getRefDisplayName() {
return pht('Revision Symbol "%s"', $this->getSymbol());
}
- protected function resolveSymbol($symbol) {
- $matches = null;
+ protected function getSimpleSymbolPrefixPattern() {
+ return '[Dd]?';
+ }
+
+ protected function getSimpleSymbolPHIDType() {
+ return 'DREV';
+ }
- if (!preg_match('/^[Dd]?([1-9]\d*)\z/', $symbol, $matches)) {
- throw new PhutilArgumentUsageException(
- pht(
- 'The format of revision symbol "%s" is unrecognized. '.
- 'Expected a revision monogram like "D123", or a '.
- 'revision ID like "123".',
- $symbol));
- }
+ public function getSimpleSymbolConduitSearchMethodName() {
+ return 'differential.revision.search';
+ }
+
+ public function getSimpleSymbolInspectFunctionName() {
+ return 'revision';
+ }
- return (int)$matches[1];
+ public function newSimpleSymbolObjectRef() {
+ return new ArcanistRevisionRef();
}
}
diff --git a/src/ref/revision/ArcanistRevisionSymbolRefInspector.php b/src/ref/revision/ArcanistRevisionSymbolRefInspector.php
deleted file mode 100644
--- a/src/ref/revision/ArcanistRevisionSymbolRefInspector.php
+++ /dev/null
@@ -1,22 +0,0 @@
-<?php
-
-final class ArcanistRevisionSymbolRefInspector
- extends ArcanistRefInspector {
-
- public function getInspectFunctionName() {
- return 'revision';
- }
-
- public function newInspectRef(array $argv) {
- if (count($argv) !== 1) {
- throw new PhutilArgumentUsageException(
- pht(
- 'Expected exactly one argument to "revision(...)" with a '.
- 'revision symbol.'));
- }
-
- return id(new ArcanistRevisionSymbolRef())
- ->setSymbol($argv[0]);
- }
-
-}
diff --git a/src/ref/file/ArcanistFileSymbolHardpointQuery.php b/src/ref/simple/ArcanistSimpleSymbolHardpointQuery.php
rename from src/ref/file/ArcanistFileSymbolHardpointQuery.php
rename to src/ref/simple/ArcanistSimpleSymbolHardpointQuery.php
--- a/src/ref/file/ArcanistFileSymbolHardpointQuery.php
+++ b/src/ref/simple/ArcanistSimpleSymbolHardpointQuery.php
@@ -1,6 +1,6 @@
<?php
-final class ArcanistFileSymbolHardpointQuery
+final class ArcanistSimpleSymbolHardpointQuery
extends ArcanistRuntimeHardpointQuery {
public function getHardpoints() {
@@ -10,7 +10,7 @@
}
protected function canLoadRef(ArcanistRef $ref) {
- return ($ref instanceof ArcanistFileSymbolRef);
+ return ($ref instanceof ArcanistSimpleSymbolRef);
}
public function loadHardpoint(array $refs, $hardpoint) {
@@ -19,23 +19,31 @@
foreach ($refs as $key => $ref) {
switch ($ref->getSymbolType()) {
- case ArcanistFileSymbolRef::TYPE_ID:
+ case ArcanistSimpleSymbolRef::TYPE_ID:
$id_map[$key] = $ref->getSymbol();
break;
- case ArcanistFileSymbolRef::TYPE_PHID:
+ case ArcanistSimpleSymbolRef::TYPE_PHID:
$phid_map[$key] = $ref->getSymbol();
break;
}
}
+ $template_ref = head($refs);
+
+ $conduit_method =
+ $template_ref->getSimpleSymbolConduitSearchMethodName();
+ $conduit_attachments =
+ $template_ref->getSimpleSymbolConduitSearchAttachments();
+
$futures = array();
if ($id_map) {
$id_future = $this->newConduitSearch(
- 'file.search',
+ $conduit_method,
array(
'ids' => array_values(array_fuse($id_map)),
- ));
+ ),
+ $conduit_attachments);
$futures[] = $id_future;
} else {
@@ -44,10 +52,11 @@
if ($phid_map) {
$phid_future = $this->newConduitSearch(
- 'file.search',
+ $ref->getSimpleSymbolConduitSearchMethodName(),
array(
'phids' => array_values(array_fuse($phid_map)),
- ));
+ ),
+ $conduit_attachments);
$futures[] = $phid_future;
} else {
@@ -76,12 +85,16 @@
}
}
+ $object_ref = $template_ref->newSimpleSymbolObjectRef();
+
foreach ($result_map as $key => $raw_result) {
if ($raw_result === null) {
continue;
}
- $result_map[$key] = ArcanistFileRef::newFromConduit($raw_result);
+ $result_map[$key] = call_user_func_array(
+ array(get_class($object_ref), 'newFromConduit'),
+ array($raw_result));
}
yield $this->yieldMap($result_map);
diff --git a/src/ref/simple/ArcanistSimpleSymbolRef.php b/src/ref/simple/ArcanistSimpleSymbolRef.php
new file mode 100644
--- /dev/null
+++ b/src/ref/simple/ArcanistSimpleSymbolRef.php
@@ -0,0 +1,58 @@
+<?php
+
+abstract class ArcanistSimpleSymbolRef
+ extends ArcanistSymbolRef {
+
+ private $type;
+
+ const TYPE_ID = 'id';
+ const TYPE_PHID = 'phid';
+
+ final protected function newCacheKeyParts() {
+ return array(
+ sprintf('type(%s)', $this->type),
+ );
+ }
+
+ final public function getSymbolType() {
+ return $this->type;
+ }
+
+ final protected function resolveSymbol($symbol) {
+ $matches = null;
+
+ $prefix_pattern = $this->getSimpleSymbolPrefixPattern();
+ $id_pattern = '(^'.$prefix_pattern.'([1-9]\d*)\z)';
+
+ $is_id = preg_match($id_pattern, $symbol, $matches);
+ if ($is_id) {
+ $this->type = self::TYPE_ID;
+ return (int)$matches[1];
+ }
+
+ $phid_type = $this->getSimpleSymbolPHIDType();
+ $phid_type = preg_quote($phid_type);
+ $phid_pattern = '(^PHID-'.$phid_type.'-\S+\z)';
+ $is_phid = preg_match($phid_pattern, $symbol, $matches);
+ if ($is_phid) {
+ $this->type = self::TYPE_PHID;
+ return $matches[0];
+ }
+
+ throw new PhutilArgumentUsageException(
+ pht(
+ 'The format of symbol "%s" is unrecognized. Expected a '.
+ 'monogram like "X123", or an ID like "123", or a PHID.',
+ $symbol));
+ }
+
+ abstract protected function getSimpleSymbolPrefixPattern();
+ abstract protected function getSimpleSymbolPHIDType();
+ abstract public function getSimpleSymbolConduitSearchMethodName();
+ abstract public function getSimpleSymbolInspectFunctionName();
+
+ public function getSimpleSymbolConduitSearchAttachments() {
+ return array();
+ }
+
+}
diff --git a/src/ref/simple/ArcanistSimpleSymbolRefInspector.php b/src/ref/simple/ArcanistSimpleSymbolRefInspector.php
new file mode 100644
--- /dev/null
+++ b/src/ref/simple/ArcanistSimpleSymbolRefInspector.php
@@ -0,0 +1,47 @@
+<?php
+
+final class ArcanistSimpleSymbolRefInspector
+ extends ArcanistRefInspector {
+
+ private $templateRef;
+
+ protected function newInspectors() {
+ $refs = id(new PhutilClassMapQuery())
+ ->setAncestorClass('ArcanistSimpleSymbolRef')
+ ->execute();
+
+ $inspectors = array();
+ foreach ($refs as $ref) {
+ $inspectors[] = id(new self())
+ ->setTemplateRef($ref);
+ }
+
+ return $inspectors;
+ }
+
+ public function setTemplateRef(ArcanistSimpleSymbolRef $template_ref) {
+ $this->templateRef = $template_ref;
+ return $this;
+ }
+
+ public function getTemplateRef() {
+ return $this->templateRef;
+ }
+
+ public function getInspectFunctionName() {
+ return $this->getTemplateRef()->getSimpleSymbolInspectFunctionName();
+ }
+
+ public function newInspectRef(array $argv) {
+ if (count($argv) !== 1) {
+ throw new PhutilArgumentUsageException(
+ pht(
+ 'Expected exactly one argument to "%s(...)" with a symbol.',
+ $this->getInspectFunctionName()));
+ }
+
+ return id(clone $this->getTemplateRef())
+ ->setSymbol($argv[0]);
+ }
+
+}
diff --git a/src/ref/symbol/ArcanistSymbolEngine.php b/src/ref/symbol/ArcanistSymbolEngine.php
--- a/src/ref/symbol/ArcanistSymbolEngine.php
+++ b/src/ref/symbol/ArcanistSymbolEngine.php
@@ -59,6 +59,17 @@
$symbols);
}
+ public function loadPasteForSymbol($symbol) {
+ $refs = $this->loadPastesForSymbols(array($symbol));
+ return head($refs)->getObject();
+ }
+
+ public function loadPastesForSymbols(array $symbols) {
+ return $this->loadRefsForSymbols(
+ new ArcanistPasteSymbolRef(),
+ $symbols);
+ }
+
public function loadRefsForSymbols(
ArcanistSymbolRef $template,
array $symbols) {
diff --git a/src/ref/task/ArcanistTaskRef.php b/src/ref/task/ArcanistTaskRef.php
new file mode 100644
--- /dev/null
+++ b/src/ref/task/ArcanistTaskRef.php
@@ -0,0 +1,44 @@
+<?php
+
+final class ArcanistTaskRef
+ extends ArcanistRef
+ implements
+ ArcanistDisplayRefInterface {
+
+ private $parameters;
+
+ public function getRefDisplayName() {
+ return pht('Task "%s"', $this->getMonogram());
+ }
+
+ public static function newFromConduit(array $parameters) {
+ $ref = new self();
+ $ref->parameters = $parameters;
+ return $ref;
+ }
+
+ public function getID() {
+ return idx($this->parameters, 'id');
+ }
+
+ public function getPHID() {
+ return idx($this->parameters, 'phid');
+ }
+
+ public function getName() {
+ return idxv($this->parameters, array('fields', 'name'));
+ }
+
+ public function getMonogram() {
+ return 'T'.$this->getID();
+ }
+
+ public function getDisplayRefObjectName() {
+ return $this->getMonogram();
+ }
+
+ public function getDisplayRefTitle() {
+ return $this->getName();
+ }
+
+}
diff --git a/src/ref/task/ArcanistTaskSymbolRef.php b/src/ref/task/ArcanistTaskSymbolRef.php
new file mode 100644
--- /dev/null
+++ b/src/ref/task/ArcanistTaskSymbolRef.php
@@ -0,0 +1,30 @@
+<?php
+
+final class ArcanistTaskSymbolRef
+ extends ArcanistSimpleSymbolRef {
+
+ public function getRefDisplayName() {
+ return pht('Task Symbol "%s"', $this->getSymbol());
+ }
+
+ protected function getSimpleSymbolPrefixPattern() {
+ return '[Tt]?';
+ }
+
+ protected function getSimpleSymbolPHIDType() {
+ return 'TASK';
+ }
+
+ public function getSimpleSymbolConduitSearchMethodName() {
+ return 'maniphest.search';
+ }
+
+ public function getSimpleSymbolInspectFunctionName() {
+ return 'task';
+ }
+
+ public function newSimpleSymbolObjectRef() {
+ return new ArcanistTaskRef();
+ }
+
+}
diff --git a/src/toolset/query/ArcanistRuntimeHardpointQuery.php b/src/toolset/query/ArcanistRuntimeHardpointQuery.php
--- a/src/toolset/query/ArcanistRuntimeHardpointQuery.php
+++ b/src/toolset/query/ArcanistRuntimeHardpointQuery.php
@@ -51,14 +51,19 @@
abstract protected function canLoadRef(ArcanistRef $ref);
- final public function newConduitSearch($method, $constraints) {
+ final public function newConduitSearch(
+ $method,
+ $constraints,
+ $attachments = array()) {
+
$conduit_engine = $this->getRuntime()
->getConduitEngine();
$conduit_future = id(new ConduitSearchFuture())
->setConduitEngine($conduit_engine)
->setMethod($method)
- ->setConstraints($constraints);
+ ->setConstraints($constraints)
+ ->setAttachments($attachments);
return $conduit_future;
}
diff --git a/src/workflow/ArcanistCallConduitWorkflow.php b/src/workflow/ArcanistCallConduitWorkflow.php
--- a/src/workflow/ArcanistCallConduitWorkflow.php
+++ b/src/workflow/ArcanistCallConduitWorkflow.php
@@ -44,13 +44,7 @@
}
$method = head($method);
- if (phutil_is_interactive()) {
- echo tsprintf(
- "%s\n",
- pht('Waiting for JSON parameters on stdin...'));
- }
-
- $params = @file_get_contents('php://stdin');
+ $params = $this->readStdin();
try {
$params = phutil_json_decode($params);
} catch (PhutilJSONParserException $ex) {
diff --git a/src/workflow/ArcanistPasteWorkflow.php b/src/workflow/ArcanistPasteWorkflow.php
--- a/src/workflow/ArcanistPasteWorkflow.php
+++ b/src/workflow/ArcanistPasteWorkflow.php
@@ -1,145 +1,137 @@
<?php
-/**
- * Upload a chunk of text to the Paste application, or download one.
- */
-final class ArcanistPasteWorkflow extends ArcanistWorkflow {
-
- private $id;
- private $language;
- private $title;
- private $json;
+final class ArcanistPasteWorkflow
+ extends ArcanistArcWorkflow {
public function getWorkflowName() {
return 'paste';
}
- public function getCommandSynopses() {
- return phutil_console_format(<<<EOTEXT
- **paste** [--title __title__] [--lang __language__] [--json]
- **paste** __id__ [--json]
-EOTEXT
- );
- }
-
- public function getCommandHelp() {
- return phutil_console_format(<<<EOTEXT
- Supports: text
- Share and grab text using the Paste application. To create a paste,
- use stdin to provide the text:
+ public function getWorkflowInformation() {
+ $help = pht(<<<EOTEXT
+Share and grab text using the Paste application. To create a paste,
+use stdin to provide the text:
- $ cat list_of_ducks.txt | arc paste
+ $ cat list_of_ducks.txt | arc paste
- To retrieve a paste, specify the paste ID:
+To retrieve a paste, specify the paste ID:
- $ arc paste P123
+ $ arc paste P123
EOTEXT
);
+
+ return $this->newWorkflowInformation()
+ ->addExample('**paste** [__options__] --')
+ ->addExample('**paste** [__options__] -- __object__')
+ ->setHelp($help);
}
- public function getArguments() {
+ public function getWorkflowArguments() {
return array(
- 'title' => array(
- 'param' => 'title',
- 'help' => pht('Title for the paste.'),
- ),
- 'lang' => array(
- 'param' => 'language',
- 'help' => pht('Language for syntax highlighting.'),
- ),
- 'json' => array(
- 'help' => pht('Output in JSON format.'),
- ),
- '*' => 'argv',
+ $this->newWorkflowArgument('title')
+ ->setParameter('title')
+ ->setHelp(pht('Title for the paste.')),
+ $this->newWorkflowArgument('lang')
+ ->setParameter('language')
+ ->setHelp(pht('Language for the paste.')),
+ $this->newWorkflowArgument('json')
+ ->setHelp(pht('Output in JSON format.')),
+ $this->newWorkflowArgument('argv')
+ ->setWildcard(true),
);
}
- public function requiresAuthentication() {
- return true;
- }
-
- protected function didParseArguments() {
- $this->json = $this->getArgument('json');
- $this->language = $this->getArgument('lang');
- $this->title = $this->getArgument('title');
+ public function runWorkflow() {
+ $set_language = $this->getArgument('lang');
+ $set_title = $this->getArgument('title');
$argv = $this->getArgument('argv');
if (count($argv) > 1) {
- throw new ArcanistUsageException(
- pht('Specify only one paste to retrieve.'));
- } else if (count($argv) == 1) {
- $id = $argv[0];
- if (!preg_match('/^P?\d+/', $id)) {
- throw new ArcanistUsageException(
+ throw new PhutilArgumentUsageException(
+ pht(
+ 'Specify only one paste to retrieve.'));
+ }
+
+ $symbols = $this->getSymbolEngine();
+
+ if (count($argv) === 1) {
+ if ($set_language !== null) {
+ throw new PhutilArgumentUsageException(
pht(
- 'Specify a paste ID, like %s.',
- 'P123'));
+ 'Flag "--lang" is not supported when reading pastes.'));
}
- $this->id = (int)ltrim($id, 'P');
- if ($this->language || $this->title) {
- throw new ArcanistUsageException(
+ if ($set_title !== null) {
+ throw new PhutilArgumentUsageException(
pht(
- 'Use options %s and %s only when creating pastes.',
- '--lang',
- '--title'));
+ 'Flag "--title" is not supported when reading pastes.'));
}
- }
- }
- public function run() {
- if ($this->id) {
- return $this->getPaste();
- } else {
- return $this->createPaste();
- }
- }
+ $paste_symbol = $argv[0];
- private function getPaste() {
- $conduit = $this->getConduit();
-
- $info = $conduit->callMethodSynchronous(
- 'paste.query',
- array(
- 'ids' => array($this->id),
- ));
- $info = head($info);
-
- if ($this->json) {
- echo json_encode($info)."\n";
- } else {
- echo $info['content'];
- if (!preg_match('/\\n$/', $info['content'])) {
- // If there's no newline, add one, since it looks stupid otherwise. If
- // you want byte-for-byte equivalence you can use `--json`.
- echo "\n";
+ $paste_ref = $symbols->loadPasteForSymbol($paste_symbol);
+ if (!$paste_ref) {
+ throw new PhutilArgumentUsageException(
+ pht(
+ 'Paste "%s" does not exist, or you do not have access '.
+ 'to see it.'));
}
+
+ echo $paste_ref->getContent();
+
+ return 0;
}
- return 0;
- }
+ $content = $this->readStdin();
- private function createPaste() {
- $conduit = $this->getConduit();
+ $xactions = array();
- if (!function_exists('posix_isatty') || posix_isatty(STDIN)) {
- $this->writeStatusMessage(pht('Reading paste from stdin...')."\n");
+ if ($set_title === null) {
+ $set_title = pht('Command-Line Input');
}
- $info = $conduit->callMethodSynchronous(
- 'paste.create',
- array(
- 'content' => file_get_contents('php://stdin'),
- 'title' => $this->title,
- 'language' => $this->language,
- ));
-
- if ($this->getArgument('json')) {
- echo json_encode($info)."\n";
- } else {
- echo $info['objectName'].': '.$info['uri']."\n";
+ $xactions[] = array(
+ 'type' => 'title',
+ 'value' => $set_title,
+ );
+
+ if ($set_language !== null) {
+ $xactions[] = array(
+ 'type' => 'language',
+ 'value' => $set_language,
+ );
}
+ $xactions[] = array(
+ 'type' => 'text',
+ 'value' => $content,
+ );
+
+ $method = 'paste.edit';
+
+ $parameters = array(
+ 'transactions' => $xactions,
+ );
+
+ $conduit_engine = $this->getConduitEngine();
+ $conduit_call = $conduit_engine->newCall($method, $parameters);
+ $conduit_future = $conduit_engine->newFuture($conduit_call);
+ $result = $conduit_future->resolve();
+
+ $paste_phid = idxv($result, array('object', 'phid'));
+ $paste_ref = $symbols->loadPasteForSymbol($paste_phid);
+
+ $log = $this->getLogEngine();
+
+ $log->writeSuccess(
+ pht('DONE'),
+ pht('Created a new paste.'));
+
+ echo tsprintf(
+ '%s',
+ $paste_ref->newDisplayRef()
+ ->setURI($paste_ref->getURI()));
+
return 0;
}
diff --git a/src/workflow/ArcanistWorkflow.php b/src/workflow/ArcanistWorkflow.php
--- a/src/workflow/ArcanistWorkflow.php
+++ b/src/workflow/ArcanistWorkflow.php
@@ -52,7 +52,6 @@
private $repositoryAPI;
private $configurationManager;
private $arguments = array();
- private $passedArguments = array();
private $command;
private $stashed;
@@ -777,10 +776,6 @@
return $this->arguments->getArg($key);
}
- final public function getPassedArguments() {
- return $this->passedArguments;
- }
-
final public function getCompleteArgumentSpecification() {
$spec = $this->getArguments();
$arc_config = $this->getArcanistConfiguration();
@@ -791,8 +786,6 @@
}
final public function parseArguments(array $args) {
- $this->passedArguments = $args;
-
$spec = $this->getCompleteArgumentSpecification();
$dict = array();
@@ -2411,4 +2404,21 @@
return $this->getRuntime()->getViewer();
}
+ final protected function readStdin() {
+ $log = $this->getLogEngine();
+ $log->writeWaitingForInput();
+
+ // NOTE: We can't just "file_get_contents()" here because signals don't
+ // interrupt it. If the user types "^C", we want to interrupt the read.
+
+ $raw_handle = fopen('php://stdin', 'rb');
+ $stdin = new PhutilSocketChannel($raw_handle);
+
+ while ($stdin->update()) {
+ PhutilChannel::waitForAny(array($stdin));
+ }
+
+ return $stdin->read();
+ }
+
}

File Metadata

Mime Type
text/plain
Expires
Thu, Mar 27, 9:31 PM (4 d, 20 h ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7224155
Default Alt Text
D21104.id50266.diff (35 KB)

Event Timeline