public static function loadOneSkinSpecification($name)
 {
     // Only allow skins which we know to exist to load. This prevents loading
     // skins like "../../secrets/evil/".
     $all = self::loadAllSkinSpecifications();
     if (empty($all[$name])) {
         throw new Exception(pht('Blog skin "%s" is not a valid skin!', $name));
     }
     $paths = PhabricatorEnv::getEnvConfig('phame.skins');
     $base = dirname(phutil_get_library_root('phabricator'));
     foreach ($paths as $path) {
         $path = Filesystem::resolvePath($path, $base);
         $skin_path = $path . DIRECTORY_SEPARATOR . $name;
         if (is_dir($skin_path)) {
             // Double check that the skin really lives in the skin directory.
             if (!Filesystem::isDescendant($skin_path, $path)) {
                 throw new Exception(pht('Blog skin "%s" is not located in path "%s"!', $name, $path));
             }
             $spec = self::loadSkinSpecification($skin_path);
             if ($spec) {
                 $spec->setName($name);
                 return $spec;
             }
         }
     }
     return null;
 }
示例#2
0
 public function run()
 {
     $paths = $this->getPaths();
     $affected_tests = array();
     foreach ($paths as $path) {
         $absolute_path = Filesystem::resolvePath($path);
         if (is_dir($absolute_path)) {
             $absolute_test_path = Filesystem::resolvePath('tests/' . $path);
             if (is_readable($absolute_test_path)) {
                 $affected_tests[] = $absolute_test_path;
             }
         }
         if (is_readable($absolute_path)) {
             $filename = basename($path);
             $directory = dirname($path);
             // assumes directory layout: tests/<package>/test_<module>.py
             $relative_test_path = 'tests/' . $directory . '/test_' . $filename;
             $absolute_test_path = Filesystem::resolvePath($relative_test_path);
             if (is_readable($absolute_test_path)) {
                 $affected_tests[] = $absolute_test_path;
             }
         }
     }
     return $this->runTests($affected_tests, './');
 }
 public function execute(PhutilArgumentParser $args)
 {
     $console = PhutilConsole::getConsole();
     $paths = $args->getArg('paths');
     if (!$paths) {
         $paths = array(getcwd());
     }
     $targets = array();
     foreach ($paths as $path) {
         $root = Filesystem::resolvePath($path);
         if (!Filesystem::pathExists($root) || !is_dir($root)) {
             throw new PhutilArgumentUsageException(pht('Path "%s" does not exist, or is not a directory.', $path));
         }
         $libraries = id(new FileFinder($path))->withPath('*/__phutil_library_init__.php')->find();
         if (!$libraries) {
             throw new PhutilArgumentUsageException(pht('Path "%s" contains no libphutil libraries.', $path));
         }
         foreach ($libraries as $library) {
             $targets[] = Filesystem::resolvePath(dirname($library)) . '/';
         }
     }
     $targets = array_unique($targets);
     foreach ($targets as $library) {
         echo tsprintf("**<bg:blue> %s </bg>** %s\n", pht('EXTRACT'), pht('Extracting "%s"...', Filesystem::readablePath($library)));
         $this->extractLibrary($library);
     }
     return 0;
 }
 protected function getPathArgumentForLinterFuture($path)
 {
     $full_path = Filesystem::resolvePath($path);
     $ret = array($full_path);
     // The |path| we get fed needs to be made relative to the project_root,
     // otherwise the |engine| won't recognise it.
     $relative_path = Filesystem::readablePath($full_path, $this->getProjectRoot());
     $changed = $this->getEngine()->getPathChangedLines($relative_path);
     if ($changed !== null) {
         // Convert the ordered set of changed lines to a list of ranges.
         $changed_lines = array_keys(array_filter($changed));
         $ranges = array(array($changed_lines[0], $changed_lines[0]));
         foreach (array_slice($changed_lines, 1) as $line) {
             $range = last($ranges);
             if ($range[1] + 1 === $line) {
                 ++$range[1];
                 $ranges[last_key($ranges)] = $range;
             } else {
                 $ranges[] = array($line, $line);
             }
         }
         foreach ($ranges as $range) {
             $ret[] = sprintf('--lines=%d:%d', $range[0], $range[1]);
         }
     }
     return csprintf('%Ls', $ret);
 }
示例#5
0
 protected function readBookConfiguration($book_path)
 {
     if ($book_path === null) {
         throw new PhutilArgumentUsageException('Specify a Diviner book configuration file with --book.');
     }
     $book_data = Filesystem::readFile($book_path);
     $book = json_decode($book_data, true);
     if (!is_array($book)) {
         throw new PhutilArgumentUsageException("Book configuration '{$book_path}' is not in JSON format.");
     }
     PhutilTypeSpec::checkMap($book, array('name' => 'string', 'title' => 'optional string', 'short' => 'optional string', 'preface' => 'optional string', 'root' => 'optional string', 'uri.source' => 'optional string', 'rules' => 'optional map<regex, string>', 'exclude' => 'optional regex|list<regex>', 'groups' => 'optional map<string, map<string, wild>>'));
     // If the book specifies a "root", resolve it; otherwise, use the directory
     // the book configuration file lives in.
     $full_path = dirname(Filesystem::resolvePath($book_path));
     if (empty($book['root'])) {
         $book['root'] = '.';
     }
     $book['root'] = Filesystem::resolvePath($book['root'], $full_path);
     if (!preg_match('/^[a-z][a-z-]*\\z/', $book['name'])) {
         $name = $book['name'];
         throw new PhutilArgumentUsageException("Book configuration '{$book_path}' has name '{$name}', but book names " . "must include only lowercase letters and hyphens.");
     }
     foreach (idx($book, 'groups', array()) as $group) {
         PhutilTypeSpec::checkmap($group, array('name' => 'string', 'include' => 'optional regex|list<regex>'));
     }
     $this->bookConfigPath = $book_path;
     $this->config = $book;
 }
