@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
at upstream/main 117 lines 3.2 kB view raw
1<?php 2 3final class DiffusionMercurialServeSSHWorkflow 4 extends DiffusionMercurialSSHWorkflow { 5 6 protected $didSeeWrite; 7 8 protected 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 identifyRepository() { 28 $args = $this->getArgs(); 29 $path = $args->getArg('repository'); 30 return $this->loadRepositoryWithPath( 31 $path, 32 PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL); 33 } 34 35 protected function executeRepositoryOperations() { 36 $repository = $this->getRepository(); 37 $args = $this->getArgs(); 38 39 if (!$args->getArg('stdio')) { 40 throw new Exception(pht('Expected `%s`!', 'hg ... --stdio')); 41 } 42 43 if ($args->getArg('command') !== array('serve')) { 44 throw new Exception(pht('Expected `%s`!', 'hg ... serve')); 45 } 46 47 if ($this->shouldProxy()) { 48 // NOTE: For now, we're always requesting a writable node. The request 49 // may not actually need one, but we can't currently determine whether 50 // it is read-only or not at this phase of evaluation. 51 $command = $this->getProxyCommand(true); 52 } else { 53 $command = csprintf( 54 'hg -R %s serve --stdio', 55 $repository->getLocalPath()); 56 } 57 $command = PhabricatorDaemon::sudoCommandAsDaemonUser($command); 58 59 $future = id(new ExecFuture('%C', $command)) 60 ->setEnv($this->getEnvironment()); 61 62 $io_channel = $this->getIOChannel(); 63 $protocol_channel = new DiffusionMercurialWireClientSSHProtocolChannel( 64 $io_channel); 65 66 $err = id($this->newPassthruCommand()) 67 ->setIOChannel($protocol_channel) 68 ->setCommandChannelFromExecFuture($future) 69 ->setWillWriteCallback(array($this, 'willWriteMessageCallback')) 70 ->execute(); 71 72 if (!$err && $this->didSeeWrite) { 73 $repository->writeStatusMessage( 74 PhabricatorRepositoryStatusMessage::TYPE_NEEDS_UPDATE, 75 PhabricatorRepositoryStatusMessage::CODE_OKAY); 76 } 77 78 return $err; 79 } 80 81 public function willWriteMessageCallback( 82 PhabricatorSSHPassthruCommand $command, 83 $message) { 84 85 $command = $message['command']; 86 87 // Check if this is a readonly command. 88 89 $is_readonly = false; 90 if ($command == 'batch') { 91 $cmds = idx($message['arguments'], 'cmds'); 92 if (DiffusionMercurialWireProtocol::isReadOnlyBatchCommand($cmds)) { 93 $is_readonly = true; 94 } 95 } else if (DiffusionMercurialWireProtocol::isReadOnlyCommand($command)) { 96 $is_readonly = true; 97 } 98 99 if (!$is_readonly) { 100 $this->requireWriteAccess(); 101 $this->didSeeWrite = true; 102 } 103 104 return $message['raw']; 105 } 106 107 protected function raiseWrongVCSException( 108 PhabricatorRepository $repository) { 109 throw new Exception( 110 pht( 111 'This repository ("%s") is not a Mercurial repository. Use "%s" to '. 112 'interact with this repository.', 113 $repository->getDisplayName(), 114 $repository->getVersionControlSystem())); 115 } 116 117}