Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F15423373
D9294.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
45 KB
Referenced Files
None
Subscribers
None
D9294.diff
View Options
diff --git a/resources/celerity/map.php b/resources/celerity/map.php
--- a/resources/celerity/map.php
+++ b/resources/celerity/map.php
@@ -11,7 +11,7 @@
'core.pkg.js' => '07b01d4f',
'darkconsole.pkg.js' => 'ca8671ce',
'differential.pkg.css' => '4a93db37',
- 'differential.pkg.js' => 'eca39a2c',
+ 'differential.pkg.js' => '2b128f3a',
'diffusion.pkg.css' => '471bc9eb',
'diffusion.pkg.js' => '077e3ad0',
'maniphest.pkg.css' => 'f88a8402',
@@ -358,13 +358,13 @@
'rsrc/js/application/dashboard/behavior-dashboard-move-panels.js' => 'fa187a68',
'rsrc/js/application/dashboard/behavior-dashboard-query-panel-select.js' => '3be3eef5',
'rsrc/js/application/dashboard/behavior-dashboard-tab-panel.js' => 'aa077691',
- 'rsrc/js/application/differential/ChangesetViewManager.js' => 'db09a523',
+ 'rsrc/js/application/differential/ChangesetViewManager.js' => '1f304ef8',
'rsrc/js/application/differential/DifferentialInlineCommentEditor.js' => 'f2441746',
'rsrc/js/application/differential/behavior-add-reviewers-and-ccs.js' => '533a187b',
'rsrc/js/application/differential/behavior-comment-jump.js' => '71755c79',
'rsrc/js/application/differential/behavior-comment-preview.js' => '127f2018',
'rsrc/js/application/differential/behavior-diff-radios.js' => 'e1ff79b1',
- 'rsrc/js/application/differential/behavior-dropdown-menus.js' => '64a79839',
+ 'rsrc/js/application/differential/behavior-dropdown-menus.js' => '710f209e',
'rsrc/js/application/differential/behavior-edit-inline-comments.js' => '00861799',
'rsrc/js/application/differential/behavior-keyboard-nav.js' => '173ce7e7',
'rsrc/js/application/differential/behavior-populate.js' => 'bdb3e4d0',
@@ -509,7 +509,7 @@
'aphront-two-column-view-css' => '16ab3ad2',
'aphront-typeahead-control-css' => 'a989b5b3',
'auth-css' => '1e655982',
- 'changeset-view-manager' => 'db09a523',
+ 'changeset-view-manager' => '1f304ef8',
'config-options-css' => '7fedf08b',
'conpherence-menu-css' => 'e1e0fdf1',
'conpherence-message-pane-css' => '11a393ca',
@@ -564,7 +564,7 @@
'javelin-behavior-differential-add-reviewers-and-ccs' => '533a187b',
'javelin-behavior-differential-comment-jump' => '71755c79',
'javelin-behavior-differential-diff-radios' => 'e1ff79b1',
- 'javelin-behavior-differential-dropdown-menus' => '64a79839',
+ 'javelin-behavior-differential-dropdown-menus' => '710f209e',
'javelin-behavior-differential-edit-inline-comments' => '00861799',
'javelin-behavior-differential-feedback-preview' => '127f2018',
'javelin-behavior-differential-keyboard-navigation' => '173ce7e7',
@@ -1001,6 +1001,17 @@
5 => 'phabricator-drag-and-drop-file-upload',
6 => 'phabricator-draggable-list',
),
+ '1f304ef8' =>
+ array(
+ 0 => 'javelin-dom',
+ 1 => 'javelin-util',
+ 2 => 'javelin-stratcom',
+ 3 => 'javelin-install',
+ 4 => 'javelin-workflow',
+ 5 => 'javelin-router',
+ 6 => 'javelin-behavior-device',
+ 7 => 'javelin-vector',
+ ),
'2290aeef' =>
array(
0 => 'javelin-install',
@@ -1273,11 +1284,6 @@
2 => 'javelin-util',
3 => 'phabricator-shaped-request',
),
- '7319e029' =>
- array(
- 0 => 'javelin-behavior',
- 1 => 'javelin-dom',
- ),
'62e18640' =>
array(
0 => 'javelin-install',
@@ -1291,18 +1297,6 @@
1 => 'javelin-dom',
2 => 'javelin-fx',
),
- '64a79839' =>
- array(
- 0 => 'javelin-behavior',
- 1 => 'javelin-dom',
- 2 => 'javelin-util',
- 3 => 'javelin-stratcom',
- 4 => 'phuix-dropdown-menu',
- 5 => 'phuix-action-list-view',
- 6 => 'phuix-action-view',
- 7 => 'phabricator-phtize',
- 8 => 'changeset-view-manager',
- ),
'64ef2fd2' =>
array(
0 => 'javelin-behavior',
@@ -1344,12 +1338,30 @@
1 => 'javelin-dom',
2 => 'javelin-util',
),
+ '710f209e' =>
+ array(
+ 0 => 'javelin-behavior',
+ 1 => 'javelin-dom',
+ 2 => 'javelin-util',
+ 3 => 'javelin-stratcom',
+ 4 => 'javelin-workflow',
+ 5 => 'phuix-dropdown-menu',
+ 6 => 'phuix-action-list-view',
+ 7 => 'phuix-action-view',
+ 8 => 'phabricator-phtize',
+ 9 => 'changeset-view-manager',
+ ),
'71755c79' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-stratcom',
2 => 'javelin-dom',
),
+ '7319e029' =>
+ array(
+ 0 => 'javelin-behavior',
+ 1 => 'javelin-dom',
+ ),
'76f4ebed' =>
array(
0 => 'javelin-install',
@@ -1916,17 +1928,6 @@
1 => 'javelin-util',
2 => 'javelin-stratcom',
),
- 'db09a523' =>
- array(
- 0 => 'javelin-dom',
- 1 => 'javelin-util',
- 2 => 'javelin-stratcom',
- 3 => 'javelin-install',
- 4 => 'javelin-workflow',
- 5 => 'javelin-router',
- 6 => 'javelin-behavior-device',
- 7 => 'javelin-vector',
- ),
'dd7e8ef5' =>
array(
0 => 'javelin-behavior',
diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -2258,6 +2258,8 @@
'PhabricatorSystemRemoveDestroyWorkflow' => 'applications/system/management/PhabricatorSystemRemoveDestroyWorkflow.php',
'PhabricatorSystemRemoveLogWorkflow' => 'applications/system/management/PhabricatorSystemRemoveLogWorkflow.php',
'PhabricatorSystemRemoveWorkflow' => 'applications/system/management/PhabricatorSystemRemoveWorkflow.php',
+ 'PhabricatorSystemSelectEncodingController' => 'applications/system/controller/PhabricatorSystemSelectEncodingController.php',
+ 'PhabricatorSystemSelectHighlightController' => 'applications/system/controller/PhabricatorSystemSelectHighlightController.php',
'PhabricatorTaskmasterDaemon' => 'infrastructure/daemon/workers/PhabricatorTaskmasterDaemon.php',
'PhabricatorTestCase' => 'infrastructure/testing/PhabricatorTestCase.php',
'PhabricatorTestController' => 'applications/base/controller/__tests__/PhabricatorTestController.php',
@@ -5134,6 +5136,8 @@
'PhabricatorSystemRemoveDestroyWorkflow' => 'PhabricatorSystemRemoveWorkflow',
'PhabricatorSystemRemoveLogWorkflow' => 'PhabricatorSystemRemoveWorkflow',
'PhabricatorSystemRemoveWorkflow' => 'PhabricatorManagementWorkflow',
+ 'PhabricatorSystemSelectEncodingController' => 'PhabricatorController',
+ 'PhabricatorSystemSelectHighlightController' => 'PhabricatorController',
'PhabricatorTaskmasterDaemon' => 'PhabricatorDaemon',
'PhabricatorTestCase' => 'ArcanistPhutilTestCase',
'PhabricatorTestController' => 'PhabricatorController',
diff --git a/src/applications/differential/controller/DifferentialChangesetViewController.php b/src/applications/differential/controller/DifferentialChangesetViewController.php
--- a/src/applications/differential/controller/DifferentialChangesetViewController.php
+++ b/src/applications/differential/controller/DifferentialChangesetViewController.php
@@ -155,6 +155,8 @@
$parser->setRightSideCommentMapping($right_source, $right_new);
$parser->setLeftSideCommentMapping($left_source, $left_new);
$parser->setWhitespaceMode($request->getStr('whitespace'));
+ $parser->setCharacterEncoding($request->getStr('encoding'));
+ $parser->setHighlightAs($request->getStr('highlight'));
if ($request->getStr('renderer') == '1up') {
$parser->setRenderer(new DifferentialChangesetOneUpRenderer());
diff --git a/src/applications/differential/parser/DifferentialChangesetParser.php b/src/applications/differential/parser/DifferentialChangesetParser.php
--- a/src/applications/differential/parser/DifferentialChangesetParser.php
+++ b/src/applications/differential/parser/DifferentialChangesetParser.php
@@ -41,6 +41,26 @@
private $highlightErrors;
private $disableCache;
private $renderer;
+ private $characterEncoding;
+ private $highlightAs;
+
+ public function setHighlightAs($highlight_as) {
+ $this->highlightAs = $highlight_as;
+ return $this;
+ }
+
+ public function getHighlightAs() {
+ return $this->highlightAs;
+ }
+
+ public function setCharacterEncoding($character_encoding) {
+ $this->characterEncoding = $character_encoding;
+ return $this;
+ }
+
+ public function getCharacterEncoding() {
+ return $this->characterEncoding;
+ }
public function setRenderer($renderer) {
$this->renderer = $renderer;
@@ -422,8 +442,15 @@
}
private function getHighlightFuture($corpus) {
+ $language = $this->highlightAs;
+
+ if (!$language) {
+ $language = $this->highlightEngine->getLanguageFromFilename(
+ $this->filename);
+ }
+
return $this->highlightEngine->getHighlightFuture(
- $this->highlightEngine->getLanguageFromFilename($this->filename),
+ $language,
$corpus);
}
@@ -455,6 +482,14 @@
$skip_cache = true;
}
+ if ($this->characterEncoding) {
+ $skip_cache = true;
+ }
+
+ if ($this->highlightAs) {
+ $skip_cache = true;
+ }
+
$this->whitespaceMode = $whitespace_mode;
$changeset = $this->changeset;
@@ -677,6 +712,25 @@
// requests.
$this->isTopLevel = (($range_start === null) && ($range_len === null));
$this->highlightEngine = PhabricatorSyntaxHighlighter::newEngine();
+
+ $encoding = null;
+ if ($this->characterEncoding) {
+ // We are forcing this changeset to be interpreted with a specific
+ // character encoding, so force all the hunks into that encoding and
+ // propagate it to the renderer.
+ $encoding = $this->characterEncoding;
+ foreach ($this->changeset->getHunks() as $hunk) {
+ $hunk->forceEncoding($this->characterEncoding);
+ }
+ } else {
+ // We're just using the default, so tell the renderer what that is
+ // (by reading the encoding from the first hunk).
+ foreach ($this->changeset->getHunks() as $hunk) {
+ $encoding = $hunk->getDataEncoding();
+ break;
+ }
+ }
+
$this->tryCacheStuff();
$render_pch = $this->shouldRenderPropertyChangeHeader($this->changeset);
@@ -700,7 +754,8 @@
->setMarkupEngine($this->markupEngine)
->setHandles($this->handles)
->setOldLines($this->old)
- ->setNewLines($this->new);
+ ->setNewLines($this->new)
+ ->setOriginalCharacterEncoding($encoding);
if ($this->user) {
$renderer->setUser($this->user);
@@ -1013,18 +1068,18 @@
private function isCommentVisibleOnRenderedDiff(
PhabricatorInlineCommentInterface $comment) {
- $changeset_id = $comment->getChangesetID();
- $is_new = $comment->getIsNewFile();
+ $changeset_id = $comment->getChangesetID();
+ $is_new = $comment->getIsNewFile();
- if ($changeset_id == $this->rightSideChangesetID &&
+ if ($changeset_id == $this->rightSideChangesetID &&
$is_new == $this->rightSideAttachesToNewFile) {
- return true;
- }
+ return true;
+ }
- if ($changeset_id == $this->leftSideChangesetID &&
+ if ($changeset_id == $this->leftSideChangesetID &&
$is_new == $this->leftSideAttachesToNewFile) {
- return true;
- }
+ return true;
+ }
return false;
}
diff --git a/src/applications/differential/render/DifferentialChangesetHTMLRenderer.php b/src/applications/differential/render/DifferentialChangesetHTMLRenderer.php
--- a/src/applications/differential/render/DifferentialChangesetHTMLRenderer.php
+++ b/src/applications/differential/render/DifferentialChangesetHTMLRenderer.php
@@ -9,248 +9,275 @@
$change = $changeset->getChangeType();
$file = $changeset->getFileType();
- $message = null;
- if ($change == DifferentialChangeType::TYPE_CHANGE &&
- $file == DifferentialChangeType::FILE_TEXT) {
- if ($force) {
- // We have to force something to render because there were no changes
- // of other kinds.
- $message = pht('This file was not modified.');
+ $messages = array();
+ $none = hsprintf('');
+ switch ($change) {
+
+ case DifferentialChangeType::TYPE_ADD:
+ switch ($file) {
+ case DifferentialChangeType::FILE_TEXT:
+ $messages[] = pht(
+ 'This file was <strong>added</strong>.',
+ $none);
+ break;
+ case DifferentialChangeType::FILE_IMAGE:
+ $messages[] = pht(
+ 'This image was <strong>added</strong>.',
+ $none);
+ break;
+ case DifferentialChangeType::FILE_DIRECTORY:
+ $messages[] = pht(
+ 'This directory was <strong>added</strong>.',
+ $none);
+ break;
+ case DifferentialChangeType::FILE_BINARY:
+ $messages[] = pht(
+ 'This binary file was <strong>added</strong>.',
+ $none);
+ break;
+ case DifferentialChangeType::FILE_SYMLINK:
+ $messages[] = pht(
+ 'This symlink was <strong>added</strong>.',
+ $none);
+ break;
+ case DifferentialChangeType::FILE_SUBMODULE:
+ $messages[] = pht(
+ 'This submodule was <strong>added</strong>.',
+ $none);
+ break;
+ }
+ break;
+
+ case DifferentialChangeType::TYPE_DELETE:
+ switch ($file) {
+ case DifferentialChangeType::FILE_TEXT:
+ $messages[] = pht(
+ 'This file was <strong>deleted</strong>.',
+ $none);
+ break;
+ case DifferentialChangeType::FILE_IMAGE:
+ $messages[] = pht(
+ 'This image was <strong>deleted</strong>.',
+ $none);
+ break;
+ case DifferentialChangeType::FILE_DIRECTORY:
+ $messages[] = pht(
+ 'This directory was <strong>deleted</strong>.',
+ $none);
+ break;
+ case DifferentialChangeType::FILE_BINARY:
+ $messages[] = pht(
+ 'This binary file was <strong>deleted</strong>.',
+ $none);
+ break;
+ case DifferentialChangeType::FILE_SYMLINK:
+ $messages[] = pht(
+ 'This symlink was <strong>deleted</strong>.',
+ $none);
+ break;
+ case DifferentialChangeType::FILE_SUBMODULE:
+ $messages[] = pht(
+ 'This submodule was <strong>deleted</strong>.',
+ $none);
+ break;
+ }
+ break;
+
+ case DifferentialChangeType::TYPE_MOVE_HERE:
+ $from = phutil_tag('strong', array(), $changeset->getOldFile());
+ switch ($file) {
+ case DifferentialChangeType::FILE_TEXT:
+ $messages[] = pht('This file was moved from %s.', $from);
+ break;
+ case DifferentialChangeType::FILE_IMAGE:
+ $messages[] = pht('This image was moved from %s.', $from);
+ break;
+ case DifferentialChangeType::FILE_DIRECTORY:
+ $messages[] = pht('This directory was moved from %s.', $from);
+ break;
+ case DifferentialChangeType::FILE_BINARY:
+ $messages[] = pht('This binary file was moved from %s.', $from);
+ break;
+ case DifferentialChangeType::FILE_SYMLINK:
+ $messages[] = pht('This symlink was moved from %s.', $from);
+ break;
+ case DifferentialChangeType::FILE_SUBMODULE:
+ $messages[] = pht('This submodule was moved from %s.', $from);
+ break;
+ }
+ break;
+
+ case DifferentialChangeType::TYPE_COPY_HERE:
+ $from = phutil_tag('strong', array(), $changeset->getOldFile());
+ switch ($file) {
+ case DifferentialChangeType::FILE_TEXT:
+ $messages[] = pht('This file was copied from %s.', $from);
+ break;
+ case DifferentialChangeType::FILE_IMAGE:
+ $messages[] = pht('This image was copied from %s.', $from);
+ break;
+ case DifferentialChangeType::FILE_DIRECTORY:
+ $messages[] = pht('This directory was copied from %s.', $from);
+ break;
+ case DifferentialChangeType::FILE_BINARY:
+ $messages[] = pht('This binary file was copied from %s.', $from);
+ break;
+ case DifferentialChangeType::FILE_SYMLINK:
+ $messages[] = pht('This symlink was copied from %s.', $from);
+ break;
+ case DifferentialChangeType::FILE_SUBMODULE:
+ $messages[] = pht('This submodule was copied from %s.', $from);
+ break;
+ }
+ break;
+
+ case DifferentialChangeType::TYPE_MOVE_AWAY:
+ $paths = phutil_tag(
+ 'strong',
+ array(),
+ implode(', ', $changeset->getAwayPaths()));
+ switch ($file) {
+ case DifferentialChangeType::FILE_TEXT:
+ $messages[] = pht('This file was moved to %s.', $paths);
+ break;
+ case DifferentialChangeType::FILE_IMAGE:
+ $messages[] = pht('This image was moved to %s.', $paths);
+ break;
+ case DifferentialChangeType::FILE_DIRECTORY:
+ $messages[] = pht('This directory was moved to %s.', $paths);
+ break;
+ case DifferentialChangeType::FILE_BINARY:
+ $messages[] = pht('This binary file was moved to %s.', $paths);
+ break;
+ case DifferentialChangeType::FILE_SYMLINK:
+ $messages[] = pht('This symlink was moved to %s.', $paths);
+ break;
+ case DifferentialChangeType::FILE_SUBMODULE:
+ $messages[] = pht('This submodule was moved to %s.', $paths);
+ break;
+ }
+ break;
+
+ case DifferentialChangeType::TYPE_COPY_AWAY:
+ $paths = phutil_tag(
+ 'strong',
+ array(),
+ implode(', ', $changeset->getAwayPaths()));
+ switch ($file) {
+ case DifferentialChangeType::FILE_TEXT:
+ $messages[] = pht('This file was copied to %s.', $paths);
+ break;
+ case DifferentialChangeType::FILE_IMAGE:
+ $messages[] = pht('This image was copied to %s.', $paths);
+ break;
+ case DifferentialChangeType::FILE_DIRECTORY:
+ $messages[] = pht('This directory was copied to %s.', $paths);
+ break;
+ case DifferentialChangeType::FILE_BINARY:
+ $messages[] = pht('This binary file was copied to %s.', $paths);
+ break;
+ case DifferentialChangeType::FILE_SYMLINK:
+ $messages[] = pht('This symlink was copied to %s.', $paths);
+ break;
+ case DifferentialChangeType::FILE_SUBMODULE:
+ $messages[] = pht('This submodule was copied to %s.', $paths);
+ break;
+ }
+ break;
+
+ case DifferentialChangeType::TYPE_MULTICOPY:
+ $paths = phutil_tag(
+ 'strong',
+ array(),
+ implode(', ', $changeset->getAwayPaths()));
+ switch ($file) {
+ case DifferentialChangeType::FILE_TEXT:
+ $messages[] = pht(
+ 'This file was deleted after being copied to %s.',
+ $paths);
+ break;
+ case DifferentialChangeType::FILE_IMAGE:
+ $messages[] = pht(
+ 'This image was deleted after being copied to %s.',
+ $paths);
+ break;
+ case DifferentialChangeType::FILE_DIRECTORY:
+ $messages[] = pht(
+ 'This directory was deleted after being copied to %s.',
+ $paths);
+ break;
+ case DifferentialChangeType::FILE_BINARY:
+ $messages[] = pht(
+ 'This binary file was deleted after being copied to %s.',
+ $paths);
+ break;
+ case DifferentialChangeType::FILE_SYMLINK:
+ $messages[] = pht(
+ 'This symlink was deleted after being copied to %s.',
+ $paths);
+ break;
+ case DifferentialChangeType::FILE_SUBMODULE:
+ $messages[] = pht(
+ 'This submodule was deleted after being copied to %s.',
+ $paths);
+ break;
+ }
+ break;
+
+ default:
+ switch ($file) {
+ case DifferentialChangeType::FILE_TEXT:
+ // This is the default case, so we only render this header if
+ // forced to since it's not very useful.
+ if ($force) {
+ $messages[] = pht('This file was not modified.');
+ }
+ break;
+ case DifferentialChangeType::FILE_IMAGE:
+ $messages[] = pht('This is an image.');
+ break;
+ case DifferentialChangeType::FILE_DIRECTORY:
+ $messages[] = pht('This is a directory.');
+ break;
+ case DifferentialChangeType::FILE_BINARY:
+ $messages[] = pht('This is a binary file.');
+ break;
+ case DifferentialChangeType::FILE_SYMLINK:
+ $messages[] = pht('This is a symlink.');
+ break;
+ case DifferentialChangeType::FILE_SUBMODULE:
+ $messages[] = pht('This is a submodule.');
+ break;
+ }
+ break;
+ }
+
+ $encoding = $this->getOriginalCharacterEncoding();
+ if ($encoding != 'utf8' && ($file == DifferentialChangeType::FILE_TEXT)) {
+ if ($encoding) {
+ $messages[] = pht(
+ 'This file was converted from %s for display.',
+ phutil_tag('strong', array(), $encoding));
} else {
- // Default case of changes to a text file, no metadata.
- return null;
- }
- } else {
- $none = hsprintf('');
- switch ($change) {
-
- case DifferentialChangeType::TYPE_ADD:
- switch ($file) {
- case DifferentialChangeType::FILE_TEXT:
- $message = pht('This file was <strong>added</strong>.', $none);
- break;
- case DifferentialChangeType::FILE_IMAGE:
- $message = pht('This image was <strong>added</strong>.', $none);
- break;
- case DifferentialChangeType::FILE_DIRECTORY:
- $message = pht(
- 'This directory was <strong>added</strong>.',
- $none);
- break;
- case DifferentialChangeType::FILE_BINARY:
- $message = pht(
- 'This binary file was <strong>added</strong>.',
- $none);
- break;
- case DifferentialChangeType::FILE_SYMLINK:
- $message = pht('This symlink was <strong>added</strong>.', $none);
- break;
- case DifferentialChangeType::FILE_SUBMODULE:
- $message = pht(
- 'This submodule was <strong>added</strong>.',
- $none);
- break;
- }
- break;
-
- case DifferentialChangeType::TYPE_DELETE:
- switch ($file) {
- case DifferentialChangeType::FILE_TEXT:
- $message = pht('This file was <strong>deleted</strong>.', $none);
- break;
- case DifferentialChangeType::FILE_IMAGE:
- $message = pht('This image was <strong>deleted</strong>.', $none);
- break;
- case DifferentialChangeType::FILE_DIRECTORY:
- $message = pht(
- 'This directory was <strong>deleted</strong>.',
- $none);
- break;
- case DifferentialChangeType::FILE_BINARY:
- $message = pht(
- 'This binary file was <strong>deleted</strong>.',
- $none);
- break;
- case DifferentialChangeType::FILE_SYMLINK:
- $message = pht(
- 'This symlink was <strong>deleted</strong>.',
- $none);
- break;
- case DifferentialChangeType::FILE_SUBMODULE:
- $message = pht(
- 'This submodule was <strong>deleted</strong>.',
- $none);
- break;
- }
- break;
-
- case DifferentialChangeType::TYPE_MOVE_HERE:
- $from = phutil_tag('strong', array(), $changeset->getOldFile());
- switch ($file) {
- case DifferentialChangeType::FILE_TEXT:
- $message = pht('This file was moved from %s.', $from);
- break;
- case DifferentialChangeType::FILE_IMAGE:
- $message = pht('This image was moved from %s.', $from);
- break;
- case DifferentialChangeType::FILE_DIRECTORY:
- $message = pht('This directory was moved from %s.', $from);
- break;
- case DifferentialChangeType::FILE_BINARY:
- $message = pht('This binary file was moved from %s.', $from);
- break;
- case DifferentialChangeType::FILE_SYMLINK:
- $message = pht('This symlink was moved from %s.', $from);
- break;
- case DifferentialChangeType::FILE_SUBMODULE:
- $message = pht('This submodule was moved from %s.', $from);
- break;
- }
- break;
-
- case DifferentialChangeType::TYPE_COPY_HERE:
- $from = phutil_tag('strong', array(), $changeset->getOldFile());
- switch ($file) {
- case DifferentialChangeType::FILE_TEXT:
- $message = pht('This file was copied from %s.', $from);
- break;
- case DifferentialChangeType::FILE_IMAGE:
- $message = pht('This image was copied from %s.', $from);
- break;
- case DifferentialChangeType::FILE_DIRECTORY:
- $message = pht('This directory was copied from %s.', $from);
- break;
- case DifferentialChangeType::FILE_BINARY:
- $message = pht('This binary file was copied from %s.', $from);
- break;
- case DifferentialChangeType::FILE_SYMLINK:
- $message = pht('This symlink was copied from %s.', $from);
- break;
- case DifferentialChangeType::FILE_SUBMODULE:
- $message = pht('This submodule was copied from %s.', $from);
- break;
- }
- break;
-
- case DifferentialChangeType::TYPE_MOVE_AWAY:
- $paths = phutil_tag(
- 'strong',
- array(),
- implode(', ', $changeset->getAwayPaths()));
- switch ($file) {
- case DifferentialChangeType::FILE_TEXT:
- $message = pht('This file was moved to %s.', $paths);
- break;
- case DifferentialChangeType::FILE_IMAGE:
- $message = pht('This image was moved to %s.', $paths);
- break;
- case DifferentialChangeType::FILE_DIRECTORY:
- $message = pht('This directory was moved to %s.', $paths);
- break;
- case DifferentialChangeType::FILE_BINARY:
- $message = pht('This binary file was moved to %s.', $paths);
- break;
- case DifferentialChangeType::FILE_SYMLINK:
- $message = pht('This symlink was moved to %s.', $paths);
- break;
- case DifferentialChangeType::FILE_SUBMODULE:
- $message = pht('This submodule was moved to %s.', $paths);
- break;
- }
- break;
-
- case DifferentialChangeType::TYPE_COPY_AWAY:
- $paths = phutil_tag(
- 'strong',
- array(),
- implode(', ', $changeset->getAwayPaths()));
- switch ($file) {
- case DifferentialChangeType::FILE_TEXT:
- $message = pht('This file was copied to %s.', $paths);
- break;
- case DifferentialChangeType::FILE_IMAGE:
- $message = pht('This image was copied to %s.', $paths);
- break;
- case DifferentialChangeType::FILE_DIRECTORY:
- $message = pht('This directory was copied to %s.', $paths);
- break;
- case DifferentialChangeType::FILE_BINARY:
- $message = pht('This binary file was copied to %s.', $paths);
- break;
- case DifferentialChangeType::FILE_SYMLINK:
- $message = pht('This symlink was copied to %s.', $paths);
- break;
- case DifferentialChangeType::FILE_SUBMODULE:
- $message = pht('This submodule was copied to %s.', $paths);
- break;
- }
- break;
-
- case DifferentialChangeType::TYPE_MULTICOPY:
- $paths = phutil_tag(
- 'strong',
- array(),
- implode(', ', $changeset->getAwayPaths()));
- switch ($file) {
- case DifferentialChangeType::FILE_TEXT:
- $message = pht(
- 'This file was deleted after being copied to %s.',
- $paths);
- break;
- case DifferentialChangeType::FILE_IMAGE:
- $message = pht(
- 'This image was deleted after being copied to %s.',
- $paths);
- break;
- case DifferentialChangeType::FILE_DIRECTORY:
- $message = pht(
- 'This directory was deleted after being copied to %s.',
- $paths);
- break;
- case DifferentialChangeType::FILE_BINARY:
- $message = pht(
- 'This binary file was deleted after being copied to %s.',
- $paths);
- break;
- case DifferentialChangeType::FILE_SYMLINK:
- $message = pht(
- 'This symlink was deleted after being copied to %s.',
- $paths);
- break;
- case DifferentialChangeType::FILE_SUBMODULE:
- $message = pht(
- 'This submodule was deleted after being copied to %s.',
- $paths);
- break;
- }
- break;
-
- default:
- switch ($file) {
- case DifferentialChangeType::FILE_TEXT:
- $message = pht('This is a file.');
- break;
- case DifferentialChangeType::FILE_IMAGE:
- $message = pht('This is an image.');
- break;
- case DifferentialChangeType::FILE_DIRECTORY:
- $message = pht('This is a directory.');
- break;
- case DifferentialChangeType::FILE_BINARY:
- $message = pht('This is a binary file.');
- break;
- case DifferentialChangeType::FILE_SYMLINK:
- $message = pht('This is a symlink.');
- break;
- case DifferentialChangeType::FILE_SUBMODULE:
- $message = pht('This is a submodule.');
- break;
- }
- break;
+ $messages[] = pht(
+ 'This file uses an unknown character encoding.');
}
}
- return phutil_tag_div('differential-meta-notice', $message);
+ if (!$messages) {
+ return null;
+ }
+
+ foreach ($messages as $key => $message) {
+ $messages[$key] = phutil_tag('li', array(), $message);
+ }
+
+ return phutil_tag(
+ 'ul',
+ array(
+ 'class' => 'differential-meta-notice',
+ ),
+ $messages);
}
protected function renderPropertyChangeHeader() {
diff --git a/src/applications/differential/render/DifferentialChangesetRenderer.php b/src/applications/differential/render/DifferentialChangesetRenderer.php
--- a/src/applications/differential/render/DifferentialChangesetRenderer.php
+++ b/src/applications/differential/render/DifferentialChangesetRenderer.php
@@ -28,6 +28,16 @@
private $gaps;
private $mask;
private $depths;
+ private $originalCharacterEncoding;
+
+ public function setOriginalCharacterEncoding($original_character_encoding) {
+ $this->originalCharacterEncoding = $original_character_encoding;
+ return $this;
+ }
+
+ public function getOriginalCharacterEncoding() {
+ return $this->originalCharacterEncoding;
+ }
public function setDepths($depths) {
$this->depths = $depths;
diff --git a/src/applications/differential/storage/DifferentialHunkLegacy.php b/src/applications/differential/storage/DifferentialHunkLegacy.php
--- a/src/applications/differential/storage/DifferentialHunkLegacy.php
+++ b/src/applications/differential/storage/DifferentialHunkLegacy.php
@@ -8,4 +8,13 @@
return 'differential_hunk';
}
+ public function getDataEncoding() {
+ return 'utf8';
+ }
+
+ public function forceEncoding($encoding) {
+ // Not supported, these are always utf8.
+ return $this;
+ }
+
}
diff --git a/src/applications/differential/storage/DifferentialHunkModern.php b/src/applications/differential/storage/DifferentialHunkModern.php
--- a/src/applications/differential/storage/DifferentialHunkModern.php
+++ b/src/applications/differential/storage/DifferentialHunkModern.php
@@ -14,6 +14,7 @@
protected $data;
private $rawData;
+ private $forcedEncoding;
public function getTableName() {
return 'differential_hunk_modern';
@@ -41,7 +42,12 @@
public function getChanges() {
return $this->getUTF8StringFromStorage(
$this->getRawData(),
- $this->getDataEncoding());
+ nonempty($this->forcedEncoding, $this->getDataEncoding()));
+ }
+
+ public function forceEncoding($encoding) {
+ $this->forcedEncoding = $encoding;
+ return $this;
}
public function save() {
diff --git a/src/applications/differential/view/DifferentialChangesetListView.php b/src/applications/differential/view/DifferentialChangesetListView.php
--- a/src/applications/differential/view/DifferentialChangesetListView.php
+++ b/src/applications/differential/view/DifferentialChangesetListView.php
@@ -127,6 +127,11 @@
'Show Raw File (Left)' => pht('Show Raw File (Left)'),
'Show Raw File (Right)' => pht('Show Raw File (Right)'),
'Configure Editor' => pht('Configure Editor'),
+ 'Load Changes' => pht('Load Changes'),
+ 'View Side-by-Side' => pht('View Side-by-Side'),
+ 'View Unified' => pht('View Unified (Barely Works!)'),
+ 'Change Text Encoding...' => pht('Change Text Encoding...'),
+ 'Highlight As...' => pht('Highlight As...'),
),
));
diff --git a/src/applications/diffusion/controller/DiffusionDiffController.php b/src/applications/diffusion/controller/DiffusionDiffController.php
--- a/src/applications/diffusion/controller/DiffusionDiffController.php
+++ b/src/applications/diffusion/controller/DiffusionDiffController.php
@@ -68,6 +68,9 @@
array(
'action' => 'rendering-ref')));
+ $parser->setCharacterEncoding($request->getStr('encoding'));
+ $parser->setHighlightAs($request->getStr('highlight'));
+
$coverage = $drequest->loadCoverage();
if ($coverage) {
$parser->setCoverage($coverage);
diff --git a/src/applications/system/application/PhabricatorApplicationSystem.php b/src/applications/system/application/PhabricatorApplicationSystem.php
--- a/src/applications/system/application/PhabricatorApplicationSystem.php
+++ b/src/applications/system/application/PhabricatorApplicationSystem.php
@@ -15,6 +15,10 @@
'/status/' => 'PhabricatorStatusController',
'/debug/' => 'PhabricatorDebugController',
'/robots.txt' => 'PhabricatorRobotsController',
+ '/services/' => array(
+ 'encoding/' => 'PhabricatorSystemSelectEncodingController',
+ 'highlight/' => 'PhabricatorSystemSelectHighlightController',
+ ),
);
}
diff --git a/src/applications/system/controller/PhabricatorSystemSelectEncodingController.php b/src/applications/system/controller/PhabricatorSystemSelectEncodingController.php
new file mode 100644
--- /dev/null
+++ b/src/applications/system/controller/PhabricatorSystemSelectEncodingController.php
@@ -0,0 +1,55 @@
+<?php
+
+final class PhabricatorSystemSelectEncodingController
+ extends PhabricatorController {
+
+ public function shouldRequireLogin() {
+ return false;
+ }
+
+ public function processRequest() {
+ $request = $this->getRequest();
+
+ if (!function_exists('mb_list_encodings')) {
+ return $this->newDialog()
+ ->setTitle(pht('No Encoding Support'))
+ ->appendParagraph(
+ pht(
+ 'This system does not have the "mbstring" extension installed, '.
+ 'so character encodings are not supported. Install "mbstring" to '.
+ 'enable support.'))
+ ->addCancelButton('/');
+ }
+
+ if ($request->isFormPost()) {
+ $result = array('encoding' => $request->getStr('encoding'));
+ return id(new AphrontAjaxResponse())->setContent($result);
+ }
+
+ $encodings = mb_list_encodings();
+ $encodings = array_fuse($encodings);
+ asort($encodings);
+ unset($encodings['pass']);
+ unset($encodings['auto']);
+
+ $encodings = array(
+ '' => pht('(Use Default)'),
+ ) + $encodings;
+
+ $form = id(new AphrontFormView())
+ ->setUser($this->getRequest()->getUser())
+ ->appendRemarkupInstructions(pht('Choose a text encoding to use.'))
+ ->appendChild(
+ id(new AphrontFormSelectControl())
+ ->setLabel(pht('Encoding'))
+ ->setName('encoding')
+ ->setValue($request->getStr('encoding'))
+ ->setOptions($encodings));
+
+ return $this->newDialog()
+ ->setTitle(pht('Select Character Encoding'))
+ ->appendChild($form->buildLayoutView())
+ ->addSubmitButton(pht('Choose Encoding'))
+ ->addCancelButton('/');
+ }
+}
diff --git a/src/applications/system/controller/PhabricatorSystemSelectHighlightController.php b/src/applications/system/controller/PhabricatorSystemSelectHighlightController.php
new file mode 100644
--- /dev/null
+++ b/src/applications/system/controller/PhabricatorSystemSelectHighlightController.php
@@ -0,0 +1,38 @@
+<?php
+
+final class PhabricatorSystemSelectHighlightController
+ extends PhabricatorController {
+
+ public function shouldRequireLogin() {
+ return false;
+ }
+
+ public function processRequest() {
+ $request = $this->getRequest();
+
+ if ($request->isFormPost()) {
+ $result = array('highlight' => $request->getStr('highlight'));
+ return id(new AphrontAjaxResponse())->setContent($result);
+ }
+
+ $languages = array(
+ '' => pht('(Use Default)'),
+ ) + PhabricatorEnv::getEnvConfig('pygments.dropdown-choices');
+
+ $form = id(new AphrontFormView())
+ ->setUser($this->getRequest()->getUser())
+ ->appendRemarkupInstructions(pht('Choose a syntax highlighting to use.'))
+ ->appendChild(
+ id(new AphrontFormSelectControl())
+ ->setLabel(pht('Highlighting'))
+ ->setName('highlight')
+ ->setValue($request->getStr('highlight'))
+ ->setOptions($languages));
+
+ return $this->newDialog()
+ ->setTitle(pht('Select Syntax Highlighting'))
+ ->appendChild($form->buildLayoutView())
+ ->addSubmitButton(pht('Choose Highlighting'))
+ ->addCancelButton('/');
+ }
+}
diff --git a/src/infrastructure/storage/lisk/PhabricatorLiskDAO.php b/src/infrastructure/storage/lisk/PhabricatorLiskDAO.php
--- a/src/infrastructure/storage/lisk/PhabricatorLiskDAO.php
+++ b/src/infrastructure/storage/lisk/PhabricatorLiskDAO.php
@@ -183,6 +183,29 @@
if ($encoding == 'utf8') {
return $string;
}
+
+ if (function_exists('mb_detect_encoding')) {
+ if (strlen($encoding)) {
+ $try_encodings = array(
+ $encoding,
+ );
+ } else {
+ // TODO: This is pretty much a guess, and probably needs to be
+ // configurable in the long run.
+ $try_encodings = array(
+ 'JIS',
+ 'EUC-JP',
+ 'SJIS',
+ 'ISO-8859-1',
+ );
+ }
+
+ $guess = mb_detect_encoding($string, $try_encodings);
+ if ($guess) {
+ return mb_convert_encoding($string, 'UTF-8', $guess);
+ }
+ }
+
return phutil_utf8ize($string);
}
diff --git a/webroot/rsrc/js/application/differential/ChangesetViewManager.js b/webroot/rsrc/js/application/differential/ChangesetViewManager.js
--- a/webroot/rsrc/js/application/differential/ChangesetViewManager.js
+++ b/webroot/rsrc/js/application/differential/ChangesetViewManager.js
@@ -22,6 +22,7 @@
this._whitespace = data.whitespace;
this._renderer = data.renderer;
this._highlight = data.highlight;
+ this._encoding = data.encoding;
},
members: {
@@ -35,6 +36,7 @@
_whitespace: null,
_renderer: null,
_highlight: null,
+ _encoding: null,
/**
@@ -120,8 +122,10 @@
var params = {
ref: this._ref,
- whitespace: this._whitespace,
- renderer: this._getRenderer()
+ whitespace: this._whitespace || '',
+ renderer: this.getRenderer() || '',
+ highlight: this._highlight || '',
+ encoding: this._encoding || ''
};
var workflow = new JX.Workflow(this._renderURI, params)
@@ -160,8 +164,16 @@
return JX.Router.getInstance().getRoutableByKey(this._getRoutableKey());
},
+ setRenderer: function(renderer) {
+ this._renderer = renderer;
+ return this;
+ },
+
+ getRenderer: function() {
+ if (this._renderer !== null) {
+ return this._renderer;
+ }
- _getRenderer: function() {
// TODO: This is a big pile of TODOs.
// NOTE: If you load the page at one device resolution and then resize to
@@ -176,6 +188,23 @@
return renderer;
},
+ setEncoding: function(encoding) {
+ this._encoding = encoding;
+ return this;
+ },
+
+ getEncoding: function() {
+ return this._encoding;
+ },
+
+ setHighlight: function(highlight) {
+ this._highlight = highlight;
+ return this;
+ },
+
+ getHighlight: function() {
+ return this._highlight;
+ },
_getNodeData: function() {
return JX.Stratcom.getData(this._node);
diff --git a/webroot/rsrc/js/application/differential/behavior-dropdown-menus.js b/webroot/rsrc/js/application/differential/behavior-dropdown-menus.js
--- a/webroot/rsrc/js/application/differential/behavior-dropdown-menus.js
+++ b/webroot/rsrc/js/application/differential/behavior-dropdown-menus.js
@@ -4,6 +4,7 @@
* javelin-dom
* javelin-util
* javelin-stratcom
+ * javelin-workflow
* phuix-dropdown-menu
* phuix-action-list-view
* phuix-action-view
@@ -48,13 +49,18 @@
var buildmenu = function(e) {
var button = e.getNode('differential-view-options');
var data = JX.Stratcom.getData(button);
-
if (data.menu) {
return;
}
e.prevent();
+ var changeset = JX.DOM.findAbove(
+ button,
+ 'div',
+ 'differential-changeset');
+
+ var view = JX.ChangesetViewManager.getForNode(changeset);
var menu = new JX.PHUIXDropdownMenu(button);
var list = new JX.PHUIXActionListView();
@@ -103,12 +109,15 @@
var up_item = new JX.PHUIXActionView()
.setHandler(function(e) {
- var changeset = JX.DOM.findAbove(
- button,
- 'div',
- 'differential-changeset');
-
- var view = JX.ChangesetViewManager.getForNode(changeset);
+ if (view.isLoaded()) {
+ var renderer = view.getRenderer();
+ if (renderer == '1up') {
+ renderer = '2up';
+ } else {
+ renderer = '1up';
+ }
+ view.setRenderer(renderer);
+ }
view.reload();
e.prevent();
@@ -116,22 +125,54 @@
});
list.addItem(up_item);
+ var encoding_item = new JX.PHUIXActionView()
+ .setIcon('fa-font')
+ .setName(pht('Change Text Encoding...'))
+ .setHandler(function(e) {
+ var params = {
+ encoding: view.getEncoding()
+ };
+
+ new JX.Workflow('/services/encoding/', params)
+ .setHandler(function(r) {
+ view.setEncoding(r.encoding);
+ view.reload();
+ })
+ .start();
+
+ e.prevent();
+ menu.close();
+ });
+ list.addItem(encoding_item);
+
+ var highlight_item = new JX.PHUIXActionView()
+ .setIcon('fa-sun-o')
+ .setName(pht('Highlight As...'))
+ .setHandler(function(e) {
+ var params = {
+ highlight: view.getHighlight()
+ };
+
+ new JX.Workflow('/services/highlight/', params)
+ .setHandler(function(r) {
+ view.setHighlight(r.highlight);
+ view.reload();
+ })
+ .start();
+
+ e.prevent();
+ menu.close();
+ });
+ list.addItem(highlight_item);
+
add_link('fa-arrow-left', pht('Show Raw File (Left)'), data.leftURI);
add_link('fa-arrow-right', pht('Show Raw File (Right)'), data.rightURI);
add_link('fa-pencil', pht('Open in Editor'), data.editor, true);
add_link('fa-wrench', pht('Configure Editor'), data.editorConfigure);
-
menu.setContent(list.getNode());
menu.listen('open', function() {
- var changeset = JX.DOM.findAbove(
- button,
- 'div',
- 'differential-changeset');
-
- var view = JX.ChangesetViewManager.getForNode(changeset);
-
// When the user opens the menu, check if there are any "Show More"
// links in the changeset body. If there aren't, disable the "Show
// Entire File" menu item since it won't change anything.
@@ -155,16 +196,23 @@
.setHandler(function(e) { e.prevent(); });
}
- // TODO: This is temporary and just makes testing easier. It will do
- // some mojo soon.
+ encoding_item.setDisabled(!view.isLoaded());
+ highlight_item.setDisabled(!view.isLoaded());
+
if (view.isLoaded()) {
- up_item
- .setIcon('fa-refresh')
- .setName('Reload');
+ if (view.getRenderer() == '2up') {
+ up_item
+ .setIcon('fa-list-alt')
+ .setName(pht('View Unified'));
+ } else {
+ up_item
+ .setIcon('fa-files-o')
+ .setName(pht('View Side-by-Side'));
+ }
} else {
up_item
.setIcon('fa-refresh')
- .setName('Load');
+ .setName(pht('Load Changes'));
}
visible_item
@@ -198,6 +246,7 @@
}
});
+
data.menu = menu;
menu.open();
};
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Mar 23, 3:14 PM (1 w, 5 d ago)
Storage Engine
amazon-s3
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
phabricator/secure/rb/2b/b6al2z6ddteqogae
Default Alt Text
D9294.diff (45 KB)
Attached To
Mode
D9294: Substantially support character encodings and "Highlight As" in changesets
Attached
Detach File
Event Timeline
Log In to Comment