diff --git a/src/applications/diffusion/conduit/DiffusionQueryConduitAPIMethod.php b/src/applications/diffusion/conduit/DiffusionQueryConduitAPIMethod.php --- a/src/applications/diffusion/conduit/DiffusionQueryConduitAPIMethod.php +++ b/src/applications/diffusion/conduit/DiffusionQueryConduitAPIMethod.php @@ -145,6 +145,12 @@ $this->setDiffusionRequest($drequest); + // TODO: Allow web UI queries opt out of this if they don't care about + // fetching the most up-to-date data? Synchronization can be slow, and a + // lot of web reads are probably fine if they're a few seconds out of + // date. + $repository->synchronizeWorkingCopyBeforeRead(); + return $this->getResult($request); } } diff --git a/src/applications/diffusion/controller/DiffusionServeController.php b/src/applications/diffusion/controller/DiffusionServeController.php --- a/src/applications/diffusion/controller/DiffusionServeController.php +++ b/src/applications/diffusion/controller/DiffusionServeController.php @@ -538,10 +538,35 @@ $command = csprintf('%s', $bin); $command = PhabricatorDaemon::sudoCommandAsDaemonUser($command); - list($err, $stdout, $stderr) = id(new ExecFuture('%C', $command)) - ->setEnv($env, true) - ->write($input) - ->resolve(); + $unguarded = AphrontWriteGuard::beginScopedUnguardedWrites(); + + $did_write_lock = false; + if ($this->isReadOnlyRequest($repository)) { + $repository->synchronizeWorkingCopyBeforeRead(); + } else { + $did_write_lock = true; + $repository->synchronizeWorkingCopyBeforeWrite($viewer); + } + + $caught = null; + try { + list($err, $stdout, $stderr) = id(new ExecFuture('%C', $command)) + ->setEnv($env, true) + ->write($input) + ->resolve(); + } catch (Exception $ex) { + $caught = $ex; + } + + if ($did_write_lock) { + $repository->synchronizeWorkingCopyAfterWrite(); + } + + unset($unguarded); + + if ($caught) { + throw $caught; + } if ($err) { if ($this->isValidGitShallowCloneResponse($stdout, $stderr)) { diff --git a/src/applications/diffusion/protocol/DiffusionCommandEngine.php b/src/applications/diffusion/protocol/DiffusionCommandEngine.php --- a/src/applications/diffusion/protocol/DiffusionCommandEngine.php +++ b/src/applications/diffusion/protocol/DiffusionCommandEngine.php @@ -8,6 +8,7 @@ private $argv; private $passthru; private $connectAsDevice; + private $sudoAsDaemon; public static function newCommandEngine(PhabricatorRepository $repository) { $engines = self::newCommandEngines(); @@ -92,10 +93,25 @@ return $this->connectAsDevice; } + public function setSudoAsDaemon($sudo_as_daemon) { + $this->sudoAsDaemon = $sudo_as_daemon; + return $this; + } + + public function getSudoAsDaemon() { + return $this->sudoAsDaemon; + } + public function newFuture() { $argv = $this->newCommandArgv(); $env = $this->newCommandEnvironment(); + if ($this->getSudoAsDaemon()) { + $command = call_user_func_array('csprintf', $argv); + $command = PhabricatorDaemon::sudoCommandAsDaemonUser($command); + $argv = array('%C', $command); + } + if ($this->getPassthru()) { $future = newv('PhutilExecPassthru', $argv); } else { diff --git a/src/applications/repository/storage/PhabricatorRepository.php b/src/applications/repository/storage/PhabricatorRepository.php --- a/src/applications/repository/storage/PhabricatorRepository.php +++ b/src/applications/repository/storage/PhabricatorRepository.php @@ -1954,6 +1954,10 @@ $uris = array(); foreach ($bindings as $binding) { + if ($binding->getIsDisabled()) { + continue; + } + $iface = $binding->getInterface(); // If we're never proxying this and it's locally satisfiable, return @@ -2197,11 +2201,6 @@ private function shouldEnableSynchronization() { - $device = AlmanacKeys::getLiveDevice(); - if (!$device) { - return false; - } - $service_phid = $this->getAlmanacServicePHID(); if (!$service_phid) { return false; @@ -2212,6 +2211,18 @@ return false; } + // TODO: It may eventually make sense to try to version and synchronize + // observed repositories (so that daemons don't do reads against out-of + // date hosts), but don't bother for now. + if (!$this->isHosted()) { + return false; + } + + $device = AlmanacKeys::getLiveDevice(); + if (!$device) { + return false; + } + return true; } @@ -2451,6 +2462,7 @@ $future = DiffusionCommandEngine::newCommandEngine($this) ->setArgv($argv) ->setConnectAsDevice(true) + ->setSudoAsDaemon(true) ->setProtocol($fetch_uri->getProtocol()) ->newFuture();