示例#6
0
 public function run()
 {
     $revisions = $this->getConduit()->callMethodSynchronous('differential.query', array('authors' => array($this->getUserPHID()), 'status' => 'status-open'));
     if (!$revisions) {
         echo "You have no open Differential revisions.\n";
         return 0;
     }
     $repository_api = $this->getRepositoryAPI();
     $info = array();
     $status_len = 0;
     foreach ($revisions as $key => $revision) {
         $revision_path = Filesystem::resolvePath($revision['sourcePath']);
         $current_path = Filesystem::resolvePath($repository_api->getPath());
         if ($revision_path == $current_path) {
             $info[$key]['here'] = 1;
         } else {
             $info[$key]['here'] = 0;
         }
         $info[$key]['sort'] = sprintf('%d%04d%08d', $info[$key]['here'], $revision['status'], $revision['id']);
         $info[$key]['statusColorized'] = BranchInfo::renderColorizedRevisionStatus($revision['statusName']);
         $status_len = max($status_len, strlen($info[$key]['statusColorized']));
     }
     $info = isort($info, 'sort');
     foreach ($info as $key => $spec) {
         $revision = $revisions[$key];
         printf("%s %-" . ($status_len + 4) . "s D%d: %s\n", $spec['here'] ? phutil_console_format('**%s**', '*') : ' ', $spec['statusColorized'], $revision['id'], $revision['title']);
     }
     return 0;
 }
示例#7
0
 public function run()
 {
     if ($this->getRunAllTests()) {
         $root = $this->getWorkingCopy()->getProjectRoot();
         $all_tests = glob(Filesystem::resolvePath("{$root}/tests/**/test_*.py"));
         return $this->runTests($all_tests, $root);
     }
     $paths = $this->getPaths();
     $affected_tests = array();
     foreach ($paths as $path) {
         $absolute_path = Filesystem::resolvePath($path);
         if (is_dir($absolute_path)) {
             $absolute_test_path = Filesystem::resolvePath('tests/' . $path);
             if (is_readable($absolute_test_path)) {
                 $affected_tests[] = $absolute_test_path;
             }
         }
         if (is_readable($absolute_path)) {
             $filename = basename($path);
             $directory = dirname($path);
             // assumes directory layout: tests/<package>/test_<module>.py
             $relative_test_path = 'tests/' . $directory . '/test_' . $filename;
             $absolute_test_path = Filesystem::resolvePath($relative_test_path);
             if (is_readable($absolute_test_path)) {
                 $affected_tests[] = $absolute_test_path;
             }
         }
     }
     return $this->runTests($affected_tests, './');
 }
示例#8
0
 public function run()
 {
     static $color_map = array('Closed' => 'cyan', 'Needs Review' => 'magenta', 'Needs Revision' => 'red', 'Changes Planned' => 'red', 'Accepted' => 'green', 'No Revision' => 'blue', 'Abandoned' => 'default');
     $revisions = $this->getConduit()->callMethodSynchronous('differential.query', array('authors' => array($this->getUserPHID()), 'status' => 'status-open'));
     if (!$revisions) {
         echo pht('You have no open Differential revisions.') . "\n";
         return 0;
     }
     $repository_api = $this->getRepositoryAPI();
     $info = array();
     foreach ($revisions as $key => $revision) {
         $revision_path = Filesystem::resolvePath($revision['sourcePath']);
         $current_path = Filesystem::resolvePath($repository_api->getPath());
         if ($revision_path == $current_path) {
             $info[$key]['exists'] = 1;
         } else {
             $info[$key]['exists'] = 0;
         }
         $info[$key]['sort'] = sprintf('%d%04d%08d', $info[$key]['exists'], $revision['status'], $revision['id']);
         $info[$key]['statusName'] = $revision['statusName'];
         $info[$key]['color'] = idx($color_map, $revision['statusName'], 'default');
     }
     $table = id(new PhutilConsoleTable())->setShowHeader(false)->addColumn('exists', array('title' => ''))->addColumn('status', array('title' => pht('Status')))->addColumn('title', array('title' => pht('Title')));
     $info = isort($info, 'sort');
     foreach ($info as $key => $spec) {
         $revision = $revisions[$key];
         $table->addRow(array('exists' => $spec['exists'] ? phutil_console_format('**%s**', '*') : '', 'status' => phutil_console_format("<fg:{$spec['color']}>%s</fg>", $spec['statusName']), 'title' => phutil_console_format('**D%d:** %s', $revision['id'], $revision['title'])));
     }
     $table->draw();
     return 0;
 }
 public function run()
 {
     $argv = $this->getArgument('argv');
     if (count($argv) > 1) {
         throw new ArcanistUsageException("Provide only one path to 'arc liberate'. The path should be a " . "directory where you want to create or update a libphutil library.");
     } else {
         if (count($argv) == 0) {
             $path = getcwd();
         } else {
             $path = reset($argv);
         }
     }
     $is_remap = $this->getArgument('remap');
     $is_verify = $this->getArgument('verify');
     $path = Filesystem::resolvePath($path);
     if (Filesystem::pathExists($path) && is_dir($path)) {
         $init = id(new FileFinder($path))->withPath('*/__phutil_library_init__.php')->find();
     } else {
         $init = null;
     }
     if ($init) {
         if (count($init) > 1) {
             throw new ArcanistUsageException("Specified directory contains more than one libphutil library. Use " . "a more specific path.");
         }
         $path = Filesystem::resolvePath(dirname(reset($init)), $path);
     } else {
         $found = false;
         foreach (Filesystem::walkToRoot($path) as $dir) {
             if (Filesystem::pathExists($dir . '/__phutil_library_init__.php')) {
                 $path = $dir;
                 $found = true;
                 break;
             }
         }
         if (!$found) {
             echo "No library currently exists at that path...\n";
             $this->liberateCreateDirectory($path);
             $this->liberateCreateLibrary($path);
             return;
         }
     }
     $version = $this->getLibraryFormatVersion($path);
     switch ($version) {
         case 1:
             if ($this->getArgument('upgrade')) {
                 return $this->upgradeLibrary($path);
             }
             throw new ArcanistUsageException("This library is using libphutil v1, which is no longer supported. " . "Run 'arc liberate --upgrade' to upgrade to v2.");
         case 2:
             if ($this->getArgument('upgrade')) {
                 throw new ArcanistUsageException("Can't upgrade a v2 library!");
             }
             return $this->liberateVersion2($path);
         default:
             throw new ArcanistUsageException("Unknown library version '{$version}'!");
     }
 }
 public function saveToArchive($path)
 {
     $tmp = new TempFile();
     execx('tar -C %s -czvvf %s .', $this->getPath(), $tmp);
     $ok = rename($tmp, Filesystem::resolvePath($path));
     if (!$ok) {
         throw new FilesystemException($path, 'Failed to overwrite file.');
     }
     return $this;
 }
