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 @@ -47,6 +47,7 @@ 'ArcanistBrowseObjectNameURIHardpointLoader' => 'browse/loader/ArcanistBrowseObjectNameURIHardpointLoader.php', 'ArcanistBrowsePathURIHardpointLoader' => 'browse/loader/ArcanistBrowsePathURIHardpointLoader.php', 'ArcanistBrowseRef' => 'browse/ref/ArcanistBrowseRef.php', + 'ArcanistBrowseRevisionURIHardpointLoader' => 'browse/loader/ArcanistBrowseRevisionURIHardpointLoader.php', 'ArcanistBrowseURIHardpointLoader' => 'browse/loader/ArcanistBrowseURIHardpointLoader.php', 'ArcanistBrowseURIRef' => 'browse/ref/ArcanistBrowseURIRef.php', 'ArcanistBrowseWorkflow' => 'browse/workflow/ArcanistBrowseWorkflow.php', @@ -168,6 +169,7 @@ 'ArcanistGeneratedLinterTestCase' => 'lint/linter/__tests__/ArcanistGeneratedLinterTestCase.php', 'ArcanistGetConfigWorkflow' => 'workflow/ArcanistGetConfigWorkflow.php', 'ArcanistGitAPI' => 'repository/api/ArcanistGitAPI.php', + 'ArcanistGitCommitMessageHardpointLoader' => 'loader/ArcanistGitCommitMessageHardpointLoader.php', 'ArcanistGitHardpointLoader' => 'loader/ArcanistGitHardpointLoader.php', 'ArcanistGitLandEngine' => 'land/ArcanistGitLandEngine.php', 'ArcanistGitRevisionHardpointLoader' => 'loader/ArcanistGitRevisionHardpointLoader.php', @@ -487,6 +489,7 @@ 'ArcanistBrowseObjectNameURIHardpointLoader' => 'ArcanistBrowseURIHardpointLoader', 'ArcanistBrowsePathURIHardpointLoader' => 'ArcanistBrowseURIHardpointLoader', 'ArcanistBrowseRef' => 'ArcanistRef', + 'ArcanistBrowseRevisionURIHardpointLoader' => 'ArcanistBrowseURIHardpointLoader', 'ArcanistBrowseURIHardpointLoader' => 'ArcanistHardpointLoader', 'ArcanistBrowseURIRef' => 'ArcanistRef', 'ArcanistBrowseWorkflow' => 'ArcanistWorkflow', @@ -608,6 +611,7 @@ 'ArcanistGeneratedLinterTestCase' => 'ArcanistLinterTestCase', 'ArcanistGetConfigWorkflow' => 'ArcanistWorkflow', 'ArcanistGitAPI' => 'ArcanistRepositoryAPI', + 'ArcanistGitCommitMessageHardpointLoader' => 'ArcanistGitHardpointLoader', 'ArcanistGitHardpointLoader' => 'ArcanistHardpointLoader', 'ArcanistGitLandEngine' => 'ArcanistLandEngine', 'ArcanistGitRevisionHardpointLoader' => 'ArcanistGitHardpointLoader', diff --git a/src/browse/loader/ArcanistBrowseCommitHardpointLoader.php b/src/browse/loader/ArcanistBrowseCommitHardpointLoader.php --- a/src/browse/loader/ArcanistBrowseCommitHardpointLoader.php +++ b/src/browse/loader/ArcanistBrowseCommitHardpointLoader.php @@ -33,9 +33,6 @@ $commit_map = array(); foreach ($refs as $key => $ref) { - $is_commit = $ref->hasType( - ArcanistBrowseCommitURIHardpointLoader::BROWSETYPE); - $token = $ref->getToken(); if ($token === '.') { @@ -44,12 +41,10 @@ continue; } + // Always resolve the empty token; top-level loaders filter out + // irrelevant tokens before this stage. if ($token === null) { - if ($is_commit) { - $token = $api->getHeadCommit(); - } else { - continue; - } + $token = $api->getHeadCommit(); } try { diff --git a/src/browse/loader/ArcanistBrowseCommitURIHardpointLoader.php b/src/browse/loader/ArcanistBrowseCommitURIHardpointLoader.php --- a/src/browse/loader/ArcanistBrowseCommitURIHardpointLoader.php +++ b/src/browse/loader/ArcanistBrowseCommitURIHardpointLoader.php @@ -47,7 +47,6 @@ } $refs = $this->getRefsWithSupportedTypes($refs); - if (!$refs) { return array(); } @@ -80,7 +79,7 @@ $uri = $commit_ref->getURI(); if ($uri !== null) { $results[$key][] = id(new ArcanistBrowseURIRef()) - ->setURI() + ->setURI($uri) ->setType(self::BROWSETYPE); } } diff --git a/src/browse/loader/ArcanistBrowseRevisionURIHardpointLoader.php b/src/browse/loader/ArcanistBrowseRevisionURIHardpointLoader.php new file mode 100644 --- /dev/null +++ b/src/browse/loader/ArcanistBrowseRevisionURIHardpointLoader.php @@ -0,0 +1,78 @@ +getQuery(); + + $working_ref = $query->getWorkingCopyRef(); + if (!$working_ref) { + return array(); + } + + $repository_ref = $query->getRepositoryRef(); + if (!$repository_ref) { + return array(); + } + + $refs = $this->getRefsWithSupportedTypes($refs); + if (!$refs) { + return array(); + } + + $this->newQuery($refs) + ->needHardpoints( + array( + 'commitRefs', + )) + ->execute(); + + $states = array(); + $map = array(); + foreach ($refs as $key => $ref) { + foreach ($ref->getCommitRefs() as $commit_ref) { + $hash = $commit_ref->getCommitHash(); + $states[$hash] = id(clone $working_ref) + ->setCommitRef($commit_ref); + $map[$hash][] = $key; + } + } + + if (!$states) { + return array(); + } + + $this->newQuery($states) + ->needHardpoints( + array( + 'revisionRefs', + )) + ->execute(); + + $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][] = id(new ArcanistBrowseURIRef()) + ->setURI($uri) + ->setType(self::BROWSETYPE); + } + } + } + + return $results; + } + + +} diff --git a/src/browse/workflow/ArcanistBrowseWorkflow.php b/src/browse/workflow/ArcanistBrowseWorkflow.php --- a/src/browse/workflow/ArcanistBrowseWorkflow.php +++ b/src/browse/workflow/ArcanistBrowseWorkflow.php @@ -68,13 +68,6 @@ $console = PhutilConsole::getConsole(); $targets = $this->getArgument('targets'); - if (!$targets) { - throw new ArcanistUsageException( - pht( - 'Specify one or more paths or objects to browse. Use the '. - 'command "%s" if you want to browse this directory.', - 'arc browse .')); - } $targets = array_fuse($targets); if (!$targets) { @@ -222,11 +215,19 @@ // If anything failed to resolve, this is also an error. if ($zero_hits) { foreach ($zero_hits as $ref) { - echo tsprintf( - "%s\n", - pht( - 'Unable to resolve argument "%s".', - $ref->getToken())); + $token = $ref->getToken(); + if ($token === null) { + echo tsprintf( + "%s\n", + pht( + 'Unable to resolve default browse target.')); + } else { + echo tsprintf( + "%s\n", + pht( + 'Unable to resolve argument "%s".', + $ref->getToken())); + } } foreach ($loaders as $loader) { diff --git a/src/loader/ArcanistGitCommitMessageHardpointLoader.php b/src/loader/ArcanistGitCommitMessageHardpointLoader.php new file mode 100644 --- /dev/null +++ b/src/loader/ArcanistGitCommitMessageHardpointLoader.php @@ -0,0 +1,41 @@ +getQuery()->getRepositoryAPI(); + + + $futures = array(); + foreach ($refs as $ref_key => $ref) { + $hash = $ref->getCommitHash(); + + $futures[$ref_key] = $api->execFutureLocal( + 'log -n1 --format=%C %s --', + '%s%n%n%b', + $hash); + } + + $iterator = $this->newFutureIterator($futures); + + $results = array(); + foreach ($iterator as $ref_key => $future) { + list($stdout) = $future->resolvex(); + $results[$ref_key] = $stdout; + } + + return $results; + } + +} diff --git a/src/loader/ArcanistGitRevisionHardpointLoader.php b/src/loader/ArcanistGitRevisionHardpointLoader.php --- a/src/loader/ArcanistGitRevisionHardpointLoader.php +++ b/src/loader/ArcanistGitRevisionHardpointLoader.php @@ -33,10 +33,12 @@ $commit->getCommitHash(), ); - $commit_hashes[] = array( - 'gttr', - $commit->getTreeHash(), - ); + if ($commit->getTreeHash()) { + $commit_hashes[] = array( + 'gttr', + $commit->getTreeHash(), + ); + } foreach ($commit_hashes as $hash) { $hashes[] = $hash; diff --git a/src/ref/ArcanistRevisionRef.php b/src/ref/ArcanistRevisionRef.php --- a/src/ref/ArcanistRevisionRef.php +++ b/src/ref/ArcanistRevisionRef.php @@ -28,6 +28,22 @@ return idx($this->parameters, 'statusName'); } + public function isClosed() { + // TODO: This should use sensible constants, not English language + // display text. + switch ($this->getStatusDisplayName()) { + case 'Abandoned': + case 'Closed': + return true; + } + + return false; + } + + public function getURI() { + return idx($this->parameters, 'uri'); + } + public function getFullName() { return pht('%s: %s', $this->getMonogram(), $this->getName()); }