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); } }
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); }
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; }
} 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 {
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; } } }