示例#11
0
 public function loadDictionary($path)
 {
     $root = $this->getProjectRoot();
     $path = Filesystem::resolvePath($path, $root);
     $dict = phutil_json_decode(Filesystem::readFile($path));
     PhutilTypeSpec::checkMap($dict, array('rules' => 'map<string, map<string, string>>'));
     $rules = $dict['rules'];
     $this->dictionaries[] = $path;
     $this->exactWordRules = array_merge($this->exactWordRules, idx($rules, 'exact', array()));
     $this->partialWordRules = array_merge($this->partialWordRules, idx($rules, 'partial', array()));
 }
示例#12
0
/**
 * @group xhpast
 */
function xhpast_get_build_instructions()
{
    $root = phutil_get_library_root('phutil');
    $make = $root . '/../scripts/build_xhpast.sh';
    $make = Filesystem::resolvePath($make);
    return <<<EOHELP
Your version of 'xhpast' is unbuilt or out of date. Run this script to build it:

  \$ {$make}

EOHELP;
}
示例#13
0
 /**
  * Create a new lock on a lockfile. The file need not exist yet.
  *
  * @param   string          The lockfile to use.
  * @return  PhutilFileLock  New lock object.
  *
  * @task construct
  */
 public static function newForPath($lockfile)
 {
     $lockfile = Filesystem::resolvePath($lockfile);
     $name = 'file:' . $lockfile;
     $lock = self::getLock($name);
     if (!$lock) {
         $lock = new PhutilFileLock($name);
         $lock->lockfile = $lockfile;
         self::registerLock($lock);
     }
     return $lock;
 }
示例#14
0
function phutil_get_library_name_for_root($path)
{
    $path = rtrim(Filesystem::resolvePath($path), '/');
    $bootloader = PhutilBootloader::getInstance();
    $libraries = $bootloader->getAllLibraries();
    foreach ($libraries as $library) {
        $root = $bootloader->getLibraryRoot($library);
        if (rtrim(Filesystem::resolvePath($root), '/') == $path) {
            return $library;
        }
    }
    return null;
}
示例#15
0
 public function run()
 {
     $this->projectRoot = $this->getWorkingCopy()->getProjectRoot();
     $this->affectedTests = array();
     foreach ($this->getPaths() as $path) {
         $path = Filesystem::resolvePath($path);
         // TODO: add support for directories
         // Users can call phpunit on the directory themselves
         if (is_dir($path)) {
             continue;
         }
         // Not sure if it would make sense to go further if
         // it is not a .php file
         if (substr($path, -4) != '.php') {
             continue;
         }
         if (substr($path, -8) == 'Test.php') {
             // Looks like a valid test file name.
             $this->affectedTests[$path] = $path;
             continue;
         }
         if ($test = $this->findTestFile($path)) {
             $this->affectedTests[$path] = $test;
         }
     }
     if (empty($this->affectedTests)) {
         throw new ArcanistNoEffectException('No tests to run.');
     }
     $this->prepareConfigFile();
     $futures = array();
     $tmpfiles = array();
     foreach ($this->affectedTests as $class_path => $test_path) {
         $json_tmp = new TempFile();
         $clover_tmp = null;
         $clover = null;
         if ($this->getEnableCoverage() !== false) {
             $clover_tmp = new TempFile();
             $clover = csprintf('--coverage-clover %s', $clover_tmp);
         }
         $config = $this->configFile ? csprintf('-c %s', $this->configFile) : null;
         $futures[$test_path] = new ExecFuture('phpunit %C --log-json %s %C %s', $config, $json_tmp, $clover, $test_path);
         $tmpfiles[$test_path] = array('json' => $json_tmp, 'clover' => $clover_tmp);
     }
     $results = array();
     foreach (Futures($futures)->limit(4) as $test => $future) {
         list($err, $stdout, $stderr) = $future->resolve();
         $results[] = $this->parseTestResults($test_path, $tmpfiles[$test]['json'], $tmpfiles[$test]['clover']);
     }
     return array_mergev($results);
 }
