public function testXHPASTLint()
 {
     $linter = new ArcanistXHPASTLinter();
     $linter->setCustomSeverityMap(array(ArcanistXHPASTLinter::LINT_RAGGED_CLASSTREE_EDGE => ArcanistLintSeverity::SEVERITY_WARNING));
     $working_copy = ArcanistWorkingCopyIdentity::newFromPath(__FILE__);
     return $this->executeTestsInDirectory(dirname(__FILE__) . '/xhpast/', $linter, $working_copy);
 }
 public function run()
 {
     $roots = array('libphutil' => dirname(phutil_get_library_root('phutil')), 'arcanist' => dirname(phutil_get_library_root('arcanist')));
     foreach ($roots as $lib => $root) {
         echo phutil_console_format("%s\n", pht('Upgrading %s...', $lib));
         $working_copy = ArcanistWorkingCopyIdentity::newFromPath($root);
         $configuration_manager = clone $this->getConfigurationManager();
         $configuration_manager->setWorkingCopyIdentity($working_copy);
         $repository = ArcanistRepositoryAPI::newAPIFromConfigurationManager($configuration_manager);
         if (!Filesystem::pathExists($repository->getMetadataPath())) {
             throw new ArcanistUsageException(pht("%s must be in its git working copy to be automatically upgraded. " . "This copy of %s (in '%s') is not in a git working copy.", $lib, $lib, $root));
         }
         $this->setRepositoryAPI($repository);
         // Require no local changes.
         $this->requireCleanWorkingCopy();
         // Require the library be on master.
         $branch_name = $repository->getBranchName();
         if ($branch_name != 'master') {
             throw new ArcanistUsageException(pht("%s must be on branch '%s' to be automatically upgraded. " . "This copy of %s (in '%s') is on branch '%s'.", $lib, 'master', $lib, $root, $branch_name));
         }
         chdir($root);
         try {
             phutil_passthru('git pull --rebase');
         } catch (Exception $ex) {
             phutil_passthru('git rebase --abort');
             throw $ex;
         }
     }
     echo phutil_console_format("**%s** %s\n", pht('Updated!'), pht('Your copy of arc is now up to date.'));
     return 0;
 }
 public function run()
 {
     $roots = array();
     $roots['libphutil'] = dirname(phutil_get_library_root('phutil'));
     $roots['arcanist'] = dirname(phutil_get_library_root('arcanist'));
     foreach ($roots as $lib => $root) {
         echo "Upgrading {$lib}...\n";
         if (!Filesystem::pathExists($root . '/.git')) {
             throw new ArcanistUsageException("{$lib} must be in its git working copy to be automatically " . "upgraded. This copy of {$lib} (in '{$root}') is not in a git " . "working copy.");
         }
         $working_copy = ArcanistWorkingCopyIdentity::newFromPath($root);
         $configuration_manager = clone $this->getConfigurationManager();
         $configuration_manager->setWorkingCopyIdentity($working_copy);
         $repository_api = ArcanistRepositoryAPI::newAPIFromConfigurationManager($configuration_manager);
         $this->setRepositoryAPI($repository_api);
         // Require no local changes.
         $this->requireCleanWorkingCopy();
         // Require the library be on master.
         $branch_name = $repository_api->getBranchName();
         if ($branch_name != 'master') {
             throw new ArcanistUsageException("{$lib} must be on branch 'master' to be automatically upgraded. " . "This copy of {$lib} (in '{$root}') is on branch '{$branch_name}'.");
         }
         chdir($root);
         try {
             phutil_passthru('git pull --rebase');
         } catch (Exception $ex) {
             phutil_passthru('git rebase --abort');
             throw $ex;
         }
     }
     echo phutil_console_wrap(phutil_console_format("**Updated!** Your copy of arc is now up to date.\n"));
     return 0;
 }
 public function run()
 {
     $roots = array();
     $roots['libphutil'] = dirname(phutil_get_library_root('phutil'));
     $roots['arcanist'] = dirname(phutil_get_library_root('arcanist'));
     foreach ($roots as $lib => $root) {
         echo "Upgrading {$lib}...\n";
         if (!Filesystem::pathExists($root . '/.git')) {
             throw new ArcanistUsageException("{$lib} must be in its git working copy to be automatically " . "upgraded. This copy of {$lib} (in '{$root}') is not in a git " . "working copy.");
         }
         $working_copy = ArcanistWorkingCopyIdentity::newFromPath($root);
         $repository_api = ArcanistRepositoryAPI::newAPIFromWorkingCopyIdentity($working_copy);
         // Force the range to HEAD^..HEAD, which is meaningless but keeps us
         // from triggering "base" rules or other commit range resolution rules
         // that might prompt the user when we pull the working copy status.
         $repository_api->setRelativeCommit('HEAD^');
         $this->setRepositoryAPI($repository_api);
         // Require no local changes.
         $this->requireCleanWorkingCopy();
         // Require the library be on master.
         $branch_name = $repository_api->getBranchName();
         if ($branch_name != 'master') {
             throw new ArcanistUsageException("{$lib} must be on branch 'master' to be automatically upgraded. " . "This copy of {$lib} (in '{$root}') is on branch '{$branch_name}'.");
         }
         chdir($root);
         try {
             phutil_passthru('git pull --rebase');
         } catch (Exception $ex) {
             phutil_passthru('git rebase --abort');
             throw $ex;
         }
     }
     echo phutil_console_wrap(phutil_console_format("**Updated!** Your copy of arc is now up to date.\n"));
     return 0;
 }
 public function testPhutilXHPASTLint()
 {
     $linter = new ArcanistPhutilXHPASTLinter();
     $linter->setXHPASTLinter(new ArcanistXHPASTLinter());
     $linter->setDeprecatedFunctions(array('deprecated_function' => 'This function is most likely deprecated.'));
     $working_copy = ArcanistWorkingCopyIdentity::newFromPath(__FILE__);
     return $this->executeTestsInDirectory(dirname(__FILE__) . '/phlxhp/', $linter, $working_copy);
 }
 public function testSpellingLint()
 {
     $linter = new ArcanistSpellingLinter();
     $linter->removeLintRule('acc' . 'out');
     $linter->addPartialWordRule('supermn', 'superman');
     $linter->addWholeWordRule('batmn', 'batman');
     $working_copy = ArcanistWorkingCopyIdentity::newFromPath(__FILE__);
     return $this->executeTestsInDirectory(dirname(__FILE__) . '/spelling/', $linter, $working_copy);
 }
 private function buildParser()
 {
     // TODO: This is a little hacky beacuse we're using the Arcanist repository
     // itself to execute tests with, but it should be OK until we get proper
     // isolation for repository-oriented test cases.
     $root = dirname(phutil_get_library_root('arcanist'));
     $copy = ArcanistWorkingCopyIdentity::newFromPath($root);
     $repo = ArcanistRepositoryAPI::newAPIFromWorkingCopyIdentity($copy);
     return new ArcanistBaseCommitParser($repo);
 }
 public function testStateParsing()
 {
     $dir = dirname(__FILE__) . '/state/';
     $tests = Filesystem::listDirectory($dir, $include_hidden = false);
     foreach ($tests as $test) {
         $fixture = PhutilDirectoryFixture::newFromArchive($dir . '/' . $test);
         $fixture_path = $fixture->getPath();
         $working_copy = ArcanistWorkingCopyIdentity::newFromPath($fixture_path);
         $api = ArcanistRepositoryAPI::newAPIFromWorkingCopyIdentity($working_copy);
         $api->setBaseCommitArgumentRules('arc:this');
         $this->assertCorrectState($test, $api);
     }
 }
