@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 recaptime-dev/main 531 lines 21 kB view raw
1<?php 2 3final class DiffusionRepositoryEditEngine 4 extends PhabricatorEditEngine { 5 6 const ENGINECONST = 'diffusion.repository'; 7 8 private $versionControlSystem; 9 10 public function setVersionControlSystem($version_control_system) { 11 $this->versionControlSystem = $version_control_system; 12 return $this; 13 } 14 15 public function getVersionControlSystem() { 16 return $this->versionControlSystem; 17 } 18 19 public function isEngineConfigurable() { 20 return false; 21 } 22 23 public function isDefaultQuickCreateEngine() { 24 return true; 25 } 26 27 public function getQuickCreateOrderVector() { 28 return id(new PhutilSortVector())->addInt(300); 29 } 30 31 public function getEngineName() { 32 return pht('Repositories'); 33 } 34 35 public function getSummaryHeader() { 36 return pht('Edit Repositories'); 37 } 38 39 public function getSummaryText() { 40 return pht('Creates and edits repositories.'); 41 } 42 43 public function getEngineApplicationClass() { 44 return PhabricatorDiffusionApplication::class; 45 } 46 47 protected function newEditableObject() { 48 $viewer = $this->getViewer(); 49 $repository = PhabricatorRepository::initializeNewRepository($viewer); 50 51 $repository->setDetail('newly-initialized', true); 52 53 $vcs = $this->getVersionControlSystem(); 54 if ($vcs) { 55 $repository->setVersionControlSystem($vcs); 56 } 57 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. 61 62 // Eventually we can make this more flexible, but this rule is a reasonable 63 // starting point as we begin to deploy cluster services. 64 65 $services = id(new AlmanacServiceQuery()) 66 ->setViewer(PhabricatorUser::getOmnipotentUser()) 67 ->withServiceTypes( 68 array( 69 AlmanacClusterRepositoryServiceType::SERVICETYPE, 70 )) 71 ->needProperties(true) 72 ->execute(); 73 if ($services) { 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]); 78 } 79 } 80 81 if (!$services) { 82 throw new Exception( 83 pht( 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 '. 87 'take place.')); 88 } 89 90 shuffle($services); 91 $service = head($services); 92 93 $repository->setAlmanacServicePHID($service->getPHID()); 94 } 95 96 return $repository; 97 } 98 99 protected function newObjectQuery() { 100 return new PhabricatorRepositoryQuery(); 101 } 102 103 protected function getObjectCreateTitleText($object) { 104 return pht('Create Repository'); 105 } 106 107 protected function getObjectCreateButtonText($object) { 108 return pht('Create Repository'); 109 } 110 111 protected function getObjectEditTitleText($object) { 112 return pht('Edit Repository: %s', $object->getName()); 113 } 114 115 protected function getObjectEditShortText($object) { 116 return $object->getDisplayName(); 117 } 118 119 protected function getObjectCreateShortText() { 120 return pht('Create Repository'); 121 } 122 123 protected function getObjectName() { 124 return pht('Repository'); 125 } 126 127 protected function getObjectViewURI($object) { 128 return $object->getPathURI('manage/'); 129 } 130 131 protected function getCreateNewObjectPolicy() { 132 return $this->getApplication()->getPolicy( 133 DiffusionCreateRepositoriesCapability::CAPABILITY); 134 } 135 136 protected function newPages($object) { 137 $panels = DiffusionRepositoryManagementPanel::getAllPanels(); 138 139 $pages = array(); 140 $uris = array(); 141 foreach ($panels as $panel_key => $panel) { 142 $panel->setRepository($object); 143 144 $uris[$panel_key] = $panel->getPanelURI(); 145 146 $page = $panel->newEditEnginePage(); 147 if (!$page) { 148 continue; 149 } 150 $pages[] = $page; 151 } 152 153 $basics_key = DiffusionRepositoryBasicsManagementPanel::PANELKEY; 154 $basics_uri = $uris[$basics_key]; 155 156 $more_pages = array( 157 id(new PhabricatorEditPage()) 158 ->setKey('encoding') 159 ->setLabel(pht('Text Encoding')) 160 ->setViewURI($basics_uri) 161 ->setFieldKeys( 162 array( 163 'encoding', 164 )), 165 id(new PhabricatorEditPage()) 166 ->setKey('extensions') 167 ->setLabel(pht('Extensions')) 168 ->setIsDefault(true), 169 ); 170 171 foreach ($more_pages as $page) { 172 $pages[] = $page; 173 } 174 175 return $pages; 176 } 177 178 protected function willConfigureFields($object, array $fields) { 179 // Change the default field order so related fields are adjacent. 180 $after = array( 181 'policy.edit' => array('policy.push'), 182 ); 183 184 $result = array(); 185 foreach ($fields as $key => $value) { 186 $result[$key] = $value; 187 188 if (!isset($after[$key])) { 189 continue; 190 } 191 192 foreach ($after[$key] as $next_key) { 193 if (!isset($fields[$next_key])) { 194 continue; 195 } 196 197 unset($result[$next_key]); 198 $result[$next_key] = $fields[$next_key]; 199 unset($fields[$next_key]); 200 } 201 } 202 203 return $result; 204 } 205 206 207 protected function buildCustomEditFields($object) { 208 $viewer = $this->getViewer(); 209 210 $policies = id(new PhabricatorPolicyQuery()) 211 ->setViewer($viewer) 212 ->setObject($object) 213 ->execute(); 214 215 $fetch_value = $object->getFetchRules(); 216 $track_value = $object->getTrackOnlyRules(); 217 $permanent_value = $object->getPermanentRefRules(); 218 219 $automation_instructions = pht( 220 "Configure **Repository Automation** to allow this server to ". 221 "write to this repository.". 222 "\n\n". 223 "IMPORTANT: This feature is new, experimental, and not supported. ". 224 "Use it at your own risk."); 225 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.". 231 "\n\n". 232 "IMPORTANT: This feature is new, experimental, and not supported. ". 233 "Use it at your own risk."); 234 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**. The import process will ignore '. 238 'commits which do not affect this path.'); 239 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.', 251 $git_version, 252 $filesize_version); 253 } 254 } 255 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 this software.'); 260 261 return array( 262 id(new PhabricatorSelectEditField()) 263 ->setKey('vcs') 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( 272 pht( 273 'Choose which version control system to use when creating a '. 274 'repository.')) 275 ->setConduitTypeDescription(pht('Version control system selection.')) 276 ->setValue($object->getVersionControlSystem()), 277 id(new PhabricatorTextEditField()) 278 ->setKey('name') 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()) 288 ->setKey('callsign') 289 ->setLabel(pht('Callsign')) 290 ->setControlInstructions( 291 pht('Callsign is the monogram rXXXX for this repository. '. 292 'It cannot contain spaces.')) 293 ->setTransactionType( 294 PhabricatorRepositoryCallsignTransaction::TRANSACTIONTYPE) 295 ->setDescription(pht('The repository callsign.')) 296 ->setConduitDescription(pht('Change the repository callsign.')) 297 ->setConduitTypeDescription(pht('New repository callsign.')) 298 ->setValue($object->getCallsign()), 299 id(new PhabricatorTextEditField()) 300 ->setKey('shortName') 301 ->setLabel(pht('Short Name')) 302 ->setControlInstructions( 303 pht('Short Name is part of the URI paths for this repository. '. 304 'It cannot contain spaces.')) 305 ->setTransactionType( 306 PhabricatorRepositorySlugTransaction::TRANSACTIONTYPE) 307 ->setDescription(pht('Short, unique repository name.')) 308 ->setConduitDescription(pht('Change the repository short name.')) 309 ->setConduitTypeDescription(pht('New short name for the repository.')) 310 ->setValue($object->getRepositorySlug()), 311 id(new PhabricatorRemarkupEditField()) 312 ->setKey('description') 313 ->setLabel(pht('Description')) 314 ->setTransactionType( 315 PhabricatorRepositoryDescriptionTransaction::TRANSACTIONTYPE) 316 ->setDescription(pht('Repository description.')) 317 ->setConduitDescription(pht('Change the repository description.')) 318 ->setConduitTypeDescription(pht('New repository description.')) 319 ->setValue($object->getDetail('description')), 320 id(new PhabricatorTextEditField()) 321 ->setKey('encoding') 322 ->setLabel(pht('Text Encoding')) 323 ->setIsCopyable(true) 324 ->setTransactionType( 325 PhabricatorRepositoryEncodingTransaction::TRANSACTIONTYPE) 326 ->setDescription(pht('Default text encoding.')) 327 ->setConduitDescription(pht('Change the default text encoding.')) 328 ->setConduitTypeDescription(pht('New text encoding.')) 329 ->setValue($object->getDetail('encoding')), 330 id(new PhabricatorBoolEditField()) 331 ->setKey('allowDangerousChanges') 332 ->setLabel(pht('Allow Dangerous Changes')) 333 ->setIsCopyable(true) 334 ->setIsFormField(false) 335 ->setOptions( 336 pht('Prevent Dangerous Changes'), 337 pht('Allow Dangerous Changes')) 338 ->setTransactionType( 339 PhabricatorRepositoryDangerousTransaction::TRANSACTIONTYPE) 340 ->setDescription(pht('Permit dangerous changes to be made.')) 341 ->setConduitDescription(pht('Allow or prevent dangerous changes.')) 342 ->setConduitTypeDescription(pht('New protection setting.')) 343 ->setValue($object->shouldAllowDangerousChanges()), 344 id(new PhabricatorBoolEditField()) 345 ->setKey('allowEnormousChanges') 346 ->setLabel(pht('Allow Enormous Changes')) 347 ->setIsCopyable(true) 348 ->setIsFormField(false) 349 ->setOptions( 350 pht('Prevent Enormous Changes'), 351 pht('Allow Enormous Changes')) 352 ->setTransactionType( 353 PhabricatorRepositoryEnormousTransaction::TRANSACTIONTYPE) 354 ->setDescription(pht('Permit enormous changes to be made.')) 355 ->setConduitDescription(pht('Allow or prevent enormous changes.')) 356 ->setConduitTypeDescription(pht('New protection setting.')) 357 ->setValue($object->shouldAllowEnormousChanges()), 358 id(new PhabricatorSelectEditField()) 359 ->setKey('status') 360 ->setLabel(pht('Status')) 361 ->setTransactionType( 362 PhabricatorRepositoryActivateTransaction::TRANSACTIONTYPE) 363 ->setIsFormField(false) 364 ->setOptions(PhabricatorRepository::getStatusNameMap()) 365 ->setDescription(pht('Active or inactive status.')) 366 ->setConduitDescription(pht('Active or deactivate the repository.')) 367 ->setConduitTypeDescription(pht('New repository status.')) 368 ->setValue($object->getStatus()), 369 id(new PhabricatorTextEditField()) 370 ->setKey('defaultBranch') 371 ->setLabel(pht('Default Branch')) 372 ->setTransactionType( 373 PhabricatorRepositoryDefaultBranchTransaction::TRANSACTIONTYPE) 374 ->setIsCopyable(true) 375 ->setDescription(pht('Default branch name.')) 376 ->setConduitDescription(pht('Set the default branch name.')) 377 ->setConduitTypeDescription(pht('New default branch name.')) 378 ->setValue($object->getDetail('default-branch')), 379 id(new PhabricatorTextAreaEditField()) 380 ->setIsStringList(true) 381 ->setKey('fetchRefs') 382 ->setLabel(pht('Fetch Refs')) 383 ->setTransactionType( 384 PhabricatorRepositoryFetchRefsTransaction::TRANSACTIONTYPE) 385 ->setIsCopyable(true) 386 ->setDescription(pht('Fetch only these refs.')) 387 ->setConduitDescription(pht('Set the fetched refs.')) 388 ->setConduitTypeDescription(pht('New fetched refs.')) 389 ->setValue($fetch_value), 390 id(new PhabricatorTextAreaEditField()) 391 ->setIsStringList(true) 392 ->setKey('permanentRefs') 393 ->setLabel(pht('Permanent Refs')) 394 ->setTransactionType( 395 PhabricatorRepositoryPermanentRefsTransaction::TRANSACTIONTYPE) 396 ->setIsCopyable(true) 397 ->setDescription(pht('Only these refs are considered permanent.')) 398 ->setConduitDescription(pht('Set the permanent refs.')) 399 ->setConduitTypeDescription(pht('New permanent ref rules.')) 400 ->setValue($permanent_value), 401 id(new PhabricatorTextAreaEditField()) 402 ->setIsStringList(true) 403 ->setKey('trackOnly') 404 ->setLabel(pht('Track Only')) 405 ->setTransactionType( 406 PhabricatorRepositoryTrackOnlyTransaction::TRANSACTIONTYPE) 407 ->setIsCopyable(true) 408 ->setControlInstructions($track_instructions) 409 ->setDescription(pht('Track only these branches.')) 410 ->setConduitDescription(pht('Set the tracked branches.')) 411 ->setConduitTypeDescription(pht('New tracked branches.')) 412 ->setValue($track_value), 413 id(new PhabricatorTextEditField()) 414 ->setKey('importOnly') 415 ->setLabel(pht('Import Only')) 416 ->setTransactionType( 417 PhabricatorRepositorySVNSubpathTransaction::TRANSACTIONTYPE) 418 ->setIsCopyable(true) 419 ->setDescription(pht('Subpath to selectively import.')) 420 ->setConduitDescription(pht('Set the subpath to import.')) 421 ->setConduitTypeDescription(pht('New subpath to import.')) 422 ->setValue($object->getDetail('svn-subpath')) 423 ->setControlInstructions($subpath_instructions), 424 id(new PhabricatorTextEditField()) 425 ->setKey('stagingAreaURI') 426 ->setLabel(pht('Staging Area URI')) 427 ->setTransactionType( 428 PhabricatorRepositoryStagingURITransaction::TRANSACTIONTYPE) 429 ->setIsCopyable(true) 430 ->setDescription(pht('Staging area URI.')) 431 ->setConduitDescription(pht('Set the staging area URI.')) 432 ->setConduitTypeDescription(pht('New staging area URI.')) 433 ->setValue($object->getStagingURI()) 434 ->setControlInstructions($staging_instructions), 435 id(new PhabricatorDatasourceEditField()) 436 ->setKey('automationBlueprintPHIDs') 437 ->setLabel(pht('Use Blueprints')) 438 ->setTransactionType( 439 PhabricatorRepositoryBlueprintsTransaction::TRANSACTIONTYPE) 440 ->setIsCopyable(true) 441 ->setDatasource(new DrydockBlueprintDatasource()) 442 ->setDescription(pht('Automation blueprints.')) 443 ->setConduitDescription(pht('Change automation blueprints.')) 444 ->setConduitTypeDescription(pht('New blueprint PHIDs.')) 445 ->setValue($object->getAutomationBlueprintPHIDs()) 446 ->setControlInstructions($automation_instructions), 447 id(new PhabricatorStringListEditField()) 448 ->setKey('symbolLanguages') 449 ->setLabel(pht('Languages')) 450 ->setTransactionType( 451 PhabricatorRepositorySymbolLanguagesTransaction::TRANSACTIONTYPE) 452 ->setIsCopyable(true) 453 ->setDescription( 454 pht('Languages which define symbols in this repository.')) 455 ->setConduitDescription( 456 pht('Change symbol languages for this repository.')) 457 ->setConduitTypeDescription( 458 pht('New symbol languages.')) 459 ->setValue($object->getSymbolLanguages()), 460 id(new PhabricatorDatasourceEditField()) 461 ->setKey('symbolRepositoryPHIDs') 462 ->setLabel(pht('Uses Symbols From')) 463 ->setTransactionType( 464 PhabricatorRepositorySymbolSourcesTransaction::TRANSACTIONTYPE) 465 ->setIsCopyable(true) 466 ->setDatasource(new DiffusionRepositoryDatasource()) 467 ->setDescription(pht('Repositories to link symbols from.')) 468 ->setConduitDescription(pht('Change symbol source repositories.')) 469 ->setConduitTypeDescription(pht('New symbol repositories.')) 470 ->setValue($object->getSymbolSources()), 471 id(new PhabricatorBoolEditField()) 472 ->setKey('publish') 473 ->setLabel(pht('Publish/Notify')) 474 ->setTransactionType( 475 PhabricatorRepositoryNotifyTransaction::TRANSACTIONTYPE) 476 ->setIsCopyable(true) 477 ->setOptions( 478 pht('Disable Notifications, Feed, and Herald'), 479 pht('Enable Notifications, Feed, and Herald')) 480 ->setDescription(pht('Configure how changes are published.')) 481 ->setConduitDescription(pht('Change publishing options.')) 482 ->setConduitTypeDescription(pht('New notification setting.')) 483 ->setValue(!$object->isPublishingDisabled()), 484 id(new PhabricatorPolicyEditField()) 485 ->setKey('policy.push') 486 ->setLabel(pht('Push Policy')) 487 ->setAliases(array('push')) 488 ->setIsCopyable(true) 489 ->setCapability(DiffusionPushCapability::CAPABILITY) 490 ->setPolicies($policies) 491 ->setTransactionType( 492 PhabricatorRepositoryPushPolicyTransaction::TRANSACTIONTYPE) 493 ->setDescription( 494 pht('Controls who can push changes to the repository.')) 495 ->setConduitDescription( 496 pht('Change the push policy of the repository.')) 497 ->setConduitTypeDescription(pht('New policy PHID or constant.')) 498 ->setValue($object->getPolicy(DiffusionPushCapability::CAPABILITY)), 499 id(new PhabricatorTextEditField()) 500 ->setKey('filesizeLimit') 501 ->setLabel(pht('Filesize Limit')) 502 ->setTransactionType( 503 PhabricatorRepositoryFilesizeLimitTransaction::TRANSACTIONTYPE) 504 ->setDescription(pht('Maximum permitted file size.')) 505 ->setConduitDescription(pht('Change the filesize limit.')) 506 ->setConduitTypeDescription(pht('New repository filesize limit.')) 507 ->setControlInstructions($filesize_warning) 508 ->setValue($object->getFilesizeLimit()), 509 id(new PhabricatorTextEditField()) 510 ->setKey('copyTimeLimit') 511 ->setLabel(pht('Clone/Fetch Timeout')) 512 ->setTransactionType( 513 PhabricatorRepositoryCopyTimeLimitTransaction::TRANSACTIONTYPE) 514 ->setDescription( 515 pht('Maximum permitted duration of internal clone/fetch.')) 516 ->setConduitDescription(pht('Change the copy time limit.')) 517 ->setConduitTypeDescription(pht('New repository copy time limit.')) 518 ->setValue($object->getCopyTimeLimit()), 519 id(new PhabricatorTextEditField()) 520 ->setKey('touchLimit') 521 ->setLabel(pht('Touched Paths Limit')) 522 ->setTransactionType( 523 PhabricatorRepositoryTouchLimitTransaction::TRANSACTIONTYPE) 524 ->setDescription(pht('Maximum permitted paths touched per commit.')) 525 ->setConduitDescription(pht('Change the touch limit.')) 526 ->setConduitTypeDescription(pht('New repository touch limit.')) 527 ->setValue($object->getTouchLimit()), 528 ); 529 } 530 531}