array( 'param' => 'branch_name', 'help' => pht( 'Default branch name to view on server. Defaults to "master".'), ), 'force' => array( 'help' => pht( 'Open arguments as paths, even if they do not exist in the '. 'working copy.'), ), '*' => 'paths', ); } public function desiresWorkingCopy() { return true; } public function requiresConduit() { return true; } public function requiresAuthentication() { return true; } public function desiresRepositoryAPI() { return true; } public function run() { $console = PhutilConsole::getConsole(); $is_force = $this->getArgument('force'); $things = $this->getArgument('paths'); if (!$things) { throw new ArcanistUsageException( pht( 'Specify one or more paths or objects to browse. Use the command '. '"arc browse ." if you want to browse this directory.')); } $things = array_fuse($things); $objects = $this->getConduit()->callMethodSynchronous( 'phid.lookup', array( 'names' => array_keys($things), )); $uris = array(); foreach ($objects as $name => $object) { $uris[] = $object['uri']; $console->writeOut( pht( 'Opening **%s** as an object.', $name)."\n"); unset($things[$name]); } if ($this->hasRepositoryAPI()) { $repository_api = $this->getRepositoryAPI(); $project_root = $this->getWorkingCopy()->getProjectRoot(); // First, try to resolve arguments as symbolic commits. $commits = array(); foreach ($things as $key => $thing) { $commit = $repository_api->getCanonicalRevisionName($thing); if ($commit) { $commits[$commit] = $key; } } if ($commits) { $commit_info = $this->getConduit()->callMethodSynchronous( 'diffusion.querycommits', array( 'repositoryPHID' => $this->getRepositoryPHID(), 'names' => array_keys($commits), )); foreach ($commit_info['identifierMap'] as $ckey => $cphid) { $thing = $commits[$ckey]; unset($things[$thing]); $uris[] = $commit_info['data'][$cphid]['uri']; $console->writeOut( pht( 'Opening **%s** as a commit.', $thing)."\n"); } } // If we fail, try to resolve them as paths. foreach ($things as $key => $path) { $path = preg_replace('/:([0-9]+)$/', '$\1', $path); $full_path = Filesystem::resolvePath($path); if (!$is_force && !Filesystem::pathExists($full_path)) { continue; } $console->writeOut( pht( 'Opening **%s** as a repository path.', $key)."\n"); unset($things[$key]); if ($full_path == $project_root) { $path = ''; } else { $path = Filesystem::readablePath($full_path, $project_root); } $base_uri = $this->getBaseURI(); $uris[] = $base_uri.$path; } } else { if ($things) { $console->writeOut( pht( "The current working directory is not a repository working ". "copy, so remaining arguments can not be resolved as paths or ". "commits. To browse paths or symbolic commits in Diffusion, run ". "'arc browse' from inside a working copy.")."\n"); } } foreach ($things as $thing) { $console->writeOut( pht( 'Unable to find an object named **%s**, no such commit exists in '. 'the remote, and no such path exists in the working copy. Use '. '__--force__ to treat this as a path anyway.', $thing)."\n"); } if ($uris) { $this->openURIsInBrowser($uris); } return 0; } private function getBaseURI() { $repo_uri = $this->getRepositoryURI(); if ($repo_uri === null) { throw new ArcanistUsageException( pht( 'arc is unable to determine which repository in Diffusion '. 'this working copy belongs to. Use "arc which" to understand how '. 'arc looks for a repository.')); } $branch = $this->getArgument('branch', 'master'); return $repo_uri.'browse/'.$branch.'/'; } }