Esempio n. 9
0
 public function run()
 {
     // We might not be in a working directory, so we don't want to require a
     // working copy identity here.
     $working_copy = ArcanistWorkingCopyIdentity::newFromPath(getcwd());
     $aliases = self::getAliases($working_copy);
     $argv = $this->getArgument('argv');
     if (count($argv) == 0) {
         if ($aliases) {
             foreach ($aliases as $alias => $binding) {
                 echo phutil_console_format("**%s** %s\n", $alias, implode(' ', $binding));
             }
         } else {
             echo "You haven't defined any aliases yet.\n";
         }
     } else {
         if (count($argv) == 1) {
             if (empty($aliases[$argv[0]])) {
                 echo "No alias '{$argv[0]}' to remove.\n";
             } else {
                 echo phutil_console_format("'**arc %s**' is currently aliased to '**arc %s**'.", $argv[0], implode(' ', $aliases[$argv[0]]));
                 $ok = phutil_console_confirm('Delete this alias?');
                 if ($ok) {
                     $was = implode(' ', $aliases[$argv[0]]);
                     unset($aliases[$argv[0]]);
                     $this->writeAliases($aliases);
                     echo "Unaliased '{$argv[0]}' (was '{$was}').\n";
                 } else {
                     throw new ArcanistUserAbortException();
                 }
             }
         } else {
             $arc_config = $this->getArcanistConfiguration();
             if ($arc_config->buildWorkflow($argv[0])) {
                 throw new ArcanistUsageException("You can not create an alias for '{$argv[0]}' because it is a " . "builtin command. 'arc alias' can only create new commands.");
             }
             $aliases[$argv[0]] = array_slice($argv, 1);
             echo phutil_console_format("Aliased '**arc %s**' to '**arc %s**'.\n", $argv[0], implode(' ', $aliases[$argv[0]]));
             $this->writeAliases($aliases);
         }
     }
     return 0;
 }
 public function run()
 {
     $console = PhutilConsole::getConsole();
     if (!Filesystem::binaryExists('git')) {
         throw new ArcanistUsageException(pht('Cannot display current version without having `%s` installed.', 'git'));
     }
     $roots = array('arcanist' => dirname(phutil_get_library_root('arcanist')), 'libphutil' => dirname(phutil_get_library_root('phutil')));
     foreach ($roots as $lib => $root) {
         $working_copy = ArcanistWorkingCopyIdentity::newFromPath($root);
         $configuration_manager = clone $this->getConfigurationManager();
         $configuration_manager->setWorkingCopyIdentity($working_copy);
         $repository = ArcanistRepositoryAPI::newAPIFromConfigurationManager($configuration_manager);
         if (!Filesystem::pathExists($repository->getMetadataPath())) {
             throw new ArcanistUsageException(pht('%s is not a git working copy.', $lib));
         }
         list($stdout) = $repository->execxLocal('log -1 --format=%s', '%H %ct');
         list($commit, $timestamp) = explode(' ', $stdout);
         $console->writeOut("%s %s (%s)\n", $lib, $commit, date('j M Y', (int) $timestamp));
     }
 }
 private function parseState($test)
 {
     $dir = dirname(__FILE__) . '/state/';
     $fixture = PhutilDirectoryFixture::newFromArchive($dir . '/' . $test);
     $fixture_path = $fixture->getPath();
     $working_copy = ArcanistWorkingCopyIdentity::newFromPath($fixture_path);
     $configuration_manager = new ArcanistConfigurationManager();
     $configuration_manager->setWorkingCopyIdentity($working_copy);
     $api = ArcanistRepositoryAPI::newAPIFromConfigurationManager($configuration_manager);
     $api->setBaseCommitArgumentRules('arc:this');
     if ($api instanceof ArcanistSubversionAPI) {
         // Upgrade the repository so that the test will still pass if the local
         // `svn` is newer than the `svn` which created the repository.
         // NOTE: Some versions of Subversion (1.7.x?) exit with an error code on
         // a no-op upgrade, although newer versions do not. We just ignore the
         // error here; if it's because of an actual problem we'll hit an error
         // shortly anyway.
         $api->execManualLocal('upgrade');
     }
     $this->assertCorrectState($test, $api);
 }