示例#16
0
 public function getJSHintOptions()
 {
     $working_copy = $this->getEngine()->getWorkingCopy();
     $options = '--reporter ' . dirname(realpath(__FILE__)) . '/reporter.js';
     $config = $working_copy->getConfig('lint.jshint.config');
     if ($config !== null) {
         $config = Filesystem::resolvePath($config, $working_copy->getProjectRoot());
         if (!Filesystem::pathExists($config)) {
             throw new ArcanistUsageException("Unable to find custom options file defined by 'lint.jshint.config'. " . "Make sure that the path is correct.");
         }
         $options .= ' --config ' . $config;
     }
     return $options;
 }
 private function hasEmoji($name)
 {
     $path = Filesystem::resolvePath('rsrc/image/emoji');
     if (Filesystem::pathExists($path)) {
         $files = Filesystem::listDirectory('rsrc/image/emoji', $include_hidden = false);
         foreach ($files as $file) {
             $info = pathinfo($file);
             $file_name = basename($file, '.' . $info['extension']);
             if ($file_name == $name) {
                 return true;
             }
         }
     }
     return false;
 }
 protected function parseLinterOutput($path, $err, $stdout, $stderr)
 {
     $ok = $err == 0;
     if (!$ok) {
         return false;
     }
     $root = $this->getProjectRoot();
     $path = Filesystem::resolvePath($path, $root);
     $orig = file_get_contents($path);
     if ($orig == $stdout) {
         return array();
     }
     $message = id(new ArcanistLintMessage())->setPath($path)->setLine(1)->setChar(1)->setGranularity(ArcanistLinter::GRANULARITY_FILE)->setCode('CFMT')->setSeverity(ArcanistLintSeverity::SEVERITY_AUTOFIX)->setName('Code style violation')->setDescription("'{$path}' has code style errors.")->setOriginalText($orig)->setReplacementText($stdout);
     return array($message);
 }
