Page MenuHomestyx hydra

No OneTemporary

diff --git a/src/applications/diffusion/controller/file/DiffusionBrowseFileController.php b/src/applications/diffusion/controller/file/DiffusionBrowseFileController.php
index a6f5ca6322..f2ac3271ae 100644
--- a/src/applications/diffusion/controller/file/DiffusionBrowseFileController.php
+++ b/src/applications/diffusion/controller/file/DiffusionBrowseFileController.php
@@ -1,231 +1,258 @@
<?php
/*
* Copyright 2011 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
class DiffusionBrowseFileController extends DiffusionController {
public function processRequest() {
// Build the view selection form.
$select_map = array(
'highlighted' => 'View as Highlighted Text',
'blame' => 'View as Highlighted Text with Blame',
'plain' => 'View as Plain Text',
'plainblame' => 'View as Plain Text with Blame',
);
$request = $this->getRequest();
$selected = $request->getStr('view');
$select = '<select name="view">';
foreach ($select_map as $k => $v) {
$option = phutil_render_tag(
'option',
array(
'value' => $k,
'selected' => ($k == $selected) ? 'selected' : null,
),
phutil_escape_html($v));
$select .= $option;
}
$select .= '</select>';
$view_select_panel = new AphrontPanelView();
$view_select_form = phutil_render_tag(
'form',
array(
'action' => $request->getRequestURI(),
'method' => 'get',
'style' => 'display: inline',
),
$select.
'<button>view</button>');
$view_select_panel->appendChild($view_select_form);
// Build the content of the file.
$corpus = $this->buildCorpus($selected);
// Render the page.
$content = array();
$content[] = $this->buildCrumbs(
array(
'branch' => true,
'path' => true,
'view' => 'browse',
));
$content[] = $view_select_panel;
$content[] = $corpus;
$nav = $this->buildSideNav('browse', true);
$nav->appendChild($content);
return $this->buildStandardPageResponse(
$nav,
array(
'title' => 'Browse',
));
}
- public static function renderRevision(
- DiffusionRequest $drequest,
- $revision) {
-
- $callsign = $drequest->getCallsign();
-
- $name = 'r'.$callsign.$revision;
- return phutil_render_tag(
- 'a',
- array(
- 'href' => '/'.$name,
- ),
- $name
- );
- }
-
-
private function buildCorpus($selected) {
- $blame = ($selected == 'blame' || $selected == 'plainblame');
+ $needs_blame = ($selected == 'blame' || $selected == 'plainblame');
$file_query = DiffusionFileContentQuery::newFromDiffusionRequest(
$this->diffusionRequest);
- $file_query->setNeedsBlame($blame);
+ $file_query->setNeedsBlame($needs_blame);
+ $file_query->loadFileContent();
// TODO: image
// TODO: blame of blame.
switch ($selected) {
case 'plain':
- case 'plainblame':
$style =
"margin: 1em 2em; width: 90%; height: 80em; font-family: monospace";
$corpus = phutil_render_tag(
'textarea',
array(
'style' => $style,
),
phutil_escape_html($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];
+ $author = $blame_dict[$rev]['author'];
+ $rows[] =
+ sprintf("%-10s %-15s %s", substr($rev, 0, 7), $author, $line);
+ }
+
+ $corpus = phutil_render_tag(
+ 'textarea',
+ array(
+ 'style' => $style,
+ ),
+ phutil_escape_html(implode("\n", $rows)));
+
+ break;
+
case 'highlighted':
case 'blame':
default:
require_celerity_resource('syntax-highlighting-css');
require_celerity_resource('diffusion-source-css');
- list($data, $blamedata, $revs) = $file_query->getTokenizedData();
+ list($text_list, $rev_list, $blame_dict) = $file_query->getBlameData();
$drequest = $this->getDiffusionRequest();
$path = $drequest->getPath();
$highlightEngine = new PhutilDefaultSyntaxHighlighterEngine();
- $data = $highlightEngine->highlightSource($path, $data);
- $data = explode("\n", rtrim($data));
+ $text_list = explode("\n", $highlightEngine->highlightSource($path,
+ implode("\n", $text_list)));
- $rows = $this->buildDisplayRows($data, $blame, $blamedata, $drequest,
- $revs);
+ $rows = $this->buildDisplayRows($text_list, $rev_list, $blame_dict,
+ $needs_blame, $drequest);
$corpus_table = phutil_render_tag(
'table',
array(
'class' => "diffusion-source remarkup-code PhabricatorMonospaced",
),
implode("\n", $rows));
$corpus = phutil_render_tag(
'div',
array(
'style' => 'padding: 0pt 2em;',
),
$corpus_table);
break;
}
return $corpus;
}
- private static function buildDisplayRows($data, $blame, $blamedata, $drequest,
- $revs) {
- $last = null;
+ private static function buildDisplayRows($text_list, $rev_list, $blame_dict,
+ $needs_blame, DiffusionRequest $drequest) {
+ $last_rev = null;
$color = null;
$rows = array();
$n = 1;
- foreach ($data as $k => $line) {
- if ($blame) {
- if ($last == $blamedata[$k][0]) {
- $blameinfo =
+
+ $epoch_list = ipull($blame_dict, 'epoch');
+ $max = max($epoch_list);
+ $min = min($epoch_list);
+ $range = $max - $min + 1;
+
+ foreach ($text_list as $k => $line) {
+ if ($needs_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 darker the color.
+ $rev = $rev_list[$k];
+ if ($last_rev == $rev) {
+ $blame_info =
'<th style="background: '.$color.'; width: 9em;"></th>'.
'<th style="background: '.$color.'"></th>';
} else {
- switch ($drequest->getRepository()->getVersionControlSystem()) {
- case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT:
- // TODO: better color for git.
- $color = '#dddddd';
- break;
- case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN:
- $color = sprintf(
- '#%02xee%02x',
- $revs[$blamedata[$k][0]],
- $revs[$blamedata[$k][0]]);
- break;
- default:
- throw new Exception('repository type not supported');
- }
+
+ $color_number = (int)(0xEE -
+ 0xEE * ($blame_dict[$rev]['epoch'] - $min) / $range);
+ $color = sprintf('#%02xee%02x', $color_number, $color_number);
+
$revision_link = self::renderRevision(
- $drequest,
- $blamedata[$k][0]);
+ $drequest,
+ substr($rev, 0, 7));
- $author_link = $blamedata[$k][1];
- $blameinfo =
+ $author_link = $blame_dict[$rev]['author'];
+ $blame_info =
'<th style="background: '.$color.
'; width: 9em;">'.$revision_link.'</th>'.
'<th style="background: '.$color.
'; font-weight: normal; color: #333;">'.$author_link.'</th>';
- $last = $blamedata[$k][0];
+ $last_rev = $rev;
}
} else {
- $blameinfo = null;
+ $blame_info = null;
}
+ // Highlight the line of interest if needed.
if ($n == $drequest->getLine()) {
$tr = '<tr style="background: #ffff00;">';
$targ = '<a id="scroll_target"></a>';
Javelin::initBehavior('diffusion-jump-to',
array('target' => 'scroll_target'));
} else {
$tr = '<tr>';
$targ = null;
}
+ // Create the row display.
$uri_path = $drequest->getUriPath();
$uri_rev = $drequest->getCommit();
$l = phutil_render_tag(
'a',
array(
'href' => $uri_path.';'.$uri_rev.'$'.$n,
),
$n);
- $rows[] = $tr.$blameinfo.'<th>'.$l.'</th><td>'.$targ.$line.'</td></tr>';
+ $rows[] = $tr.$blame_info.'<th>'.$l.'</th><td>'.$targ.$line.'</td></tr>';
++$n;
}
return $rows;
}
+
+
+ private static function renderRevision(DiffusionRequest $drequest,
+ $revision) {
+
+ $callsign = $drequest->getCallsign();
+
+ $name = 'r'.$callsign.$revision;
+ return phutil_render_tag(
+ 'a',
+ array(
+ 'href' => '/'.$name,
+ ),
+ $name
+ );
+ }
+
}
diff --git a/src/applications/diffusion/controller/file/__init__.php b/src/applications/diffusion/controller/file/__init__.php
index 7b85e05b1f..529bf8288a 100644
--- a/src/applications/diffusion/controller/file/__init__.php
+++ b/src/applications/diffusion/controller/file/__init__.php
@@ -1,20 +1,20 @@
<?php
/**
* This file is automatically generated. Lint this module to rebuild it.
* @generated
*/
phutil_require_module('phabricator', 'applications/diffusion/controller/base');
phutil_require_module('phabricator', 'applications/diffusion/query/filecontent/base');
-phutil_require_module('phabricator', 'applications/repository/constants/repositorytype');
phutil_require_module('phabricator', 'infrastructure/celerity/api');
phutil_require_module('phabricator', 'infrastructure/javelin/api');
phutil_require_module('phabricator', 'view/layout/panel');
phutil_require_module('phutil', 'markup');
phutil_require_module('phutil', 'markup/syntax/engine/default');
+phutil_require_module('phutil', 'utils');
phutil_require_source('DiffusionBrowseFileController.php');
diff --git a/src/applications/diffusion/query/filecontent/base/DiffusionFileContentQuery.php b/src/applications/diffusion/query/filecontent/base/DiffusionFileContentQuery.php
index a832e6cc77..42be58a645 100644
--- a/src/applications/diffusion/query/filecontent/base/DiffusionFileContentQuery.php
+++ b/src/applications/diffusion/query/filecontent/base/DiffusionFileContentQuery.php
@@ -1,81 +1,115 @@
<?php
/*
* Copyright 2011 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
abstract class DiffusionFileContentQuery {
private $request;
private $needsBlame;
+ private $fileContent;
final private function __construct() {
// <private>
}
final public static function newFromDiffusionRequest(
DiffusionRequest $request) {
$repository = $request->getRepository();
switch ($repository->getVersionControlSystem()) {
case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT:
$class = 'DiffusionGitFileContentQuery';
break;
case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN:
$class = 'DiffusionSvnFileContentQuery';
break;
default:
throw new Exception("Unsupported VCS!");
}
PhutilSymbolLoader::loadClass($class);
$query = new $class();
$query->request = $request;
return $query;
}
final protected function getRequest() {
return $this->request;
}
final public function loadFileContent() {
- return $this->executeQuery();
+ $this->fileContent = $this->executeQuery();
}
abstract protected function executeQuery();
final public function getRawData() {
- return $this->loadFileContent()->getCorpus();
+ return $this->fileContent->getCorpus();
}
- final public function getTokenizedData() {
- return $this->tokenizeData($this->getRawData());
+ final public function getBlameData() {
+ $raw_data = $this->getRawData();
+
+ $text_list = array();
+ $rev_list = array();
+ $blame_dict = array();
+
+ if (!$this->getNeedsBlame()) {
+ $text_list = explode("\n", rtrim($raw_data));
+ } else {
+ foreach (explode("\n", rtrim($raw_data)) as $k => $line) {
+ list($rev_id, $author, $text) = $this->tokenizeLine($line);
+
+ $text_list[$k] = $text;
+ $rev_list[$k] = $rev_id;
+
+ if (!isset($blame_dict[$rev_id]) &&
+ !isset($blame_dict[$rev_id]['author'] )) {
+ $blame_dict[$rev_id]['author'] = $author;
+ }
+ }
+
+ $repository = $this->getRequest()->getRepository();
+ $commits = id(new PhabricatorRepositoryCommit())->loadAllWhere(
+ 'repositoryID = %d AND commitIdentifier IN (%Ls)', $repository->getID(),
+ array_unique($rev_list));
+
+ foreach ($commits as $commit) {
+ $commitIdentifier = $commit->getCommitIdentifier();
+ $epoch = $commit->getEpoch();
+ $blame_dict[$commitIdentifier]['epoch'] = $epoch;
+ }
+ }
+
+ return array($text_list, $rev_list, $blame_dict);
}
- abstract protected function tokenizeData($data);
+ abstract protected function tokenizeLine($line);
public function setNeedsBlame($needs_blame)
{
$this->needsBlame = $needs_blame;
}
public function getNeedsBlame()
{
return $this->needsBlame;
}
}
diff --git a/src/applications/diffusion/query/filecontent/base/__init__.php b/src/applications/diffusion/query/filecontent/base/__init__.php
index f964d49824..7ad4326f05 100644
--- a/src/applications/diffusion/query/filecontent/base/__init__.php
+++ b/src/applications/diffusion/query/filecontent/base/__init__.php
@@ -1,14 +1,16 @@
<?php
/**
* This file is automatically generated. Lint this module to rebuild it.
* @generated
*/
phutil_require_module('phabricator', 'applications/repository/constants/repositorytype');
+phutil_require_module('phabricator', 'applications/repository/storage/commit');
phutil_require_module('phutil', 'symbols');
+phutil_require_module('phutil', 'utils');
phutil_require_source('DiffusionFileContentQuery.php');
diff --git a/src/applications/diffusion/query/filecontent/git/DiffusionGitFileContentQuery.php b/src/applications/diffusion/query/filecontent/git/DiffusionGitFileContentQuery.php
index 0465f6ccf0..9176fbfebb 100644
--- a/src/applications/diffusion/query/filecontent/git/DiffusionGitFileContentQuery.php
+++ b/src/applications/diffusion/query/filecontent/git/DiffusionGitFileContentQuery.php
@@ -1,80 +1,62 @@
<?php
/*
* Copyright 2011 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
final class DiffusionGitFileContentQuery extends DiffusionFileContentQuery {
protected function executeQuery() {
$drequest = $this->getRequest();
$repository = $drequest->getRepository();
$path = $drequest->getPath();
$commit = $drequest->getCommit();
$local_path = $repository->getDetail('local-path');
if ($this->getNeedsBlame()) {
list($corpus) = execx(
- '(cd %s && git --no-pager blame -c --date short %s -- %s)',
+ '(cd %s && git --no-pager blame -c -l --date short %s -- %s)',
$local_path,
$commit,
$path);
} else {
list($corpus) = execx(
'(cd %s && git cat-file blob %s:%s)',
$local_path,
$commit,
$path);
}
$file_content = new DiffusionFileContent();
$file_content->setCorpus($corpus);
return $file_content;
}
- protected function tokenizeData($data) {
- $m = array();
- $blamedata = array();
- $revs = array();
-
- if ($this->getNeedsBlame()) {
- $data = explode("\n", rtrim($data));
- foreach ($data as $k => $line) {
- // sample line:
- // d1b4fcdd ( hzhao 2009-05-01 202)function print();
- preg_match('/^\s*?(\S+?)\s*\(\s*(\S+)\s+\S+\s+\d+\)(.*)?$/',
- $line, $m);
- $data[$k] = idx($m, 3);
- $blamedata[$k] = array($m[1], $m[2]);
-
- $revs[$m[1]] = true;
- }
- $data = implode("\n", $data);
- krsort($revs);
- $ii = 0;
- $len = count($revs);
- foreach ($revs as $rev => $ignored) {
- $revs[$rev] = (int)(0xEE * ($ii / $len));
- ++$ii;
- }
- }
-
- return array($data, $blamedata, $revs);
+ protected function tokenizeLine($line) {
+ $m = array();
+ // sample line:
+ // d1b4fcdd2a7c8c0f8cbdd01ca839d992135424dc
+ // ( hzhao 2009-05-01 202)function print();
+ preg_match('/^\s*?(\S+?)\s*\(\s*(\S+)\s+\S+\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/svn/DiffusionSvnFileContentQuery.php b/src/applications/diffusion/query/filecontent/svn/DiffusionSvnFileContentQuery.php
index 27f1b05326..64e7f9f085 100644
--- a/src/applications/diffusion/query/filecontent/svn/DiffusionSvnFileContentQuery.php
+++ b/src/applications/diffusion/query/filecontent/svn/DiffusionSvnFileContentQuery.php
@@ -1,90 +1,71 @@
<?php
/*
* Copyright 2011 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
final class DiffusionSvnFileContentQuery extends DiffusionFileContentQuery {
protected function executeQuery() {
$drequest = $this->getRequest();
$repository = $drequest->getRepository();
$path = $drequest->getPath();
$commit = $drequest->getCommit();
$remote_uri = $repository->getDetail('remote-uri');
try {
list($corpus) = execx(
'svn --non-interactive %s %s%s@%s',
$this->getNeedsBlame() ? 'blame' : 'cat',
$remote_uri,
$path,
$commit);
} 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 tokenizeData($data)
- {
+ protected function tokenizeLine($line) {
+ // sample line:
+ // 347498 yliu function print();
$m = array();
- $blamedata = array();
- $revs = array();
+ preg_match('/^\s*(\d+)\s+(\S+)(?: (.*))?$/', $line, $m);
+ $rev_id = $m[1];
+ $author = $m[2];
+ $text = idx($m, 3);
- if ($this->getNeedsBlame()) {
- $data = explode("\n", rtrim($data));
- foreach ($data as $k => $line) {
- // sample line:
- // 347498 yliu function print();
- preg_match('/^\s*(\d+)\s+(\S+)(?: (.*))?$/', $line, $m);
- $data[$k] = idx($m, 3);
- $blamedata[$k] = array($m[1], $m[2]);
-
- $revs[$m[1]] = true;
- }
- $data = implode("\n", $data);
-
- krsort($revs);
- $ii = 0;
- $len = count($revs);
- foreach ($revs as $rev => $ignored) {
- $revs[$rev] = (int)(0xEE * ($ii / $len));
- ++$ii;
- }
- }
-
- return array($data, $blamedata, $revs);
+ return array($rev_id, $author, $text);
}
}

File Metadata

Mime Type
text/x-diff
Expires
Mon, Jul 28, 6:38 AM (1 w, 20 h ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
186464
Default Alt Text
(21 KB)

Event Timeline