@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Add Herald support for blocking ref changes

Summary: Ref T4195. Allows users to write Herald rules which block ref changes. For example, you can write a rule like `alincoln can not create branches`, or `no one can push to the branch "frozen"`.

Test Plan:
This covers a lot of ground. I created and pushed a bunch of rules, then looked at transcripts, in general. Here are some bits in detail:

Here's a hook-based reject message:

>>> orbital ~/repos/POEMS $ git push
Counting objects: 5, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 274 bytes, done.
Total 3 (delta 2), reused 0 (delta 0)
remote: +---------------------------------------------------------------+
remote: | * * * PUSH REJECTED BY EVIL DRAGON BUREAUCRATS * * * |
remote: +---------------------------------------------------------------+
remote: \
remote: \ ^ /^
remote: \ / \ // \
remote: \ |\___/| / \// .\
remote: \ /V V \__ / // | \ \ *----*
remote: / / \/_/ // | \ \ \ |
remote: @___@` \/_ // | \ \ \/\ \
remote: 0/0/| \/_ // | \ \ \ \
remote: 0/0/0/0/| \/// | \ \ | |
remote: 0/0/0/0/0/_|_ / ( // | \ _\ | /
remote: 0/0/0/0/0/0/`/,_ _ _/ ) ; -. | _ _\.-~ / /
remote: ,-} _ *-.|.-~-. .~ ~
remote: \ \__/ `/\ / ~-. _ .-~ /
remote: \____(Oo) *. } { /
remote: ( (--) .----~-.\ \-` .~
remote: //__\\ \ DENIED! ///.----..< \ _ -~
remote: // \\ ///-._ _ _ _ _ _ _{^ - - - - ~
remote:
remote:
remote: This commit was rejected by Herald pre-commit rule H24.
remote: Rule: No Branches Called Blarp
remote: Reason: "blarp" is a bad branch name
remote:
To ssh://dweller@localhost/diffusion/POEMS/
! [remote rejected] blarp -> blarp (pre-receive hook declined)
error: failed to push some refs to 'ssh://dweller@localhost/diffusion/POEMS/'

Here's a transcript, showing that all the field values populate sensibly:

{F90453}

Here's a rule:

{F90454}

Reviewers: btrahan

Reviewed By: btrahan

CC: aran

Maniphest Tasks: T4195

Differential Revision: https://secure.phabricator.com/D7782

