4
* Browse files or objects in the Phabricator web interface.
6
final class ArcanistBrowseWorkflow extends ArcanistWorkflow {
8
public function getWorkflowName() {
12
public function getCommandSynopses() {
13
return phutil_console_format(<<<EOTEXT
14
**browse** [__options__] __path__ ...
15
**browse** [__options__] __object__ ...
20
public function getCommandHelp() {
21
return phutil_console_format(<<<EOTEXT
22
Supports: git, hg, svn
23
Open a file or object (like a task or revision) in your web browser.
25
$ arc browse README # Open a file in Diffusion.
26
$ arc browse T123 # View a task.
27
$ arc browse HEAD # View a symbolic commit.
29
Set the 'browser' value using 'arc set-config' to select a browser. If
30
no browser is set, the command will try to guess which browser to use.
35
public function getArguments() {
38
'param' => 'branch_name',
40
'Default branch name to view on server. Defaults to "master".'),
44
'Open arguments as paths, even if they do not exist in the '.
51
public function desiresWorkingCopy() {
55
public function requiresConduit() {
59
public function requiresAuthentication() {
63
public function desiresRepositoryAPI() {
67
public function run() {
68
$console = PhutilConsole::getConsole();
70
$is_force = $this->getArgument('force');
72
$things = $this->getArgument('paths');
74
throw new ArcanistUsageException(
76
'Specify one or more paths or objects to browse. Use the command '.
77
'"arc browse ." if you want to browse this directory.'));
79
$things = array_fuse($things);
81
$objects = $this->getConduit()->callMethodSynchronous(
84
'names' => array_keys($things),
88
foreach ($objects as $name => $object) {
89
$uris[] = $object['uri'];
93
'Opening **%s** as an object.',
96
unset($things[$name]);
99
if ($this->hasRepositoryAPI()) {
100
$repository_api = $this->getRepositoryAPI();
101
$project_root = $this->getWorkingCopy()->getProjectRoot();
103
// First, try to resolve arguments as symbolic commits.
106
foreach ($things as $key => $thing) {
108
// Git resolves '.' like HEAD, but it should be interpreted to mean
109
// "the current directory". Just skip resolution and fall through.
114
$commit = $repository_api->getCanonicalRevisionName($thing);
116
$commits[$commit] = $key;
118
} catch (Exception $ex) {
124
$commit_info = $this->getConduit()->callMethodSynchronous(
125
'diffusion.querycommits',
127
'repositoryPHID' => $this->getRepositoryPHID(),
128
'names' => array_keys($commits),
131
foreach ($commit_info['identifierMap'] as $ckey => $cphid) {
132
$thing = $commits[$ckey];
133
unset($things[$thing]);
135
$uris[] = $commit_info['data'][$cphid]['uri'];
139
'Opening **%s** as a commit.',
144
// If we fail, try to resolve them as paths.
146
foreach ($things as $key => $path) {
148
$parts = explode(':', $path);
149
if (count($parts) > 1) {
150
$lines = array_pop($parts);
152
$path = implode(':', $parts);
154
$full_path = Filesystem::resolvePath($path);
156
if (!$is_force && !Filesystem::pathExists($full_path)) {
162
'Opening **%s** as a repository path.',
165
unset($things[$key]);
167
if ($full_path == $project_root) {
170
$path = Filesystem::readablePath($full_path, $project_root);
173
$base_uri = $this->getBaseURI();
174
$uri = $base_uri.$path;
177
$uri = $uri.'$'.$lines;
186
"The current working directory is not a repository working ".
187
"copy, so remaining arguments can not be resolved as paths or ".
188
"commits. To browse paths or symbolic commits in Diffusion, run ".
189
"'arc browse' from inside a working copy.")."\n");
193
foreach ($things as $thing) {
196
'Unable to find an object named **%s**, no such commit exists in '.
197
'the remote, and no such path exists in the working copy. Use '.
198
'__--force__ to treat this as a path anyway.',
203
$this->openURIsInBrowser($uris);
209
private function getBaseURI() {
210
$repo_uri = $this->getRepositoryURI();
211
if ($repo_uri === null) {
212
throw new ArcanistUsageException(
214
'arc is unable to determine which repository in Diffusion '.
215
'this working copy belongs to. Use "arc which" to understand how '.
216
'arc looks for a repository.'));
219
$branch = $this->getArgument('branch', 'master');
221
return $repo_uri.'browse/'.$branch.'/';