3 final class DiffusionRepositoryEditEngine
4 extends PhabricatorEditEngine
{
6 const ENGINECONST
= 'diffusion.repository';
8 private $versionControlSystem;
10 public function setVersionControlSystem($version_control_system) {
11 $this->versionControlSystem
= $version_control_system;
15 public function getVersionControlSystem() {
16 return $this->versionControlSystem
;
19 public function isEngineConfigurable() {
23 public function isDefaultQuickCreateEngine() {
27 public function getQuickCreateOrderVector() {
28 return id(new PhutilSortVector())->addInt(300);
31 public function getEngineName() {
32 return pht('Repositories');
35 public function getSummaryHeader() {
36 return pht('Edit Repositories');
39 public function getSummaryText() {
40 return pht('Creates and edits repositories.');
43 public function getEngineApplicationClass() {
44 return 'PhabricatorDiffusionApplication';
47 protected function newEditableObject() {
48 $viewer = $this->getViewer();
49 $repository = PhabricatorRepository
::initializeNewRepository($viewer);
51 $repository->setDetail('newly-initialized', true);
53 $vcs = $this->getVersionControlSystem();
55 $repository->setVersionControlSystem($vcs);
58 // Pick a random open service to allocate this repository on, if any exist.
59 // If there are no services, we aren't in cluster mode and will allocate
60 // locally. If there are services but none permit allocations, we fail.
62 // Eventually we can make this more flexible, but this rule is a reasonable
63 // starting point as we begin to deploy cluster services.
65 $services = id(new AlmanacServiceQuery())
66 ->setViewer(PhabricatorUser
::getOmnipotentUser())
69 AlmanacClusterRepositoryServiceType
::SERVICETYPE
,
71 ->needProperties(true)
74 // Filter out services which do not permit new allocations.
75 foreach ($services as $key => $possible_service) {
76 if ($possible_service->getAlmanacPropertyValue('closed')) {
77 unset($services[$key]);
84 'This install is configured in cluster mode, but all available '.
85 'repository cluster services are closed to new allocations. '.
86 'At least one service must be open to allow new allocations to '.
91 $service = head($services);
93 $repository->setAlmanacServicePHID($service->getPHID());
99 protected function newObjectQuery() {
100 return new PhabricatorRepositoryQuery();
103 protected function getObjectCreateTitleText($object) {
104 return pht('Create Repository');
107 protected function getObjectCreateButtonText($object) {
108 return pht('Create Repository');
111 protected function getObjectEditTitleText($object) {
112 return pht('Edit Repository: %s', $object->getName());
115 protected function getObjectEditShortText($object) {
116 return $object->getDisplayName();
119 protected function getObjectCreateShortText() {
120 return pht('Create Repository');
123 protected function getObjectName() {
124 return pht('Repository');
127 protected function getObjectViewURI($object) {
128 return $object->getPathURI('manage/');
131 protected function getCreateNewObjectPolicy() {
132 return $this->getApplication()->getPolicy(
133 DiffusionCreateRepositoriesCapability
::CAPABILITY
);
136 protected function newPages($object) {
137 $panels = DiffusionRepositoryManagementPanel
::getAllPanels();
141 foreach ($panels as $panel_key => $panel) {
142 $panel->setRepository($object);
144 $uris[$panel_key] = $panel->getPanelURI();
146 $page = $panel->newEditEnginePage();
153 $basics_key = DiffusionRepositoryBasicsManagementPanel
::PANELKEY
;
154 $basics_uri = $uris[$basics_key];
157 id(new PhabricatorEditPage())
159 ->setLabel(pht('Text Encoding'))
160 ->setViewURI($basics_uri)
165 id(new PhabricatorEditPage())
166 ->setKey('extensions')
167 ->setLabel(pht('Extensions'))
168 ->setIsDefault(true),
171 foreach ($more_pages as $page) {
178 protected function willConfigureFields($object, array $fields) {
179 // Change the default field order so related fields are adjacent.
181 'policy.edit' => array('policy.push'),
185 foreach ($fields as $key => $value) {
186 $result[$key] = $value;
188 if (!isset($after[$key])) {
192 foreach ($after[$key] as $next_key) {
193 if (!isset($fields[$next_key])) {
197 unset($result[$next_key]);
198 $result[$next_key] = $fields[$next_key];
199 unset($fields[$next_key]);
207 protected function buildCustomEditFields($object) {
208 $viewer = $this->getViewer();
210 $policies = id(new PhabricatorPolicyQuery())
215 $fetch_value = $object->getFetchRules();
216 $track_value = $object->getTrackOnlyRules();
217 $permanent_value = $object->getPermanentRefRules();
219 $automation_instructions = pht(
220 "Configure **Repository Automation** to allow Phabricator to ".
221 "write to this repository.".
223 "IMPORTANT: This feature is new, experimental, and not supported. ".
224 "Use it at your own risk.");
226 $staging_instructions = pht(
227 "To make it easier to run integration tests and builds on code ".
228 "under review, you can configure a **Staging Area**. When `arc` ".
229 "creates a diff, it will push a copy of the changes to the ".
230 "configured staging area with a corresponding tag.".
232 "IMPORTANT: This feature is new, experimental, and not supported. ".
233 "Use it at your own risk.");
235 $subpath_instructions = pht(
236 'If you want to import only part of a repository, like `trunk/`, '.
237 'you can set a path in **Import Only**. Phabricator will ignore '.
238 'commits which do not affect this path.');
240 $filesize_warning = null;
241 if ($object->isGit()) {
242 $git_binary = PhutilBinaryAnalyzer
::getForBinary('git');
243 $git_version = $git_binary->getBinaryVersion();
244 $filesize_version = '1.8.4';
245 if (version_compare($git_version, $filesize_version, '<')) {
246 $filesize_warning = pht(
247 '(WARNING) {icon exclamation-triangle} The version of "git" ("%s") '.
248 'installed on this server does not support '.
249 '"--batch-check=<format>", a feature required to enforce filesize '.
250 'limits. Upgrade to "git" %s or newer to use this feature.',
256 $track_instructions = pht(
257 'WARNING: The "Track Only" feature is deprecated. Use "Fetch Refs" '.
258 'and "Permanent Refs" instead. This feature will be removed in a '.
259 'future version of Phabricator.');
262 id(new PhabricatorSelectEditField())
264 ->setLabel(pht('Version Control System'))
265 ->setTransactionType(
266 PhabricatorRepositoryVCSTransaction
::TRANSACTIONTYPE
)
267 ->setIsFormField(false)
268 ->setIsCopyable(true)
269 ->setOptions(PhabricatorRepositoryType
::getAllRepositoryTypes())
270 ->setDescription(pht('Underlying repository version control system.'))
271 ->setConduitDescription(
273 'Choose which version control system to use when creating a '.
275 ->setConduitTypeDescription(pht('Version control system selection.'))
276 ->setValue($object->getVersionControlSystem()),
277 id(new PhabricatorTextEditField())
279 ->setLabel(pht('Name'))
280 ->setIsRequired(true)
281 ->setTransactionType(
282 PhabricatorRepositoryNameTransaction
::TRANSACTIONTYPE
)
283 ->setDescription(pht('The repository name.'))
284 ->setConduitDescription(pht('Rename the repository.'))
285 ->setConduitTypeDescription(pht('New repository name.'))
286 ->setValue($object->getName()),
287 id(new PhabricatorTextEditField())
289 ->setLabel(pht('Callsign'))
290 ->setTransactionType(
291 PhabricatorRepositoryCallsignTransaction
::TRANSACTIONTYPE
)
292 ->setDescription(pht('The repository callsign.'))
293 ->setConduitDescription(pht('Change the repository callsign.'))
294 ->setConduitTypeDescription(pht('New repository callsign.'))
295 ->setValue($object->getCallsign()),
296 id(new PhabricatorTextEditField())
297 ->setKey('shortName')
298 ->setLabel(pht('Short Name'))
299 ->setTransactionType(
300 PhabricatorRepositorySlugTransaction
::TRANSACTIONTYPE
)
301 ->setDescription(pht('Short, unique repository name.'))
302 ->setConduitDescription(pht('Change the repository short name.'))
303 ->setConduitTypeDescription(pht('New short name for the repository.'))
304 ->setValue($object->getRepositorySlug()),
305 id(new PhabricatorRemarkupEditField())
306 ->setKey('description')
307 ->setLabel(pht('Description'))
308 ->setTransactionType(
309 PhabricatorRepositoryDescriptionTransaction
::TRANSACTIONTYPE
)
310 ->setDescription(pht('Repository description.'))
311 ->setConduitDescription(pht('Change the repository description.'))
312 ->setConduitTypeDescription(pht('New repository description.'))
313 ->setValue($object->getDetail('description')),
314 id(new PhabricatorTextEditField())
316 ->setLabel(pht('Text Encoding'))
317 ->setIsCopyable(true)
318 ->setTransactionType(
319 PhabricatorRepositoryEncodingTransaction
::TRANSACTIONTYPE
)
320 ->setDescription(pht('Default text encoding.'))
321 ->setConduitDescription(pht('Change the default text encoding.'))
322 ->setConduitTypeDescription(pht('New text encoding.'))
323 ->setValue($object->getDetail('encoding')),
324 id(new PhabricatorBoolEditField())
325 ->setKey('allowDangerousChanges')
326 ->setLabel(pht('Allow Dangerous Changes'))
327 ->setIsCopyable(true)
328 ->setIsFormField(false)
330 pht('Prevent Dangerous Changes'),
331 pht('Allow Dangerous Changes'))
332 ->setTransactionType(
333 PhabricatorRepositoryDangerousTransaction
::TRANSACTIONTYPE
)
334 ->setDescription(pht('Permit dangerous changes to be made.'))
335 ->setConduitDescription(pht('Allow or prevent dangerous changes.'))
336 ->setConduitTypeDescription(pht('New protection setting.'))
337 ->setValue($object->shouldAllowDangerousChanges()),
338 id(new PhabricatorBoolEditField())
339 ->setKey('allowEnormousChanges')
340 ->setLabel(pht('Allow Enormous Changes'))
341 ->setIsCopyable(true)
342 ->setIsFormField(false)
344 pht('Prevent Enormous Changes'),
345 pht('Allow Enormous Changes'))
346 ->setTransactionType(
347 PhabricatorRepositoryEnormousTransaction
::TRANSACTIONTYPE
)
348 ->setDescription(pht('Permit enormous changes to be made.'))
349 ->setConduitDescription(pht('Allow or prevent enormous changes.'))
350 ->setConduitTypeDescription(pht('New protection setting.'))
351 ->setValue($object->shouldAllowEnormousChanges()),
352 id(new PhabricatorSelectEditField())
354 ->setLabel(pht('Status'))
355 ->setTransactionType(
356 PhabricatorRepositoryActivateTransaction
::TRANSACTIONTYPE
)
357 ->setIsFormField(false)
358 ->setOptions(PhabricatorRepository
::getStatusNameMap())
359 ->setDescription(pht('Active or inactive status.'))
360 ->setConduitDescription(pht('Active or deactivate the repository.'))
361 ->setConduitTypeDescription(pht('New repository status.'))
362 ->setValue($object->getStatus()),
363 id(new PhabricatorTextEditField())
364 ->setKey('defaultBranch')
365 ->setLabel(pht('Default Branch'))
366 ->setTransactionType(
367 PhabricatorRepositoryDefaultBranchTransaction
::TRANSACTIONTYPE
)
368 ->setIsCopyable(true)
369 ->setDescription(pht('Default branch name.'))
370 ->setConduitDescription(pht('Set the default branch name.'))
371 ->setConduitTypeDescription(pht('New default branch name.'))
372 ->setValue($object->getDetail('default-branch')),
373 id(new PhabricatorTextAreaEditField())
374 ->setIsStringList(true)
375 ->setKey('fetchRefs')
376 ->setLabel(pht('Fetch Refs'))
377 ->setTransactionType(
378 PhabricatorRepositoryFetchRefsTransaction
::TRANSACTIONTYPE
)
379 ->setIsCopyable(true)
380 ->setDescription(pht('Fetch only these refs.'))
381 ->setConduitDescription(pht('Set the fetched refs.'))
382 ->setConduitTypeDescription(pht('New fetched refs.'))
383 ->setValue($fetch_value),
384 id(new PhabricatorTextAreaEditField())
385 ->setIsStringList(true)
386 ->setKey('permanentRefs')
387 ->setLabel(pht('Permanent Refs'))
388 ->setTransactionType(
389 PhabricatorRepositoryPermanentRefsTransaction
::TRANSACTIONTYPE
)
390 ->setIsCopyable(true)
391 ->setDescription(pht('Only these refs are considered permanent.'))
392 ->setConduitDescription(pht('Set the permanent refs.'))
393 ->setConduitTypeDescription(pht('New permanent ref rules.'))
394 ->setValue($permanent_value),
395 id(new PhabricatorTextAreaEditField())
396 ->setIsStringList(true)
397 ->setKey('trackOnly')
398 ->setLabel(pht('Track Only'))
399 ->setTransactionType(
400 PhabricatorRepositoryTrackOnlyTransaction
::TRANSACTIONTYPE
)
401 ->setIsCopyable(true)
402 ->setControlInstructions($track_instructions)
403 ->setDescription(pht('Track only these branches.'))
404 ->setConduitDescription(pht('Set the tracked branches.'))
405 ->setConduitTypeDescription(pht('New tracked branches.'))
406 ->setValue($track_value),
407 id(new PhabricatorTextEditField())
408 ->setKey('importOnly')
409 ->setLabel(pht('Import Only'))
410 ->setTransactionType(
411 PhabricatorRepositorySVNSubpathTransaction
::TRANSACTIONTYPE
)
412 ->setIsCopyable(true)
413 ->setDescription(pht('Subpath to selectively import.'))
414 ->setConduitDescription(pht('Set the subpath to import.'))
415 ->setConduitTypeDescription(pht('New subpath to import.'))
416 ->setValue($object->getDetail('svn-subpath'))
417 ->setControlInstructions($subpath_instructions),
418 id(new PhabricatorTextEditField())
419 ->setKey('stagingAreaURI')
420 ->setLabel(pht('Staging Area URI'))
421 ->setTransactionType(
422 PhabricatorRepositoryStagingURITransaction
::TRANSACTIONTYPE
)
423 ->setIsCopyable(true)
424 ->setDescription(pht('Staging area URI.'))
425 ->setConduitDescription(pht('Set the staging area URI.'))
426 ->setConduitTypeDescription(pht('New staging area URI.'))
427 ->setValue($object->getStagingURI())
428 ->setControlInstructions($staging_instructions),
429 id(new PhabricatorDatasourceEditField())
430 ->setKey('automationBlueprintPHIDs')
431 ->setLabel(pht('Use Blueprints'))
432 ->setTransactionType(
433 PhabricatorRepositoryBlueprintsTransaction
::TRANSACTIONTYPE
)
434 ->setIsCopyable(true)
435 ->setDatasource(new DrydockBlueprintDatasource())
436 ->setDescription(pht('Automation blueprints.'))
437 ->setConduitDescription(pht('Change automation blueprints.'))
438 ->setConduitTypeDescription(pht('New blueprint PHIDs.'))
439 ->setValue($object->getAutomationBlueprintPHIDs())
440 ->setControlInstructions($automation_instructions),
441 id(new PhabricatorStringListEditField())
442 ->setKey('symbolLanguages')
443 ->setLabel(pht('Languages'))
444 ->setTransactionType(
445 PhabricatorRepositorySymbolLanguagesTransaction
::TRANSACTIONTYPE
)
446 ->setIsCopyable(true)
448 pht('Languages which define symbols in this repository.'))
449 ->setConduitDescription(
450 pht('Change symbol languages for this repository.'))
451 ->setConduitTypeDescription(
452 pht('New symbol languages.'))
453 ->setValue($object->getSymbolLanguages()),
454 id(new PhabricatorDatasourceEditField())
455 ->setKey('symbolRepositoryPHIDs')
456 ->setLabel(pht('Uses Symbols From'))
457 ->setTransactionType(
458 PhabricatorRepositorySymbolSourcesTransaction
::TRANSACTIONTYPE
)
459 ->setIsCopyable(true)
460 ->setDatasource(new DiffusionRepositoryDatasource())
461 ->setDescription(pht('Repositories to link symbols from.'))
462 ->setConduitDescription(pht('Change symbol source repositories.'))
463 ->setConduitTypeDescription(pht('New symbol repositories.'))
464 ->setValue($object->getSymbolSources()),
465 id(new PhabricatorBoolEditField())
467 ->setLabel(pht('Publish/Notify'))
468 ->setTransactionType(
469 PhabricatorRepositoryNotifyTransaction
::TRANSACTIONTYPE
)
470 ->setIsCopyable(true)
472 pht('Disable Notifications, Feed, and Herald'),
473 pht('Enable Notifications, Feed, and Herald'))
474 ->setDescription(pht('Configure how changes are published.'))
475 ->setConduitDescription(pht('Change publishing options.'))
476 ->setConduitTypeDescription(pht('New notification setting.'))
477 ->setValue(!$object->isPublishingDisabled()),
478 id(new PhabricatorPolicyEditField())
479 ->setKey('policy.push')
480 ->setLabel(pht('Push Policy'))
481 ->setAliases(array('push'))
482 ->setIsCopyable(true)
483 ->setCapability(DiffusionPushCapability
::CAPABILITY
)
484 ->setPolicies($policies)
485 ->setTransactionType(
486 PhabricatorRepositoryPushPolicyTransaction
::TRANSACTIONTYPE
)
488 pht('Controls who can push changes to the repository.'))
489 ->setConduitDescription(
490 pht('Change the push policy of the repository.'))
491 ->setConduitTypeDescription(pht('New policy PHID or constant.'))
492 ->setValue($object->getPolicy(DiffusionPushCapability
::CAPABILITY
)),
493 id(new PhabricatorTextEditField())
494 ->setKey('filesizeLimit')
495 ->setLabel(pht('Filesize Limit'))
496 ->setTransactionType(
497 PhabricatorRepositoryFilesizeLimitTransaction
::TRANSACTIONTYPE
)
498 ->setDescription(pht('Maximum permitted file size.'))
499 ->setConduitDescription(pht('Change the filesize limit.'))
500 ->setConduitTypeDescription(pht('New repository filesize limit.'))
501 ->setControlInstructions($filesize_warning)
502 ->setValue($object->getFilesizeLimit()),
503 id(new PhabricatorTextEditField())
504 ->setKey('copyTimeLimit')
505 ->setLabel(pht('Clone/Fetch Timeout'))
506 ->setTransactionType(
507 PhabricatorRepositoryCopyTimeLimitTransaction
::TRANSACTIONTYPE
)
509 pht('Maximum permitted duration of internal clone/fetch.'))
510 ->setConduitDescription(pht('Change the copy time limit.'))
511 ->setConduitTypeDescription(pht('New repository copy time limit.'))
512 ->setValue($object->getCopyTimeLimit()),
513 id(new PhabricatorTextEditField())
514 ->setKey('touchLimit')
515 ->setLabel(pht('Touched Paths Limit'))
516 ->setTransactionType(
517 PhabricatorRepositoryTouchLimitTransaction
::TRANSACTIONTYPE
)
518 ->setDescription(pht('Maximum permitted paths touched per commit.'))
519 ->setConduitDescription(pht('Change the touch limit.'))
520 ->setConduitTypeDescription(pht('New repository touch limit.'))
521 ->setValue($object->getTouchLimit()),