1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-12-15 10:00:55 +01:00

(stable) Promote 2017 Week 33

This commit is contained in:
epriestley 2017-08-22 15:30:02 -07:00
commit fb4e7a9a8d
88 changed files with 1606 additions and 1280 deletions

View file

@ -9,7 +9,7 @@ return array(
'names' => array( 'names' => array(
'conpherence.pkg.css' => 'e68cf1fa', 'conpherence.pkg.css' => 'e68cf1fa',
'conpherence.pkg.js' => 'b5b51108', 'conpherence.pkg.js' => 'b5b51108',
'core.pkg.css' => '0e4a68ad', 'core.pkg.css' => 'fe4effd6',
'core.pkg.js' => '5d80e0db', 'core.pkg.js' => '5d80e0db',
'darkconsole.pkg.js' => '1f9a31bc', 'darkconsole.pkg.js' => '1f9a31bc',
'differential.pkg.css' => '45951e9e', 'differential.pkg.css' => '45951e9e',
@ -36,13 +36,13 @@ return array(
'rsrc/css/aphront/tokenizer.css' => '15d5ff71', 'rsrc/css/aphront/tokenizer.css' => '15d5ff71',
'rsrc/css/aphront/tooltip.css' => '173b9431', 'rsrc/css/aphront/tooltip.css' => '173b9431',
'rsrc/css/aphront/typeahead-browse.css' => 'f2818435', 'rsrc/css/aphront/typeahead-browse.css' => 'f2818435',
'rsrc/css/aphront/typeahead.css' => '4434bc8a', 'rsrc/css/aphront/typeahead.css' => 'a4a21016',
'rsrc/css/application/almanac/almanac.css' => 'dbb9b3af', 'rsrc/css/application/almanac/almanac.css' => 'dbb9b3af',
'rsrc/css/application/auth/auth.css' => '0877ed6e', 'rsrc/css/application/auth/auth.css' => '0877ed6e',
'rsrc/css/application/base/main-menu-view.css' => '16053029', 'rsrc/css/application/base/main-menu-view.css' => '16053029',
'rsrc/css/application/base/notification-menu.css' => '73fefdfa', 'rsrc/css/application/base/notification-menu.css' => '73fefdfa',
'rsrc/css/application/base/phui-theme.css' => '9f261c6b', 'rsrc/css/application/base/phui-theme.css' => '9f261c6b',
'rsrc/css/application/base/standard-page-view.css' => 'c581d2ac', 'rsrc/css/application/base/standard-page-view.css' => '34ee718b',
'rsrc/css/application/chatlog/chatlog.css' => 'd295b020', 'rsrc/css/application/chatlog/chatlog.css' => 'd295b020',
'rsrc/css/application/conduit/conduit-api.css' => '7bc725c4', 'rsrc/css/application/conduit/conduit-api.css' => '7bc725c4',
'rsrc/css/application/config/config-options.css' => 'd55ed093', 'rsrc/css/application/config/config-options.css' => 'd55ed093',
@ -75,7 +75,7 @@ return array(
'rsrc/css/application/diffusion/diffusion-readme.css' => '419dd5b6', 'rsrc/css/application/diffusion/diffusion-readme.css' => '419dd5b6',
'rsrc/css/application/diffusion/diffusion-repository.css' => 'ee6f20ec', 'rsrc/css/application/diffusion/diffusion-repository.css' => 'ee6f20ec',
'rsrc/css/application/diffusion/diffusion-source.css' => '750add59', 'rsrc/css/application/diffusion/diffusion-source.css' => '750add59',
'rsrc/css/application/diffusion/diffusion.css' => '67bd971b', 'rsrc/css/application/diffusion/diffusion.css' => 'ceacf994',
'rsrc/css/application/feed/feed.css' => 'ecd4ec57', 'rsrc/css/application/feed/feed.css' => 'ecd4ec57',
'rsrc/css/application/files/global-drag-and-drop.css' => 'b556a948', 'rsrc/css/application/files/global-drag-and-drop.css' => 'b556a948',
'rsrc/css/application/flag/flag.css' => 'bba8f811', 'rsrc/css/application/flag/flag.css' => 'bba8f811',
@ -111,7 +111,7 @@ return array(
'rsrc/css/application/releeph/releeph-request-differential-create-dialog.css' => '8d8b92cd', 'rsrc/css/application/releeph/releeph-request-differential-create-dialog.css' => '8d8b92cd',
'rsrc/css/application/releeph/releeph-request-typeahead.css' => '667a48ae', 'rsrc/css/application/releeph/releeph-request-typeahead.css' => '667a48ae',
'rsrc/css/application/search/application-search-view.css' => '66ee5d46', 'rsrc/css/application/search/application-search-view.css' => '66ee5d46',
'rsrc/css/application/search/search-results.css' => '8f8e08ed', 'rsrc/css/application/search/search-results.css' => '505dd8cf',
'rsrc/css/application/slowvote/slowvote.css' => 'a94b7230', 'rsrc/css/application/slowvote/slowvote.css' => 'a94b7230',
'rsrc/css/application/tokens/tokens.css' => '3d0f239e', 'rsrc/css/application/tokens/tokens.css' => '3d0f239e',
'rsrc/css/application/uiexample/example.css' => '528b19de', 'rsrc/css/application/uiexample/example.css' => '528b19de',
@ -165,7 +165,7 @@ return array(
'rsrc/css/phui/phui-image-mask.css' => 'a8498f9c', 'rsrc/css/phui/phui-image-mask.css' => 'a8498f9c',
'rsrc/css/phui/phui-info-view.css' => 'e1b4ec37', 'rsrc/css/phui/phui-info-view.css' => 'e1b4ec37',
'rsrc/css/phui/phui-invisible-character-view.css' => '6993d9f0', 'rsrc/css/phui/phui-invisible-character-view.css' => '6993d9f0',
'rsrc/css/phui/phui-left-right.css' => 'f60c67e7', 'rsrc/css/phui/phui-left-right.css' => '75227a4d',
'rsrc/css/phui/phui-lightbox.css' => '0a035e40', 'rsrc/css/phui/phui-lightbox.css' => '0a035e40',
'rsrc/css/phui/phui-list.css' => '38f8c9bd', 'rsrc/css/phui/phui-list.css' => '38f8c9bd',
'rsrc/css/phui/phui-object-box.css' => '9cff003c', 'rsrc/css/phui/phui-object-box.css' => '9cff003c',
@ -178,12 +178,12 @@ return array(
'rsrc/css/phui/phui-status.css' => 'd5263e49', 'rsrc/css/phui/phui-status.css' => 'd5263e49',
'rsrc/css/phui/phui-tag-view.css' => 'b4719c50', 'rsrc/css/phui/phui-tag-view.css' => 'b4719c50',
'rsrc/css/phui/phui-timeline-view.css' => 'f21db7ca', 'rsrc/css/phui/phui-timeline-view.css' => 'f21db7ca',
'rsrc/css/phui/phui-two-column-view.css' => 'ae38a939', 'rsrc/css/phui/phui-two-column-view.css' => '76dcd3d4',
'rsrc/css/phui/workboards/phui-workboard-color.css' => '783cdff5', 'rsrc/css/phui/workboards/phui-workboard-color.css' => '783cdff5',
'rsrc/css/phui/workboards/phui-workboard.css' => '3bc85455', 'rsrc/css/phui/workboards/phui-workboard.css' => '3bc85455',
'rsrc/css/phui/workboards/phui-workcard.css' => 'cca5fa92', 'rsrc/css/phui/workboards/phui-workcard.css' => 'cca5fa92',
'rsrc/css/phui/workboards/phui-workpanel.css' => 'a3a63478', 'rsrc/css/phui/workboards/phui-workpanel.css' => 'a3a63478',
'rsrc/css/sprite-login.css' => '587d92d7', 'rsrc/css/sprite-login.css' => '396f3c3a',
'rsrc/css/sprite-tokens.css' => '9cdfd599', 'rsrc/css/sprite-tokens.css' => '9cdfd599',
'rsrc/css/syntax/syntax-default.css' => '9923583c', 'rsrc/css/syntax/syntax-default.css' => '9923583c',
'rsrc/externals/d3/d3.min.js' => 'a11a5ff2', 'rsrc/externals/d3/d3.min.js' => 'a11a5ff2',
@ -359,8 +359,8 @@ return array(
'rsrc/image/phrequent_active.png' => 'a466a8ed', 'rsrc/image/phrequent_active.png' => 'a466a8ed',
'rsrc/image/phrequent_inactive.png' => 'bfc15a69', 'rsrc/image/phrequent_inactive.png' => 'bfc15a69',
'rsrc/image/resize.png' => 'fd476de4', 'rsrc/image/resize.png' => 'fd476de4',
'rsrc/image/sprite-login-X2.png' => '4abee916', 'rsrc/image/sprite-login-X2.png' => '308c92c4',
'rsrc/image/sprite-login.png' => '2b9663fd', 'rsrc/image/sprite-login.png' => '9ec54245',
'rsrc/image/sprite-tokens-X2.png' => '804a5232', 'rsrc/image/sprite-tokens-X2.png' => '804a5232',
'rsrc/image/sprite-tokens.png' => 'b41d03da', 'rsrc/image/sprite-tokens.png' => 'b41d03da',
'rsrc/image/texture/card-gradient.png' => '815f26e8', 'rsrc/image/texture/card-gradient.png' => '815f26e8',
@ -546,7 +546,7 @@ return array(
'aphront-table-view-css' => 'a3aa6910', 'aphront-table-view-css' => 'a3aa6910',
'aphront-tokenizer-control-css' => '15d5ff71', 'aphront-tokenizer-control-css' => '15d5ff71',
'aphront-tooltip-css' => '173b9431', 'aphront-tooltip-css' => '173b9431',
'aphront-typeahead-control-css' => '4434bc8a', 'aphront-typeahead-control-css' => 'a4a21016',
'application-search-view-css' => '66ee5d46', 'application-search-view-css' => '66ee5d46',
'auth-css' => '0877ed6e', 'auth-css' => '0877ed6e',
'bulk-job-css' => 'df9c1d4a', 'bulk-job-css' => 'df9c1d4a',
@ -570,7 +570,7 @@ return array(
'differential-revision-history-css' => '0e8eb855', 'differential-revision-history-css' => '0e8eb855',
'differential-revision-list-css' => 'f3c47d33', 'differential-revision-list-css' => 'f3c47d33',
'differential-table-of-contents-css' => 'ae4b7a55', 'differential-table-of-contents-css' => 'ae4b7a55',
'diffusion-css' => '67bd971b', 'diffusion-css' => 'ceacf994',
'diffusion-icons-css' => '0c15255e', 'diffusion-icons-css' => '0c15255e',
'diffusion-readme-css' => '419dd5b6', 'diffusion-readme-css' => '419dd5b6',
'diffusion-repository-css' => 'ee6f20ec', 'diffusion-repository-css' => 'ee6f20ec',
@ -798,11 +798,11 @@ return array(
'phabricator-phtize' => 'd254d646', 'phabricator-phtize' => 'd254d646',
'phabricator-prefab' => 'c5af80a2', 'phabricator-prefab' => 'c5af80a2',
'phabricator-remarkup-css' => 'cad18339', 'phabricator-remarkup-css' => 'cad18339',
'phabricator-search-results-css' => '8f8e08ed', 'phabricator-search-results-css' => '505dd8cf',
'phabricator-shaped-request' => '7cbe244b', 'phabricator-shaped-request' => '7cbe244b',
'phabricator-slowvote-css' => 'a94b7230', 'phabricator-slowvote-css' => 'a94b7230',
'phabricator-source-code-view-css' => 'aea41829', 'phabricator-source-code-view-css' => 'aea41829',
'phabricator-standard-page-view' => 'c581d2ac', 'phabricator-standard-page-view' => '34ee718b',
'phabricator-textareautils' => '320810c8', 'phabricator-textareautils' => '320810c8',
'phabricator-title' => '485aaa6c', 'phabricator-title' => '485aaa6c',
'phabricator-tooltip' => '358b8c04', 'phabricator-tooltip' => '358b8c04',
@ -854,7 +854,7 @@ return array(
'phui-info-view-css' => 'e1b4ec37', 'phui-info-view-css' => 'e1b4ec37',
'phui-inline-comment-view-css' => '65ae3bc2', 'phui-inline-comment-view-css' => '65ae3bc2',
'phui-invisible-character-view-css' => '6993d9f0', 'phui-invisible-character-view-css' => '6993d9f0',
'phui-left-right-css' => 'f60c67e7', 'phui-left-right-css' => '75227a4d',
'phui-lightbox-css' => '0a035e40', 'phui-lightbox-css' => '0a035e40',
'phui-list-view-css' => '38f8c9bd', 'phui-list-view-css' => '38f8c9bd',
'phui-object-box-css' => '9cff003c', 'phui-object-box-css' => '9cff003c',
@ -874,7 +874,7 @@ return array(
'phui-tag-view-css' => 'b4719c50', 'phui-tag-view-css' => 'b4719c50',
'phui-theme-css' => '9f261c6b', 'phui-theme-css' => '9f261c6b',
'phui-timeline-view-css' => 'f21db7ca', 'phui-timeline-view-css' => 'f21db7ca',
'phui-two-column-view-css' => 'ae38a939', 'phui-two-column-view-css' => '76dcd3d4',
'phui-workboard-color-css' => '783cdff5', 'phui-workboard-color-css' => '783cdff5',
'phui-workboard-view-css' => '3bc85455', 'phui-workboard-view-css' => '3bc85455',
'phui-workcard-view-css' => 'cca5fa92', 'phui-workcard-view-css' => 'cca5fa92',
@ -897,7 +897,7 @@ return array(
'releeph-request-differential-create-dialog' => '8d8b92cd', 'releeph-request-differential-create-dialog' => '8d8b92cd',
'releeph-request-typeahead-css' => '667a48ae', 'releeph-request-typeahead-css' => '667a48ae',
'setup-issue-css' => 'f794cfc3', 'setup-issue-css' => 'f794cfc3',
'sprite-login-css' => '587d92d7', 'sprite-login-css' => '396f3c3a',
'sprite-tokens-css' => '9cdfd599', 'sprite-tokens-css' => '9cdfd599',
'syntax-default-css' => '9923583c', 'syntax-default-css' => '9923583c',
'syntax-highlighting-css' => 'cae95e89', 'syntax-highlighting-css' => 'cae95e89',

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 879 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 722 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 421 B

After

Width:  |  Height:  |  Size: 522 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 365 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1,013 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 934 B

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 776 B

View file

@ -21,11 +21,6 @@
"rule": ".login-Disqus", "rule": ".login-Disqus",
"hash": "77b29d56329a3c30b79d6b6673b0e39b" "hash": "77b29d56329a3c30b79d6b6673b0e39b"
}, },
"login-Dropbox": {
"name": "login-Dropbox",
"rule": ".login-Dropbox",
"hash": "5eaf07ae4598227fbbba3474675d18c7"
},
"login-Facebook": { "login-Facebook": {
"name": "login-Facebook", "name": "login-Facebook",
"rule": ".login-Facebook", "rule": ".login-Facebook",
@ -61,21 +56,11 @@
"rule": ".login-LDAP", "rule": ".login-LDAP",
"hash": "e31df2e9faf8ca0925ef93128a82fa7a" "hash": "e31df2e9faf8ca0925ef93128a82fa7a"
}, },
"login-Linkedin": {
"name": "login-Linkedin",
"rule": ".login-Linkedin",
"hash": "b7ee1e92c923462531f3a34093e57127"
},
"login-MediaWiki": { "login-MediaWiki": {
"name": "login-MediaWiki", "name": "login-MediaWiki",
"rule": ".login-MediaWiki", "rule": ".login-MediaWiki",
"hash": "f1f0a9382434081a9a84e7584828c2dd" "hash": "f1f0a9382434081a9a84e7584828c2dd"
}, },
"login-Openid": {
"name": "login-Openid",
"rule": ".login-Openid",
"hash": "886f65ad44435344a1fa1c13e7758155"
},
"login-PayPal": { "login-PayPal": {
"name": "login-PayPal", "name": "login-PayPal",
"rule": ".login-PayPal", "rule": ".login-PayPal",
@ -84,7 +69,7 @@
"login-Phabricator": { "login-Phabricator": {
"name": "login-Phabricator", "name": "login-Phabricator",
"rule": ".login-Phabricator", "rule": ".login-Phabricator",
"hash": "d0f830803593bbcc025d7d5a29ee3ecd" "hash": "54f5ddae4b9d138c438ec00ed42544d2"
}, },
"login-Slack": { "login-Slack": {
"name": "login-Slack", "name": "login-Slack",
@ -120,11 +105,6 @@
"name": "login-WordPressCOM", "name": "login-WordPressCOM",
"rule": ".login-WordPressCOM", "rule": ".login-WordPressCOM",
"hash": "9eae4205dbed0c42a18ee4f8e0fa151b" "hash": "9eae4205dbed0c42a18ee4f8e0fa151b"
},
"login-Yahoo": {
"name": "login-Yahoo",
"rule": ".login-Yahoo",
"hash": "f37822c769f6b8ebd1dda6b3ac89b83b"
} }
}, },
"scales": [ "scales": [

View file

@ -0,0 +1,48 @@
<?php
// Migrate saved Differential revision queries from using a "<select />"
// control with hard-coded status groups for status selection to using a
// tokenizer with status functions.
$table = new PhabricatorSavedQuery();
$conn = $table->establishConnection('w');
$status_map = array(
'status-open' => array('open()'),
'status-closed' => array('closed()'),
'status-accepted' => array('accepted'),
'status-needs-review' => array('needs-review'),
'status-needs-revision' => array('needs-revision'),
'status-abandoned' => array('abandoned'),
);
foreach (new LiskMigrationIterator($table) as $query) {
if ($query->getEngineClassName() !== 'DifferentialRevisionSearchEngine') {
// This isn't a revision query.
continue;
}
$parameters = $query->getParameters();
$status = idx($parameters, 'status');
if (!$status) {
// This query didn't specify a "status" value.
continue;
}
if (!isset($status_map[$status])) {
// The "status" value is unknown, or does not correspond to a
// modern "status" constraint.
continue;
}
$parameters['statuses'] = $status_map[$status];
queryfx(
$conn,
'UPDATE %T SET parameters = %s WHERE id = %d',
$table->getTableName(),
phutil_json_encode($parameters),
$query->getID());
}

View file

@ -0,0 +1,17 @@
UPDATE {$NAMESPACE}_differential.differential_revision
SET status = "needs-review" WHERE status = "0";
UPDATE {$NAMESPACE}_differential.differential_revision
SET status = "needs-revision" WHERE status = "1";
UPDATE {$NAMESPACE}_differential.differential_revision
SET status = "accepted" WHERE status = "2";
UPDATE {$NAMESPACE}_differential.differential_revision
SET status = "published" WHERE status = "3";
UPDATE {$NAMESPACE}_differential.differential_revision
SET status = "abandoned" WHERE status = "4";
UPDATE {$NAMESPACE}_differential.differential_revision
SET status = "changes-planned" WHERE status = "5";

View file

@ -0,0 +1,38 @@
<?php
$map = array(
'0' => 'needs-review',
'1' => 'needs-revision',
'2' => 'accepted',
'3' => 'published',
'4' => 'abandoned',
'5' => 'changes-planned',
);
$table = new DifferentialTransaction();
$conn = $table->establishConnection('w');
foreach (new LiskMigrationIterator($table) as $xaction) {
$type = $xaction->getTransactionType();
if (($type != 'differential:status') &&
($type != 'differential.revision.status')) {
continue;
}
$old = $xaction->getOldValue();
$new = $xaction->getNewValue();
$old = idx($map, $old, $old);
$new = idx($map, $new, $new);
queryfx(
$conn,
'UPDATE %T SET transactionType = %s, oldValue = %s, newValue = %s
WHERE id = %d',
$table->getTableName(),
'differential.revision.status',
json_encode($old),
json_encode($new),
$xaction->getID());
}

View file

@ -0,0 +1,2 @@
ALTER TABLE {$NAMESPACE}_phame.phame_post
ADD views INTEGER NOT NULL;

View file

@ -0,0 +1,2 @@
UPDATE {$NAMESPACE}_phame.phame_post
SET views = 0;

View file

@ -445,7 +445,6 @@ phutil_register_library_map(array(
'DifferentialExactUserFunctionDatasource' => 'applications/differential/typeahead/DifferentialExactUserFunctionDatasource.php', 'DifferentialExactUserFunctionDatasource' => 'applications/differential/typeahead/DifferentialExactUserFunctionDatasource.php',
'DifferentialFieldParseException' => 'applications/differential/exception/DifferentialFieldParseException.php', 'DifferentialFieldParseException' => 'applications/differential/exception/DifferentialFieldParseException.php',
'DifferentialFieldValidationException' => 'applications/differential/exception/DifferentialFieldValidationException.php', 'DifferentialFieldValidationException' => 'applications/differential/exception/DifferentialFieldValidationException.php',
'DifferentialFindConduitAPIMethod' => 'applications/differential/conduit/DifferentialFindConduitAPIMethod.php',
'DifferentialGetAllDiffsConduitAPIMethod' => 'applications/differential/conduit/DifferentialGetAllDiffsConduitAPIMethod.php', 'DifferentialGetAllDiffsConduitAPIMethod' => 'applications/differential/conduit/DifferentialGetAllDiffsConduitAPIMethod.php',
'DifferentialGetCommitMessageConduitAPIMethod' => 'applications/differential/conduit/DifferentialGetCommitMessageConduitAPIMethod.php', 'DifferentialGetCommitMessageConduitAPIMethod' => 'applications/differential/conduit/DifferentialGetCommitMessageConduitAPIMethod.php',
'DifferentialGetCommitPathsConduitAPIMethod' => 'applications/differential/conduit/DifferentialGetCommitPathsConduitAPIMethod.php', 'DifferentialGetCommitPathsConduitAPIMethod' => 'applications/differential/conduit/DifferentialGetCommitPathsConduitAPIMethod.php',
@ -521,6 +520,7 @@ phutil_register_library_map(array(
'DifferentialRevisionAuthorProjectsHeraldField' => 'applications/differential/herald/DifferentialRevisionAuthorProjectsHeraldField.php', 'DifferentialRevisionAuthorProjectsHeraldField' => 'applications/differential/herald/DifferentialRevisionAuthorProjectsHeraldField.php',
'DifferentialRevisionCloseDetailsController' => 'applications/differential/controller/DifferentialRevisionCloseDetailsController.php', 'DifferentialRevisionCloseDetailsController' => 'applications/differential/controller/DifferentialRevisionCloseDetailsController.php',
'DifferentialRevisionCloseTransaction' => 'applications/differential/xaction/DifferentialRevisionCloseTransaction.php', 'DifferentialRevisionCloseTransaction' => 'applications/differential/xaction/DifferentialRevisionCloseTransaction.php',
'DifferentialRevisionClosedStatusDatasource' => 'applications/differential/typeahead/DifferentialRevisionClosedStatusDatasource.php',
'DifferentialRevisionCommandeerTransaction' => 'applications/differential/xaction/DifferentialRevisionCommandeerTransaction.php', 'DifferentialRevisionCommandeerTransaction' => 'applications/differential/xaction/DifferentialRevisionCommandeerTransaction.php',
'DifferentialRevisionContentAddedHeraldField' => 'applications/differential/herald/DifferentialRevisionContentAddedHeraldField.php', 'DifferentialRevisionContentAddedHeraldField' => 'applications/differential/herald/DifferentialRevisionContentAddedHeraldField.php',
'DifferentialRevisionContentHeraldField' => 'applications/differential/herald/DifferentialRevisionContentHeraldField.php', 'DifferentialRevisionContentHeraldField' => 'applications/differential/herald/DifferentialRevisionContentHeraldField.php',
@ -548,6 +548,7 @@ phutil_register_library_map(array(
'DifferentialRevisionListController' => 'applications/differential/controller/DifferentialRevisionListController.php', 'DifferentialRevisionListController' => 'applications/differential/controller/DifferentialRevisionListController.php',
'DifferentialRevisionListView' => 'applications/differential/view/DifferentialRevisionListView.php', 'DifferentialRevisionListView' => 'applications/differential/view/DifferentialRevisionListView.php',
'DifferentialRevisionMailReceiver' => 'applications/differential/mail/DifferentialRevisionMailReceiver.php', 'DifferentialRevisionMailReceiver' => 'applications/differential/mail/DifferentialRevisionMailReceiver.php',
'DifferentialRevisionOpenStatusDatasource' => 'applications/differential/typeahead/DifferentialRevisionOpenStatusDatasource.php',
'DifferentialRevisionOperationController' => 'applications/differential/controller/DifferentialRevisionOperationController.php', 'DifferentialRevisionOperationController' => 'applications/differential/controller/DifferentialRevisionOperationController.php',
'DifferentialRevisionPHIDType' => 'applications/differential/phid/DifferentialRevisionPHIDType.php', 'DifferentialRevisionPHIDType' => 'applications/differential/phid/DifferentialRevisionPHIDType.php',
'DifferentialRevisionPackageHeraldField' => 'applications/differential/herald/DifferentialRevisionPackageHeraldField.php', 'DifferentialRevisionPackageHeraldField' => 'applications/differential/herald/DifferentialRevisionPackageHeraldField.php',
@ -572,6 +573,9 @@ phutil_register_library_map(array(
'DifferentialRevisionSearchConduitAPIMethod' => 'applications/differential/conduit/DifferentialRevisionSearchConduitAPIMethod.php', 'DifferentialRevisionSearchConduitAPIMethod' => 'applications/differential/conduit/DifferentialRevisionSearchConduitAPIMethod.php',
'DifferentialRevisionSearchEngine' => 'applications/differential/query/DifferentialRevisionSearchEngine.php', 'DifferentialRevisionSearchEngine' => 'applications/differential/query/DifferentialRevisionSearchEngine.php',
'DifferentialRevisionStatus' => 'applications/differential/constants/DifferentialRevisionStatus.php', 'DifferentialRevisionStatus' => 'applications/differential/constants/DifferentialRevisionStatus.php',
'DifferentialRevisionStatusDatasource' => 'applications/differential/typeahead/DifferentialRevisionStatusDatasource.php',
'DifferentialRevisionStatusFunctionDatasource' => 'applications/differential/typeahead/DifferentialRevisionStatusFunctionDatasource.php',
'DifferentialRevisionStatusTransaction' => 'applications/differential/xaction/DifferentialRevisionStatusTransaction.php',
'DifferentialRevisionSummaryHeraldField' => 'applications/differential/herald/DifferentialRevisionSummaryHeraldField.php', 'DifferentialRevisionSummaryHeraldField' => 'applications/differential/herald/DifferentialRevisionSummaryHeraldField.php',
'DifferentialRevisionSummaryTransaction' => 'applications/differential/xaction/DifferentialRevisionSummaryTransaction.php', 'DifferentialRevisionSummaryTransaction' => 'applications/differential/xaction/DifferentialRevisionSummaryTransaction.php',
'DifferentialRevisionTestPlanTransaction' => 'applications/differential/xaction/DifferentialRevisionTestPlanTransaction.php', 'DifferentialRevisionTestPlanTransaction' => 'applications/differential/xaction/DifferentialRevisionTestPlanTransaction.php',
@ -772,6 +776,7 @@ phutil_register_library_map(array(
'DiffusionPathQueryTestCase' => 'applications/diffusion/query/pathid/__tests__/DiffusionPathQueryTestCase.php', 'DiffusionPathQueryTestCase' => 'applications/diffusion/query/pathid/__tests__/DiffusionPathQueryTestCase.php',
'DiffusionPathTreeController' => 'applications/diffusion/controller/DiffusionPathTreeController.php', 'DiffusionPathTreeController' => 'applications/diffusion/controller/DiffusionPathTreeController.php',
'DiffusionPathValidateController' => 'applications/diffusion/controller/DiffusionPathValidateController.php', 'DiffusionPathValidateController' => 'applications/diffusion/controller/DiffusionPathValidateController.php',
'DiffusionPatternSearchView' => 'applications/diffusion/view/DiffusionPatternSearchView.php',
'DiffusionPhpExternalSymbolsSource' => 'applications/diffusion/symbol/DiffusionPhpExternalSymbolsSource.php', 'DiffusionPhpExternalSymbolsSource' => 'applications/diffusion/symbol/DiffusionPhpExternalSymbolsSource.php',
'DiffusionPreCommitContentAffectedFilesHeraldField' => 'applications/diffusion/herald/DiffusionPreCommitContentAffectedFilesHeraldField.php', 'DiffusionPreCommitContentAffectedFilesHeraldField' => 'applications/diffusion/herald/DiffusionPreCommitContentAffectedFilesHeraldField.php',
'DiffusionPreCommitContentAuthorHeraldField' => 'applications/diffusion/herald/DiffusionPreCommitContentAuthorHeraldField.php', 'DiffusionPreCommitContentAuthorHeraldField' => 'applications/diffusion/herald/DiffusionPreCommitContentAuthorHeraldField.php',
@ -4412,6 +4417,7 @@ phutil_register_library_map(array(
'PhamePostTransactionQuery' => 'applications/phame/query/PhamePostTransactionQuery.php', 'PhamePostTransactionQuery' => 'applications/phame/query/PhamePostTransactionQuery.php',
'PhamePostTransactionType' => 'applications/phame/xaction/PhamePostTransactionType.php', 'PhamePostTransactionType' => 'applications/phame/xaction/PhamePostTransactionType.php',
'PhamePostViewController' => 'applications/phame/controller/post/PhamePostViewController.php', 'PhamePostViewController' => 'applications/phame/controller/post/PhamePostViewController.php',
'PhamePostViewsTransaction' => 'applications/phame/xaction/PhamePostViewsTransaction.php',
'PhamePostVisibilityTransaction' => 'applications/phame/xaction/PhamePostVisibilityTransaction.php', 'PhamePostVisibilityTransaction' => 'applications/phame/xaction/PhamePostVisibilityTransaction.php',
'PhameSchemaSpec' => 'applications/phame/storage/PhameSchemaSpec.php', 'PhameSchemaSpec' => 'applications/phame/storage/PhameSchemaSpec.php',
'PhameSite' => 'applications/phame/site/PhameSite.php', 'PhameSite' => 'applications/phame/site/PhameSite.php',
@ -5415,7 +5421,6 @@ phutil_register_library_map(array(
'DifferentialExactUserFunctionDatasource' => 'PhabricatorTypeaheadCompositeDatasource', 'DifferentialExactUserFunctionDatasource' => 'PhabricatorTypeaheadCompositeDatasource',
'DifferentialFieldParseException' => 'Exception', 'DifferentialFieldParseException' => 'Exception',
'DifferentialFieldValidationException' => 'Exception', 'DifferentialFieldValidationException' => 'Exception',
'DifferentialFindConduitAPIMethod' => 'DifferentialConduitAPIMethod',
'DifferentialGetAllDiffsConduitAPIMethod' => 'DifferentialConduitAPIMethod', 'DifferentialGetAllDiffsConduitAPIMethod' => 'DifferentialConduitAPIMethod',
'DifferentialGetCommitMessageConduitAPIMethod' => 'DifferentialConduitAPIMethod', 'DifferentialGetCommitMessageConduitAPIMethod' => 'DifferentialConduitAPIMethod',
'DifferentialGetCommitPathsConduitAPIMethod' => 'DifferentialConduitAPIMethod', 'DifferentialGetCommitPathsConduitAPIMethod' => 'DifferentialConduitAPIMethod',
@ -5514,6 +5519,7 @@ phutil_register_library_map(array(
'DifferentialRevisionAuthorProjectsHeraldField' => 'DifferentialRevisionHeraldField', 'DifferentialRevisionAuthorProjectsHeraldField' => 'DifferentialRevisionHeraldField',
'DifferentialRevisionCloseDetailsController' => 'DifferentialController', 'DifferentialRevisionCloseDetailsController' => 'DifferentialController',
'DifferentialRevisionCloseTransaction' => 'DifferentialRevisionActionTransaction', 'DifferentialRevisionCloseTransaction' => 'DifferentialRevisionActionTransaction',
'DifferentialRevisionClosedStatusDatasource' => 'PhabricatorTypeaheadDatasource',
'DifferentialRevisionCommandeerTransaction' => 'DifferentialRevisionActionTransaction', 'DifferentialRevisionCommandeerTransaction' => 'DifferentialRevisionActionTransaction',
'DifferentialRevisionContentAddedHeraldField' => 'DifferentialRevisionHeraldField', 'DifferentialRevisionContentAddedHeraldField' => 'DifferentialRevisionHeraldField',
'DifferentialRevisionContentHeraldField' => 'DifferentialRevisionHeraldField', 'DifferentialRevisionContentHeraldField' => 'DifferentialRevisionHeraldField',
@ -5541,6 +5547,7 @@ phutil_register_library_map(array(
'DifferentialRevisionListController' => 'DifferentialController', 'DifferentialRevisionListController' => 'DifferentialController',
'DifferentialRevisionListView' => 'AphrontView', 'DifferentialRevisionListView' => 'AphrontView',
'DifferentialRevisionMailReceiver' => 'PhabricatorObjectMailReceiver', 'DifferentialRevisionMailReceiver' => 'PhabricatorObjectMailReceiver',
'DifferentialRevisionOpenStatusDatasource' => 'PhabricatorTypeaheadDatasource',
'DifferentialRevisionOperationController' => 'DifferentialController', 'DifferentialRevisionOperationController' => 'DifferentialController',
'DifferentialRevisionPHIDType' => 'PhabricatorPHIDType', 'DifferentialRevisionPHIDType' => 'PhabricatorPHIDType',
'DifferentialRevisionPackageHeraldField' => 'DifferentialRevisionHeraldField', 'DifferentialRevisionPackageHeraldField' => 'DifferentialRevisionHeraldField',
@ -5565,6 +5572,9 @@ phutil_register_library_map(array(
'DifferentialRevisionSearchConduitAPIMethod' => 'PhabricatorSearchEngineAPIMethod', 'DifferentialRevisionSearchConduitAPIMethod' => 'PhabricatorSearchEngineAPIMethod',
'DifferentialRevisionSearchEngine' => 'PhabricatorApplicationSearchEngine', 'DifferentialRevisionSearchEngine' => 'PhabricatorApplicationSearchEngine',
'DifferentialRevisionStatus' => 'Phobject', 'DifferentialRevisionStatus' => 'Phobject',
'DifferentialRevisionStatusDatasource' => 'PhabricatorTypeaheadDatasource',
'DifferentialRevisionStatusFunctionDatasource' => 'PhabricatorTypeaheadCompositeDatasource',
'DifferentialRevisionStatusTransaction' => 'DifferentialRevisionTransactionType',
'DifferentialRevisionSummaryHeraldField' => 'DifferentialRevisionHeraldField', 'DifferentialRevisionSummaryHeraldField' => 'DifferentialRevisionHeraldField',
'DifferentialRevisionSummaryTransaction' => 'DifferentialRevisionTransactionType', 'DifferentialRevisionSummaryTransaction' => 'DifferentialRevisionTransactionType',
'DifferentialRevisionTestPlanTransaction' => 'DifferentialRevisionTransactionType', 'DifferentialRevisionTestPlanTransaction' => 'DifferentialRevisionTransactionType',
@ -5768,6 +5778,7 @@ phutil_register_library_map(array(
'DiffusionPathQueryTestCase' => 'PhabricatorTestCase', 'DiffusionPathQueryTestCase' => 'PhabricatorTestCase',
'DiffusionPathTreeController' => 'DiffusionController', 'DiffusionPathTreeController' => 'DiffusionController',
'DiffusionPathValidateController' => 'DiffusionController', 'DiffusionPathValidateController' => 'DiffusionController',
'DiffusionPatternSearchView' => 'DiffusionView',
'DiffusionPhpExternalSymbolsSource' => 'DiffusionExternalSymbolsSource', 'DiffusionPhpExternalSymbolsSource' => 'DiffusionExternalSymbolsSource',
'DiffusionPreCommitContentAffectedFilesHeraldField' => 'DiffusionPreCommitContentHeraldField', 'DiffusionPreCommitContentAffectedFilesHeraldField' => 'DiffusionPreCommitContentHeraldField',
'DiffusionPreCommitContentAuthorHeraldField' => 'DiffusionPreCommitContentHeraldField', 'DiffusionPreCommitContentAuthorHeraldField' => 'DiffusionPreCommitContentHeraldField',
@ -10031,6 +10042,7 @@ phutil_register_library_map(array(
'PhamePostTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'PhamePostTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
'PhamePostTransactionType' => 'PhabricatorModularTransactionType', 'PhamePostTransactionType' => 'PhabricatorModularTransactionType',
'PhamePostViewController' => 'PhameLiveController', 'PhamePostViewController' => 'PhameLiveController',
'PhamePostViewsTransaction' => 'PhamePostTransactionType',
'PhamePostVisibilityTransaction' => 'PhamePostTransactionType', 'PhamePostVisibilityTransaction' => 'PhamePostTransactionType',
'PhameSchemaSpec' => 'PhabricatorConfigSchemaSpec', 'PhameSchemaSpec' => 'PhabricatorConfigSchemaSpec',
'PhameSite' => 'PhabricatorSite', 'PhameSite' => 'PhabricatorSite',

View file

@ -93,7 +93,7 @@ final class PhabricatorAuthSSHKeyEditController
try { try {
$editor->applyTransactions($key, $xactions); $editor->applyTransactions($key, $xactions);
return id(new AphrontRedirectResponse())->setURI($key->getURI()); return id(new AphrontRedirectResponse())->setURI($cancel_uri);
} catch (PhabricatorApplicationTransactionValidationException $ex) { } catch (PhabricatorApplicationTransactionValidationException $ex) {
$validation_exception = $ex; $validation_exception = $ex;
$e_name = $ex->getShortMessage($type_name); $e_name = $ex->getShortMessage($type_name);

View file

@ -50,9 +50,15 @@ final class PhabricatorDataCacheSpec extends PhabricatorCacheSpec {
->setVersion(phpversion('apcu')); ->setVersion(phpversion('apcu'));
if (ini_get('apc.enabled')) { if (ini_get('apc.enabled')) {
if (function_exists('apcu_clear_cache')) {
$clear_callback = 'apcu_clear_cache';
} else {
$clear_callback = 'apc_clear_cache';
}
$this $this
->setIsEnabled(true) ->setIsEnabled(true)
->setClearCacheCallback('apc_clear_cache'); ->setClearCacheCallback($clear_callback);
$this->initAPCCommonSpec(); $this->initAPCCommonSpec();
} else { } else {
$this->setIsEnabled(false); $this->setIsEnabled(false);

View file

@ -7,6 +7,12 @@ final class PhabricatorElasticsearchSetupCheck extends PhabricatorSetupCheck {
} }
protected function executeChecks() { protected function executeChecks() {
// TODO: Avoid fataling if we don't have a master database configured
// but have the MySQL search index configured. See T12965.
if (PhabricatorEnv::isReadOnly()) {
return;
}
$services = PhabricatorSearchService::getAllServices(); $services = PhabricatorSearchService::getAllServices();
foreach ($services as $service) { foreach ($services as $service) {

View file

@ -9,7 +9,13 @@ final class PhabricatorMySQLSetupCheck extends PhabricatorSetupCheck {
protected function executeChecks() { protected function executeChecks() {
$refs = PhabricatorDatabaseRef::getActiveDatabaseRefs(); $refs = PhabricatorDatabaseRef::getActiveDatabaseRefs();
foreach ($refs as $ref) { foreach ($refs as $ref) {
$this->executeRefChecks($ref); try {
$this->executeRefChecks($ref);
} catch (AphrontConnectionQueryException $ex) {
// If we're unable to connect to a host, just skip the checks for it.
// This can happen if we're restarting during a cluster incident. See
// T12966 for discussion.
}
} }
} }

View file

@ -52,8 +52,9 @@ final class DifferentialCloseConduitAPIMethod
$xactions = array(); $xactions = array();
$xactions[] = id(new DifferentialTransaction()) $xactions[] = id(new DifferentialTransaction())
->setTransactionType(DifferentialTransaction::TYPE_ACTION) ->setTransactionType(
->setNewValue(DifferentialAction::ACTION_CLOSE); DifferentialRevisionCloseTransaction::TRANSACTIONTYPE)
->setNewValue(true);
$content_source = $request->newContentSource(); $content_source = $request->newContentSource();

View file

@ -63,6 +63,7 @@ final class DifferentialCreateCommentConduitAPIMethod
'resign' => DifferentialRevisionResignTransaction::TRANSACTIONTYPE, 'resign' => DifferentialRevisionResignTransaction::TRANSACTIONTYPE,
'request_review' => 'request_review' =>
DifferentialRevisionRequestReviewTransaction::TRANSACTIONTYPE, DifferentialRevisionRequestReviewTransaction::TRANSACTIONTYPE,
'rethink' => DifferentialRevisionPlanChangesTransaction::TRANSACTIONTYPE,
); );
$action = $request->getValue('action'); $action = $request->getValue('action');
@ -76,9 +77,10 @@ final class DifferentialCreateCommentConduitAPIMethod
case 'none': case 'none':
break; break;
default: default:
$xactions[] = id(new DifferentialTransaction()) throw new Exception(
->setTransactionType(DifferentialTransaction::TYPE_ACTION) pht(
->setNewValue($action); 'Unsupported action "%s".',
$action));
break; break;
} }
} }

View file

@ -1,99 +0,0 @@
<?php
final class DifferentialFindConduitAPIMethod
extends DifferentialConduitAPIMethod {
public function getAPIMethodName() {
return 'differential.find';
}
public function getMethodStatus() {
return self::METHOD_STATUS_DEPRECATED;
}
public function getMethodStatusDescription() {
return pht("Replaced by '%s'.", 'differential.query');
}
public function getMethodDescription() {
return pht('Query Differential revisions which match certain criteria.');
}
protected function defineParamTypes() {
$types = array(
'open',
'committable',
'revision-ids',
'phids',
);
return array(
'query' => 'required '.$this->formatStringConstants($types),
'guids' => 'required nonempty list<guids>',
);
}
protected function defineReturnType() {
return 'nonempty list<dict>';
}
protected function execute(ConduitAPIRequest $request) {
$type = $request->getValue('query');
$guids = $request->getValue('guids');
$results = array();
if (!$guids) {
return $results;
}
$query = id(new DifferentialRevisionQuery())
->setViewer($request->getUser());
switch ($type) {
case 'open':
$query
->withStatus(DifferentialLegacyQuery::STATUS_OPEN)
->withAuthors($guids);
break;
case 'committable':
$query
->withStatus(DifferentialLegacyQuery::STATUS_ACCEPTED)
->withAuthors($guids);
break;
case 'revision-ids':
$query
->withIDs($guids);
break;
case 'owned':
$query->withAuthors($guids);
break;
case 'phids':
$query
->withPHIDs($guids);
break;
}
$revisions = $query->execute();
foreach ($revisions as $revision) {
$diff = $revision->loadActiveDiff();
if (!$diff) {
continue;
}
$id = $revision->getID();
$results[] = array(
'id' => $id,
'phid' => $revision->getPHID(),
'name' => $revision->getTitle(),
'uri' => PhabricatorEnv::getProductionURI('/D'.$id),
'dateCreated' => $revision->getDateCreated(),
'authorPHID' => $revision->getAuthorPHID(),
'statusName' => $revision->getStatusDisplayName(),
'sourcePath' => $diff->getSourcePath(),
);
}
return $results;
}
}

View file

@ -82,7 +82,7 @@ final class DifferentialGetRevisionConduitAPIMethod
'authorPHID' => $revision->getAuthorPHID(), 'authorPHID' => $revision->getAuthorPHID(),
'uri' => PhabricatorEnv::getURI('/D'.$revision->getID()), 'uri' => PhabricatorEnv::getURI('/D'.$revision->getID()),
'title' => $revision->getTitle(), 'title' => $revision->getTitle(),
'status' => $revision->getStatus(), 'status' => $revision->getLegacyRevisionStatus(),
'statusName' => $revision->getStatusDisplayName(), 'statusName' => $revision->getStatusDisplayName(),
'summary' => $revision->getSummary(), 'summary' => $revision->getSummary(),
'testPlan' => $revision->getTestPlan(), 'testPlan' => $revision->getTestPlan(),

View file

@ -150,7 +150,10 @@ final class DifferentialQueryConduitAPIMethod
} }
if ($status) { if ($status) {
$query->withStatus($status); $statuses = DifferentialLegacyQuery::getModernValues($status);
if ($statuses) {
$query->withStatuses($statuses);
}
} }
if ($order) { if ($order) {
$query->setOrder($order); $query->setOrder($order);
@ -215,7 +218,7 @@ final class DifferentialQueryConduitAPIMethod
'dateCreated' => $revision->getDateCreated(), 'dateCreated' => $revision->getDateCreated(),
'dateModified' => $revision->getDateModified(), 'dateModified' => $revision->getDateModified(),
'authorPHID' => $revision->getAuthorPHID(), 'authorPHID' => $revision->getAuthorPHID(),
'status' => $revision->getStatus(), 'status' => $revision->getLegacyRevisionStatus(),
'statusName' => $revision->getStatusDisplayName(), 'statusName' => $revision->getStatusDisplayName(),
'properties' => $revision->getProperties(), 'properties' => $revision->getProperties(),
'branch' => $diff->getBranch(), 'branch' => $diff->getBranch(),

View file

@ -15,7 +15,7 @@ final class DifferentialLegacyQuery
return array_keys(self::getMap()); return array_keys(self::getMap());
} }
public static function getQueryValues($status) { public static function getModernValues($status) {
if ($status === self::STATUS_ANY) { if ($status === self::STATUS_ANY) {
return null; return null;
} }
@ -28,18 +28,7 @@ final class DifferentialLegacyQuery
$status)); $status));
} }
$values = array(); return $map[$status];
foreach ($map[$status] as $status_constant) {
$status_object = DifferentialRevisionStatus::newForStatus(
$status_constant);
$legacy_key = $status_object->getLegacyKey();
if ($legacy_key !== null) {
$values[] = $legacy_key;
}
}
return $values;
} }
private static function getMap() { private static function getMap() {

View file

@ -32,6 +32,18 @@ final class DifferentialRevisionStatus extends Phobject {
return idx($this->spec, 'color.tag', 'bluegrey'); return idx($this->spec, 'color.tag', 'bluegrey');
} }
public function getTimelineIcon() {
return idx($this->spec, 'icon.timeline');
}
public function getTimelineColor() {
return idx($this->spec, 'color.timeline');
}
public function getANSIColor() {
return idx($this->spec, 'color.ansi');
}
public function getDisplayName() { public function getDisplayName() {
return idx($this->spec, 'name'); return idx($this->spec, 'name');
} }
@ -52,6 +64,10 @@ final class DifferentialRevisionStatus extends Phobject {
return ($this->key === self::NEEDS_REVIEW); return ($this->key === self::NEEDS_REVIEW);
} }
public function isNeedsRevision() {
return ($this->key === self::NEEDS_REVISION);
}
public function isPublished() { public function isPublished() {
return ($this->key === self::PUBLISHED); return ($this->key === self::PUBLISHED);
} }
@ -72,22 +88,11 @@ final class DifferentialRevisionStatus extends Phobject {
return $result; return $result;
} }
public static function newForLegacyStatus($legacy_status) { public static function getAll() {
$result = new self(); $result = array();
$map = self::getMap(); foreach (self::getMap() as $key => $spec) {
foreach ($map as $key => $spec) { $result[$key] = self::newForStatus($key);
if (!isset($spec['legacy'])) {
continue;
}
if ($spec['legacy'] != $legacy_status) {
continue;
}
$result->key = $key;
$result->spec = $spec;
break;
} }
return $result; return $result;
@ -102,19 +107,23 @@ final class DifferentialRevisionStatus extends Phobject {
'name' => pht('Needs Review'), 'name' => pht('Needs Review'),
'legacy' => 0, 'legacy' => 0,
'icon' => 'fa-code', 'icon' => 'fa-code',
'icon.timeline' => 'fa-undo',
'closed' => false, 'closed' => false,
'color.icon' => 'grey', 'color.icon' => 'grey',
'color.tag' => 'bluegrey', 'color.tag' => 'bluegrey',
'color.ansi' => 'magenta', 'color.ansi' => 'magenta',
'color.timeline' => 'orange',
), ),
self::NEEDS_REVISION => array( self::NEEDS_REVISION => array(
'name' => pht('Needs Revision'), 'name' => pht('Needs Revision'),
'legacy' => 1, 'legacy' => 1,
'icon' => 'fa-refresh', 'icon' => 'fa-refresh',
'icon.timeline' => 'fa-times',
'closed' => false, 'closed' => false,
'color.icon' => 'red', 'color.icon' => 'red',
'color.tag' => 'red', 'color.tag' => 'red',
'color.ansi' => 'red', 'color.ansi' => 'red',
'color.timeline' => 'red',
), ),
self::CHANGES_PLANNED => array( self::CHANGES_PLANNED => array(
'name' => pht('Changes Planned'), 'name' => pht('Changes Planned'),
@ -129,10 +138,12 @@ final class DifferentialRevisionStatus extends Phobject {
'name' => pht('Accepted'), 'name' => pht('Accepted'),
'legacy' => 2, 'legacy' => 2,
'icon' => 'fa-check', 'icon' => 'fa-check',
'icon.timeline' => 'fa-check',
'closed' => $close_on_accept, 'closed' => $close_on_accept,
'color.icon' => 'green', 'color.icon' => 'green',
'color.tag' => 'green', 'color.tag' => 'green',
'color.ansi' => 'green', 'color.ansi' => 'green',
'color.timeline' => 'green',
), ),
self::PUBLISHED => array( self::PUBLISHED => array(
'name' => pht('Closed'), 'name' => pht('Closed'),

View file

@ -177,7 +177,7 @@ final class DifferentialDiffViewController extends DifferentialController {
$revisions = id(new DifferentialRevisionQuery()) $revisions = id(new DifferentialRevisionQuery())
->setViewer($viewer) ->setViewer($viewer)
->withAuthors(array($viewer->getPHID())) ->withAuthors(array($viewer->getPHID()))
->withStatus(DifferentialLegacyQuery::STATUS_OPEN) ->withIsOpen(true)
->requireCapabilities( ->requireCapabilities(
array( array(
PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_VIEW,

View file

@ -808,7 +808,7 @@ final class DifferentialRevisionViewController extends DifferentialController {
$query = id(new DifferentialRevisionQuery()) $query = id(new DifferentialRevisionQuery())
->setViewer($this->getRequest()->getUser()) ->setViewer($this->getRequest()->getUser())
->withStatus(DifferentialLegacyQuery::STATUS_OPEN) ->withIsOpen(true)
->withUpdatedEpochBetween($recent, null) ->withUpdatedEpochBetween($recent, null)
->setOrder(DifferentialRevisionQuery::ORDER_MODIFIED) ->setOrder(DifferentialRevisionQuery::ORDER_MODIFIED)
->setLimit(10) ->setLimit(10)

View file

@ -69,9 +69,7 @@ final class DifferentialTransactionEditor
$types[] = PhabricatorTransactions::TYPE_EDIT_POLICY; $types[] = PhabricatorTransactions::TYPE_EDIT_POLICY;
$types[] = PhabricatorTransactions::TYPE_INLINESTATE; $types[] = PhabricatorTransactions::TYPE_INLINESTATE;
$types[] = DifferentialTransaction::TYPE_ACTION;
$types[] = DifferentialTransaction::TYPE_INLINE; $types[] = DifferentialTransaction::TYPE_INLINE;
$types[] = DifferentialTransaction::TYPE_STATUS;
$types[] = DifferentialTransaction::TYPE_UPDATE; $types[] = DifferentialTransaction::TYPE_UPDATE;
return $types; return $types;
@ -82,8 +80,6 @@ final class DifferentialTransactionEditor
PhabricatorApplicationTransaction $xaction) { PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) { switch ($xaction->getTransactionType()) {
case DifferentialTransaction::TYPE_ACTION:
return null;
case DifferentialTransaction::TYPE_INLINE: case DifferentialTransaction::TYPE_INLINE:
return null; return null;
case DifferentialTransaction::TYPE_UPDATE: case DifferentialTransaction::TYPE_UPDATE:
@ -102,7 +98,6 @@ final class DifferentialTransactionEditor
PhabricatorApplicationTransaction $xaction) { PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) { switch ($xaction->getTransactionType()) {
case DifferentialTransaction::TYPE_ACTION:
case DifferentialTransaction::TYPE_UPDATE: case DifferentialTransaction::TYPE_UPDATE:
return $xaction->getNewValue(); return $xaction->getNewValue();
case DifferentialTransaction::TYPE_INLINE: case DifferentialTransaction::TYPE_INLINE:
@ -121,28 +116,6 @@ final class DifferentialTransactionEditor
switch ($xaction->getTransactionType()) { switch ($xaction->getTransactionType()) {
case DifferentialTransaction::TYPE_INLINE: case DifferentialTransaction::TYPE_INLINE:
return $xaction->hasComment(); return $xaction->hasComment();
case DifferentialTransaction::TYPE_ACTION:
$status_closed = ArcanistDifferentialRevisionStatus::CLOSED;
$status_abandoned = ArcanistDifferentialRevisionStatus::ABANDONED;
$status_review = ArcanistDifferentialRevisionStatus::NEEDS_REVIEW;
$status_revision = ArcanistDifferentialRevisionStatus::NEEDS_REVISION;
$status_plan = ArcanistDifferentialRevisionStatus::CHANGES_PLANNED;
$action_type = $xaction->getNewValue();
switch ($action_type) {
case DifferentialAction::ACTION_CLOSE:
return ($object->getStatus() != $status_closed);
case DifferentialAction::ACTION_ABANDON:
return ($object->getStatus() != $status_abandoned);
case DifferentialAction::ACTION_RECLAIM:
return ($object->getStatus() == $status_abandoned);
case DifferentialAction::ACTION_REOPEN:
return ($object->getStatus() == $status_closed);
case DifferentialAction::ACTION_RETHINK:
return ($object->getStatus() != $status_plan);
case DifferentialAction::ACTION_CLAIM:
return ($actor_phid != $object->getAuthorPHID());
}
} }
return parent::transactionHasEffect($object, $xaction); return parent::transactionHasEffect($object, $xaction);
@ -152,23 +125,16 @@ final class DifferentialTransactionEditor
PhabricatorLiskDAO $object, PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) { PhabricatorApplicationTransaction $xaction) {
$status_review = ArcanistDifferentialRevisionStatus::NEEDS_REVIEW;
$status_revision = ArcanistDifferentialRevisionStatus::NEEDS_REVISION;
$status_plan = ArcanistDifferentialRevisionStatus::CHANGES_PLANNED;
$status_abandoned = ArcanistDifferentialRevisionStatus::ABANDONED;
$status_accepted = ArcanistDifferentialRevisionStatus::ACCEPTED;
switch ($xaction->getTransactionType()) { switch ($xaction->getTransactionType()) {
case DifferentialTransaction::TYPE_INLINE: case DifferentialTransaction::TYPE_INLINE:
return; return;
case DifferentialTransaction::TYPE_UPDATE: case DifferentialTransaction::TYPE_UPDATE:
if (!$this->getIsCloseByCommit()) { if (!$this->getIsCloseByCommit()) {
switch ($object->getStatus()) { if ($object->isNeedsRevision() ||
case $status_revision: $object->isChangePlanned() ||
case $status_plan: $object->isAbandoned()) {
case $status_abandoned: $object->setModernRevisionStatus(
$object->setStatus($status_review); DifferentialRevisionStatus::NEEDS_REVIEW);
break;
} }
} }
@ -184,38 +150,6 @@ final class DifferentialTransactionEditor
// TODO: Update the `diffPHID` once we add that. // TODO: Update the `diffPHID` once we add that.
return; return;
case DifferentialTransaction::TYPE_ACTION:
switch ($xaction->getNewValue()) {
case DifferentialAction::ACTION_ABANDON:
$object->setStatus(ArcanistDifferentialRevisionStatus::ABANDONED);
return;
case DifferentialAction::ACTION_RETHINK:
$object->setStatus($status_plan);
return;
case DifferentialAction::ACTION_RECLAIM:
$object->setStatus($status_review);
return;
case DifferentialAction::ACTION_REOPEN:
$object->setStatus($status_review);
return;
case DifferentialAction::ACTION_CLOSE:
$old_status = $object->getStatus();
$object->setStatus(ArcanistDifferentialRevisionStatus::CLOSED);
$was_accepted = ($old_status == $status_accepted);
$object->setProperty(
DifferentialRevision::PROPERTY_CLOSED_FROM_ACCEPTED,
$was_accepted);
return;
case DifferentialAction::ACTION_CLAIM:
$object->setAuthorPHID($this->getActingAsPHID());
return;
default:
throw new Exception(
pht(
'Differential action "%s" is not a valid action!',
$xaction->getNewValue()));
}
break;
} }
return parent::applyCustomInternalTransaction($object, $xaction); return parent::applyCustomInternalTransaction($object, $xaction);
@ -255,9 +189,6 @@ final class DifferentialTransactionEditor
$actor_phid = $this->getActingAsPHID(); $actor_phid = $this->getActingAsPHID();
$type_edge = PhabricatorTransactions::TYPE_EDGE; $type_edge = PhabricatorTransactions::TYPE_EDGE;
$status_plan = ArcanistDifferentialRevisionStatus::CHANGES_PLANNED;
$edge_reviewer = DifferentialRevisionHasReviewerEdgeType::EDGECONST;
$edge_ref_task = DifferentialRevisionHasTaskEdgeType::EDGECONST; $edge_ref_task = DifferentialRevisionHasTaskEdgeType::EDGECONST;
$is_sticky_accept = PhabricatorEnv::getEnvConfig( $is_sticky_accept = PhabricatorEnv::getEnvConfig(
@ -280,7 +211,7 @@ final class DifferentialTransactionEditor
case DifferentialRevisionRequestReviewTransaction::TRANSACTIONTYPE: case DifferentialRevisionRequestReviewTransaction::TRANSACTIONTYPE:
$downgrade_rejects = true; $downgrade_rejects = true;
if ((!$is_sticky_accept) || if ((!$is_sticky_accept) ||
($object->getStatus() != $status_plan)) { (!$object->isChangePlanned())) {
// If the old state isn't "changes planned", downgrade the accepts. // If the old state isn't "changes planned", downgrade the accepts.
// This exception allows an accepted revision to go through // This exception allows an accepted revision to go through
// "Plan Changes" -> "Request Review" and return to "accepted" if // "Plan Changes" -> "Request Review" and return to "accepted" if
@ -297,48 +228,6 @@ final class DifferentialTransactionEditor
$old_accept = DifferentialReviewerStatus::STATUS_ACCEPTED_OLDER; $old_accept = DifferentialReviewerStatus::STATUS_ACCEPTED_OLDER;
$old_reject = DifferentialReviewerStatus::STATUS_REJECTED_OLDER; $old_reject = DifferentialReviewerStatus::STATUS_REJECTED_OLDER;
if ($downgrade_rejects || $downgrade_accepts) {
// When a revision is updated, change all "reject" to "rejected older
// revision". This means we won't immediately push the update back into
// "needs review", but outstanding rejects will still block it from
// moving to "accepted".
// We also do this for "Request Review", even though the diff is not
// updated directly. Essentially, this acts like an update which doesn't
// actually change the diff text.
$edits = array();
foreach ($object->getReviewers() as $reviewer) {
if ($downgrade_rejects) {
if ($reviewer->getReviewerStatus() == $new_reject) {
$edits[$reviewer->getReviewerPHID()] = array(
'data' => array(
'status' => $old_reject,
),
);
}
}
if ($downgrade_accepts) {
if ($reviewer->getReviewerStatus() == $new_accept) {
$edits[$reviewer->getReviewerPHID()] = array(
'data' => array(
'status' => $old_accept,
),
);
}
}
}
if ($edits) {
$results[] = id(new DifferentialTransaction())
->setTransactionType($type_edge)
->setMetadataValue('edge:type', $edge_reviewer)
->setIgnoreOnNoEffect(true)
->setNewValue(array('+' => $edits));
}
}
$downgrade = array(); $downgrade = array();
if ($downgrade_accepts) { if ($downgrade_accepts) {
$downgrade[] = DifferentialReviewerStatus::STATUS_ACCEPTED; $downgrade[] = DifferentialReviewerStatus::STATUS_ACCEPTED;
@ -397,56 +286,9 @@ final class DifferentialTransactionEditor
} }
break; break;
case PhabricatorTransactions::TYPE_COMMENT:
// When a user leaves a comment, upgrade their reviewer status from
// "added" to "commented" if they're also a reviewer. We may further
// upgrade this based on other actions in the transaction group.
if ($this->hasReviewTransaction) {
// If we're also applying a review transaction, skip this.
break;
}
$status_added = DifferentialReviewerStatus::STATUS_ADDED;
$status_commented = DifferentialReviewerStatus::STATUS_COMMENTED;
$data = array(
'status' => $status_commented,
);
$edits = array();
foreach ($object->getReviewers() as $reviewer) {
if ($reviewer->getReviewerPHID() == $actor_phid) {
if ($reviewer->getReviewerStatus() == $status_added) {
$edits[$actor_phid] = array(
'data' => $data,
);
}
}
}
if ($edits) {
$results[] = id(new DifferentialTransaction())
->setTransactionType($type_edge)
->setMetadataValue('edge:type', $edge_reviewer)
->setIgnoreOnNoEffect(true)
->setNewValue(array('+' => $edits));
}
break;
case DifferentialRevisionCommandeerTransaction::TRANSACTIONTYPE: case DifferentialRevisionCommandeerTransaction::TRANSACTIONTYPE:
$is_commandeer = true; $is_commandeer = true;
break; break;
case DifferentialTransaction::TYPE_ACTION:
$action_type = $xaction->getNewValue();
switch ($action_type) {
case DifferentialAction::ACTION_CLAIM:
$is_commandeer = true;
break;
}
break;
} }
if ($is_commandeer) { if ($is_commandeer) {
@ -456,7 +298,6 @@ final class DifferentialTransactionEditor
if (!$this->didExpandInlineState) { if (!$this->didExpandInlineState) {
switch ($xaction->getTransactionType()) { switch ($xaction->getTransactionType()) {
case PhabricatorTransactions::TYPE_COMMENT: case PhabricatorTransactions::TYPE_COMMENT:
case DifferentialTransaction::TYPE_ACTION:
case DifferentialTransaction::TYPE_UPDATE: case DifferentialTransaction::TYPE_UPDATE:
case DifferentialTransaction::TYPE_INLINE: case DifferentialTransaction::TYPE_INLINE:
$this->didExpandInlineState = true; $this->didExpandInlineState = true;
@ -502,8 +343,6 @@ final class DifferentialTransactionEditor
PhabricatorApplicationTransaction $xaction) { PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) { switch ($xaction->getTransactionType()) {
case DifferentialTransaction::TYPE_ACTION:
return;
case DifferentialTransaction::TYPE_INLINE: case DifferentialTransaction::TYPE_INLINE:
$reply = $xaction->getComment()->getReplyToComment(); $reply = $xaction->getComment()->getReplyToComment();
if ($reply && !$reply->getHasReplies()) { if ($reply && !$reply->getHasReplies()) {
@ -575,33 +414,6 @@ final class DifferentialTransactionEditor
return parent::applyBuiltinExternalTransaction($object, $xaction); return parent::applyBuiltinExternalTransaction($object, $xaction);
} }
protected function mergeEdgeData($type, array $u, array $v) {
$result = parent::mergeEdgeData($type, $u, $v);
switch ($type) {
case DifferentialRevisionHasReviewerEdgeType::EDGECONST:
// When the same reviewer has their status updated by multiple
// transactions, we want the strongest status to win. An example of
// this is when a user adds a comment and also accepts a revision which
// they are a reviewer on. The comment creates a "commented" status,
// while the accept creates an "accepted" status. Since accept is
// stronger, it should win and persist.
$u_status = idx($u, 'status');
$v_status = idx($v, 'status');
$u_str = DifferentialReviewerStatus::getStatusStrength($u_status);
$v_str = DifferentialReviewerStatus::getStatusStrength($v_status);
if ($u_str > $v_str) {
$result['status'] = $u_status;
} else {
$result['status'] = $v_status;
}
break;
}
return $result;
}
protected function applyFinalEffects( protected function applyFinalEffects(
PhabricatorLiskDAO $object, PhabricatorLiskDAO $object,
array $xactions) { array $xactions) {
@ -641,101 +453,112 @@ final class DifferentialTransactionEditor
} }
} }
$status_accepted = ArcanistDifferentialRevisionStatus::ACCEPTED; $xactions = $this->updateReviewStatus($object, $xactions);
$status_revision = ArcanistDifferentialRevisionStatus::NEEDS_REVISION;
$status_review = ArcanistDifferentialRevisionStatus::NEEDS_REVIEW;
$is_sticky_accept = PhabricatorEnv::getEnvConfig(
'differential.sticky-accept');
$old_status = $object->getStatus();
$active_diff = $object->getActiveDiff();
switch ($old_status) {
case $status_accepted:
case $status_revision:
case $status_review:
// Try to move a revision to "accepted". We look for:
//
// - at least one accepting reviewer who is a user; and
// - no rejects; and
// - no rejects of older diffs; and
// - no blocking reviewers.
$has_accepting_user = false;
$has_rejecting_reviewer = false;
$has_rejecting_older_reviewer = false;
$has_blocking_reviewer = false;
foreach ($object->getReviewers() as $reviewer) {
$reviewer_status = $reviewer->getReviewerStatus();
switch ($reviewer_status) {
case DifferentialReviewerStatus::STATUS_REJECTED:
$active_phid = $active_diff->getPHID();
if ($reviewer->isRejected($active_phid)) {
$has_rejecting_reviewer = true;
} else {
$has_rejecting_older_reviewer = true;
}
break;
case DifferentialReviewerStatus::STATUS_REJECTED_OLDER:
$has_rejecting_older_reviewer = true;
break;
case DifferentialReviewerStatus::STATUS_BLOCKING:
$has_blocking_reviewer = true;
break;
case DifferentialReviewerStatus::STATUS_ACCEPTED:
if ($reviewer->isUser()) {
$active_phid = $active_diff->getPHID();
if ($reviewer->isAccepted($active_phid)) {
$has_accepting_user = true;
}
}
break;
}
}
$new_status = null;
if ($has_accepting_user &&
!$has_rejecting_reviewer &&
!$has_rejecting_older_reviewer &&
!$has_blocking_reviewer) {
$new_status = $status_accepted;
} else if ($has_rejecting_reviewer) {
// This isn't accepted, and there's at least one rejecting reviewer,
// so the revision needs changes. This usually happens after a
// "reject".
$new_status = $status_revision;
} else if ($old_status == $status_accepted) {
// This revision was accepted, but it no longer satisfies the
// conditions for acceptance. This usually happens after an accepting
// reviewer resigns or is removed.
$new_status = $status_review;
}
if ($new_status !== null && ($new_status != $old_status)) {
$xaction = id(new DifferentialTransaction())
->setTransactionType(DifferentialTransaction::TYPE_STATUS)
->setOldValue($old_status)
->setNewValue($new_status);
$xaction = $this->populateTransaction($object, $xaction)->save();
$xactions[] = $xaction;
$object->setStatus($new_status)->save();
}
break;
default:
// Revisions can't transition out of other statuses (like closed or
// abandoned) as a side effect of reviewer status changes.
break;
}
$this->markReviewerComments($object, $xactions); $this->markReviewerComments($object, $xactions);
return $xactions; return $xactions;
} }
private function updateReviewStatus(
DifferentialRevision $revision,
array $xactions) {
$was_accepted = $revision->isAccepted();
$was_revision = $revision->isNeedsRevision();
$was_review = $revision->isNeedsReview();
if (!$was_accepted && !$was_revision && !$was_review) {
// Revisions can't transition out of other statuses (like closed or
// abandoned) as a side effect of reviewer status changes.
return $xactions;
}
// Try to move a revision to "accepted". We look for:
//
// - at least one accepting reviewer who is a user; and
// - no rejects; and
// - no rejects of older diffs; and
// - no blocking reviewers.
$has_accepting_user = false;
$has_rejecting_reviewer = false;
$has_rejecting_older_reviewer = false;
$has_blocking_reviewer = false;
$active_diff = $revision->getActiveDiff();
foreach ($revision->getReviewers() as $reviewer) {
$reviewer_status = $reviewer->getReviewerStatus();
switch ($reviewer_status) {
case DifferentialReviewerStatus::STATUS_REJECTED:
$active_phid = $active_diff->getPHID();
if ($reviewer->isRejected($active_phid)) {
$has_rejecting_reviewer = true;
} else {
$has_rejecting_older_reviewer = true;
}
break;
case DifferentialReviewerStatus::STATUS_REJECTED_OLDER:
$has_rejecting_older_reviewer = true;
break;
case DifferentialReviewerStatus::STATUS_BLOCKING:
$has_blocking_reviewer = true;
break;
case DifferentialReviewerStatus::STATUS_ACCEPTED:
if ($reviewer->isUser()) {
$active_phid = $active_diff->getPHID();
if ($reviewer->isAccepted($active_phid)) {
$has_accepting_user = true;
}
}
break;
}
}
$new_status = null;
if ($has_accepting_user &&
!$has_rejecting_reviewer &&
!$has_rejecting_older_reviewer &&
!$has_blocking_reviewer) {
$new_status = DifferentialRevisionStatus::ACCEPTED;
} else if ($has_rejecting_reviewer) {
// This isn't accepted, and there's at least one rejecting reviewer,
// so the revision needs changes. This usually happens after a
// "reject".
$new_status = DifferentialRevisionStatus::NEEDS_REVISION;
} else if ($was_accepted) {
// This revision was accepted, but it no longer satisfies the
// conditions for acceptance. This usually happens after an accepting
// reviewer resigns or is removed.
$new_status = DifferentialRevisionStatus::NEEDS_REVIEW;
}
if ($new_status === null) {
return $xactions;
}
$old_status = $revision->getModernRevisionStatus();
if ($new_status == $old_status) {
return $xactions;
}
$xaction = id(new DifferentialTransaction())
->setTransactionType(
DifferentialRevisionStatusTransaction::TRANSACTIONTYPE)
->setOldValue($old_status)
->setNewValue($new_status);
$xaction = $this->populateTransaction($revision, $xaction)
->save();
$xactions[] = $xaction;
// Save the status adjustment we made earlier.
$revision
->setModernRevisionStatus($new_status)
->save();
return $xactions;
}
protected function validateTransaction( protected function validateTransaction(
PhabricatorLiskDAO $object, PhabricatorLiskDAO $object,
$type, $type,
@ -748,40 +571,6 @@ final class DifferentialTransactionEditor
foreach ($xactions as $xaction) { foreach ($xactions as $xaction) {
switch ($type) { switch ($type) {
case PhabricatorTransactions::TYPE_EDGE:
switch ($xaction->getMetadataValue('edge:type')) {
case DifferentialRevisionHasReviewerEdgeType::EDGECONST:
// Prevent the author from becoming a reviewer.
// NOTE: This is pretty gross, but this restriction is unusual.
// If we end up with too much more of this, we should try to clean
// this up -- maybe by moving validation to after transactions
// are adjusted (so we can just examine the final value) or adding
// a second phase there?
$author_phid = $object->getAuthorPHID();
$new = $xaction->getNewValue();
$add = idx($new, '+', array());
$eq = idx($new, '=', array());
$phids = array_keys($add + $eq);
foreach ($phids as $phid) {
if (($phid == $author_phid) &&
!$allow_self_accept &&
!$xaction->getIsCommandeerSideEffect()) {
$errors[] =
new PhabricatorApplicationTransactionValidationError(
$type,
pht('Invalid'),
pht('The author of a revision can not be a reviewer.'),
$xaction);
}
}
break;
}
break;
case DifferentialTransaction::TYPE_UPDATE: case DifferentialTransaction::TYPE_UPDATE:
$diff = $this->loadDiff($xaction->getNewValue()); $diff = $this->loadDiff($xaction->getNewValue());
if (!$diff) { if (!$diff) {
@ -801,172 +590,12 @@ final class DifferentialTransactionEditor
$xaction); $xaction);
} }
break; break;
case DifferentialTransaction::TYPE_ACTION:
$error = $this->validateDifferentialAction(
$object,
$type,
$xaction,
$xaction->getNewValue());
if ($error) {
$errors[] = new PhabricatorApplicationTransactionValidationError(
$type,
pht('Invalid'),
$error,
$xaction);
}
break;
} }
} }
return $errors; return $errors;
} }
private function validateDifferentialAction(
DifferentialRevision $revision,
$type,
DifferentialTransaction $xaction,
$action) {
$author_phid = $revision->getAuthorPHID();
$actor_phid = $this->getActingAsPHID();
$actor_is_author = ($author_phid == $actor_phid);
$config_abandon_key = 'differential.always-allow-abandon';
$always_allow_abandon = PhabricatorEnv::getEnvConfig($config_abandon_key);
$config_close_key = 'differential.always-allow-close';
$always_allow_close = PhabricatorEnv::getEnvConfig($config_close_key);
$config_reopen_key = 'differential.allow-reopen';
$allow_reopen = PhabricatorEnv::getEnvConfig($config_reopen_key);
$config_self_accept_key = 'differential.allow-self-accept';
$allow_self_accept = PhabricatorEnv::getEnvConfig($config_self_accept_key);
$revision_status = $revision->getStatus();
$status_accepted = ArcanistDifferentialRevisionStatus::ACCEPTED;
$status_abandoned = ArcanistDifferentialRevisionStatus::ABANDONED;
$status_closed = ArcanistDifferentialRevisionStatus::CLOSED;
switch ($action) {
case DifferentialAction::ACTION_CLAIM:
// You can claim a revision if you're not the owner. If you are, this
// is a no-op rather than invalid.
if ($revision_status == $status_closed) {
return pht(
'You can not commandeer this revision because it has already been '.
'closed.');
}
break;
case DifferentialAction::ACTION_ABANDON:
if (!$actor_is_author && !$always_allow_abandon) {
return pht(
'You can not abandon this revision because you do not own it. '.
'You can only abandon revisions you own.');
}
if ($revision_status == $status_closed) {
return pht(
'You can not abandon this revision because it has already been '.
'closed.');
}
// NOTE: Abandons of already-abandoned revisions are treated as no-op
// instead of invalid. Other abandons are OK.
break;
case DifferentialAction::ACTION_RECLAIM:
if (!$actor_is_author) {
return pht(
'You can not reclaim this revision because you do not own '.
'it. You can only reclaim revisions you own.');
}
if ($revision_status == $status_closed) {
return pht(
'You can not reclaim this revision because it has already been '.
'closed.');
}
// NOTE: Reclaims of other non-abandoned revisions are treated as no-op
// instead of invalid.
break;
case DifferentialAction::ACTION_REOPEN:
if (!$allow_reopen) {
return pht(
'The reopen action is not enabled on this Phabricator install. '.
'Adjust your configuration to enable it.');
}
// NOTE: If the revision is not closed, this is caught as a no-op
// instead of an invalid transaction.
break;
case DifferentialAction::ACTION_RETHINK:
if (!$actor_is_author) {
return pht(
'You can not plan changes to this revision because you do not '.
'own it. To plan changes to a revision, you must be its owner.');
}
switch ($revision_status) {
case ArcanistDifferentialRevisionStatus::ACCEPTED:
case ArcanistDifferentialRevisionStatus::NEEDS_REVISION:
case ArcanistDifferentialRevisionStatus::NEEDS_REVIEW:
// These are OK.
break;
case ArcanistDifferentialRevisionStatus::CHANGES_PLANNED:
// Let this through, it's a no-op.
break;
case ArcanistDifferentialRevisionStatus::ABANDONED:
return pht(
'You can not plan changes to this revision because it has '.
'been abandoned.');
case ArcanistDifferentialRevisionStatus::CLOSED:
return pht(
'You can not plan changes to this revision because it has '.
'already been closed.');
default:
throw new Exception(
pht(
'Encountered unexpected revision status ("%s") when '.
'validating "%s" action.',
$revision_status,
$action));
}
break;
case DifferentialAction::ACTION_CLOSE:
// We force revisions closed when we discover a corresponding commit.
// In this case, revisions are allowed to transition to closed from
// any state. This is an automated action taken by the daemons.
if (!$this->getIsCloseByCommit()) {
if (!$actor_is_author && !$always_allow_close) {
return pht(
'You can not close this revision because you do not own it. To '.
'close a revision, you must be its owner.');
}
if ($revision_status != $status_accepted) {
return pht(
'You can not close this revision because it has not been '.
'accepted. You can only close accepted revisions.');
}
}
break;
}
return null;
}
protected function sortTransactions(array $xactions) { protected function sortTransactions(array $xactions) {
$xactions = parent::sortTransactions($xactions); $xactions = parent::sortTransactions($xactions);
@ -1374,14 +1003,6 @@ final class DifferentialTransactionEditor
// When users commandeer revisions, we may need to trigger // When users commandeer revisions, we may need to trigger
// signatures or author-based rules. // signatures or author-based rules.
return true; return true;
case DifferentialTransaction::TYPE_ACTION:
switch ($xaction->getNewValue()) {
case DifferentialAction::ACTION_CLAIM:
// When users commandeer revisions, we may need to trigger
// signatures or author-based rules.
return true;
}
break;
} }
} }

View file

@ -33,7 +33,6 @@ final class DifferentialRevisionPHIDType extends PhabricatorPHIDType {
$revision = $objects[$phid]; $revision = $objects[$phid];
$title = $revision->getTitle(); $title = $revision->getTitle();
$status = $revision->getStatus();
$monogram = $revision->getMonogram(); $monogram = $revision->getMonogram();
$uri = $revision->getURI(); $uri = $revision->getURI();
@ -46,10 +45,8 @@ final class DifferentialRevisionPHIDType extends PhabricatorPHIDType {
$handle->setStatus(PhabricatorObjectHandle::STATUS_CLOSED); $handle->setStatus(PhabricatorObjectHandle::STATUS_CLOSED);
} }
$status = $revision->getStatus(); $icon = $revision->getStatusIcon();
$color = $revision->getStatusIconColor();
$icon = $revision->getStatusIcon($status);
$color = $revision->getStatusIconColor($status);
$name = $revision->getStatusDisplayName(); $name = $revision->getStatusDisplayName();
$handle $handle

View file

@ -10,8 +10,6 @@ final class DifferentialRevisionQuery
private $pathIDs = array(); private $pathIDs = array();
private $status = 'status-any';
private $authors = array(); private $authors = array();
private $draftAuthors = array(); private $draftAuthors = array();
private $ccs = array(); private $ccs = array();
@ -25,6 +23,8 @@ final class DifferentialRevisionQuery
private $repositoryPHIDs; private $repositoryPHIDs;
private $updatedEpochMin; private $updatedEpochMin;
private $updatedEpochMax; private $updatedEpochMax;
private $statuses;
private $isOpen;
const ORDER_MODIFIED = 'order-modified'; const ORDER_MODIFIED = 'order-modified';
const ORDER_CREATED = 'order-created'; const ORDER_CREATED = 'order-created';
@ -133,16 +133,13 @@ final class DifferentialRevisionQuery
return $this; return $this;
} }
/** public function withStatuses(array $statuses) {
* Filter results to revisions with a given status. Provide a class constant, $this->statuses = $statuses;
* such as `DifferentialLegacyQuery::STATUS_OPEN`. return $this;
* }
* @param const Class STATUS constant, like STATUS_OPEN.
* @return this public function withIsOpen($is_open) {
* @task config $this->isOpen = $is_open;
*/
public function withStatus($status_constant) {
$this->status = $status_constant;
return $this; return $this;
} }
@ -694,14 +691,24 @@ final class DifferentialRevisionQuery
$this->updatedEpochMax); $this->updatedEpochMax);
} }
// NOTE: Although the status constants are integers in PHP, the column is a if ($this->statuses !== null) {
// string column in MySQL, and MySQL won't use keys on string columns if
// you put integers in the query.
$statuses = DifferentialLegacyQuery::getQueryValues($this->status);
if ($statuses !== null) {
$where[] = qsprintf( $where[] = qsprintf(
$conn_r, $conn_r,
'r.status IN (%Ls)', 'r.status in (%Ls)',
$this->statuses);
}
if ($this->isOpen !== null) {
if ($this->isOpen) {
$statuses = DifferentialLegacyQuery::getModernValues(
DifferentialLegacyQuery::STATUS_OPEN);
} else {
$statuses = DifferentialLegacyQuery::getModernValues(
DifferentialLegacyQuery::STATUS_CLOSED);
}
$where[] = qsprintf(
$conn_r,
'r.status in (%Ls)',
$statuses); $statuses);
} }

View file

@ -151,9 +151,8 @@ final class DifferentialRevisionRequiredActionResultBucket
private function filterShouldUpdate(array $phids) { private function filterShouldUpdate(array $phids) {
$statuses = array( $statuses = array(
ArcanistDifferentialRevisionStatus::NEEDS_REVISION, DifferentialRevisionStatus::NEEDS_REVISION,
ArcanistDifferentialRevisionStatus::CHANGES_PLANNED, DifferentialRevisionStatus::CHANGES_PLANNED,
ArcanistDifferentialRevisionStatus::IN_PREPARATION,
); );
$statuses = array_fuse($statuses); $statuses = array_fuse($statuses);
@ -161,7 +160,7 @@ final class DifferentialRevisionRequiredActionResultBucket
$results = array(); $results = array();
foreach ($objects as $key => $object) { foreach ($objects as $key => $object) {
if (empty($statuses[$object->getStatus()])) { if (empty($statuses[$object->getModernRevisionStatus()])) {
continue; continue;
} }
@ -190,10 +189,9 @@ final class DifferentialRevisionRequiredActionResultBucket
private function filterWaitingOnAuthors(array $phids) { private function filterWaitingOnAuthors(array $phids) {
$statuses = array( $statuses = array(
ArcanistDifferentialRevisionStatus::ACCEPTED, DifferentialRevisionStatus::ACCEPTED,
ArcanistDifferentialRevisionStatus::NEEDS_REVISION, DifferentialRevisionStatus::NEEDS_REVISION,
ArcanistDifferentialRevisionStatus::CHANGES_PLANNED, DifferentialRevisionStatus::CHANGES_PLANNED,
ArcanistDifferentialRevisionStatus::IN_PREPARATION,
); );
$statuses = array_fuse($statuses); $statuses = array_fuse($statuses);
@ -201,7 +199,7 @@ final class DifferentialRevisionRequiredActionResultBucket
$results = array(); $results = array();
foreach ($objects as $key => $object) { foreach ($objects as $key => $object) {
if (empty($statuses[$object->getStatus()])) { if (empty($statuses[$object->getModernRevisionStatus()])) {
continue; continue;
} }

View file

@ -41,8 +41,8 @@ final class DifferentialRevisionSearchEngine
$query->withRepositoryPHIDs($map['repositoryPHIDs']); $query->withRepositoryPHIDs($map['repositoryPHIDs']);
} }
if ($map['status']) { if ($map['statuses']) {
$query->withStatus($map['status']); $query->withStatuses($map['statuses']);
} }
return $query; return $query;
@ -77,10 +77,11 @@ final class DifferentialRevisionSearchEngine
->setDatasource(new DiffusionRepositoryFunctionDatasource()) ->setDatasource(new DiffusionRepositoryFunctionDatasource())
->setDescription( ->setDescription(
pht('Find revisions from specific repositories.')), pht('Find revisions from specific repositories.')),
id(new PhabricatorSearchSelectField()) id(new PhabricatorSearchDatasourceField())
->setLabel(pht('Status')) ->setLabel(pht('Statuses'))
->setKey('status') ->setKey('statuses')
->setOptions($this->getStatusOptions()) ->setAliases(array('status'))
->setDatasource(new DifferentialRevisionStatusFunctionDatasource())
->setDescription( ->setDescription(
pht('Find revisions with particular statuses.')), pht('Find revisions with particular statuses.')),
); );
@ -115,7 +116,7 @@ final class DifferentialRevisionSearchEngine
return $query return $query
->setParameter('responsiblePHIDs', array($viewer->getPHID())) ->setParameter('responsiblePHIDs', array($viewer->getPHID()))
->setParameter('status', DifferentialLegacyQuery::STATUS_OPEN) ->setParameter('statuses', array('open()'))
->setParameter('bucket', $bucket_key); ->setParameter('bucket', $bucket_key);
case 'authored': case 'authored':
return $query return $query
@ -267,7 +268,7 @@ final class DifferentialRevisionSearchEngine
$blocking_revisions = id(new DifferentialRevisionQuery()) $blocking_revisions = id(new DifferentialRevisionQuery())
->setViewer($viewer) ->setViewer($viewer)
->withPHIDs($revision_phids) ->withPHIDs($revision_phids)
->withStatus(DifferentialLegacyQuery::STATUS_OPEN) ->withIsOpen(true)
->execute(); ->execute();
$blocking_revisions = mpull($blocking_revisions, null, 'getPHID'); $blocking_revisions = mpull($blocking_revisions, null, 'getPHID');

View file

@ -72,7 +72,7 @@ final class DifferentialRevision extends DifferentialDAO
->attachRepository(null) ->attachRepository(null)
->attachActiveDiff(null) ->attachActiveDiff(null)
->attachReviewers(array()) ->attachReviewers(array())
->setStatus(ArcanistDifferentialRevisionStatus::NEEDS_REVIEW); ->setModernRevisionStatus(DifferentialRevisionStatus::NEEDS_REVIEW);
} }
protected function getConfiguration() { protected function getConfiguration() {
@ -612,6 +612,18 @@ final class DifferentialRevision extends DifferentialDAO
return $this; return $this;
} }
public function setModernRevisionStatus($status) {
return $this->setStatus($status);
}
public function getModernRevisionStatus() {
return $this->getStatus();
}
public function getLegacyRevisionStatus() {
return $this->getStatusObject()->getLegacyKey();
}
public function isClosed() { public function isClosed() {
return $this->getStatusObject()->isClosedStatus(); return $this->getStatusObject()->isClosedStatus();
} }
@ -628,6 +640,10 @@ final class DifferentialRevision extends DifferentialDAO
return $this->getStatusObject()->isNeedsReview(); return $this->getStatusObject()->isNeedsReview();
} }
public function isNeedsRevision() {
return $this->getStatusObject()->isNeedsRevision();
}
public function isChangePlanned() { public function isChangePlanned() {
return $this->getStatusObject()->isChangePlanned(); return $this->getStatusObject()->isChangePlanned();
} }
@ -650,7 +666,7 @@ final class DifferentialRevision extends DifferentialDAO
public function getStatusObject() { public function getStatusObject() {
$status = $this->getStatus(); $status = $this->getStatus();
return DifferentialRevisionStatus::newForLegacyStatus($status); return DifferentialRevisionStatus::newForStatus($status);
} }
public function getFlag(PhabricatorUser $viewer) { public function getFlag(PhabricatorUser $viewer) {
@ -897,13 +913,26 @@ final class DifferentialRevision extends DifferentialDAO
->setKey('authorPHID') ->setKey('authorPHID')
->setType('phid') ->setType('phid')
->setDescription(pht('Revision author PHID.')), ->setDescription(pht('Revision author PHID.')),
id(new PhabricatorConduitSearchFieldSpecification())
->setKey('status')
->setType('map<string, wild>')
->setDescription(pht('Information about revision status.')),
); );
} }
public function getFieldValuesForConduit() { public function getFieldValuesForConduit() {
$status = $this->getStatusObject();
$status_info = array(
'value' => $status->getKey(),
'name' => $status->getDisplayName(),
'closed' => $status->isClosedStatus(),
'color.ansi' => $status->getANSIColor(),
);
return array( return array(
'title' => $this->getTitle(), 'title' => $this->getTitle(),
'authorPHID' => $this->getAuthorPHID(), 'authorPHID' => $this->getAuthorPHID(),
'status' => $status_info,
); );
} }

View file

@ -8,7 +8,6 @@ final class DifferentialTransaction
const TYPE_INLINE = 'differential:inline'; const TYPE_INLINE = 'differential:inline';
const TYPE_UPDATE = 'differential:update'; const TYPE_UPDATE = 'differential:update';
const TYPE_ACTION = 'differential:action'; const TYPE_ACTION = 'differential:action';
const TYPE_STATUS = 'differential:status';
const MAILTAG_REVIEWERS = 'differential-reviewers'; const MAILTAG_REVIEWERS = 'differential-reviewers';
const MAILTAG_CLOSED = 'differential-committed'; const MAILTAG_CLOSED = 'differential-committed';
@ -305,15 +304,6 @@ final class DifferentialTransaction
return DifferentialAction::getBasicStoryText($new, $author_handle); return DifferentialAction::getBasicStoryText($new, $author_handle);
} }
break; break;
case self::TYPE_STATUS:
switch ($this->getNewValue()) {
case ArcanistDifferentialRevisionStatus::ACCEPTED:
return pht('This revision is now accepted and ready to land.');
case ArcanistDifferentialRevisionStatus::NEEDS_REVISION:
return pht('This revision now requires changes to proceed.');
case ArcanistDifferentialRevisionStatus::NEEDS_REVIEW:
return pht('This revision now requires review to proceed.');
}
} }
return parent::getTitle(); return parent::getTitle();
@ -457,21 +447,6 @@ final class DifferentialTransaction
$object_link); $object_link);
} }
break; break;
case self::TYPE_STATUS:
switch ($this->getNewValue()) {
case ArcanistDifferentialRevisionStatus::ACCEPTED:
return pht(
'%s is now accepted and ready to land.',
$object_link);
case ArcanistDifferentialRevisionStatus::NEEDS_REVISION:
return pht(
'%s now requires changes to proceed.',
$object_link);
case ArcanistDifferentialRevisionStatus::NEEDS_REVIEW:
return pht(
'%s now requires review to proceed.',
$object_link);
}
} }
return parent::getTitleForFeed(); return parent::getTitleForFeed();
@ -483,16 +458,6 @@ final class DifferentialTransaction
return 'fa-comment'; return 'fa-comment';
case self::TYPE_UPDATE: case self::TYPE_UPDATE:
return 'fa-refresh'; return 'fa-refresh';
case self::TYPE_STATUS:
switch ($this->getNewValue()) {
case ArcanistDifferentialRevisionStatus::ACCEPTED:
return 'fa-check';
case ArcanistDifferentialRevisionStatus::NEEDS_REVISION:
return 'fa-times';
case ArcanistDifferentialRevisionStatus::NEEDS_REVIEW:
return 'fa-undo';
}
break;
case self::TYPE_ACTION: case self::TYPE_ACTION:
switch ($this->getNewValue()) { switch ($this->getNewValue()) {
case DifferentialAction::ACTION_CLOSE: case DifferentialAction::ACTION_CLOSE:
@ -530,14 +495,12 @@ final class DifferentialTransaction
// Never group status changes with other types of actions, they're indirect // Never group status changes with other types of actions, they're indirect
// and don't make sense when combined with direct actions. // and don't make sense when combined with direct actions.
$type_status = self::TYPE_STATUS; if ($this->isStatusTransaction($this)) {
if ($this->getTransactionType() == $type_status) {
return false; return false;
} }
foreach ($group as $xaction) { foreach ($group as $xaction) {
if ($xaction->getTransactionType() == $type_status) { if ($this->isStatusTransaction($xaction)) {
return false; return false;
} }
} }
@ -545,21 +508,20 @@ final class DifferentialTransaction
return parent::shouldDisplayGroupWith($group); return parent::shouldDisplayGroupWith($group);
} }
private function isStatusTransaction($xaction) {
$status_type = DifferentialRevisionStatusTransaction::TRANSACTIONTYPE;
if ($xaction->getTransactionType() == $status_type) {
return true;
}
return false;
}
public function getColor() { public function getColor() {
switch ($this->getTransactionType()) { switch ($this->getTransactionType()) {
case self::TYPE_UPDATE: case self::TYPE_UPDATE:
return PhabricatorTransactions::COLOR_SKY; return PhabricatorTransactions::COLOR_SKY;
case self::TYPE_STATUS:
switch ($this->getNewValue()) {
case ArcanistDifferentialRevisionStatus::ACCEPTED:
return PhabricatorTransactions::COLOR_GREEN;
case ArcanistDifferentialRevisionStatus::NEEDS_REVISION:
return PhabricatorTransactions::COLOR_RED;
case ArcanistDifferentialRevisionStatus::NEEDS_REVIEW:
return PhabricatorTransactions::COLOR_ORANGE;
}
break;
case self::TYPE_ACTION: case self::TYPE_ACTION:
switch ($this->getNewValue()) { switch ($this->getNewValue()) {
case DifferentialAction::ACTION_CLOSE: case DifferentialAction::ACTION_CLOSE:

View file

@ -0,0 +1,74 @@
<?php
final class DifferentialRevisionClosedStatusDatasource
extends PhabricatorTypeaheadDatasource {
const FUNCTION_TOKEN = 'closed()';
public function getBrowseTitle() {
return pht('Browse Any Closed Status');
}
public function getPlaceholderText() {
return pht('Type closed()...');
}
public function getDatasourceApplicationClass() {
return 'PhabricatorDifferentialApplication';
}
public function getDatasourceFunctions() {
return array(
'closed' => array(
'name' => pht('Any Closed Status'),
'summary' => pht('Find results with any closed status.'),
'description' => pht(
'This function includes results which have any closed status.'),
),
);
}
public function loadResults() {
$results = array(
$this->buildClosedResult(),
);
return $this->filterResultsAgainstTokens($results);
}
protected function evaluateFunction($function, array $argv_list) {
$results = array();
$map = DifferentialRevisionStatus::getAll();
foreach ($argv_list as $argv) {
foreach ($map as $status) {
if ($status->isClosedStatus()) {
$results[] = $status->getKey();
}
}
}
return $results;
}
public function renderFunctionTokens($function, array $argv_list) {
$results = array();
foreach ($argv_list as $argv) {
$results[] = PhabricatorTypeaheadTokenView::newFromTypeaheadResult(
$this->buildClosedResult());
}
return $results;
}
private function buildClosedResult() {
$name = pht('Any Closed Status');
return $this->newFunctionResult()
->setName($name.' closed')
->setDisplayName($name)
->setPHID(self::FUNCTION_TOKEN)
->setUnique(true)
->addAttribute(pht('Select any closed status.'));
}
}

View file

@ -0,0 +1,74 @@
<?php
final class DifferentialRevisionOpenStatusDatasource
extends PhabricatorTypeaheadDatasource {
const FUNCTION_TOKEN = 'open()';
public function getBrowseTitle() {
return pht('Browse Any Open Status');
}
public function getPlaceholderText() {
return pht('Type open()...');
}
public function getDatasourceApplicationClass() {
return 'PhabricatorDifferentialApplication';
}
public function getDatasourceFunctions() {
return array(
'open' => array(
'name' => pht('Any Open Status'),
'summary' => pht('Find results with any open status.'),
'description' => pht(
'This function includes results which have any open status.'),
),
);
}
public function loadResults() {
$results = array(
$this->buildOpenResult(),
);
return $this->filterResultsAgainstTokens($results);
}
protected function evaluateFunction($function, array $argv_list) {
$results = array();
$map = DifferentialRevisionStatus::getAll();
foreach ($argv_list as $argv) {
foreach ($map as $status) {
if (!$status->isClosedStatus()) {
$results[] = $status->getKey();
}
}
}
return $results;
}
public function renderFunctionTokens($function, array $argv_list) {
$results = array();
foreach ($argv_list as $argv) {
$results[] = PhabricatorTypeaheadTokenView::newFromTypeaheadResult(
$this->buildOpenResult());
}
return $results;
}
private function buildOpenResult() {
$name = pht('Any Open Status');
return $this->newFunctionResult()
->setName($name.' open')
->setDisplayName($name)
->setPHID(self::FUNCTION_TOKEN)
->setUnique(true)
->addAttribute(pht('Select any open status.'));
}
}

View file

@ -0,0 +1,52 @@
<?php
final class DifferentialRevisionStatusDatasource
extends PhabricatorTypeaheadDatasource {
public function getBrowseTitle() {
return pht('Browse Statuses');
}
public function getPlaceholderText() {
return pht('Type a revision status name...');
}
public function getDatasourceApplicationClass() {
return 'PhabricatorDifferentialApplication';
}
public function loadResults() {
$results = $this->buildResults();
return $this->filterResultsAgainstTokens($results);
}
protected function renderSpecialTokens(array $values) {
return $this->renderTokensFromResults($this->buildResults(), $values);
}
private function buildResults() {
$results = array();
$statuses = DifferentialRevisionStatus::getAll();
foreach ($statuses as $status) {
$key = $status->getKey();
$result = id(new PhabricatorTypeaheadResult())
->setIcon($status->getIcon())
->setPHID($key)
->setName($status->getDisplayName());
if ($status->isClosedStatus()) {
$result->addAttribute(pht('Closed Status'));
} else {
$result->addAttribute(pht('Open Status'));
}
$results[$key] = $result;
}
return $results;
}
}

View file

@ -0,0 +1,22 @@
<?php
final class DifferentialRevisionStatusFunctionDatasource
extends PhabricatorTypeaheadCompositeDatasource {
public function getBrowseTitle() {
return pht('Browse Statuses');
}
public function getPlaceholderText() {
return pht('Type a revision status name or function...');
}
public function getComponentDatasources() {
return array(
new DifferentialRevisionStatusDatasource(),
new DifferentialRevisionClosedStatusDatasource(),
new DifferentialRevisionOpenStatusDatasource(),
);
}
}

View file

@ -47,7 +47,8 @@ final class DifferentialRevisionAbandonTransaction
} }
public function applyInternalEffects($object, $value) { public function applyInternalEffects($object, $value) {
$object->setStatus(ArcanistDifferentialRevisionStatus::ABANDONED); $status_abandoned = DifferentialRevisionStatus::ABANDONED;
$object->setModernRevisionStatus($status_abandoned);
} }
protected function validateAction($object, PhabricatorUser $viewer) { protected function validateAction($object, PhabricatorUser $viewer) {

View file

@ -103,7 +103,7 @@ final class DifferentialRevisionAcceptTransaction
if ($reviewer->isAccepted($diff_phid)) { if ($reviewer->isAccepted($diff_phid)) {
// If a reviewer is already in a full "accepted" state, don't // If a reviewer is already in a full "accepted" state, don't
// include that reviewer as an option unless we're listing all // include that reviewer as an option unless we're listing all
// reviwers, including reviewers who have already accepted. // reviewers, including reviewers who have already accepted.
continue; continue;
} }
} }

View file

@ -35,14 +35,10 @@ final class DifferentialRevisionCloseTransaction
} }
public function applyInternalEffects($object, $value) { public function applyInternalEffects($object, $value) {
$status_closed = ArcanistDifferentialRevisionStatus::CLOSED; $was_accepted = $object->isAccepted();
$status_accepted = ArcanistDifferentialRevisionStatus::ACCEPTED;
$old_status = $object->getStatus(); $status_published = DifferentialRevisionStatus::PUBLISHED;
$object->setModernRevisionStatus($status_published);
$object->setStatus($status_closed);
$was_accepted = ($old_status == $status_accepted);
$object->setProperty( $object->setProperty(
DifferentialRevision::PROPERTY_CLOSED_FROM_ACCEPTED, DifferentialRevision::PROPERTY_CLOSED_FROM_ACCEPTED,
@ -50,6 +46,12 @@ final class DifferentialRevisionCloseTransaction
} }
protected function validateAction($object, PhabricatorUser $viewer) { protected function validateAction($object, PhabricatorUser $viewer) {
if ($this->getEditor()->getIsCloseByCommit()) {
// If we're closing a revision because we discovered a commit, we don't
// care what state it was in.
return;
}
if ($object->isClosed()) { if ($object->isClosed()) {
throw new Exception( throw new Exception(
pht( pht(
@ -78,9 +80,50 @@ final class DifferentialRevisionCloseTransaction
} }
public function getTitle() { public function getTitle() {
return pht( if (!$this->getMetadataValue('isCommitClose')) {
'%s closed this revision.', return pht(
$this->renderAuthor()); '%s closed this revision.',
$this->renderAuthor());
}
$commit_phid = $this->getMetadataValue('commitPHID');
$committer_phid = $this->getMetadataValue('committerPHID');
$author_phid = $this->getMetadataValue('authorPHID');
if ($committer_phid) {
$committer_name = $this->renderHandle($committer_phid);
} else {
$committer_name = $this->getMetadataValue('committerName');
}
if ($author_phid) {
$author_name = $this->renderHandle($author_phid);
} else {
$author_name = $this->getMetadatavalue('authorName');
}
$same_phid =
strlen($committer_phid) &&
strlen($author_phid) &&
($committer_phid == $author_phid);
$same_name =
!strlen($committer_phid) &&
!strlen($author_phid) &&
($committer_name == $author_name);
if ($same_name || $same_phid) {
return pht(
'Closed by commit %s (authored by %s).',
$this->renderHandle($commit_phid),
$author_name);
} else {
return pht(
'Closed by commit %s (authored by %s, committed by %s).',
$this->renderHandle($commit_phid),
$author_name,
$committer_name);
}
} }
public function getTitleForFeed() { public function getTitleForFeed() {

View file

@ -46,13 +46,12 @@ final class DifferentialRevisionPlanChangesTransaction
} }
public function generateOldValue($object) { public function generateOldValue($object) {
$status_planned = ArcanistDifferentialRevisionStatus::CHANGES_PLANNED; return $object->isChangePlanned();
return ($object->getStatus() == $status_planned);
} }
public function applyInternalEffects($object, $value) { public function applyInternalEffects($object, $value) {
$status_planned = ArcanistDifferentialRevisionStatus::CHANGES_PLANNED; $status_planned = DifferentialRevisionStatus::CHANGES_PLANNED;
$object->setStatus($status_planned); $object->setModernRevisionStatus($status_planned);
} }
protected function validateAction($object, PhabricatorUser $viewer) { protected function validateAction($object, PhabricatorUser $viewer) {

View file

@ -47,7 +47,8 @@ final class DifferentialRevisionReclaimTransaction
} }
public function applyInternalEffects($object, $value) { public function applyInternalEffects($object, $value) {
$object->setStatus(ArcanistDifferentialRevisionStatus::NEEDS_REVIEW); $status_review = DifferentialRevisionStatus::NEEDS_REVIEW;
$object->setModernRevisionStatus($status_review);
} }
protected function validateAction($object, PhabricatorUser $viewer) { protected function validateAction($object, PhabricatorUser $viewer) {

View file

@ -35,7 +35,8 @@ final class DifferentialRevisionReopenTransaction
} }
public function applyInternalEffects($object, $value) { public function applyInternalEffects($object, $value) {
$object->setStatus(ArcanistDifferentialRevisionStatus::NEEDS_REVIEW); $status_review = DifferentialRevisionStatus::NEEDS_REVIEW;
$object->setModernRevisionStatus($status_review);
} }
protected function validateAction($object, PhabricatorUser $viewer) { protected function validateAction($object, PhabricatorUser $viewer) {

View file

@ -27,13 +27,12 @@ final class DifferentialRevisionRequestReviewTransaction
} }
public function generateOldValue($object) { public function generateOldValue($object) {
$status_review = ArcanistDifferentialRevisionStatus::NEEDS_REVIEW; return $object->isNeedsReview();
return ($object->getStatus() == $status_review);
} }
public function applyInternalEffects($object, $value) { public function applyInternalEffects($object, $value) {
$status_review = ArcanistDifferentialRevisionStatus::NEEDS_REVIEW; $status_review = DifferentialRevisionStatus::NEEDS_REVIEW;
$object->setStatus($status_review); $object->setModernRevisionStatus($status_review);
} }
protected function validateAction($object, PhabricatorUser $viewer) { protected function validateAction($object, PhabricatorUser $viewer) {

View file

@ -210,34 +210,6 @@ abstract class DifferentialRevisionReviewTransaction
$map = array_select_keys($map, $value); $map = array_select_keys($map, $value);
} }
// Convert reviewer statuses into edge data.
foreach ($map as $reviewer_phid => $reviewer_status) {
$map[$reviewer_phid] = array(
'data' => array(
'status' => $reviewer_status,
),
);
}
// This is currently double-writing: to the old (edge) store and the new
// (reviewer) store. Do the old edge write first.
$src_phid = $revision->getPHID();
$edge_type = DifferentialRevisionHasReviewerEdgeType::EDGECONST;
$editor = new PhabricatorEdgeEditor();
foreach ($map as $dst_phid => $edge_data) {
if ($status == DifferentialReviewerStatus::STATUS_RESIGNED) {
// TODO: For now, we just remove these reviewers. In the future, we will
// store resignations explicitly.
$editor->removeEdge($src_phid, $edge_type, $dst_phid);
} else {
$editor->addEdge($src_phid, $edge_type, $dst_phid, $edge_data);
}
}
$editor->save();
// Now, do the new write. // Now, do the new write.
if ($map) { if ($map) {
@ -249,6 +221,7 @@ abstract class DifferentialRevisionReviewTransaction
} }
$table = new DifferentialReviewer(); $table = new DifferentialReviewer();
$src_phid = $revision->getPHID();
$reviewers = $table->loadAllWhere( $reviewers = $table->loadAllWhere(
'revisionPHID = %s AND reviewerPHID IN (%Ls)', 'revisionPHID = %s AND reviewerPHID IN (%Ls)',
@ -256,7 +229,7 @@ abstract class DifferentialRevisionReviewTransaction
array_keys($map)); array_keys($map));
$reviewers = mpull($reviewers, null, 'getReviewerPHID'); $reviewers = mpull($reviewers, null, 'getReviewerPHID');
foreach ($map as $dst_phid => $edge_data) { foreach (array_keys($map) as $dst_phid) {
$reviewer = idx($reviewers, $dst_phid); $reviewer = idx($reviewers, $dst_phid);
if (!$reviewer) { if (!$reviewer) {
$reviewer = id(new DifferentialReviewer()) $reviewer = id(new DifferentialReviewer())

View file

@ -106,43 +106,9 @@ final class DifferentialRevisionReviewersTransaction
public function applyExternalEffects($object, $value) { public function applyExternalEffects($object, $value) {
$src_phid = $object->getPHID(); $src_phid = $object->getPHID();
// This is currently double-writing: to the old (edge) store and the new
// (reviewer) store. Do the old edge write first.
$old = $this->generateOldValue($object); $old = $this->generateOldValue($object);
$new = $value; $new = $value;
$edge_type = DifferentialRevisionHasReviewerEdgeType::EDGECONST;
$editor = new PhabricatorEdgeEditor();
$rem = array_diff_key($old, $new); $rem = array_diff_key($old, $new);
foreach ($rem as $dst_phid => $status) {
$editor->removeEdge($src_phid, $edge_type, $dst_phid);
}
foreach ($new as $dst_phid => $status) {
$old_status = idx($old, $dst_phid);
if ($old_status === $status) {
continue;
}
$data = array(
'data' => array(
'status' => $status,
// TODO: This seemes like it's buggy before the Modular Transactions
// changes. Figure out what's going on here? We don't have a very
// clean way to get the active diff ID right now.
'diffID' => null,
),
);
$editor->addEdge($src_phid, $edge_type, $dst_phid, $data);
}
$editor->save();
// Now, do the new write.
$table = new DifferentialReviewer(); $table = new DifferentialReviewer();
$table_name = $table->getTableName(); $table_name = $table->getTableName();

View file

@ -0,0 +1,73 @@
<?php
final class DifferentialRevisionStatusTransaction
extends DifferentialRevisionTransactionType {
const TRANSACTIONTYPE = 'differential.revision.status';
public function generateOldValue($object) {
return $object->getModernRevisionStatus();
}
public function applyInternalEffects($object, $value) {
$object->setModernRevisionStatus($value);
}
public function getTitle() {
$status = $this->newStatusObject();
if ($status->isAccepted()) {
return pht('This revision is now accepted and ready to land.');
}
if ($status->isNeedsRevision()) {
return pht('This revision now requires changes to proceed.');
}
if ($status->isNeedsReview()) {
return pht('This revision now requires review to proceed.');
}
return null;
}
public function getTitleForFeed() {
$status = $this->newStatusObject();
if ($status->isAccepted()) {
return pht(
'%s is now accepted and ready to land.',
$this->renderObject());
}
if ($status->isNeedsRevision()) {
return pht(
'%s now requires changes to proceed.',
$this->renderObject());
}
if ($status->isNeedsReview()) {
return pht(
'%s now requires review to proceed.',
$this->renderObject());
}
return null;
}
public function getIcon() {
$status = $this->newStatusObject();
return $status->getTimelineIcon();
}
public function getColor() {
$status = $this->newStatusObject();
return $status->getTimelineColor();
}
private function newStatusObject() {
$new = $this->getNewValue();
return DifferentialRevisionStatus::newForStatus($new);
}
}

View file

@ -71,6 +71,11 @@ final class DiffusionBranchTableController extends DiffusionController {
->setHeader(pht('Branches')) ->setHeader(pht('Branches'))
->setHeaderIcon('fa-code-fork'); ->setHeaderIcon('fa-code-fork');
if (!$repository->isSVN()) {
$branch_tag = $this->renderBranchTag($drequest);
$header->addTag($branch_tag);
}
$tabs = $this->buildTabsView('branch'); $tabs = $this->buildTabsView('branch');
$view = id(new PHUITwoColumnView()) $view = id(new PHUITwoColumnView())

View file

@ -5,6 +5,7 @@ final class DiffusionBrowseController extends DiffusionController {
private $lintCommit; private $lintCommit;
private $lintMessages; private $lintMessages;
private $coverage; private $coverage;
private $corpusButtons = array();
public function shouldAllowPublic() { public function shouldAllowPublic() {
return true; return true;
@ -22,8 +23,7 @@ final class DiffusionBrowseController extends DiffusionController {
// list. // list.
$grep = $request->getStr('grep'); $grep = $request->getStr('grep');
$find = $request->getStr('find'); if (strlen($grep)) {
if (strlen($grep) || strlen($find)) {
return $this->browseSearch(); return $this->browseSearch();
} }
@ -57,14 +57,17 @@ final class DiffusionBrowseController extends DiffusionController {
private function browseSearch() { private function browseSearch() {
$drequest = $this->getDiffusionRequest(); $drequest = $this->getDiffusionRequest();
$header = $this->buildHeaderView($drequest); $header = $this->buildHeaderView($drequest);
$path = nonempty(basename($drequest->getPath()), '/');
$search_form = $this->renderSearchForm();
$search_results = $this->renderSearchResults(); $search_results = $this->renderSearchResults();
$search_form = $this->renderSearchForm($path);
$search_form = id(new PHUIObjectBoxView()) $search_form = phutil_tag(
->setHeaderText(pht('Search')) 'div',
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) array(
->appendChild($search_form); 'class' => 'diffusion-mobile-search-form',
),
$search_form);
$crumbs = $this->buildCrumbs( $crumbs = $this->buildCrumbs(
array( array(
@ -74,8 +77,11 @@ final class DiffusionBrowseController extends DiffusionController {
)); ));
$crumbs->setBorder(true); $crumbs->setBorder(true);
$tabs = $this->buildTabsView('code');
$view = id(new PHUITwoColumnView()) $view = id(new PHUITwoColumnView())
->setHeader($header) ->setHeader($header)
->setTabs($tabs)
->setFooter( ->setFooter(
array( array(
$search_form, $search_form,
@ -235,50 +241,47 @@ final class DiffusionBrowseController extends DiffusionController {
require_celerity_resource('diffusion-source-css'); require_celerity_resource('diffusion-source-css');
// Render the page. // Render the page.
$curtain = $this->buildCurtain($drequest, $show_blame, $show_editor); $bar = $this->buildButtonBar($drequest, $show_blame, $show_editor);
$properties = $this->buildPropertyView($drequest);
$header = $this->buildHeaderView($drequest); $header = $this->buildHeaderView($drequest);
$header->setHeaderIcon('fa-file-code-o'); $header->setHeaderIcon('fa-file-code-o');
$content = array();
$follow = $request->getStr('follow'); $follow = $request->getStr('follow');
$follow_notice = null;
if ($follow) { if ($follow) {
$notice = new PHUIInfoView(); $follow_notice = id(new PHUIInfoView())
$notice->setSeverity(PHUIInfoView::SEVERITY_WARNING); ->setSeverity(PHUIInfoView::SEVERITY_WARNING)
$notice->setTitle(pht('Unable to Continue')); ->setTitle(pht('Unable to Continue'));
switch ($follow) { switch ($follow) {
case 'first': case 'first':
$notice->appendChild( $follow_notice->appendChild(
pht( pht(
'Unable to continue tracing the history of this file because '. 'Unable to continue tracing the history of this file because '.
'this commit is the first commit in the repository.')); 'this commit is the first commit in the repository.'));
break; break;
case 'created': case 'created':
$notice->appendChild( $follow_notice->appendChild(
pht( pht(
'Unable to continue tracing the history of this file because '. 'Unable to continue tracing the history of this file because '.
'this commit created the file.')); 'this commit created the file.'));
break; break;
} }
$content[] = $notice;
} }
$renamed = $request->getStr('renamed'); $renamed = $request->getStr('renamed');
$renamed_notice = null;
if ($renamed) { if ($renamed) {
$notice = new PHUIInfoView(); $renamed_notice = id(new PHUIInfoView())
$notice->setSeverity(PHUIInfoView::SEVERITY_NOTICE); ->setSeverity(PHUIInfoView::SEVERITY_NOTICE)
$notice->setTitle(pht('File Renamed')); ->setTitle(pht('File Renamed'))
$notice->appendChild( ->appendChild(
pht( pht(
'File history passes through a rename from "%s" to "%s".', 'File history passes through a rename from "%s" to "%s".',
$drequest->getPath(), $drequest->getPath(),
$renamed)); $renamed));
$content[] = $notice;
} }
$content[] = $corpus; $open_revisions = $this->buildOpenRevisions();
$content[] = $this->buildOpenRevisions(); $owners_list = $this->buildOwnersList($drequest);
$crumbs = $this->buildCrumbs( $crumbs = $this->buildCrumbs(
array( array(
@ -289,17 +292,20 @@ final class DiffusionBrowseController extends DiffusionController {
$crumbs->setBorder(true); $crumbs->setBorder(true);
$basename = basename($this->getDiffusionRequest()->getPath()); $basename = basename($this->getDiffusionRequest()->getPath());
$tabs = $this->buildTabsView('code');
$bar->setRight($this->corpusButtons);
$view = id(new PHUITwoColumnView()) $view = id(new PHUITwoColumnView())
->setHeader($header) ->setHeader($header)
->setCurtain($curtain) ->setTabs($tabs)
->setMainColumn(array( ->setFooter(array(
$content, $bar,
)); $follow_notice,
$renamed_notice,
if ($properties) { $corpus,
$view->addPropertySection(pht('Details'), $properties); $open_revisions,
} $owners_list,
));
$title = array($basename, $repository->getDisplayName()); $title = array($basename, $repository->getDisplayName());
@ -323,14 +329,12 @@ final class DiffusionBrowseController extends DiffusionController {
$reason = $results->getReasonForEmptyResultSet(); $reason = $results->getReasonForEmptyResultSet();
$actions = $this->getActions($drequest); $this->buildActionButtons($drequest, true);
$details = $this->buildPropertyView($drequest); $details = $this->buildPropertyView($drequest);
$header = $this->buildHeaderView($drequest); $header = $this->buildHeaderView($drequest);
$header->setHeaderIcon('fa-folder-open'); $header->setHeaderIcon('fa-folder-open');
$search_form = $this->renderSearchForm();
$empty_result = null; $empty_result = null;
$browse_panel = null; $browse_panel = null;
$branch_panel = null; $branch_panel = null;
@ -361,7 +365,7 @@ final class DiffusionBrowseController extends DiffusionController {
$title = nonempty(basename($drequest->getPath()), '/'); $title = nonempty(basename($drequest->getPath()), '/');
$icon = 'fa-folder-open'; $icon = 'fa-folder-open';
$browse_header = $this->buildPanelHeaderView($title, $icon, $actions); $browse_header = $this->buildPanelHeaderView($title, $icon);
$browse_panel = id(new PHUIObjectBoxView()) $browse_panel = id(new PHUIObjectBoxView())
->setHeader($browse_header) ->setHeader($browse_header)
@ -369,12 +373,6 @@ final class DiffusionBrowseController extends DiffusionController {
->setTable($browse_table) ->setTable($browse_table)
->setPager($pager); ->setPager($pager);
$browse_panel->setShowHide(
array(pht('Show Search')),
pht('Hide Search'),
$search_form,
'#');
$path = $drequest->getPath(); $path = $drequest->getPath();
$is_branch = (!strlen($path) && $repository->supportsBranchComparison()); $is_branch = (!strlen($path) && $repository->supportsBranchComparison());
if ($is_branch) { if ($is_branch) {
@ -393,15 +391,23 @@ final class DiffusionBrowseController extends DiffusionController {
)); ));
$crumbs->setBorder(true); $crumbs->setBorder(true);
$tabs = $this->buildTabsView('code');
$owners_list = $this->buildOwnersList($drequest);
$bar = id(new PHUILeftRightView())
->setRight($this->corpusButtons)
->addClass('diffusion-action-bar');
$view = id(new PHUITwoColumnView()) $view = id(new PHUITwoColumnView())
->setHeader($header) ->setHeader($header)
->setTabs($tabs)
->setFooter( ->setFooter(
array( array(
$bar,
$branch_panel, $branch_panel,
$empty_result, $empty_result,
$browse_panel, $browse_panel,
$open_revisions, $open_revisions,
$owners_list,
$readme, $readme,
)); ));
@ -449,159 +455,58 @@ final class DiffusionBrowseController extends DiffusionController {
'limit' => $pager->getPageSize() + 1, 'limit' => $pager->getPageSize() + 1,
'offset' => $pager->getOffset(), 'offset' => $pager->getOffset(),
)); ));
} else { // Filename search.
$search_mode = 'find';
$query_string = $request->getStr('find');
$results = $this->callConduitWithDiffusionRequest(
'diffusion.querypaths',
array(
'pattern' => $query_string,
'commit' => $drequest->getStableCommit(),
'path' => $drequest->getPath(),
'limit' => $pager->getPageSize() + 1,
'offset' => $pager->getOffset(),
));
} }
break; break;
} }
$results = $pager->sliceResults($results); $results = $pager->sliceResults($results);
$table = null;
$header = null;
if ($search_mode == 'grep') { if ($search_mode == 'grep') {
$table = $this->renderGrepResults($results, $query_string); $table = $this->renderGrepResults($results, $query_string);
$header = pht( $title = pht(
'File content matching "%s" under "%s"', 'File content matching "%s" under "%s"',
$query_string, $query_string,
nonempty($drequest->getPath(), '/')); nonempty($drequest->getPath(), '/'));
} else { $header = id(new PHUIHeaderView())
$table = $this->renderFindResults($results); ->setHeader($title)
$header = pht( ->addClass('diffusion-search-result-header');
'Paths matching "%s" under "%s"',
$query_string,
nonempty($drequest->getPath(), '/'));
} }
return id(new PHUIObjectBoxView()) return array($header, $table, $pager);
->setHeaderText($header)
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
->setTable($table)
->setPager($pager);
} }
private function renderGrepResults(array $results, $pattern) { private function renderGrepResults(array $results, $pattern) {
$drequest = $this->getDiffusionRequest(); $drequest = $this->getDiffusionRequest();
require_celerity_resource('phabricator-search-results-css'); require_celerity_resource('phabricator-search-results-css');
$rows = array(); if (!$results) {
foreach ($results as $result) { return id(new PHUIInfoView())
list($path, $line, $string) = $result; ->setSeverity(PHUIInfoView::SEVERITY_NODATA)
->appendChild(
$href = $drequest->generateURI(array( pht(
'action' => 'browse', 'The pattern you searched for was not found in the content of any '.
'path' => $path, 'files.'));
'line' => $line,
));
$matches = null;
$count = @preg_match_all(
'('.$pattern.')u',
$string,
$matches,
PREG_OFFSET_CAPTURE);
if (!$count) {
$output = ltrim($string);
} else {
$output = array();
$cursor = 0;
$length = strlen($string);
foreach ($matches[0] as $match) {
$offset = $match[1];
if ($cursor != $offset) {
$output[] = array(
'text' => substr($string, $cursor, $offset),
'highlight' => false,
);
}
$output[] = array(
'text' => $match[0],
'highlight' => true,
);
$cursor = $offset + strlen($match[0]);
}
if ($cursor != $length) {
$output[] = array(
'text' => substr($string, $cursor),
'highlight' => false,
);
}
if ($output) {
$output[0]['text'] = ltrim($output[0]['text']);
}
foreach ($output as $key => $segment) {
if ($segment['highlight']) {
$output[$key] = phutil_tag('strong', array(), $segment['text']);
} else {
$output[$key] = $segment['text'];
}
}
}
$string = phutil_tag(
'pre',
array('class' => 'PhabricatorMonospaced phui-source-fragment'),
$output);
$path = Filesystem::readablePath($path, $drequest->getPath());
$rows[] = array(
phutil_tag('a', array('href' => $href), $path),
$line,
$string,
);
} }
$table = id(new AphrontTableView($rows)) $grouped = array();
->setClassName('remarkup-code') foreach ($results as $file) {
->setHeaders(array(pht('Path'), pht('Line'), pht('String'))) list($path, $line, $string) = $file;
->setColumnClasses(array('', 'n', 'wide')) $grouped[$path][] = array($line, $string);
->setNoDataString(
pht(
'The pattern you searched for was not found in the content of any '.
'files.'));
return $table;
}
private function renderFindResults(array $results) {
$drequest = $this->getDiffusionRequest();
$rows = array();
foreach ($results as $result) {
$href = $drequest->generateURI(array(
'action' => 'browse',
'path' => $result,
));
$readable = Filesystem::readablePath($result, $drequest->getPath());
$rows[] = array(
phutil_tag('a', array('href' => $href), $readable),
);
} }
$table = id(new AphrontTableView($rows)) $view = array();
->setHeaders(array(pht('Path'))) foreach ($grouped as $path => $matches) {
->setColumnClasses(array('wide')) $view[] = id(new DiffusionPatternSearchView())
->setNoDataString( ->setPath($path)
pht( ->setMatches($matches)
'The pattern you searched for did not match the names of any '. ->setPattern($pattern)
'files.')); ->setDiffusionRequest($drequest)
->render();
}
return $table; return $view;
} }
private function loadLintMessages() { private function loadLintMessages() {
@ -737,14 +642,13 @@ final class DiffusionBrowseController extends DiffusionController {
Javelin::initBehavior('load-blame', array('id' => $id)); Javelin::initBehavior('load-blame', array('id' => $id));
$file = $this->renderFileButton(); $this->corpusButtons[] = $this->renderFileButton();
$title = basename($this->getDiffusionRequest()->getPath()); $title = basename($this->getDiffusionRequest()->getPath());
$icon = 'fa-file-code-o'; $icon = 'fa-file-code-o';
$drequest = $this->getDiffusionRequest(); $drequest = $this->getDiffusionRequest();
$actions = $this->getActions($drequest); $this->buildActionButtons($drequest);
$header = $this->buildPanelHeaderView($title, $icon, $actions); $header = $this->buildPanelHeaderView($title, $icon);
$header->addActionLink($file);
$corpus = id(new PHUIObjectBoxView()) $corpus = id(new PHUIObjectBoxView())
->setHeader($header) ->setHeader($header)
@ -783,12 +687,11 @@ final class DiffusionBrowseController extends DiffusionController {
return $corpus; return $corpus;
} }
private function buildCurtain( private function buildButtonBar(
DiffusionRequest $drequest, DiffusionRequest $drequest,
$show_blame, $show_blame,
$show_editor) { $show_editor) {
$curtain = $this->newCurtainView($drequest);
$viewer = $this->getViewer(); $viewer = $this->getViewer();
$base_uri = $this->getRequest()->getRequestURI(); $base_uri = $this->getRequest()->getRequestURI();
@ -796,19 +699,21 @@ final class DiffusionBrowseController extends DiffusionController {
$repository = $drequest->getRepository(); $repository = $drequest->getRepository();
$path = $drequest->getPath(); $path = $drequest->getPath();
$line = nonempty((int)$drequest->getLine(), 1); $line = nonempty((int)$drequest->getLine(), 1);
$buttons = array();
$editor_link = $user->loadEditorLink($path, $line, $repository); $editor_link = $user->loadEditorLink($path, $line, $repository);
$template = $user->loadEditorLink($path, '%l', $repository); $template = $user->loadEditorLink($path, '%l', $repository);
$curtain->addAction( $buttons[] =
id(new PhabricatorActionView()) id(new PHUIButtonView())
->setName(pht('Show Last Change')) ->setText(pht('Last Change'))
->setColor(PHUIButtonView::GREY)
->setHref( ->setHref(
$drequest->generateURI( $drequest->generateURI(
array( array(
'action' => 'change', 'action' => 'change',
))) )))
->setIcon('fa-backward')); ->setIcon('fa-backward');
if ($show_blame) { if ($show_blame) {
$blame_text = pht('Disable Blame'); $blame_text = pht('Disable Blame');
@ -820,48 +725,76 @@ final class DiffusionBrowseController extends DiffusionController {
$blame_value = 1; $blame_value = 1;
} }
$curtain->addAction( $blame = id(new PHUIButtonView())
id(new PhabricatorActionView()) ->setText($blame_text)
->setName($blame_text) ->setIcon($blame_icon)
->setHref($base_uri->alter('blame', $blame_value)) ->setUser($viewer)
->setIcon($blame_icon) ->setColor(PHUIButtonView::GREY);
->setUser($viewer)
->setRenderAsForm($viewer->isLoggedIn()));
$curtain->addAction( if ($viewer->isLoggedIn()) {
id(new PhabricatorActionView()) $blame = phabricator_form(
->setName(pht('Open in Editor')) $viewer,
->setHref($editor_link) array(
->setIcon('fa-pencil') 'action' => $base_uri->alter('blame', $blame_value),
->setID('editor_link') 'method' => 'POST',
->setMetadata(array('link_template' => $template)) 'style' => 'display: inline-block;',
->setDisabled(!$editor_link)); ),
$blame);
} else {
$blame->setTag('a');
$blame->setHref($base_uri->alter('blame', $blame_value));
}
$buttons[] = $blame;
if ($editor_link) {
$buttons[] =
id(new PHUIButtonView())
->setTag('a')
->setText(pht('Open File'))
->setHref($editor_link)
->setIcon('fa-pencil')
->setID('editor_link')
->setMetadata(array('link_template' => $template))
->setDisabled(!$editor_link)
->setColor(PHUIButtonView::GREY);
}
$href = null; $href = null;
$show_lint = true;
if ($this->getRequest()->getStr('lint') !== null) { if ($this->getRequest()->getStr('lint') !== null) {
$lint_text = pht('Hide %d Lint Message(s)', count($this->lintMessages)); $lint_text = pht('Hide Lint');
$href = $base_uri->alter('lint', null); $href = $base_uri->alter('lint', null);
} else if ($this->lintCommit === null) { } else if ($this->lintCommit === null) {
$lint_text = pht('Lint not Available'); $show_lint = false;
} else { } else {
$lint_text = pht( $lint_text = pht('Show Lint');
'Show %d Lint Message(s)',
count($this->lintMessages));
$href = $this->getDiffusionRequest()->generateURI(array( $href = $this->getDiffusionRequest()->generateURI(array(
'action' => 'browse', 'action' => 'browse',
'commit' => $this->lintCommit, 'commit' => $this->lintCommit,
))->alter('lint', ''); ))->alter('lint', '');
} }
$curtain->addAction( if ($show_lint) {
id(new PhabricatorActionView()) $buttons[] =
->setName($lint_text) id(new PHUIButtonView())
->setHref($href) ->setTag('a')
->setIcon('fa-exclamation-triangle') ->setText($lint_text)
->setDisabled(!$href)); ->setHref($href)
->setIcon('fa-exclamation-triangle')
->setDisabled(!$href)
->setColor(PHUIButtonView::GREY);
}
$bar = id(new PHUILeftRightView())
->setLeft($buttons)
->addClass('diffusion-action-bar full-mobile-buttons');
return $bar;
}
private function buildOwnersList(DiffusionRequest $drequest) {
$viewer = $this->getViewer();
$repository = $drequest->getRepository(); $repository = $drequest->getRepository();
$owners = 'PhabricatorOwnersApplication'; $owners = 'PhabricatorOwnersApplication';
@ -881,30 +814,54 @@ final class DiffusionBrowseController extends DiffusionController {
$repository->getPHID(), $repository->getPHID(),
$drequest->getPath()); $drequest->getPath());
$ownership = id(new PHUIObjectItemListView())
->setUser($viewer)
->setNoDataString(pht('No Owners'));
if ($packages) { if ($packages) {
$ownership = id(new PHUIStatusListView())
->setUser($viewer);
foreach ($packages as $package) { foreach ($packages as $package) {
$icon = 'fa-list-alt'; $item = id(new PHUIObjectItemView())
$color = 'grey'; ->setObject($package)
->setObjectName($package->getMonogram())
->setHeader($package->getName())
->setHref($package->getURI());
$item = id(new PHUIStatusItemView()) $owners = $package->getOwners();
->setIcon($icon, $color) if ($owners) {
->setTarget($viewer->renderHandle($package->getPHID())); $owner_list = $viewer->renderHandleList(
mpull($owners, 'getUserPHID'));
} else {
$owner_list = phutil_tag('em', array(), pht('None'));
}
$item->addAttribute(pht('Owners: %s', $owner_list));
$auto = $package->getAutoReview();
$autoreview_map = PhabricatorOwnersPackage::getAutoreviewOptionsMap();
$spec = idx($autoreview_map, $auto, array());
$name = idx($spec, 'name', $auto);
$item->addIcon('fa-code', $name);
if ($package->getAuditingEnabled()) {
$item->addIcon('fa-check', pht('Auditing Enabled'));
} else {
$item->addIcon('fa-ban', pht('No Auditing'));
}
if ($package->isArchived()) {
$item->setDisabled(true);
}
$ownership->addItem($item); $ownership->addItem($item);
} }
} else {
$ownership = phutil_tag('em', array(), pht('None'));
} }
$curtain->newPanel() $view = id(new PHUIObjectBoxView())
->setHeaderText(pht('Owners')) ->setHeaderText(pht('Owner Packages'))
->appendChild($ownership); ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
->setObjectList($ownership);
} }
return $curtain; return $view;
} }
private function renderFileButton($file_uri = null, $label = null) { private function renderFileButton($file_uri = null, $label = null) {
@ -912,11 +869,11 @@ final class DiffusionBrowseController extends DiffusionController {
$base_uri = $this->getRequest()->getRequestURI(); $base_uri = $this->getRequest()->getRequestURI();
if ($file_uri) { if ($file_uri) {
$text = pht('Download Raw'); $text = pht('Download File');
$href = $file_uri; $href = $file_uri;
$icon = 'fa-download'; $icon = 'fa-download';
} else { } else {
$text = pht('View Raw'); $text = pht('Raw File');
$href = $base_uri->alter('view', 'raw'); $href = $base_uri->alter('view', 'raw');
$icon = 'fa-file-text'; $icon = 'fa-file-text';
} }
@ -929,7 +886,8 @@ final class DiffusionBrowseController extends DiffusionController {
->setTag('a') ->setTag('a')
->setText($text) ->setText($text)
->setHref($href) ->setHref($href)
->setIcon($icon); ->setIcon($icon)
->setColor(PHUIButtonView::GREY);
return $button; return $button;
} }
@ -1358,13 +1316,12 @@ final class DiffusionBrowseController extends DiffusionController {
'src' => $file_uri, 'src' => $file_uri,
))); )));
$file = $this->renderFileButton($file_uri); $this->corpusButtons[] = $this->renderFileButton($file_uri);
$title = basename($this->getDiffusionRequest()->getPath()); $title = basename($this->getDiffusionRequest()->getPath());
$icon = 'fa-file-image-o'; $icon = 'fa-file-image-o';
$drequest = $this->getDiffusionRequest(); $drequest = $this->getDiffusionRequest();
$actions = $this->getActions($drequest); $this->buildActionButtons($drequest);
$header = $this->buildPanelHeaderView($title, $icon, $actions); $header = $this->buildPanelHeaderView($title, $icon);
$header->addActionLink($file);
return id(new PHUIObjectBoxView()) return id(new PHUIObjectBoxView())
->setHeader($header) ->setHeader($header)
@ -1379,13 +1336,12 @@ final class DiffusionBrowseController extends DiffusionController {
->addPadding(PHUI::PADDING_LARGE) ->addPadding(PHUI::PADDING_LARGE)
->appendChild($text); ->appendChild($text);
$file = $this->renderFileButton($file_uri); $this->corpusButtons[] = $this->renderFileButton($file_uri);
$title = basename($this->getDiffusionRequest()->getPath()); $title = basename($this->getDiffusionRequest()->getPath());
$icon = 'fa-file'; $icon = 'fa-file';
$drequest = $this->getDiffusionRequest(); $drequest = $this->getDiffusionRequest();
$actions = $this->getActions($drequest); $this->buildActionButtons($drequest);
$header = $this->buildPanelHeaderView($title, $icon, $actions); $header = $this->buildPanelHeaderView($title, $icon);
$header->addActionLink($file);
$box = id(new PHUIObjectBoxView()) $box = id(new PHUIObjectBoxView())
->setHeader($header) ->setHeader($header)
@ -1581,43 +1537,6 @@ final class DiffusionBrowseController extends DiffusionController {
return "{$summary}\n{$date} \xC2\xB7 {$author}"; return "{$summary}\n{$date} \xC2\xB7 {$author}";
} }
protected function renderSearchForm() {
$drequest = $this->getDiffusionRequest();
$forms = array();
$form = id(new AphrontFormView())
->setUser($this->getViewer())
->setMethod('GET');
switch ($drequest->getRepository()->getVersionControlSystem()) {
case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN:
$forms[] = id(clone $form)
->appendChild(pht('Search is not available in Subversion.'));
break;
default:
$forms[] = id(clone $form)
->appendChild(
id(new AphrontFormTextWithSubmitControl())
->setLabel(pht('File Name'))
->setSubmitLabel(pht('Search File Names'))
->setName('find')
->setValue($this->getRequest()->getStr('find')));
$forms[] = id(clone $form)
->appendChild(
id(new AphrontFormTextWithSubmitControl())
->setLabel(pht('Pattern'))
->setSubmitLabel(pht('Grep File Content'))
->setName('grep')
->setValue($this->getRequest()->getStr('grep')));
break;
}
require_celerity_resource('diffusion-icons-css');
$form_box = phutil_tag_div('diffusion-search-boxen', $forms);
return $form_box;
}
protected function markupText($text) { protected function markupText($text) {
$engine = PhabricatorMarkupEngine::newDiffusionMarkupEngine(); $engine = PhabricatorMarkupEngine::newDiffusionMarkupEngine();
$engine->setConfig('viewer', $this->getRequest()->getUser()); $engine->setConfig('viewer', $this->getRequest()->getUser());
@ -1635,34 +1554,43 @@ final class DiffusionBrowseController extends DiffusionController {
protected function buildHeaderView(DiffusionRequest $drequest) { protected function buildHeaderView(DiffusionRequest $drequest) {
$viewer = $this->getViewer(); $viewer = $this->getViewer();
$repository = $drequest->getRepository();
$tag = $this->renderCommitHashTag($drequest); $commit_tag = $this->renderCommitHashTag($drequest);
$path = nonempty(basename($drequest->getPath()), '/');
$search = $this->renderSearchForm($path);
$header = id(new PHUIHeaderView()) $header = id(new PHUIHeaderView())
->setUser($viewer) ->setUser($viewer)
->setHeader($this->renderPathLinks($drequest, $mode = 'browse')) ->setHeader($this->renderPathLinks($drequest, $mode = 'browse'))
->addTag($tag); ->addActionItem($search)
->addTag($commit_tag)
->addClass('diffusion-browse-header');
if (!$repository->isSVN()) {
$branch_tag = $this->renderBranchTag($drequest);
$header->addTag($branch_tag);
}
return $header; return $header;
} }
protected function buildPanelHeaderView($title, $icon, array $actions) { protected function buildPanelHeaderView($title, $icon) {
$header = id(new PHUIHeaderView()) $header = id(new PHUIHeaderView())
->setHeader($title) ->setHeader($title)
->setHeaderIcon($icon) ->setHeaderIcon($icon)
->addClass('diffusion-panel-header-view'); ->addClass('diffusion-panel-header-view');
foreach ($actions as $action_link) {
if ($action_link) {
$header->addActionLink($action_link);
}
}
return $header; return $header;
} }
protected function getActions(DiffusionRequest $drequest) { protected function buildActionButtons(
DiffusionRequest $drequest,
$is_directory = false) {
$viewer = $this->getViewer(); $viewer = $this->getViewer();
$repository = $drequest->getRepository(); $repository = $drequest->getRepository();
$history_uri = $drequest->generateURI(array('action' => 'history')); $history_uri = $drequest->generateURI(array('action' => 'history'));
@ -1674,7 +1602,7 @@ final class DiffusionBrowseController extends DiffusionController {
'action' => 'browse', 'action' => 'browse',
)); ));
if ($repository->supportsBranchComparison()) { if ($repository->supportsBranchComparison() && $is_directory) {
$compare_uri = $drequest->generateURI(array('action' => 'compare')); $compare_uri = $drequest->generateURI(array('action' => 'compare'));
$compare = id(new PHUIButtonView()) $compare = id(new PHUIButtonView())
->setText(pht('Compare')) ->setText(pht('Compare'))
@ -1683,6 +1611,7 @@ final class DiffusionBrowseController extends DiffusionController {
->setTag('a') ->setTag('a')
->setHref($compare_uri) ->setHref($compare_uri)
->setColor(PHUIButtonView::GREY); ->setColor(PHUIButtonView::GREY);
$this->corpusButtons[] = $compare;
} }
$head = null; $head = null;
@ -1692,6 +1621,7 @@ final class DiffusionBrowseController extends DiffusionController {
->setHref($head_uri) ->setHref($head_uri)
->setIcon('fa-home') ->setIcon('fa-home')
->setColor(PHUIButtonView::GREY); ->setColor(PHUIButtonView::GREY);
$this->corpusButtons[] = $head;
} }
$history = id(new PHUIButtonView()) $history = id(new PHUIButtonView())
@ -1700,8 +1630,8 @@ final class DiffusionBrowseController extends DiffusionController {
->setTag('a') ->setTag('a')
->setIcon('fa-history') ->setIcon('fa-history')
->setColor(PHUIButtonView::GREY); ->setColor(PHUIButtonView::GREY);
$this->corpusButtons[] = $history;
return array($history, $compare, $head);
} }
protected function buildPropertyView( protected function buildPropertyView(
@ -1758,7 +1688,7 @@ final class DiffusionBrowseController extends DiffusionController {
$revisions = id(new DifferentialRevisionQuery()) $revisions = id(new DifferentialRevisionQuery())
->setViewer($viewer) ->setViewer($viewer)
->withPath($repository->getID(), $path_id) ->withPath($repository->getID(), $path_id)
->withStatus(DifferentialLegacyQuery::STATUS_OPEN) ->withIsOpen(true)
->withUpdatedEpochBetween($recent, null) ->withUpdatedEpochBetween($recent, null)
->setOrder(DifferentialRevisionQuery::ORDER_MODIFIED) ->setOrder(DifferentialRevisionQuery::ORDER_MODIFIED)
->setLimit(10) ->setLimit(10)
@ -1905,8 +1835,8 @@ final class DiffusionBrowseController extends DiffusionController {
$title = basename($this->getDiffusionRequest()->getPath()); $title = basename($this->getDiffusionRequest()->getPath());
$icon = 'fa-archive'; $icon = 'fa-archive';
$drequest = $this->getDiffusionRequest(); $drequest = $this->getDiffusionRequest();
$actions = $this->getActions($drequest); $this->buildActionButtons($drequest);
$header = $this->buildPanelHeaderView($title, $icon, $actions); $header = $this->buildPanelHeaderView($title, $icon);
$severity = PHUIInfoView::SEVERITY_NOTICE; $severity = PHUIInfoView::SEVERITY_NOTICE;
@ -1918,14 +1848,13 @@ final class DiffusionBrowseController extends DiffusionController {
try { try {
$file = $this->loadGitLFSFile($ref); $file = $this->loadGitLFSFile($ref);
$data = $this->renderGitLFSButton(); $data = $this->renderGitLFSButton();
$header->addActionLink($data);
} catch (Exception $ex) { } catch (Exception $ex) {
$severity = PHUIInfoView::SEVERITY_ERROR; $severity = PHUIInfoView::SEVERITY_ERROR;
$messages[] = pht('The data for this file could not be loaded.'); $messages[] = pht('The data for this file could not be loaded.');
} }
$raw = $this->renderFileButton(null, pht('View Raw LFS Pointer')); $this->corpusButtons[] = $this->renderFileButton(
$header->addActionLink($raw); null, pht('View Raw LFS Pointer'));
$corpus = id(new PHUIObjectBoxView()) $corpus = id(new PHUIObjectBoxView())
->setHeader($header) ->setHeader($header)

View file

@ -148,7 +148,7 @@ abstract class DiffusionController extends PhabricatorController {
if (!$spec['commit'] && !$spec['tags'] && !$spec['branches']) { if (!$spec['commit'] && !$spec['tags'] && !$spec['branches']) {
$branch_name = $drequest->getBranch(); $branch_name = $drequest->getBranch();
if ($branch_name) { if (strlen($branch_name)) {
$repository_name .= ' ('.$branch_name.')'; $repository_name .= ' ('.$branch_name.')';
} }
} }
@ -343,6 +343,38 @@ abstract class DiffusionController extends PhabricatorController {
return $tag; return $tag;
} }
protected function renderBranchTag(DiffusionRequest $drequest) {
$branch = $drequest->getBranch();
$branch = id(new PhutilUTF8StringTruncator())
->setMaximumGlyphs(24)
->truncateString($branch);
$tag = id(new PHUITagView())
->setName($branch)
->setColor(PHUITagView::COLOR_INDIGO)
->setBorder(PHUITagView::BORDER_NONE)
->setType(PHUITagView::TYPE_OUTLINE)
->addClass('diffusion-header-branch-tag');
return $tag;
}
protected function renderSymbolicCommit(DiffusionRequest $drequest) {
$symbolic_tag = $drequest->getSymbolicCommit();
$symbolic_tag = id(new PhutilUTF8StringTruncator())
->setMaximumGlyphs(24)
->truncateString($symbolic_tag);
$tag = id(new PHUITagView())
->setName($symbolic_tag)
->setIcon('fa-tag')
->setColor(PHUITagView::COLOR_INDIGO)
->setBorder(PHUITagView::BORDER_NONE)
->setType(PHUITagView::TYPE_SHADE);
return $tag;
}
protected function renderDirectoryReadme(DiffusionBrowseResultSet $browse) { protected function renderDirectoryReadme(DiffusionBrowseResultSet $browse) {
$readme_path = $browse->getReadmePath(); $readme_path = $browse->getReadmePath();
if ($readme_path === null) { if ($readme_path === null) {
@ -410,6 +442,58 @@ abstract class DiffusionController extends PhabricatorController {
->setContent($readme_corpus); ->setContent($readme_corpus);
} }
protected function renderSearchForm($path = '/') {
$drequest = $this->getDiffusionRequest();
$viewer = $this->getViewer();
switch ($drequest->getRepository()->getVersionControlSystem()) {
case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN:
return null;
}
$search_term = $this->getRequest()->getStr('grep');
require_celerity_resource('diffusion-icons-css');
require_celerity_resource('diffusion-css');
$href = $drequest->generateURI(array(
'action' => 'browse',
'path' => $path,
));
$bar = javelin_tag(
'input',
array(
'type' => 'text',
'id' => 'diffusion-search-input',
'name' => 'grep',
'class' => 'diffusion-search-input',
'sigil' => 'diffusion-search-input',
'placeholder' => pht('Pattern Search'),
'value' => $search_term,
));
$form = phabricator_form(
$viewer,
array(
'method' => 'GET',
'action' => $href,
'sigil' => 'diffusion-search-form',
'class' => 'diffusion-search-form',
'id' => 'diffusion-search-form',
),
array(
$bar,
));
$form_view = phutil_tag(
'div',
array(
'class' => 'diffusion-search-form-view',
),
$form);
return $form_view;
}
protected function buildTabsView($key) { protected function buildTabsView($key) {
$drequest = $this->getDiffusionRequest(); $drequest = $this->getDiffusionRequest();
$repository = $drequest->getRepository(); $repository = $drequest->getRepository();
@ -418,15 +502,15 @@ abstract class DiffusionController extends PhabricatorController {
$view->addMenuItem( $view->addMenuItem(
id(new PHUIListItemView()) id(new PHUIListItemView())
->setKey('home') ->setKey('code')
->setName(pht('Home')) ->setName(pht('Code'))
->setIcon('fa-home') ->setIcon('fa-code')
->setHref($drequest->generateURI( ->setHref($drequest->generateURI(
array( array(
'action' => 'branch', 'action' => 'branch',
'path' => '/', 'path' => '/',
))) )))
->setSelected($key == 'home')); ->setSelected($key == 'code'));
if (!$repository->isSVN()) { if (!$repository->isSVN()) {
$view->addMenuItem( $view->addMenuItem(

View file

@ -11,6 +11,7 @@ final class DiffusionGraphController extends DiffusionController {
if ($response) { if ($response) {
return $response; return $response;
} }
require_celerity_resource('diffusion-css');
$viewer = $this->getViewer(); $viewer = $this->getViewer();
$drequest = $this->getDiffusionRequest(); $drequest = $this->getDiffusionRequest();
@ -83,6 +84,7 @@ final class DiffusionGraphController extends DiffusionController {
private function buildHeader(DiffusionRequest $drequest) { private function buildHeader(DiffusionRequest $drequest) {
$viewer = $this->getViewer(); $viewer = $this->getViewer();
$repository = $drequest->getRepository();
$no_path = !strlen($drequest->getPath()); $no_path = !strlen($drequest->getPath());
if ($no_path) { if ($no_path) {
@ -96,6 +98,11 @@ final class DiffusionGraphController extends DiffusionController {
->setHeader($header_text) ->setHeader($header_text)
->setHeaderIcon('fa-code-fork'); ->setHeaderIcon('fa-code-fork');
if (!$repository->isSVN()) {
$branch_tag = $this->renderBranchTag($drequest);
$header->addTag($branch_tag);
}
return $header; return $header;
} }

View file

@ -11,6 +11,7 @@ final class DiffusionHistoryController extends DiffusionController {
if ($response) { if ($response) {
return $response; return $response;
} }
require_celerity_resource('diffusion-css');
$viewer = $this->getViewer(); $viewer = $this->getViewer();
$drequest = $this->getDiffusionRequest(); $drequest = $this->getDiffusionRequest();
@ -78,6 +79,7 @@ final class DiffusionHistoryController extends DiffusionController {
private function buildHeader(DiffusionRequest $drequest) { private function buildHeader(DiffusionRequest $drequest) {
$viewer = $this->getViewer(); $viewer = $this->getViewer();
$repository = $drequest->getRepository();
$no_path = !strlen($drequest->getPath()); $no_path = !strlen($drequest->getPath());
if ($no_path) { if ($no_path) {
@ -91,6 +93,16 @@ final class DiffusionHistoryController extends DiffusionController {
->setHeader($header_text) ->setHeader($header_text)
->setHeaderIcon('fa-clock-o'); ->setHeaderIcon('fa-clock-o');
if (!$repository->isSVN()) {
$branch_tag = $this->renderBranchTag($drequest);
$header->addTag($branch_tag);
}
if ($drequest->getSymbolicCommit()) {
$symbolic_tag = $this->renderSymbolicCommit($drequest);
$header->addTag($symbolic_tag);
}
return $header; return $header;
} }

View file

@ -167,6 +167,7 @@ final class DiffusionLintController extends DiffusionController {
'path' => true, 'path' => true,
'view' => 'lint', 'view' => 'lint',
)); ));
$crumbs->setBorder(true);
if ($drequest) { if ($drequest) {
$title[] = $drequest->getRepository()->getDisplayName(); $title[] = $drequest->getRepository()->getDisplayName();
@ -178,7 +179,7 @@ final class DiffusionLintController extends DiffusionController {
$branch = $drequest->loadBranch(); $branch = $drequest->loadBranch();
$header = id(new PHUIHeaderView()) $header = id(new PHUIHeaderView())
->setHeader($this->renderPathLinks($drequest, 'lint')) ->setHeader(pht('Lint: %s', $this->renderPathLinks($drequest, 'lint')))
->setUser($viewer) ->setUser($viewer)
->setHeaderIcon('fa-code'); ->setHeaderIcon('fa-code');
$actions = $this->buildActionView($drequest); $actions = $this->buildActionView($drequest);
@ -465,6 +466,7 @@ final class DiffusionLintController extends DiffusionController {
'path' => true, 'path' => true,
'view' => 'lint', 'view' => 'lint',
)); ));
$crumbs->setBorder(true);
$header = id(new PHUIHeaderView()) $header = id(new PHUIHeaderView())
->setHeader(pht('Lint: %s', $drequest->getRepository()->getDisplayName())) ->setHeader(pht('Lint: %s', $drequest->getRepository()->getDisplayName()))

View file

@ -31,8 +31,6 @@ final class DiffusionRepositoryController extends DiffusionController {
$description = $this->buildDescriptionView($repository); $description = $this->buildDescriptionView($repository);
$locate_file = $this->buildLocateFile(); $locate_file = $this->buildLocateFile();
$header->setActionList($actions);
// Before we do any work, make sure we're looking at a some content: we're // Before we do any work, make sure we're looking at a some content: we're
// on a valid branch, and the repository is not empty. // on a valid branch, and the repository is not empty.
$page_has_content = false; $page_has_content = false;
@ -100,7 +98,7 @@ final class DiffusionRepositoryController extends DiffusionController {
->setErrors(array($empty_message)); ->setErrors(array($empty_message));
} }
$tabs = $this->buildTabsView('home'); $tabs = $this->buildTabsView('code');
$clone_uri = $drequest->generateURI( $clone_uri = $drequest->generateURI(
array( array(
@ -113,6 +111,15 @@ final class DiffusionRepositoryController extends DiffusionController {
$clone_text = pht('Clone'); $clone_text = pht('Clone');
} }
$actions_button = id(new PHUIButtonView())
->setTag('a')
->setText(pht('Actions'))
->setIcon('fa-bars')
->addClass('mmr')
->setColor(PHUIButtonView::GREY)
->setDropdown(true)
->setDropdownMenu($actions);
$clone_button = id(new PHUIButtonView()) $clone_button = id(new PHUIButtonView())
->setTag('a') ->setTag('a')
->setText($clone_text) ->setText($clone_text)
@ -123,7 +130,7 @@ final class DiffusionRepositoryController extends DiffusionController {
$bar = id(new PHUILeftRightView()) $bar = id(new PHUILeftRightView())
->setLeft($locate_file) ->setLeft($locate_file)
->setRight(array($this->branchButton, $clone_button)) ->setRight(array($this->branchButton, $actions_button, $clone_button))
->addClass('diffusion-action-bar'); ->addClass('diffusion-action-bar');
$view = id(new PHUITwoColumnView()) $view = id(new PHUITwoColumnView())
@ -293,6 +300,9 @@ final class DiffusionRepositoryController extends DiffusionController {
private function buildHeaderView(PhabricatorRepository $repository) { private function buildHeaderView(PhabricatorRepository $repository) {
$viewer = $this->getViewer(); $viewer = $this->getViewer();
$drequest = $this->getDiffusionRequest();
$search = $this->renderSearchForm();
$header = id(new PHUIHeaderView()) $header = id(new PHUIHeaderView())
->setHeader($repository->getName()) ->setHeader($repository->getName())
->setUser($viewer) ->setUser($viewer)
@ -300,6 +310,7 @@ final class DiffusionRepositoryController extends DiffusionController {
->setProfileHeader(true) ->setProfileHeader(true)
->setImage($repository->getProfileImageURI()) ->setImage($repository->getProfileImageURI())
->setImageEditURL('/diffusion/picture/'.$repository->getID().'/') ->setImageEditURL('/diffusion/picture/'.$repository->getID().'/')
->addActionItem($search)
->addClass('diffusion-profile-header'); ->addClass('diffusion-profile-header');
if (!$repository->isTracked()) { if (!$repository->isTracked()) {
@ -315,6 +326,14 @@ final class DiffusionRepositoryController extends DiffusionController {
$header->setStatus('fa-check', 'bluegrey', pht('Active')); $header->setStatus('fa-check', 'bluegrey', pht('Active'));
} }
if (!$repository->isSVN()) {
$default = $repository->getDefaultBranch();
if ($default != $drequest->getBranch()) {
$branch_tag = $this->renderBranchTag($drequest);
$header->addTag($branch_tag);
}
}
return $header; return $header;
} }
@ -546,8 +565,22 @@ final class DiffusionRepositoryController extends DiffusionController {
$browse_uri = $drequest->generateURI(array('action' => 'browse')); $browse_uri = $drequest->generateURI(array('action' => 'browse'));
$pager->setURI($browse_uri, 'offset'); $pager->setURI($browse_uri, 'offset');
$repository_name = $repository->getName();
$branch_name = $drequest->getBranch();
if (strlen($branch_name)) {
$repository_name .= ' ('.$branch_name.')';
}
$header = phutil_tag(
'a',
array(
'href' => $browse_uri,
'class' => 'diffusion-view-browse-header',
),
$repository_name);
return id(new PHUIObjectBoxView()) return id(new PHUIObjectBoxView())
->setHeaderText($repository->getName()) ->setHeaderText($header)
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
->setTable($browse_table) ->setTable($browse_table)
->setPager($pager); ->setPager($pager);

View file

@ -37,9 +37,6 @@ final class DiffusionRepositoryEditController
$crumbs->setBorder(true); $crumbs->setBorder(true);
$title = pht('Choose Repository Type'); $title = pht('Choose Repository Type');
$header = id(new PHUIHeaderView())
->setHeader(pht('Create Repository'))
->setHeaderIcon('fa-plus-square');
$layout = id(new AphrontMultiColumnView()) $layout = id(new AphrontMultiColumnView())
->setFluidLayout(true); ->setFluidLayout(true);
@ -47,8 +44,10 @@ final class DiffusionRepositoryEditController
$create_uri = $request->getRequestURI(); $create_uri = $request->getRequestURI();
foreach ($vcs_types as $vcs_key => $vcs_type) { foreach ($vcs_types as $vcs_key => $vcs_type) {
$image = idx($vcs_type, 'image');
$image = PhabricatorFile::loadBuiltin($viewer, $image);
$action = id(new PHUIActionPanelView()) $action = id(new PHUIActionPanelView())
->setIcon(idx($vcs_type, 'icon')) ->setImage($image->getBestURI())
->setHeader(idx($vcs_type, 'create.header')) ->setHeader(idx($vcs_type, 'create.header'))
->setHref($create_uri->alter('vcs', $vcs_key)) ->setHref($create_uri->alter('vcs', $vcs_key))
->setSubheader(idx($vcs_type, 'create.subheader')); ->setSubheader(idx($vcs_type, 'create.subheader'));
@ -62,9 +61,12 @@ final class DiffusionRepositoryEditController
$observe_href = PhabricatorEnv::getDoclink( $observe_href = PhabricatorEnv::getDoclink(
'Diffusion User Guide: Existing Repositories'); 'Diffusion User Guide: Existing Repositories');
require_celerity_resource('diffusion-css');
$image = PhabricatorFile::loadBuiltin($viewer, 'repo/repo.png');
$hints->addColumn( $hints->addColumn(
id(new PHUIActionPanelView()) id(new PHUIActionPanelView())
->setIcon('fa-book') ->setImage($image->getBestURI())
->setHeader(pht('Import or Observe an Existing Repository')) ->setHeader(pht('Import or Observe an Existing Repository'))
->setHref($observe_href) ->setHref($observe_href)
->setSubheader( ->setSubheader(
@ -72,12 +74,15 @@ final class DiffusionRepositoryEditController
'Review the documentation describing how to import or observe an '. 'Review the documentation describing how to import or observe an '.
'existing repository.'))); 'existing repository.')));
$layout = id(new PHUIBoxView())
->addClass('diffusion-create-repo')
->appendChild($layout);
$view = id(new PHUITwoColumnView()) $view = id(new PHUITwoColumnView())
->setHeader($header) ->setFixed(true)
->setFooter( ->setFooter(
array( array(
$layout, $layout,
phutil_tag('br'),
$hints, $hints,
)); ));

View file

@ -11,6 +11,7 @@ final class DiffusionTagListController extends DiffusionController {
if ($response) { if ($response) {
return $response; return $response;
} }
require_celerity_resource('diffusion-css');
$viewer = $this->getViewer(); $viewer = $this->getViewer();
$drequest = $this->getDiffusionRequest(); $drequest = $this->getDiffusionRequest();
@ -50,6 +51,11 @@ final class DiffusionTagListController extends DiffusionController {
->setHeader(pht('Tags')) ->setHeader(pht('Tags'))
->setHeaderIcon('fa-tags'); ->setHeaderIcon('fa-tags');
if (!$repository->isSVN()) {
$branch_tag = $this->renderBranchTag($drequest);
$header->addTag($branch_tag);
}
if (!$tags) { if (!$tags) {
$content = $this->renderStatusMessage( $content = $this->renderStatusMessage(
pht('No Tags'), pht('No Tags'),

View file

@ -19,36 +19,15 @@ final class DiffusionCommitRevisionAcceptedHeraldField
return null; return null;
} }
$status = $revision->getStatus(); if ($revision->isAccepted()) {
return $revision->getPHID();
switch ($status) {
case ArcanistDifferentialRevisionStatus::ACCEPTED:
return $revision->getPHID();
case ArcanistDifferentialRevisionStatus::CLOSED:
if ($revision->hasRevisionProperty(
DifferentialRevision::PROPERTY_CLOSED_FROM_ACCEPTED)) {
if ($revision->getProperty(
DifferentialRevision::PROPERTY_CLOSED_FROM_ACCEPTED)) {
return $revision->getPHID();
} else {
return null;
}
} else {
// continue on to old-style precommitRevisionStatus
break;
}
default:
return null;
} }
$data = $object->getCommitData(); $was_accepted = DifferentialRevision::PROPERTY_CLOSED_FROM_ACCEPTED;
$status = $data->getCommitDetail('precommitRevisionStatus'); if ($revision->isPublished()) {
if ($revision->getProperty($was_accepted)) {
switch ($status) {
case ArcanistDifferentialRevisionStatus::ACCEPTED:
case ArcanistDifferentialRevisionStatus::CLOSED:
return $revision->getPHID(); return $revision->getPHID();
}
} }
return null; return null;

View file

@ -15,21 +15,19 @@ final class DiffusionPreCommitContentRevisionAcceptedHeraldField
public function getHeraldFieldValue($object) { public function getHeraldFieldValue($object) {
$revision = $this->getAdapter()->getRevision(); $revision = $this->getAdapter()->getRevision();
if (!$revision) { if (!$revision) {
return null; return null;
} }
switch ($revision->getStatus()) { if ($revision->isAccepted()) {
case ArcanistDifferentialRevisionStatus::ACCEPTED: return $revision->getPHID();
return $revision->getPHID(); }
case ArcanistDifferentialRevisionStatus::CLOSED:
if ($revision->getProperty(
DifferentialRevision::PROPERTY_CLOSED_FROM_ACCEPTED)) {
return $revision->getPHID(); $was_accepted = DifferentialRevision::PROPERTY_CLOSED_FROM_ACCEPTED;
} if ($revision->isPublished()) {
break; if ($revision->getProperty($was_accepted)) {
return $revision->getPHID();
}
} }
return null; return null;

View file

@ -110,6 +110,7 @@ final class DiffusionRepositoryBranchesManagementPanel
->execute(); ->execute();
$branches = DiffusionRepositoryRef::loadAllFromDictionaries($branches); $branches = DiffusionRepositoryRef::loadAllFromDictionaries($branches);
$branches = $pager->sliceResults($branches); $branches = $pager->sliceResults($branches);
$can_close_branches = ($repository->isHg());
$rows = array(); $rows = array();
foreach ($branches as $branch) { foreach ($branches as $branch) {
@ -117,8 +118,25 @@ final class DiffusionRepositoryBranchesManagementPanel
$tracking = $repository->shouldTrackBranch($branch_name); $tracking = $repository->shouldTrackBranch($branch_name);
$autoclosing = $repository->shouldAutocloseBranch($branch_name); $autoclosing = $repository->shouldAutocloseBranch($branch_name);
$default = $repository->getDefaultBranch();
$icon = null;
if ($default == $branch->getShortName()) {
$icon = id(new PHUIIconView())
->setIcon('fa-code-fork');
}
$fields = $branch->getRawFields();
$closed = idx($fields, 'closed');
if ($closed) {
$status = pht('Closed');
} else {
$status = pht('Open');
}
$rows[] = array( $rows[] = array(
$icon,
$branch_name, $branch_name,
$status,
$tracking ? pht('Tracking') : pht('Off'), $tracking ? pht('Tracking') : pht('Off'),
$autoclosing ? pht('Autoclose On') : pht('Off'), $autoclosing ? pht('Autoclose On') : pht('Off'),
); );
@ -126,16 +144,28 @@ final class DiffusionRepositoryBranchesManagementPanel
$branch_table = new AphrontTableView($rows); $branch_table = new AphrontTableView($rows);
$branch_table->setHeaders( $branch_table->setHeaders(
array( array(
'',
pht('Branch'), pht('Branch'),
pht('Status'),
pht('Track'), pht('Track'),
pht('Autoclose'), pht('Autoclose'),
)); ));
$branch_table->setColumnClasses( $branch_table->setColumnClasses(
array( array(
'',
'pri', 'pri',
'narrow', 'narrow',
'narrow',
'wide', 'wide',
)); ));
$branch_table->setColumnVisibility(
array(
true,
true,
$can_close_branches,
true,
true,
));
$box = id(new PHUIObjectBoxView()) $box = id(new PHUIObjectBoxView())
->setHeaderText(pht('Branch Status')) ->setHeaderText(pht('Branch Status'))

View file

@ -233,6 +233,7 @@ final class DiffusionSetPasswordSettingsPanel extends PhabricatorSettingsPanel {
$object_box = id(new PHUIObjectBoxView()) $object_box = id(new PHUIObjectBoxView())
->setHeaderText($title) ->setHeaderText($title)
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
->setForm($form) ->setForm($form)
->setFormErrors($errors); ->setFormErrors($errors);
@ -258,6 +259,7 @@ final class DiffusionSetPasswordSettingsPanel extends PhabricatorSettingsPanel {
$remove_box = id(new PHUIObjectBoxView()) $remove_box = id(new PHUIObjectBoxView())
->setHeaderText(pht('Remove VCS Password')) ->setHeaderText(pht('Remove VCS Password'))
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
->setForm($remove_form); ->setForm($remove_form);
$saved = null; $saved = null;

View file

@ -74,14 +74,6 @@ final class DiffusionBranchListView extends DiffusionView {
} }
} }
$fields = $branch->getRawFields();
$closed = idx($fields, 'closed');
if ($closed) {
$status = pht('Closed');
} else {
$status = pht('Open');
}
$browse_href = $drequest->generateURI( $browse_href = $drequest->generateURI(
array( array(
'action' => 'browse', 'action' => 'browse',
@ -129,6 +121,18 @@ final class DiffusionBranchListView extends DiffusionView {
} }
$item->addAttribute(array($datetime)); $item->addAttribute(array($datetime));
if ($can_close_branches) {
$fields = $branch->getRawFields();
$closed = idx($fields, 'closed');
if ($closed) {
$status = pht('Branch Closed');
$item->setDisabled(true);
} else {
$status = pht('Branch Open');
}
$item->addAttribute($status);
}
$list->addItem($item); $list->addItem($item);
} }

View file

@ -0,0 +1,124 @@
<?php
final class DiffusionPatternSearchView extends DiffusionView {
private $path;
private $matches;
private $pattern;
public function setPath($path) {
$this->path = $path;
return $this;
}
public function setMatches(array $matches) {
$this->matches = $matches;
return $this;
}
public function setPattern($pattern) {
$this->pattern = $pattern;
return $this;
}
public function render() {
$drequest = $this->getDiffusionRequest();
$path = $this->path;
$pattern = $this->pattern;
$rows = array();
foreach ($this->matches as $result) {
list($line, $string) = $result;
$matches = null;
$count = @preg_match_all(
'('.$pattern.')u',
$string,
$matches,
PREG_OFFSET_CAPTURE);
if (!$count) {
$output = ltrim($string);
} else {
$output = array();
$cursor = 0;
$length = strlen($string);
foreach ($matches[0] as $match) {
$offset = $match[1];
if ($cursor != $offset) {
$output[] = array(
'text' => substr($string, $cursor, $offset),
'highlight' => false,
);
}
$output[] = array(
'text' => $match[0],
'highlight' => true,
);
$cursor = $offset + strlen($match[0]);
}
if ($cursor != $length) {
$output[] = array(
'text' => substr($string, $cursor),
'highlight' => false,
);
}
if ($output) {
$output[0]['text'] = ltrim($output[0]['text']);
}
foreach ($output as $key => $segment) {
if ($segment['highlight']) {
$output[$key] = phutil_tag('strong', array(), $segment['text']);
} else {
$output[$key] = $segment['text'];
}
}
}
$string = phutil_tag(
'pre',
array('class' => 'PhabricatorMonospaced phui-source-fragment'),
$output);
$href = $drequest->generateURI(array(
'action' => 'browse',
'path' => $path,
'line' => $line,
));
$rows[] = array(
phutil_tag('a', array('href' => $href), $line),
$string,
);
}
$path_title = Filesystem::readablePath($this->path, $drequest->getPath());
$href = $drequest->generateURI(array(
'action' => 'browse',
'path' => $path_title,
));
$title = phutil_tag('a', array('href' => $href), $path_title);
$table = id(new AphrontTableView($rows))
->setClassName('remarkup-code')
->setHeaders(array(pht('Line'), pht('String')))
->setColumnClasses(array('n', 'wide'));
$header = id(new PHUIHeaderView())
->setHeader($title);
$box = id(new PHUIObjectBoxView())
->setHeader($header)
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
->setTable($table);
return $box->render();
}
}

View file

@ -18,6 +18,25 @@ final class PhamePostViewController
$is_live = $this->getIsLive(); $is_live = $this->getIsLive();
$is_external = $this->getIsExternal(); $is_external = $this->getIsExternal();
// Register a blog "view" count
//
if (!$post->isDraft() && !$post->isArchived()) {
$unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
$xactions = array();
$xactions[] = id(new PhamePostTransaction())
->setTransactionType(PhamePostViewsTransaction::TRANSACTIONTYPE)
->setNewValue(null);
$editor = id(new PhamePostEditor())
->setActor($viewer)
->setContentSourceFromRequest($request)
->setContinueOnMissingFields(true)
->setContinueOnNoEffect(true);
$editor->applyTransactions($post, $xactions);
unset($unguarded);
}
$header = id(new PHUIHeaderView()) $header = id(new PHUIHeaderView())
->addClass('phame-header-bar') ->addClass('phame-header-bar')
->setUser($viewer); ->setUser($viewer);
@ -151,6 +170,11 @@ final class PhamePostViewController
->setUser($viewer) ->setUser($viewer)
->setObject($post); ->setObject($post);
$views = id(new PhutilNumber($post->getViews()));
$properties->addProperty(
pht('Views'),
pht('%s', $views));
$is_live = $this->getIsLive(); $is_live = $this->getIsLive();
$is_external = $this->getIsExternal(); $is_external = $this->getIsExternal();
$next_view = new PhameNextPostView(); $next_view = new PhameNextPostView();

View file

@ -41,6 +41,12 @@ final class PhamePostEditor
if ($object->isDraft() || $object->isArchived()) { if ($object->isDraft() || $object->isArchived()) {
return false; return false;
} }
foreach ($xactions as $xaction) {
switch ($xaction->getTransactionType()) {
case PhamePostViewsTransaction::TRANSACTIONTYPE:
return false;
}
}
return true; return true;
} }

View file

@ -22,6 +22,7 @@ final class PhamePost extends PhameDAO
protected $phameTitle; protected $phameTitle;
protected $body; protected $body;
protected $visibility; protected $visibility;
protected $views;
protected $configData; protected $configData;
protected $datePublished; protected $datePublished;
protected $blogPHID; protected $blogPHID;
@ -40,7 +41,8 @@ final class PhamePost extends PhameDAO
->setBlogPHID($blog->getPHID()) ->setBlogPHID($blog->getPHID())
->attachBlog($blog) ->attachBlog($blog)
->setDatePublished(PhabricatorTime::getNow()) ->setDatePublished(PhabricatorTime::getNow())
->setVisibility(PhameConstants::VISIBILITY_PUBLISHED); ->setVisibility(PhameConstants::VISIBILITY_PUBLISHED)
->setViews(0);
return $post; return $post;
} }
@ -128,6 +130,7 @@ final class PhamePost extends PhameDAO
'subtitle' => 'text64', 'subtitle' => 'text64',
'phameTitle' => 'sort64?', 'phameTitle' => 'sort64?',
'visibility' => 'uint32', 'visibility' => 'uint32',
'views' => 'uint32',
'mailKey' => 'bytes20', 'mailKey' => 'bytes20',
'headerImagePHID' => 'phid?', 'headerImagePHID' => 'phid?',

View file

@ -0,0 +1,18 @@
<?php
final class PhamePostViewsTransaction
extends PhamePostTransactionType {
const TRANSACTIONTYPE = 'phame.post.views';
public function generateOldValue($object) {
return $object->getViews();
}
public function applyInternalEffects($object, $value) {
$views = $object->getViews();
$views++;
$object->setViews($views);
}
}

View file

@ -26,18 +26,21 @@ final class PhabricatorRepositoryType extends Phobject {
self::REPOSITORY_TYPE_GIT => array( self::REPOSITORY_TYPE_GIT => array(
'name' => pht('Git'), 'name' => pht('Git'),
'icon' => 'fa-git', 'icon' => 'fa-git',
'image' => 'repo/repo-git.png',
'create.header' => pht('Create Git Repository'), 'create.header' => pht('Create Git Repository'),
'create.subheader' => pht('Create a new Git repository.'), 'create.subheader' => pht('Create a new Git repository.'),
), ),
self::REPOSITORY_TYPE_MERCURIAL => array( self::REPOSITORY_TYPE_MERCURIAL => array(
'name' => pht('Mercurial'), 'name' => pht('Mercurial'),
'icon' => 'fa-code-fork', 'icon' => 'fa-code-fork',
'image' => 'repo/repo-hg.png',
'create.header' => pht('Create Mercurial Repository'), 'create.header' => pht('Create Mercurial Repository'),
'create.subheader' => pht('Create a new Mercurial repository.'), 'create.subheader' => pht('Create a new Mercurial repository.'),
), ),
self::REPOSITORY_TYPE_SVN => array( self::REPOSITORY_TYPE_SVN => array(
'name' => pht('Subversion'), 'name' => pht('Subversion'),
'icon' => 'fa-database', 'icon' => 'fa-database',
'image' => 'repo/repo-svn.png',
'create.header' => pht('Create Subversion Repository'), 'create.header' => pht('Create Subversion Repository'),
'create.subheader' => pht('Create a new Subversion repository.'), 'create.subheader' => pht('Create a new Subversion repository.'),
), ),

View file

@ -186,11 +186,6 @@ abstract class PhabricatorRepositoryCommitMessageParserWorker
$revision = $revision_query->executeOne(); $revision = $revision_query->executeOne();
if ($revision) { if ($revision) {
if (!$data->getCommitDetail('precommitRevisionStatus')) {
$data->setCommitDetail(
'precommitRevisionStatus',
$revision->getStatus());
}
$commit_drev = DiffusionCommitHasRevisionEdgeType::EDGECONST; $commit_drev = DiffusionCommitHasRevisionEdgeType::EDGECONST;
id(new PhabricatorEdgeEditor()) id(new PhabricatorEdgeEditor())
->addEdge($commit->getPHID(), $commit_drev, $revision->getPHID()) ->addEdge($commit->getPHID(), $commit_drev, $revision->getPHID())
@ -205,9 +200,11 @@ abstract class PhabricatorRepositoryCommitMessageParserWorker
$should_close = !$revision->isPublished() && $should_autoclose; $should_close = !$revision->isPublished() && $should_autoclose;
if ($should_close) { if ($should_close) {
$commit_close_xaction = id(new DifferentialTransaction()) $type_close = DifferentialRevisionCloseTransaction::TRANSACTIONTYPE;
->setTransactionType(DifferentialTransaction::TYPE_ACTION)
->setNewValue(DifferentialAction::ACTION_CLOSE) $commit_close_xaction = id(new DifferentialTransaction())
->setTransactionType($type_close)
->setNewValue(true)
->setMetadataValue('isCommitClose', true); ->setMetadataValue('isCommitClose', true);
$commit_close_xaction->setMetadataValue( $commit_close_xaction->setMetadataValue(

View file

@ -28,55 +28,46 @@ final class PhabricatorNamedQueryQuery
return $this; return $this;
} }
protected function loadPage() { public function newResultObject() {
$table = new PhabricatorNamedQuery(); return new PhabricatorNamedQuery();
$conn_r = $table->establishConnection('r');
$data = queryfx_all(
$conn_r,
'SELECT * FROM %T %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
return $table->loadAllFromArray($data);
} }
protected function buildWhereClause(AphrontDatabaseConnection $conn_r) { protected function loadPage() {
$where = array(); return $this->loadStandardPage($this->newResultObject());
}
if ($this->ids) { protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
if ($this->ids !== null) {
$where[] = qsprintf( $where[] = qsprintf(
$conn_r, $conn,
'id IN (%Ld)', 'id IN (%Ld)',
$this->ids); $this->ids);
} }
if ($this->engineClassNames) { if ($this->engineClassNames !== null) {
$where[] = qsprintf( $where[] = qsprintf(
$conn_r, $conn,
'engineClassName IN (%Ls)', 'engineClassName IN (%Ls)',
$this->engineClassNames); $this->engineClassNames);
} }
if ($this->userPHIDs) { if ($this->userPHIDs !== null) {
$where[] = qsprintf( $where[] = qsprintf(
$conn_r, $conn,
'userPHID IN (%Ls)', 'userPHID IN (%Ls)',
$this->userPHIDs); $this->userPHIDs);
} }
if ($this->queryKeys) { if ($this->queryKeys !== null) {
$where[] = qsprintf( $where[] = qsprintf(
$conn_r, $conn,
'queryKey IN (%Ls)', 'queryKey IN (%Ls)',
$this->queryKeys); $this->queryKeys);
} }
$where[] = $this->buildPagingClause($conn_r); return $where;
return $this->formatWhereClause($where);
} }
public function getQueryApplicationClass() { public function getQueryApplicationClass() {

View file

@ -121,18 +121,18 @@ final class PhabricatorSettingsMainController
} }
$header = id(new PHUIHeaderView()) $header = id(new PHUIHeaderView())
->setHeader($header_text) ->setHeader($header_text);
->setHeaderIcon('fa-pencil');
$title = $panel->getPanelName(); $title = $panel->getPanelName();
$view = id(new PHUITwoColumnView()) $view = id(new PHUITwoColumnView())
->setHeader($header) ->setHeader($header)
->setFooter($response); ->setFixed(true)
->setNavigation($nav)
->setMainColumn($response);
return $this->newPage() return $this->newPage()
->setTitle($title) ->setTitle($title)
->setNavigation($nav)
->setCrumbs($crumbs) ->setCrumbs($crumbs)
->appendChild($view); ->appendChild($view);

View file

@ -6,7 +6,7 @@ final class PhabricatorConpherencePreferencesSettingsPanel
const PANELKEY = 'conpherence'; const PANELKEY = 'conpherence';
public function getPanelName() { public function getPanelName() {
return pht('Conpherence Preferences'); return pht('Conpherence');
} }
public function getPanelGroupKey() { public function getPanelGroupKey() {

View file

@ -1141,10 +1141,8 @@ abstract class PhabricatorEditEngine
if ($this->getIsCreate()) { if ($this->getIsCreate()) {
$header_text = $this->getFormHeaderText($object); $header_text = $this->getFormHeaderText($object);
$header_icon = 'fa-plus-square';
} else { } else {
$header_text = $this->getObjectEditTitleText($object); $header_text = $this->getObjectEditTitleText($object);
$header_icon = 'fa-pencil';
} }
$show_preview = !$request->isAjax(); $show_preview = !$request->isAjax();
@ -1185,8 +1183,7 @@ abstract class PhabricatorEditEngine
$crumbs = $this->buildCrumbs($object, $final = true); $crumbs = $this->buildCrumbs($object, $final = true);
$header = id(new PHUIHeaderView()) $header = id(new PHUIHeaderView())
->setHeader($header_text) ->setHeader($header_text);
->setHeaderIcon($header_icon);
$crumbs->setBorder(true); $crumbs->setBorder(true);
if ($action_button) { if ($action_button) {
@ -1216,8 +1213,6 @@ abstract class PhabricatorEditEngine
$view->setHeader($header); $view->setHeader($header);
} }
$view->setFooter($content);
$page = $controller->newPage() $page = $controller->newPage()
->setTitle($header_text) ->setTitle($header_text)
->setCrumbs($crumbs) ->setCrumbs($crumbs)
@ -1225,7 +1220,11 @@ abstract class PhabricatorEditEngine
$navigation = $this->getNavigation(); $navigation = $this->getNavigation();
if ($navigation) { if ($navigation) {
$page->setNavigation($navigation); $view->setFixed(true);
$view->setNavigation($navigation);
$view->setMainColumn($content);
} else {
$view->setFooter($content);
} }
return $page; return $page;

View file

@ -140,7 +140,7 @@ Reproducibility
The most important part of your report content is instructions on how to The most important part of your report content is instructions on how to
reproduce the issue. What did you do? If you do it again, does it still break? reproduce the issue. What did you do? If you do it again, does it still break?
Does it depend on a specific browser? Can you reproduce the issue on a free Does it depend on a specific browser? Can you reproduce the issue on a test
instance on `admin.phabricator.com`? instance on `admin.phabricator.com`?
It is nearly impossible for us to resolve many issues if we can not reproduce It is nearly impossible for us to resolve many issues if we can not reproduce

View file

@ -92,8 +92,14 @@ JX.install('AphlictClientServer', {
var server = this._server.listen.apply(this._server, arguments); var server = this._server.listen.apply(this._server, arguments);
var wss = new WebSocket.Server({server: server}); var wss = new WebSocket.Server({server: server});
wss.on('connection', function(ws) { // This function checks for upgradeReq which is only available in
var path = url.parse(ws.upgradeReq.url).pathname; // ws2 by default, not ws3. See T12755 for more information.
wss.on('connection', function(ws, request) {
if ('upgradeReq' in ws) {
request = ws.upgradeReq;
}
var path = url.parse(request.url).pathname;
var instance = self._parseInstanceFromPath(path); var instance = self._parseInstanceFromPath(path);
var listener = self.getListenerList(instance).addListener(ws); var listener = self.getListenerList(instance).addListener(ws);

View file

@ -28,6 +28,9 @@ div.jx-typeahead-results a.jx-result {
color: {$darkgreytext}; color: {$darkgreytext};
display: block; display: block;
font-size: {$normalfontsize}; font-size: {$normalfontsize};
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
} }
div.jx-typeahead-results a.jx-result + a.jx-result { div.jx-typeahead-results a.jx-result + a.jx-result {
@ -68,7 +71,8 @@ div.jx-typeahead-results a.diffusion-locate-file {
} }
.diffusion-locate-file strong { .diffusion-locate-file strong {
color: {$blue}; color: {$fire};
text-decoration: underline;
} }
.diffusion-locate-file .phui-icon-view { .diffusion-locate-file .phui-icon-view {

View file

@ -186,6 +186,7 @@ a.handle-status-closed:hover {
.device .phabricator-standard-page-tabs { .device .phabricator-standard-page-tabs {
margin-bottom: 20px; margin-bottom: 20px;
padding: 0 12px;
} }
.device-phone .phabricator-standard-page-tabs { .device-phone .phabricator-standard-page-tabs {

View file

@ -12,6 +12,10 @@
display: block; display: block;
} }
.device-phone .diffusion-profile-header .phui-header-col1 {
display: none;
}
.diffusion-action-bar { .diffusion-action-bar {
margin-bottom: 16px; margin-bottom: 16px;
} }
@ -33,6 +37,22 @@
display: block; display: block;
} }
.device-phone .diffusion-action-bar .button .phui-button-text {
visibility: hidden;
width: 0;
margin-left: 8px;
}
.device-phone .full-mobile-buttons.diffusion-action-bar .phui-lr-container
.phui-left-view {
display: inline-block;
}
.device-phone .full-mobile-buttons.diffusion-action-bar .phui-lr-container
.phui-right-view {
display: inline-block;
}
.diffusion-profile-locate .phui-form-view { .diffusion-profile-locate .phui-form-view {
margin: 0; margin: 0;
padding: 0; padding: 0;
@ -60,6 +80,12 @@
padding: 0; padding: 0;
} }
.diffusion-view-browse-header {
display: block;
padding: 2px 0;
font-size: {$biggestfontsize};
}
/* - List Styles ------------------------------------------------------------*/ /* - List Styles ------------------------------------------------------------*/
.diffusion-history-list .phui-oi-link { .diffusion-history-list .phui-oi-link {
@ -106,6 +132,12 @@
margin-right: 4px; margin-right: 4px;
} }
.diffusion-header-branch-tag.phui-tag-view.phui-tag-type-outline
.phui-tag-core {
padding: 3px 12px 2px;
font-size: {$normalfontsize};
}
/* - Browse Styles ----------------------------------------------------------*/ /* - Browse Styles ----------------------------------------------------------*/
.diffusion-browse-table .commit-detail { .diffusion-browse-table .commit-detail {
@ -116,6 +148,58 @@
color: {$darkbluetext}; color: {$darkbluetext};
} }
.diffusion-search-result-header.phui-header-shell {
border: none;
padding-bottom: 24px;
}
/* - Search Input ------------------------------------------------------------*/
.diffusion-search-form-view {
width: 240px;
}
.diffusion-search-form-view .diffusion-search-input {
width: 240px;
border-radius: 20px;
padding-left: 12px;
}
.device-phone .diffusion-browse-header .diffusion-search-form-view,
.device-phone .diffusion-profile-header .diffusion-search-form-view {
display: none;
}
.diffusion-mobile-search-form {
display: none;
}
.device-phone .diffusion-mobile-search-form {
display: block;
}
.device-phone .diffusion-search-form-view {
width: 100%;
margin-bottom: 20px;
}
.device-phone .diffusion-search-form-view .diffusion-search-input {
width: 100%;
}
/* - Create Repository -------------------------------------------------------*/
.diffusion-create-repo {
margin-top: 32px;
margin-bottom: 20px;
}
.device .diffusion-create-repo {
margin-top: 0;
margin-bottom: 0;
}
/* - Phone Style ------------------------------------------------------------*/ /* - Phone Style ------------------------------------------------------------*/
.device-phone.diffusion-history-view .phui-two-column-view .device-phone.diffusion-history-view .phui-two-column-view

View file

@ -12,9 +12,10 @@
} }
.phui-source-fragment strong { .phui-source-fragment strong {
background-color: {$lightyellow}; background-color: {$gentle.highlight};
font-weight: normal; font-weight: 600;
color: {$blacktext}; color: {$blacktext};
letter-spacing: 0.02em;
} }
.phui-fulltext-tokens { .phui-fulltext-tokens {

View file

@ -21,6 +21,14 @@
text-align: right; text-align: right;
} }
.phui-left-view .button {
margin-right: 8px;
}
.phui-right-view .button {
margin-left: 8px;
}
.phui-lr-view-top .phui-left-view, .phui-lr-view-top .phui-left-view,
.phui-lr-view-top .phui-right-view { .phui-lr-view-top .phui-right-view {
vertical-align: top; vertical-align: top;

View file

@ -185,6 +185,15 @@
padding: 0 12px; padding: 0 12px;
} }
.device-phone .phui-two-column-tabs .phui-list-view.phui-list-tabbar {
text-align: center;
}
.device-phone .phui-two-column-tabs .phui-list-view.phui-list-tabbar > li {
float: none;
display: inline-block;
}
/* Info View */ /* Info View */
.phui-two-column-view .phui-info-view { .phui-two-column-view .phui-info-view {
@ -235,3 +244,54 @@
.phui-document-view { .phui-document-view {
margin: 0 0 20px 0; margin: 0 0 20px 0;
} }
/*- Fixed Styles with Navigation -------------------------------------------- */
.phui-two-column-fixed.phui-two-column-view .phui-two-column-header {
background: transparent;
border: none;
margin-bottom: 0;
}
.phui-two-column-fixed.phui-two-column-view .phui-side-column
.phui-box-border {
background: transparent;
border: none;
padding: 0;
width: 180px;
}
.device-desktop
.phui-two-column-fixed.phui-two-column-view.phui-side-column-left
.phui-side-column {
width: 200px;
}
.device-desktop
.phui-two-column-fixed.phui-two-column-view.phui-side-column-left
.phui-main-column {
width: calc(100% - 200px)
}
.phui-two-column-fixed.phui-two-column-view .phui-basic-nav
.phabricator-side-menu {
background: transparent;
}
.phui-two-column-fixed.phui-two-column-view
.phui-basic-nav .phabricator-side-menu .phui-list-item-selected {
border-radius: 3px;
background-color: #f5f9ff;
border: 1px solid {$sky};
padding-left: 3px;
}
.phui-two-column-fixed.phui-two-column-view .phui-basic-nav
.phabricator-side-menu .phui-list-item-href {
border-radius: 3px;
}
.phui-two-column-fixed.phui-two-column-view .phui-header-action-links
.phui-mobile-menu {
display: block;
}

View file

@ -14,7 +14,7 @@ only screen and (-webkit-min-device-pixel-ratio: 1.5),
only screen and (min-resolution: 1.5dppx) { only screen and (min-resolution: 1.5dppx) {
.sprite-login { .sprite-login {
background-image: url(/rsrc/image/sprite-login-X2.png); background-image: url(/rsrc/image/sprite-login-X2.png);
background-size: 145px 174px; background-size: 145px 145px;
} }
} }
@ -35,28 +35,24 @@ only screen and (min-resolution: 1.5dppx) {
background-position: -87px 0px; background-position: -87px 0px;
} }
.login-Dropbox { .login-Facebook {
background-position: -116px 0px; background-position: -116px 0px;
} }
.login-Facebook { .login-Generic {
background-position: 0px -29px; background-position: 0px -29px;
} }
.login-Generic { .login-Github {
background-position: -29px -29px; background-position: -29px -29px;
} }
.login-Github { .login-Google {
background-position: -58px -29px; background-position: -58px -29px;
} }
.login-Google {
background-position: -87px -29px;
}
.login-HTTP { .login-HTTP {
background-position: -116px -29px; background-position: -87px -29px;
} }
.login-Jira { .login-Jira {
@ -67,54 +63,42 @@ only screen and (min-resolution: 1.5dppx) {
background-position: -29px -58px; background-position: -29px -58px;
} }
.login-Linkedin { .login-MediaWiki {
background-position: -58px -58px; background-position: -58px -58px;
} }
.login-MediaWiki { .login-PayPal {
background-position: -87px -58px; background-position: -87px -58px;
} }
.login-Openid { .login-Phabricator {
background-position: -116px -58px;
}
.login-PayPal {
background-position: 0px -87px; background-position: 0px -87px;
} }
.login-Phabricator {
background-position: -58px -87px;
}
.login-Slack { .login-Slack {
background-position: -87px -87px; background-position: -29px -87px;
} }
.login-Stripe { .login-Stripe {
background-position: -116px -87px; background-position: -58px -87px;
} }
.login-TestPayment { .login-TestPayment {
background-position: 0px -116px; background-position: -87px -87px;
} }
.login-TwitchTV { .login-TwitchTV {
background-position: -29px -116px; background-position: 0px -116px;
} }
.login-Twitter { .login-Twitter {
background-position: -58px -116px; background-position: -29px -116px;
} }
.login-WePay { .login-WePay {
background-position: -87px -116px; background-position: -58px -116px;
} }
.login-WordPressCOM { .login-WordPressCOM {
background-position: -116px -116px; background-position: -87px -116px;
}
.login-Yahoo {
background-position: 0px -145px;
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 12 KiB