@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.

Allow Herald pre-commit rules to act on repository projects

Summary:
Fixes T4264. Adds:

- New "Repository's projects" field to Herald pre-commit rules, so you can write global rules which act based on projects.
- Allows pre-ref/pre-content rules to bind to projects, and fire for all repositories in that project, so users with limited power can write rules which apply to many repositories.
- The pre-ref and pre-content classes were starting to share a fair amount of code, so I made them both extend an abstract base class.

Test Plan: Wrote new pre-ref and pre-content rules bound to projects, then pushed commits into repositories in those projects and not in those projects. The "repository projects" field populated, and the rules fired for repositories in the relevant projects.

Reviewers: btrahan

Reviewed By: btrahan

CC: aran

Maniphest Tasks: T4264

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

+158 -239
+1
scripts/repository/commit_hook.php
··· 13 13 $repository = id(new PhabricatorRepositoryQuery()) 14 14 ->setViewer(PhabricatorUser::getOmnipotentUser()) 15 15 ->withCallsigns(array($argv[1])) 16 + ->needProjectPHIDs(true) 16 17 ->executeOne(); 17 18 18 19 if (!$repository) {
+4 -2
src/__phutil_library_map__.php
··· 778 778 'HeraldObjectTranscript' => 'applications/herald/storage/transcript/HeraldObjectTranscript.php', 779 779 'HeraldPHIDTypeRule' => 'applications/herald/phid/HeraldPHIDTypeRule.php', 780 780 'HeraldPholioMockAdapter' => 'applications/herald/adapter/HeraldPholioMockAdapter.php', 781 + 'HeraldPreCommitAdapter' => 'applications/diffusion/herald/HeraldPreCommitAdapter.php', 781 782 'HeraldPreCommitContentAdapter' => 'applications/diffusion/herald/HeraldPreCommitContentAdapter.php', 782 783 'HeraldPreCommitRefAdapter' => 'applications/diffusion/herald/HeraldPreCommitRefAdapter.php', 783 784 'HeraldRecursiveConditionsException' => 'applications/herald/engine/exception/HeraldRecursiveConditionsException.php', ··· 3251 3252 'HeraldNewController' => 'HeraldController', 3252 3253 'HeraldPHIDTypeRule' => 'PhabricatorPHIDType', 3253 3254 'HeraldPholioMockAdapter' => 'HeraldAdapter', 3254 - 'HeraldPreCommitContentAdapter' => 'HeraldAdapter', 3255 - 'HeraldPreCommitRefAdapter' => 'HeraldAdapter', 3255 + 'HeraldPreCommitAdapter' => 'HeraldAdapter', 3256 + 'HeraldPreCommitContentAdapter' => 'HeraldPreCommitAdapter', 3257 + 'HeraldPreCommitRefAdapter' => 'HeraldPreCommitAdapter', 3256 3258 'HeraldRecursiveConditionsException' => 'Exception', 3257 3259 'HeraldRemarkupRule' => 'PhabricatorRemarkupRuleObject', 3258 3260 'HeraldRule' =>
+113
src/applications/diffusion/herald/HeraldPreCommitAdapter.php
··· 1 + <?php 2 + 3 + abstract class HeraldPreCommitAdapter extends HeraldAdapter { 4 + 5 + private $log; 6 + private $hookEngine; 7 + 8 + public function setPushLog(PhabricatorRepositoryPushLog $log) { 9 + $this->log = $log; 10 + return $this; 11 + } 12 + 13 + public function setHookEngine(DiffusionCommitHookEngine $engine) { 14 + $this->hookEngine = $engine; 15 + return $this; 16 + } 17 + 18 + public function getHookEngine() { 19 + return $this->hookEngine; 20 + } 21 + 22 + public function getAdapterApplicationClass() { 23 + return 'PhabricatorApplicationDiffusion'; 24 + } 25 + 26 + public function getObject() { 27 + return $this->log; 28 + } 29 + 30 + public function supportsRuleType($rule_type) { 31 + switch ($rule_type) { 32 + case HeraldRuleTypeConfig::RULE_TYPE_GLOBAL: 33 + case HeraldRuleTypeConfig::RULE_TYPE_OBJECT: 34 + return true; 35 + case HeraldRuleTypeConfig::RULE_TYPE_PERSONAL: 36 + default: 37 + return false; 38 + } 39 + } 40 + 41 + public function canTriggerOnObject($object) { 42 + if ($object instanceof PhabricatorRepository) { 43 + return true; 44 + } 45 + 46 + if ($object instanceof PhabricatorProject) { 47 + return true; 48 + } 49 + 50 + return false; 51 + } 52 + 53 + public function explainValidTriggerObjects() { 54 + return pht( 55 + 'This rule can trigger for **repositories** or **projects**.'); 56 + } 57 + 58 + public function getTriggerObjectPHIDs() { 59 + return array_merge( 60 + array( 61 + $this->hookEngine->getRepository()->getPHID(), 62 + $this->getPHID(), 63 + ), 64 + $this->hookEngine->getRepository()->getProjectPHIDs()); 65 + } 66 + 67 + public function getActions($rule_type) { 68 + switch ($rule_type) { 69 + case HeraldRuleTypeConfig::RULE_TYPE_GLOBAL: 70 + case HeraldRuleTypeConfig::RULE_TYPE_OBJECT: 71 + return array( 72 + self::ACTION_BLOCK, 73 + self::ACTION_NOTHING 74 + ); 75 + case HeraldRuleTypeConfig::RULE_TYPE_PERSONAL: 76 + return array( 77 + self::ACTION_NOTHING, 78 + ); 79 + } 80 + } 81 + 82 + public function getPHID() { 83 + return $this->getObject()->getPHID(); 84 + } 85 + 86 + public function applyHeraldEffects(array $effects) { 87 + assert_instances_of($effects, 'HeraldEffect'); 88 + 89 + $result = array(); 90 + foreach ($effects as $effect) { 91 + $action = $effect->getAction(); 92 + switch ($action) { 93 + case self::ACTION_NOTHING: 94 + $result[] = new HeraldApplyTranscript( 95 + $effect, 96 + true, 97 + pht('Did nothing.')); 98 + break; 99 + case self::ACTION_BLOCK: 100 + $result[] = new HeraldApplyTranscript( 101 + $effect, 102 + true, 103 + pht('Blocked push.')); 104 + break; 105 + default: 106 + throw new Exception(pht('No rules to handle action "%s"!', $action)); 107 + } 108 + } 109 + 110 + return $result; 111 + } 112 + 113 + }
+25 -132
src/applications/diffusion/herald/HeraldPreCommitContentAdapter.php
··· 1 1 <?php 2 2 3 - final class HeraldPreCommitContentAdapter extends HeraldAdapter { 3 + final class HeraldPreCommitContentAdapter extends HeraldPreCommitAdapter { 4 4 5 - private $log; 6 - private $hookEngine; 7 5 private $changesets; 8 6 private $commitRef; 9 7 private $fields; 10 8 private $revision = false; 11 9 12 - public function setPushLog(PhabricatorRepositoryPushLog $log) { 13 - $this->log = $log; 14 - return $this; 15 - } 16 - 17 - public function setHookEngine(DiffusionCommitHookEngine $engine) { 18 - $this->hookEngine = $engine; 19 - return $this; 20 - } 21 - 22 - public function getAdapterApplicationClass() { 23 - return 'PhabricatorApplicationDiffusion'; 24 - } 25 - 26 - public function getObject() { 27 - return $this->log; 28 - } 29 - 30 10 public function getAdapterContentName() { 31 11 return pht('Commit Hook: Commit Content'); 32 12 } ··· 41 21 "Hook rules can block changes."); 42 22 } 43 23 44 - public function supportsRuleType($rule_type) { 45 - switch ($rule_type) { 46 - case HeraldRuleTypeConfig::RULE_TYPE_GLOBAL: 47 - case HeraldRuleTypeConfig::RULE_TYPE_OBJECT: 48 - return true; 49 - case HeraldRuleTypeConfig::RULE_TYPE_PERSONAL: 50 - default: 51 - return false; 52 - } 53 - } 54 - 55 - public function canTriggerOnObject($object) { 56 - if ($object instanceof PhabricatorRepository) { 57 - return true; 58 - } 59 - return false; 60 - } 61 - 62 - public function explainValidTriggerObjects() { 63 - return pht( 64 - 'This rule can trigger for **repositories**.'); 65 - } 66 - 67 - public function getTriggerObjectPHIDs() { 68 - return array( 69 - $this->hookEngine->getRepository()->getPHID(), 70 - $this->getPHID(), 71 - ); 72 - } 73 - 74 - public function getFieldNameMap() { 75 - return array( 76 - ) + parent::getFieldNameMap(); 77 - } 78 - 79 24 public function getFields() { 80 25 return array_merge( 81 26 array( ··· 90 35 self::FIELD_DIFF_ADDED_CONTENT, 91 36 self::FIELD_DIFF_REMOVED_CONTENT, 92 37 self::FIELD_REPOSITORY, 38 + self::FIELD_REPOSITORY_PROJECTS, 93 39 self::FIELD_PUSHER, 94 40 self::FIELD_PUSHER_PROJECTS, 95 41 self::FIELD_DIFFERENTIAL_REVISION, ··· 102 48 parent::getFields()); 103 49 } 104 50 105 - public function getConditionsForField($field) { 106 - switch ($field) { 107 - } 108 - return parent::getConditionsForField($field); 109 - } 110 - 111 - public function getActions($rule_type) { 112 - switch ($rule_type) { 113 - case HeraldRuleTypeConfig::RULE_TYPE_GLOBAL: 114 - case HeraldRuleTypeConfig::RULE_TYPE_OBJECT: 115 - return array( 116 - self::ACTION_BLOCK, 117 - self::ACTION_NOTHING 118 - ); 119 - case HeraldRuleTypeConfig::RULE_TYPE_PERSONAL: 120 - return array( 121 - self::ACTION_NOTHING, 122 - ); 123 - } 124 - } 125 - 126 - public function getValueTypeForFieldAndCondition($field, $condition) { 127 - return parent::getValueTypeForFieldAndCondition($field, $condition); 128 - } 129 - 130 - public function getPHID() { 131 - return $this->getObject()->getPHID(); 132 - } 133 - 134 51 public function getHeraldName() { 135 - return pht('Push Log'); 52 + return pht('Push Log (Content)'); 136 53 } 137 54 138 55 public function getHeraldField($field) { ··· 159 76 case self::FIELD_DIFF_REMOVED_CONTENT: 160 77 return $this->getDiffContent('-'); 161 78 case self::FIELD_REPOSITORY: 162 - return $this->hookEngine->getRepository()->getPHID(); 79 + return $this->getHookEngine()->getRepository()->getPHID(); 80 + case self::FIELD_REPOSITORY_PROJECTS: 81 + return $this->getHookEngine()->getRepository()->getProjectPHIDs(); 163 82 case self::FIELD_PUSHER: 164 - return $this->hookEngine->getViewer()->getPHID(); 83 + return $this->getHookEngine()->getViewer()->getPHID(); 165 84 case self::FIELD_PUSHER_PROJECTS: 166 - return $this->hookEngine->loadViewerProjectPHIDsForHerald(); 85 + return $this->getHookEngine()->loadViewerProjectPHIDsForHerald(); 167 86 case self::FIELD_DIFFERENTIAL_REVISION: 168 87 $revision = $this->getRevision(); 169 88 if (!$revision) { ··· 199 118 return parent::getHeraldField($field); 200 119 } 201 120 202 - public function applyHeraldEffects(array $effects) { 203 - assert_instances_of($effects, 'HeraldEffect'); 204 - 205 - $result = array(); 206 - foreach ($effects as $effect) { 207 - $action = $effect->getAction(); 208 - switch ($action) { 209 - case self::ACTION_NOTHING: 210 - $result[] = new HeraldApplyTranscript( 211 - $effect, 212 - true, 213 - pht('Did nothing.')); 214 - break; 215 - case self::ACTION_BLOCK: 216 - $result[] = new HeraldApplyTranscript( 217 - $effect, 218 - true, 219 - pht('Blocked push.')); 220 - break; 221 - default: 222 - throw new Exception(pht('No rules to handle action "%s"!', $action)); 223 - } 224 - } 225 - 226 - return $result; 227 - } 228 - 229 121 private function getDiffContent($type) { 230 122 if ($this->changesets === null) { 231 123 try { 232 - $this->changesets = $this->hookEngine->loadChangesetsForCommit( 233 - $this->log->getRefNew()); 124 + $this->changesets = $this->getHookEngine()->loadChangesetsForCommit( 125 + $this->getObject()->getRefNew()); 234 126 } catch (Exception $ex) { 235 127 $this->changesets = $ex; 236 128 } ··· 277 169 278 170 private function getCommitRef() { 279 171 if ($this->commitRef === null) { 280 - $this->commitRef = $this->hookEngine->loadCommitRefForCommit( 281 - $this->log->getRefNew()); 172 + $this->commitRef = $this->getHookEngine()->loadCommitRefForCommit( 173 + $this->getObject()->getRefNew()); 282 174 } 283 175 return $this->commitRef; 284 176 } 285 177 286 178 private function getAuthorPHID() { 287 - $repository = $this->hookEngine->getRepository(); 179 + $repository = $this->getHookEngine()->getRepository(); 288 180 $vcs = $repository->getVersionControlSystem(); 289 181 switch ($vcs) { 290 182 case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT: ··· 297 189 return $this->lookupUser($author); 298 190 case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN: 299 191 // In Subversion, the pusher is always the author. 300 - return $this->hookEngine->getViewer()->getPHID(); 192 + return $this->getHookEngine()->getViewer()->getPHID(); 301 193 } 302 194 } 303 195 304 196 private function getCommitterPHID() { 305 - $repository = $this->hookEngine->getRepository(); 197 + $repository = $this->getHookEngine()->getRepository(); 306 198 $vcs = $repository->getVersionControlSystem(); 307 199 switch ($vcs) { 308 200 case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT: ··· 321 213 return $phid; 322 214 case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN: 323 215 // In Subversion, the pusher is always the committer. 324 - return $this->hookEngine->getViewer()->getPHID(); 216 + return $this->getHookEngine()->getViewer()->getPHID(); 325 217 } 326 218 } 327 219 328 220 private function getAuthorRaw() { 329 - $repository = $this->hookEngine->getRepository(); 221 + $repository = $this->getHookEngine()->getRepository(); 330 222 $vcs = $repository->getVersionControlSystem(); 331 223 switch ($vcs) { 332 224 case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT: ··· 335 227 return $ref->getAuthor(); 336 228 case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN: 337 229 // In Subversion, the pusher is always the author. 338 - return $this->hookEngine->getViewer()->getUsername(); 230 + return $this->getHookEngine()->getViewer()->getUsername(); 339 231 } 340 232 } 341 233 342 234 private function getCommitterRaw() { 343 - $repository = $this->hookEngine->getRepository(); 235 + $repository = $this->getHookEngine()->getRepository(); 344 236 $vcs = $repository->getVersionControlSystem(); 345 237 switch ($vcs) { 346 238 case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT: ··· 355 247 return $ref->getAuthor(); 356 248 case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN: 357 249 // In Subversion, the pusher is always the committer. 358 - return $this->hookEngine->getViewer()->getUsername(); 250 + return $this->getHookEngine()->getViewer()->getUsername(); 359 251 } 360 252 } 361 253 ··· 368 260 private function getCommitFields() { 369 261 if ($this->fields === null) { 370 262 $this->fields = id(new DiffusionLowLevelCommitFieldsQuery()) 371 - ->setRepository($this->hookEngine->getRepository()) 263 + ->setRepository($this->getHookEngine()->getRepository()) 372 264 ->withCommitRef($this->getCommitRef()) 373 265 ->execute(); 374 266 } ··· 394 286 } 395 287 396 288 private function getIsMergeCommit() { 397 - $repository = $this->hookEngine->getRepository(); 289 + $repository = $this->getHookEngine()->getRepository(); 398 290 $vcs = $repository->getVersionControlSystem(); 399 291 switch ($vcs) { 400 292 case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT: 401 293 case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL: 402 294 $parents = id(new DiffusionLowLevelParentsQuery()) 403 295 ->setRepository($repository) 404 - ->withIdentifier($this->log->getRefNew()) 296 + ->withIdentifier($this->getObject()->getRefNew()) 405 297 ->execute(); 406 298 407 299 return (count($parents) > 1); ··· 414 306 } 415 307 416 308 private function getBranches() { 417 - return $this->hookEngine->loadBranches($this->log->getRefNew()); 309 + return $this->getHookEngine()->loadBranches( 310 + $this->getObject()->getRefNew()); 418 311 } 419 312 420 313 }
+8 -103
src/applications/diffusion/herald/HeraldPreCommitRefAdapter.php
··· 1 1 <?php 2 2 3 - final class HeraldPreCommitRefAdapter extends HeraldAdapter { 4 - 5 - private $log; 6 - private $hookEngine; 3 + final class HeraldPreCommitRefAdapter extends HeraldPreCommitAdapter { 7 4 8 5 const FIELD_REF_TYPE = 'ref-type'; 9 6 const FIELD_REF_NAME = 'ref-name'; ··· 12 9 const VALUE_REF_TYPE = 'value-ref-type'; 13 10 const VALUE_REF_CHANGE = 'value-ref-change'; 14 11 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 12 public function getAdapterContentName() { 34 13 return pht('Commit Hook: Branches/Tags/Bookmarks'); 35 14 } ··· 44 23 "Hook rules can block changes."); 45 24 } 46 25 47 - public function supportsRuleType($rule_type) { 48 - switch ($rule_type) { 49 - case HeraldRuleTypeConfig::RULE_TYPE_GLOBAL: 50 - case HeraldRuleTypeConfig::RULE_TYPE_OBJECT: 51 - return true; 52 - case HeraldRuleTypeConfig::RULE_TYPE_PERSONAL: 53 - default: 54 - return false; 55 - } 56 - } 57 - 58 - public function canTriggerOnObject($object) { 59 - if ($object instanceof PhabricatorRepository) { 60 - return true; 61 - } 62 - return false; 63 - } 64 - 65 - public function explainValidTriggerObjects() { 66 - return pht( 67 - 'This rule can trigger for **repositories**.'); 68 - } 69 - 70 - public function getTriggerObjectPHIDs() { 71 - return array( 72 - $this->hookEngine->getRepository()->getPHID(), 73 - $this->getPHID(), 74 - ); 75 - } 76 - 77 26 public function getFieldNameMap() { 78 27 return array( 79 28 self::FIELD_REF_TYPE => pht('Ref type'), ··· 89 38 self::FIELD_REF_NAME, 90 39 self::FIELD_REF_CHANGE, 91 40 self::FIELD_REPOSITORY, 41 + self::FIELD_REPOSITORY_PROJECTS, 92 42 self::FIELD_PUSHER, 93 43 self::FIELD_PUSHER_PROJECTS, 94 44 self::FIELD_RULE, ··· 119 69 return parent::getConditionsForField($field); 120 70 } 121 71 122 - public function getActions($rule_type) { 123 - switch ($rule_type) { 124 - case HeraldRuleTypeConfig::RULE_TYPE_GLOBAL: 125 - case HeraldRuleTypeConfig::RULE_TYPE_OBJECT: 126 - return array( 127 - self::ACTION_BLOCK, 128 - self::ACTION_NOTHING 129 - ); 130 - case HeraldRuleTypeConfig::RULE_TYPE_PERSONAL: 131 - return array( 132 - self::ACTION_NOTHING, 133 - ); 134 - } 135 - } 136 - 137 72 public function getValueTypeForFieldAndCondition($field, $condition) { 138 73 switch ($field) { 139 74 case self::FIELD_REF_TYPE: ··· 145 80 return parent::getValueTypeForFieldAndCondition($field, $condition); 146 81 } 147 82 148 - public function getPHID() { 149 - return $this->getObject()->getPHID(); 150 - } 151 - 152 83 public function getHeraldName() { 153 - return pht('Push Log'); 84 + return pht('Push Log (Ref)'); 154 85 } 155 86 156 87 public function getHeraldField($field) { ··· 163 94 case self::FIELD_REF_CHANGE: 164 95 return $log->getChangeFlags(); 165 96 case self::FIELD_REPOSITORY: 166 - return $this->hookEngine->getRepository()->getPHID(); 97 + return $this->getHookEngine()->getRepository()->getPHID(); 98 + case self::FIELD_REPOSITORY_PROJECTS: 99 + return $this->getHookEngine()->getRepository()->getProjectPHIDs(); 167 100 case self::FIELD_PUSHER: 168 - return $this->hookEngine->getViewer()->getPHID(); 101 + return $this->getHookEngine()->getViewer()->getPHID(); 169 102 case self::FIELD_PUSHER_PROJECTS: 170 - return $this->hookEngine->loadViewerProjectPHIDsForHerald(); 103 + return $this->getHookEngine()->loadViewerProjectPHIDsForHerald(); 171 104 } 172 105 173 106 return parent::getHeraldField($field); 174 - } 175 - 176 - 177 - public function applyHeraldEffects(array $effects) { 178 - assert_instances_of($effects, 'HeraldEffect'); 179 - 180 - $result = array(); 181 - foreach ($effects as $effect) { 182 - $action = $effect->getAction(); 183 - switch ($action) { 184 - case self::ACTION_NOTHING: 185 - $result[] = new HeraldApplyTranscript( 186 - $effect, 187 - true, 188 - pht('Did nothing.')); 189 - break; 190 - case self::ACTION_BLOCK: 191 - $result[] = new HeraldApplyTranscript( 192 - $effect, 193 - true, 194 - pht('Blocked push.')); 195 - break; 196 - default: 197 - throw new Exception(pht('No rules to handle action "%s"!', $action)); 198 - } 199 - } 200 - 201 - return $result; 202 107 } 203 108 204 109 }
+4
src/applications/herald/adapter/HeraldAdapter.php
··· 19 19 const FIELD_DIFF_ADDED_CONTENT = 'diff-added-content'; 20 20 const FIELD_DIFF_REMOVED_CONTENT = 'diff-removed-content'; 21 21 const FIELD_REPOSITORY = 'repository'; 22 + const FIELD_REPOSITORY_PROJECTS = 'repository-projects'; 22 23 const FIELD_RULE = 'rule'; 23 24 const FIELD_AFFECTED_PACKAGE = 'affected-package'; 24 25 const FIELD_AFFECTED_PACKAGE_OWNER = 'affected-package-owner'; ··· 193 194 self::FIELD_DIFF_ADDED_CONTENT => pht('Any added file content'), 194 195 self::FIELD_DIFF_REMOVED_CONTENT => pht('Any removed file content'), 195 196 self::FIELD_REPOSITORY => pht('Repository'), 197 + self::FIELD_REPOSITORY_PROJECTS => pht('Repository\'s projects'), 196 198 self::FIELD_RULE => pht('Another Herald rule'), 197 199 self::FIELD_AFFECTED_PACKAGE => pht('Any affected package'), 198 200 self::FIELD_AFFECTED_PACKAGE_OWNER => ··· 283 285 case self::FIELD_AFFECTED_PACKAGE: 284 286 case self::FIELD_AFFECTED_PACKAGE_OWNER: 285 287 case self::FIELD_PUSHER_PROJECTS: 288 + case self::FIELD_REPOSITORY_PROJECTS: 286 289 return array( 287 290 self::CONDITION_INCLUDE_ALL, 288 291 self::CONDITION_INCLUDE_ANY, ··· 713 716 case self::FIELD_AUTHOR_PROJECTS: 714 717 case self::FIELD_PUSHER_PROJECTS: 715 718 case self::FIELD_PROJECTS: 719 + case self::FIELD_REPOSITORY_PROJECTS: 716 720 return self::VALUE_PROJECT; 717 721 case self::FIELD_REVIEWERS: 718 722 return self::VALUE_USER_OR_PROJECT;
+2 -1
src/applications/herald/controller/HeraldNewController.php
··· 172 172 ->appendRemarkupInstructions( 173 173 pht( 174 174 'Choose the object this rule will act on (for example, enter '. 175 - '`rX` to act on the `rX` repository).')) 175 + '`rX` to act on the `rX` repository, or `#project` to act on '. 176 + 'a project).')) 176 177 ->appendRemarkupInstructions( 177 178 $adapter->explainValidTriggerObjects()) 178 179 ->appendChild(
+1 -1
src/applications/herald/storage/HeraldRule.php
··· 17 17 protected $isDisabled = 0; 18 18 protected $triggerObjectPHID; 19 19 20 - protected $configVersion = 23; 20 + protected $configVersion = 24; 21 21 22 22 // phids for which this rule has been applied 23 23 private $ruleApplied = self::ATTACHABLE;