[ Index ] |
PHP Cross Reference of Phabricator |
[Summary view] [Print] [Text view]
1 <?php 2 3 final class DiffusionSSHMercurialServeWorkflow 4 extends DiffusionSSHMercurialWorkflow { 5 6 protected $didSeeWrite; 7 8 public function didConstruct() { 9 $this->setName('hg'); 10 $this->setArguments( 11 array( 12 array( 13 'name' => 'repository', 14 'short' => 'R', 15 'param' => 'repo', 16 ), 17 array( 18 'name' => 'stdio', 19 ), 20 array( 21 'name' => 'command', 22 'wildcard' => true, 23 ), 24 )); 25 } 26 27 protected function executeRepositoryOperations() { 28 $args = $this->getArgs(); 29 $path = $args->getArg('repository'); 30 $repository = $this->loadRepository($path); 31 32 $args = $this->getArgs(); 33 34 if (!$args->getArg('stdio')) { 35 throw new Exception('Expected `hg ... --stdio`!'); 36 } 37 38 if ($args->getArg('command') !== array('serve')) { 39 throw new Exception('Expected `hg ... serve`!'); 40 } 41 42 $command = csprintf('hg -R %s serve --stdio', $repository->getLocalPath()); 43 $command = PhabricatorDaemon::sudoCommandAsDaemonUser($command); 44 45 $future = id(new ExecFuture('%C', $command)) 46 ->setEnv($this->getEnvironment()); 47 48 $io_channel = $this->getIOChannel(); 49 $protocol_channel = new DiffusionSSHMercurialWireClientProtocolChannel( 50 $io_channel); 51 52 $err = id($this->newPassthruCommand()) 53 ->setIOChannel($protocol_channel) 54 ->setCommandChannelFromExecFuture($future) 55 ->setWillWriteCallback(array($this, 'willWriteMessageCallback')) 56 ->execute(); 57 58 // TODO: It's apparently technically possible to communicate errors to 59 // Mercurial over SSH by writing a special "\n<error>\n-\n" string. However, 60 // my attempt to implement that resulted in Mercurial closing the socket and 61 // then hanging, without showing the error. This might be an issue on our 62 // side (we need to close our half of the socket?), or maybe the code 63 // for this in Mercurial doesn't actually work, or maybe something else 64 // is afoot. At some point, we should look into doing this more cleanly. 65 // For now, when we, e.g., reject writes for policy reasons, the user will 66 // see "abort: unexpected response: empty string" after the diagnostically 67 // useful, e.g., "remote: This repository is read-only over SSH." message. 68 69 if (!$err && $this->didSeeWrite) { 70 $repository->writeStatusMessage( 71 PhabricatorRepositoryStatusMessage::TYPE_NEEDS_UPDATE, 72 PhabricatorRepositoryStatusMessage::CODE_OKAY); 73 } 74 75 return $err; 76 } 77 78 public function willWriteMessageCallback( 79 PhabricatorSSHPassthruCommand $command, 80 $message) { 81 82 $command = $message['command']; 83 84 // Check if this is a readonly command. 85 86 $is_readonly = false; 87 if ($command == 'batch') { 88 $cmds = idx($message['arguments'], 'cmds'); 89 if (DiffusionMercurialWireProtocol::isReadOnlyBatchCommand($cmds)) { 90 $is_readonly = true; 91 } 92 } else if (DiffusionMercurialWireProtocol::isReadOnlyCommand($command)) { 93 $is_readonly = true; 94 } 95 96 if (!$is_readonly) { 97 $this->requireWriteAccess(); 98 $this->didSeeWrite = true; 99 } 100 101 // If we're good, return the raw message data. 102 return $message['raw']; 103 } 104 105 }
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 |