+341 -17
+1 -1
src/__celerity_resource_map__.php
··· 1211 1211 ), 1212 1212 'herald-rule-editor' => 1213 1213 array( 1214 - 'uri' => '/res/928275b4/rsrc/js/application/herald/HeraldRuleEditor.js', 1214 + 'uri' => '/res/92c05b75/rsrc/js/application/herald/HeraldRuleEditor.js', 1215 1215 'type' => 'js', 1216 1216 'requires' => 1217 1217 array(
+2
src/__phutil_library_map__.php
··· 756 756 'HeraldObjectTranscript' => 'applications/herald/storage/transcript/HeraldObjectTranscript.php', 757 757 'HeraldPHIDTypeRule' => 'applications/herald/phid/HeraldPHIDTypeRule.php', 758 758 'HeraldPholioMockAdapter' => 'applications/herald/adapter/HeraldPholioMockAdapter.php', 759 + 'HeraldPreCommitRefAdapter' => 'applications/diffusion/herald/HeraldPreCommitRefAdapter.php', 759 760 'HeraldRecursiveConditionsException' => 'applications/herald/engine/exception/HeraldRecursiveConditionsException.php', 760 761 'HeraldRepetitionPolicyConfig' => 'applications/herald/config/HeraldRepetitionPolicyConfig.php', 761 762 'HeraldRule' => 'applications/herald/storage/HeraldRule.php', ··· 3177 3178 'HeraldNewController' => 'HeraldController', 3178 3179 'HeraldPHIDTypeRule' => 'PhabricatorPHIDType', 3179 3180 'HeraldPholioMockAdapter' => 'HeraldAdapter', 3181 + 'HeraldPreCommitRefAdapter' => 'HeraldAdapter', 3180 3182 'HeraldRecursiveConditionsException' => 'Exception', 3181 3183 'HeraldRule' => 3182 3184 array(
+88 -1
src/applications/diffusion/engine/DiffusionCommitHookEngine.php
··· 26 26 private $transactionKey; 27 27 private $mercurialHook; 28 28 29 + private $heraldViewerProjects; 30 + 29 31 30 32 /* -( Config )------------------------------------------------------------- */ 31 33 ··· 130 132 throw $ex; 131 133 } 132 134 133 - // TODO: Fire ref herald rules. 135 + $this->applyHeraldRefRules($ref_updates); 134 136 135 137 $content_updates = $this->findContentUpdates($ref_updates); 136 138 $all_updates = array_merge($all_updates, $content_updates); ··· 221 223 } 222 224 223 225 226 + /* -( Herald )------------------------------------------------------------- */ 227 + 228 + 229 + private function applyHeraldRefRules(array $ref_updates) { 230 + if (!$ref_updates) { 231 + return; 232 + } 233 + 234 + $engine = new HeraldEngine(); 235 + $rules = null; 236 + $blocking_effect = null; 237 + foreach ($ref_updates as $ref_update) { 238 + $adapter = id(new HeraldPreCommitRefAdapter()) 239 + ->setPushLog($ref_update) 240 + ->setHookEngine($this); 241 + 242 + if ($rules === null) { 243 + $rules = $engine->loadRulesForAdapter($adapter); 244 + } 245 + 246 + $effects = $engine->applyRules($rules, $adapter); 247 + $engine->applyEffects($effects, $adapter, $rules); 248 + $xscript = $engine->getTranscript(); 249 + 250 + if ($blocking_effect === null) { 251 + foreach ($effects as $effect) { 252 + if ($effect->getAction() == HeraldAdapter::ACTION_BLOCK) { 253 + $blocking_effect = $effect; 254 + break; 255 + } 256 + } 257 + } 258 + } 259 + 260 + if ($blocking_effect) { 261 + foreach ($ref_updates as $ref_update) { 262 + $ref_update->setRejectCode(PhabricatorRepositoryPushLog::REJECT_HERALD); 263 + $ref_update->setRejectDetails($blocking_effect->getRulePHID()); 264 + } 265 + 266 + $message = $blocking_effect->getTarget(); 267 + if (!strlen($message)) { 268 + $message = pht('(None.)'); 269 + } 270 + 271 + $rules = mpull($rules, null, 'getID'); 272 + $rule = idx($rules, $effect->getRuleID()); 273 + if ($rule && strlen($rule->getName())) { 274 + $rule_name = $rule->getName(); 275 + } else { 276 + $rule_name = pht('Unnamed Herald Rule'); 277 + } 278 + 279 + throw new DiffusionCommitHookRejectException( 280 + pht( 281 + "This commit was rejected by Herald pre-commit rule %s.\n". 282 + "Rule: %s\n". 283 + "Reason: %s", 284 + 'H'.$blocking_effect->getRuleID(), 285 + $rule_name, 286 + $message)); 287 + } 288 + } 289 + 290 + public function loadViewerProjectPHIDsForHerald() { 291 + // This just caches the viewer's projects so we don't need to load them 292 + // over and over again when applying Herald rules. 293 + if ($this->heraldViewerProjects === null) { 294 + $this->heraldViewerProjects = id(new PhabricatorProjectQuery()) 295 + ->setViewer($this->getViewer()) 296 + ->withMemberPHIDs(array($this->getViewer()->getPHID())) 297 + ->execute(); 298 + } 299 + 300 + return mpull($this->heraldViewerProjects, 'getPHID'); 301 + } 302 + 303 + 224 304 /* -( Git )---------------------------------------------------------------- */ 225 305 226 306 ··· 246 326 247 327 if (preg_match('(^refs/heads/)', $ref_raw)) { 248 328 $ref_type = PhabricatorRepositoryPushLog::REFTYPE_BRANCH; 329 + $ref_raw = substr($ref_raw, strlen('refs/heads/')); 249 330 } else if (preg_match('(^refs/tags/)', $ref_raw)) { 250 331 $ref_type = PhabricatorRepositoryPushLog::REFTYPE_TAG; 332 + $ref_raw = substr($ref_raw, strlen('refs/tags/')); 251 333 } else { 252 334 throw new Exception( 253 335 pht( ··· 764 846 // code. This indicates a broken hook, and covers the case where we 765 847 // encounter some unexpected exception and consequently reject the changes. 766 848 849 + // NOTE: We generate PHIDs up front so the Herald transcripts can pick them 850 + // up. 851 + $phid = id(new PhabricatorRepositoryPushLog())->generatePHID(); 852 + 767 853 return PhabricatorRepositoryPushLog::initializeNewLog($this->getViewer()) 854 + ->setPHID($phid) 768 855 ->attachRepository($this->getRepository()) 769 856 ->setRepositoryPHID($this->getRepository()->getPHID()) 770 857 ->setEpoch(time())
+163
src/applications/diffusion/herald/HeraldPreCommitRefAdapter.php
··· 1 + <?php 2 + 3 + final class HeraldPreCommitRefAdapter extends HeraldAdapter { 4 + 5 + private $log; 6 + private $hookEngine; 7 + 8 + const FIELD_REF_TYPE = 'ref-type'; 9 + const FIELD_REF_NAME = 'ref-name'; 10 + const FIELD_REF_CHANGE = 'ref-change'; 11 + 12 + const VALUE_REF_TYPE = 'value-ref-type'; 13 + const VALUE_REF_CHANGE = 'value-ref-change'; 14 + 15 + public function setPushLog(PhabricatorRepositoryPushLog $log) { 16 + $this->log = $log; 17 + return $this; 18 + } 19 + 20 + public function setHookEngine(DiffusionCommitHookEngine $engine) { 21 + $this->hookEngine = $engine; 22 + return $this; 23 + } 24 + 25 + public function getAdapterApplicationClass() { 26 + return 'PhabricatorApplicationDiffusion'; 27 + } 28 + 29 + public function getObject() { 30 + return $this->log; 31 + } 32 + 33 + public function getAdapterContentName() { 34 + return pht('Commit Hook: Branches/Tags/Bookmarks'); 35 + } 36 + 37 + public function getFieldNameMap() { 38 + return array( 39 + self::FIELD_REF_TYPE => pht('Ref type'), 40 + self::FIELD_REF_NAME => pht('Ref name'), 41 + self::FIELD_REF_CHANGE => pht('Ref change type'), 42 + ) + parent::getFieldNameMap(); 43 + } 44 + 45 + public function getFields() { 46 + return array_merge( 47 + array( 48 + self::FIELD_REF_TYPE, 49 + self::FIELD_REF_NAME, 50 + self::FIELD_REF_CHANGE, 51 + self::FIELD_REPOSITORY, 52 + self::FIELD_PUSHER, 53 + self::FIELD_PUSHER_PROJECTS, 54 + self::FIELD_RULE, 55 + ), 56 + parent::getFields()); 57 + } 58 + 59 + public function getConditionsForField($field) { 60 + switch ($field) { 61 + case self::FIELD_REF_NAME: 62 + return array( 63 + self::CONDITION_IS, 64 + self::CONDITION_IS_NOT, 65 + self::CONDITION_CONTAINS, 66 + self::CONDITION_REGEXP, 67 + ); 68 + case self::FIELD_REF_TYPE: 69 + return array( 70 + self::CONDITION_IS, 71 + self::CONDITION_IS_NOT, 72 + ); 73 + case self::FIELD_REF_CHANGE: 74 + return array( 75 + self::CONDITION_HAS_BIT, 76 + self::CONDITION_NOT_BIT, 77 + ); 78 + } 79 + return parent::getConditionsForField($field); 80 + } 81 + 82 + public function getActions($rule_type) { 83 + switch ($rule_type) { 84 + case HeraldRuleTypeConfig::RULE_TYPE_GLOBAL: 85 + return array( 86 + self::ACTION_BLOCK, 87 + self::ACTION_NOTHING 88 + ); 89 + case HeraldRuleTypeConfig::RULE_TYPE_PERSONAL: 90 + return array( 91 + self::ACTION_NOTHING, 92 + ); 93 + } 94 + } 95 + 96 + public function getValueTypeForFieldAndCondition($field, $condition) { 97 + switch ($field) { 98 + case self::FIELD_REF_TYPE: 99 + return self::VALUE_REF_TYPE; 100 + case self::FIELD_REF_CHANGE: 101 + return self::VALUE_REF_CHANGE; 102 + } 103 + 104 + return parent::getValueTypeForFieldAndCondition($field, $condition); 105 + } 106 + 107 + public function getPHID() { 108 + return $this->getObject()->getPHID(); 109 + } 110 + 111 + public function getHeraldName() { 112 + return pht('Push Log'); 113 + } 114 + 115 + public function getHeraldField($field) { 116 + $log = $this->getObject(); 117 + switch ($field) { 118 + case self::FIELD_REF_TYPE: 119 + return $log->getRefType(); 120 + case self::FIELD_REF_NAME: 121 + return $log->getRefName(); 122 + case self::FIELD_REF_CHANGE: 123 + return $log->getChangeFlags(); 124 + case self::FIELD_REPOSITORY: 125 + return $this->hookEngine->getRepository()->getPHID(); 126 + case self::FIELD_PUSHER: 127 + return $this->hookEngine->getViewer()->getPHID(); 128 + case self::FIELD_PUSHER_PROJECTS: 129 + return $this->hookEngine->loadViewerProjectPHIDsForHerald(); 130 + } 131 + 132 + return parent::getHeraldField($field); 133 + } 134 + 135 + 136 + public function applyHeraldEffects(array $effects) { 137 + assert_instances_of($effects, 'HeraldEffect'); 138 + 139 + $result = array(); 140 + foreach ($effects as $effect) { 141 + $action = $effect->getAction(); 142 + switch ($action) { 143 + case self::ACTION_NOTHING: 144 + $result[] = new HeraldApplyTranscript( 145 + $effect, 146 + true, 147 + pht('Did nothing.')); 148 + break; 149 + case self::ACTION_BLOCK: 150 + $result[] = new HeraldApplyTranscript( 151 + $effect, 152 + true, 153 + pht('Blocked push.')); 154 + break; 155 + default: 156 + throw new Exception(pht('No rules to handle action "%s"!', $action)); 157 + } 158 + } 159 + 160 + return $result; 161 + } 162 + 163 + }
+22
src/applications/herald/adapter/HeraldAdapter.php
··· 25 25 const FIELD_ALWAYS = 'always'; 26 26 const FIELD_AUTHOR_PROJECTS = 'authorprojects'; 27 27 const FIELD_PROJECTS = 'projects'; 28 + const FIELD_PUSHER = 'pusher'; 29 + const FIELD_PUSHER_PROJECTS = 'pusher-projects'; 28 30 29 31 const CONDITION_CONTAINS = 'contains'; 30 32 const CONDITION_NOT_CONTAINS = '!contains'; ··· 44 46 const CONDITION_NOT_EXISTS = '!exists'; 45 47 const CONDITION_UNCONDITIONALLY = 'unconditionally'; 46 48 const CONDITION_REGEXP_PAIR = 'regexp-pair'; 49 + const CONDITION_HAS_BIT = 'bit'; 50 + const CONDITION_NOT_BIT = '!bit'; 47 51 48 52 const ACTION_ADD_CC = 'addcc'; 49 53 const ACTION_REMOVE_CC = 'remcc'; ··· 56 60 const ACTION_ADD_REVIEWERS = 'addreviewers'; 57 61 const ACTION_ADD_BLOCKING_REVIEWERS = 'addblockingreviewers'; 58 62 const ACTION_APPLY_BUILD_PLANS = 'applybuildplans'; 63 + const ACTION_BLOCK = 'block'; 59 64 60 65 const VALUE_TEXT = 'text'; 61 66 const VALUE_NONE = 'none'; ··· 156 161 self::FIELD_ALWAYS => pht('Always'), 157 162 self::FIELD_AUTHOR_PROJECTS => pht("Author's projects"), 158 163 self::FIELD_PROJECTS => pht("Projects"), 164 + self::FIELD_PUSHER => pht('Pusher'), 165 + self::FIELD_PUSHER_PROJECTS => pht("Pusher's projects"), 159 166 ); 160 167 } 161 168 ··· 183 190 self::CONDITION_NOT_EXISTS => pht('does not exist'), 184 191 self::CONDITION_UNCONDITIONALLY => '', // don't show anything! 185 192 self::CONDITION_REGEXP_PAIR => pht('matches regexp pair'), 193 + self::CONDITION_HAS_BIT => pht('has bit'), 194 + self::CONDITION_NOT_BIT => pht('lacks bit'), 186 195 ); 187 196 } 188 197 ··· 200 209 case self::FIELD_AUTHOR: 201 210 case self::FIELD_COMMITTER: 202 211 case self::FIELD_REVIEWER: 212 + case self::FIELD_PUSHER: 203 213 return array( 204 214 self::CONDITION_IS_ANY, 205 215 self::CONDITION_IS_NOT_ANY, ··· 218 228 case self::FIELD_PROJECTS: 219 229 case self::FIELD_AFFECTED_PACKAGE: 220 230 case self::FIELD_AFFECTED_PACKAGE_OWNER: 231 + case self::FIELD_PUSHER_PROJECTS: 221 232 return array( 222 233 self::CONDITION_INCLUDE_ALL, 223 234 self::CONDITION_INCLUDE_ANY, ··· 392 403 $result = !$result; 393 404 } 394 405 return $result; 406 + case self::CONDITION_HAS_BIT: 407 + return (($condition_value & $field_value) === $condition_value); 408 + case self::CONDITION_NOT_BIT: 409 + return (($condition_value & $field_value) !== $condition_value); 395 410 default: 396 411 throw new HeraldInvalidConditionException( 397 412 "Unknown condition '{$condition_type}'."); ··· 469 484 case self::CONDITION_EXISTS: 470 485 case self::CONDITION_NOT_EXISTS: 471 486 case self::CONDITION_UNCONDITIONALLY: 487 + case self::CONDITION_HAS_BIT: 488 + case self::CONDITION_NOT_BIT: 472 489 // No explicit validation for these types, although there probably 473 490 // should be in some cases. 474 491 break; ··· 500 517 self::ACTION_ADD_REVIEWERS => pht('Add reviewers'), 501 518 self::ACTION_ADD_BLOCKING_REVIEWERS => pht('Add blocking reviewers'), 502 519 self::ACTION_APPLY_BUILD_PLANS => pht('Apply build plans'), 520 + self::ACTION_BLOCK => pht('Block change with message'), 503 521 ); 504 522 case HeraldRuleTypeConfig::RULE_TYPE_PERSONAL: 505 523 return array( ··· 551 569 $target = PhabricatorFlagColor::COLOR_BLUE; 552 570 } 553 571 break; 572 + case self::ACTION_BLOCK: 554 573 case self::ACTION_NOTHING: 555 574 break; 556 575 default: ··· 607 626 case self::FIELD_AFFECTED_PACKAGE: 608 627 return self::VALUE_OWNERS_PACKAGE; 609 628 case self::FIELD_AUTHOR_PROJECTS: 629 + case self::FIELD_PUSHER_PROJECTS: 610 630 case self::FIELD_PROJECTS: 611 631 return self::VALUE_PROJECT; 612 632 case self::FIELD_REVIEWERS: ··· 670 690 return self::VALUE_USER_OR_PROJECT; 671 691 case self::ACTION_APPLY_BUILD_PLANS: 672 692 return self::VALUE_BUILD_PLAN; 693 + case self::ACTION_BLOCK: 694 + return self::VALUE_TEXT; 673 695 default: 674 696 throw new Exception("Unknown or invalid action '{$action}'."); 675 697 }
+35 -4
src/applications/herald/controller/HeraldRuleController.php
··· 349 349 350 350 switch ($action->getAction()) { 351 351 case HeraldAdapter::ACTION_FLAG: 352 + case HeraldAdapter::ACTION_BLOCK: 352 353 $current_value = $action->getTarget(); 353 354 break; 354 355 default: ··· 414 415 'root' => 'herald-rule-edit-form', 415 416 'conditions' => (object)$serial_conditions, 416 417 'actions' => (object)$serial_actions, 418 + 'select' => array( 419 + HeraldAdapter::VALUE_CONTENT_SOURCE => array( 420 + 'options' => PhabricatorContentSource::getSourceNameMap(), 421 + 'default' => PhabricatorContentSource::SOURCE_WEB, 422 + ), 423 + HeraldAdapter::VALUE_FLAG_COLOR => array( 424 + 'options' => PhabricatorFlagColor::getColorNameMap(), 425 + 'default' => PhabricatorFlagColor::COLOR_BLUE, 426 + ), 427 + HeraldPreCommitRefAdapter::VALUE_REF_TYPE => array( 428 + 'options' => array( 429 + PhabricatorRepositoryPushLog::REFTYPE_BRANCH 430 + => pht('branch (git/hg)'), 431 + PhabricatorRepositoryPushLog::REFTYPE_TAG 432 + => pht('tag (git)'), 433 + PhabricatorRepositoryPushLog::REFTYPE_BOOKMARK 434 + => pht('bookmark (hg)'), 435 + ), 436 + 'default' => PhabricatorRepositoryPushLog::REFTYPE_BRANCH, 437 + ), 438 + HeraldPreCommitRefAdapter::VALUE_REF_CHANGE => array( 439 + 'options' => array( 440 + PhabricatorRepositoryPushLog::CHANGEFLAG_ADD => 441 + pht('change creates ref'), 442 + PhabricatorRepositoryPushLog::CHANGEFLAG_DELETE => 443 + pht('change deletes ref'), 444 + PhabricatorRepositoryPushLog::CHANGEFLAG_REWRITE => 445 + pht('change rewrites ref'), 446 + PhabricatorRepositoryPushLog::CHANGEFLAG_DANGEROUS => 447 + pht('dangerous change'), 448 + ), 449 + 'default' => PhabricatorRepositoryPushLog::CHANGEFLAG_ADD, 450 + ), 451 + ), 417 452 'template' => $this->buildTokenizerTemplates() + array( 418 453 'rules' => $all_rules, 419 - 'colors' => PhabricatorFlagColor::getColorNameMap(), 420 - 'defaultColor' => PhabricatorFlagColor::COLOR_BLUE, 421 - 'contentSources' => PhabricatorContentSource::getSourceNameMap(), 422 - 'defaultSource' => PhabricatorContentSource::SOURCE_WEB 423 454 ), 424 455 'author' => array($rule->getAuthorPHID() => 425 456 $handles[$rule->getAuthorPHID()]->getName()),
+4
src/applications/herald/controller/HeraldTranscriptController.php
··· 293 293 case HeraldAdapter::ACTION_FLAG: 294 294 $target = PhabricatorFlagColor::getColorName($target); 295 295 break; 296 + case HeraldAdapter::ACTION_BLOCK: 297 + // Target is a text string. 298 + $target = $target; 299 + break; 296 300 default: 297 301 if ($target) { 298 302 foreach ($target as $k => $phid) {
+6 -2
src/applications/herald/engine/HeraldEngine.php
··· 24 24 return idx($this->rules, $id); 25 25 } 26 26 27 - public static function loadAndApplyRules(HeraldAdapter $adapter) { 28 - $rules = id(new HeraldRuleQuery()) 27 + public function loadRulesForAdapter(HeraldAdapter $adapter) { 28 + return id(new HeraldRuleQuery()) 29 29 ->setViewer(PhabricatorUser::getOmnipotentUser()) 30 30 ->withDisabled(false) 31 31 ->withContentTypes(array($adapter->getAdapterContentType())) ··· 33 33 ->needAppliedToPHIDs(array($adapter->getPHID())) 34 34 ->needValidateAuthors(true) 35 35 ->execute(); 36 + } 36 37 38 + public static function loadAndApplyRules(HeraldAdapter $adapter) { 37 39 $engine = new HeraldEngine(); 40 + 41 + $rules = $engine->loadRulesForAdapter($adapter); 38 42 $effects = $engine->applyRules($rules, $adapter); 39 43 $engine->applyEffects($effects, $adapter, $rules); 40 44
+3 -2
src/applications/herald/storage/HeraldRule.php
··· 16 16 protected $ruleType; 17 17 protected $isDisabled = 0; 18 18 19 - protected $configVersion = 15; 19 + protected $configVersion = 16; 20 20 21 - private $ruleApplied = self::ATTACHABLE; // phids for which this rule has been applied 21 + // phids for which this rule has been applied 22 + private $ruleApplied = self::ATTACHABLE; 22 23 private $validAuthor = self::ATTACHABLE; 23 24 private $author = self::ATTACHABLE; 24 25 private $conditions;
+13
src/applications/repository/query/PhabricatorRepositoryPushLogQuery.php
··· 4 4 extends PhabricatorCursorPagedPolicyAwareQuery { 5 5 6 6 private $ids; 7 + private $phids; 7 8 private $repositoryPHIDs; 8 9 private $pusherPHIDs; 9 10 private $refTypes; ··· 11 12 12 13 public function withIDs(array $ids) { 13 14 $this->ids = $ids; 15 + return $this; 16 + } 17 + 18 + public function withPHIDs(array $phids) { 19 + $this->phids = $phids; 14 20 return $this; 15 21 } 16 22 ··· 82 88 $conn_r, 83 89 'id IN (%Ld)', 84 90 $this->ids); 91 + } 92 + 93 + if ($this->phids) { 94 + $where[] = qsprintf( 95 + $conn_r, 96 + 'phid IN (%Ls)', 97 + $this->phids); 85 98 } 86 99 87 100 if ($this->repositoryPHIDs) {
+4 -7
webroot/rsrc/js/application/herald/HeraldRuleEditor.js
··· 233 233 set_fn = JX.bag; 234 234 break; 235 235 case 'contentsource': 236 - input = this._renderSelect(this._config.template.contentSources); 237 - get_fn = function() { return input.value; }; 238 - set_fn = function(v) { input.value = v; }; 239 - set_fn(this._config.template.defaultSource); 240 - break; 241 236 case 'flagcolor': 242 - input = this._renderSelect(this._config.template.colors); 237 + case 'value-ref-type': 238 + case 'value-ref-change': 239 + input = this._renderSelect(this._config.select[type].options); 243 240 get_fn = function() { return input.value; }; 244 241 set_fn = function(v) { input.value = v; }; 245 - set_fn(this._config.template.defaultColor); 242 + set_fn(this._config.select[type]['default']); 246 243 break; 247 244 default: 248 245 input = JX.$N('input', {type: 'text'});