Esempio n. 12
0
 public function run()
 {
     $roots = array('libphutil' => dirname(phutil_get_library_root('phutil')), 'arcanist' => dirname(phutil_get_library_root('arcanist')));
     foreach ($roots as $lib => $root) {
         echo phutil_console_format("%s\n", pht('Upgrading %s...', $lib));
         $working_copy = ArcanistWorkingCopyIdentity::newFromPath($root);
         $configuration_manager = clone $this->getConfigurationManager();
         $configuration_manager->setWorkingCopyIdentity($working_copy);
         $repository = ArcanistRepositoryAPI::newAPIFromConfigurationManager($configuration_manager);
         if (!Filesystem::pathExists($repository->getMetadataPath())) {
             throw new ArcanistUsageException(pht("%s must be in its git working copy to be automatically upgraded. " . "This copy of %s (in '%s') is not in a git working copy.", $lib, $lib, $root));
         }
         $this->setRepositoryAPI($repository);
         // NOTE: Don't use requireCleanWorkingCopy() here because it tries to
         // amend changes and generally move the workflow forward. We just want to
         // abort if there are local changes and make the user sort things out.
         $uncommitted = $repository->getUncommittedStatus();
         if ($uncommitted) {
             $message = pht('You have uncommitted changes in the working copy for this ' . 'library:');
             $list = id(new PhutilConsoleList())->setWrap(false)->addItems(array_keys($uncommitted));
             id(new PhutilConsoleBlock())->addParagraph($message)->addList($list)->draw();
             throw new ArcanistUsageException(pht('`arc upgrade` can only upgrade clean working copies.'));
         }
         $branch_name = $repository->getBranchName();
         if ($branch_name != 'master' && $branch_name != 'stable') {
             throw new ArcanistUsageException(pht("%s must be on either branch '%s' or '%s' to be automatically " . "upgraded. " . "This copy of %s (in '%s') is on branch '%s'.", $lib, 'master', 'stable', $lib, $root, $branch_name));
         }
         chdir($root);
         try {
             execx('git pull --rebase');
         } catch (Exception $ex) {
             // If we failed, try to go back to the old state, then throw the
             // original exception.
             exec_manual('git rebase --abort');
             throw $ex;
         }
     }
     echo phutil_console_format("**%s** %s\n", pht('Updated!'), pht('Your copy of arc is now up to date.'));
     return 0;
 }
 public function run()
 {
     $pos = $this->getArgument('current');
     $argv = $this->getArgument('argv', array());
     $argc = count($argv);
     if ($pos === null) {
         $pos = $argc - 1;
     }
     if ($pos > $argc) {
         throw new ArcanistUsageException(pht('Specified position is greater than the number of ' . 'arguments provided.'));
     }
     // Determine which revision control system the working copy uses, so we
     // can filter out commands and flags which aren't supported. If we can't
     // figure it out, just return all flags/commands.
     $vcs = null;
     // We have to build our own because if we requiresWorkingCopy() we'll throw
     // if we aren't in a .arcconfig directory. We probably still can't do much,
     // but commands can raise more detailed errors.
     $configuration_manager = $this->getConfigurationManager();
     $working_copy = ArcanistWorkingCopyIdentity::newFromPath(getcwd());
     if ($working_copy->getVCSType()) {
         $configuration_manager->setWorkingCopyIdentity($working_copy);
         $repository_api = ArcanistRepositoryAPI::newAPIFromConfigurationManager($configuration_manager);
         $vcs = $repository_api->getSourceControlSystemName();
     }
     $arc_config = $this->getArcanistConfiguration();
     if ($pos <= 1) {
         $workflows = $arc_config->buildAllWorkflows();
         $complete = array();
         foreach ($workflows as $name => $workflow) {
             if (!$workflow->shouldShellComplete()) {
                 continue;
             }
             $workflow->setArcanistConfiguration($this->getArcanistConfiguration());
             $workflow->setConfigurationManager($this->getConfigurationManager());
             if ($vcs || $workflow->requiresWorkingCopy()) {
                 $supported_vcs = $workflow->getSupportedRevisionControlSystems();
                 if (!in_array($vcs, $supported_vcs)) {
                     continue;
                 }
             }
             $complete[] = $name;
         }
         // Also permit autocompletion of "arc alias" commands.
         $aliases = ArcanistAliasWorkflow::getAliases($configuration_manager);
         foreach ($aliases as $key => $value) {
             $complete[] = $key;
         }
         echo implode(' ', $complete) . "\n";
         return 0;
     } else {
         $workflow = $arc_config->buildWorkflow($argv[1]);
         if (!$workflow) {
             list($new_command, $new_args) = ArcanistAliasWorkflow::resolveAliases($argv[1], $arc_config, array_slice($argv, 2), $configuration_manager);
             if ($new_command) {
                 $workflow = $arc_config->buildWorkflow($new_command);
             }
             if (!$workflow) {
                 return 1;
             } else {
                 $argv = array_merge(array($argv[0]), array($new_command), $new_args);
             }
         }
         $arguments = $workflow->getArguments();
         $prev = idx($argv, $pos - 1, null);
         if (!strncmp($prev, '--', 2)) {
             $prev = substr($prev, 2);
         } else {
             $prev = null;
         }
         if ($prev !== null && isset($arguments[$prev]) && isset($arguments[$prev]['param'])) {
             $type = idx($arguments[$prev], 'paramtype');
             switch ($type) {
                 case 'file':
                     echo "FILE\n";
                     break;
                 case 'complete':
                     echo implode(' ', $workflow->getShellCompletions($argv)) . "\n";
                     break;
                 default:
                     echo "ARGUMENT\n";
                     break;
             }
             return 0;
         } else {
             $output = array();
             foreach ($arguments as $argument => $spec) {
                 if ($argument == '*') {
                     continue;
                 }
                 if ($vcs && isset($spec['supports']) && !in_array($vcs, $spec['supports'])) {
                     continue;
                 }
                 $output[] = '--' . $argument;
             }
             $cur = idx($argv, $pos, '');
             $any_match = false;
             if (strlen($cur)) {
                 foreach ($output as $possible) {
                     if (!strncmp($possible, $cur, strlen($cur))) {
                         $any_match = true;
                     }
                 }
             }
             if (!$any_match && isset($arguments['*'])) {
                 // TODO: This is mega hacktown but something else probably breaks
                 // if we use a rich argument specification; fix it when we move to
                 // PhutilArgumentParser since everything will need to be tested then
                 // anyway.
                 if ($arguments['*'] == 'branch' && isset($repository_api)) {
                     $branches = $repository_api->getAllBranches();
                     $branches = ipull($branches, 'name');
                     $output = $branches;
                 } else {
                     $output = array('FILE');
                 }
             }
             echo implode(' ', $output) . "\n";
             return 0;
         }
     }
 }
 public function run($dir)
 {
     $working_copy = ArcanistWorkingCopyIdentity::newFromPath($dir);
     $configuration_manager = new ArcanistConfigurationManager();
     $configuration_manager->setWorkingCopyIdentity($working_copy);
     $api = ArcanistRepositoryAPI::newAPIFromConfigurationManager($configuration_manager);
     $this->svnRoot = id(new PhutilURI($api->getSourceControlPath()))->getPath();
     if ($api instanceof ArcanistGitAPI) {
         $svn_fetch = $api->getGitConfig('svn-remote.svn.fetch');
         list($this->svnRoot) = explode(':', $svn_fetch);
         if ($this->svnRoot != '') {
             $this->svnRoot = '/' . $this->svnRoot;
         }
     }
     $project_id = $working_copy->getProjectID();
     $project = id(new PhabricatorRepositoryArcanistProject())->loadOneWhere('name = %s', $project_id);
     if (!$project || !$project->getRepositoryID()) {
         throw new Exception("Couldn't find repository for {$project_id}.");
     }
     $branch_name = $api->getBranchName();
     $this->branch = PhabricatorRepositoryBranch::loadOrCreateBranch($project->getRepositoryID(), $branch_name);
     $this->conn = $this->branch->establishConnection('w');
     $this->lintCommit = null;
     if (!$this->all) {
         $this->lintCommit = $this->branch->getLintCommit();
     }
     if ($this->lintCommit) {
         try {
             $commit = $this->lintCommit;
             if ($this->svnRoot) {
                 $commit = $api->getCanonicalRevisionName('@' . $commit);
             }
             $all_files = $api->getChangedFiles($commit);
         } catch (ArcanistCapabilityNotSupportedException $ex) {
             $this->lintCommit = null;
         }
     }
     if (!$this->lintCommit) {
         $where = $this->svnRoot ? qsprintf($this->conn, 'AND path LIKE %>', $this->svnRoot . '/') : '';
         queryfx($this->conn, 'DELETE FROM %T WHERE branchID = %d %Q', PhabricatorRepository::TABLE_LINTMESSAGE, $this->branch->getID(), $where);
         $all_files = $api->getAllFiles();
     }
     $count = 0;
     $files = array();
     foreach ($all_files as $file => $val) {
         $count++;
         if (!$this->lintCommit) {
             $file = $val;
         } else {
             $this->deletes[] = $this->svnRoot . '/' . $file;
             if ($val & ArcanistRepositoryAPI::FLAG_DELETED) {
                 continue;
             }
         }
         $files[$file] = $file;
         if (count($files) >= $this->chunkSize) {
             $this->runArcLint($files);
             $files = array();
         }
     }
     $this->runArcLint($files);
     $this->saveLintMessages();
     $this->lintCommit = $api->getUnderlyingWorkingCopyRevision();
     $this->branch->setLintCommit($this->lintCommit);
     $this->branch->save();
     if ($this->blame) {
         $this->blameAuthors();
         $this->blame = array();
     }
     return $count;
 }
