public static function newAPIFromWorkingCopyIdentity(ArcanistWorkingCopyIdentity $working_copy)
 {
     $root = $working_copy->getProjectRoot();
     if (!$root) {
         throw new ArcanistUsageException("There is no readable '.arcconfig' file in the working directory or " . "any parent directory. Create an '.arcconfig' file to configure arc.");
     }
     // check if we're in an svn working copy
     list($err) = exec_manual('svn info');
     if (!$err) {
         $api = newv('ArcanistSubversionAPI', array($root));
         $api->workingCopyIdentity = $working_copy;
         return $api;
     }
     if (Filesystem::pathExists($root . '/.hg')) {
         $api = newv('ArcanistMercurialAPI', array($root));
         $api->workingCopyIdentity = $working_copy;
         return $api;
     }
     $git_root = self::discoverGitBaseDirectory($root);
     if ($git_root) {
         if (!Filesystem::pathsAreEquivalent($root, $git_root)) {
             throw new ArcanistUsageException("'.arcconfig' file is located at '{$root}', but working copy root " . "is '{$git_root}'. Move '.arcconfig' file to the working copy root.");
         }
         $api = newv('ArcanistGitAPI', array($root));
         $api->workingCopyIdentity = $working_copy;
         return $api;
     }
     throw new ArcanistUsageException("The current working directory is not part of a working copy for a " . "supported version control system (svn, git or mercurial).");
 }
 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('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 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();
     $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);
     }
 }
