Changeset View
Standalone View
src/applications/drydock/blueprint/DrydockWorkingCopyBlueprintImplementation.php
Show First 20 Lines • Show All 167 Lines • ▼ Show 20 Lines | public function activateResource( | ||||
$interface = $lease->getInterface($command_type); | $interface = $lease->getInterface($command_type); | ||||
// TODO: Make this configurable. | // TODO: Make this configurable. | ||||
$resource_id = $resource->getID(); | $resource_id = $resource->getID(); | ||||
$root = "/var/drydock/workingcopy-{$resource_id}"; | $root = "/var/drydock/workingcopy-{$resource_id}"; | ||||
$map = $resource->getAttribute('repositories.map'); | $map = $resource->getAttribute('repositories.map'); | ||||
$futures = array(); | |||||
$repositories = $this->loadRepositories(ipull($map, 'phid')); | $repositories = $this->loadRepositories(ipull($map, 'phid')); | ||||
foreach ($map as $directory => $spec) { | foreach ($map as $directory => $spec) { | ||||
// TODO: Validate directory isn't goofy like "/etc" or "../../lol" | // TODO: Validate directory isn't goofy like "/etc" or "../../lol" | ||||
// somewhere? | // somewhere? | ||||
$repository = $repositories[$spec['phid']]; | $repository = $repositories[$spec['phid']]; | ||||
$path = "{$root}/repo/{$directory}/"; | $path = "{$root}/repo/{$directory}/"; | ||||
// TODO: Run these in parallel? | $future = $interface->getExecFuture( | ||||
$interface->execx( | |||||
'git clone -- %s %s', | 'git clone -- %s %s', | ||||
(string)$repository->getCloneURIObject(), | (string)$repository->getCloneURIObject(), | ||||
$path); | $path); | ||||
$future->setTimeout($repository->getCopyTimeLimit()); | |||||
$futures[$directory] = $future; | |||||
amckinley: Could this result in a collision? Or are these directories already guaranteed to be unique? | |||||
Done Inline ActionsThe directories are "sort of guaranteed unique for our purposes" if we get this far since they're already keys in $map. They're originally derived elsewhere from $repository->getCloneName(), which is not always guaranteed to be unique, but I think that's more of an issue for a higher-level layer to care about. We aren't creating any new problems by doing this, at least. epriestley: The directories are "sort of guaranteed unique for our purposes" if we get this far since… | |||||
} | |||||
foreach (new FutureIterator($futures) as $key => $future) { | |||||
$future->resolvex(); | |||||
} | } | ||||
$resource | $resource | ||||
->setAttribute('workingcopy.root', $root) | ->setAttribute('workingcopy.root', $root) | ||||
->activateResource(); | ->activateResource(); | ||||
} | } | ||||
public function destroyResource( | public function destroyResource( | ||||
Show All 38 Lines | public function activateLease( | ||||
$host_lease = $this->loadHostLease($resource); | $host_lease = $this->loadHostLease($resource); | ||||
$command_type = DrydockCommandInterface::INTERFACE_TYPE; | $command_type = DrydockCommandInterface::INTERFACE_TYPE; | ||||
$interface = $host_lease->getInterface($command_type); | $interface = $host_lease->getInterface($command_type); | ||||
$map = $lease->getAttribute('repositories.map'); | $map = $lease->getAttribute('repositories.map'); | ||||
$root = $resource->getAttribute('workingcopy.root'); | $root = $resource->getAttribute('workingcopy.root'); | ||||
$repositories = $this->loadRepositories(ipull($map, 'phid')); | |||||
$default = null; | $default = null; | ||||
foreach ($map as $directory => $spec) { | foreach ($map as $directory => $spec) { | ||||
$repository = $repositories[$spec['phid']]; | |||||
$interface->pushWorkingDirectory("{$root}/repo/{$directory}/"); | $interface->pushWorkingDirectory("{$root}/repo/{$directory}/"); | ||||
$cmd = array(); | $cmd = array(); | ||||
$arg = array(); | $arg = array(); | ||||
$cmd[] = 'git clean -d --force'; | $cmd[] = 'git clean -d --force'; | ||||
$cmd[] = 'git fetch'; | $cmd[] = 'git fetch'; | ||||
Show All 13 Lines | foreach ($map as $directory => $spec) { | ||||
} else if ($branch !== null) { | } else if ($branch !== null) { | ||||
$cmd[] = 'git checkout %s --'; | $cmd[] = 'git checkout %s --'; | ||||
$arg[] = $branch; | $arg[] = $branch; | ||||
$cmd[] = 'git reset --hard origin/%s'; | $cmd[] = 'git reset --hard origin/%s'; | ||||
$arg[] = $branch; | $arg[] = $branch; | ||||
} | } | ||||
$this->execxv($interface, $cmd, $arg); | $this->newExecvFuture($interface, $cmd, $arg) | ||||
->setTimeout($repository->getCopyTimeLimit()) | |||||
->resolvex(); | |||||
Not Done Inline ActionsWe don't want to also do these in parallel like activateResource() now does? amckinley: We don't want to also do these in parallel like `activateResource()` now does? | |||||
Done Inline ActionsIt would probably be slightly preferable, but since the two commands have to go in sequence it would be a bigger rework than the clone rework above. In practice, although we use this stuff (multiple working copies: libphutil/ + arcanist/ + phabricator/) other projects normally don't so the benefit is likely minimal. I reworked above but not here just out of guesses about patch size and comfort with how thoroughly I was testing. I think this stuff is likely to get more significant work in some future iteration, e.g. see T9492. epriestley: It would probably be slightly preferable, but since the two commands have to go in sequence it… | |||||
if (idx($spec, 'default')) { | if (idx($spec, 'default')) { | ||||
$default = $directory; | $default = $directory; | ||||
} | } | ||||
// If we're fetching a ref from a remote, do that separately so we can | // If we're fetching a ref from a remote, do that separately so we can | ||||
// raise a more tailored error. | // raise a more tailored error. | ||||
if ($ref) { | if ($ref) { | ||||
$cmd = array(); | $cmd = array(); | ||||
$arg = array(); | $arg = array(); | ||||
$ref_uri = $ref['uri']; | $ref_uri = $ref['uri']; | ||||
$ref_ref = $ref['ref']; | $ref_ref = $ref['ref']; | ||||
$cmd[] = 'git fetch --no-tags -- %s +%s:%s'; | $cmd[] = 'git fetch --no-tags -- %s +%s:%s'; | ||||
$arg[] = $ref_uri; | $arg[] = $ref_uri; | ||||
$arg[] = $ref_ref; | $arg[] = $ref_ref; | ||||
$arg[] = $ref_ref; | $arg[] = $ref_ref; | ||||
$cmd[] = 'git checkout %s --'; | $cmd[] = 'git checkout %s --'; | ||||
$arg[] = $ref_ref; | $arg[] = $ref_ref; | ||||
try { | try { | ||||
$this->execxv($interface, $cmd, $arg); | $this->newExecvFuture($interface, $cmd, $arg) | ||||
->setTimeout($repository->getCopyTimeLimit()) | |||||
->resolvex(); | |||||
} catch (CommandException $ex) { | } catch (CommandException $ex) { | ||||
$display_command = csprintf( | $display_command = csprintf( | ||||
'git fetch %R %R', | 'git fetch %R %R', | ||||
$ref_uri, | $ref_uri, | ||||
$ref_ref); | $ref_ref); | ||||
$error = DrydockCommandError::newFromCommandException($ex) | $error = DrydockCommandError::newFromCommandException($ex) | ||||
->setPhase(self::PHASE_REMOTEFETCH) | ->setPhase(self::PHASE_REMOTEFETCH) | ||||
▲ Show 20 Lines • Show All 197 Lines • ▼ Show 20 Lines | final class DrydockWorkingCopyBlueprintImplementation | ||||
public function getCommandError(DrydockLease $lease) { | public function getCommandError(DrydockLease $lease) { | ||||
return $lease->getAttribute('workingcopy.vcs.error'); | return $lease->getAttribute('workingcopy.vcs.error'); | ||||
} | } | ||||
private function execxv( | private function execxv( | ||||
DrydockCommandInterface $interface, | DrydockCommandInterface $interface, | ||||
array $commands, | array $commands, | ||||
array $arguments) { | array $arguments) { | ||||
return $this->newExecvFuture($interface, $commands, $arguments)->resolvex(); | |||||
} | |||||
private function newExecvFuture( | |||||
DrydockCommandInterface $interface, | |||||
array $commands, | |||||
array $arguments) { | |||||
$commands = implode(' && ', $commands); | $commands = implode(' && ', $commands); | ||||
$argv = array_merge(array($commands), $arguments); | $argv = array_merge(array($commands), $arguments); | ||||
return call_user_func_array(array($interface, 'execx'), $argv); | return call_user_func_array(array($interface, 'getExecFuture'), $argv); | ||||
} | } | ||||
} | } |
Could this result in a collision? Or are these directories already guaranteed to be unique?