Esempio n. 15
0
 } else {
     if ($help) {
         array_unshift($args, 'help');
     }
 }
 $configuration_manager = new ArcanistConfigurationManager();
 if ($custom_arcrc) {
     $configuration_manager->setUserConfigurationFileLocation($custom_arcrc);
 }
 $global_config = $configuration_manager->readUserArcConfig();
 $system_config = $configuration_manager->readSystemArcConfig();
 $runtime_config = $configuration_manager->applyRuntimeArcConfig($base_args);
 if ($skip_arcconfig) {
     $working_copy = ArcanistWorkingCopyIdentity::newDummyWorkingCopy();
 } else {
     $working_copy = ArcanistWorkingCopyIdentity::newFromPath($working_directory);
 }
 $configuration_manager->setWorkingCopyIdentity($working_copy);
 reenter_if_this_is_arcanist_or_libphutil($console, $working_copy, $original_argv);
 // Load additional libraries, which can provide new classes like configuration
 // overrides, linters and lint engines, unit test engines, etc.
 // If the user specified "--load-phutil-library" one or more times from
 // the command line, we load those libraries **instead** of whatever else
 // is configured. This is basically a debugging feature to let you force
 // specific libraries to load regardless of the state of the world.
 if ($load) {
     $console->writeLog("Using '--load-phutil-library' flag, configuration will be ignored " . "and configured libraries will not be loaded." . "\n");
     // Load the flag libraries. These must load, since the user specified them
     // explicitly.
     arcanist_load_libraries($load, $must_load = true, $lib_source = 'a "--load-phutil-library" flag', $working_copy);
 } else {
Esempio n. 16
0
 function generateCoverageResults()
 {
     // Find all executables, not just the test executables.
     // We need to do this because the test executables may not
     // include all of the possible code (linker decides to omit
     // it from the image) so we see a skewed representation of
     // the source lines.
     $fp = popen("find {$this->repo_root} -type f -name watchman -o " . "-name \\*.a -o -name \\*.so -o -name \\*.dylib", "r");
     while (true) {
         $line = fgets($fp);
         if ($line === false) {
             break;
         }
         $obj_files[] = trim($line);
     }
     // Parse line information from the objects
     foreach ($obj_files as $object) {
         DwarfLineInfo::loadObject($object);
     }
     $CG = new CallgrindFile((string) $this->cg_file);
     $CG->parse();
     $source_files = array();
     foreach ($CG->getSourceFiles() as $filename) {
         if (Filesystem::isDescendant($filename, $this->repo_root) && !preg_match("/(thirdparty|tests)/", $filename)) {
             $source_files[$filename] = $filename;
         }
     }
     $cov = array();
     foreach ($source_files as $filename) {
         $relsrc = substr($filename, strlen($this->repo_root) + 1);
         $cov[$relsrc] = CallgrindFile::mergeSourceLineData($filename, array($CG));
     }
     $res = new ArcanistUnitTestResult();
     $res->setName('coverage');
     $res->setUserData("Collected");
     $res->setResult(ArcanistUnitTestResult::RESULT_PASS);
     $res->setCoverage($cov);
     // Stash it for review with our `arc cov` command
     $wc = ArcanistWorkingCopyIdentity::newFromPath($this->repo_root);
     $api = ArcanistRepositoryAPI::newAPIFromWorkingCopyIdentity($wc);
     $api->writeScratchFile('wman-cov.json', json_encode($cov));
     return array($res);
 }
 public function testCpplintLint()
 {
     $linter = new ArcanistCpplintLinter();
     $working_copy = ArcanistWorkingCopyIdentity::newFromPath(__FILE__);
     return $this->executeTestsInDirectory(dirname(__FILE__) . '/cpp/', $linter, $working_copy);
 }
 public function run($dir)
 {
     $working_copy = ArcanistWorkingCopyIdentity::newFromPath($dir);
     $configuration_manager = new ArcanistConfigurationManager();
     $configuration_manager->setWorkingCopyIdentity($working_copy);
     $api = ArcanistRepositoryAPI::newAPIFromConfigurationManager($configuration_manager);
     $this->svnRoot = id(new PhutilURI($api->getSourceControlPath()))->getPath();
     if ($api instanceof ArcanistGitAPI) {
         $svn_fetch = $api->getGitConfig('svn-remote.svn.fetch');
         list($this->svnRoot) = explode(':', $svn_fetch);
         if ($this->svnRoot != '') {
             $this->svnRoot = '/' . $this->svnRoot;
         }
     }
     $callsign = $configuration_manager->getConfigFromAnySource('repository.callsign');
     $uuid = $api->getRepositoryUUID();
     $remote_uri = $api->getRemoteURI();
     $repository_query = id(new PhabricatorRepositoryQuery())->setViewer(PhabricatorUser::getOmnipotentUser());
     if ($callsign) {
         $repository_query->withCallsigns(array($callsign));
     } else {
         if ($uuid) {
             $repository_query->withUUIDs(array($uuid));
         } else {
             if ($remote_uri) {
                 $repository_query->withRemoteURIs(array($remote_uri));
             }
         }
     }
     $repository = $repository_query->executeOne();
     $branch_name = $api->getBranchName();
     if (!$repository) {
         throw new Exception(pht('No repository was found.'));
     }
     $this->branch = PhabricatorRepositoryBranch::loadOrCreateBranch($repository->getID(), $branch_name);
     $this->conn = $this->branch->establishConnection('w');
     $this->lintCommit = null;
     if (!$this->all) {
         $this->lintCommit = $this->branch->getLintCommit();
     }
     if ($this->lintCommit) {
         try {
             $commit = $this->lintCommit;
             if ($this->svnRoot) {
                 $commit = $api->getCanonicalRevisionName('@' . $commit);
             }
             $all_files = $api->getChangedFiles($commit);
         } catch (ArcanistCapabilityNotSupportedException $ex) {
             $this->lintCommit = null;
         }
     }
     if (!$this->lintCommit) {
         $where = $this->svnRoot ? qsprintf($this->conn, 'AND path LIKE %>', $this->svnRoot . '/') : '';
         queryfx($this->conn, 'DELETE FROM %T WHERE branchID = %d %Q', PhabricatorRepository::TABLE_LINTMESSAGE, $this->branch->getID(), $where);
         $all_files = $api->getAllFiles();
     }
     $count = 0;
     $files = array();
     foreach ($all_files as $file => $val) {
         $count++;
         if (!$this->lintCommit) {
             $file = $val;
         } else {
             $this->deletes[] = $this->svnRoot . '/' . $file;
             if ($val & ArcanistRepositoryAPI::FLAG_DELETED) {
                 continue;
             }
         }
         $files[$file] = $file;
         if (count($files) >= $this->chunkSize) {
             $this->runArcLint($files);
             $files = array();
         }
     }
     $this->runArcLint($files);
     $this->saveLintMessages();
     $this->lintCommit = $api->getUnderlyingWorkingCopyRevision();
     $this->branch->setLintCommit($this->lintCommit);
     $this->branch->save();
     if ($this->blame) {
         $this->blameAuthors();
         $this->blame = array();
     }
     return $count;
 }
 public function run()
 {
     $pos = $this->getArgument('current');
     $argv = $this->getArgument('argv', array());
     $argc = count($argv);
     if ($pos === null) {
         $pos = $argc - 1;
     }
     // Determine which revision control system the working copy uses, so we
     // can filter out commands and flags which aren't supported. If we can't
     // figure it out, just return all flags/commands.
     $vcs = null;
     // We have to build our own because if we requiresWorkingCopy() we'll throw
     // if we aren't in a .arcconfig directory. We probably still can't do much,
     // but commands can raise more detailed errors.
     $working_copy = ArcanistWorkingCopyIdentity::newFromPath(getcwd());
     if ($working_copy->getProjectRoot()) {
         $repository_api = ArcanistRepositoryAPI::newAPIFromWorkingCopyIdentity($working_copy);
         $vcs = $repository_api->getSourceControlSystemName();
     }
     $arc_config = $this->getArcanistConfiguration();
     if ($pos == 1) {
         $workflows = $arc_config->buildAllWorkflows();
         $complete = array();
         foreach ($workflows as $name => $workflow) {
             if (!$workflow->shouldShellComplete()) {
                 continue;
             }
             $supported = $workflow->getSupportedRevisionControlSystems();
             $ok = in_array('any', $supported) || in_array($vcs, $supported);
             if (!$ok) {
                 continue;
             }
             $complete[] = $name;
         }
         // Also permit autocompletion of "arc alias" commands.
         foreach (ArcanistAliasWorkflow::getAliases($working_copy) as $key => $value) {
             $complete[] = $key;
         }
         echo implode(' ', $complete) . "\n";
         return 0;
     } else {
         $workflow = $arc_config->buildWorkflow($argv[1]);
         if (!$workflow) {
             list($new_command, $new_args) = ArcanistAliasWorkflow::resolveAliases($argv[1], $arc_config, array_slice($argv, 2), $working_copy);
             if ($new_command) {
                 $workflow = $arc_config->buildWorkflow($new_command);
             }
             if (!$workflow) {
                 return 1;
             } else {
                 $argv = array_merge(array($argv[0]), array($new_command), $new_args);
             }
         }
         $arguments = $workflow->getArguments();
         $prev = idx($argv, $pos - 1, null);
         if (!strncmp($prev, '--', 2)) {
             $prev = substr($prev, 2);
         } else {
             $prev = null;
         }
         if ($prev !== null && isset($arguments[$prev]) && isset($arguments[$prev]['param'])) {
             $type = idx($arguments[$prev], 'paramtype');
             switch ($type) {
                 case 'file':
                     echo "FILE\n";
                     break;
                 case 'complete':
                     echo implode(' ', $workflow->getShellCompletions($argv)) . "\n";
                     break;
                 default:
                     echo "ARGUMENT\n";
                     break;
             }
             return 0;
         } else {
             $output = array();
             foreach ($arguments as $argument => $spec) {
                 if ($argument == '*') {
                     continue;
                 }
                 if ($vcs && isset($spec['supports']) && !in_array($vcs, $spec['supports'])) {
                     continue;
                 }
                 $output[] = '--' . $argument;
             }
             $cur = idx($argv, $pos, '');
             $any_match = false;
             foreach ($output as $possible) {
                 if (!strncmp($possible, $cur, strlen($cur))) {
                     $any_match = true;
                 }
             }
             if (!$any_match && isset($arguments['*'])) {
                 // TODO: the '*' specifier should probably have more details about
                 // whether or not it is a list of files. Since it almost always is in
                 // practice, assume FILE for now.
                 echo "FILE\n";
             } else {
                 echo implode(' ', $output) . "\n";
             }
             return 0;
         }
     }
 }