Page MenuHomePhabricator

D21080.diff
No OneTemporary

D21080.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
@@ -57,13 +57,22 @@
'ArcanistBranchRefPro' => 'ref/ArcanistBranchRefPro.php',
'ArcanistBranchWorkflow' => 'workflow/ArcanistBranchWorkflow.php',
'ArcanistBrowseCommitHardpointLoader' => 'browse/loader/ArcanistBrowseCommitHardpointLoader.php',
+ 'ArcanistBrowseCommitHardpointQuery' => 'browse/query/ArcanistBrowseCommitHardpointQuery.php',
'ArcanistBrowseCommitURIHardpointLoader' => 'browse/loader/ArcanistBrowseCommitURIHardpointLoader.php',
+ 'ArcanistBrowseCommitURIHardpointQuery' => 'browse/query/ArcanistBrowseCommitURIHardpointQuery.php',
'ArcanistBrowseObjectNameURIHardpointLoader' => 'browse/loader/ArcanistBrowseObjectNameURIHardpointLoader.php',
+ 'ArcanistBrowseObjectNameURIHardpointQuery' => 'browse/query/ArcanistBrowseObjectNameURIHardpointQuery.php',
'ArcanistBrowsePathURIHardpointLoader' => 'browse/loader/ArcanistBrowsePathURIHardpointLoader.php',
+ 'ArcanistBrowsePathURIHardpointQuery' => 'browse/query/ArcanistBrowsePathURIHardpointQuery.php',
'ArcanistBrowseRef' => 'browse/ref/ArcanistBrowseRef.php',
+ 'ArcanistBrowseRefInspector' => 'inspector/ArcanistBrowseRefInspector.php',
+ 'ArcanistBrowseRefPro' => 'browse/ref/ArcanistBrowseRefPro.php',
'ArcanistBrowseRevisionURIHardpointLoader' => 'browse/loader/ArcanistBrowseRevisionURIHardpointLoader.php',
+ 'ArcanistBrowseRevisionURIHardpointQuery' => 'browse/query/ArcanistBrowseRevisionURIHardpointQuery.php',
'ArcanistBrowseURIHardpointLoader' => 'browse/loader/ArcanistBrowseURIHardpointLoader.php',
+ 'ArcanistBrowseURIHardpointQuery' => 'browse/query/ArcanistBrowseURIHardpointQuery.php',
'ArcanistBrowseURIRef' => 'browse/ref/ArcanistBrowseURIRef.php',
+ 'ArcanistBrowseURIRefPro' => 'browse/ref/ArcanistBrowseURIRefPro.php',
'ArcanistBrowseWorkflow' => 'browse/workflow/ArcanistBrowseWorkflow.php',
'ArcanistBuildPlanRef' => 'ref/ArcanistBuildPlanRef.php',
'ArcanistBuildRef' => 'ref/ArcanistBuildRef.php',
@@ -1031,13 +1040,22 @@
'ArcanistBranchRefPro' => 'ArcanistRefPro',
'ArcanistBranchWorkflow' => 'ArcanistFeatureWorkflow',
'ArcanistBrowseCommitHardpointLoader' => 'ArcanistHardpointLoader',
+ 'ArcanistBrowseCommitHardpointQuery' => 'ArcanistWorkflowHardpointQuery',
'ArcanistBrowseCommitURIHardpointLoader' => 'ArcanistBrowseURIHardpointLoader',
+ 'ArcanistBrowseCommitURIHardpointQuery' => 'ArcanistBrowseURIHardpointQuery',
'ArcanistBrowseObjectNameURIHardpointLoader' => 'ArcanistBrowseURIHardpointLoader',
+ 'ArcanistBrowseObjectNameURIHardpointQuery' => 'ArcanistBrowseURIHardpointQuery',
'ArcanistBrowsePathURIHardpointLoader' => 'ArcanistBrowseURIHardpointLoader',
+ 'ArcanistBrowsePathURIHardpointQuery' => 'ArcanistBrowseURIHardpointQuery',
'ArcanistBrowseRef' => 'ArcanistRef',
+ 'ArcanistBrowseRefInspector' => 'ArcanistRefInspector',
+ 'ArcanistBrowseRefPro' => 'ArcanistRefPro',
'ArcanistBrowseRevisionURIHardpointLoader' => 'ArcanistBrowseURIHardpointLoader',
+ 'ArcanistBrowseRevisionURIHardpointQuery' => 'ArcanistBrowseURIHardpointQuery',
'ArcanistBrowseURIHardpointLoader' => 'ArcanistHardpointLoader',
+ 'ArcanistBrowseURIHardpointQuery' => 'ArcanistWorkflowHardpointQuery',
'ArcanistBrowseURIRef' => 'ArcanistRef',
+ 'ArcanistBrowseURIRefPro' => 'ArcanistRefPro',
'ArcanistBrowseWorkflow' => 'ArcanistArcWorkflow',
'ArcanistBuildPlanRef' => 'Phobject',
'ArcanistBuildRef' => 'Phobject',
diff --git a/src/browse/query/ArcanistBrowseCommitHardpointQuery.php b/src/browse/query/ArcanistBrowseCommitHardpointQuery.php
new file mode 100644
--- /dev/null
+++ b/src/browse/query/ArcanistBrowseCommitHardpointQuery.php
@@ -0,0 +1,65 @@
+<?php
+
+final class ArcanistBrowseCommitHardpointQuery
+ extends ArcanistWorkflowHardpointQuery {
+
+ public function getHardpoints() {
+ return array(
+ ArcanistBrowseRefPro::HARDPOINT_COMMITREFS,
+ );
+ }
+
+ protected function canLoadRef(ArcanistRefPro $ref) {
+ return ($ref instanceof ArcanistBrowseRefPro);
+ }
+
+ public function loadHardpoint(array $refs, $hardpoint) {
+ $api = $this->getRepositoryAPI();
+
+ $commit_map = array();
+ foreach ($refs as $key => $ref) {
+ $token = $ref->getToken();
+
+ if ($token === '.') {
+ // Git resolves "." like HEAD, but we want to treat it as "browse the
+ // current directory" instead in all cases.
+ continue;
+ }
+
+ // Always resolve the empty token; top-level loaders filter out
+ // irrelevant tokens before this stage.
+ if ($token === null) {
+ $token = $api->getHeadCommit();
+ }
+
+ // TODO: We should pull a full commit ref out of the API as soon as it
+ // is able to provide them. In particular, we currently miss Git tree
+ // hashes which reduces the accuracy of lookups.
+
+ try {
+ $commit = $api->getCanonicalRevisionName($token);
+ if ($commit) {
+ $commit_map[$commit][] = $key;
+ }
+ } catch (Exception $ex) {
+ // Ignore anything we can't resolve.
+ }
+ }
+
+ if (!$commit_map) {
+ yield $this->yieldMap(array());
+ }
+
+ $results = array();
+ foreach ($commit_map as $commit_identifier => $ref_keys) {
+ foreach ($ref_keys as $key) {
+ $commit_ref = id(new ArcanistCommitRefPro())
+ ->setCommitHash($commit_identifier);
+ $results[$key][] = $commit_ref;
+ }
+ }
+
+ yield $this->yieldMap($results);
+ }
+
+}
diff --git a/src/browse/query/ArcanistBrowseCommitURIHardpointQuery.php b/src/browse/query/ArcanistBrowseCommitURIHardpointQuery.php
new file mode 100644
--- /dev/null
+++ b/src/browse/query/ArcanistBrowseCommitURIHardpointQuery.php
@@ -0,0 +1,76 @@
+<?php
+
+final class ArcanistBrowseCommitURIHardpointQuery
+ extends ArcanistBrowseURIHardpointQuery {
+
+ const BROWSETYPE = 'commit';
+
+ public function willLoadBrowseURIRefs(array $refs) {
+ $refs = $this->getRefsWithSupportedTypes($refs);
+
+ if (!$refs) {
+ return;
+ }
+
+ $query = $this->getQuery();
+
+ $working_ref = $query->getWorkingCopyRef();
+ if (!$working_ref) {
+ // If we aren't in a working copy, don't warn about this.
+ return;
+ }
+
+ $repository_ref = $this->getQuery()->getRepositoryRef();
+ if (!$repository_ref) {
+ echo pht(
+ 'NO REPOSITORY: Unable to determine which repository this working '.
+ 'copy belongs to, so arguments can not be resolved as commits. Use '.
+ '"%s" to understand how repositories are resolved.',
+ 'arc which');
+ echo "\n";
+ return;
+ }
+ }
+
+ public function loadHardpoint(array $refs, $hardpoint) {
+ $refs = $this->getRefsWithSupportedTypes($refs);
+ if (!$refs) {
+ yield $this->yieldMap(array());
+ }
+
+ yield $this->yieldRequests(
+ $refs,
+ array(
+ ArcanistBrowseRefPro::HARDPOINT_COMMITREFS,
+ ));
+
+ $commit_refs = array();
+ foreach ($refs as $key => $ref) {
+ foreach ($ref->getCommitRefs() as $commit_ref) {
+ $commit_refs[] = $commit_ref;
+ }
+ }
+
+ yield $this->yieldRequests(
+ $commit_refs,
+ array(
+ ArcanistCommitRefPro::HARDPOINT_UPSTREAM,
+ ));
+
+ $results = array();
+ foreach ($refs as $key => $ref) {
+ $commit_refs = $ref->getCommitRefs();
+ foreach ($commit_refs as $commit_ref) {
+ $uri = $commit_ref->getURI();
+ if ($uri !== null) {
+ $results[$key][] = $this->newBrowseURIRef()
+ ->setURI($uri);
+ }
+ }
+ }
+
+ yield $this->yieldMap($results);
+ }
+
+
+}
diff --git a/src/browse/query/ArcanistBrowseObjectNameURIHardpointQuery.php b/src/browse/query/ArcanistBrowseObjectNameURIHardpointQuery.php
new file mode 100644
--- /dev/null
+++ b/src/browse/query/ArcanistBrowseObjectNameURIHardpointQuery.php
@@ -0,0 +1,56 @@
+<?php
+
+final class ArcanistBrowseObjectNameURIHardpointQuery
+ extends ArcanistBrowseURIHardpointQuery {
+
+ const BROWSETYPE = 'object';
+
+ public function loadHardpoint(array $refs, $hardpoint) {
+ $refs = $this->getRefsWithSupportedTypes($refs);
+ if (!$refs) {
+ yield $this->yieldMap(array());
+ }
+
+ $name_map = array();
+ $token_set = array();
+ foreach ($refs as $key => $ref) {
+ $token = $ref->getToken();
+ if (!strlen($token)) {
+ continue;
+ }
+
+ $name_map[$key] = $token;
+ $token_set[$token] = $token;
+ }
+
+ if (!$token_set) {
+ yield $this->yieldMap(array());
+ }
+
+ $objects = (yield $this->yieldConduit(
+ 'phid.lookup',
+ array(
+ 'names' => $token_set,
+ )));
+
+ $result = array();
+ foreach ($name_map as $ref_key => $token) {
+ $object = idx($objects, $token);
+
+ if (!$object) {
+ continue;
+ }
+
+ $uri = idx($object, 'uri');
+ if (!strlen($uri)) {
+ continue;
+ }
+
+ $result[$ref_key][] = $this->newBrowseURIRef()
+ ->setURI($object['uri']);
+ }
+
+ yield $this->yieldMap($result);
+ }
+
+}
diff --git a/src/browse/query/ArcanistBrowsePathURIHardpointQuery.php b/src/browse/query/ArcanistBrowsePathURIHardpointQuery.php
new file mode 100644
--- /dev/null
+++ b/src/browse/query/ArcanistBrowsePathURIHardpointQuery.php
@@ -0,0 +1,128 @@
+<?php
+
+final class ArcanistBrowsePathURIHardpointQuery
+ extends ArcanistBrowseURIHardpointQuery {
+
+ const BROWSETYPE = 'path';
+
+ public function willLoadBrowseURIRefs(array $refs) {
+ $refs = $this->getRefsWithSupportedTypes($refs);
+ if (!$refs) {
+ return;
+ }
+
+ $query = $this->getQuery();
+
+ $working_ref = $query->getWorkingCopyRef();
+ if (!$working_ref) {
+ echo pht(
+ 'NO WORKING COPY: The current directory is not a repository '.
+ 'working copy, so arguments can not be resolved as paths. Run '.
+ 'this command inside a working copy to resolve paths.');
+ echo "\n";
+ return;
+ }
+
+ $repository_ref = $query->getRepositoryRef();
+ if (!$repository_ref) {
+ echo pht(
+ 'NO REPOSITORY: Unable to determine which repository this working '.
+ 'copy belongs to, so arguments can not be resolved as paths. Use '.
+ '"%s" to understand how repositories are resolved.',
+ 'arc which');
+ echo "\n";
+ return;
+ }
+ }
+
+ public function didFailToLoadBrowseURIRefs(array $refs) {
+ $refs = $this->getRefsWithSupportedTypes($refs);
+ if (!$refs) {
+ return;
+ }
+
+ $query = $this->getQuery();
+
+ $working_ref = $query->getWorkingCopyRef();
+ if (!$working_ref) {
+ return;
+ }
+
+ $repository_ref = $query->getRepositoryRef();
+ if (!$repository_ref) {
+ return;
+ }
+
+ echo pht(
+ 'Use "--types path" to force arguments to be interpreted as paths.');
+ echo "\n";
+ }
+
+
+ public function loadHardpoint(array $refs, $hardpoint) {
+ $refs = $this->getRefsWithSupportedTypes($refs);
+ if (!$refs) {
+ yield $this->yieldMap(array());
+ }
+
+ $repository_ref = (yield $this->yieldRepositoryRef());
+ if (!$repository_ref) {
+ yield $this->yieldMap(array());
+ }
+
+ $working_copy = $this->getWorkingCopy();
+ $working_root = $working_copy->getPath();
+
+ $results = array();
+ foreach ($refs as $key => $ref) {
+ $is_path = $ref->hasType(self::BROWSETYPE);
+
+ $path = $ref->getToken();
+ if ($path === null) {
+ // If we're explicitly resolving no arguments as a path, treat it
+ // as the current working directory.
+ if ($is_path) {
+ $path = '.';
+ } else {
+ continue;
+ }
+ }
+
+ $lines = null;
+ $parts = explode(':', $path);
+ if (count($parts) > 1) {
+ $lines = array_pop($parts);
+ }
+ $path = implode(':', $parts);
+
+ $full_path = Filesystem::resolvePath($path);
+
+ if (!Filesystem::pathExists($full_path)) {
+ if (!$is_path) {
+ continue;
+ }
+ }
+
+ if ($full_path == $working_root) {
+ $path = '';
+ } else {
+ $path = Filesystem::readablePath($full_path, $working_root);
+ }
+
+ $params = array(
+ 'path' => $path,
+ 'lines' => $lines,
+ 'branch' => $ref->getBranch(),
+ );
+
+ $uri = $repository_ref->newBrowseURI($params);
+
+ $results[$key][] = $this->newBrowseURIRef()
+ ->setURI($uri);
+ }
+
+ yield $this->yieldMap($results);
+ }
+
+
+}
diff --git a/src/browse/query/ArcanistBrowseRevisionURIHardpointQuery.php b/src/browse/query/ArcanistBrowseRevisionURIHardpointQuery.php
new file mode 100644
--- /dev/null
+++ b/src/browse/query/ArcanistBrowseRevisionURIHardpointQuery.php
@@ -0,0 +1,62 @@
+<?php
+
+final class ArcanistBrowseRevisionURIHardpointQuery
+ extends ArcanistBrowseURIHardpointQuery {
+
+ const BROWSETYPE = 'revision';
+
+ public function loadHardpoint(array $refs, $hardpoint) {
+ $refs = $this->getRefsWithSupportedTypes($refs);
+ if (!$refs) {
+ yield $this->yieldMap(array());
+ }
+
+ yield $this->yieldRequests(
+ $refs,
+ array(
+ ArcanistBrowseRefPro::HARDPOINT_COMMITREFS,
+ ));
+
+ $states = array();
+ $map = array();
+ foreach ($refs as $key => $ref) {
+ foreach ($ref->getCommitRefs() as $commit_ref) {
+ $hash = $commit_ref->getCommitHash();
+ $states[$hash] = id(new ArcanistWorkingCopyStateRefPro())
+ ->setCommitRef($commit_ref);
+ $map[$hash][] = $key;
+ }
+ }
+
+ if (!$states) {
+ yield $this->yieldMap(array());
+ }
+
+ yield $this->yieldRequests(
+ $states,
+ array(
+ 'revisionRefs',
+ ));
+
+ $results = array();
+ foreach ($states as $hash => $state) {
+ foreach ($state->getRevisionRefs() as $revision) {
+ if ($revision->isClosed()) {
+ // Don't resolve closed revisions.
+ continue;
+ }
+
+ $uri = $revision->getURI();
+
+ foreach ($map[$hash] as $key) {
+ $results[$key][] = $this->newBrowseURIRef()
+ ->setURI($uri);
+ }
+ }
+ }
+
+ yield $this->yieldMap($results);
+ }
+
+
+}
diff --git a/src/browse/query/ArcanistBrowseURIHardpointQuery.php b/src/browse/query/ArcanistBrowseURIHardpointQuery.php
new file mode 100644
--- /dev/null
+++ b/src/browse/query/ArcanistBrowseURIHardpointQuery.php
@@ -0,0 +1,49 @@
+<?php
+
+abstract class ArcanistBrowseURIHardpointQuery
+ extends ArcanistWorkflowHardpointQuery {
+
+ public function getSupportedBrowseType() {
+ return $this->getPhobjectClassConstant('BROWSETYPE', 32);
+ }
+
+ public function getHardpoints() {
+ return array(
+ ArcanistBrowseRefPro::HARDPOINT_URIS,
+ );
+ }
+
+ protected function canLoadRef(ArcanistRefPro $ref) {
+ return ($ref instanceof ArcanistBrowseRefPro);
+ }
+
+ public function getRefsWithSupportedTypes(array $refs) {
+ $type = $this->getSupportedBrowseType();
+
+ foreach ($refs as $key => $ref) {
+ if ($ref->isUntyped()) {
+ continue;
+ }
+
+ if ($ref->hasType($type)) {
+ continue;
+ }
+
+ unset($refs[$key]);
+ }
+
+ return $refs;
+ }
+
+ public static function getAllBrowseQueries() {
+ return id(new PhutilClassMapQuery())
+ ->setAncestorClass(__CLASS__)
+ ->execute();
+ }
+
+ final protected function newBrowseURIRef() {
+ return id(new ArcanistBrowseURIRefPro())
+ ->setType($this->getSupportedBrowseType());
+ }
+
+}
diff --git a/src/browse/ref/ArcanistBrowseRefPro.php b/src/browse/ref/ArcanistBrowseRefPro.php
new file mode 100644
--- /dev/null
+++ b/src/browse/ref/ArcanistBrowseRefPro.php
@@ -0,0 +1,69 @@
+<?php
+
+final class ArcanistBrowseRefPro
+ extends ArcanistRefPro {
+
+ const HARDPOINT_URIS = 'uris';
+ const HARDPOINT_COMMITREFS = 'commitRefs';
+
+ private $token;
+ private $types = array();
+ private $branch;
+
+ public function getRefDisplayName() {
+ return pht('Browse Query "%s"', $this->getToken());
+ }
+
+ protected function newHardpoints() {
+ return array(
+ $this->newVectorHardpoint(self::HARDPOINT_COMMITREFS),
+ $this->newVectorHardpoint(self::HARDPOINT_URIS),
+ );
+ }
+
+ public function setToken($token) {
+ $this->token = $token;
+ return $this;
+ }
+
+ public function getToken() {
+ return $this->token;
+ }
+
+ public function setTypes(array $types) {
+ $this->types = $types;
+ return $this;
+ }
+
+ public function getTypes() {
+ return $this->types;
+ }
+
+ public function hasType($type) {
+ $map = $this->getTypes();
+ $map = array_fuse($map);
+ return isset($map[$type]);
+ }
+
+ public function isUntyped() {
+ return !$this->types;
+ }
+
+ public function setBranch($branch) {
+ $this->branch = $branch;
+ return $this;
+ }
+
+ public function getBranch() {
+ return $this->branch;
+ }
+
+ public function getURIs() {
+ return $this->getHardpoint(self::HARDPOINT_URIS);
+ }
+
+ public function getCommitRefs() {
+ return $this->getHardpoint(self::HARDPOINT_COMMITREFS);
+ }
+
+}
diff --git a/src/browse/ref/ArcanistBrowseURIRefPro.php b/src/browse/ref/ArcanistBrowseURIRefPro.php
new file mode 100644
--- /dev/null
+++ b/src/browse/ref/ArcanistBrowseURIRefPro.php
@@ -0,0 +1,35 @@
+<?php
+
+final class ArcanistBrowseURIRefPro
+ extends ArcanistRefPro {
+
+ private $uri;
+ private $type;
+
+ public function getRefDisplayName() {
+ return pht('Browse URI "%s"', $this->getURI());
+ }
+
+ public function defineHardpoints() {
+ return array();
+ }
+
+ public function setURI($uri) {
+ $this->uri = $uri;
+ return $this;
+ }
+
+ public function getURI() {
+ return $this->uri;
+ }
+
+ public function setType($type) {
+ $this->type = $type;
+ return $this;
+ }
+
+ public function getType() {
+ return $this->type;
+ }
+
+}
diff --git a/src/hardpoint/ArcanistHardpointTask.php b/src/hardpoint/ArcanistHardpointTask.php
--- a/src/hardpoint/ArcanistHardpointTask.php
+++ b/src/hardpoint/ArcanistHardpointTask.php
@@ -171,6 +171,19 @@
$result = $generator_result->getValue();
} else {
$result = $generator->getReturn();
+
+ if ($result instanceof ArcanistHardpointTaskResult) {
+ throw new Exception(
+ pht(
+ 'Generator (for query "%s") returned an '.
+ '"ArcanistHardpointTaskResult" object, which is not a valid '.
+ 'thing to return from a generator.'.
+ "\n\n".
+ 'This almost always means the generator implementation has a '.
+ '"return $this->yield..." statement which should be '.
+ 'a "yield $this->yield..." instead.',
+ get_class($query)));
+ }
}
$this->attachResult($result);
diff --git a/src/inspector/ArcanistBrowseRefInspector.php b/src/inspector/ArcanistBrowseRefInspector.php
new file mode 100644
--- /dev/null
+++ b/src/inspector/ArcanistBrowseRefInspector.php
@@ -0,0 +1,22 @@
+<?php
+
+final class ArcanistBrowseRefInspector
+ extends ArcanistRefInspector {
+
+ public function getInspectFunctionName() {
+ return 'browse';
+ }
+
+ public function newInspectRef(array $argv) {
+ if (count($argv) !== 1) {
+ throw new PhutilArgumentUsageException(
+ pht(
+ 'Expected exactly one argument to "browse(...)" with a '.
+ 'token.'));
+ }
+
+ return id(new ArcanistBrowseRefPro())
+ ->setToken($argv[0]);
+ }
+
+}
diff --git a/src/workflow/ArcanistInspectWorkflow.php b/src/workflow/ArcanistInspectWorkflow.php
--- a/src/workflow/ArcanistInspectWorkflow.php
+++ b/src/workflow/ArcanistInspectWorkflow.php
@@ -21,7 +21,7 @@
public function getWorkflowArguments() {
return array(
- $this->newWorkflowArgument('all')
+ $this->newWorkflowArgument('explore')
->setHelp(pht('Load all object hardpoints.')),
$this->newWorkflowArgument('objects')
->setWildcard(true),
@@ -29,7 +29,7 @@
}
public function runWorkflow() {
- $is_all = $this->getArgument('all');
+ $is_explore = $this->getArgument('explore');
$objects = $this->getArgument('objects');
$inspectors = ArcanistRefInspector::getAllInspectors();
@@ -88,7 +88,7 @@
$all_refs[] = $ref;
}
- if ($is_all) {
+ if ($is_explore) {
foreach ($ref_lists as $ref_class => $refs) {
$ref = head($refs);

File Metadata

Mime Type
text/plain
Expires
Thu, May 9, 8:58 PM (2 w, 6 d ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
6274485
Default Alt Text
D21080.diff (20 KB)

Event Timeline