Differential D14337 Diff 34622 src/applications/drydock/operation/DrydockLandRepositoryOperation.php
Changeset View
Changeset View
Standalone View
Standalone View
src/applications/drydock/operation/DrydockLandRepositoryOperation.php
| Show All 29 Lines | switch ($operation->getOperationState()) { | ||||
| $target); | $target); | ||||
| case DrydockRepositoryOperation::STATE_DONE: | case DrydockRepositoryOperation::STATE_DONE: | ||||
| return pht( | return pht( | ||||
| 'Revision landed into %s.', | 'Revision landed into %s.', | ||||
| $repository->getMonogram()); | $repository->getMonogram()); | ||||
| } | } | ||||
| } | } | ||||
| public function getWorkingCopyMerges(DrydockRepositoryOperation $operation) { | |||||
| $repository = $operation->getRepository(); | |||||
| $merges = array(); | |||||
| $object = $operation->getObject(); | |||||
| if ($object instanceof DifferentialRevision) { | |||||
| $diff = $this->loadDiff($operation); | |||||
| $merges[] = array( | |||||
| 'src.uri' => $repository->getStagingURI(), | |||||
| 'src.ref' => $diff->getStagingRef(), | |||||
| ); | |||||
| } else { | |||||
| throw new Exception( | |||||
| pht( | |||||
| 'Invalid or unknown object ("%s") for land operation, expected '. | |||||
| 'Differential Revision.', | |||||
| $operation->getObjectPHID())); | |||||
| } | |||||
| return $merges; | |||||
| } | |||||
| public function applyOperation( | public function applyOperation( | ||||
| DrydockRepositoryOperation $operation, | DrydockRepositoryOperation $operation, | ||||
| DrydockInterface $interface) { | DrydockInterface $interface) { | ||||
| $viewer = $this->getViewer(); | $viewer = $this->getViewer(); | ||||
| $repository = $operation->getRepository(); | $repository = $operation->getRepository(); | ||||
| $cmd = array(); | $cmd = array(); | ||||
| $arg = array(); | $arg = array(); | ||||
| $object = $operation->getObject(); | $object = $operation->getObject(); | ||||
| if ($object instanceof DifferentialRevision) { | if ($object instanceof DifferentialRevision) { | ||||
| $revision = $object; | $revision = $object; | ||||
| $diff_phid = $operation->getProperty('differential.diffPHID'); | $diff = $this->loadDiff($operation); | ||||
| $diff = id(new DifferentialDiffQuery()) | |||||
| ->setViewer($viewer) | |||||
| ->withPHIDs(array($diff_phid)) | |||||
| ->executeOne(); | |||||
| if (!$diff) { | |||||
| throw new Exception( | |||||
| pht( | |||||
| 'Unable to load diff "%s".', | |||||
| $diff_phid)); | |||||
| } | |||||
| $diff_revid = $diff->getRevisionID(); | |||||
| $revision_id = $revision->getID(); | |||||
| if ($diff_revid != $revision_id) { | |||||
| throw new Exception( | |||||
| pht( | |||||
| 'Diff ("%s") has wrong revision ID ("%s", expected "%s").', | |||||
| $diff_phid, | |||||
| $diff_revid, | |||||
| $revision_id)); | |||||
| } | |||||
| $cmd[] = 'git fetch --no-tags -- %s +%s:%s'; | |||||
| $arg[] = $repository->getStagingURI(); | |||||
| $arg[] = $diff->getStagingRef(); | |||||
| $arg[] = $diff->getStagingRef(); | |||||
| $merge_src = $diff->getStagingRef(); | |||||
| $dict = $diff->getDiffAuthorshipDict(); | $dict = $diff->getDiffAuthorshipDict(); | ||||
| $author_name = idx($dict, 'authorName'); | $author_name = idx($dict, 'authorName'); | ||||
| $author_email = idx($dict, 'authorEmail'); | $author_email = idx($dict, 'authorEmail'); | ||||
| $api_method = 'differential.getcommitmessage'; | $api_method = 'differential.getcommitmessage'; | ||||
| $api_params = array( | $api_params = array( | ||||
| 'revision_id' => $revision->getID(), | 'revision_id' => $revision->getID(), | ||||
| Show All 10 Lines | if ($object instanceof DifferentialRevision) { | ||||
| $operation->getObjectPHID())); | $operation->getObjectPHID())); | ||||
| } | } | ||||
| $target = $operation->getRepositoryTarget(); | $target = $operation->getRepositoryTarget(); | ||||
| list($type, $name) = explode(':', $target, 2); | list($type, $name) = explode(':', $target, 2); | ||||
| switch ($type) { | switch ($type) { | ||||
| case 'branch': | case 'branch': | ||||
| $push_dst = 'refs/heads/'.$name; | $push_dst = 'refs/heads/'.$name; | ||||
| $merge_dst = 'refs/remotes/origin/'.$name; | |||||
| break; | break; | ||||
| default: | default: | ||||
| throw new Exception( | throw new Exception( | ||||
| pht( | pht( | ||||
| 'Unknown repository operation target type "%s" (in target "%s").', | 'Unknown repository operation target type "%s" (in target "%s").', | ||||
| $type, | $type, | ||||
| $target)); | $target)); | ||||
| } | } | ||||
| $committer_info = $this->getCommitterInfo($operation); | $committer_info = $this->getCommitterInfo($operation); | ||||
| $cmd[] = 'git checkout %s'; | // NOTE: We're doing this commit with "-F -" so we don't run into trouble | ||||
| $arg[] = $merge_dst; | // with enormous commit messages which might otherwise exceed the maximum | ||||
| // size of a command. | |||||
| $cmd[] = 'git merge --no-stat --squash --ff-only -- %s'; | |||||
| $arg[] = $merge_src; | $future = $interface->getExecFuture( | ||||
| 'git -c user.name=%s -c user.email=%s commit --author %s -F - --', | |||||
| $cmd[] = 'git -c user.name=%s -c user.email=%s commit --author %s -m %s'; | $committer_info['name'], | ||||
| $committer_info['email'], | |||||
| $arg[] = $committer_info['name']; | "{$author_name} <{$author_email}>"); | ||||
| $arg[] = $committer_info['email']; | |||||
| $future | |||||
| $arg[] = "{$author_name} <{$author_email}>"; | ->write($commit_message) | ||||
| $arg[] = $commit_message; | ->resolvex(); | ||||
| $cmd[] = 'git push origin -- %s:%s'; | $interface->execx( | ||||
| $arg[] = 'HEAD'; | 'git push origin -- %s:%s', | ||||
| $arg[] = $push_dst; | 'HEAD', | ||||
| $push_dst); | |||||
| $cmd = implode(' && ', $cmd); | |||||
| $argv = array_merge(array($cmd), $arg); | |||||
| $result = call_user_func_array( | |||||
| array($interface, 'execx'), | |||||
| $argv); | |||||
| } | } | ||||
| private function getCommitterInfo(DrydockRepositoryOperation $operation) { | private function getCommitterInfo(DrydockRepositoryOperation $operation) { | ||||
| $viewer = $this->getViewer(); | $viewer = $this->getViewer(); | ||||
| $committer_name = null; | $committer_name = null; | ||||
| $author_phid = $operation->getAuthorPHID(); | $author_phid = $operation->getAuthorPHID(); | ||||
| Show All 16 Lines | private function getCommitterInfo(DrydockRepositoryOperation $operation) { | ||||
| // now just make something up so we don't leak anyone's stuff. | // now just make something up so we don't leak anyone's stuff. | ||||
| return array( | return array( | ||||
| 'name' => $committer_name, | 'name' => $committer_name, | ||||
| 'email' => 'autocommitter@example.com', | 'email' => 'autocommitter@example.com', | ||||
| ); | ); | ||||
| } | } | ||||
| private function loadDiff(DrydockRepositoryOperation $operation) { | |||||
| $viewer = $this->getViewer(); | |||||
| $revision = $operation->getObject(); | |||||
| $diff_phid = $operation->getProperty('differential.diffPHID'); | |||||
| $diff = id(new DifferentialDiffQuery()) | |||||
| ->setViewer($viewer) | |||||
| ->withPHIDs(array($diff_phid)) | |||||
| ->executeOne(); | |||||
| if (!$diff) { | |||||
| throw new Exception( | |||||
| pht( | |||||
| 'Unable to load diff "%s".', | |||||
| $diff_phid)); | |||||
| } | |||||
| $diff_revid = $diff->getRevisionID(); | |||||
| $revision_id = $revision->getID(); | |||||
| if ($diff_revid != $revision_id) { | |||||
| throw new Exception( | |||||
| pht( | |||||
| 'Diff ("%s") has wrong revision ID ("%s", expected "%s").', | |||||
| $diff_phid, | |||||
| $diff_revid, | |||||
| $revision_id)); | |||||
| } | |||||
| return $diff; | |||||
| } | |||||
| } | } | ||||