示例#10
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);
 }
 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;
 }
 /**
  * Locate all the information we need about a directory which we presume
  * to be a working copy. Particularly, we want to discover:
  *
  *   - Is the directory inside a working copy (hg, git, svn)?
  *   - If so, what is the root of the working copy?
  *   - Is there a `.arcconfig` file?
  *
  * This is complicated, mostly because Subversion has special rules. In
  * particular:
  *
  *   - Until 1.7, Subversion put a `.svn/` directory inside //every//
  *     directory in a working copy. After 1.7, it //only// puts one at the
  *     root.
  *   - We allow `.arcconfig` to appear anywhere in a Subversion working copy,
  *     and use the one closest to the directory.
  *   - Although we may use a `.arcconfig` from a subdirectory, we store
  *     metadata in the root's `.svn/`, because it's the only one guaranteed
  *     to exist.
  *
  * Users also do these kinds of things in the wild:
  *
  *   - Put working copies inside other working copies.
  *   - Put working copies inside `.git/` directories.
  *   - Create `.arcconfig` files at `/.arcconfig`, `/home/.arcconfig`, etc.
  *
  * This method attempts to be robust against all sorts of possible
  * misconfiguration.
  *
  * @param string    Path to load information for, usually the current working
  *                  directory (unless running unit tests).
  * @param map|null  Pass `null` to locate and load a `.arcconfig` file if one
  *                  exists. Pass a map to use it to set configuration.
  * @return ArcanistWorkingCopyIdentity Constructed working copy identity.
  */
 private static function newFromPathWithConfig($path, $config)
 {
     $project_root = null;
     $vcs_root = null;
     $vcs_type = null;
     // First, find the outermost directory which is a Git, Mercurial or
     // Subversion repository, if one exists. We go from the top because this
     // makes it easier to identify the root of old SVN working copies (which
     // have a ".svn/" directory inside every directory in the working copy) and
     // gives us the right result if you have a Git repository inside a
     // Subversion repository or something equally ridiculous.
     $paths = Filesystem::walkToRoot($path);
     $config_paths = array();
     $paths = array_reverse($paths);
     foreach ($paths as $path_key => $parent_path) {
         $try = array('git' => $parent_path . '/.git', 'hg' => $parent_path . '/.hg', 'svn' => $parent_path . '/.svn');
         foreach ($try as $vcs => $try_dir) {
             if (!Filesystem::pathExists($try_dir)) {
                 continue;
             }
             // NOTE: We're distinguishing between the `$project_root` and the
             // `$vcs_root` because they may not be the same in Subversion. Normally,
             // they are identical. However, in Subversion, the `$vcs_root` is the
             // base directory of the working copy (the directory which has the
             // `.svn/` directory, after SVN 1.7), while the `$project_root` might
             // be any subdirectory of the `$vcs_root`: it's the the directory
             // closest to the current directory which contains a `.arcconfig`.
             $project_root = $parent_path;
             $vcs_root = $parent_path;
             $vcs_type = $vcs;
             if ($vcs == 'svn') {
                 // For Subversion, we'll look for a ".arcconfig" file here or in
                 // any subdirectory, starting at the deepest subdirectory.
                 $config_paths = array_slice($paths, $path_key);
                 $config_paths = array_reverse($config_paths);
             } else {
                 // For Git and Mercurial, we'll only look for ".arcconfig" right here.
                 $config_paths = array($parent_path);
             }
             break;
         }
     }
     $console = PhutilConsole::getConsole();
     $looked_in = array();
     foreach ($config_paths as $config_path) {
         $config_file = $config_path . '/.arcconfig';
         $looked_in[] = $config_file;
         if (Filesystem::pathExists($config_file)) {
             // We always need to examine the filesystem to look for `.arcconfig`
             // so we can set the project root correctly. We might or might not
             // actually read the file: if the caller passed in configuration data,
             // we'll ignore the actual file contents.
             $project_root = $config_path;
             if ($config === null) {
                 $console->writeLog("%s\n", pht('Working Copy: Reading .arcconfig from "%s".', $config_file));
                 $config_data = Filesystem::readFile($config_file);
                 $config = self::parseRawConfigFile($config_data, $config_file);
             }
             break;
         }
     }
     if ($config === null) {
         if ($looked_in) {
             $console->writeLog("%s\n", pht('Working Copy: Unable to find .arcconfig in any of these ' . 'locations: %s.', implode(', ', $looked_in)));
         } else {
             $console->writeLog("%s\n", pht('Working Copy: No candidate locations for .arcconfig from ' . 'this working directory.'));
         }
         $config = array();
     }
     if ($project_root === null) {
         // We aren't in a working directory at all. This is fine if we're
         // running a command like "arc help". If we're running something that
         // requires a working directory, an exception will be raised a little
         // later on.
         $console->writeLog("%s\n", pht('Working Copy: Path "%s" is not in any working copy.', $path));
         return new ArcanistWorkingCopyIdentity($path, $config);
     }
     $console->writeLog("%s\n", pht('Working Copy: Path "%s" is part of `%s` working copy "%s".', $path, $vcs_type, $vcs_root));
     $console->writeLog("%s\n", pht('Working Copy: Project root is at "%s".', $project_root));
     $identity = new ArcanistWorkingCopyIdentity($project_root, $config);
     $identity->localMetaDir = $vcs_root . '/.' . $vcs_type;
     $identity->localConfig = $identity->readLocalArcConfig();
     $identity->vcsType = $vcs_type;
     $identity->vcsRoot = $vcs_root;
     return $identity;
 }
示例#15
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);
 }
示例#16
0
/**
 * NOTE: SPOOKY BLACK MAGIC
 *
 * When arc is run in a copy of arcanist other than itself, or a copy of
 * libphutil other than the one we loaded, reenter the script and force it
 * to use the current working directory instead of the default.
 *
 * In the case of execution inside arcanist/, we force execution of the local
 * arc binary.
 *
 * In the case of execution inside libphutil/, we force the local copy to load
 * instead of the one selected by default rules.
 *
 * @param PhutilConsole                 Console.
 * @param ArcanistWorkingCopyIdentity   The current working copy.
 * @param array                         Original arc arguments.
 * @return void
 */
