3 final class PhabricatorRepositoryManagementClusterizeWorkflow
4 extends PhabricatorRepositoryManagementWorkflow
{
6 protected function didConstruct() {
8 ->setName('clusterize')
9 ->setExamples('**clusterize** [options] __repository__ ...')
11 pht('Convert existing repositories into cluster repositories.'))
18 'Cluster repository service in Almanac to move repositories '.
22 'name' => 'remove-service',
23 'help' => pht('Take repositories out of a cluster.'),
26 'name' => 'repositories',
32 public function execute(PhutilArgumentParser
$args) {
33 $viewer = $this->getViewer();
35 $repositories = $this->loadRepositories($args, 'repositories');
37 throw new PhutilArgumentUsageException(
38 pht('Specify one or more repositories to clusterize.'));
41 $service_name = $args->getArg('service');
42 $remove_service = $args->getArg('remove-service');
44 if ($remove_service && $service_name) {
45 throw new PhutilArgumentUsageException(
46 pht('Specify --service or --remove-service, but not both.'));
49 if (!$service_name && !$remove_service) {
50 throw new PhutilArgumentUsageException(
51 pht('Specify --service or --remove-service.'));
54 if ($remove_service) {
57 $service = id(new AlmanacServiceQuery())
59 ->withNames(array($service_name))
62 AlmanacClusterRepositoryServiceType
::SERVICETYPE
,
64 ->needActiveBindings(true)
67 throw new PhutilArgumentUsageException(
69 'No repository service "%s" exists.',
75 $service_phid = $service->getPHID();
77 $bindings = $service->getActiveBindings();
79 $unique_devices = array();
80 foreach ($bindings as $binding) {
81 $unique_devices[$binding->getDevicePHID()] = $binding->getDevice();
84 if (count($unique_devices) > 1) {
85 $device_names = mpull($unique_devices, 'getName');
87 echo id(new PhutilConsoleBlock())
90 'Service "%s" is actively bound to more than one device (%s).',
92 implode(', ', $device_names)))
95 'If you clusterize a repository onto this service it may be '.
96 'unclear which devices have up-to-date copies of the '.
97 'repository. If so, leader/follower ambiguity will freeze the '.
98 'repository. You may need to manually promote a device to '.
99 'unfreeze it. See "Ambiguous Leaders" in the documentation '.
101 ->drawConsoleString();
103 $prompt = pht('Continue anyway?');
104 if (!phutil_console_confirm($prompt)) {
105 throw new PhutilArgumentUsageException(
106 pht('User aborted the workflow.'));
110 $service_phid = null;
113 $content_source = $this->newContentSource();
114 $diffusion_phid = id(new PhabricatorDiffusionApplication())->getPHID();
116 foreach ($repositories as $repository) {
119 $xactions[] = id(new PhabricatorRepositoryTransaction())
120 ->setTransactionType(
121 PhabricatorRepositoryServiceTransaction
::TRANSACTIONTYPE
)
122 ->setNewValue($service_phid);
124 id(new PhabricatorRepositoryEditor())
126 ->setActingAsPHID($diffusion_phid)
127 ->setContentSource($content_source)
128 ->setContinueOnNoEffect(true)
129 ->setContinueOnMissingFields(true)
130 ->applyTransactions($repository, $xactions);
136 'Moved repository "%s" to cluster service "%s".',
137 $repository->getDisplayName(),
138 $service->getName()));
143 'Removed repository "%s" from cluster service.',
144 $repository->getDisplayName()));