示例#19
0
 /**
  * Main entry point for the test engine. Determines what files changed
  * and test based on the files that have changed.
  * @return array Array of test results.
  * @throws ArcanistNoEffectException
  * @throws CommandException
  */
 public function run()
 {
     /*
      * Determine whether it shall run all the test or more precisely the
      * modified file
      *
      */
     if (!$this->getRunAllTests()) {
         $pattern_tests = $this->getAllTestsPattern();
     } else {
         $pattern_tests = $this->getGranularTestsPattern();
     }
     /*
      * Throw an error if there is no test that can be run
      */
     if (!$pattern_tests) {
         throw new ArcanistNoEffectException(pht('No tests to run.'));
     }
     /*
      * Retrieve working copy and project root path
      */
     $workingCopy = $this->getWorkingCopy();
     $projectRoot = $workingCopy->getProjectRoot();
     /*
      * Create new temp-file paths to receive junit test result
      * and lcov coverage result only if coverage is activated.
      */
     $junit_tmp = new TempFile();
     $cover_tmp = null;
     if ($this->getEnableCoverage() !== false) {
         $cover_tmp = Filesystem::resolvePath('./coverage/cobertura-coverage.xml', $projectRoot);
     }
     $future = $this->buildTestFuture($pattern_tests, $junit_tmp);
     list($err, $stdout, $stderr) = $future->resolve();
     /*
      * Check that the future output desired files
      */
     if (!Filesystem::pathExists($junit_tmp)) {
         throw new CommandException(pht('Testing Command failed with error #%s!', $err), $future->getCommand(), $err, $stdout, $stderr);
     }
     if ($this->getEnableCoverage() !== false) {
         if (!Filesystem::pathExists($cover_tmp)) {
             throw new CommandException(pht('Coverage Command failed with error #%s!', $err), $future->getCommand(), $err, $stdout, $stderr);
         }
     }
     return $this->parseTestResults($junit_tmp, $cover_tmp);
 }
 public static function loadOneSkinSpecification($name)
 {
     $paths = PhabricatorEnv::getEnvConfig('phame.skins');
     $base = dirname(phutil_get_library_root('phabricator'));
     foreach ($paths as $path) {
         $path = Filesystem::resolvePath($path, $base);
         $skin_path = $path . DIRECTORY_SEPARATOR . $name;
         if (is_dir($skin_path)) {
             $spec = self::loadSkinSpecification($skin_path);
             if ($spec) {
                 $spec->setName($name);
                 return $spec;
             }
         }
     }
     return null;
 }
 protected function executeChecks()
 {
     $max_allowed_packet = self::loadRawConfigValue('max_allowed_packet');
     $recommended_minimum = 1024 * 1024;
     if ($max_allowed_packet < $recommended_minimum) {
         $message = pht("MySQL is configured with a very small 'max_allowed_packet' (%d), " . "which may cause some large writes to fail. Strongly consider raising " . "this to at least %d in your MySQL configuration.", $max_allowed_packet, $recommended_minimum);
         $this->newIssue('mysql.max_allowed_packet')->setName(pht('Small MySQL "max_allowed_packet"'))->setMessage($message)->addMySQLConfig('max_allowed_packet');
     }
     $modes = self::loadRawConfigValue('sql_mode');
     $modes = explode(',', $modes);
     if (!in_array('STRICT_ALL_TABLES', $modes)) {
         $summary = pht('MySQL is not in strict mode, but using strict mode is strongly ' . 'encouraged.');
         $message = pht("On your MySQL instance, the global %s is not set to %s. " . "It is strongly encouraged that you enable this mode when running " . "Phabricator.\n\n" . "By default MySQL will silently ignore some types of errors, which " . "can cause data loss and raise security concerns. Enabling strict " . "mode makes MySQL raise an explicit error instead, and prevents this " . "entire class of problems from doing any damage.\n\n" . "You can find more information about this mode (and how to configure " . "it) in the MySQL manual. Usually, it is sufficient to add this to " . "your %s file (in the %s section) and then restart %s:\n\n" . "%s\n" . "(Note that if you run other applications against the same database, " . "they may not work in strict mode. Be careful about enabling it in " . "these cases.)", phutil_tag('tt', array(), 'sql_mode'), phutil_tag('tt', array(), 'STRICT_ALL_TABLES'), phutil_tag('tt', array(), 'my.cnf'), phutil_tag('tt', array(), '[mysqld]'), phutil_tag('tt', array(), 'mysqld'), phutil_tag('pre', array(), 'sql_mode=STRICT_ALL_TABLES'));
         $this->newIssue('mysql.mode')->setName(pht('MySQL STRICT_ALL_TABLES Mode Not Set'))->setSummary($summary)->setMessage($message)->addMySQLConfig('sql_mode');
     }
     $stopword_file = self::loadRawConfigValue('ft_stopword_file');
     if (!PhabricatorDefaultSearchEngineSelector::shouldUseElasticSearch()) {
         if ($stopword_file === null) {
             $summary = pht('Your version of MySQL does not support configuration of a ' . 'stopword file. You will not be able to find search results for ' . 'common words.');
             $message = pht("Your MySQL instance does not support the %s option. You will not " . "be able to find search results for common words. You can gain " . "access to this option by upgrading MySQL to a more recent " . "version.\n\n" . "You can ignore this warning if you plan to configure ElasticSearch " . "later, or aren't concerned about searching for common words.", phutil_tag('tt', array(), 'ft_stopword_file'));
             $this->newIssue('mysql.ft_stopword_file')->setName(pht('MySQL ft_stopword_file Not Supported'))->setSummary($summary)->setMessage($message)->addMySQLConfig('ft_stopword_file');
         } else {
             if ($stopword_file == '(built-in)') {
                 $root = dirname(phutil_get_library_root('phabricator'));
                 $stopword_path = $root . '/resources/sql/stopwords.txt';
                 $stopword_path = Filesystem::resolvePath($stopword_path);
                 $namespace = PhabricatorEnv::getEnvConfig('storage.default-namespace');
                 $summary = pht('MySQL is using a default stopword file, which will prevent ' . 'searching for many common words.');
                 $message = pht("Your MySQL instance is using the builtin stopword file for " . "building search indexes. This can make Phabricator's search " . "feature less useful.\n\n" . "Stopwords are common words which are not indexed and thus can not " . "be searched for. The default stopword file has about 500 words, " . "including various words which you are likely to wish to search " . "for, such as 'various', 'likely', 'wish', and 'zero'.\n\n" . "To make search more useful, you can use an alternate stopword " . "file with fewer words. Alternatively, if you aren't concerned " . "about searching for common words, you can ignore this warning. " . "If you later plan to configure ElasticSearch, you can also ignore " . "this warning: this stopword file only affects MySQL fulltext " . "indexes.\n\n" . "To choose a different stopword file, add this to your %s file " . "(in the %s section) and then restart %s:\n\n" . "%s\n" . "(You can also use a different file if you prefer. The file " . "suggested above has about 50 of the most common English words.)\n\n" . "Finally, run this command to rebuild indexes using the new " . "rules:\n\n" . "%s", phutil_tag('tt', array(), 'my.cnf'), phutil_tag('tt', array(), '[mysqld]'), phutil_tag('tt', array(), 'mysqld'), phutil_tag('pre', array(), 'ft_stopword_file=' . $stopword_path), phutil_tag('pre', array(), "mysql> REPAIR TABLE {$namespace}_search.search_documentfield;"));
                 $this->newIssue('mysql.ft_stopword_file')->setName(pht('MySQL is Using Default Stopword File'))->setSummary($summary)->setMessage($message)->addMySQLConfig('ft_stopword_file');
             }
         }
     }
     $min_len = self::loadRawConfigValue('ft_min_word_len');
     if ($min_len >= 4) {
         if (!PhabricatorDefaultSearchEngineSelector::shouldUseElasticSearch()) {
             $namespace = PhabricatorEnv::getEnvConfig('storage.default-namespace');
             $summary = pht('MySQL is configured to only index words with at least %d ' . 'characters.', $min_len);
             $message = pht("Your MySQL instance is configured to use the default minimum word " . "length when building search indexes, which is 4. This means words " . "which are only 3 characters long will not be indexed and can not " . "be searched for.\n\n" . "For example, you will not be able to find search results for words " . "like 'SMS', 'web', or 'DOS'.\n\n" . "You can change this setting to 3 to allow these words to be " . "indexed. Alternatively, you can ignore this warning if you are " . "not concerned about searching for 3-letter words. If you later " . "plan to configure ElasticSearch, you can also ignore this warning: " . "only MySQL fulltext search is affected.\n\n" . "To reduce the minimum word length to 3, add this to your %s file " . "(in the %s section) and then restart %s:\n\n" . "%s\n" . "Finally, run this command to rebuild indexes using the new " . "rules:\n\n" . "%s", phutil_tag('tt', array(), 'my.cnf'), phutil_tag('tt', array(), '[mysqld]'), phutil_tag('tt', array(), 'mysqld'), phutil_tag('pre', array(), 'ft_min_word_len=3'), phutil_tag('pre', array(), "mysql> REPAIR TABLE {$namespace}_search.search_documentfield;"));
             $this->newIssue('mysql.ft_min_word_len')->setName(pht('MySQL is Using Default Minimum Word Length'))->setSummary($summary)->setMessage($message)->addMySQLConfig('ft_min_word_len');
         }
     }
 }