function reenter_if_this_is_arcanist_or_libphutil(PhutilConsole $console, ArcanistWorkingCopyIdentity $working_copy, array $original_argv)
{
    $project_id = $working_copy->getProjectID();
    if ($project_id != 'arcanist' && $project_id != 'libphutil') {
        // We're not in a copy of arcanist or libphutil.
        return;
    }
    $library_names = array('arcanist' => 'arcanist', 'libphutil' => 'phutil');
    $library_root = phutil_get_library_root($library_names[$project_id]);
    $project_root = $working_copy->getProjectRoot();
    if (Filesystem::isDescendant($library_root, $project_root)) {
        // We're in a copy of arcanist or libphutil, but already loaded the correct
        // copy. Continue execution normally.
        return;
    }
    if ($project_id == 'libphutil') {
        $console->writeLog("This is libphutil! Forcing this copy to load...\n");
        $original_argv[0] = dirname(phutil_get_library_root('arcanist')) . '/bin/arc';
        $libphutil_path = $project_root;
    } else {
        $console->writeLog("This is arcanist! Forcing this copy to run...\n");
        $original_argv[0] = $project_root . '/bin/arc';
        $libphutil_path = dirname(phutil_get_library_root('phutil'));
    }
    if (phutil_is_windows()) {
        $err = phutil_passthru('set ARC_PHUTIL_PATH=%s & %Ls', $libphutil_path, $original_argv);
    } else {
        $err = phutil_passthru('ARC_PHUTIL_PATH=%s %Ls', $libphutil_path, $original_argv);
    }
    exit($err);
}
 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()
 {
     $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;
         }
     }
 }
 public function testCpplintLint()
 {
     $linter = new ArcanistCpplintLinter();
     $working_copy = ArcanistWorkingCopyIdentity::newFromPath(__FILE__);
     return $this->executeTestsInDirectory(dirname(__FILE__) . '/cpp/', $linter, $working_copy);
 }
