@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 "is merge commit" Herald field for pre-commit rules

Summary:
Ref T4195. This allows you to write rules which disallow merge commits.

Also make the reject message a little more useful.

Test Plan:
remote: This push was rejected by Herald push rule H27.
remote: Change: commit/daed0d448404
remote: Rule: No Merges
remote: Reason: No merge commits allowed. If you must push a merge, include "@force-merge" in the commit message.

Reviewers: btrahan

Reviewed By: btrahan

CC: aran

Maniphest Tasks: T4195

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

+51 -2
+11 -2
src/applications/diffusion/engine/DiffusionCommitHookEngine.php
··· 259 259 $engine = new HeraldEngine(); 260 260 $rules = null; 261 261 $blocking_effect = null; 262 + $blocked_update = null; 262 263 foreach ($updates as $update) { 263 264 $adapter = id(clone $adapter_template) 264 265 ->setPushLog($update); ··· 275 276 foreach ($effects as $effect) { 276 277 if ($effect->getAction() == HeraldAdapter::ACTION_BLOCK) { 277 278 $blocking_effect = $effect; 279 + $blocked_update = $update; 278 280 break; 279 281 } 280 282 } ··· 299 301 } else { 300 302 $rule_name = pht('Unnamed Herald Rule'); 301 303 } 304 + 305 + $blocked_ref_name = coalesce( 306 + $blocked_update->getRefName(), 307 + $blocked_update->getRefNewShort()); 308 + $blocked_name = $blocked_update->getRefType().'/'.$blocked_ref_name; 302 309 303 310 throw new DiffusionCommitHookRejectException( 304 311 pht( 305 - "This commit was rejected by Herald pre-commit rule %s.\n". 306 - "Rule: %s\n". 312 + "This push was rejected by Herald push rule %s.\n". 313 + "Change: %s\n". 314 + " Rule: %s\n". 307 315 "Reason: %s", 308 316 'H'.$blocking_effect->getRuleID(), 317 + $blocked_name, 309 318 $rule_name, 310 319 $message)); 311 320 }
+23
src/applications/diffusion/herald/HeraldPreCommitContentAdapter.php
··· 53 53 self::FIELD_DIFFERENTIAL_ACCEPTED, 54 54 self::FIELD_DIFFERENTIAL_REVIEWERS, 55 55 self::FIELD_DIFFERENTIAL_CCS, 56 + self::FIELD_IS_MERGE_COMMIT, 56 57 self::FIELD_RULE, 57 58 ), 58 59 parent::getFields()); ··· 141 142 return array(); 142 143 } 143 144 return $revision->getCCPHIDs(); 145 + case self::FIELD_IS_MERGE_COMMIT: 146 + return $this->getIsMergeCommit(); 144 147 } 145 148 146 149 return parent::getHeraldField($field); ··· 304 307 } 305 308 306 309 return $this->revision; 310 + } 311 + 312 + private function getIsMergeCommit() { 313 + $repository = $this->hookEngine->getRepository(); 314 + $vcs = $repository->getVersionControlSystem(); 315 + switch ($vcs) { 316 + case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT: 317 + case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL: 318 + $parents = id(new DiffusionLowLevelParentsQuery()) 319 + ->setRepository($repository) 320 + ->withIdentifier($this->log->getRefNew()) 321 + ->execute(); 322 + 323 + return (count($parents) > 1); 324 + case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN: 325 + // NOTE: For now, we ignore "svn:mergeinfo" at all levels. We might 326 + // change this some day, but it's not nearly as clear a signal as 327 + // ancestry is in Git/Mercurial. 328 + return false; 329 + } 307 330 } 308 331 309 332 }
+17
src/applications/herald/adapter/HeraldAdapter.php
··· 31 31 const FIELD_DIFFERENTIAL_REVIEWERS = 'differential-reviewers'; 32 32 const FIELD_DIFFERENTIAL_CCS = 'differential-ccs'; 33 33 const FIELD_DIFFERENTIAL_ACCEPTED = 'differential-accepted'; 34 + const FIELD_IS_MERGE_COMMIT = 'is-merge-commit'; 34 35 35 36 const CONDITION_CONTAINS = 'contains'; 36 37 const CONDITION_NOT_CONTAINS = '!contains'; ··· 52 53 const CONDITION_REGEXP_PAIR = 'regexp-pair'; 53 54 const CONDITION_HAS_BIT = 'bit'; 54 55 const CONDITION_NOT_BIT = '!bit'; 56 + const CONDITION_IS_TRUE = 'true'; 57 + const CONDITION_IS_FALSE = 'false'; 55 58 56 59 const ACTION_ADD_CC = 'addcc'; 57 60 const ACTION_REMOVE_CC = 'remcc'; ··· 172 175 self::FIELD_DIFFERENTIAL_CCS => pht('Differential CCs'), 173 176 self::FIELD_DIFFERENTIAL_ACCEPTED 174 177 => pht('Accepted Differential revision'), 178 + self::FIELD_IS_MERGE_COMMIT => pht('Commit is a merge'), 175 179 ); 176 180 } 177 181 ··· 186 190 self::CONDITION_IS => pht('is'), 187 191 self::CONDITION_IS_NOT => pht('is not'), 188 192 self::CONDITION_IS_ANY => pht('is any of'), 193 + self::CONDITION_IS_TRUE => pht('is true'), 194 + self::CONDITION_IS_FALSE => pht('is false'), 189 195 self::CONDITION_IS_NOT_ANY => pht('is not any of'), 190 196 self::CONDITION_INCLUDE_ALL => pht('include all of'), 191 197 self::CONDITION_INCLUDE_ANY => pht('include any of'), ··· 292 298 self::CONDITION_EXISTS, 293 299 self::CONDITION_NOT_EXISTS, 294 300 ); 301 + case self::FIELD_IS_MERGE_COMMIT: 302 + return array( 303 + self::CONDITION_IS_TRUE, 304 + self::CONDITION_IS_FALSE, 305 + ); 295 306 default: 296 307 throw new Exception( 297 308 "This adapter does not define conditions for field '{$field}'!"); ··· 362 373 array_fuse($field_value), 363 374 $condition_value); 364 375 case self::CONDITION_EXISTS: 376 + case self::CONDITION_IS_TRUE: 365 377 return (bool)$field_value; 366 378 case self::CONDITION_NOT_EXISTS: 379 + case self::CONDITION_IS_FALSE: 367 380 return !$field_value; 368 381 case self::CONDITION_UNCONDITIONALLY: 369 382 return (bool)$field_value; ··· 515 528 case self::CONDITION_UNCONDITIONALLY: 516 529 case self::CONDITION_HAS_BIT: 517 530 case self::CONDITION_NOT_BIT: 531 + case self::CONDITION_IS_TRUE: 532 + case self::CONDITION_IS_FALSE: 518 533 // No explicit validation for these types, although there probably 519 534 // should be in some cases. 520 535 break; ··· 669 684 case self::CONDITION_EXISTS: 670 685 case self::CONDITION_NOT_EXISTS: 671 686 case self::CONDITION_UNCONDITIONALLY: 687 + case self::CONDITION_IS_TRUE: 688 + case self::CONDITION_IS_FALSE: 672 689 return self::VALUE_NONE; 673 690 case self::CONDITION_RULE: 674 691 case self::CONDITION_NOT_RULE: