Page MenuHomestyx hydra

No OneTemporary

diff --git a/resources/sql/patches/20130304.lintauthor.sql b/resources/sql/patches/20130304.lintauthor.sql
new file mode 100644
index 0000000000..ffcb484c26
--- /dev/null
+++ b/resources/sql/patches/20130304.lintauthor.sql
@@ -0,0 +1,3 @@
+ALTER TABLE `{$NAMESPACE}_repository`.`repository_lintmessage`
+ ADD authorPHID varchar(64) COLLATE utf8_bin AFTER line,
+ ADD INDEX key_author (authorPHID);
diff --git a/scripts/repository/save_lint.php b/scripts/repository/save_lint.php
index 2777d3cd5b..0a23adb49c 100755
--- a/scripts/repository/save_lint.php
+++ b/scripts/repository/save_lint.php
@@ -1,53 +1,58 @@
#!/usr/bin/env php
<?php
require_once dirname(__FILE__).'/../__init_script__.php';
$synopsis = <<<EOT
**save_lint.php**
Discover lint problems and save them to database so that they can
be displayed in Diffusion.
EOT;
$args = id(new PhutilArgumentParser($argv))
->setTagline('save lint errors to database')
->setSynopsis($synopsis)
->parseStandardArguments()
->parse(array(
array(
'name' => 'all',
'help' =>
"Discover problems in the whole repository instead of just changes ".
"since the last run.",
),
array(
'name' => 'arc',
'param' => 'path',
'default' => 'arc',
'help' => "Path to Arcanist executable.",
),
array(
'name' => 'severity',
'param' => 'string',
'default' => ArcanistLintSeverity::SEVERITY_ADVICE,
'help' => "Minimum severity, one of ArcanistLintSeverity constants.",
),
array(
'name' => 'chunk-size',
'param' => 'number',
'default' => 256,
'help' => "Number of paths passed to `arc` at once.",
),
+ array(
+ 'name' => 'blame',
+ 'help' => "Assign lint errors to authors who last modified the line.",
+ ),
));
echo "Saving lint errors to database...\n";
$count = id(new DiffusionLintSaveRunner())
->setAll($args->getArg('all', false))
->setArc($args->getArg('arc'))
->setSeverity($args->getArg('severity'))
->setChunkSize($args->getArg('chunk-size'))
+ ->setNeedsBlame($args->getArg('blame'))
->run('.');
echo "\nProcessed {$count} files.\n";
diff --git a/src/applications/diffusion/DiffusionLintSaveRunner.php b/src/applications/diffusion/DiffusionLintSaveRunner.php
index 90069b1660..6d2f0b3b4e 100644
--- a/src/applications/diffusion/DiffusionLintSaveRunner.php
+++ b/src/applications/diffusion/DiffusionLintSaveRunner.php
@@ -1,210 +1,287 @@
<?php
final class DiffusionLintSaveRunner {
private $arc = 'arc';
private $severity = ArcanistLintSeverity::SEVERITY_ADVICE;
private $all = false;
private $chunkSize = 256;
+ private $needsBlame = false;
private $svnRoot;
private $lintCommit;
private $branch;
private $conn;
private $deletes = array();
private $inserts = array();
+ private $blame = array();
public function setArc($path) {
$this->arc = $path;
return $this;
}
public function setSeverity($string) {
$this->severity = $string;
return $this;
}
public function setAll($bool) {
$this->all = $bool;
return $this;
}
public function setChunkSize($number) {
$this->chunkSize = $number;
return $this;
}
+ public function setNeedsBlame($boolean) {
+ $this->needsBlame = $boolean;
+ return $this;
+ }
+
public function run($dir) {
$working_copy = ArcanistWorkingCopyIdentity::newFromPath($dir);
$api = ArcanistRepositoryAPI::newAPIFromWorkingCopyIdentity($working_copy);
$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;
+ $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 = new PhabricatorRepositoryBranch();
$this->conn = $this->branch->establishConnection('w');
$this->branch = $this->branch->loadOneWhere(
'repositoryID = %d AND name = %s',
$project->getRepositoryID(),
$branch_name);
$this->lintCommit = null;
if (!$this->branch) {
$this->branch = id(new PhabricatorRepositoryBranch())
->setRepositoryID($project->getRepositoryID())
->setName($branch_name)
->save();
} else 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();
}
- $this->deletes = array();
- $this->inserts = array();
$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->branch->setLintCommit($api->getUnderlyingWorkingCopyRevision());
+
+ $this->lintCommit = $api->getUnderlyingWorkingCopyRevision();
+ $this->branch->setLintCommit($this->lintCommit);
$this->branch->save();
+ if ($this->blame) {
+ $this->blameAuthors();
+ $this->blame = array();
+ }
+
return $count;
}
private function runArcLint(array $files) {
if (!$files) {
return;
}
echo '.';
try {
$future = new ExecFuture(
'%C lint --severity %s --output json %Ls',
$this->arc,
$this->severity,
$files);
foreach (new LinesOfALargeExecFuture($future) as $json) {
$paths = json_decode($json, true);
if (!is_array($paths)) {
fprintf(STDERR, "Invalid JSON: {$json}\n");
continue;
}
foreach ($paths as $path => $messages) {
if (!isset($files[$path])) {
continue;
}
foreach ($messages as $message) {
+ $line = idx($message, 'line', 0);
+
$this->inserts[] = qsprintf(
$this->conn,
'(%d, %s, %d, %s, %s, %s, %s)',
$this->branch->getID(),
$this->svnRoot.'/'.$path,
- idx($message, 'line', 0),
+ $line,
idx($message, 'code', ''),
idx($message, 'severity', ''),
idx($message, 'name', ''),
idx($message, 'description', ''));
+
+ if ($line && $this->needsBlame) {
+ $this->blame[$path][$line] = true;
+ }
}
if (count($this->deletes) >= 1024 || count($this->inserts) >= 256) {
- $this->saveLintMessages($this->branch);
- $this->deletes = array();
- $this->inserts = array();
+ $this->saveLintMessages();
}
}
}
} catch (Exception $ex) {
fprintf(STDERR, $ex->getMessage()."\n");
}
}
private function saveLintMessages() {
$this->conn->openTransaction();
foreach (array_chunk($this->deletes, 1024) as $paths) {
queryfx(
$this->conn,
'DELETE FROM %T WHERE branchID = %d AND path IN (%Ls)',
PhabricatorRepository::TABLE_LINTMESSAGE,
$this->branch->getID(),
$paths);
}
foreach (array_chunk($this->inserts, 256) as $values) {
queryfx(
$this->conn,
'INSERT INTO %T
(branchID, path, line, code, severity, name, description)
VALUES %Q',
PhabricatorRepository::TABLE_LINTMESSAGE,
implode(', ', $values));
}
$this->conn->saveTransaction();
+
+ $this->deletes = array();
+ $this->inserts = array();
+ }
+
+
+ private function blameAuthors() {
+ $repository = id(new PhabricatorRepository())->load(
+ $this->branch->getRepositoryID());
+
+ $queries = array();
+ $futures = array();
+ foreach ($this->blame as $path => $lines) {
+ $drequest = DiffusionRequest::newFromDictionary(array(
+ 'repository' => $repository,
+ 'branch' => $this->branch->getName(),
+ 'path' => $path,
+ 'commit' => $this->lintCommit,
+ ));
+ $query = DiffusionFileContentQuery::newFromDiffusionRequest($drequest)
+ ->setNeedsBlame(true);
+ $queries[$path] = $query;
+ $futures[$path] = $query->getFileContentFuture();
+ }
+
+ $authors = array();
+
+ foreach (Futures($futures)->limit(8) as $path => $future) {
+ $queries[$path]->loadFileContentFromFuture($future);
+ list(, $rev_list, $blame_dict) = $queries[$path]->getBlameData();
+ foreach (array_keys($this->blame[$path]) as $line) {
+ $commit_identifier = $rev_list[$line - 1];
+ $author = idx($blame_dict[$commit_identifier], 'authorPHID');
+ if ($author) {
+ $authors[$author][$path][] = $line;
+ }
+ }
+ }
+
+ if ($authors) {
+ $this->conn->openTransaction();
+
+ foreach ($authors as $author => $paths) {
+ $where = array();
+ foreach ($paths as $path => $lines) {
+ $where[] = qsprintf(
+ $this->conn,
+ '(path = %s AND line IN (%Ld))',
+ $this->svnRoot.'/'.$path,
+ $lines);
+ }
+ queryfx(
+ $this->conn,
+ 'UPDATE %T SET authorPHID = %s WHERE %Q',
+ PhabricatorRepository::TABLE_LINTMESSAGE,
+ $author,
+ implode(' OR ', $where));
+ }
+
+ $this->conn->saveTransaction();
+ }
}
}
diff --git a/src/applications/diffusion/controller/DiffusionBrowseFileController.php b/src/applications/diffusion/controller/DiffusionBrowseFileController.php
index 076e041a69..80898a2f71 100644
--- a/src/applications/diffusion/controller/DiffusionBrowseFileController.php
+++ b/src/applications/diffusion/controller/DiffusionBrowseFileController.php
@@ -1,967 +1,966 @@
<?php
final class DiffusionBrowseFileController extends DiffusionController {
private $corpusType = 'text';
private $lintCommit;
private $lintMessages;
public function processRequest() {
$request = $this->getRequest();
$drequest = $this->getDiffusionRequest();
$before = $request->getStr('before');
if ($before) {
return $this->buildBeforeResponse($before);
}
$path = $drequest->getPath();
$selected = $request->getStr('view');
$preferences = $request->getUser()->loadPreferences();
if (!$selected) {
$selected = $preferences->getPreference(
PhabricatorUserPreferences::PREFERENCE_DIFFUSION_VIEW,
'highlighted');
} else if ($request->isFormPost() && $selected != 'raw') {
$preferences->setPreference(
PhabricatorUserPreferences::PREFERENCE_DIFFUSION_VIEW,
$selected);
$preferences->save();
return id(new AphrontRedirectResponse())
->setURI($request->getRequestURI()->alter('view', $selected));
}
$needs_blame = ($selected == 'plainblame');
if ($selected == 'blame' && $request->isAjax()) {
$needs_blame = true;
}
$file_query = DiffusionFileContentQuery::newFromDiffusionRequest(
$this->diffusionRequest);
$file_query->setViewer($request->getUser());
$file_query->setNeedsBlame($needs_blame);
$file_query->loadFileContent();
$data = $file_query->getRawData();
if ($selected === 'raw') {
return $this->buildRawResponse($path, $data);
}
$this->loadLintMessages();
// Build the content of the file.
$corpus = $this->buildCorpus(
$selected,
$file_query,
$needs_blame,
$drequest,
$path,
$data);
if ($request->isAjax()) {
return id(new AphrontAjaxResponse())->setContent($corpus);
}
require_celerity_resource('diffusion-source-css');
if ($this->corpusType == 'text') {
$view_select_panel = $this->renderViewSelectPanel($selected);
} else {
$view_select_panel = null;
}
// Render the page.
$content = array();
$follow = $request->getStr('follow');
if ($follow) {
$notice = new AphrontErrorView();
$notice->setSeverity(AphrontErrorView::SEVERITY_WARNING);
$notice->setTitle('Unable to Continue');
switch ($follow) {
case 'first':
$notice->appendChild(
"Unable to continue tracing the history of this file because ".
"this commit is the first commit in the repository.");
break;
case 'created':
$notice->appendChild(
"Unable to continue tracing the history of this file because ".
"this commit created the file.");
break;
}
$content[] = $notice;
}
$renamed = $request->getStr('renamed');
if ($renamed) {
$notice = new AphrontErrorView();
$notice->setSeverity(AphrontErrorView::SEVERITY_NOTICE);
$notice->setTitle('File Renamed');
$notice->appendChild(
"File history passes through a rename from '".$drequest->getPath().
"' to '".$renamed."'.");
$content[] = $notice;
}
$content[] = $view_select_panel;
$content[] = $corpus;
$content[] = $this->buildOpenRevisions();
$nav = $this->buildSideNav('browse', true);
$nav->appendChild($content);
$crumbs = $this->buildCrumbs(
array(
'branch' => true,
'path' => true,
'view' => 'browse',
));
$nav->setCrumbs($crumbs);
$basename = basename($this->getDiffusionRequest()->getPath());
return $this->buildApplicationPage(
$nav,
array(
'title' => $basename,
));
}
private function loadLintMessages() {
$drequest = $this->getDiffusionRequest();
$branch = $drequest->loadBranch();
if (!$branch || !$branch->getLintCommit()) {
return;
}
$this->lintCommit = $branch->getLintCommit();
$conn = id(new PhabricatorRepository())->establishConnection('r');
$where = '';
if ($drequest->getLint()) {
$where = qsprintf(
$conn,
'AND code = %s',
$drequest->getLint());
}
$this->lintMessages = queryfx_all(
$conn,
'SELECT * FROM %T WHERE branchID = %d %Q AND path = %s',
PhabricatorRepository::TABLE_LINTMESSAGE,
$branch->getID(),
$where,
'/'.$drequest->getPath());
}
private function buildCorpus($selected,
DiffusionFileContentQuery $file_query,
$needs_blame,
DiffusionRequest $drequest,
$path,
$data) {
if (ArcanistDiffUtils::isHeuristicBinaryFile($data)) {
$file = $this->loadFileForData($path, $data);
$file_uri = $file->getBestURI();
if ($file->isViewableImage()) {
$this->corpusType = 'image';
return $this->buildImageCorpus($file_uri);
} else {
$this->corpusType = 'binary';
return $this->buildBinaryCorpus($file_uri, $data);
}
}
switch ($selected) {
case 'plain':
$style =
"margin: 1em 2em; width: 90%; height: 80em; font-family: monospace";
$corpus = phutil_tag(
'textarea',
array(
'style' => $style,
),
$file_query->getRawData());
break;
case 'plainblame':
$style =
"margin: 1em 2em; width: 90%; height: 80em; font-family: monospace";
list($text_list, $rev_list, $blame_dict) =
$file_query->getBlameData();
$rows = array();
foreach ($text_list as $k => $line) {
$rev = $rev_list[$k];
- if (isset($blame_dict[$rev]['handle'])) {
- $author = $blame_dict[$rev]['handle']->getName();
- } else {
- $author = $blame_dict[$rev]['author'];
- }
+ $author = $blame_dict[$rev]['author'];
$rows[] =
sprintf("%-10s %-20s %s", substr($rev, 0, 7), $author, $line);
}
$corpus = phutil_tag(
'textarea',
array(
'style' => $style,
),
implode("\n", $rows));
break;
case 'highlighted':
case 'blame':
default:
require_celerity_resource('syntax-highlighting-css');
list($text_list, $rev_list, $blame_dict) = $file_query->getBlameData();
$text_list = implode("\n", $text_list);
$text_list = PhabricatorSyntaxHighlighter::highlightWithFilename(
$path,
$text_list);
$text_list = explode("\n", $text_list);
$rows = $this->buildDisplayRows($text_list, $rev_list, $blame_dict,
$needs_blame, $drequest, $file_query, $selected);
$corpus_table = javelin_tag(
'table',
array(
'class' => "diffusion-source remarkup-code PhabricatorMonospaced",
'sigil' => 'diffusion-source',
),
$rows);
if ($this->getRequest()->isAjax()) {
return $corpus_table;
}
$id = celerity_generate_unique_node_id();
$projects = $drequest->loadArcanistProjects();
$langs = array();
foreach ($projects as $project) {
$ls = $project->getSymbolIndexLanguages();
if (!$ls) {
continue;
}
$dep_projects = $project->getSymbolIndexProjects();
$dep_projects[] = $project->getPHID();
foreach ($ls as $lang) {
if (!isset($langs[$lang])) {
$langs[$lang] = array();
}
$langs[$lang] += $dep_projects + array($project);
}
}
$lang = last(explode('.', $drequest->getPath()));
if (isset($langs[$lang])) {
Javelin::initBehavior(
'repository-crossreference',
array(
'container' => $id,
'lang' => $lang,
'projects' => $langs[$lang],
));
}
$corpus = phutil_tag(
'div',
array(
'style' => 'padding: 0 2em;',
'id' => $id,
),
$corpus_table);
Javelin::initBehavior('load-blame', array('id' => $id));
break;
}
return $corpus;
}
private function renderViewSelectPanel($selected) {
$toggle_blame = array(
'highlighted' => 'blame',
'blame' => 'highlighted',
'plain' => 'plainblame',
'plainblame' => 'plain',
'raw' => 'raw', // not a real case.
);
$toggle_highlight = array(
'highlighted' => 'plain',
'blame' => 'plainblame',
'plain' => 'highlighted',
'plainblame' => 'blame',
'raw' => 'raw', // not a real case.
);
$user = $this->getRequest()->getUser();
$base_uri = $this->getRequest()->getRequestURI();
$blame_on = ($selected == 'blame' || $selected == 'plainblame');
if ($blame_on) {
$blame_text = pht('Disable Blame');
} else {
$blame_text = pht('Enable Blame');
}
$blame_button = $this->createViewAction(
$blame_text,
$base_uri->alter('view', $toggle_blame[$selected]),
$user);
$highlight_on = ($selected == 'blame' || $selected == 'highlighted');
if ($highlight_on) {
$highlight_text = pht('Disable Highlighting');
} else {
$highlight_text = pht('Enable Highlighting');
}
$highlight_button = $this->createViewAction(
$highlight_text,
$base_uri->alter('view', $toggle_highlight[$selected]),
$user);
$href = null;
if ($this->getRequest()->getStr('lint') !== null) {
$lint_text = pht('Hide %d Lint Message(s)', count($this->lintMessages));
$href = $base_uri->alter('lint', null);
} else if ($this->lintCommit === null) {
$lint_text = pht('Lint not Available');
} else {
$lint_text = pht(
'Show %d Lint Message(s)',
count($this->lintMessages));
$href = $this->getDiffusionRequest()->generateURI(array(
'action' => 'browse',
'commit' => $this->lintCommit,
))->alter('lint', '');
}
$lint_button = $this->createViewAction(
$lint_text,
$href,
$user);
if (!$href) {
$lint_button->setDisabled(true);
}
$raw_button = $this->createViewAction(
pht('View Raw File'),
$base_uri->alter('view', 'raw'),
$user,
'file');
$edit_button = $this->createEditAction();
return id(new PhabricatorActionListView())
->setUser($user)
->addAction($blame_button)
->addAction($highlight_button)
->addAction($lint_button)
->addAction($raw_button)
->addAction($edit_button);
}
private function createViewAction(
$localized_text,
$href,
$user,
$icon = null) {
return id(new PhabricatorActionView())
->setName($localized_text)
->setIcon($icon)
->setUser($user)
->setRenderAsForm(true)
->setHref($href);
}
private function createEditAction() {
$request = $this->getRequest();
$user = $request->getUser();
$drequest = $this->getDiffusionRequest();
$repository = $drequest->getRepository();
$path = $drequest->getPath();
$line = nonempty((int)$drequest->getLine(), 1);
$callsign = $repository->getCallsign();
$editor_link = $user->loadEditorLink($path, $line, $callsign);
$action = id(new PhabricatorActionView())
->setName(pht('Open in Editor'))
->setIcon('edit');
$action->setHref($editor_link);
$action->setDisabled(!$editor_link);
return $action;
}
private function buildDisplayRows(
array $text_list,
array $rev_list,
array $blame_dict,
$needs_blame,
DiffusionRequest $drequest,
DiffusionFileContentQuery $file_query,
$selected) {
+ $handles = array();
if ($blame_dict) {
$epoch_list = ipull(ifilter($blame_dict, 'epoch'), 'epoch');
$epoch_min = min($epoch_list);
$epoch_max = max($epoch_list);
$epoch_range = ($epoch_max - $epoch_min) + 1;
+ $handles = $this->loadViewerHandles(ipull($blame_dict, 'authorPHID'));
}
$line_arr = array();
$line_str = $drequest->getLine();
$ranges = explode(',', $line_str);
foreach ($ranges as $range) {
if (strpos($range, '-') !== false) {
list($min, $max) = explode('-', $range, 2);
$line_arr[] = array(
'min' => min($min, $max),
'max' => max($min, $max),
);
} else if (strlen($range)) {
$line_arr[] = array(
'min' => $range,
'max' => $range,
);
}
}
$display = array();
$line_number = 1;
$last_rev = null;
$color = null;
foreach ($text_list as $k => $line) {
$display_line = array(
'epoch' => null,
'commit' => null,
'author' => null,
'target' => null,
'highlighted' => null,
'line' => $line_number,
'data' => $line,
);
if ($selected == 'blame') {
// If the line's rev is same as the line above, show empty content
// with same color; otherwise generate blame info. The newer a change
// is, the more saturated the color.
$rev = idx($rev_list, $k, $last_rev);
if ($last_rev == $rev) {
$display_line['color'] = $color;
} else {
$blame = $blame_dict[$rev];
if (!isset($blame['epoch'])) {
$color = '#ffd'; // Render as warning.
} else {
$color_ratio = ($blame['epoch'] - $epoch_min) / $epoch_range;
$color_value = 0xF6 * (1.0 - $color_ratio);
$color = sprintf(
'#%02x%02x%02x',
$color_value,
0xF6,
$color_value);
}
$display_line['epoch'] = idx($blame, 'epoch');
$display_line['color'] = $color;
$display_line['commit'] = $rev;
- if (isset($blame['handle'])) {
- $author_link = $blame['handle']->renderLink();
+ $author_phid = idx($blame, 'authorPHID');
+ if ($author_phid && $handles[$author_phid]) {
+ $author_link = $handles[$author_phid]->renderLink();
} else {
$author_link = phutil_tag(
'span',
array(
),
$blame['author']);
}
$display_line['author'] = $author_link;
$last_rev = $rev;
}
}
if ($line_arr) {
if ($line_number == $line_arr[0]['min']) {
$display_line['target'] = true;
}
foreach ($line_arr as $range) {
if ($line_number >= $range['min'] &&
$line_number <= $range['max']) {
$display_line['highlighted'] = true;
}
}
}
$display[] = $display_line;
++$line_number;
}
$commits = array_filter(ipull($display, 'commit'));
if ($commits) {
$commits = id(new PhabricatorAuditCommitQuery())
->withIdentifiers($drequest->getRepository()->getID(), $commits)
->needCommitData(true)
->execute();
$commits = mpull($commits, null, 'getCommitIdentifier');
}
$revision_ids = id(new DifferentialRevision())
->loadIDsByCommitPHIDs(mpull($commits, 'getPHID'));
$revisions = array();
if ($revision_ids) {
$revisions = id(new DifferentialRevision())->loadAllWhere(
'id IN (%Ld)',
$revision_ids);
}
$request = $this->getRequest();
$user = $request->getUser();
Javelin::initBehavior('phabricator-oncopy', array());
$engine = null;
$inlines = array();
if ($this->getRequest()->getStr('lint') !== null && $this->lintMessages) {
$engine = new PhabricatorMarkupEngine();
$engine->setViewer($user);
foreach ($this->lintMessages as $message) {
$inline = id(new PhabricatorAuditInlineComment())
->setID($message['id'])
->setSyntheticAuthor(
ArcanistLintSeverity::getStringForSeverity($message['severity']).
' '.$message['code'].' ('.$message['name'].')')
->setLineNumber($message['line'])
->setContent($message['description']);
$inlines[$message['line']][] = $inline;
$engine->addObject(
$inline,
PhabricatorInlineCommentInterface::MARKUP_FIELD_BODY);
}
$engine->process();
require_celerity_resource('differential-changeset-view-css');
}
$rows = $this->renderInlines(
idx($inlines, 0, array()),
($selected == 'blame'),
$engine);
foreach ($display as $line) {
$line_href = $drequest->generateURI(
array(
'action' => 'browse',
'line' => $line['line'],
'stable' => true,
));
$blame = array();
$style = null;
if (array_key_exists('color', $line)) {
if ($line['color']) {
$style = 'background: '.$line['color'].';';
}
$before_link = null;
$commit_link = null;
$revision_link = null;
if (idx($line, 'commit')) {
$commit = $line['commit'];
$summary = 'Unknown';
if (idx($commits, $commit)) {
$summary = $commits[$commit]->getCommitData()->getSummary();
}
$tooltip = phabricator_date(
$line['epoch'],
$user)." \xC2\xB7 ".$summary;
Javelin::initBehavior('phabricator-tooltips', array());
require_celerity_resource('aphront-tooltip-css');
$commit_link = javelin_tag(
'a',
array(
'href' => $drequest->generateURI(
array(
'action' => 'commit',
'commit' => $line['commit'],
)),
'sigil' => 'has-tooltip',
'meta' => array(
'tip' => $tooltip,
'align' => 'E',
'size' => 600,
),
),
phutil_utf8_shorten($line['commit'], 9, ''));
$revision_id = null;
if (idx($commits, $commit)) {
$revision_id = idx($revision_ids, $commits[$commit]->getPHID());
}
if ($revision_id) {
$revision = idx($revisions, $revision_id);
if (!$revision) {
$tooltip = '(Invalid revision)';
} else {
$tooltip =
phabricator_date($revision->getDateModified(), $user).
" \xC2\xB7 ".
$revision->getTitle();
}
$revision_link = javelin_tag(
'a',
array(
'href' => '/D'.$revision_id,
'sigil' => 'has-tooltip',
'meta' => array(
'tip' => $tooltip,
'align' => 'E',
'size' => 600,
),
),
'D'.$revision_id);
}
$uri = $line_href->alter('before', $commit);
$before_link = javelin_tag(
'a',
array(
'href' => $uri->setQueryParam('view', 'blame'),
'sigil' => 'has-tooltip',
'meta' => array(
'tip' => 'Skip Past This Commit',
'align' => 'E',
'size' => 300,
),
),
"\xC2\xAB");
}
$blame[] = phutil_tag(
'th',
array(
'class' => 'diffusion-blame-link',
'style' => $style,
),
$before_link);
$blame[] = phutil_tag(
'th',
array(
'class' => 'diffusion-rev-link',
'style' => $style,
),
$commit_link);
$blame[] = phutil_tag(
'th',
array(
'class' => 'diffusion-rev-link',
'style' => $style,
),
$revision_link);
$blame[] = phutil_tag(
'th',
array(
'class' => 'diffusion-author-link',
'style' => $style,
),
idx($line, 'author'));
}
$line_link = phutil_tag(
'a',
array(
'href' => $line_href,
),
$line['line']);
$blame[] = javelin_tag(
'th',
array(
'class' => 'diffusion-line-link',
'sigil' => 'diffusion-line-link',
'style' => $style,
),
$line_link);
Javelin::initBehavior('diffusion-line-linker');
if ($line['target']) {
Javelin::initBehavior(
'diffusion-jump-to',
array(
'target' => 'scroll_target',
));
$anchor_text = phutil_tag(
'a',
array(
'id' => 'scroll_target',
),
'');
} else {
$anchor_text = null;
}
$blame[] = phutil_tag(
'td',
array(
),
array(
$anchor_text,
// NOTE: See phabricator-oncopy behavior.
"\xE2\x80\x8B",
// TODO: [HTML] Not ideal.
phutil_safe_html($line['data']),
));
$rows[] = phutil_tag(
'tr',
array(
'class' => ($line['highlighted'] ? 'highlighted' : null),
),
$blame);
$rows = array_merge($rows, $this->renderInlines(
idx($inlines, $line['line'], array()),
($selected == 'blame'),
$engine));
}
return $rows;
}
private function renderInlines(array $inlines, $needs_blame, $engine) {
$rows = array();
foreach ($inlines as $inline) {
$inline_view = id(new DifferentialInlineCommentView())
->setMarkupEngine($engine)
->setInlineComment($inline)
->render();
$row = array_fill(0, ($needs_blame ? 5 : 1), phutil_tag('th'));
$row[] = phutil_tag('td', array(), $inline_view);
$rows[] = phutil_tag('tr', array('class' => 'inline'), $row);
}
return $rows;
}
private function loadFileForData($path, $data) {
return PhabricatorFile::buildFromFileDataOrHash(
$data,
array(
'name' => basename($path),
'ttl' => time() + 60 * 60 * 24,
));
}
private function buildRawResponse($path, $data) {
$file = $this->loadFileForData($path, $data);
return id(new AphrontRedirectResponse())->setURI($file->getBestURI());
}
private function buildImageCorpus($file_uri) {
$properties = new PhabricatorPropertyListView();
$properties->addProperty(
pht('Image'),
phutil_tag(
'img',
array(
'src' => $file_uri,
)));
$actions = id(new PhabricatorActionListView())
->setUser($this->getRequest()->getUser())
->addAction($this->createEditAction());
return array($actions, $properties);
}
private function buildBinaryCorpus($file_uri, $data) {
$properties = new PhabricatorPropertyListView();
$size = strlen($data);
$properties->addTextContent(
pht(
'This is a binary file. It is %s byte(s) in length.',
new PhutilNumber($size)));
$actions = id(new PhabricatorActionListView())
->setUser($this->getRequest()->getUser())
->addAction($this->createEditAction())
->addAction(
id(new PhabricatorActionView())
->setName(pht('Download Binary File...'))
->setIcon('download')
->setHref($file_uri));
return array($actions, $properties);
}
private function buildBeforeResponse($before) {
$request = $this->getRequest();
$drequest = $this->getDiffusionRequest();
// NOTE: We need to get the grandparent so we can capture filename changes
// in the parent.
$parent = $this->loadParentRevisionOf($before);
$old_filename = null;
$was_created = false;
if ($parent) {
$grandparent = $this->loadParentRevisionOf(
$parent->getCommitIdentifier());
if ($grandparent) {
$rename_query = new DiffusionRenameHistoryQuery();
$rename_query->setRequest($drequest);
$rename_query->setOldCommit($grandparent->getCommitIdentifier());
$old_filename = $rename_query->loadOldFilename();
$was_created = $rename_query->getWasCreated();
}
}
$follow = null;
if ($was_created) {
// If the file was created in history, that means older commits won't
// have it. Since we know it existed at 'before', it must have been
// created then; jump there.
$target_commit = $before;
$follow = 'created';
} else if ($parent) {
// If we found a parent, jump to it. This is the normal case.
$target_commit = $parent->getCommitIdentifier();
} else {
// If there's no parent, this was probably created in the initial commit?
// And the "was_created" check will fail because we can't identify the
// grandparent. Keep the user at 'before'.
$target_commit = $before;
$follow = 'first';
}
$path = $drequest->getPath();
$renamed = null;
if ($old_filename !== null &&
$old_filename !== '/'.$path) {
$renamed = $path;
$path = $old_filename;
}
$line = null;
// If there's a follow error, drop the line so the user sees the message.
if (!$follow) {
$line = $this->getBeforeLineNumber($target_commit);
}
$before_uri = $drequest->generateURI(
array(
'action' => 'browse',
'commit' => $target_commit,
'line' => $line,
'path' => $path,
));
$before_uri->setQueryParams($request->getRequestURI()->getQueryParams());
$before_uri = $before_uri->alter('before', null);
$before_uri = $before_uri->alter('renamed', $renamed);
$before_uri = $before_uri->alter('follow', $follow);
return id(new AphrontRedirectResponse())->setURI($before_uri);
}
private function getBeforeLineNumber($target_commit) {
$drequest = $this->getDiffusionRequest();
$line = $drequest->getLine();
if (!$line) {
return null;
}
$diff_query = DiffusionRawDiffQuery::newFromDiffusionRequest($drequest);
$diff_query->setAgainstCommit($target_commit);
try {
$raw_diff = $diff_query->loadRawDiff();
$old_line = 0;
$new_line = 0;
foreach (explode("\n", $raw_diff) as $text) {
if ($text[0] == '-' || $text[0] == ' ') {
$old_line++;
}
if ($text[0] == '+' || $text[0] == ' ') {
$new_line++;
}
if ($new_line == $line) {
return $old_line;
}
}
// We didn't find the target line.
return $line;
} catch (Exception $ex) {
return $line;
}
}
private function loadParentRevisionOf($commit) {
$drequest = $this->getDiffusionRequest();
$before_req = DiffusionRequest::newFromDictionary(
array(
'repository' => $drequest->getRepository(),
'commit' => $commit,
));
$query = DiffusionCommitParentsQuery::newFromDiffusionRequest($before_req);
$parents = $query->loadParents();
return head($parents);
}
}
diff --git a/src/applications/diffusion/controller/DiffusionLintController.php b/src/applications/diffusion/controller/DiffusionLintController.php
index cb558b1cfc..086b1cf236 100644
--- a/src/applications/diffusion/controller/DiffusionLintController.php
+++ b/src/applications/diffusion/controller/DiffusionLintController.php
@@ -1,234 +1,232 @@
<?php
final class DiffusionLintController extends DiffusionController {
public function processRequest() {
$request = $this->getRequest();
$user = $this->getRequest()->getUser();
$drequest = $this->diffusionRequest;
if ($request->getStr('lint') !== null) {
$controller = new DiffusionLintDetailsController($request);
$controller->setDiffusionRequest($drequest);
$controller->setCurrentApplication($this->getCurrentApplication());
return $this->delegateToController($controller);
}
$owners = array();
if (!$drequest) {
if (!$request->getArr('owner')) {
$owners[$user->getPHID()] = $user->getFullName();
} else {
$phids = $request->getArr('owner');
$phid = reset($phids);
$handles = $this->loadViewerHandles(array($phid));
$owners[$phid] = $handles[$phid]->getFullName();
}
}
$codes = $this->loadLintCodes(array_keys($owners));
if ($codes && !$drequest) {
$branches = id(new PhabricatorRepositoryBranch())->loadAllWhere(
'id IN (%Ld)',
array_unique(ipull($codes, 'branchID')));
$repositories = id(new PhabricatorRepository())->loadAllWhere(
'id IN (%Ld)',
array_unique(mpull($branches, 'getRepositoryID')));
$drequests = array();
foreach ($branches as $id => $branch) {
$drequests[$id] = DiffusionRequest::newFromDictionary(array(
'repository' => $repositories[$branch->getRepositoryID()],
'branch' => $branch->getName(),
));
}
}
$rows = array();
foreach ($codes as $code) {
if (!$this->diffusionRequest) {
$drequest = $drequests[$code['branchID']];
}
$rows[] = array(
hsprintf(
'<a href="%s">%s</a>',
$drequest->generateURI(array(
'action' => 'lint',
'lint' => $code['code'],
)),
$code['n']),
hsprintf(
'<a href="%s">%s</a>',
$drequest->generateURI(array(
'action' => 'browse',
'lint' => $code['code'],
)),
$code['files']),
hsprintf(
'<a href="%s">%s</a>',
$drequest->generateURI(array('action' => 'lint')),
$drequest->getCallsign()),
ArcanistLintSeverity::getStringForSeverity($code['maxSeverity']),
$code['code'],
$code['maxName'],
$code['maxDescription'],
);
}
$table = id(new AphrontTableView($rows))
->setHeaders(array(
'Problems',
'Files',
'Repository',
'Severity',
'Code',
'Name',
'Example',
))
->setColumnVisibility(array(true, true, !$this->diffusionRequest))
->setColumnClasses(array('n', 'n', '', '', 'pri', '', ''));
$content = array();
$link = null;
if ($this->diffusionRequest) {
$link = hsprintf(
'<a href="%s">%s</a>',
$drequest->generateURI(array(
'action' => 'lint',
'lint' => '',
)),
pht('Switch to List View'));
} else {
$form = id(new AphrontFormView())
->setUser($user)
->setMethod('GET')
->appendChild(
id(new AphrontFormTokenizerControl())
->setDatasource('/typeahead/common/users/')
->setLimit(1)
->setName('owner')
->setLabel('Owner')
->setValue($owners))
->appendChild(
id(new AphrontFormSubmitControl())
->setValue('Filter'));
$content[] = id(new AphrontListFilterView())->appendChild($form);
}
$content[] = id(new AphrontPanelView())
->setHeader(pht('%d Lint Message(s)', array_sum(ipull($codes, 'n'))))
->setCaption($link)
->appendChild($table);
$title = array('Lint');
$crumbs = $this->buildCrumbs(
array(
'branch' => true,
'path' => true,
'view' => 'lint',
));
if ($this->diffusionRequest) {
$title[] = $drequest->getCallsign();
$content = $this->buildSideNav('lint', false)
->setCrumbs($crumbs)
->appendChild($content);
} else {
array_unshift($content, $crumbs);
}
return $this->buildApplicationPage(
$content,
array('title' => $title));
}
private function loadLintCodes(array $owner_phids) {
$drequest = $this->diffusionRequest;
$conn = id(new PhabricatorRepository())->establishConnection('r');
$where = array('1 = 1');
if ($drequest) {
$branch = $drequest->loadBranch();
if (!$branch) {
return array();
}
$where[] = qsprintf($conn, 'branchID = %d', $branch->getID());
if ($drequest->getPath() != '') {
$path = '/'.$drequest->getPath();
$is_dir = (substr($path, -1) == '/');
$where[] = ($is_dir
? qsprintf($conn, 'path LIKE %>', $path)
: qsprintf($conn, 'path = %s', $path));
}
}
if ($owner_phids) {
+ $or = array();
+ $or[] = qsprintf($conn, 'authorPHID IN (%Ls)', $owner_phids);
+
+ $paths = array();
$packages = id(new PhabricatorOwnersOwner())
->loadAllWhere('userPHID IN (%Ls)', $owner_phids);
- if (!$packages) {
- return array();
- }
-
- $paths = id(new PhabricatorOwnersPath())
- ->loadAllWhere('packageID IN (%Ld)', array_keys($packages));
- if (!$paths) {
- return array();
+ if ($packages) {
+ $paths = id(new PhabricatorOwnersPath())->loadAllWhere(
+ 'packageID IN (%Ld)',
+ mpull($packages, 'getPackageID'));
}
- $repositories = id(new PhabricatorRepository())->loadAllWhere(
- 'phid IN (%Ls)',
- array_unique(mpull($paths, 'getRepositoryPHID')));
- $repositories = mpull($repositories, 'getID', 'getPHID');
+ if ($paths) {
+ $repositories = id(new PhabricatorRepository())->loadAllWhere(
+ 'phid IN (%Ls)',
+ array_unique(mpull($paths, 'getRepositoryPHID')));
+ $repositories = mpull($repositories, 'getID', 'getPHID');
- $branches = id(new PhabricatorRepositoryBranch())->loadAllWhere(
- 'repositoryID IN (%Ld)',
- $repositories);
- $branches = mgroup($branches, 'getRepositoryID');
+ $branches = id(new PhabricatorRepositoryBranch())->loadAllWhere(
+ 'repositoryID IN (%Ld)',
+ $repositories);
+ $branches = mgroup($branches, 'getRepositoryID');
+ }
- $or = array();
foreach ($paths as $path) {
$branch = idx($branches, $repositories[$path->getRepositoryPHID()]);
if ($branch) {
$condition = qsprintf(
$conn,
'(branchID IN (%Ld) AND path LIKE %>)',
array_keys($branch),
$path->getPath());
if ($path->getExcluded()) {
$where[] = 'NOT '.$condition;
} else {
$or[] = $condition;
}
}
}
- if (!$or) {
- return array();
- }
$where[] = '('.implode(' OR ', $or).')';
}
return queryfx_all(
$conn,
'SELECT
branchID,
code,
MAX(severity) AS maxSeverity,
MAX(name) AS maxName,
MAX(description) AS maxDescription,
COUNT(DISTINCT path) AS files,
COUNT(*) AS n
FROM %T
WHERE %Q
GROUP BY branchID, code
ORDER BY n DESC',
PhabricatorRepository::TABLE_LINTMESSAGE,
implode(' AND ', $where));
}
}
diff --git a/src/applications/diffusion/controller/DiffusionLintDetailsController.php b/src/applications/diffusion/controller/DiffusionLintDetailsController.php
index 0b5035acb8..0ccb3028a1 100644
--- a/src/applications/diffusion/controller/DiffusionLintDetailsController.php
+++ b/src/applications/diffusion/controller/DiffusionLintDetailsController.php
@@ -1,140 +1,149 @@
<?php
final class DiffusionLintDetailsController extends DiffusionController {
public function processRequest() {
$limit = 500;
$offset = $this->getRequest()->getInt('offset', 0);
$drequest = $this->getDiffusionRequest();
$branch = $drequest->loadBranch();
$messages = $this->loadLintMessages($branch, $limit, $offset);
$is_dir = (substr('/'.$drequest->getPath(), -1) == '/');
+ $authors = $this->loadViewerHandles(ipull($messages, 'authorPHID'));
+
$rows = array();
foreach ($messages as $message) {
$path = hsprintf(
'<a href="%s">%s</a>',
$drequest->generateURI(array(
'action' => 'lint',
'path' => $message['path'],
)),
substr($message['path'], strlen($drequest->getPath()) + 1));
$line = hsprintf(
'<a href="%s">%s</a>',
$drequest->generateURI(array(
'action' => 'browse',
'path' => $message['path'],
'line' => $message['line'],
'commit' => $branch->getLintCommit(),
)),
$message['line']);
+ $author = $message['authorPHID'];
+ if ($author && $authors[$author]) {
+ $author = $authors[$author]->renderLink();
+ }
+
$rows[] = array(
$path,
$line,
+ $author,
ArcanistLintSeverity::getStringForSeverity($message['severity']),
$message['name'],
$message['description'],
);
}
$table = id(new AphrontTableView($rows))
->setHeaders(array(
'Path',
'Line',
+ 'Author',
'Severity',
'Name',
'Description',
))
- ->setColumnClasses(array('', 'n', '', '', ''))
+ ->setColumnClasses(array('', 'n'))
->setColumnVisibility(array($is_dir));
$content = array();
$pager = id(new AphrontPagerView())
->setPageSize($limit)
->setOffset($offset)
->setHasMorePages(count($messages) >= $limit)
->setURI($this->getRequest()->getRequestURI(), 'offset');
$lint = $drequest->getLint();
$link = hsprintf(
'<a href="%s">%s</a>',
$drequest->generateURI(array(
'action' => 'lint',
'lint' => null,
)),
pht('Switch to Grouped View'));
$content[] = id(new AphrontPanelView())
->setHeader(
($lint != '' ? $lint." \xC2\xB7 " : '').
pht('%d Lint Message(s)', count($messages)))
->setCaption($link)
->appendChild($table)
->appendChild($pager);
$nav = $this->buildSideNav('lint', false);
$nav->appendChild($content);
$crumbs = $this->buildCrumbs(
array(
'branch' => true,
'path' => true,
'view' => 'lint',
));
$nav->setCrumbs($crumbs);
return $this->buildApplicationPage(
$nav,
array('title' => array(
'Lint',
$drequest->getRepository()->getCallsign(),
)));
}
private function loadLintMessages(
PhabricatorRepositoryBranch $branch,
$limit,
$offset) {
$drequest = $this->getDiffusionRequest();
if (!$branch) {
return array();
}
$conn = $branch->establishConnection('r');
$where = array(
qsprintf($conn, 'branchID = %d', $branch->getID()),
);
if ($drequest->getPath() != '') {
$path = '/'.$drequest->getPath();
$is_dir = (substr($path, -1) == '/');
$where[] = ($is_dir
? qsprintf($conn, 'path LIKE %>', $path)
: qsprintf($conn, 'path = %s', $path));
}
if ($drequest->getLint() != '') {
$where[] = qsprintf(
$conn,
'code = %s',
$drequest->getLint());
}
return queryfx_all(
$conn,
'SELECT *
FROM %T
WHERE %Q
ORDER BY path, code, line LIMIT %d OFFSET %d',
PhabricatorRepository::TABLE_LINTMESSAGE,
implode(' AND ', $where),
$limit,
$offset);
}
}
diff --git a/src/applications/diffusion/query/filecontent/DiffusionFileContentQuery.php b/src/applications/diffusion/query/filecontent/DiffusionFileContentQuery.php
index 086ff4f458..f7012088ae 100644
--- a/src/applications/diffusion/query/filecontent/DiffusionFileContentQuery.php
+++ b/src/applications/diffusion/query/filecontent/DiffusionFileContentQuery.php
@@ -1,123 +1,126 @@
<?php
abstract class DiffusionFileContentQuery extends DiffusionQuery {
private $needsBlame;
private $fileContent;
private $viewer;
final public static function newFromDiffusionRequest(
DiffusionRequest $request) {
return parent::newQueryObject(__CLASS__, $request);
}
- final public function loadFileContent() {
- $this->fileContent = $this->executeQuery();
+ abstract public function getFileContentFuture();
+ abstract protected function executeQueryFromFuture(Future $future);
+
+ final public function loadFileContentFromFuture(Future $future) {
+ $this->fileContent = $this->executeQueryFromFuture($future);
$repository = $this->getRequest()->getRepository();
$try_encoding = $repository->getDetail('encoding');
if ($try_encoding) {
$this->fileContent->setCorpus(
phutil_utf8_convert(
$this->fileContent->getCorpus(), "UTF-8", $try_encoding));
}
return $this->fileContent;
}
+ final protected function executeQuery() {
+ return $this->loadFileContentFromFuture($this->getFileContentFuture());
+ }
+
+ final public function loadFileContent() {
+ return $this->executeQuery();
+ }
+
final public function getRawData() {
return $this->fileContent->getCorpus();
}
final public function getBlameData() {
$raw_data = preg_replace('/\n$/', '', $this->getRawData());
$text_list = array();
$rev_list = array();
$blame_dict = array();
if (!$this->getNeedsBlame()) {
$text_list = explode("\n", $raw_data);
} else if ($raw_data != '') {
$lines = array();
foreach (explode("\n", $raw_data) as $k => $line) {
$lines[$k] = $this->tokenizeLine($line);
list($rev_id, $author, $text) = $lines[$k];
$text_list[$k] = $text;
$rev_list[$k] = $rev_id;
}
$rev_list = $this->processRevList($rev_list);
foreach ($lines as $k => $line) {
list($rev_id, $author, $text) = $line;
$rev_id = $rev_list[$k];
if (!isset($blame_dict[$rev_id])) {
$blame_dict[$rev_id]['author'] = $author;
}
}
$repository = $this->getRequest()->getRepository();
$commits = id(new PhabricatorAuditCommitQuery())
->withIdentifiers(
$repository->getID(),
array_unique($rev_list))
->execute();
foreach ($commits as $commit) {
$blame_dict[$commit->getCommitIdentifier()]['epoch'] =
$commit->getEpoch();
}
- $commits_data = array();
if ($commits) {
$commits_data = id(new PhabricatorRepositoryCommitData())->loadAllWhere(
'commitID IN (%Ls)',
mpull($commits, 'getID'));
- }
-
- $phids = array();
- foreach ($commits_data as $data) {
- $phids[] = $data->getCommitDetail('authorPHID');
- }
-
- $loader = new PhabricatorObjectHandleData(array_unique($phids));
- $loader->setViewer($this->viewer);
- $handles = $loader->loadHandles();
- foreach ($commits_data as $data) {
- if ($data->getCommitDetail('authorPHID')) {
- $commit_identifier =
- $commits[$data->getCommitID()]->getCommitIdentifier();
- $blame_dict[$commit_identifier]['handle'] =
- $handles[$data->getCommitDetail('authorPHID')];
+ foreach ($commits_data as $data) {
+ $author_phid = $data->getCommitDetail('authorPHID');
+ if (!$author_phid) {
+ continue;
+ }
+ $commit = $commits[$data->getCommitID()];
+ $commit_identifier = $commit->getCommitIdentifier();
+ $blame_dict[$commit_identifier]['authorPHID'] = $author_phid;
}
}
+
}
return array($text_list, $rev_list, $blame_dict);
}
abstract protected function tokenizeLine($line);
public function setNeedsBlame($needs_blame) {
$this->needsBlame = $needs_blame;
return $this;
}
public function getNeedsBlame() {
return $this->needsBlame;
}
public function setViewer(PhabricatorUser $user) {
$this->viewer = $user;
return $this;
}
protected function processRevList(array $rev_list) {
return $rev_list;
}
}
diff --git a/src/applications/diffusion/query/filecontent/DiffusionGitFileContentQuery.php b/src/applications/diffusion/query/filecontent/DiffusionGitFileContentQuery.php
index 4703937371..30e10c9177 100644
--- a/src/applications/diffusion/query/filecontent/DiffusionGitFileContentQuery.php
+++ b/src/applications/diffusion/query/filecontent/DiffusionGitFileContentQuery.php
@@ -1,49 +1,52 @@
<?php
final class DiffusionGitFileContentQuery extends DiffusionFileContentQuery {
- protected function executeQuery() {
+ public function getFileContentFuture() {
$drequest = $this->getRequest();
$repository = $drequest->getRepository();
$path = $drequest->getPath();
$commit = $drequest->getCommit();
if ($this->getNeedsBlame()) {
- list($corpus) = $repository->execxLocalCommand(
+ return $repository->getLocalCommandFuture(
'--no-pager blame -c -l --date=short %s -- %s',
$commit,
$path);
} else {
- list($corpus) = $repository->execxLocalCommand(
+ return $repository->getLocalCommandFuture(
'cat-file blob %s:%s',
$commit,
$path);
}
+ }
+
+ protected function executeQueryFromFuture(Future $future) {
+ list($corpus) = $future->resolvex();
$file_content = new DiffusionFileContent();
$file_content->setCorpus($corpus);
return $file_content;
}
-
protected function tokenizeLine($line) {
$m = array();
// sample lines:
//
// d1b4fcdd2a7c8c0f8cbdd01ca839d992135424dc
// ( hzhao 2009-05-01 202)function print();
//
// 8220d5d54f6d5d5552a636576cbe9c35f15b65b2
// (Andrew Gallagher 2010-12-03 324)
// // Add the lines for trailing context
preg_match('/^\s*?(\S+?)\s*\(\s*([^)]*)\s+\d{4}-\d{2}-\d{2}\s+\d+\)(.*)?$/',
$line, $m);
$rev_id = $m[1];
$author = $m[2];
$text = idx($m, 3);
return array($rev_id, $author, $text);
}
}
diff --git a/src/applications/diffusion/query/filecontent/DiffusionMercurialFileContentQuery.php b/src/applications/diffusion/query/filecontent/DiffusionMercurialFileContentQuery.php
index 512a427253..c97b53e75a 100644
--- a/src/applications/diffusion/query/filecontent/DiffusionMercurialFileContentQuery.php
+++ b/src/applications/diffusion/query/filecontent/DiffusionMercurialFileContentQuery.php
@@ -1,74 +1,78 @@
<?php
final class DiffusionMercurialFileContentQuery
extends DiffusionFileContentQuery {
- protected function executeQuery() {
+ public function getFileContentFuture() {
$drequest = $this->getRequest();
$repository = $drequest->getRepository();
$path = $drequest->getPath();
$commit = $drequest->getCommit();
if ($this->getNeedsBlame()) {
// NOTE: We're using "--number" instead of "--changeset" because there is
// no way to get "--changeset" to show us the full commit hashes.
- list($corpus) = $repository->execxLocalCommand(
+ return $repository->getLocalCommandFuture(
'annotate --user --number --rev %s -- %s',
$commit,
$path);
} else {
- list($corpus) = $repository->execxLocalCommand(
+ return $repository->getLocalCommandFuture(
'cat --rev %s -- %s',
$commit,
$path);
}
+ }
+
+ protected function executeQueryFromFuture(Future $future) {
+ list($corpus) = $future->resolvex();
$file_content = new DiffusionFileContent();
$file_content->setCorpus($corpus);
return $file_content;
}
protected function tokenizeLine($line) {
$matches = null;
preg_match(
'/^(.*?)\s+([0-9]+): (.*)$/',
$line,
$matches);
return array($matches[2], $matches[1], $matches[3]);
}
/**
* Convert local revision IDs into full commit identifier hashes.
*/
protected function processRevList(array $rev_list) {
$drequest = $this->getRequest();
$repository = $drequest->getRepository();
$revs = array_unique($rev_list);
foreach ($revs as $key => $rev) {
$revs[$key] = '--rev '.(int)$rev;
}
list($stdout) = $repository->execxLocalCommand(
'log --template=%s %C',
'{rev} {node}\\n',
implode(' ', $revs));
$map = array();
foreach (explode("\n", trim($stdout)) as $line) {
list($rev, $node) = explode(' ', $line);
$map[$rev] = $node;
}
foreach ($rev_list as $k => $rev) {
$rev_list[$k] = $map[$rev];
}
return $rev_list;
}
}
diff --git a/src/applications/diffusion/query/filecontent/DiffusionSvnFileContentQuery.php b/src/applications/diffusion/query/filecontent/DiffusionSvnFileContentQuery.php
index 8cb6c10dc9..8c37389d19 100644
--- a/src/applications/diffusion/query/filecontent/DiffusionSvnFileContentQuery.php
+++ b/src/applications/diffusion/query/filecontent/DiffusionSvnFileContentQuery.php
@@ -1,55 +1,59 @@
<?php
final class DiffusionSvnFileContentQuery extends DiffusionFileContentQuery {
- protected function executeQuery() {
+ public function getFileContentFuture() {
$drequest = $this->getRequest();
$repository = $drequest->getRepository();
$path = $drequest->getPath();
$commit = $drequest->getCommit();
$remote_uri = $repository->getRemoteURI();
+ return $repository->getRemoteCommandFuture(
+ '%C %s%s@%s',
+ $this->getNeedsBlame() ? 'blame --force' : 'cat',
+ $remote_uri,
+ phutil_escape_uri($path),
+ $commit);
+ }
+
+ protected function executeQueryFromFuture(Future $future) {
try {
- list($corpus) = $repository->execxRemoteCommand(
- '%C %s%s@%s',
- $this->getNeedsBlame() ? 'blame --force' : 'cat',
- $remote_uri,
- phutil_escape_uri($path),
- $commit);
+ list($corpus) = $future->resolvex();
} catch (CommandException $ex) {
$stderr = $ex->getStdErr();
if (preg_match('/path not found$/', trim($stderr))) {
// TODO: Improve user experience for this. One way to end up here
// is to have the parser behind and look at a file which was recently
// nuked; Diffusion will think it still exists and try to grab content
// at HEAD.
throw new Exception(
"Failed to retrieve file content from Subversion. The file may ".
"have been recently deleted, or the Diffusion cache may be out of ".
"date.");
} else {
throw $ex;
}
}
$file_content = new DiffusionFileContent();
$file_content->setCorpus($corpus);
return $file_content;
}
protected function tokenizeLine($line) {
// sample line:
// 347498 yliu function print();
$m = array();
preg_match('/^\s*(\d+)\s+(\S+)(?: (.*))?$/', $line, $m);
$rev_id = $m[1];
$author = $m[2];
$text = idx($m, 3);
return array($rev_id, $author, $text);
}
}
diff --git a/src/infrastructure/storage/patch/PhabricatorBuiltinPatchList.php b/src/infrastructure/storage/patch/PhabricatorBuiltinPatchList.php
index e3ea4e2eec..2d4d5ec191 100644
--- a/src/infrastructure/storage/patch/PhabricatorBuiltinPatchList.php
+++ b/src/infrastructure/storage/patch/PhabricatorBuiltinPatchList.php
@@ -1,1167 +1,1171 @@
<?php
final class PhabricatorBuiltinPatchList extends PhabricatorSQLPatchList {
public function getNamespace() {
return 'phabricator';
}
private function getPatchPath($file) {
$root = dirname(phutil_get_library_root('phabricator'));
$path = $root.'/resources/sql/patches/'.$file;
// Make sure it exists.
Filesystem::readFile($path);
return $path;
}
public function getPatches() {
return array(
'db.audit' => array(
'type' => 'db',
'name' => 'audit',
'after' => array( /* First Patch */ ),
),
'db.calendar' => array(
'type' => 'db',
'name' => 'calendar',
),
'db.chatlog' => array(
'type' => 'db',
'name' => 'chatlog',
),
'db.conduit' => array(
'type' => 'db',
'name' => 'conduit',
),
'db.countdown' => array(
'type' => 'db',
'name' => 'countdown',
),
'db.daemon' => array(
'type' => 'db',
'name' => 'daemon',
),
'db.differential' => array(
'type' => 'db',
'name' => 'differential',
),
'db.draft' => array(
'type' => 'db',
'name' => 'draft',
),
'db.drydock' => array(
'type' => 'db',
'name' => 'drydock',
),
'db.feed' => array(
'type' => 'db',
'name' => 'feed',
),
'db.file' => array(
'type' => 'db',
'name' => 'file',
),
'db.flag' => array(
'type' => 'db',
'name' => 'flag',
),
'db.harbormaster' => array(
'type' => 'db',
'name' => 'harbormaster',
),
'db.herald' => array(
'type' => 'db',
'name' => 'herald',
),
'db.maniphest' => array(
'type' => 'db',
'name' => 'maniphest',
),
'db.meta_data' => array(
'type' => 'db',
'name' => 'meta_data',
),
'db.metamta' => array(
'type' => 'db',
'name' => 'metamta',
),
'db.oauth_server' => array(
'type' => 'db',
'name' => 'oauth_server',
),
'db.owners' => array(
'type' => 'db',
'name' => 'owners',
),
'db.pastebin' => array(
'type' => 'db',
'name' => 'pastebin',
),
'db.phame' => array(
'type' => 'db',
'name' => 'phame',
),
'db.phriction' => array(
'type' => 'db',
'name' => 'phriction',
),
'db.project' => array(
'type' => 'db',
'name' => 'project',
),
'db.repository' => array(
'type' => 'db',
'name' => 'repository',
),
'db.search' => array(
'type' => 'db',
'name' => 'search',
),
'db.slowvote' => array(
'type' => 'db',
'name' => 'slowvote',
),
'db.timeline' => array(
'type' => 'db',
'name' => 'timeline',
),
'db.user' => array(
'type' => 'db',
'name' => 'user',
),
'db.worker' => array(
'type' => 'db',
'name' => 'worker',
),
'db.xhpastview' => array(
'type' => 'db',
'name' => 'xhpastview',
),
'db.cache' => array(
'type' => 'db',
'name' => 'cache',
),
'db.fact' => array(
'type' => 'db',
'name' => 'fact',
),
'db.ponder' => array(
'type' => 'db',
'name' => 'ponder',
),
'db.xhprof' => array(
'type' => 'db',
'name' => 'xhprof',
),
'db.pholio' => array(
'type' => 'db',
'name' => 'pholio',
),
'db.conpherence' => array(
'type' => 'db',
'name' => 'conpherence',
),
'db.config' => array(
'type' => 'db',
'name' => 'config',
),
'db.token' => array(
'type' => 'db',
'name' => 'token',
),
'0000.legacy.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('0000.legacy.sql'),
'legacy' => 0,
),
'000.project.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('000.project.sql'),
'legacy' => 0,
),
'001.maniphest_projects.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('001.maniphest_projects.sql'),
'legacy' => 1,
),
'002.oauth.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('002.oauth.sql'),
'legacy' => 2,
),
'003.more_oauth.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('003.more_oauth.sql'),
'legacy' => 3,
),
'004.daemonrepos.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('004.daemonrepos.sql'),
'legacy' => 4,
),
'005.workers.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('005.workers.sql'),
'legacy' => 5,
),
'006.repository.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('006.repository.sql'),
'legacy' => 6,
),
'007.daemonlog.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('007.daemonlog.sql'),
'legacy' => 7,
),
'008.repoopt.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('008.repoopt.sql'),
'legacy' => 8,
),
'009.repo_summary.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('009.repo_summary.sql'),
'legacy' => 9,
),
'010.herald.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('010.herald.sql'),
'legacy' => 10,
),
'011.badcommit.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('011.badcommit.sql'),
'legacy' => 11,
),
'012.dropphidtype.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('012.dropphidtype.sql'),
'legacy' => 12,
),
'013.commitdetail.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('013.commitdetail.sql'),
'legacy' => 13,
),
'014.shortcuts.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('014.shortcuts.sql'),
'legacy' => 14,
),
'015.preferences.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('015.preferences.sql'),
'legacy' => 15,
),
'016.userrealnameindex.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('016.userrealnameindex.sql'),
'legacy' => 16,
),
'017.sessionkeys.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('017.sessionkeys.sql'),
'legacy' => 17,
),
'018.owners.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('018.owners.sql'),
'legacy' => 18,
),
'019.arcprojects.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('019.arcprojects.sql'),
'legacy' => 19,
),
'020.pathcapital.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('020.pathcapital.sql'),
'legacy' => 20,
),
'021.xhpastview.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('021.xhpastview.sql'),
'legacy' => 21,
),
'022.differentialcommit.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('022.differentialcommit.sql'),
'legacy' => 22,
),
'023.dxkeys.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('023.dxkeys.sql'),
'legacy' => 23,
),
'024.mlistkeys.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('024.mlistkeys.sql'),
'legacy' => 24,
),
'025.commentopt.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('025.commentopt.sql'),
'legacy' => 25,
),
'026.diffpropkey.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('026.diffpropkey.sql'),
'legacy' => 26,
),
'027.metamtakeys.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('027.metamtakeys.sql'),
'legacy' => 27,
),
'028.systemagent.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('028.systemagent.sql'),
'legacy' => 28,
),
'029.cursors.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('029.cursors.sql'),
'legacy' => 29,
),
'030.imagemacro.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('030.imagemacro.sql'),
'legacy' => 30,
),
'031.workerrace.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('031.workerrace.sql'),
'legacy' => 31,
),
'032.viewtime.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('032.viewtime.sql'),
'legacy' => 32,
),
'033.privtest.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('033.privtest.sql'),
'legacy' => 33,
),
'034.savedheader.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('034.savedheader.sql'),
'legacy' => 34,
),
'035.proxyimage.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('035.proxyimage.sql'),
'legacy' => 35,
),
'036.mailkey.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('036.mailkey.sql'),
'legacy' => 36,
),
'037.setuptest.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('037.setuptest.sql'),
'legacy' => 37,
),
'038.admin.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('038.admin.sql'),
'legacy' => 38,
),
'039.userlog.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('039.userlog.sql'),
'legacy' => 39,
),
'040.transform.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('040.transform.sql'),
'legacy' => 40,
),
'041.heraldrepetition.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('041.heraldrepetition.sql'),
'legacy' => 41,
),
'042.commentmetadata.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('042.commentmetadata.sql'),
'legacy' => 42,
),
'043.pastebin.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('043.pastebin.sql'),
'legacy' => 43,
),
'044.countdown.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('044.countdown.sql'),
'legacy' => 44,
),
'045.timezone.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('045.timezone.sql'),
'legacy' => 45,
),
'046.conduittoken.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('046.conduittoken.sql'),
'legacy' => 46,
),
'047.projectstatus.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('047.projectstatus.sql'),
'legacy' => 47,
),
'048.relationshipkeys.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('048.relationshipkeys.sql'),
'legacy' => 48,
),
'049.projectowner.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('049.projectowner.sql'),
'legacy' => 49,
),
'050.taskdenormal.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('050.taskdenormal.sql'),
'legacy' => 50,
),
'051.projectfilter.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('051.projectfilter.sql'),
'legacy' => 51,
),
'052.pastelanguage.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('052.pastelanguage.sql'),
'legacy' => 52,
),
'053.feed.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('053.feed.sql'),
'legacy' => 53,
),
'054.subscribers.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('054.subscribers.sql'),
'legacy' => 54,
),
'055.add_author_to_files.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('055.add_author_to_files.sql'),
'legacy' => 55,
),
'056.slowvote.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('056.slowvote.sql'),
'legacy' => 56,
),
'057.parsecache.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('057.parsecache.sql'),
'legacy' => 57,
),
'058.missingkeys.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('058.missingkeys.sql'),
'legacy' => 58,
),
'059.engines.php' => array(
'type' => 'php',
'name' => $this->getPatchPath('059.engines.php'),
'legacy' => 59,
),
'060.phriction.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('060.phriction.sql'),
'legacy' => 60,
),
'061.phrictioncontent.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('061.phrictioncontent.sql'),
'legacy' => 61,
),
'062.phrictionmenu.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('062.phrictionmenu.sql'),
'legacy' => 62,
),
'063.pasteforks.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('063.pasteforks.sql'),
'legacy' => 63,
),
'064.subprojects.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('064.subprojects.sql'),
'legacy' => 64,
),
'065.sshkeys.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('065.sshkeys.sql'),
'legacy' => 65,
),
'066.phrictioncontent.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('066.phrictioncontent.sql'),
'legacy' => 66,
),
'067.preferences.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('067.preferences.sql'),
'legacy' => 67,
),
'068.maniphestauxiliarystorage.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('068.maniphestauxiliarystorage.sql'),
'legacy' => 68,
),
'069.heraldxscript.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('069.heraldxscript.sql'),
'legacy' => 69,
),
'070.differentialaux.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('070.differentialaux.sql'),
'legacy' => 70,
),
'071.contentsource.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('071.contentsource.sql'),
'legacy' => 71,
),
'072.blamerevert.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('072.blamerevert.sql'),
'legacy' => 72,
),
'073.reposymbols.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('073.reposymbols.sql'),
'legacy' => 73,
),
'074.affectedpath.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('074.affectedpath.sql'),
'legacy' => 74,
),
'075.revisionhash.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('075.revisionhash.sql'),
'legacy' => 75,
),
'076.indexedlanguages.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('076.indexedlanguages.sql'),
'legacy' => 76,
),
'077.originalemail.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('077.originalemail.sql'),
'legacy' => 77,
),
'078.nametoken.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('078.nametoken.sql'),
'legacy' => 78,
),
'079.nametokenindex.php' => array(
'type' => 'php',
'name' => $this->getPatchPath('079.nametokenindex.php'),
'legacy' => 79,
),
'080.filekeys.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('080.filekeys.sql'),
'legacy' => 80,
),
'081.filekeys.php' => array(
'type' => 'php',
'name' => $this->getPatchPath('081.filekeys.php'),
'legacy' => 81,
),
'082.xactionkey.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('082.xactionkey.sql'),
'legacy' => 82,
),
'083.dxviewtime.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('083.dxviewtime.sql'),
'legacy' => 83,
),
'084.pasteauthorkey.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('084.pasteauthorkey.sql'),
'legacy' => 84,
),
'085.packagecommitrelationship.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('085.packagecommitrelationship.sql'),
'legacy' => 85,
),
'086.formeraffil.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('086.formeraffil.sql'),
'legacy' => 86,
),
'087.phrictiondelete.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('087.phrictiondelete.sql'),
'legacy' => 87,
),
'088.audit.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('088.audit.sql'),
'legacy' => 88,
),
'089.projectwiki.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('089.projectwiki.sql'),
'legacy' => 89,
),
'090.forceuniqueprojectnames.php' => array(
'type' => 'php',
'name' => $this->getPatchPath('090.forceuniqueprojectnames.php'),
'legacy' => 90,
),
'091.uniqueslugkey.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('091.uniqueslugkey.sql'),
'legacy' => 91,
),
'092.dropgithubnotification.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('092.dropgithubnotification.sql'),
'legacy' => 92,
),
'093.gitremotes.php' => array(
'type' => 'php',
'name' => $this->getPatchPath('093.gitremotes.php'),
'legacy' => 93,
),
'094.phrictioncolumn.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('094.phrictioncolumn.sql'),
'legacy' => 94,
),
'095.directory.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('095.directory.sql'),
'legacy' => 95,
),
'096.filename.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('096.filename.sql'),
'legacy' => 96,
),
'097.heraldruletypes.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('097.heraldruletypes.sql'),
'legacy' => 97,
),
'098.heraldruletypemigration.php' => array(
'type' => 'php',
'name' => $this->getPatchPath('098.heraldruletypemigration.php'),
'legacy' => 98,
),
'099.drydock.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('099.drydock.sql'),
'legacy' => 99,
),
'100.projectxaction.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('100.projectxaction.sql'),
'legacy' => 100,
),
'101.heraldruleapplied.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('101.heraldruleapplied.sql'),
'legacy' => 101,
),
'102.heraldcleanup.php' => array(
'type' => 'php',
'name' => $this->getPatchPath('102.heraldcleanup.php'),
'legacy' => 102,
),
'103.heraldedithistory.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('103.heraldedithistory.sql'),
'legacy' => 103,
),
'104.searchkey.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('104.searchkey.sql'),
'legacy' => 104,
),
'105.mimetype.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('105.mimetype.sql'),
'legacy' => 105,
),
'106.chatlog.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('106.chatlog.sql'),
'legacy' => 106,
),
'107.oauthserver.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('107.oauthserver.sql'),
'legacy' => 107,
),
'108.oauthscope.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('108.oauthscope.sql'),
'legacy' => 108,
),
'109.oauthclientphidkey.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('109.oauthclientphidkey.sql'),
'legacy' => 109,
),
'110.commitaudit.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('110.commitaudit.sql'),
'legacy' => 110,
),
'111.commitauditmigration.php' => array(
'type' => 'php',
'name' => $this->getPatchPath('111.commitauditmigration.php'),
'legacy' => 111,
),
'112.oauthaccesscoderedirecturi.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('112.oauthaccesscoderedirecturi.sql'),
'legacy' => 112,
),
'113.lastreviewer.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('113.lastreviewer.sql'),
'legacy' => 113,
),
'114.auditrequest.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('114.auditrequest.sql'),
'legacy' => 114,
),
'115.prepareutf8.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('115.prepareutf8.sql'),
'legacy' => 115,
),
'116.utf8-backup-first-expect-wait.sql' => array(
'type' => 'sql',
'name' =>
$this->getPatchPath('116.utf8-backup-first-expect-wait.sql'),
'legacy' => 116,
),
'117.repositorydescription.php' => array(
'type' => 'php',
'name' => $this->getPatchPath('117.repositorydescription.php'),
'legacy' => 117,
),
'118.auditinline.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('118.auditinline.sql'),
'legacy' => 118,
),
'119.filehash.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('119.filehash.sql'),
'legacy' => 119,
),
'120.noop.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('120.noop.sql'),
'legacy' => 120,
),
'121.drydocklog.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('121.drydocklog.sql'),
'legacy' => 121,
),
'122.flag.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('122.flag.sql'),
'legacy' => 122,
),
'123.heraldrulelog.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('123.heraldrulelog.sql'),
'legacy' => 123,
),
'124.subpriority.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('124.subpriority.sql'),
'legacy' => 124,
),
'125.ipv6.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('125.ipv6.sql'),
'legacy' => 125,
),
'126.edges.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('126.edges.sql'),
'legacy' => 126,
),
'127.userkeybody.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('127.userkeybody.sql'),
'legacy' => 127,
),
'128.phabricatorcom.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('128.phabricatorcom.sql'),
'legacy' => 128,
),
'129.savedquery.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('129.savedquery.sql'),
'legacy' => 129,
),
'130.denormalrevisionquery.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('130.denormalrevisionquery.sql'),
'legacy' => 130,
),
'131.migraterevisionquery.php' => array(
'type' => 'php',
'name' => $this->getPatchPath('131.migraterevisionquery.php'),
'legacy' => 131,
),
'132.phame.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('132.phame.sql'),
'legacy' => 132,
),
'133.imagemacro.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('133.imagemacro.sql'),
'legacy' => 133,
),
'134.emptysearch.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('134.emptysearch.sql'),
'legacy' => 134,
),
'135.datecommitted.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('135.datecommitted.sql'),
'legacy' => 135,
),
'136.sex.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('136.sex.sql'),
'legacy' => 136,
),
'137.auditmetadata.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('137.auditmetadata.sql'),
'legacy' => 137,
),
'138.notification.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('138.notification.sql'),
),
'holidays.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('holidays.sql'),
),
'userstatus.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('userstatus.sql'),
),
'emailtable.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('emailtable.sql'),
),
'emailtableport.sql' => array(
'type' => 'php',
'name' => $this->getPatchPath('emailtableport.php'),
),
'emailtableremove.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('emailtableremove.sql'),
),
'phiddrop.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('phiddrop.sql'),
),
'testdatabase.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('testdatabase.sql'),
),
'ldapinfo.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('ldapinfo.sql'),
),
'threadtopic.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('threadtopic.sql'),
),
'usertranslation.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('usertranslation.sql'),
),
'differentialbookmarks.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('differentialbookmarks.sql'),
),
'harbormasterobject.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('harbormasterobject.sql'),
),
'markupcache.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('markupcache.sql'),
),
'maniphestxcache.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('maniphestxcache.sql'),
),
'migrate-maniphest-dependencies.php' => array(
'type' => 'php',
'name' => $this->getPatchPath('migrate-maniphest-dependencies.php'),
),
'migrate-differential-dependencies.php' => array(
'type' => 'php',
'name' => $this->getPatchPath(
'migrate-differential-dependencies.php'),
),
'phameblog.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('phameblog.sql'),
),
'migrate-maniphest-revisions.php' => array(
'type' => 'php',
'name' => $this->getPatchPath('migrate-maniphest-revisions.php'),
),
'daemonstatus.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('daemonstatus.sql'),
),
'symbolcontexts.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('symbolcontexts.sql'),
),
'migrate-project-edges.php' => array(
'type' => 'php',
'name' => $this->getPatchPath('migrate-project-edges.php'),
),
'fact-raw.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('fact-raw.sql'),
),
'ponder.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('ponder.sql')
),
'policy-project.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('policy-project.sql'),
),
'daemonstatuskey.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('daemonstatuskey.sql'),
),
'edgetype.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('edgetype.sql'),
),
'ponder-comments.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('ponder-comments.sql'),
),
'pastepolicy.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('pastepolicy.sql'),
),
'xhprof.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('xhprof.sql'),
),
'draft-metadata.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('draft-metadata.sql'),
),
'phamedomain.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('phamedomain.sql'),
),
'ponder-mailkey.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('ponder-mailkey.sql'),
),
'ponder-mailkey-populate.php' => array(
'type' => 'php',
'name' => $this->getPatchPath('ponder-mailkey-populate.php'),
),
'phamepolicy.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('phamepolicy.sql'),
),
'phameoneblog.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('phameoneblog.sql'),
),
'statustxt.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('statustxt.sql'),
),
'daemontaskarchive.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('daemontaskarchive.sql'),
),
'drydocktaskid.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('drydocktaskid.sql'),
),
'drydockresoucetype.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('drydockresourcetype.sql'),
),
'liskcounters.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('liskcounters.sql'),
),
'liskcounters.php' => array(
'type' => 'php',
'name' => $this->getPatchPath('liskcounters.php'),
),
'dropfileproxyimage.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('dropfileproxyimage.sql'),
),
'repository-lint.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('repository-lint.sql'),
),
'liskcounters-task.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('liskcounters-task.sql'),
),
'pholio.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('pholio.sql'),
),
'owners-exclude.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('owners-exclude.sql'),
),
'20121209.pholioxactions.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20121209.pholioxactions.sql'),
),
'20121209.xmacroadd.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20121209.xmacroadd.sql'),
),
'20121209.xmacromigrate.php' => array(
'type' => 'php',
'name' => $this->getPatchPath('20121209.xmacromigrate.php'),
),
'20121209.xmacromigratekey.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20121209.xmacromigratekey.sql'),
),
'20121220.generalcache.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20121220.generalcache.sql'),
),
'20121226.config.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20121226.config.sql'),
),
'20130101.confxaction.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130101.confxaction.sql'),
),
'20130102.metamtareceivedmailmessageidhash.sql' => array(
'type' => 'sql',
'name' =>
$this->getPatchPath('20130102.metamtareceivedmailmessageidhash.sql'),
),
'20130103.filemetadata.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130103.filemetadata.sql'),
),
'20130111.conpherence.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130111.conpherence.sql'),
),
'20130127.altheraldtranscript.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130127.altheraldtranscript.sql'),
),
'20130201.revisionunsubscribed.php' => array(
'type' => 'php',
'name' => $this->getPatchPath('20130201.revisionunsubscribed.php'),
),
'20130201.revisionunsubscribed.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130201.revisionunsubscribed.sql'),
),
'20130131.conpherencepics.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130131.conpherencepics.sql'),
),
'20130214.chatlogchannel.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130214.chatlogchannel.sql'),
),
'20130214.chatlogchannelid.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130214.chatlogchannelid.sql'),
),
'20130214.token.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130214.token.sql'),
),
'20130215.phabricatorfileaddttl.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130215.phabricatorfileaddttl.sql'),
),
'20130217.cachettl.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130217.cachettl.sql'),
),
'20130218.updatechannelid.php' => array(
'type' => 'php',
'name' => $this->getPatchPath('20130218.updatechannelid.php'),
),
'20130218.longdaemon.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130218.longdaemon.sql'),
),
'20130219.commitsummary.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130219.commitsummary.sql'),
),
'20130219.commitsummarymig.php' => array(
'type' => 'php',
'name' => $this->getPatchPath('20130219.commitsummarymig.php'),
),
'20130222.dropchannel.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130222.dropchannel.sql'),
),
'20130226.commitkey.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130226.commitkey.sql'),
),
'20131302.maniphestvalue.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20131302.maniphestvalue.sql'),
),
+ '20130304.lintauthor.sql' => array(
+ 'type' => 'sql',
+ 'name' => $this->getPatchPath('20130304.lintauthor.sql'),
+ ),
);
}
}

File Metadata

Mime Type
text/x-diff
Expires
Thu, Nov 13, 7:02 PM (10 h, 4 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
336491
Default Alt Text
(100 KB)

Event Timeline