示例#22
0
 /**
  * Determines what executables and lint paths to use. Between platforms
  * this also changes whether the lint engine is run under .NET or Mono. It
  * also ensures that all of the required binaries are available for the lint
  * to run successfully.
  *
  * @return void
  */
 private function loadEnvironment()
 {
     if ($this->loaded) {
         return;
     }
     // Determine runtime engine (.NET or Mono).
     if (phutil_is_windows()) {
         $this->runtimeEngine = '';
     } else {
         if (Filesystem::binaryExists('mono')) {
             $this->runtimeEngine = 'mono ';
         } else {
             throw new Exception(pht('Unable to find Mono and you are not on Windows!'));
         }
     }
     // Determine cslint path.
     $cslint = $this->cslintHintPath;
     if ($cslint !== null && file_exists($cslint)) {
         $this->cslintEngine = Filesystem::resolvePath($cslint);
     } else {
         if (Filesystem::binaryExists('cslint.exe')) {
             $this->cslintEngine = 'cslint.exe';
         } else {
             throw new Exception(pht('Unable to locate %s.', 'cslint'));
         }
     }
     // Determine cslint version.
     $ver_future = new ExecFuture('%C -v', $this->runtimeEngine . $this->cslintEngine);
     list($err, $stdout, $stderr) = $ver_future->resolve();
     if ($err !== 0) {
         throw new Exception(pht('You are running an old version of %s. Please ' . 'upgrade to version %s.', 'cslint', self::SUPPORTED_VERSION));
     }
     $ver = (int) $stdout;
     if ($ver < self::SUPPORTED_VERSION) {
         throw new Exception(pht('You are running an old version of %s. Please ' . 'upgrade to version %s.', 'cslint', self::SUPPORTED_VERSION));
     } else {
         if ($ver > self::SUPPORTED_VERSION) {
             throw new Exception(pht('Arcanist does not support this version of %s (it is newer). ' . 'You can try upgrading Arcanist with `%s`.', 'cslint', 'arc upgrade'));
         }
     }
     $this->loaded = true;
 }
 public function setLinterConfigurationValue($key, $value)
 {
     switch ($key) {
         case 'config':
             $working_copy = $this->getEngine()->getWorkingCopy();
             $root = $working_copy->getProjectRoot();
             $path = $value;
             if (Filesystem::pathExists($path)) {
                 $this->configPath = $path;
                 return;
             }
             $path = Filesystem::resolvePath($path, $root);
             if (Filesystem::pathExists($path)) {
                 $this->configPath = $path;
                 return;
             }
             throw new ArcanistUsageException(pht('None of the configured Scalafmt configs can be located.'));
     }
     return parent::setLinterConfigurationValue($key, $value);
 }
示例#24
0
 /**
  * Determine if a path is one of the paths in the list. Note that an empty
  * file list is considered to contain every file.
  *
  * @param  string  Relative or absolute system file path.
  * @param  bool    If true, consider the path to be contained in the list if
  *                 the list contains a parent directory. If false, require
  *                 that the path be part of the list explicitly.
  * @return bool    If true, the file is in the list.
  * @task test
  */
 public function contains($path, $allow_parent_directory = true)
 {
     if ($this->isEmpty()) {
         return true;
     }
     $path = Filesystem::resolvePath($path);
     if (is_dir($path)) {
         $path .= DIRECTORY_SEPARATOR;
     }
     foreach ($this->files as $file) {
         if ($file == $path) {
             return true;
         }
         if ($allow_parent_directory) {
             $len = strlen($file);
             if (isset($this->dirs[$file]) && !strncmp($file, $path, $len)) {
                 return true;
             }
         }
     }
     return false;
 }
示例#25
0
 private function findTestForFile($file_path)
 {
     // Follow the hard rails convention: replace app/path/to/class.rb with
     // spec/path/to/class_spec.rb
     $relative_path = substr($file_path, strlen($this->projectRoot) + 1);
     $accpetable_directories = ['app/', 'lib/'];
     $found = false;
     foreach ($accpetable_directories as $dir) {
         if (0 === strpos($relative_path, $dir)) {
             $found = true;
         }
     }
     if (!$found) {
         return false;
     }
     $expected_loc = 'spec/' . substr($relative_path, 4, -3) . '_spec.rb';
     $expected_loc = Filesystem::resolvePath($expected_loc, $this->projectRoot);
     if (Filesystem::pathExists($expected_loc)) {
         return $expected_loc;
     }
     return false;
 }
 public function run()
 {
     $repository_api = $this->getRepositoryAPI();
     $project_root = $this->getWorkingCopy()->getProjectRoot();
     $in_paths = $this->getArgument('paths');
     $paths = array();
     foreach ($in_paths as $key => $path) {
         $full_path = Filesystem::resolvePath($path);
         $paths[$key] = Filesystem::readablePath($full_path, $project_root);
     }
     if (!$paths) {
         throw new ArcanistUsageException("Specify a path to browse");
     }
     $base_uri = $this->getBaseURI();
     $browser = $this->getBrowserCommand();
     foreach ($paths as $path) {
         $ret_code = phutil_passthru("%s %s", $browser, $base_uri . $path);
         if ($ret_code) {
             throw new ArcanistUsageException("It seems we failed to open the browser; Perhaps you should try to " . "set the 'browser' config option. The command we tried to use was: " . $browser);
         }
     }
     return 0;
 }
 private function getTestsForPaths()
 {
     $project_root = $this->getWorkingCopy()->getProjectRoot();
     $look_here = array();
     foreach ($this->getPaths() as $path) {
         $library_root = phutil_get_library_root_for_path($path);
         if (!$library_root) {
             continue;
         }
         $library_name = phutil_get_library_name_for_root($library_root);
         if (!$library_name) {
             throw new Exception("Attempting to run unit tests on a libphutil library which has not " . "been loaded, at:\n\n" . "    {$library_root}\n\n" . "This probably means one of two things:\n\n" . "    - You may need to add this library to .arcconfig.\n" . "    - You may be running tests on a copy of libphutil or arcanist\n" . "      using a different copy of libphutil or arcanist. This\n" . "      operation is not supported.");
         }
         $path = Filesystem::resolvePath($path, $project_root);
         if (!is_dir($path)) {
             $path = dirname($path);
         }
         if ($path == $library_root) {
             $look_here[$library_name . ':.'] = array('library' => $library_name, 'path' => '');
         } else {
             if (!Filesystem::isDescendant($path, $library_root)) {
                 // We have encountered some kind of symlink maze -- for instance, $path
                 // is some symlink living outside the library that links into some file
                 // inside the library. Just ignore these cases, since the affected file
                 // does not actually lie within the library.
                 continue;
             } else {
                 $library_path = Filesystem::readablePath($path, $library_root);
                 do {
                     $look_here[$library_name . ':' . $library_path] = array('library' => $library_name, 'path' => $library_path);
                     $library_path = dirname($library_path);
                 } while ($library_path != '.');
             }
         }
     }
     // Look for any class that extends ArcanistPhutilTestCase inside a
     // __tests__ directory in any parent directory of every affected file.
     //
     // The idea is that "infrastructure/__tests__/" tests defines general tests
     // for all of "infrastructure/", and those tests run for any change in
     // "infrastructure/". However, "infrastructure/concrete/rebar/__tests__/"
     // defines more specific tests that run only when rebar/ (or some
     // subdirectory) changes.
     $run_tests = array();
     foreach ($look_here as $path_info) {
         $library = $path_info['library'];
         $path = $path_info['path'];
         $symbols = id(new PhutilSymbolLoader())->setType('class')->setLibrary($library)->setPathPrefix(($path ? $path . '/' : '') . '__tests__/')->setAncestorClass('ArcanistPhutilTestCase')->setConcreteOnly(true)->selectAndLoadSymbols();
         foreach ($symbols as $symbol) {
             $run_tests[$symbol['name']] = true;
         }
     }
     $run_tests = array_keys($run_tests);
     return $run_tests;
 }
