@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 138 lines 3.7 kB view raw
1<?php 2 3final class DiffusionGitReceivePackSSHWorkflow extends DiffusionGitSSHWorkflow { 4 5 protected function didConstruct() { 6 $this->setName('git-receive-pack'); 7 $this->setArguments( 8 array( 9 array( 10 'name' => 'dir', 11 'wildcard' => true, 12 ), 13 )); 14 } 15 16 protected function executeRepositoryOperations() { 17 // This is a write, and must have write access. 18 $this->requireWriteAccess(); 19 20 $is_proxy = $this->shouldProxy(); 21 if ($is_proxy) { 22 return $this->executeRepositoryProxyOperations($for_write = true); 23 } 24 25 $host_wait_start = microtime(true); 26 27 $repository = $this->getRepository(); 28 $viewer = $this->getSSHUser(); 29 $device = AlmanacKeys::getLiveDevice(); 30 31 $cluster_engine = id(new DiffusionRepositoryClusterEngine()) 32 ->setViewer($viewer) 33 ->setRepository($repository) 34 ->setLog($this); 35 36 $command = csprintf('git-receive-pack %s', $repository->getLocalPath()); 37 $cluster_engine->synchronizeWorkingCopyBeforeWrite(); 38 39 if ($device) { 40 $this->writeClusterEngineLogMessage( 41 pht( 42 "# Ready to receive on cluster host \"%s\".\n", 43 $device->getName())); 44 } 45 46 $log = $this->newProtocolLog($is_proxy); 47 if ($log) { 48 $this->setProtocolLog($log); 49 $log->didStartSession($command); 50 } 51 52 $caught = null; 53 try { 54 $err = $this->executeRepositoryCommand($command); 55 } catch (Exception $ex) { 56 $caught = $ex; 57 } 58 59 if ($log) { 60 $log->didEndSession(); 61 } 62 63 // We've committed the write (or rejected it), so we can release the lock 64 // without waiting for the client to receive the acknowledgement. 65 $cluster_engine->synchronizeWorkingCopyAfterWrite(); 66 67 if ($caught) { 68 throw $caught; 69 } 70 71 if (!$err) { 72 $this->waitForGitClient(); 73 74 // When a repository is clustered, we reach this cleanup code on both 75 // the proxy and the actual final endpoint node. Don't do more cleanup 76 // or logging than we need to. 77 $repository->writeStatusMessage( 78 PhabricatorRepositoryStatusMessage::TYPE_NEEDS_UPDATE, 79 PhabricatorRepositoryStatusMessage::CODE_OKAY); 80 81 $host_wait_end = microtime(true); 82 83 $this->updatePushLogWithTimingInformation( 84 $this->getClusterEngineLogProperty('writeWait'), 85 $this->getClusterEngineLogProperty('readWait'), 86 ($host_wait_end - $host_wait_start)); 87 } 88 89 return $err; 90 } 91 92 private function executeRepositoryCommand($command) { 93 $repository = $this->getRepository(); 94 $command = PhabricatorDaemon::sudoCommandAsDaemonUser($command); 95 96 $future = id(new ExecFuture('%C', $command)) 97 ->setEnv($this->getEnvironment()); 98 99 return $this->newPassthruCommand() 100 ->setIOChannel($this->getIOChannel()) 101 ->setCommandChannelFromExecFuture($future) 102 ->execute(); 103 } 104 105 private function updatePushLogWithTimingInformation( 106 $write_wait, 107 $read_wait, 108 $host_wait) { 109 110 if ($write_wait !== null) { 111 $write_wait = (int)(1000000 * $write_wait); 112 } 113 114 if ($read_wait !== null) { 115 $read_wait = (int)(1000000 * $read_wait); 116 } 117 118 if ($host_wait !== null) { 119 $host_wait = (int)(1000000 * $host_wait); 120 } 121 122 $identifier = $this->getRequestIdentifier(); 123 124 $event = new PhabricatorRepositoryPushEvent(); 125 $conn = $event->establishConnection('w'); 126 127 queryfx( 128 $conn, 129 'UPDATE %T SET writeWait = %nd, readWait = %nd, hostWait = %nd 130 WHERE requestIdentifier = %s', 131 $event->getTableName(), 132 $write_wait, 133 $read_wait, 134 $host_wait, 135 $identifier); 136 } 137 138}