Example #1
0
 public function execute()
 {
     global $wgUser, $wgCodeReviewMaxDiffSize;
     // Before doing anything at all, let's check permissions
     if (!$wgUser->isAllowed('codereview-use')) {
         $this->dieUsage('You don\'t have permission to view code diffs', 'permissiondenied');
     }
     $params = $this->extractRequestParams();
     $repo = CodeRepository::newFromName($params['repo']);
     if (!$repo) {
         $this->dieUsage("Invalid repo ``{$params['repo']}''", 'invalidrepo');
     }
     $lastStoredRev = $repo->getLastStoredRev();
     if ($params['rev'] > $lastStoredRev) {
         $this->dieUsage("There is no revision with ID {$params['rev']}", 'nosuchrev');
     }
     $diff = $repo->getDiff($params['rev']);
     if (!is_string($diff)) {
         // FIXME: Are we sure we don't want to throw an error here?
         $html = 'Failed to load diff. Error message: ' . CodeRepository::getDiffErrorMessage($diff);
     } elseif (strlen($diff) > $wgCodeReviewMaxDiffSize) {
         $html = 'Diff too large.';
     } else {
         $hilite = new CodeDiffHighlighter();
         $html = $hilite->render($diff);
     }
     $data = array('repo' => $params['repo'], 'id' => $params['rev'], 'diff' => $html);
     $this->getResult()->addValue('code', 'rev', $data);
 }
Example #2
0
 /**
  * Import a repository in the local database.
  * @param $repoName String Local name of repository
  * @param $start Int Revision to begin the import from (Default: null, means last stored revision);
  */
 private function importRepo($repoName, $start = null, $cacheSize = 0)
 {
     global $wgCodeReviewImportBatchSize;
     static $adaptorReported = false;
     $repo = CodeRepository::newFromName($repoName);
     if (!$repo) {
         $this->error("Invalid repo {$repoName}");
         return;
     }
     $svn = SubversionAdaptor::newFromRepo($repo->getPath());
     if (!$adaptorReported) {
         $this->output("Using " . get_class($svn) . " adaptor\n");
         $adaptorReported = true;
     }
     $this->output("IMPORT FROM REPO: {$repoName}\n");
     $lastStoredRev = $repo->getLastStoredRev();
     $this->output("Last stored revision: {$lastStoredRev}\n");
     $chunkSize = $wgCodeReviewImportBatchSize;
     $startTime = microtime(true);
     $revCount = 0;
     $start = $start !== null ? intval($start) : $lastStoredRev + 1;
     /*
      * FIXME: when importing only a part of a repository, the given path
      * might not have been created with revision 1. For example, the
      * mediawiki '/trunk/phase3' got created with r1284.
      */
     if ($start > $lastStoredRev + 1) {
         $this->error("Invalid starting point. r{$start} is beyond last stored revision: r" . ($lastStoredRev + 1));
         return;
     }
     $this->output("Syncing from r{$start} to HEAD...\n");
     if (!$svn->canConnect()) {
         $this->error("Unable to connect to repository.");
         return;
     }
     while (true) {
         $log = $svn->getLog('', $start, $start + $chunkSize - 1);
         if (empty($log)) {
             # Repo seems to give a blank when max rev is invalid, which
             # stops new revisions from being added. Try to avoid this
             # by trying less at a time from the last point.
             if ($chunkSize <= 1) {
                 break;
                 // done!
             }
             $chunkSize = max(1, floor($chunkSize / 4));
             continue;
         } else {
             $start += $chunkSize;
         }
         if (!is_array($log)) {
             var_dump($log);
             // @TODO: cleanup :)
             $this->error('Log entry is not an array! See content above.', true);
         }
         foreach ($log as $data) {
             $revCount++;
             $delta = microtime(true) - $startTime;
             $revSpeed = $revCount / $delta;
             $codeRev = CodeRevision::newFromSvn($repo, $data);
             $codeRev->save();
             $this->output(sprintf("%d %s %s (%0.1f revs/sec)\n", $codeRev->getId(), wfTimestamp(TS_DB, $codeRev->getTimestamp()), $codeRev->getAuthor(), $revSpeed));
         }
         wfWaitForSlaves();
     }
     if ($cacheSize !== 0) {
         $dbw = wfGetDB(DB_MASTER);
         $options = array('ORDER BY' => 'cr_id DESC');
         if ($cacheSize == "all") {
             $this->output("Pre-caching all uncached diffs...\n");
         } else {
             if ($cacheSize == 1) {
                 $this->output("Pre-caching the latest diff...\n");
             } else {
                 $this->output("Pre-caching the latest {$cacheSize} diffs...\n");
             }
             $options['LIMIT'] = $cacheSize;
         }
         // Get all rows for this repository that don't already have a diff filled in.
         // This is LIMITed according to the $cacheSize setting, above, so only the
         // rows that we plan to pre-cache are returned.
         // TODO: This was optimised in order to skip rows that already have a diff,
         //		 which is mostly what is required, but there may be situations where
         //		 you want to re-calculate diffs (e.g. if $wgCodeReviewMaxDiffPaths
         //		 changes).  If these situations arise we will either want to revert
         //		 this behaviour, or add a --force flag or something.
         $res = $dbw->select('code_rev', 'cr_id', array('cr_repo_id' => $repo->getId(), 'cr_diff IS NULL OR cr_diff = ""'), __METHOD__, $options);
         foreach ($res as $row) {
             $repo->getRevision($row->cr_id);
             $diff = $repo->getDiff($row->cr_id);
             // trigger caching
             $msg = "Diff r{$row->cr_id} ";
             if (is_integer($diff)) {
                 $msg .= "Skipped: " . CodeRepository::getDiffErrorMessage($diff);
             } else {
                 $msg .= "done";
             }
             $this->output($msg . "\n");
         }
     } else {
         $this->output("Pre-caching skipped.\n");
     }
     $this->output("Done!\n");
 }