示例#20
0
function arcanist_load_libraries($load, $must_load, $lib_source, ArcanistWorkingCopyIdentity $working_copy, $config_trace_mode)
{
    if (!$load) {
        return;
    }
    if (!is_array($load)) {
        $error = "Libraries specified by {$lib_source} are invalid; expected " . "a list. Check your configuration.";
        $console = PhutilConsole::getConsole();
        $console->writeErr("WARNING: %s\n", $error);
        return;
    }
    foreach ($load as $location) {
        // Try to resolve the library location. We look in several places, in
        // order:
        //
        //  1. Inside the working copy. This is for phutil libraries within the
        //     project. For instance "library/src" will resolve to
        //     "./library/src" if it exists.
        //  2. In the same directory as the working copy. This allows you to
        //     check out a library alongside a working copy and reference it.
        //     If we haven't resolved yet, "library/src" will try to resolve to
        //     "../library/src" if it exists.
        //  3. Using normal libphutil resolution rules. Generally, this means
        //     that it checks for libraries next to libphutil, then libraries
        //     in the PHP include_path.
        //
        // Note that absolute paths will just resolve absolutely through rule (1).
        $resolved = false;
        // Check inside the working copy. This also checks absolute paths, since
        // they'll resolve absolute and just ignore the project root.
        $resolved_location = Filesystem::resolvePath($location, $working_copy->getProjectRoot());
        if (Filesystem::pathExists($resolved_location)) {
            $location = $resolved_location;
            $resolved = true;
        }
        // If we didn't find anything, check alongside the working copy.
        if (!$resolved) {
            $resolved_location = Filesystem::resolvePath($location, dirname($working_copy->getProjectRoot()));
            if (Filesystem::pathExists($resolved_location)) {
                $location = $resolved_location;
                $resolved = true;
            }
        }
        if ($config_trace_mode) {
            echo "Loading phutil library from '{$location}'...\n";
        }
        $error = null;
        try {
            phutil_load_library($location);
        } catch (PhutilBootloaderException $ex) {
            $error = "Failed to load phutil library at location '{$location}'. " . "This library is specified by {$lib_source}. Check that the " . "setting is correct and the library is located in the right " . "place.";
            if ($must_load) {
                throw new ArcanistUsageException($error);
            } else {
                file_put_contents('php://stderr', phutil_console_wrap('WARNING: ' . $error . "\n\n"));
            }
        } catch (PhutilLibraryConflictException $ex) {
            if ($ex->getLibrary() != 'arcanist') {
                throw $ex;
            }
            $arc_dir = dirname(dirname(__FILE__));
            $error = "You are trying to run one copy of Arcanist on another copy of " . "Arcanist. This operation is not supported. To execute Arcanist " . "operations against this working copy, run './bin/arc' (from the " . "current working copy) not some other copy of 'arc' (you ran one " . "from '{$arc_dir}').";
            throw new ArcanistUsageException($error);
        }
    }
}
 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;
 }
 private function liberateBuildLintEngine($path, array $changed)
 {
     $lint_map = array();
     foreach ($changed as $module) {
         $module_path = $path . '/' . $module;
         $files = Filesystem::listDirectory($module_path);
         $lint_map[$module] = $files;
     }
     $working_copy = ArcanistWorkingCopyIdentity::newFromRootAndConfigFile($path, json_encode(array('project_id' => '__arcliberate__')), 'arc liberate');
     $engine = new ArcanistLiberateLintEngine();
     $engine->setWorkingCopy($working_copy);
     $lint_paths = array();
     foreach ($lint_map as $module => $files) {
         foreach ($files as $file) {
             $lint_paths[] = $module . '/' . $file;
         }
     }
     if (!$lint_paths) {
         return null;
     }
     $engine->setPaths($lint_paths);
     $engine->setMinimumSeverity(ArcanistLintSeverity::SEVERITY_ERROR);
     return $engine;
 }
 public function run()
 {
     $svnargs = $this->getArgument('svnargs');
     $repository = $svnargs[0];
     $transaction = $svnargs[1];
     list($commit_message) = execx('svnlook log --transaction %s %s', $transaction, $repository);
     if (strpos($commit_message, '@bypass-lint') !== false) {
         return 0;
     }
     // TODO: Do stuff with commit message.
     list($changed) = execx('svnlook changed --transaction %s %s', $transaction, $repository);
     $paths = array();
     $changed = explode("\n", trim($changed));
     foreach ($changed as $line) {
         $matches = null;
         preg_match('/^..\\s*(.*)$/', $line, $matches);
         $paths[$matches[1]] = strlen($matches[1]);
     }
     $resolved = array();
     $failed = array();
     $missing = array();
     $found = array();
     asort($paths);
     foreach ($paths as $path => $length) {
         foreach ($resolved as $rpath => $root) {
             if (!strncmp($path, $rpath, strlen($rpath))) {
                 $resolved[$path] = $root;
                 continue 2;
             }
         }
         $config = $path;
         if (basename($config) == '.arcconfig') {
             $resolved[$config] = $config;
             continue;
         }
         $config = rtrim($config, '/');
         $last_config = $config;
         do {
             if (!empty($missing[$config])) {
                 break;
             } else {
                 if (!empty($found[$config])) {
                     $resolved[$path] = $found[$config];
                     break;
                 }
             }
             list($err) = exec_manual('svnlook cat --transaction %s %s %s', $transaction, $repository, $config ? $config . '/.arcconfig' : '.arcconfig');
             if ($err) {
                 $missing[$path] = true;
             } else {
                 $resolved[$path] = $config ? $config . '/.arcconfig' : '.arcconfig';
                 $found[$config] = $resolved[$path];
                 break;
             }
             $config = dirname($config);
             if ($config == '.') {
                 $config = '';
             }
             if ($config == $last_config) {
                 break;
             }
             $last_config = $config;
         } while (true);
         if (empty($resolved[$path])) {
             $failed[] = $path;
         }
     }
     if ($failed && $resolved) {
         $failed_paths = '        ' . implode("\n        ", $failed);
         $resolved_paths = '        ' . implode("\n        ", array_keys($resolved));
         throw new ArcanistUsageException("This commit includes a mixture of files in Arcanist projects and " . "outside of Arcanist projects. A commit which affects an Arcanist " . "project must affect only that project.\n\n" . "Files in projects:\n\n" . $resolved_paths . "\n\n" . "Files not in projects:\n\n" . $failed_paths);
     }
     if (!$resolved) {
         // None of the affected paths are beneath a .arcconfig file.
         return 0;
     }
     $groups = array();
     foreach ($resolved as $path => $project) {
         $groups[$project][] = $path;
     }
     if (count($groups) > 1) {
         $message = array();
         foreach ($groups as $project => $group) {
             $message[] = "Files underneath '{$project}':\n\n";
             $message[] = "        " . implode("\n        ", $group) . "\n\n";
         }
         $message = implode('', $message);
         throw new ArcanistUsageException("This commit includes a mixture of files from different Arcanist " . "projects. A commit which affects an Arcanist project must affect " . "only that project.\n\n" . $message);
     }
     $config_file = key($groups);
     $project_root = dirname($config_file);
     $paths = reset($groups);
     list($config) = execx('svnlook cat --transaction %s %s %s', $transaction, $repository, $config_file);
     $working_copy = ArcanistWorkingCopyIdentity::newFromRootAndConfigFile($project_root, $config, $config_file . " (svnlook: {$transaction} {$repository})");
     $repository_api = new ArcanistSubversionHookAPI($project_root, $transaction, $repository);
     $lint_engine = $working_copy->getConfig('lint_engine');
     if (!$lint_engine) {
         return 0;
     }
     $engine = newv($lint_engine, array());
     $engine->setWorkingCopy($working_copy);
     $engine->setMinimumSeverity(ArcanistLintSeverity::SEVERITY_ERROR);
     $engine->setPaths($paths);
     $engine->setCommitHookMode(true);
     $engine->setHookAPI($repository_api);
     try {
         $results = $engine->run();
     } catch (ArcanistNoEffectException $no_effect) {
         // Nothing to do, bail out.
         return 0;
     }
     $failures = array();
     foreach ($results as $result) {
         if (!$result->getMessages()) {
             continue;
         }
         $failures[] = $result;
     }
     if ($failures) {
         $at = "@";
         $msg = phutil_console_format("\n**LINT ERRORS**\n\n" . "This changeset has lint errors. You must fix all lint errors before " . "you can commit.\n\n" . "You can add '{$at}bypass-lint' to your commit message to disable " . "lint checks for this commit, or '{$at}nolint' to the file with " . "errors to disable lint for that file.\n\n");
         echo phutil_console_wrap($msg);
         $renderer = new ArcanistLintConsoleRenderer();
         foreach ($failures as $result) {
             echo $renderer->renderLintResult($result);
         }
         return 1;
     }
     return 0;
 }