示例#28
0
 public function run()
 {
     $bootloader = PhutilBootloader::getInstance();
     $affected_modules = array();
     foreach ($this->getPaths() as $path) {
         $library_root = phutil_get_library_root_for_path($path);
         if (!$library_root) {
             continue;
         }
         $library_name = phutil_get_library_name_for_root($library_root);
         if (!$library_name) {
             throw new Exception("Attempting to run unit tests on a libphutil library which has not " . "been loaded, at:\n\n" . "    {$library_root}\n\n" . "This probably means one of two things:\n\n" . "    - You may need to add this library to .arcconfig.\n" . "    - You may be running tests on a copy of libphutil or arcanist\n" . "      using a different copy of libphutil or arcanist. This\n" . "      operation is not supported.");
         }
         $path = Filesystem::resolvePath($path);
         if (!is_dir($path)) {
             $path = dirname($path);
         }
         if ($path == $library_root) {
             continue;
         }
         $library_path = Filesystem::readablePath($path, $library_root);
         do {
             // Add the module and all parent modules as affected modules, which
             // means we'll look for __tests__ to run here and in any containing
             // module.
             $affected_modules[$library_name . ':' . $library_path] = array('name' => $library_name, 'root' => $library_root, 'path' => $library_path);
             $library_path = dirname($library_path);
         } while ($library_path != '.');
     }
     $tests = array();
     foreach ($affected_modules as $library_info) {
         $library_name = $library_info['name'];
         $library_root = $library_info['root'];
         $module = $library_info['path'];
         if (basename($module) == '__tests__') {
             // Okay, this is a __tests__ module.
         } else {
             $exists = $bootloader->moduleExists($library_name, $module . '/__tests__');
             if ($exists) {
                 // This is a module which has a __tests__ module in it.
                 $module .= '/__tests__';
             } else {
                 // Look for a parent named __tests__.
                 $rpos = strrpos($module, '/__tests__');
                 if ($rpos === false) {
                     // No tests to run since there is no child or parent module named
                     // __tests__.
                     continue;
                 }
                 // Select the parent named __tests__.
                 $module = substr($module, 0, $rpos + strlen('/__tests__'));
             }
         }
         $module_key = $library_name . ':' . $module;
         $tests[$module_key] = array('library' => $library_name, 'root' => $library_root, 'module' => $module);
     }
     if (!$tests) {
         throw new ArcanistNoEffectException("No tests to run.");
     }
     $run_tests = array();
     foreach ($tests as $test) {
         $symbols = id(new PhutilSymbolLoader())->setType('class')->setLibrary($test['library'])->setModule($test['module'])->setAncestorClass('ArcanistPhutilTestCase')->selectAndLoadSymbols();
         foreach ($symbols as $symbol) {
             $run_tests[$symbol['name']] = true;
         }
     }
     $run_tests = array_keys($run_tests);
     if (!$run_tests) {
         throw new ArcanistNoEffectException("No tests to run. You may need to rebuild the phutil library map.");
     }
     $enable_coverage = $this->getEnableCoverage();
     if ($enable_coverage !== false) {
         if (!function_exists('xdebug_start_code_coverage')) {
             if ($enable_coverage === true) {
                 throw new ArcanistUsageException("You specified --coverage but xdebug is not available, so " . "coverage can not be enabled for PhutilUnitTestEngine.");
             }
         } else {
             $enable_coverage = true;
         }
     }
     $results = array();
     foreach ($run_tests as $test_class) {
         PhutilSymbolLoader::loadClass($test_class);
         $test_case = newv($test_class, array());
         $test_case->setEnableCoverage($enable_coverage);
         $test_case->setProjectRoot($this->getWorkingCopy()->getProjectRoot());
         $test_case->setPaths($this->getPaths());
         $results[] = $test_case->run();
     }
     if ($results) {
         $results = call_user_func_array('array_merge', $results);
     }
     return $results;
 }
