[ Index ] |
PHP Cross Reference of Phabricator |
[Summary view] [Print] [Text view]
1 <?php 2 3 final class HeraldPreCommitContentAdapter extends HeraldPreCommitAdapter { 4 5 private $changesets; 6 private $commitRef; 7 private $fields; 8 private $revision = false; 9 10 public function getAdapterContentName() { 11 return pht('Commit Hook: Commit Content'); 12 } 13 14 public function getAdapterSortOrder() { 15 return 2500; 16 } 17 18 public function getAdapterContentDescription() { 19 return pht( 20 "React to commits being pushed to hosted repositories.\n". 21 "Hook rules can block changes and send push summary mail."); 22 } 23 24 public function getFields() { 25 return array_merge( 26 array( 27 self::FIELD_BODY, 28 self::FIELD_AUTHOR, 29 self::FIELD_AUTHOR_RAW, 30 self::FIELD_COMMITTER, 31 self::FIELD_COMMITTER_RAW, 32 self::FIELD_BRANCHES, 33 self::FIELD_DIFF_FILE, 34 self::FIELD_DIFF_CONTENT, 35 self::FIELD_DIFF_ADDED_CONTENT, 36 self::FIELD_DIFF_REMOVED_CONTENT, 37 self::FIELD_DIFF_ENORMOUS, 38 self::FIELD_REPOSITORY, 39 self::FIELD_REPOSITORY_PROJECTS, 40 self::FIELD_PUSHER, 41 self::FIELD_PUSHER_PROJECTS, 42 self::FIELD_PUSHER_IS_COMMITTER, 43 self::FIELD_DIFFERENTIAL_REVISION, 44 self::FIELD_DIFFERENTIAL_ACCEPTED, 45 self::FIELD_DIFFERENTIAL_REVIEWERS, 46 self::FIELD_DIFFERENTIAL_CCS, 47 self::FIELD_IS_MERGE_COMMIT, 48 ), 49 parent::getFields()); 50 } 51 52 public function getHeraldName() { 53 return pht('Push Log (Content)'); 54 } 55 56 public function getHeraldField($field) { 57 $log = $this->getObject(); 58 switch ($field) { 59 case self::FIELD_BODY: 60 return $this->getCommitRef()->getMessage(); 61 case self::FIELD_AUTHOR: 62 return $this->getAuthorPHID(); 63 case self::FIELD_AUTHOR_RAW: 64 return $this->getAuthorRaw(); 65 case self::FIELD_COMMITTER: 66 return $this->getCommitterPHID(); 67 case self::FIELD_COMMITTER_RAW: 68 return $this->getCommitterRaw(); 69 case self::FIELD_BRANCHES: 70 return $this->getBranches(); 71 case self::FIELD_DIFF_FILE: 72 return $this->getDiffContent('name'); 73 case self::FIELD_DIFF_CONTENT: 74 return $this->getDiffContent('*'); 75 case self::FIELD_DIFF_ADDED_CONTENT: 76 return $this->getDiffContent('+'); 77 case self::FIELD_DIFF_REMOVED_CONTENT: 78 return $this->getDiffContent('-'); 79 case self::FIELD_DIFF_ENORMOUS: 80 $this->getDiffContent('*'); 81 return ($this->changesets instanceof Exception); 82 case self::FIELD_REPOSITORY: 83 return $this->getHookEngine()->getRepository()->getPHID(); 84 case self::FIELD_REPOSITORY_PROJECTS: 85 return $this->getHookEngine()->getRepository()->getProjectPHIDs(); 86 case self::FIELD_PUSHER: 87 return $this->getHookEngine()->getViewer()->getPHID(); 88 case self::FIELD_PUSHER_PROJECTS: 89 return $this->getHookEngine()->loadViewerProjectPHIDsForHerald(); 90 case self::FIELD_DIFFERENTIAL_REVISION: 91 $revision = $this->getRevision(); 92 if (!$revision) { 93 return null; 94 } 95 return $revision->getPHID(); 96 case self::FIELD_DIFFERENTIAL_ACCEPTED: 97 $revision = $this->getRevision(); 98 if (!$revision) { 99 return null; 100 } 101 $status_accepted = ArcanistDifferentialRevisionStatus::ACCEPTED; 102 if ($revision->getStatus() != $status_accepted) { 103 return null; 104 } 105 return $revision->getPHID(); 106 case self::FIELD_DIFFERENTIAL_REVIEWERS: 107 $revision = $this->getRevision(); 108 if (!$revision) { 109 return array(); 110 } 111 return $revision->getReviewers(); 112 case self::FIELD_DIFFERENTIAL_CCS: 113 $revision = $this->getRevision(); 114 if (!$revision) { 115 return array(); 116 } 117 return $revision->getCCPHIDs(); 118 case self::FIELD_IS_MERGE_COMMIT: 119 return $this->getIsMergeCommit(); 120 case self::FIELD_PUSHER_IS_COMMITTER: 121 $pusher_phid = $this->getHookEngine()->getViewer()->getPHID(); 122 return ($this->getCommitterPHID() == $pusher_phid); 123 } 124 125 return parent::getHeraldField($field); 126 } 127 128 private function getDiffContent($type) { 129 if ($this->changesets === null) { 130 try { 131 $this->changesets = $this->getHookEngine()->loadChangesetsForCommit( 132 $this->getObject()->getRefNew()); 133 } catch (Exception $ex) { 134 $this->changesets = $ex; 135 } 136 } 137 138 if ($this->changesets instanceof Exception) { 139 $ex_class = get_class($this->changesets); 140 $ex_message = $this->changesets->getmessage(); 141 if ($type === 'name') { 142 return array("<{$ex_class}: {$ex_message}>"); 143 } else { 144 return array("<{$ex_class}>" => $ex_message); 145 } 146 } 147 148 $result = array(); 149 if ($type === 'name') { 150 foreach ($this->changesets as $change) { 151 $result[] = $change->getFilename(); 152 } 153 } else { 154 foreach ($this->changesets as $change) { 155 $lines = array(); 156 foreach ($change->getHunks() as $hunk) { 157 switch ($type) { 158 case '-': 159 $lines[] = $hunk->makeOldFile(); 160 break; 161 case '+': 162 $lines[] = $hunk->makeNewFile(); 163 break; 164 case '*': 165 default: 166 $lines[] = $hunk->makeChanges(); 167 break; 168 } 169 } 170 $result[$change->getFilename()] = implode('', $lines); 171 } 172 } 173 174 return $result; 175 } 176 177 private function getCommitRef() { 178 if ($this->commitRef === null) { 179 $this->commitRef = $this->getHookEngine()->loadCommitRefForCommit( 180 $this->getObject()->getRefNew()); 181 } 182 return $this->commitRef; 183 } 184 185 private function getAuthorPHID() { 186 $repository = $this->getHookEngine()->getRepository(); 187 $vcs = $repository->getVersionControlSystem(); 188 switch ($vcs) { 189 case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT: 190 case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL: 191 $ref = $this->getCommitRef(); 192 $author = $ref->getAuthor(); 193 if (!strlen($author)) { 194 return null; 195 } 196 return $this->lookupUser($author); 197 case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN: 198 // In Subversion, the pusher is always the author. 199 return $this->getHookEngine()->getViewer()->getPHID(); 200 } 201 } 202 203 private function getCommitterPHID() { 204 $repository = $this->getHookEngine()->getRepository(); 205 $vcs = $repository->getVersionControlSystem(); 206 switch ($vcs) { 207 case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT: 208 case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL: 209 // If there's no committer information, we're going to return the 210 // author instead. However, if there's committer information and we 211 // can't resolve it, return `null`. 212 $ref = $this->getCommitRef(); 213 $committer = $ref->getCommitter(); 214 if (!strlen($committer)) { 215 return $this->getAuthorPHID(); 216 } 217 return $this->lookupUser($committer); 218 case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN: 219 // In Subversion, the pusher is always the committer. 220 return $this->getHookEngine()->getViewer()->getPHID(); 221 } 222 } 223 224 private function getAuthorRaw() { 225 $repository = $this->getHookEngine()->getRepository(); 226 $vcs = $repository->getVersionControlSystem(); 227 switch ($vcs) { 228 case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT: 229 case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL: 230 $ref = $this->getCommitRef(); 231 return $ref->getAuthor(); 232 case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN: 233 // In Subversion, the pusher is always the author. 234 return $this->getHookEngine()->getViewer()->getUsername(); 235 } 236 } 237 238 private function getCommitterRaw() { 239 $repository = $this->getHookEngine()->getRepository(); 240 $vcs = $repository->getVersionControlSystem(); 241 switch ($vcs) { 242 case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT: 243 case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL: 244 // Here, if there's no committer, we're going to return the author 245 // instead. 246 $ref = $this->getCommitRef(); 247 $committer = $ref->getCommitter(); 248 if (strlen($committer)) { 249 return $committer; 250 } 251 return $ref->getAuthor(); 252 case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN: 253 // In Subversion, the pusher is always the committer. 254 return $this->getHookEngine()->getViewer()->getUsername(); 255 } 256 } 257 258 private function lookupUser($author) { 259 return id(new DiffusionResolveUserQuery()) 260 ->withName($author) 261 ->execute(); 262 } 263 264 private function getCommitFields() { 265 if ($this->fields === null) { 266 $this->fields = id(new DiffusionLowLevelCommitFieldsQuery()) 267 ->setRepository($this->getHookEngine()->getRepository()) 268 ->withCommitRef($this->getCommitRef()) 269 ->execute(); 270 } 271 return $this->fields; 272 } 273 274 private function getRevision() { 275 if ($this->revision === false) { 276 $fields = $this->getCommitFields(); 277 $revision_id = idx($fields, 'revisionID'); 278 if (!$revision_id) { 279 $this->revision = null; 280 } else { 281 $this->revision = id(new DifferentialRevisionQuery()) 282 ->setViewer(PhabricatorUser::getOmnipotentUser()) 283 ->withIDs(array($revision_id)) 284 ->needRelationships(true) 285 ->executeOne(); 286 } 287 } 288 289 return $this->revision; 290 } 291 292 private function getIsMergeCommit() { 293 $repository = $this->getHookEngine()->getRepository(); 294 $vcs = $repository->getVersionControlSystem(); 295 switch ($vcs) { 296 case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT: 297 case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL: 298 $parents = id(new DiffusionLowLevelParentsQuery()) 299 ->setRepository($repository) 300 ->withIdentifier($this->getObject()->getRefNew()) 301 ->execute(); 302 303 return (count($parents) > 1); 304 case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN: 305 // NOTE: For now, we ignore "svn:mergeinfo" at all levels. We might 306 // change this some day, but it's not nearly as clear a signal as 307 // ancestry is in Git/Mercurial. 308 return false; 309 } 310 } 311 312 private function getBranches() { 313 return $this->getHookEngine()->loadBranches( 314 $this->getObject()->getRefNew()); 315 } 316 317 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Sun Nov 30 09:20:46 2014 | Cross-referenced by PHPXref 0.7.1 |