示例#24
0
 private function lintFile($file, ArcanistLinter $linter)
 {
     $linter = clone $linter;
     $contents = Filesystem::readFile($file);
     $contents = preg_split('/^~{4,}\\n/m', $contents);
     if (count($contents) < 2) {
         throw new Exception(pht("Expected '%s' separating test case and results.", '~~~~~~~~~~'));
     }
     list($data, $expect, $xform, $config) = array_merge($contents, array(null, null));
     $basename = basename($file);
     if ($config) {
         $config = phutil_json_decode($config);
     } else {
         $config = array();
     }
     PhutilTypeSpec::checkMap($config, array('config' => 'optional map<string, wild>', 'path' => 'optional string', 'mode' => 'optional string', 'stopped' => 'optional bool'));
     $exception = null;
     $after_lint = null;
     $messages = null;
     $exception_message = false;
     $caught_exception = false;
     try {
         $tmp = new TempFile($basename);
         Filesystem::writeFile($tmp, $data);
         $full_path = (string) $tmp;
         $mode = idx($config, 'mode');
         if ($mode) {
             Filesystem::changePermissions($tmp, octdec($mode));
         }
         $dir = dirname($full_path);
         $path = basename($full_path);
         $working_copy = ArcanistWorkingCopyIdentity::newFromRootAndConfigFile($dir, null, pht('Unit Test'));
         $configuration_manager = new ArcanistConfigurationManager();
         $configuration_manager->setWorkingCopyIdentity($working_copy);
         $engine = new ArcanistUnitTestableLintEngine();
         $engine->setWorkingCopy($working_copy);
         $engine->setConfigurationManager($configuration_manager);
         $path_name = idx($config, 'path', $path);
         $engine->setPaths(array($path_name));
         $linter->addPath($path_name);
         $linter->addData($path_name, $data);
         foreach (idx($config, 'config', array()) as $key => $value) {
             $linter->setLinterConfigurationValue($key, $value);
         }
         $engine->addLinter($linter);
         $engine->addFileData($path_name, $data);
         $results = $engine->run();
         $this->assertEqual(1, count($results), pht('Expect one result returned by linter.'));
         $assert_stopped = idx($config, 'stopped');
         if ($assert_stopped !== null) {
             $this->assertEqual($assert_stopped, $linter->didStopAllLinters(), $assert_stopped ? pht('Expect linter to be stopped.') : pht('Expect linter to not be stopped.'));
         }
         $result = reset($results);
         $patcher = ArcanistLintPatcher::newFromArcanistLintResult($result);
         $after_lint = $patcher->getModifiedFileContent();
     } catch (PhutilTestTerminatedException $ex) {
         throw $ex;
     } catch (Exception $exception) {
         $caught_exception = true;
         if ($exception instanceof PhutilAggregateException) {
             $caught_exception = false;
             foreach ($exception->getExceptions() as $ex) {
                 if ($ex instanceof ArcanistUsageException || $ex instanceof ArcanistMissingLinterException) {
                     $this->assertSkipped($ex->getMessage());
                 } else {
                     $caught_exception = true;
                 }
             }
         } else {
             if ($exception instanceof ArcanistUsageException || $exception instanceof ArcanistMissingLinterException) {
                 $this->assertSkipped($exception->getMessage());
             }
         }
         $exception_message = $exception->getMessage() . "\n\n" . $exception->getTraceAsString();
     }
     $this->assertEqual(false, $caught_exception, $exception_message);
     $this->compareLint($basename, $expect, $result);
     $this->compareTransform($xform, $after_lint);
 }
 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;
 }
示例#26
0
            $load[] = $matches[1];
        } else {
            if (preg_match('/^--conduit-uri=(.*)$/', $arg, $matches)) {
                unset($args[$key]);
                $force_conduit = $matches[1];
            }
        }
    }
}
$args = array_values($args);
$working_directory = getcwd();
try {
    if (!$args) {
        throw new ArcanistUsageException("No command provided. Try 'arc help'.");
    }
    $working_copy = ArcanistWorkingCopyIdentity::newFromPath($working_directory);
    if ($load) {
        $libs = $load;
    } else {
        $libs = $working_copy->getConfig('phutil_libraries');
    }
    if ($libs) {
        foreach ($libs as $name => $location) {
            // Try to resolve the library location. We look in several places, in
            // order:
            //
            //  1. Inside the working copy. This is for phutil libraries within the
            //     project. For instance "library/src" will resolve to
            //     "./library/src" if it exists.
            //  2. In the same directory as the working copy. This allows you to
            //     check out a library alongside a working copy and reference it.