示例#29
0
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
$package_spec = array('javelin.pkg.js' => array('javelin-util', 'javelin-install', 'javelin-event', 'javelin-stratcom', 'javelin-behavior', 'javelin-request', 'javelin-vector', 'javelin-dom', 'javelin-json', 'javelin-uri'), 'typeahead.pkg.js' => array('javelin-typeahead', 'javelin-typeahead-normalizer', 'javelin-typeahead-source', 'javelin-typeahead-preloaded-source', 'javelin-typeahead-ondemand-source', 'javelin-tokenizer', 'javelin-behavior-aphront-basic-tokenizer'), 'core.pkg.js' => array('javelin-mask', 'javelin-workflow', 'javelin-behavior-workflow', 'javelin-behavior-aphront-form-disable-on-submit', 'phabricator-keyboard-shortcut-manager', 'phabricator-keyboard-shortcut', 'javelin-behavior-phabricator-keyboard-shortcuts', 'javelin-behavior-refresh-csrf', 'javelin-behavior-phabricator-watch-anchor', 'javelin-behavior-phabricator-autofocus', 'phabricator-paste-file-upload', 'phabricator-menu-item', 'phabricator-dropdown-menu', 'javelin-behavior-phabricator-oncopy', 'phabricator-tooltip', 'javelin-behavior-phabricator-tooltips', 'phabricator-prefab'), 'core.pkg.css' => array('phabricator-core-css', 'phabricator-core-buttons-css', 'phabricator-standard-page-view', 'aphront-dialog-view-css', 'aphront-form-view-css', 'aphront-panel-view-css', 'aphront-side-nav-view-css', 'aphront-table-view-css', 'aphront-crumbs-view-css', 'aphront-tokenizer-control-css', 'aphront-typeahead-control-css', 'aphront-list-filter-view-css', 'phabricator-directory-css', 'phabricator-jump-nav', 'phabricator-app-buttons-css', 'phabricator-remarkup-css', 'syntax-highlighting-css', 'aphront-pager-view-css', 'phabricator-transaction-view-css', 'aphront-tooltip-css', 'aphront-headsup-view-css', 'phabricator-flag-css', 'aphront-error-view-css'), 'differential.pkg.css' => array('differential-core-view-css', 'differential-changeset-view-css', 'differential-results-table-css', 'differential-revision-history-css', 'differential-table-of-contents-css', 'differential-revision-comment-css', 'differential-revision-add-comment-css', 'differential-revision-comment-list-css', 'phabricator-object-selector-css', 'aphront-headsup-action-list-view-css', 'phabricator-content-source-view-css', 'differential-local-commits-view-css', 'inline-comment-summary-css'), 'differential.pkg.js' => array('phabricator-drag-and-drop-file-upload', 'phabricator-shaped-request', 'javelin-behavior-differential-feedback-preview', 'javelin-behavior-differential-edit-inline-comments', 'javelin-behavior-differential-populate', 'javelin-behavior-differential-show-more', 'javelin-behavior-differential-diff-radios', 'javelin-behavior-differential-accept-with-errors', 'javelin-behavior-differential-comment-jump', 'javelin-behavior-differential-add-reviewers-and-ccs', 'javelin-behavior-differential-keyboard-navigation', 'javelin-behavior-aphront-drag-and-drop', 'javelin-behavior-aphront-drag-and-drop-textarea', 'javelin-behavior-phabricator-object-selector', 'javelin-behavior-repository-crossreference', 'differential-inline-comment-editor', 'javelin-behavior-differential-dropdown-menus', 'javelin-behavior-buoyant'), 'diffusion.pkg.css' => array('diffusion-commit-view-css', 'diffusion-icons-css'), 'diffusion.pkg.js' => array('javelin-behavior-diffusion-pull-lastmodified', 'javelin-behavior-diffusion-commit-graph', 'javelin-behavior-audit-preview'), 'maniphest.pkg.css' => array('maniphest-task-summary-css', 'maniphest-transaction-detail-css', 'aphront-attached-file-view-css', 'phabricator-project-tag-css'), 'maniphest.pkg.js' => array('javelin-behavior-maniphest-batch-selector', 'javelin-behavior-maniphest-transaction-controls', 'javelin-behavior-maniphest-transaction-preview', 'javelin-behavior-maniphest-transaction-expand', 'javelin-behavior-maniphest-subpriority-editor'));
require_once dirname(__FILE__) . '/__init_script__.php';
$args = new PhutilArgumentParser($argv);
$args->setTagline('map static resources');
$args->setSynopsis("**celerity_mapper.php** [--output __path__] [--with-custom] <webroot>");
$args->parse(array(array('name' => 'output', 'param' => 'path', 'default' => '../src/__celerity_resource_map__.php', 'help' => "Set the path for resource map. It is usually useful for " . "'celerity.resource-path' configuration."), array('name' => 'with-custom', 'help' => 'Include resources in <webroot>/rsrc/custom/.'), array('name' => 'webroot', 'wildcard' => true)));
$root = $args->getArg('webroot');
if (count($root) != 1 || !is_dir(reset($root))) {
    $args->printHelpAndExit();
}
$root = Filesystem::resolvePath(reset($root));
$celerity_path = Filesystem::resolvePath($args->getArg('output'), $root);
$with_custom = $args->getArg('with-custom');
$resource_hash = PhabricatorEnv::getEnvConfig('celerity.resource-hash');
$runtime_map = array();
echo "Finding raw static resources...\n";
$finder = id(new FileFinder($root))->withType('f')->withSuffix('png')->withSuffix('jpg')->withSuffix('gif')->withSuffix('swf')->withFollowSymlinks(true)->setGenerateChecksums(true);
if (!$with_custom) {
    $finder->excludePath('./rsrc/custom');
}
$raw_files = $finder->find();
echo "Processing " . count($raw_files) . " files";
foreach ($raw_files as $path => $hash) {
    echo ".";
    $path = '/' . Filesystem::readablePath($path, $root);
    $type = CelerityResourceTransformer::getResourceType($path);
    $hash = md5($hash . $path . $resource_hash);
示例#30
0
 /**
  * Build a new server. This server is bound to a working copy. The server
  * is inactive until you @{method:start} it.
  *
  * @param string Path to a Mercurial working copy.
  *
  * @task construct
  */
 public function __construct($working_copy)
 {
     $this->workingCopy = Filesystem::resolvePath($working_copy);
 }