public function applyOperation(DrydockRepositoryOperation $operation, DrydockInterface $interface)
 {
     $viewer = $this->getViewer();
     $repository = $operation->getRepository();
     $cmd = array();
     $arg = array();
     $object = $operation->getObject();
     if ($object instanceof DifferentialRevision) {
         $revision = $object;
         $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));
         }
         $cmd[] = 'git fetch --no-tags -- %s +%s:%s';
         $arg[] = $repository->getStagingURI();
         $arg[] = $diff->getStagingRef();
         $arg[] = $diff->getStagingRef();
         $merge_src = $diff->getStagingRef();
         $dict = $diff->getDiffAuthorshipDict();
         $author_name = idx($dict, 'authorName');
         $author_email = idx($dict, 'authorEmail');
         $api_method = 'differential.getcommitmessage';
         $api_params = array('revision_id' => $revision->getID());
         $commit_message = id(new ConduitCall($api_method, $api_params))->setUser($viewer)->execute();
     } else {
         throw new Exception(pht('Invalid or unknown object ("%s") for land operation, expected ' . 'Differential Revision.', $operation->getObjectPHID()));
     }
     $target = $operation->getRepositoryTarget();
     list($type, $name) = explode(':', $target, 2);
     switch ($type) {
         case 'branch':
             $push_dst = 'refs/heads/' . $name;
             $merge_dst = 'refs/remotes/origin/' . $name;
             break;
         default:
             throw new Exception(pht('Unknown repository operation target type "%s" (in target "%s").', $type, $target));
     }
     $committer_info = $this->getCommitterInfo($operation);
     $cmd[] = 'git checkout %s';
     $arg[] = $merge_dst;
     $cmd[] = 'git merge --no-stat --squash --ff-only -- %s';
     $arg[] = $merge_src;
     $cmd[] = 'git -c user.name=%s -c user.email=%s commit --author %s -m %s';
     $arg[] = $committer_info['name'];
     $arg[] = $committer_info['email'];
     $arg[] = "{$author_name} <{$author_email}>";
     $arg[] = $commit_message;
     $cmd[] = 'git push origin -- %s:%s';
     $arg[] = 'HEAD';
     $arg[] = $push_dst;
     $cmd = implode(' && ', $cmd);
     $argv = array_merge(array($cmd), $arg);
     $result = call_user_func_array(array($interface, 'execx'), $argv);
 }
 public function applyOperation(DrydockRepositoryOperation $operation, DrydockInterface $interface)
 {
     $viewer = $this->getViewer();
     $repository = $operation->getRepository();
     $cmd = array();
     $arg = array();
     $object = $operation->getObject();
     if ($object instanceof DifferentialRevision) {
         $revision = $object;
         $diff = $this->loadDiff($operation);
         $dict = $diff->getDiffAuthorshipDict();
         $author_name = idx($dict, 'authorName');
         $author_email = idx($dict, 'authorEmail');
         $api_method = 'differential.getcommitmessage';
         $api_params = array('revision_id' => $revision->getID());
         $commit_message = id(new ConduitCall($api_method, $api_params))->setUser($viewer)->execute();
     } else {
         throw new Exception(pht('Invalid or unknown object ("%s") for land operation, expected ' . 'Differential Revision.', $operation->getObjectPHID()));
     }
     $target = $operation->getRepositoryTarget();
     list($type, $name) = explode(':', $target, 2);
     switch ($type) {
         case 'branch':
             $push_dst = 'refs/heads/' . $name;
             break;
         default:
             throw new Exception(pht('Unknown repository operation target type "%s" (in target "%s").', $type, $target));
     }
     $committer_info = $this->getCommitterInfo($operation);
     // NOTE: We're doing this commit with "-F -" so we don't run into trouble
     // with enormous commit messages which might otherwise exceed the maximum
     // size of a command.
     $future = $interface->getExecFuture('git -c user.name=%s -c user.email=%s commit --author %s -F - --', $committer_info['name'], $committer_info['email'], "{$author_name} <{$author_email}>");
     $future->write($commit_message);
     try {
         $future->resolvex();
     } catch (CommandException $ex) {
         $display_command = csprintf('git commit');
         // TODO: One reason this can fail is if the changes have already been
         // merged. We could try to detect that.
         $error = DrydockCommandError::newFromCommandException($ex)->setPhase(self::PHASE_COMMIT)->setDisplayCommand($display_command);
         $operation->setCommandError($error->toDictionary());
         throw $ex;
     }
     try {
         $interface->execx('git push origin -- %s:%s', 'HEAD', $push_dst);
     } catch (CommandException $ex) {
         $display_command = csprintf('git push origin %R:%R', 'HEAD', $push_dst);
         $error = DrydockCommandError::newFromCommandException($ex)->setPhase(self::PHASE_PUSH)->setDisplayCommand($display_command);
         $operation->setCommandError($error->toDictionary());
         throw $ex;
     }
 }
 public function applyOperation(DrydockRepositoryOperation $operation, DrydockInterface $interface)
 {
     $repository = $operation->getRepository();
     if ($repository->isGit()) {
         $interface->execx('git status');
     } else {
         if ($repository->isHg()) {
             $interface->execx('hg status');
         } else {
             if ($repository->isSVN()) {
                 $interface->execx('svn status');
             } else {
                 throw new PhutilMethodNotImplementedException();
             }
         }
     }
 }
 public function applyOperation(DrydockRepositoryOperation $operation, DrydockInterface $interface)
 {
     $viewer = $this->getViewer();
     $repository = $operation->getRepository();
     $cmd = array();
     $arg = array();
     $object = $operation->getObject();
     if ($object instanceof DifferentialRevision) {
         $revision = $object;
         $diff = $this->loadDiff($operation);
         $dict = $diff->getDiffAuthorshipDict();
         $author_name = idx($dict, 'authorName');
         $author_email = idx($dict, 'authorEmail');
         $api_method = 'differential.getcommitmessage';
         $api_params = array('revision_id' => $revision->getID());
         $commit_message = id(new ConduitCall($api_method, $api_params))->setUser($viewer)->execute();
     } else {
         throw new Exception(pht('Invalid or unknown object ("%s") for land operation, expected ' . 'Differential Revision.', $operation->getObjectPHID()));
     }
     $target = $operation->getRepositoryTarget();
     list($type, $name) = explode(':', $target, 2);
     switch ($type) {
         case 'branch':
             $push_dst = 'refs/heads/' . $name;
             break;
         default:
             throw new Exception(pht('Unknown repository operation target type "%s" (in target "%s").', $type, $target));
     }
     $committer_info = $this->getCommitterInfo($operation);
     // NOTE: We're doing this commit with "-F -" so we don't run into trouble
     // with enormous commit messages which might otherwise exceed the maximum
     // size of a command.
     $future = $interface->getExecFuture('git -c user.name=%s -c user.email=%s commit --author %s -F - --', $committer_info['name'], $committer_info['email'], "{$author_name} <{$author_email}>");
     $future->write($commit_message)->resolvex();
     $interface->execx('git push origin -- %s:%s', 'HEAD', $push_dst);
 }
 private function buildRepositoryMap(DrydockRepositoryOperation $operation)
 {
     $repository = $operation->getRepository();
     $target = $operation->getRepositoryTarget();
     list($type, $name) = explode(':', $target, 2);
     switch ($type) {
         case 'branch':
             $spec = array('branch' => $name);
             break;
         case 'none':
             $spec = array();
             break;
         default:
             throw new Exception(pht('Unknown repository operation target type "%s" (in target "%s").', $type, $target));
     }
     $spec['merges'] = $operation->getWorkingCopyMerges();
     $map = array();
     $map[$repository->getCloneName()] = array('phid' => $repository->getPHID(), 'default' => true) + $spec;
     return $map;
 }