public function execute() { global $wgUser; // Before doing anything at all, let's check permissions if (!$wgUser->isAllowed('codereview-use')) { $this->dieUsage('You don\'t have permission to view code paths', 'permissiondenied'); } $params = $this->extractRequestParams(); $repo = CodeRepository::newFromName($params['repo']); if (!$repo instanceof CodeRepository) { $this->dieUsage("Invalid repo ``{$params['repo']}''", 'invalidrepo'); } $this->addTables('code_paths'); $this->addFields('DISTINCT cp_path'); $this->addWhere(array('cp_repo_id' => $repo->getId())); $db = $this->getDB(); $this->addWhere('cp_path ' . $db->buildLike($params['path'], $db->anyString())); $this->addOption('USE INDEX', 'repo_path'); $this->addOption('LIMIT', 10); $res = $this->select(__METHOD__); $result = $this->getResult(); $data = array(); foreach ($res as $row) { $item = array(); ApiResult::setContent($item, $row->cp_path); $data[] = $item; } $result->setIndexedTagName($data, 'paths'); $result->addValue('query', $this->getModuleName(), $data); }
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); }
public function execute() { $repoName = $this->getArg(0); if ($repoName == "all") { $this->error("Cannot use the 'all' repo", true); } $repo = CodeRepository::newFromName($repoName); if (!$repo) { $this->error("Repo '{$repoName}' is not a valid Repository", true); } $revisions = $this->getArg(1); if (strpos($revisions, ':') !== false) { $revisionVals = explode(':', $revisions, 2); } else { $this->error("Invalid revision range", true); } $start = intval($revisionVals[0]); $end = intval($revisionVals[1]); $revisions = range($start, $end); $dbr = wfGetDB(DB_SLAVE); $res = $dbr->select('code_paths', '*', array('cp_rev_id' => $revisions, 'cp_repo_id' => $repo->getId()), __METHOD__); $dbw = wfGetDB(DB_MASTER); $dbw->begin(); foreach ($res as $row) { $fragments = CodeRevision::getPathFragments(array(array('path' => $row->cp_path, 'action' => $row->cp_action))); CodeRevision::insertPaths($dbw, $fragments, $repo->getId(), $row->cp_rev_id); $this->output("r{$row->cp_rev_id}, path: " . $row->cp_path . " Fragments: " . count($fragments) . "\n"); } $dbw->commit(); $this->output("Done!\n"); }
function __construct($repo) { $this->mRepo = $repo instanceof CodeRepository ? $repo : CodeRepository::newFromName($repo); global $wgUser; $this->skin = $wgUser->getSkin(); $this->codeCommentLinkerHtml = new CodeCommentLinkerHtml($this->mRepo); $this->codeCommentLinkerWiki = new CodeCommentLinkerWiki($this->mRepo); }
function __construct($path, $request) { parent::__construct($path, $request); $parts = explode('/', $path, 2); $this->mRepoName = $parts[0]; $this->mBasePath = '/' . @$parts[1]; $this->mRepository = CodeRepository::newFromName($this->mRepoName); }
public function execute() { global $wgUser; $this->getMain()->setCacheMode('anon-public-user-private'); // Before doing anything at all, let's check permissions if (!$wgUser->isAllowed('codereview-use')) { $this->dieUsage('You don\'t have permission to view code revisions', 'permissiondenied'); } $params = $this->extractRequestParams(); $this->props = array_flip($params['prop']); $repo = CodeRepository::newFromName($params['repo']); if (!$repo) { $this->dieUsage("Invalid repo ``{$params['repo']}''", 'invalidrepo'); } $data = array(); $listview = new CodeRevisionListView($repo); if (isset($params['path']) && $params['path'] !== '') { $listview->mPath = CodeRevisionListView::pathsToArray($params['path']); } $pager = $listview->getPager(); $revsSet = count($params['revs']); if ($revsSet) { $db = wfGetDB(DB_SLAVE); $query = $pager->getQueryInfo(); $query['conds']['cr_id'] = $params['revs']; $revisions = $db->select($query['tables'], $query['fields'], $query['conds'], __METHOD__, $query['options'], $query['join_conds']); } else { if (!is_null($params['start'])) { $pager->setOffset($params['start']); } $limit = $params['limit']; $pager->setLimit($limit); $pager->doQuery(); $revisions = $pager->getResult(); } $count = 0; $start = 0; $defaultSort = $pager->getDefaultSort(); $result = $this->getResult(); foreach ($revisions as $row) { if (!$revsSet && $count == $limit) { $this->setContinueEnumParameter('start', $start); break; } $data[] = $this->formatRow($row, $repo, $result); $start = $row->{$defaultSort}; $count++; } $result->setIndexedTagName($data, 'revision'); $result->addValue('query', $this->getModuleName(), $data); }
public function execute() { global $wgUser; // Before doing anything at all, let's check permissions if (!$wgUser->isAllowed('codereview-use')) { $this->dieUsage('You don\'t have permission to update code', 'permissiondenied'); } $params = $this->extractRequestParams(); $repo = CodeRepository::newFromName($params['repo']); if (!$repo) { $this->dieUsage("Invalid repo ``{$params['repo']}''", 'invalidrepo'); } $svn = SubversionAdaptor::newFromRepo($repo->getPath()); $lastStoredRev = $repo->getLastStoredRev(); if ($lastStoredRev >= $params['rev']) { // Nothing to do, we're up to date. // Return an empty result $this->getResult()->addValue(null, $this->getModuleName(), array()); return; } // FIXME: this could be a lot? $log = $svn->getLog('', $lastStoredRev + 1, $params['rev']); if (!$log) { // FIXME: When and how often does this happen? // Should we use dieUsage() here instead? ApiBase::dieDebug(__METHOD__, 'Something awry...'); } $result = array(); $revs = array(); foreach ($log as $data) { $codeRev = CodeRevision::newFromSvn($repo, $data); $codeRev->save(); $result[] = array('id' => $codeRev->getId(), 'author' => $codeRev->getAuthor(), 'timestamp' => wfTimestamp(TS_ISO_8601, $codeRev->getTimestamp()), 'message' => $codeRev->getMessage()); $revs[] = $codeRev; } // Cache the diffs if there are a only a few. // Mainly for WMF post-commit ping hook... if (count($revs) <= 2) { foreach ($revs as $codeRev) { $repo->setDiffCache($codeRev); // trigger caching } } $this->getResult()->setIndexedTagName($result, 'rev'); $this->getResult()->addValue(null, $this->getModuleName(), $result); }
public function execute() { $repoName = $this->getArg(0); if ($repoName == "all") { $this->error("Cannot use the 'all' repo", true); } $repo = CodeRepository::newFromName($repoName); if (!$repo) { $this->error("Repo '{$repoName}' is not a valid Repository", true); } $revisions = $this->getArg(1); if (strpos($revisions, ':') !== false) { $revisionVals = explode(':', $revisions, 2); } else { $this->error("Invalid revision range", true); } $start = intval($revisionVals[0]); $end = intval($revisionVals[1]); $revisions = range($start, $end); $status = $this->getArg(2); if (!CodeRevision::isValidStatus($status)) { $this->error("'{$status}' is not a valid status", true); } $username = $this->getArg(3); $user = User::newFromName($username); if (!$user) { $this->error("'{$username}' is not a valid username ", true); } if (!$user->isAllowed('codereview-set-status')) { $this->error("'{$username}' does not have the 'codereview-set-status' right", true); } $dbr = wfGetDB(DB_SLAVE); $res = $dbr->select('code_rev', '*', array('cr_id' => $revisions, 'cr_repo_id' => $repo->getId()), __METHOD__); foreach ($res as $row) { $rev = CodeRevision::newFromRow($repo, $row); if ($rev && $rev->setStatus($status, $user)) { $this->output("r{$row->cr_id} updated\n"); } else { $this->output("r{$row->cr_id} not updated\n"); } } $this->output("Done!\n"); }
public function execute() { global $wgUser; // Before doing anything at all, let's check permissions if (!$wgUser->isAllowed('codereview-use')) { $this->dieUsage('You don\'t have permission to view code tags', 'permissiondenied'); } $params = $this->extractRequestParams(); $repo = CodeRepository::newFromName($params['repo']); if (!$repo instanceof CodeRepository) { $this->dieUsage("Invalid repo ``{$params['repo']}''", 'invalidrepo'); } $data = array(); foreach ($repo->getTagList(true) as $tag => $count) { $data[] = array('name' => $tag, 'revcount' => $count); } $result = $this->getResult(); $result->setIndexedTagName($data, 'tag'); $result->addValue('query', $this->getModuleName(), $data); }
public function execute() { global $wgUser; // Before doing anything at all, let's check permissions if (!$wgUser->isAllowed('codereview-use')) { $this->dieUsage('You don\'t have permission to update code', 'permissiondenied'); } $params = $this->extractRequestParams(); if ($params['comment'] && !$wgUser->isAllowed('codereview-post-comment')) { $this->dieUsage('You do not have permission to post comment', 'permissiondenied'); } global $wgCodeReviewInlineComments; if (!$wgCodeReviewInlineComments && isset($params['patchline'])) { $this->dieUsageMsg("Can not attach a comment to a diff when inline commenting is disabled (\$wgCodeReviewInlineComments is false)."); } $repo = CodeRepository::newFromName($params['repo']); if (!$repo) { $this->dieUsage("Invalid repo ``{$params['repo']}''", 'invalidrepo'); } $rev = $repo->getRevision($params['rev']); if (!$rev) { $this->dieUsage("There is no revision with ID {$params['rev']}", 'nosuchrev'); } $revisionCommitter = new CodeRevisionCommitterApi($repo, $rev); $commentID = $revisionCommitter->revisionUpdate($params['status'], $params['addtags'], $params['removetags'], $params['addflags'], $params['removeflags'], $params['addreferences'], $params['removereferences'], $params['comment'], $params['addreferenced'], $params['removereferenced']); // Forge a response object $r = array('result' => 'Success'); if ($commentID !== 0) { // id inserted $r['commentid'] = intval($commentID); // HTML Formatted comment $view = new CodeRevisionView($repo, $rev); $comment = CodeComment::newFromID($commentID, $rev); $r['HTML'] = $view->formatComment($comment); } $this->getResult()->addValue(null, $this->getModuleName(), $r); }
public function execute() { $repoName = $this->getArg(0); if ($repoName == "all") { $this->error("Cannot use the 'all' repo", true); } $repo = CodeRepository::newFromName($repoName); if (!$repo) { $this->error("Repo '{$repoName}' is not a valid Repository", true); } $revisions = $this->getArg(1); if (strpos($revisions, ':') !== false) { $revisionVals = explode(':', $revisions, 2); } else { $this->error("Invalid revision range", true); } $start = intval($revisionVals[0]); $end = intval($revisionVals[1]); $revisions = range($start, $end); $dryrun = $this->hasOption('dry-run'); $dbr = wfGetDB(DB_SLAVE); $res = $dbr->select('code_rev', '*', array('cr_id' => $revisions, 'cr_repo_id' => $repo->getId()), __METHOD__); foreach ($res as $row) { $rev = CodeRevision::newFromRow($repo, $row); $affectedRevs = $rev->getUniqueAffectedRevs(); $this->output("r{$row->cr_id}: "); if (count($affectedRevs)) { $this->output("associating revs " . implode(',', $affectedRevs) . "\n"); if (!$dryrun) { $rev->addReferencesTo($affectedRevs); } } else { $this->output("no revisions followed up\n"); } } $this->output("Done!\n"); }
/** * 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"); }
/** * Get a view object from a sub page path. * @return CodeView object or null if no valid action could be found */ private function getViewFrom($subpage) { global $wgRequest; // Defines the classes to use for each view type. // The first class name is used if no additional parameters are provided. // The second, if defined, is used if there is an additional parameter. If // there is no second class defined, then the first class is used in both // cases. static $paramClasses = array('tag' => array("CodeTagListView", "CodeRevisionTagView"), 'author' => array("CodeAuthorListView", "CodeRevisionAuthorView"), 'status' => array("CodeStatusListView", "CodeRevisionStatusView"), 'comments' => array("CodeCommentsListView"), 'statuschanges' => array("CodeStatusChangeListView"), 'releasenotes' => array("CodeReleaseNotes"), 'stats' => array("CodeRepoStatsView")); # Remove stray slashes $subpage = preg_replace('/\\/$/', '', $subpage); if ($subpage == '') { $view = new CodeRepoListView(); } else { $params = explode('/', $subpage); $repo = CodeRepository::newFromName($params[0]); // If a repository was specified, but it does not exist, redirect to the // repository list with an appropriate message. if (!$repo) { $view = new CodeRepoListView(); global $wgOut; $wgOut->addWikiMsg('code-repo-not-found', wfEscapeWikiText($params[0])); return $view; } switch (count($params)) { case 1: $view = new CodeRevisionListView($repo); break; case 2: // drop through... // drop through... case 3: if (isset($paramClasses[$params[1]])) { $row = $paramClasses[$params[1]]; if (isset($params[2]) && isset($row[1])) { $view = new $row[1]($repo, $params[2]); } else { $view = new $row[0]($repo); } } elseif ($wgRequest->wasPosted() && !$wgRequest->getCheck('wpPreview')) { # This is not really a view, but we return it nonetheless. # Add any tags, Set status, Adds comments $view = new CodeRevisionCommitter($repo, $params[1]); } elseif (empty($params[1])) { $view = new CodeRevisionListView($repo); } else { $view = new CodeRevisionView($repo, $params[1]); } break; case 4: if ($params[1] === 'author' && $params[3] === 'link') { $view = new CodeRevisionAuthorLink($repo, $params[2]); break; } elseif ($params[1] === 'comments') { $view = new CodeCommentsAuthorListView($repo, $params[3]); break; } elseif ($params[1] === 'statuschanges') { $view = new CodeStatusChangeAuthorListView($repo, $params[3]); break; } default: if ($params[2] == 'reply') { $view = new CodeRevisionView($repo, $params[1], $params[3]); break; } return null; } } return $view; }
/** * @ * @param $page Title Special page title (with repo subpage) * @param $repo */ public function __construct(Title $t, $repo) { $this->title = $t; $this->repoName = $repo; $this->repo = CodeRepository::newFromName($repo); }