1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-26 16:52:41 +01:00

Modularize Repository transactions

Summary: Depends on D19828. Ref T13216. Before adding new transactions to repositories (filesize limit, copy time limit, etc) modularize the existing transactions.

Test Plan:

- Created repository.
- Edited callsign (invalid, valid, duplicate, add, remove).
- Edited short name (invaild, valid, duplicate, add, remove).
- Edited description (add, remove).
- Edited encoding (invalid, valid, remove).
- Allowed/denied dangerous changes.
- Allowed/denied enormous chagnes.
- Activated, deactivated, reactivated.
- Changed tags.
- Changed push policy.
- Changed default branch (add, remove).
- Changed track only: add, remove, invalid function, invalid regex.
- Changed autoclose only: add, remove, invalid function, invalid regex.
- Changed publish/notify.
- Changed autoclose.
- Changed staging area (add, remove, invalid).
- Changed blueprints (add, remove).
- Changed symbols (add, remove).
- Grepped for `PhabricatorRepositoryTransaction::TYPE_`.
- Reviewed transaction history:

{F6021036}

Reviewers: amckinley

Reviewed By: amckinley

Maniphest Tasks: T13216

Differential Revision: https://secure.phabricator.com/D19829
This commit is contained in:
epriestley 2018-11-21 12:21:57 -08:00
parent c25d2a399d
commit fd12b37d16
33 changed files with 1266 additions and 949 deletions

View file

@ -4084,8 +4084,13 @@ phutil_register_library_map(array(
'PhabricatorRemarkupUIExample' => 'applications/uiexample/examples/PhabricatorRemarkupUIExample.php',
'PhabricatorRepositoriesSetupCheck' => 'applications/config/check/PhabricatorRepositoriesSetupCheck.php',
'PhabricatorRepository' => 'applications/repository/storage/PhabricatorRepository.php',
'PhabricatorRepositoryActivateTransaction' => 'applications/repository/xaction/PhabricatorRepositoryActivateTransaction.php',
'PhabricatorRepositoryAuditRequest' => 'applications/repository/storage/PhabricatorRepositoryAuditRequest.php',
'PhabricatorRepositoryAutocloseOnlyTransaction' => 'applications/repository/xaction/PhabricatorRepositoryAutocloseOnlyTransaction.php',
'PhabricatorRepositoryAutocloseTransaction' => 'applications/repository/xaction/PhabricatorRepositoryAutocloseTransaction.php',
'PhabricatorRepositoryBlueprintsTransaction' => 'applications/repository/xaction/PhabricatorRepositoryBlueprintsTransaction.php',
'PhabricatorRepositoryBranch' => 'applications/repository/storage/PhabricatorRepositoryBranch.php',
'PhabricatorRepositoryCallsignTransaction' => 'applications/repository/xaction/PhabricatorRepositoryCallsignTransaction.php',
'PhabricatorRepositoryCommit' => 'applications/repository/storage/PhabricatorRepositoryCommit.php',
'PhabricatorRepositoryCommitChangeParserWorker' => 'applications/repository/worker/commitchangeparser/PhabricatorRepositoryCommitChangeParserWorker.php',
'PhabricatorRepositoryCommitData' => 'applications/repository/storage/PhabricatorRepositoryCommitData.php',
@ -4099,10 +4104,15 @@ phutil_register_library_map(array(
'PhabricatorRepositoryCommitTestCase' => 'applications/repository/storage/__tests__/PhabricatorRepositoryCommitTestCase.php',
'PhabricatorRepositoryConfigOptions' => 'applications/repository/config/PhabricatorRepositoryConfigOptions.php',
'PhabricatorRepositoryDAO' => 'applications/repository/storage/PhabricatorRepositoryDAO.php',
'PhabricatorRepositoryDangerousTransaction' => 'applications/repository/xaction/PhabricatorRepositoryDangerousTransaction.php',
'PhabricatorRepositoryDefaultBranchTransaction' => 'applications/repository/xaction/PhabricatorRepositoryDefaultBranchTransaction.php',
'PhabricatorRepositoryDescriptionTransaction' => 'applications/repository/xaction/PhabricatorRepositoryDescriptionTransaction.php',
'PhabricatorRepositoryDestructibleCodex' => 'applications/repository/codex/PhabricatorRepositoryDestructibleCodex.php',
'PhabricatorRepositoryDiscoveryEngine' => 'applications/repository/engine/PhabricatorRepositoryDiscoveryEngine.php',
'PhabricatorRepositoryEditor' => 'applications/repository/editor/PhabricatorRepositoryEditor.php',
'PhabricatorRepositoryEncodingTransaction' => 'applications/repository/xaction/PhabricatorRepositoryEncodingTransaction.php',
'PhabricatorRepositoryEngine' => 'applications/repository/engine/PhabricatorRepositoryEngine.php',
'PhabricatorRepositoryEnormousTransaction' => 'applications/repository/xaction/PhabricatorRepositoryEnormousTransaction.php',
'PhabricatorRepositoryFerretEngine' => 'applications/repository/search/PhabricatorRepositoryFerretEngine.php',
'PhabricatorRepositoryFulltextEngine' => 'applications/repository/search/PhabricatorRepositoryFulltextEngine.php',
'PhabricatorRepositoryGitCommitChangeParserWorker' => 'applications/repository/worker/commitchangeparser/PhabricatorRepositoryGitCommitChangeParserWorker.php',
@ -4146,6 +4156,8 @@ phutil_register_library_map(array(
'PhabricatorRepositoryMercurialCommitMessageParserWorker' => 'applications/repository/worker/commitmessageparser/PhabricatorRepositoryMercurialCommitMessageParserWorker.php',
'PhabricatorRepositoryMirror' => 'applications/repository/storage/PhabricatorRepositoryMirror.php',
'PhabricatorRepositoryMirrorEngine' => 'applications/repository/engine/PhabricatorRepositoryMirrorEngine.php',
'PhabricatorRepositoryNameTransaction' => 'applications/repository/xaction/PhabricatorRepositoryNameTransaction.php',
'PhabricatorRepositoryNotifyTransaction' => 'applications/repository/xaction/PhabricatorRepositoryNotifyTransaction.php',
'PhabricatorRepositoryOldRef' => 'applications/repository/storage/PhabricatorRepositoryOldRef.php',
'PhabricatorRepositoryParsedChange' => 'applications/repository/data/PhabricatorRepositoryParsedChange.php',
'PhabricatorRepositoryPullEngine' => 'applications/repository/engine/PhabricatorRepositoryPullEngine.php',
@ -4162,6 +4174,7 @@ phutil_register_library_map(array(
'PhabricatorRepositoryPushLogQuery' => 'applications/repository/query/PhabricatorRepositoryPushLogQuery.php',
'PhabricatorRepositoryPushLogSearchEngine' => 'applications/repository/query/PhabricatorRepositoryPushLogSearchEngine.php',
'PhabricatorRepositoryPushMailWorker' => 'applications/repository/worker/PhabricatorRepositoryPushMailWorker.php',
'PhabricatorRepositoryPushPolicyTransaction' => 'applications/repository/xaction/PhabricatorRepositoryPushPolicyTransaction.php',
'PhabricatorRepositoryPushReplyHandler' => 'applications/repository/mail/PhabricatorRepositoryPushReplyHandler.php',
'PhabricatorRepositoryQuery' => 'applications/repository/query/PhabricatorRepositoryQuery.php',
'PhabricatorRepositoryRefCursor' => 'applications/repository/storage/PhabricatorRepositoryRefCursor.php',
@ -4170,18 +4183,26 @@ phutil_register_library_map(array(
'PhabricatorRepositoryRefEngine' => 'applications/repository/engine/PhabricatorRepositoryRefEngine.php',
'PhabricatorRepositoryRefPosition' => 'applications/repository/storage/PhabricatorRepositoryRefPosition.php',
'PhabricatorRepositoryRepositoryPHIDType' => 'applications/repository/phid/PhabricatorRepositoryRepositoryPHIDType.php',
'PhabricatorRepositorySVNSubpathTransaction' => 'applications/repository/xaction/PhabricatorRepositorySVNSubpathTransaction.php',
'PhabricatorRepositorySchemaSpec' => 'applications/repository/storage/PhabricatorRepositorySchemaSpec.php',
'PhabricatorRepositorySearchEngine' => 'applications/repository/query/PhabricatorRepositorySearchEngine.php',
'PhabricatorRepositoryServiceTransaction' => 'applications/repository/xaction/PhabricatorRepositoryServiceTransaction.php',
'PhabricatorRepositorySlugTransaction' => 'applications/repository/xaction/PhabricatorRepositorySlugTransaction.php',
'PhabricatorRepositoryStagingURITransaction' => 'applications/repository/xaction/PhabricatorRepositoryStagingURITransaction.php',
'PhabricatorRepositoryStatusMessage' => 'applications/repository/storage/PhabricatorRepositoryStatusMessage.php',
'PhabricatorRepositorySvnCommitChangeParserWorker' => 'applications/repository/worker/commitchangeparser/PhabricatorRepositorySvnCommitChangeParserWorker.php',
'PhabricatorRepositorySvnCommitMessageParserWorker' => 'applications/repository/worker/commitmessageparser/PhabricatorRepositorySvnCommitMessageParserWorker.php',
'PhabricatorRepositorySymbol' => 'applications/repository/storage/PhabricatorRepositorySymbol.php',
'PhabricatorRepositorySymbolLanguagesTransaction' => 'applications/repository/xaction/PhabricatorRepositorySymbolLanguagesTransaction.php',
'PhabricatorRepositorySymbolSourcesTransaction' => 'applications/repository/xaction/PhabricatorRepositorySymbolSourcesTransaction.php',
'PhabricatorRepositorySyncEvent' => 'applications/repository/storage/PhabricatorRepositorySyncEvent.php',
'PhabricatorRepositorySyncEventPHIDType' => 'applications/repository/phid/PhabricatorRepositorySyncEventPHIDType.php',
'PhabricatorRepositorySyncEventQuery' => 'applications/repository/query/PhabricatorRepositorySyncEventQuery.php',
'PhabricatorRepositoryTestCase' => 'applications/repository/storage/__tests__/PhabricatorRepositoryTestCase.php',
'PhabricatorRepositoryTrackOnlyTransaction' => 'applications/repository/xaction/PhabricatorRepositoryTrackOnlyTransaction.php',
'PhabricatorRepositoryTransaction' => 'applications/repository/storage/PhabricatorRepositoryTransaction.php',
'PhabricatorRepositoryTransactionQuery' => 'applications/repository/query/PhabricatorRepositoryTransactionQuery.php',
'PhabricatorRepositoryTransactionType' => 'applications/repository/xaction/PhabricatorRepositoryTransactionType.php',
'PhabricatorRepositoryType' => 'applications/repository/constants/PhabricatorRepositoryType.php',
'PhabricatorRepositoryURI' => 'applications/repository/storage/PhabricatorRepositoryURI.php',
'PhabricatorRepositoryURIIndex' => 'applications/repository/storage/PhabricatorRepositoryURIIndex.php',
@ -4192,6 +4213,7 @@ phutil_register_library_map(array(
'PhabricatorRepositoryURITestCase' => 'applications/repository/storage/__tests__/PhabricatorRepositoryURITestCase.php',
'PhabricatorRepositoryURITransaction' => 'applications/repository/storage/PhabricatorRepositoryURITransaction.php',
'PhabricatorRepositoryURITransactionQuery' => 'applications/repository/query/PhabricatorRepositoryURITransactionQuery.php',
'PhabricatorRepositoryVCSTransaction' => 'applications/repository/xaction/PhabricatorRepositoryVCSTransaction.php',
'PhabricatorRepositoryWorkingCopyVersion' => 'applications/repository/storage/PhabricatorRepositoryWorkingCopyVersion.php',
'PhabricatorRequestExceptionHandler' => 'aphront/handler/PhabricatorRequestExceptionHandler.php',
'PhabricatorResourceSite' => 'aphront/site/PhabricatorResourceSite.php',
@ -10004,11 +10026,16 @@ phutil_register_library_map(array(
'PhabricatorFulltextInterface',
'PhabricatorFerretInterface',
),
'PhabricatorRepositoryActivateTransaction' => 'PhabricatorRepositoryTransactionType',
'PhabricatorRepositoryAuditRequest' => array(
'PhabricatorRepositoryDAO',
'PhabricatorPolicyInterface',
),
'PhabricatorRepositoryAutocloseOnlyTransaction' => 'PhabricatorRepositoryTransactionType',
'PhabricatorRepositoryAutocloseTransaction' => 'PhabricatorRepositoryTransactionType',
'PhabricatorRepositoryBlueprintsTransaction' => 'PhabricatorRepositoryTransactionType',
'PhabricatorRepositoryBranch' => 'PhabricatorRepositoryDAO',
'PhabricatorRepositoryCallsignTransaction' => 'PhabricatorRepositoryTransactionType',
'PhabricatorRepositoryCommit' => array(
'PhabricatorRepositoryDAO',
'PhabricatorPolicyInterface',
@ -10042,10 +10069,15 @@ phutil_register_library_map(array(
'PhabricatorRepositoryCommitTestCase' => 'PhabricatorTestCase',
'PhabricatorRepositoryConfigOptions' => 'PhabricatorApplicationConfigOptions',
'PhabricatorRepositoryDAO' => 'PhabricatorLiskDAO',
'PhabricatorRepositoryDangerousTransaction' => 'PhabricatorRepositoryTransactionType',
'PhabricatorRepositoryDefaultBranchTransaction' => 'PhabricatorRepositoryTransactionType',
'PhabricatorRepositoryDescriptionTransaction' => 'PhabricatorRepositoryTransactionType',
'PhabricatorRepositoryDestructibleCodex' => 'PhabricatorDestructibleCodex',
'PhabricatorRepositoryDiscoveryEngine' => 'PhabricatorRepositoryEngine',
'PhabricatorRepositoryEditor' => 'PhabricatorApplicationTransactionEditor',
'PhabricatorRepositoryEncodingTransaction' => 'PhabricatorRepositoryTransactionType',
'PhabricatorRepositoryEngine' => 'Phobject',
'PhabricatorRepositoryEnormousTransaction' => 'PhabricatorRepositoryTransactionType',
'PhabricatorRepositoryFerretEngine' => 'PhabricatorFerretEngine',
'PhabricatorRepositoryFulltextEngine' => 'PhabricatorFulltextEngine',
'PhabricatorRepositoryGitCommitChangeParserWorker' => 'PhabricatorRepositoryCommitChangeParserWorker',
@ -10097,6 +10129,8 @@ phutil_register_library_map(array(
'PhabricatorRepositoryMercurialCommitMessageParserWorker' => 'PhabricatorRepositoryCommitMessageParserWorker',
'PhabricatorRepositoryMirror' => 'PhabricatorRepositoryDAO',
'PhabricatorRepositoryMirrorEngine' => 'PhabricatorRepositoryEngine',
'PhabricatorRepositoryNameTransaction' => 'PhabricatorRepositoryTransactionType',
'PhabricatorRepositoryNotifyTransaction' => 'PhabricatorRepositoryTransactionType',
'PhabricatorRepositoryOldRef' => array(
'PhabricatorRepositoryDAO',
'PhabricatorPolicyInterface',
@ -10125,6 +10159,7 @@ phutil_register_library_map(array(
'PhabricatorRepositoryPushLogQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhabricatorRepositoryPushLogSearchEngine' => 'PhabricatorApplicationSearchEngine',
'PhabricatorRepositoryPushMailWorker' => 'PhabricatorWorker',
'PhabricatorRepositoryPushPolicyTransaction' => 'PhabricatorRepositoryTransactionType',
'PhabricatorRepositoryPushReplyHandler' => 'PhabricatorMailReplyHandler',
'PhabricatorRepositoryQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhabricatorRepositoryRefCursor' => array(
@ -10136,12 +10171,18 @@ phutil_register_library_map(array(
'PhabricatorRepositoryRefEngine' => 'PhabricatorRepositoryEngine',
'PhabricatorRepositoryRefPosition' => 'PhabricatorRepositoryDAO',
'PhabricatorRepositoryRepositoryPHIDType' => 'PhabricatorPHIDType',
'PhabricatorRepositorySVNSubpathTransaction' => 'PhabricatorRepositoryTransactionType',
'PhabricatorRepositorySchemaSpec' => 'PhabricatorConfigSchemaSpec',
'PhabricatorRepositorySearchEngine' => 'PhabricatorApplicationSearchEngine',
'PhabricatorRepositoryServiceTransaction' => 'PhabricatorRepositoryTransactionType',
'PhabricatorRepositorySlugTransaction' => 'PhabricatorRepositoryTransactionType',
'PhabricatorRepositoryStagingURITransaction' => 'PhabricatorRepositoryTransactionType',
'PhabricatorRepositoryStatusMessage' => 'PhabricatorRepositoryDAO',
'PhabricatorRepositorySvnCommitChangeParserWorker' => 'PhabricatorRepositoryCommitChangeParserWorker',
'PhabricatorRepositorySvnCommitMessageParserWorker' => 'PhabricatorRepositoryCommitMessageParserWorker',
'PhabricatorRepositorySymbol' => 'PhabricatorRepositoryDAO',
'PhabricatorRepositorySymbolLanguagesTransaction' => 'PhabricatorRepositoryTransactionType',
'PhabricatorRepositorySymbolSourcesTransaction' => 'PhabricatorRepositoryTransactionType',
'PhabricatorRepositorySyncEvent' => array(
'PhabricatorRepositoryDAO',
'PhabricatorPolicyInterface',
@ -10149,8 +10190,10 @@ phutil_register_library_map(array(
'PhabricatorRepositorySyncEventPHIDType' => 'PhabricatorPHIDType',
'PhabricatorRepositorySyncEventQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhabricatorRepositoryTestCase' => 'PhabricatorTestCase',
'PhabricatorRepositoryTransaction' => 'PhabricatorApplicationTransaction',
'PhabricatorRepositoryTrackOnlyTransaction' => 'PhabricatorRepositoryTransactionType',
'PhabricatorRepositoryTransaction' => 'PhabricatorModularTransaction',
'PhabricatorRepositoryTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
'PhabricatorRepositoryTransactionType' => 'PhabricatorModularTransactionType',
'PhabricatorRepositoryType' => 'Phobject',
'PhabricatorRepositoryURI' => array(
'PhabricatorRepositoryDAO',
@ -10167,6 +10210,7 @@ phutil_register_library_map(array(
'PhabricatorRepositoryURITestCase' => 'PhabricatorTestCase',
'PhabricatorRepositoryURITransaction' => 'PhabricatorApplicationTransaction',
'PhabricatorRepositoryURITransactionQuery' => 'PhabricatorApplicationTransactionQuery',
'PhabricatorRepositoryVCSTransaction' => 'PhabricatorRepositoryTransactionType',
'PhabricatorRepositoryWorkingCopyVersion' => 'PhabricatorRepositoryDAO',
'PhabricatorRequestExceptionHandler' => 'AphrontRequestExceptionHandler',
'PhabricatorResourceSite' => 'PhabricatorSite',

View file

@ -25,7 +25,8 @@ final class DiffusionRepositoryEditActivateController
}
$xaction = id(new PhabricatorRepositoryTransaction())
->setTransactionType(PhabricatorRepositoryTransaction::TYPE_ACTIVATE)
->setTransactionType(
PhabricatorRepositoryActivateTransaction::TRANSACTIONTYPE)
->setNewValue($new_status);
$editor = id(new PhabricatorRepositoryEditor())

View file

@ -30,7 +30,8 @@ final class DiffusionRepositoryEditDangerousController
if ($request->isFormPost()) {
$xaction = id(new PhabricatorRepositoryTransaction())
->setTransactionType(PhabricatorRepositoryTransaction::TYPE_DANGEROUS)
->setTransactionType(
PhabricatorRepositoryDangerousTransaction::TRANSACTIONTYPE)
->setNewValue(!$repository->shouldAllowDangerousChanges());
$editor = id(new PhabricatorRepositoryEditor())

View file

@ -30,7 +30,8 @@ final class DiffusionRepositoryEditEnormousController
if ($request->isFormPost()) {
$xaction = id(new PhabricatorRepositoryTransaction())
->setTransactionType(PhabricatorRepositoryTransaction::TYPE_ENORMOUS)
->setTransactionType(
PhabricatorRepositoryEnormousTransaction::TRANSACTIONTYPE)
->setNewValue(!$repository->shouldAllowEnormousChanges());
$editor = id(new PhabricatorRepositoryEditor())

View file

@ -243,7 +243,8 @@ final class DiffusionRepositoryEditEngine
id(new PhabricatorSelectEditField())
->setKey('vcs')
->setLabel(pht('Version Control System'))
->setTransactionType(PhabricatorRepositoryTransaction::TYPE_VCS)
->setTransactionType(
PhabricatorRepositoryVCSTransaction::TRANSACTIONTYPE)
->setIsFormField(false)
->setIsCopyable(true)
->setOptions(PhabricatorRepositoryType::getAllRepositoryTypes())
@ -258,7 +259,8 @@ final class DiffusionRepositoryEditEngine
->setKey('name')
->setLabel(pht('Name'))
->setIsRequired(true)
->setTransactionType(PhabricatorRepositoryTransaction::TYPE_NAME)
->setTransactionType(
PhabricatorRepositoryNameTransaction::TRANSACTIONTYPE)
->setDescription(pht('The repository name.'))
->setConduitDescription(pht('Rename the repository.'))
->setConduitTypeDescription(pht('New repository name.'))
@ -266,7 +268,8 @@ final class DiffusionRepositoryEditEngine
id(new PhabricatorTextEditField())
->setKey('callsign')
->setLabel(pht('Callsign'))
->setTransactionType(PhabricatorRepositoryTransaction::TYPE_CALLSIGN)
->setTransactionType(
PhabricatorRepositoryCallsignTransaction::TRANSACTIONTYPE)
->setDescription(pht('The repository callsign.'))
->setConduitDescription(pht('Change the repository callsign.'))
->setConduitTypeDescription(pht('New repository callsign.'))
@ -274,7 +277,8 @@ final class DiffusionRepositoryEditEngine
id(new PhabricatorTextEditField())
->setKey('shortName')
->setLabel(pht('Short Name'))
->setTransactionType(PhabricatorRepositoryTransaction::TYPE_SLUG)
->setTransactionType(
PhabricatorRepositorySlugTransaction::TRANSACTIONTYPE)
->setDescription(pht('Short, unique repository name.'))
->setConduitDescription(pht('Change the repository short name.'))
->setConduitTypeDescription(pht('New short name for the repository.'))
@ -282,7 +286,8 @@ final class DiffusionRepositoryEditEngine
id(new PhabricatorRemarkupEditField())
->setKey('description')
->setLabel(pht('Description'))
->setTransactionType(PhabricatorRepositoryTransaction::TYPE_DESCRIPTION)
->setTransactionType(
PhabricatorRepositoryDescriptionTransaction::TRANSACTIONTYPE)
->setDescription(pht('Repository description.'))
->setConduitDescription(pht('Change the repository description.'))
->setConduitTypeDescription(pht('New repository description.'))
@ -291,7 +296,8 @@ final class DiffusionRepositoryEditEngine
->setKey('encoding')
->setLabel(pht('Text Encoding'))
->setIsCopyable(true)
->setTransactionType(PhabricatorRepositoryTransaction::TYPE_ENCODING)
->setTransactionType(
PhabricatorRepositoryEncodingTransaction::TRANSACTIONTYPE)
->setDescription(pht('Default text encoding.'))
->setConduitDescription(pht('Change the default text encoding.'))
->setConduitTypeDescription(pht('New text encoding.'))
@ -304,7 +310,8 @@ final class DiffusionRepositoryEditEngine
->setOptions(
pht('Prevent Dangerous Changes'),
pht('Allow Dangerous Changes'))
->setTransactionType(PhabricatorRepositoryTransaction::TYPE_DANGEROUS)
->setTransactionType(
PhabricatorRepositoryDangerousTransaction::TRANSACTIONTYPE)
->setDescription(pht('Permit dangerous changes to be made.'))
->setConduitDescription(pht('Allow or prevent dangerous changes.'))
->setConduitTypeDescription(pht('New protection setting.'))
@ -317,7 +324,8 @@ final class DiffusionRepositoryEditEngine
->setOptions(
pht('Prevent Enormous Changes'),
pht('Allow Enormous Changes'))
->setTransactionType(PhabricatorRepositoryTransaction::TYPE_ENORMOUS)
->setTransactionType(
PhabricatorRepositoryEnormousTransaction::TRANSACTIONTYPE)
->setDescription(pht('Permit enormous changes to be made.'))
->setConduitDescription(pht('Allow or prevent enormous changes.'))
->setConduitTypeDescription(pht('New protection setting.'))
@ -325,7 +333,8 @@ final class DiffusionRepositoryEditEngine
id(new PhabricatorSelectEditField())
->setKey('status')
->setLabel(pht('Status'))
->setTransactionType(PhabricatorRepositoryTransaction::TYPE_ACTIVATE)
->setTransactionType(
PhabricatorRepositoryActivateTransaction::TRANSACTIONTYPE)
->setIsFormField(false)
->setOptions(PhabricatorRepository::getStatusNameMap())
->setDescription(pht('Active or inactive status.'))
@ -336,7 +345,7 @@ final class DiffusionRepositoryEditEngine
->setKey('defaultBranch')
->setLabel(pht('Default Branch'))
->setTransactionType(
PhabricatorRepositoryTransaction::TYPE_DEFAULT_BRANCH)
PhabricatorRepositoryDefaultBranchTransaction::TRANSACTIONTYPE)
->setIsCopyable(true)
->setDescription(pht('Default branch name.'))
->setConduitDescription(pht('Set the default branch name.'))
@ -347,7 +356,7 @@ final class DiffusionRepositoryEditEngine
->setKey('trackOnly')
->setLabel(pht('Track Only'))
->setTransactionType(
PhabricatorRepositoryTransaction::TYPE_TRACK_ONLY)
PhabricatorRepositoryTrackOnlyTransaction::TRANSACTIONTYPE)
->setIsCopyable(true)
->setDescription(pht('Track only these branches.'))
->setConduitDescription(pht('Set the tracked branches.'))
@ -358,7 +367,7 @@ final class DiffusionRepositoryEditEngine
->setKey('autocloseOnly')
->setLabel(pht('Autoclose Only'))
->setTransactionType(
PhabricatorRepositoryTransaction::TYPE_AUTOCLOSE_ONLY)
PhabricatorRepositoryAutocloseOnlyTransaction::TRANSACTIONTYPE)
->setIsCopyable(true)
->setDescription(pht('Autoclose commits on only these branches.'))
->setConduitDescription(pht('Set the autoclose branches.'))
@ -368,7 +377,7 @@ final class DiffusionRepositoryEditEngine
->setKey('importOnly')
->setLabel(pht('Import Only'))
->setTransactionType(
PhabricatorRepositoryTransaction::TYPE_SVN_SUBPATH)
PhabricatorRepositorySVNSubpathTransaction::TRANSACTIONTYPE)
->setIsCopyable(true)
->setDescription(pht('Subpath to selectively import.'))
->setConduitDescription(pht('Set the subpath to import.'))
@ -379,7 +388,7 @@ final class DiffusionRepositoryEditEngine
->setKey('stagingAreaURI')
->setLabel(pht('Staging Area URI'))
->setTransactionType(
PhabricatorRepositoryTransaction::TYPE_STAGING_URI)
PhabricatorRepositoryStagingURITransaction::TRANSACTIONTYPE)
->setIsCopyable(true)
->setDescription(pht('Staging area URI.'))
->setConduitDescription(pht('Set the staging area URI.'))
@ -390,7 +399,7 @@ final class DiffusionRepositoryEditEngine
->setKey('automationBlueprintPHIDs')
->setLabel(pht('Use Blueprints'))
->setTransactionType(
PhabricatorRepositoryTransaction::TYPE_AUTOMATION_BLUEPRINTS)
PhabricatorRepositoryBlueprintsTransaction::TRANSACTIONTYPE)
->setIsCopyable(true)
->setDatasource(new DrydockBlueprintDatasource())
->setDescription(pht('Automation blueprints.'))
@ -402,7 +411,7 @@ final class DiffusionRepositoryEditEngine
->setKey('symbolLanguages')
->setLabel(pht('Languages'))
->setTransactionType(
PhabricatorRepositoryTransaction::TYPE_SYMBOLS_LANGUAGE)
PhabricatorRepositorySymbolLanguagesTransaction::TRANSACTIONTYPE)
->setIsCopyable(true)
->setDescription(
pht('Languages which define symbols in this repository.'))
@ -415,7 +424,7 @@ final class DiffusionRepositoryEditEngine
->setKey('symbolRepositoryPHIDs')
->setLabel(pht('Uses Symbols From'))
->setTransactionType(
PhabricatorRepositoryTransaction::TYPE_SYMBOLS_SOURCES)
PhabricatorRepositorySymbolSourcesTransaction::TRANSACTIONTYPE)
->setIsCopyable(true)
->setDatasource(new DiffusionRepositoryDatasource())
->setDescription(pht('Repositories to link symbols from.'))
@ -426,7 +435,7 @@ final class DiffusionRepositoryEditEngine
->setKey('publish')
->setLabel(pht('Publish/Notify'))
->setTransactionType(
PhabricatorRepositoryTransaction::TYPE_NOTIFY)
PhabricatorRepositoryNotifyTransaction::TRANSACTIONTYPE)
->setIsCopyable(true)
->setOptions(
pht('Disable Notifications, Feed, and Herald'),
@ -439,7 +448,7 @@ final class DiffusionRepositoryEditEngine
->setKey('autoclose')
->setLabel(pht('Autoclose'))
->setTransactionType(
PhabricatorRepositoryTransaction::TYPE_AUTOCLOSE)
PhabricatorRepositoryAutocloseTransaction::TRANSACTIONTYPE)
->setIsCopyable(true)
->setOptions(
pht('Disable Autoclose'),
@ -455,7 +464,8 @@ final class DiffusionRepositoryEditEngine
->setIsCopyable(true)
->setCapability(DiffusionPushCapability::CAPABILITY)
->setPolicies($policies)
->setTransactionType(PhabricatorRepositoryTransaction::TYPE_PUSH_POLICY)
->setTransactionType(
PhabricatorRepositoryPushPolicyTransaction::TRANSACTIONTYPE)
->setDescription(
pht('Controls who can push changes to the repository.'))
->setConduitDescription(

View file

@ -52,8 +52,8 @@ final class PhabricatorApplicationPolicyChangeTransaction
}
public function getTitle() {
$old = $this->renderPolicy($this->getOldValue());
$new = $this->renderPolicy($this->getNewValue());
$old = $this->renderApplicationPolicy($this->getOldValue());
$new = $this->renderApplicationPolicy($this->getNewValue());
return pht(
'%s changed the "%s" policy from "%s" to "%s".',
@ -64,8 +64,8 @@ final class PhabricatorApplicationPolicyChangeTransaction
}
public function getTitleForFeed() {
$old = $this->renderPolicy($this->getOldValue());
$new = $this->renderPolicy($this->getNewValue());
$old = $this->renderApplicationPolicy($this->getOldValue());
$new = $this->renderApplicationPolicy($this->getNewValue());
return pht(
'%s changed the "%s" policy for application %s from "%s" to "%s".',
@ -165,7 +165,7 @@ final class PhabricatorApplicationPolicyChangeTransaction
return $errors;
}
private function renderPolicy($name) {
private function renderApplicationPolicy($name) {
$policies = $this->getAllPolicies();
if (empty($policies[$name])) {
// Not a standard policy, check for a custom policy.

View file

@ -14,28 +14,6 @@ final class PhabricatorRepositoryEditor
public function getTransactionTypes() {
$types = parent::getTransactionTypes();
$types[] = PhabricatorRepositoryTransaction::TYPE_VCS;
$types[] = PhabricatorRepositoryTransaction::TYPE_ACTIVATE;
$types[] = PhabricatorRepositoryTransaction::TYPE_NAME;
$types[] = PhabricatorRepositoryTransaction::TYPE_DESCRIPTION;
$types[] = PhabricatorRepositoryTransaction::TYPE_ENCODING;
$types[] = PhabricatorRepositoryTransaction::TYPE_DEFAULT_BRANCH;
$types[] = PhabricatorRepositoryTransaction::TYPE_TRACK_ONLY;
$types[] = PhabricatorRepositoryTransaction::TYPE_AUTOCLOSE_ONLY;
$types[] = PhabricatorRepositoryTransaction::TYPE_SVN_SUBPATH;
$types[] = PhabricatorRepositoryTransaction::TYPE_NOTIFY;
$types[] = PhabricatorRepositoryTransaction::TYPE_AUTOCLOSE;
$types[] = PhabricatorRepositoryTransaction::TYPE_PUSH_POLICY;
$types[] = PhabricatorRepositoryTransaction::TYPE_DANGEROUS;
$types[] = PhabricatorRepositoryTransaction::TYPE_ENORMOUS;
$types[] = PhabricatorRepositoryTransaction::TYPE_SLUG;
$types[] = PhabricatorRepositoryTransaction::TYPE_SERVICE;
$types[] = PhabricatorRepositoryTransaction::TYPE_SYMBOLS_LANGUAGE;
$types[] = PhabricatorRepositoryTransaction::TYPE_SYMBOLS_SOURCES;
$types[] = PhabricatorRepositoryTransaction::TYPE_STAGING_URI;
$types[] = PhabricatorRepositoryTransaction::TYPE_AUTOMATION_BLUEPRINTS;
$types[] = PhabricatorRepositoryTransaction::TYPE_CALLSIGN;
$types[] = PhabricatorTransactions::TYPE_EDGE;
$types[] = PhabricatorTransactions::TYPE_VIEW_POLICY;
$types[] = PhabricatorTransactions::TYPE_EDIT_POLICY;
@ -43,504 +21,6 @@ final class PhabricatorRepositoryEditor
return $types;
}
protected function getCustomTransactionOldValue(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case PhabricatorRepositoryTransaction::TYPE_VCS:
return $object->getVersionControlSystem();
case PhabricatorRepositoryTransaction::TYPE_ACTIVATE:
return $object->isTracked();
case PhabricatorRepositoryTransaction::TYPE_NAME:
return $object->getName();
case PhabricatorRepositoryTransaction::TYPE_DESCRIPTION:
return $object->getDetail('description');
case PhabricatorRepositoryTransaction::TYPE_ENCODING:
return $object->getDetail('encoding');
case PhabricatorRepositoryTransaction::TYPE_DEFAULT_BRANCH:
return $object->getDetail('default-branch');
case PhabricatorRepositoryTransaction::TYPE_TRACK_ONLY:
return array_keys($object->getDetail('branch-filter', array()));
case PhabricatorRepositoryTransaction::TYPE_AUTOCLOSE_ONLY:
return array_keys($object->getDetail('close-commits-filter', array()));
case PhabricatorRepositoryTransaction::TYPE_SVN_SUBPATH:
return $object->getDetail('svn-subpath');
case PhabricatorRepositoryTransaction::TYPE_NOTIFY:
return (int)!$object->getDetail('herald-disabled');
case PhabricatorRepositoryTransaction::TYPE_AUTOCLOSE:
return (int)!$object->getDetail('disable-autoclose');
case PhabricatorRepositoryTransaction::TYPE_PUSH_POLICY:
return $object->getPushPolicy();
case PhabricatorRepositoryTransaction::TYPE_DANGEROUS:
return $object->shouldAllowDangerousChanges();
case PhabricatorRepositoryTransaction::TYPE_ENORMOUS:
return $object->shouldAllowEnormousChanges();
case PhabricatorRepositoryTransaction::TYPE_SLUG:
return $object->getRepositorySlug();
case PhabricatorRepositoryTransaction::TYPE_SERVICE:
return $object->getAlmanacServicePHID();
case PhabricatorRepositoryTransaction::TYPE_SYMBOLS_LANGUAGE:
return $object->getSymbolLanguages();
case PhabricatorRepositoryTransaction::TYPE_SYMBOLS_SOURCES:
return $object->getSymbolSources();
case PhabricatorRepositoryTransaction::TYPE_STAGING_URI:
return $object->getDetail('staging-uri');
case PhabricatorRepositoryTransaction::TYPE_AUTOMATION_BLUEPRINTS:
return $object->getDetail('automation.blueprintPHIDs', array());
case PhabricatorRepositoryTransaction::TYPE_CALLSIGN:
return $object->getCallsign();
}
}
protected function getCustomTransactionNewValue(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case PhabricatorRepositoryTransaction::TYPE_ACTIVATE:
case PhabricatorRepositoryTransaction::TYPE_NAME:
case PhabricatorRepositoryTransaction::TYPE_DESCRIPTION:
case PhabricatorRepositoryTransaction::TYPE_ENCODING:
case PhabricatorRepositoryTransaction::TYPE_DEFAULT_BRANCH:
case PhabricatorRepositoryTransaction::TYPE_TRACK_ONLY:
case PhabricatorRepositoryTransaction::TYPE_AUTOCLOSE_ONLY:
case PhabricatorRepositoryTransaction::TYPE_SVN_SUBPATH:
case PhabricatorRepositoryTransaction::TYPE_VCS:
case PhabricatorRepositoryTransaction::TYPE_PUSH_POLICY:
case PhabricatorRepositoryTransaction::TYPE_DANGEROUS:
case PhabricatorRepositoryTransaction::TYPE_ENORMOUS:
case PhabricatorRepositoryTransaction::TYPE_SERVICE:
case PhabricatorRepositoryTransaction::TYPE_SYMBOLS_LANGUAGE:
case PhabricatorRepositoryTransaction::TYPE_SYMBOLS_SOURCES:
case PhabricatorRepositoryTransaction::TYPE_STAGING_URI:
case PhabricatorRepositoryTransaction::TYPE_AUTOMATION_BLUEPRINTS:
return $xaction->getNewValue();
case PhabricatorRepositoryTransaction::TYPE_SLUG:
case PhabricatorRepositoryTransaction::TYPE_CALLSIGN:
$name = $xaction->getNewValue();
if (strlen($name)) {
return $name;
}
return null;
case PhabricatorRepositoryTransaction::TYPE_NOTIFY:
case PhabricatorRepositoryTransaction::TYPE_AUTOCLOSE:
return (int)$xaction->getNewValue();
}
}
protected function applyCustomInternalTransaction(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case PhabricatorRepositoryTransaction::TYPE_VCS:
$object->setVersionControlSystem($xaction->getNewValue());
break;
case PhabricatorRepositoryTransaction::TYPE_ACTIVATE:
$active = $xaction->getNewValue();
// The first time a repository is activated, clear the "new repository"
// flag so we stop showing setup hints.
if ($active) {
$object->setDetail('newly-initialized', false);
}
$object->setDetail('tracking-enabled', $active);
break;
case PhabricatorRepositoryTransaction::TYPE_NAME:
$object->setName($xaction->getNewValue());
break;
case PhabricatorRepositoryTransaction::TYPE_DESCRIPTION:
$object->setDetail('description', $xaction->getNewValue());
break;
case PhabricatorRepositoryTransaction::TYPE_DEFAULT_BRANCH:
$object->setDetail('default-branch', $xaction->getNewValue());
break;
case PhabricatorRepositoryTransaction::TYPE_TRACK_ONLY:
$object->setDetail(
'branch-filter',
array_fill_keys($xaction->getNewValue(), true));
break;
case PhabricatorRepositoryTransaction::TYPE_AUTOCLOSE_ONLY:
$object->setDetail(
'close-commits-filter',
array_fill_keys($xaction->getNewValue(), true));
break;
case PhabricatorRepositoryTransaction::TYPE_SVN_SUBPATH:
$object->setDetail('svn-subpath', $xaction->getNewValue());
break;
case PhabricatorRepositoryTransaction::TYPE_NOTIFY:
$object->setDetail('herald-disabled', (int)!$xaction->getNewValue());
break;
case PhabricatorRepositoryTransaction::TYPE_AUTOCLOSE:
$object->setDetail('disable-autoclose', (int)!$xaction->getNewValue());
break;
case PhabricatorRepositoryTransaction::TYPE_PUSH_POLICY:
return $object->setPushPolicy($xaction->getNewValue());
case PhabricatorRepositoryTransaction::TYPE_DANGEROUS:
$object->setDetail('allow-dangerous-changes', $xaction->getNewValue());
return;
case PhabricatorRepositoryTransaction::TYPE_ENORMOUS:
$object->setDetail('allow-enormous-changes', $xaction->getNewValue());
return;
case PhabricatorRepositoryTransaction::TYPE_SLUG:
$object->setRepositorySlug($xaction->getNewValue());
return;
case PhabricatorRepositoryTransaction::TYPE_SERVICE:
$object->setAlmanacServicePHID($xaction->getNewValue());
return;
case PhabricatorRepositoryTransaction::TYPE_SYMBOLS_LANGUAGE:
$object->setDetail('symbol-languages', $xaction->getNewValue());
return;
case PhabricatorRepositoryTransaction::TYPE_SYMBOLS_SOURCES:
$object->setDetail('symbol-sources', $xaction->getNewValue());
return;
case PhabricatorRepositoryTransaction::TYPE_STAGING_URI:
$object->setDetail('staging-uri', $xaction->getNewValue());
return;
case PhabricatorRepositoryTransaction::TYPE_AUTOMATION_BLUEPRINTS:
$object->setDetail(
'automation.blueprintPHIDs',
$xaction->getNewValue());
return;
case PhabricatorRepositoryTransaction::TYPE_CALLSIGN:
$object->setCallsign($xaction->getNewValue());
return;
case PhabricatorRepositoryTransaction::TYPE_ENCODING:
$object->setDetail('encoding', $xaction->getNewValue());
break;
}
}
protected function applyCustomExternalTransaction(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case PhabricatorRepositoryTransaction::TYPE_AUTOMATION_BLUEPRINTS:
DrydockAuthorization::applyAuthorizationChanges(
$this->getActor(),
$object->getPHID(),
$xaction->getOldValue(),
$xaction->getNewValue());
break;
}
}
protected function validateTransaction(
PhabricatorLiskDAO $object,
$type,
array $xactions) {
$errors = parent::validateTransaction($object, $type, $xactions);
switch ($type) {
case PhabricatorRepositoryTransaction::TYPE_AUTOCLOSE_ONLY:
case PhabricatorRepositoryTransaction::TYPE_TRACK_ONLY:
foreach ($xactions as $xaction) {
foreach ($xaction->getNewValue() as $pattern) {
// Check for invalid regular expressions.
$regexp = PhabricatorRepository::extractBranchRegexp($pattern);
if ($regexp !== null) {
$ok = @preg_match($regexp, '');
if ($ok === false) {
$error = new PhabricatorApplicationTransactionValidationError(
$type,
pht('Invalid'),
pht(
'Expression "%s" is not a valid regular expression. Note '.
'that you must include delimiters.',
$regexp),
$xaction);
$errors[] = $error;
continue;
}
}
// Check for formatting mistakes like `regex(...)` instead of
// `regexp(...)`.
$matches = null;
if (preg_match('/^([^(]+)\\(.*\\)\z/', $pattern, $matches)) {
switch ($matches[1]) {
case 'regexp':
break;
default:
$error = new PhabricatorApplicationTransactionValidationError(
$type,
pht('Invalid'),
pht(
'Matching function "%s(...)" is not recognized. Valid '.
'functions are: regexp(...).',
$matches[1]),
$xaction);
$errors[] = $error;
break;
}
}
}
}
break;
case PhabricatorRepositoryTransaction::TYPE_AUTOMATION_BLUEPRINTS:
foreach ($xactions as $xaction) {
$old = nonempty($xaction->getOldValue(), array());
$new = nonempty($xaction->getNewValue(), array());
$add = array_diff($new, $old);
$invalid = PhabricatorObjectQuery::loadInvalidPHIDsForViewer(
$this->getActor(),
$add);
if ($invalid) {
$errors[] = new PhabricatorApplicationTransactionValidationError(
$type,
pht('Invalid'),
pht(
'Some of the selected automation blueprints are invalid '.
'or restricted: %s.',
implode(', ', $invalid)),
$xaction);
}
}
break;
case PhabricatorRepositoryTransaction::TYPE_VCS:
$vcs_map = PhabricatorRepositoryType::getAllRepositoryTypes();
$current_vcs = $object->getVersionControlSystem();
if (!$this->getIsNewObject()) {
foreach ($xactions as $xaction) {
if ($xaction->getNewValue() == $current_vcs) {
continue;
}
$errors[] = new PhabricatorApplicationTransactionValidationError(
$type,
pht('Immutable'),
pht(
'You can not change the version control system an existing '.
'repository uses. It can only be set when a repository is '.
'first created.'),
$xaction);
}
} else {
$value = $object->getVersionControlSystem();
foreach ($xactions as $xaction) {
$value = $xaction->getNewValue();
if (empty($vcs_map[$value])) {
$errors[] = new PhabricatorApplicationTransactionValidationError(
$type,
pht('Invalid'),
pht(
'Specified version control system must be a VCS '.
'recognized by Phabricator: %s.',
implode(', ', array_keys($vcs_map))),
$xaction);
}
}
if (!strlen($value)) {
$error = new PhabricatorApplicationTransactionValidationError(
$type,
pht('Required'),
pht(
'When creating a repository, you must specify a valid '.
'underlying version control system: %s.',
implode(', ', array_keys($vcs_map))),
nonempty(last($xactions), null));
$error->setIsMissingFieldError(true);
$errors[] = $error;
}
}
break;
case PhabricatorRepositoryTransaction::TYPE_NAME:
$missing = $this->validateIsEmptyTextField(
$object->getName(),
$xactions);
if ($missing) {
$error = new PhabricatorApplicationTransactionValidationError(
$type,
pht('Required'),
pht('Repository name is required.'),
nonempty(last($xactions), null));
$error->setIsMissingFieldError(true);
$errors[] = $error;
}
break;
case PhabricatorRepositoryTransaction::TYPE_ACTIVATE:
$status_map = PhabricatorRepository::getStatusMap();
foreach ($xactions as $xaction) {
$status = $xaction->getNewValue();
if (empty($status_map[$status])) {
$errors[] = new PhabricatorApplicationTransactionValidationError(
$type,
pht('Invalid'),
pht(
'Repository status "%s" is not valid.',
$status),
$xaction);
}
}
break;
case PhabricatorRepositoryTransaction::TYPE_ENCODING:
foreach ($xactions as $xaction) {
// Make sure the encoding is valid by converting to UTF-8. This tests
// that the user has mbstring installed, and also that they didn't
// type a garbage encoding name. Note that we're converting from
// UTF-8 to the target encoding, because mbstring is fine with
// converting from a nonsense encoding.
$encoding = $xaction->getNewValue();
if (!strlen($encoding)) {
continue;
}
try {
phutil_utf8_convert('.', $encoding, 'UTF-8');
} catch (Exception $ex) {
$errors[] = new PhabricatorApplicationTransactionValidationError(
$type,
pht('Invalid'),
pht(
'Repository encoding "%s" is not valid: %s',
$encoding,
$ex->getMessage()),
$xaction);
}
}
break;
case PhabricatorRepositoryTransaction::TYPE_SLUG:
foreach ($xactions as $xaction) {
$old = $xaction->getOldValue();
$new = $xaction->getNewValue();
if (!strlen($new)) {
continue;
}
if ($new === $old) {
continue;
}
try {
PhabricatorRepository::assertValidRepositorySlug($new);
} catch (Exception $ex) {
$errors[] = new PhabricatorApplicationTransactionValidationError(
$type,
pht('Invalid'),
$ex->getMessage(),
$xaction);
continue;
}
$other = id(new PhabricatorRepositoryQuery())
->setViewer(PhabricatorUser::getOmnipotentUser())
->withSlugs(array($new))
->executeOne();
if ($other && ($other->getID() !== $object->getID())) {
$errors[] = new PhabricatorApplicationTransactionValidationError(
$type,
pht('Duplicate'),
pht(
'The selected repository short name is already in use by '.
'another repository. Choose a unique short name.'),
$xaction);
continue;
}
}
break;
case PhabricatorRepositoryTransaction::TYPE_CALLSIGN:
foreach ($xactions as $xaction) {
$old = $xaction->getOldValue();
$new = $xaction->getNewValue();
if (!strlen($new)) {
continue;
}
if ($new === $old) {
continue;
}
try {
PhabricatorRepository::assertValidCallsign($new);
} catch (Exception $ex) {
$errors[] = new PhabricatorApplicationTransactionValidationError(
$type,
pht('Invalid'),
$ex->getMessage(),
$xaction);
continue;
}
$other = id(new PhabricatorRepositoryQuery())
->setViewer(PhabricatorUser::getOmnipotentUser())
->withCallsigns(array($new))
->executeOne();
if ($other && ($other->getID() !== $object->getID())) {
$errors[] = new PhabricatorApplicationTransactionValidationError(
$type,
pht('Duplicate'),
pht(
'The selected callsign ("%s") is already in use by another '.
'repository. Choose a unique callsign.',
$new),
$xaction);
continue;
}
}
break;
case PhabricatorRepositoryTransaction::TYPE_SYMBOLS_SOURCES:
foreach ($xactions as $xaction) {
$old = $object->getSymbolSources();
$new = $xaction->getNewValue();
// If the viewer is adding new repositories, make sure they are
// valid and visible.
$add = array_diff($new, $old);
if (!$add) {
continue;
}
$repositories = id(new PhabricatorRepositoryQuery())
->setViewer($this->getActor())
->withPHIDs($add)
->execute();
$repositories = mpull($repositories, null, 'getPHID');
foreach ($add as $phid) {
if (isset($repositories[$phid])) {
continue;
}
$errors[] = new PhabricatorApplicationTransactionValidationError(
$type,
pht('Invalid'),
pht(
'Repository ("%s") does not exist, or you do not have '.
'permission to see it.',
$phid),
$xaction);
break;
}
}
break;
}
return $errors;
}
protected function didCatchDuplicateKeyException(
PhabricatorLiskDAO $object,
array $xactions,

View file

@ -117,7 +117,8 @@ final class PhabricatorRepositoryManagementClusterizeWorkflow
$xactions = array();
$xactions[] = id(new PhabricatorRepositoryTransaction())
->setTransactionType(PhabricatorRepositoryTransaction::TYPE_SERVICE)
->setTransactionType(
PhabricatorRepositoryServiceTransaction::TRANSACTIONTYPE)
->setNewValue($service_phid);
id(new PhabricatorRepositoryEditor())

View file

@ -1,29 +1,7 @@
<?php
final class PhabricatorRepositoryTransaction
extends PhabricatorApplicationTransaction {
const TYPE_VCS = 'repo:vcs';
const TYPE_ACTIVATE = 'repo:activate';
const TYPE_NAME = 'repo:name';
const TYPE_DESCRIPTION = 'repo:description';
const TYPE_ENCODING = 'repo:encoding';
const TYPE_DEFAULT_BRANCH = 'repo:default-branch';
const TYPE_TRACK_ONLY = 'repo:track-only';
const TYPE_AUTOCLOSE_ONLY = 'repo:autoclose-only';
const TYPE_SVN_SUBPATH = 'repo:svn-subpath';
const TYPE_NOTIFY = 'repo:notify';
const TYPE_AUTOCLOSE = 'repo:autoclose';
const TYPE_PUSH_POLICY = 'repo:push-policy';
const TYPE_DANGEROUS = 'repo:dangerous';
const TYPE_ENORMOUS = 'repo:enormous';
const TYPE_SLUG = 'repo:slug';
const TYPE_SERVICE = 'repo:service';
const TYPE_SYMBOLS_SOURCES = 'repo:symbol-source';
const TYPE_SYMBOLS_LANGUAGE = 'repo:symbol-language';
const TYPE_STAGING_URI = 'repo:staging-uri';
const TYPE_AUTOMATION_BLUEPRINTS = 'repo:automation-blueprints';
const TYPE_CALLSIGN = 'repo:callsign';
extends PhabricatorModularTransaction {
public function getApplicationName() {
return 'repository';
@ -37,381 +15,8 @@ final class PhabricatorRepositoryTransaction
return null;
}
public function getRequiredHandlePHIDs() {
$phids = parent::getRequiredHandlePHIDs();
$old = $this->getOldValue();
$new = $this->getNewValue();
switch ($this->getTransactionType()) {
case self::TYPE_PUSH_POLICY:
case self::TYPE_SERVICE:
if ($old) {
$phids[] = $old;
}
if ($new) {
$phids[] = $new;
}
break;
case self::TYPE_SYMBOLS_SOURCES:
case self::TYPE_AUTOMATION_BLUEPRINTS:
if ($old) {
$phids = array_merge($phids, $old);
}
if ($new) {
$phids = array_merge($phids, $new);
}
break;
}
return $phids;
}
public function shouldHide() {
$old = $this->getOldValue();
$new = $this->getNewValue();
switch ($this->getTransactionType()) {
case self::TYPE_NAME:
// Hide these on create, they aren't interesting and we have an
// explicit "create" transaction.
if (!strlen($old)) {
return true;
}
break;
}
return parent::shouldHide();
}
public function getIcon() {
switch ($this->getTransactionType()) {
case self::TYPE_VCS:
return 'fa-plus';
}
return parent::getIcon();
}
public function getColor() {
switch ($this->getTransactionType()) {
case self::TYPE_VCS:
return 'green';
}
return parent::getIcon();
}
public function getTitle() {
$author_phid = $this->getAuthorPHID();
$old = $this->getOldValue();
$new = $this->getNewValue();
switch ($this->getTransactionType()) {
case self::TYPE_VCS:
return pht(
'%s created this repository.',
$this->renderHandleLink($author_phid));
case self::TYPE_ACTIVATE:
// TODO: Old versions of this transaction use a boolean value, but
// should be migrated.
$is_deactivate =
(!$new) ||
($new == PhabricatorRepository::STATUS_INACTIVE);
if (!$is_deactivate) {
return pht(
'%s activated this repository.',
$this->renderHandleLink($author_phid));
} else {
return pht(
'%s deactivated this repository.',
$this->renderHandleLink($author_phid));
}
case self::TYPE_NAME:
return pht(
'%s renamed this repository from "%s" to "%s".',
$this->renderHandleLink($author_phid),
$old,
$new);
case self::TYPE_DESCRIPTION:
return pht(
'%s updated the description of this repository.',
$this->renderHandleLink($author_phid));
case self::TYPE_ENCODING:
if (strlen($old) && !strlen($new)) {
return pht(
'%s removed the "%s" encoding configured for this repository.',
$this->renderHandleLink($author_phid),
$old);
} else if (strlen($new) && !strlen($old)) {
return pht(
'%s set the encoding for this repository to "%s".',
$this->renderHandleLink($author_phid),
$new);
} else {
return pht(
'%s changed the repository encoding from "%s" to "%s".',
$this->renderHandleLink($author_phid),
$old,
$new);
}
case self::TYPE_DEFAULT_BRANCH:
if (!strlen($new)) {
return pht(
'%s removed "%s" as the default branch.',
$this->renderHandleLink($author_phid),
$old);
} else if (!strlen($old)) {
return pht(
'%s set the default branch to "%s".',
$this->renderHandleLink($author_phid),
$new);
} else {
return pht(
'%s changed the default branch from "%s" to "%s".',
$this->renderHandleLink($author_phid),
$old,
$new);
}
break;
case self::TYPE_TRACK_ONLY:
if (!$new) {
return pht(
'%s set this repository to track all branches.',
$this->renderHandleLink($author_phid));
} else if (!$old) {
return pht(
'%s set this repository to track branches: %s.',
$this->renderHandleLink($author_phid),
implode(', ', $new));
} else {
return pht(
'%s changed track branches from "%s" to "%s".',
$this->renderHandleLink($author_phid),
implode(', ', $old),
implode(', ', $new));
}
break;
case self::TYPE_AUTOCLOSE_ONLY:
if (!$new) {
return pht(
'%s set this repository to autoclose on all branches.',
$this->renderHandleLink($author_phid));
} else if (!$old) {
return pht(
'%s set this repository to autoclose on branches: %s.',
$this->renderHandleLink($author_phid),
implode(', ', $new));
} else {
return pht(
'%s changed autoclose branches from "%s" to "%s".',
$this->renderHandleLink($author_phid),
implode(', ', $old),
implode(', ', $new));
}
break;
case self::TYPE_SVN_SUBPATH:
if (!strlen($new)) {
return pht(
'%s removed "%s" as the Import Only path.',
$this->renderHandleLink($author_phid),
$old);
} else if (!strlen($old)) {
return pht(
'%s set the repository to import only "%s".',
$this->renderHandleLink($author_phid),
$new);
} else {
return pht(
'%s changed the import path from "%s" to "%s".',
$this->renderHandleLink($author_phid),
$old,
$new);
}
break;
case self::TYPE_NOTIFY:
if ($new) {
return pht(
'%s enabled notifications and publishing for this repository.',
$this->renderHandleLink($author_phid));
} else {
return pht(
'%s disabled notifications and publishing for this repository.',
$this->renderHandleLink($author_phid));
}
break;
case self::TYPE_AUTOCLOSE:
if ($new) {
return pht(
'%s enabled autoclose for this repository.',
$this->renderHandleLink($author_phid));
} else {
return pht(
'%s disabled autoclose for this repository.',
$this->renderHandleLink($author_phid));
}
break;
case self::TYPE_PUSH_POLICY:
return pht(
'%s changed the push policy of this repository from "%s" to "%s".',
$this->renderHandleLink($author_phid),
$this->renderPolicyName($old, 'old'),
$this->renderPolicyName($new, 'new'));
case self::TYPE_DANGEROUS:
if ($new) {
return pht(
'%s disabled protection against dangerous changes.',
$this->renderHandleLink($author_phid));
} else {
return pht(
'%s enabled protection against dangerous changes.',
$this->renderHandleLink($author_phid));
}
case self::TYPE_ENORMOUS:
if ($new) {
return pht(
'%s disabled protection against enormous changes.',
$this->renderHandleLink($author_phid));
} else {
return pht(
'%s enabled protection against enormous changes.',
$this->renderHandleLink($author_phid));
}
case self::TYPE_SLUG:
if (strlen($old) && !strlen($new)) {
return pht(
'%s removed the short name of this repository.',
$this->renderHandleLink($author_phid));
} else if (strlen($new) && !strlen($old)) {
return pht(
'%s set the short name of this repository to "%s".',
$this->renderHandleLink($author_phid),
$new);
} else {
return pht(
'%s changed the short name of this repository from "%s" to "%s".',
$this->renderHandleLink($author_phid),
$old,
$new);
}
case self::TYPE_SERVICE:
if (strlen($old) && !strlen($new)) {
return pht(
'%s moved storage for this repository from %s to local.',
$this->renderHandleLink($author_phid),
$this->renderHandleLink($old));
} else if (!strlen($old) && strlen($new)) {
// TODO: Possibly, we should distinguish between automatic assignment
// on creation vs explicit adjustment.
return pht(
'%s set storage for this repository to %s.',
$this->renderHandleLink($author_phid),
$this->renderHandleLink($new));
} else {
return pht(
'%s moved storage for this repository from %s to %s.',
$this->renderHandleLink($author_phid),
$this->renderHandleLink($old),
$this->renderHandleLink($new));
}
case self::TYPE_SYMBOLS_SOURCES:
return pht(
'%s changed symbol sources from %s to %s.',
$this->renderHandleLink($author_phid),
empty($old) ? pht('None') : $this->renderHandleList($old),
empty($new) ? pht('None') : $this->renderHandleList($new));
case self::TYPE_SYMBOLS_LANGUAGE:
return pht('%s changed indexed languages from %s to %s.',
$this->renderHandleLink($author_phid),
$old ? implode(', ', $old) : pht('Any'),
$new ? implode(', ', $new) : pht('Any'));
case self::TYPE_STAGING_URI:
if (!$old) {
return pht(
'%s set "%s" as the staging area for this repository.',
$this->renderHandleLink($author_phid),
$new);
} else if (!$new) {
return pht(
'%s removed "%s" as the staging area for this repository.',
$this->renderHandleLink($author_phid),
$old);
} else {
return pht(
'%s changed the staging area for this repository from '.
'"%s" to "%s".',
$this->renderHandleLink($author_phid),
$old,
$new);
}
case self::TYPE_AUTOMATION_BLUEPRINTS:
$add = array_diff($new, $old);
$rem = array_diff($old, $new);
if ($add && $rem) {
return pht(
'%s changed %s automation blueprint(s), '.
'added %s: %s; removed %s: %s.',
$this->renderHandleLink($author_phid),
new PhutilNumber(count($add) + count($rem)),
new PhutilNumber(count($add)),
$this->renderHandleList($add),
new PhutilNumber(count($rem)),
$this->renderHandleList($rem));
} else if ($add) {
return pht(
'%s added %s automation blueprint(s): %s.',
$this->renderHandleLink($author_phid),
new PhutilNumber(count($add)),
$this->renderHandleList($add));
} else {
return pht(
'%s removed %s automation blueprint(s): %s.',
$this->renderHandleLink($author_phid),
new PhutilNumber(count($rem)),
$this->renderHandleList($rem));
}
case self::TYPE_CALLSIGN:
if ($old === null) {
return pht(
'%s set the callsign for this repository to "%s".',
$this->renderHandleLink($author_phid),
$new);
} else if ($new === null) {
return pht(
'%s removed the callsign ("%s") for this repository.',
$this->renderHandleLink($author_phid),
$old);
} else {
return pht(
'%s changed the callsign for this repository from "%s" to "%s".',
$this->renderHandleLink($author_phid),
$old,
$new);
}
}
return parent::getTitle();
}
public function hasChangeDetails() {
switch ($this->getTransactionType()) {
case self::TYPE_DESCRIPTION:
return true;
}
return parent::hasChangeDetails();
}
public function renderChangeDetails(PhabricatorUser $viewer) {
return $this->renderTextCorpusChangeDetails(
$viewer,
$this->getOldValue(),
$this->getNewValue());
public function getBaseTransactionClass() {
return 'PhabricatorRepositoryTransactionType';
}
}

View file

@ -0,0 +1,61 @@
<?php
final class PhabricatorRepositoryActivateTransaction
extends PhabricatorRepositoryTransactionType {
const TRANSACTIONTYPE = 'repo:activate';
public function generateOldValue($object) {
return $object->isTracked();
}
public function applyInternalEffects($object, $value) {
// The first time a repository is activated, clear the "new repository"
// flag so we stop showing setup hints.
if ($value) {
$object->setDetail('newly-initialized', false);
}
$object->setDetail('tracking-enabled', $value);
}
public function getTitle() {
$new = $this->getNewValue();
// TODO: Old versions of this transaction use a boolean value, but
// should be migrated.
$is_deactivate =
(!$new) ||
($new == PhabricatorRepository::STATUS_INACTIVE);
if (!$is_deactivate) {
return pht(
'%s activated this repository.',
$this->renderAuthor());
} else {
return pht(
'%s deactivated this repository.',
$this->renderAuthor());
}
}
public function validateTransactions($object, array $xactions) {
$errors = array();
$status_map = PhabricatorRepository::getStatusMap();
foreach ($xactions as $xaction) {
$status = $xaction->getNewValue();
if (empty($status_map[$status])) {
$errors[] = $this->newInvalidError(
pht(
'Repository status "%s" is not valid. Valid statuses are: %s.',
$status,
implode(', ', array_keys($status_map))),
$xaction);
}
}
return $errors;
}
}

View file

@ -0,0 +1,42 @@
<?php
final class PhabricatorRepositoryAutocloseOnlyTransaction
extends PhabricatorRepositoryTransactionType {
const TRANSACTIONTYPE = 'repo:autoclose-only';
public function generateOldValue($object) {
return array_keys($object->getDetail('close-commits-filter', array()));
}
public function applyInternalEffects($object, $value) {
$object->setDetail('close-commits-filter', array_fill_keys($value, true));
}
public function getTitle() {
$old = $this->getOldValue();
$new = $this->getNewValue();
if (!$new) {
return pht(
'%s set this repository to autoclose on all branches.',
$this->renderAuthor());
} else if (!$old) {
return pht(
'%s set this repository to autoclose on branches: %s.',
$this->renderAuthor(),
$this->renderValue(implode(', ', $new)));
} else {
return pht(
'%s changed autoclose branches from %s to %s.',
$this->renderAuthor(),
$this->renderValue(implode(', ', $old)),
$this->renderValue(implode(', ', $new)));
}
}
public function validateTransactions($object, array $xactions) {
return $this->validateRefList($object, $xactions);
}
}

View file

@ -0,0 +1,34 @@
<?php
final class PhabricatorRepositoryAutocloseTransaction
extends PhabricatorRepositoryTransactionType {
const TRANSACTIONTYPE = 'repo:autoclose';
public function generateOldValue($object) {
return (int)!$object->getDetail('disable-autoclose');
}
public function generateNewValue($object, $value) {
return (int)$value;
}
public function applyInternalEffects($object, $value) {
$object->setDetail('disable-autoclose', (int)!$value);
}
public function getTitle() {
$new = $this->getNewValue();
if ($new) {
return pht(
'%s enabled autoclose for this repository.',
$this->renderAuthor());
} else {
return pht(
'%s disabled autoclose for this repository.',
$this->renderAuthor());
}
}
}

View file

@ -0,0 +1,81 @@
<?php
final class PhabricatorRepositoryBlueprintsTransaction
extends PhabricatorRepositoryTransactionType {
const TRANSACTIONTYPE = 'repo:automation-blueprints';
public function generateOldValue($object) {
return $object->getDetail('automation.blueprintPHIDs', array());
}
public function applyInternalEffects($object, $value) {
$object->setDetail('automation.blueprintPHIDs', $value);
}
public function applyExternalEffects($object, $value) {
DrydockAuthorization::applyAuthorizationChanges(
$this->getActor(),
$object->getPHID(),
$this->getOldValue(),
$this->getNewValue());
}
public function getTitle() {
$old = $this->getOldValue();
$new = $this->getNewValue();
$add = array_diff($new, $old);
$rem = array_diff($old, $new);
if ($add && $rem) {
return pht(
'%s changed %s automation blueprint(s), '.
'added %s: %s; removed %s: %s.',
$this->renderAuthor(),
new PhutilNumber(count($add) + count($rem)),
new PhutilNumber(count($add)),
$this->renderHandleList($add),
new PhutilNumber(count($rem)),
$this->renderHandleList($rem));
} else if ($add) {
return pht(
'%s added %s automation blueprint(s): %s.',
$this->renderAuthor(),
new PhutilNumber(count($add)),
$this->renderHandleList($add));
} else {
return pht(
'%s removed %s automation blueprint(s): %s.',
$this->renderAuthor(),
new PhutilNumber(count($rem)),
$this->renderHandleList($rem));
}
}
public function validateTransactions($object, array $xactions) {
$errors = array();
foreach ($xactions as $xaction) {
$old = nonempty($xaction->getOldValue(), array());
$new = nonempty($xaction->getNewValue(), array());
$add = array_diff($new, $old);
$invalid = PhabricatorObjectQuery::loadInvalidPHIDsForViewer(
$this->getActor(),
$add);
if ($invalid) {
$errors[] = $this->newInvalidError(
pht(
'Some of the selected automation blueprints are invalid '.
'or restricted: %s.',
implode(', ', $invalid)),
$xaction);
}
}
return $errors;
}
}

View file

@ -0,0 +1,90 @@
<?php
final class PhabricatorRepositoryCallsignTransaction
extends PhabricatorRepositoryTransactionType {
const TRANSACTIONTYPE = 'repo:callsign';
public function generateOldValue($object) {
return $object->getCallsign();
}
public function generateNewValue($object, $value) {
if (strlen($value)) {
return $value;
}
return null;
}
public function applyInternalEffects($object, $value) {
$object->setCallsign($value);
}
public function getTitle() {
$old = $this->getOldValue();
$new = $this->getNewValue();
if (!strlen($old)) {
return pht(
'%s set the callsign for this repository to %s.',
$this->renderAuthor(),
$this->renderNewValue());
} else if (!strlen($new)) {
return pht(
'%s removed the callsign (%s) for this repository.',
$this->renderAuthor(),
$this->renderOldValue());
} else {
return pht(
'%s changed the callsign for this repository from %s to %s.',
$this->renderAuthor(),
$this->renderOldValue(),
$this->renderNewValue());
}
}
public function validateTransactions($object, array $xactions) {
$errors = array();
foreach ($xactions as $xaction) {
$old = $xaction->getOldValue();
$new = $xaction->getNewValue();
if (!strlen($new)) {
continue;
}
if ($new === $old) {
continue;
}
try {
PhabricatorRepository::assertValidCallsign($new);
} catch (Exception $ex) {
$errors[] = $this->newInvalidError(
$ex->getMessage(),
$xaction);
continue;
}
$other = id(new PhabricatorRepositoryQuery())
->setViewer(PhabricatorUser::getOmnipotentUser())
->withCallsigns(array($new))
->executeOne();
if ($other && ($other->getID() !== $object->getID())) {
$errors[] = $this->newError(
pht('Duplicate'),
pht(
'The selected callsign ("%s") is already in use by another '.
'repository. Choose a unique callsign.',
$new),
$xaction);
continue;
}
}
return $errors;
}
}

View file

@ -0,0 +1,30 @@
<?php
final class PhabricatorRepositoryDangerousTransaction
extends PhabricatorRepositoryTransactionType {
const TRANSACTIONTYPE = 'repo:dangerous';
public function generateOldValue($object) {
return $object->shouldAllowDangerousChanges();
}
public function applyInternalEffects($object, $value) {
$object->setDetail('allow-dangerous-changes', $value);
}
public function getTitle() {
$new = $this->getNewValue();
if ($new) {
return pht(
'%s disabled protection against dangerous changes.',
$this->renderAuthor());
} else {
return pht(
'%s enabled protection against dangerous changes.',
$this->renderAuthor());
}
}
}

View file

@ -0,0 +1,39 @@
<?php
final class PhabricatorRepositoryDefaultBranchTransaction
extends PhabricatorRepositoryTransactionType {
const TRANSACTIONTYPE = 'repo:default-branch';
public function generateOldValue($object) {
return $object->getDetail('default-branch');
}
public function applyInternalEffects($object, $value) {
$object->setDetail('default-branch', $value);
}
public function getTitle() {
$old = $this->getOldValue();
$new = $this->getNewValue();
if (!strlen($new)) {
return pht(
'%s removed %s as the default branch.',
$this->renderAuthor(),
$this->renderOldValue());
} else if (!strlen($old)) {
return pht(
'%s set the default branch to %s.',
$this->renderAuthor(),
$this->renderNewValue());
} else {
return pht(
'%s changed the default branch from %s to %s.',
$this->renderAuthor(),
$this->renderOldValue(),
$this->renderNewValue());
}
}
}

View file

@ -0,0 +1,49 @@
<?php
final class PhabricatorRepositoryDescriptionTransaction
extends PhabricatorRepositoryTransactionType {
const TRANSACTIONTYPE = 'repo:description';
public function generateOldValue($object) {
return $object->getDetail('description');
}
public function applyInternalEffects($object, $value) {
$object->setDetail('description', $value);
}
public function getTitle() {
return pht(
'%s updated the description for this repository.',
$this->renderAuthor());
}
public function hasChangeDetailView() {
return true;
}
public function getMailDiffSectionHeader() {
return pht('CHANGES TO REPOSITORY DESCRIPTION');
}
public function newChangeDetailView() {
$viewer = $this->getViewer();
return id(new PhabricatorApplicationTransactionTextDiffDetailView())
->setViewer($viewer)
->setOldText($this->getOldValue())
->setNewText($this->getNewValue());
}
public function newRemarkupChanges() {
$changes = array();
$changes[] = $this->newRemarkupChange()
->setOldValue($this->getOldValue())
->setNewValue($this->getNewValue());
return $changes;
}
}

View file

@ -0,0 +1,68 @@
<?php
final class PhabricatorRepositoryEncodingTransaction
extends PhabricatorRepositoryTransactionType {
const TRANSACTIONTYPE = 'repo:encoding';
public function generateOldValue($object) {
return $object->getDetail('encoding');
}
public function applyInternalEffects($object, $value) {
$object->setDetail('encoding', $value);
}
public function getTitle() {
$old = $this->getOldValue();
$new = $this->getNewValue();
if (strlen($old) && !strlen($new)) {
return pht(
'%s removed the %s encoding configured for this repository.',
$this->renderAuthor(),
$this->renderOldValue());
} else if (strlen($new) && !strlen($old)) {
return pht(
'%s set the encoding for this repository to %s.',
$this->renderAuthor(),
$this->renderNewValue());
} else {
return pht(
'%s changed the repository encoding from %s to %s.',
$this->renderAuthor(),
$this->renderOldValue(),
$this->renderNewValue());
}
}
public function validateTransactions($object, array $xactions) {
$errors = array();
foreach ($xactions as $xaction) {
// Make sure the encoding is valid by converting to UTF-8. This tests
// that the user has mbstring installed, and also that they didn't
// type a garbage encoding name. Note that we're converting from
// UTF-8 to the target encoding, because mbstring is fine with
// converting from a nonsense encoding.
$encoding = $xaction->getNewValue();
if (!strlen($encoding)) {
continue;
}
try {
phutil_utf8_convert('.', $encoding, 'UTF-8');
} catch (Exception $ex) {
$errors[] = $this->newInvalidError(
pht(
'Repository encoding "%s" is not valid: %s',
$encoding,
$ex->getMessage()),
$xaction);
}
}
return $errors;
}
}

View file

@ -0,0 +1,30 @@
<?php
final class PhabricatorRepositoryEnormousTransaction
extends PhabricatorRepositoryTransactionType {
const TRANSACTIONTYPE = 'repo:enormous';
public function generateOldValue($object) {
return $object->shouldAllowEnormousChanges();
}
public function applyInternalEffects($object, $value) {
$object->setDetail('allow-enormous-changes', $value);
}
public function getTitle() {
$new = $this->getNewValue();
if ($new) {
return pht(
'%s disabled protection against enormous changes.',
$this->renderAuthor());
} else {
return pht(
'%s enabled protection against enormous changes.',
$this->renderAuthor());
}
}
}

View file

@ -0,0 +1,35 @@
<?php
final class PhabricatorRepositoryNameTransaction
extends PhabricatorRepositoryTransactionType {
const TRANSACTIONTYPE = 'repo:name';
public function generateOldValue($object) {
return $object->getName();
}
public function applyInternalEffects($object, $value) {
$object->setName($value);
}
public function getTitle() {
return pht(
'%s renamed this repository from %s to %s.',
$this->renderAuthor(),
$this->renderOldValue(),
$this->renderNewValue());
}
public function validateTransactions($object, array $xactions) {
$errors = array();
if ($this->isEmptyTextTransaction($object->getName(), $xactions)) {
$errors[] = $this->newRequiredError(
pht('Repositories must have a name.'));
}
return $errors;
}
}

View file

@ -0,0 +1,34 @@
<?php
final class PhabricatorRepositoryNotifyTransaction
extends PhabricatorRepositoryTransactionType {
const TRANSACTIONTYPE = 'repo:notify';
public function generateOldValue($object) {
return (int)!$object->getDetail('herald-disabled');
}
public function generateNewValue($object, $value) {
return (int)$value;
}
public function applyInternalEffects($object, $value) {
$object->setDetail('herald-disabled', (int)!$value);
}
public function getTitle() {
$new = $this->getNewValue();
if ($new) {
return pht(
'%s enabled notifications and publishing for this repository.',
$this->renderAuthor());
} else {
return pht(
'%s disabled notifications and publishing for this repository.',
$this->renderAuthor());
}
}
}

View file

@ -0,0 +1,24 @@
<?php
final class PhabricatorRepositoryPushPolicyTransaction
extends PhabricatorRepositoryTransactionType {
const TRANSACTIONTYPE = 'repo:push-policy';
public function generateOldValue($object) {
return $object->getPushPolicy();
}
public function applyInternalEffects($object, $value) {
$object->setPushPolicy($value);
}
public function getTitle() {
return pht(
'%s changed the push policy of this repository from %s to %s.',
$this->renderAuthor(),
$this->renderOldPolicy(),
$this->renderNewPolicy());
}
}

View file

@ -0,0 +1,39 @@
<?php
final class PhabricatorRepositorySVNSubpathTransaction
extends PhabricatorRepositoryTransactionType {
const TRANSACTIONTYPE = 'repo:svn-subpath';
public function generateOldValue($object) {
return $object->getDetail('svn-subpath');
}
public function applyInternalEffects($object, $value) {
$object->setDetail('svn-subpath', $value);
}
public function getTitle() {
$old = $this->getOldValue();
$new = $this->getNewValue();
if (!strlen($new)) {
return pht(
'%s removed %s as the "Import Only" path.',
$this->renderAuthor(),
$this->renderOldValue());
} else if (!strlen($old)) {
return pht(
'%s set the repository "Import Only" path to %s.',
$this->renderAuthor(),
$this->renderNewValue());
} else {
return pht(
'%s changed the "Import Only" path from %s to %s.',
$this->renderAuthor(),
$this->renderOldValue(),
$this->renderNewValue());
}
}
}

View file

@ -0,0 +1,59 @@
<?php
final class PhabricatorRepositoryServiceTransaction
extends PhabricatorRepositoryTransactionType {
const TRANSACTIONTYPE = 'repo:service';
public function generateOldValue($object) {
return $object->getAlmanacServicePHID();
}
public function generateNewValue($object, $value) {
if (strlen($value)) {
return $value;
}
return null;
}
public function applyInternalEffects($object, $value) {
$object->setAlmanacServicePHID($value);
}
public function getTitle() {
$old = $this->getOldValue();
$new = $this->getOldValue();
if (strlen($old) && !strlen($new)) {
return pht(
'%s moved storage for this repository from %s to local.',
$this->renderAuthor(),
$this->renderOldHandle());
} else if (!strlen($old) && strlen($new)) {
// TODO: Possibly, we should distinguish between automatic assignment
// on creation vs explicit adjustment.
return pht(
'%s set storage for this repository to %s.',
$this->renderAuthor(),
$this->renderNewHandle());
} else {
return pht(
'%s moved storage for this repository from %s to %s.',
$this->renderAuthor(),
$this->renderOldHandle(),
$this->renderNewHandle());
}
}
public function validateTransactions($object, array $xactions) {
$errors = array();
// TODO: This could use some validation, values should be valid Almanac
// services of appropriate types. It's only reachable via the CLI so it's
// difficult to get wrong in practice.
return $errors;
}
}

View file

@ -0,0 +1,88 @@
<?php
final class PhabricatorRepositorySlugTransaction
extends PhabricatorRepositoryTransactionType {
const TRANSACTIONTYPE = 'repo:slug';
public function generateOldValue($object) {
return $object->getRepositorySlug();
}
public function generateNewValue($object, $value) {
if (strlen($value)) {
return $value;
}
return null;
}
public function applyInternalEffects($object, $value) {
$object->setRepositorySlug($value);
}
public function getTitle() {
$old = $this->getOldValue();
$new = $this->getNewValue();
if (strlen($old) && !strlen($new)) {
return pht(
'%s removed the short name of this repository.',
$this->renderAuthor());
} else if (strlen($new) && !strlen($old)) {
return pht(
'%s set the short name of this repository to %s.',
$this->renderAuthor(),
$this->renderNewValue());
} else {
return pht(
'%s changed the short name of this repository from %s to %s.',
$this->renderAuthor(),
$this->renderOldValue(),
$this->renderNewValue());
}
}
public function validateTransactions($object, array $xactions) {
$errors = array();
foreach ($xactions as $xaction) {
$old = $xaction->getOldValue();
$new = $xaction->getNewValue();
if (!strlen($new)) {
continue;
}
if ($new === $old) {
continue;
}
try {
PhabricatorRepository::assertValidRepositorySlug($new);
} catch (Exception $ex) {
$errors[] = $this->newInvalidError(
$ex->getMessage(),
$xaction);
continue;
}
$other = id(new PhabricatorRepositoryQuery())
->setViewer(PhabricatorUser::getOmnipotentUser())
->withSlugs(array($new))
->executeOne();
if ($other && ($other->getID() !== $object->getID())) {
$errors[] = $this->newError(
pht('Duplicate'),
pht(
'The selected repository short name is already in use by '.
'another repository. Choose a unique short name.'),
$xaction);
continue;
}
}
return $errors;
}
}

View file

@ -0,0 +1,68 @@
<?php
final class PhabricatorRepositoryStagingURITransaction
extends PhabricatorRepositoryTransactionType {
const TRANSACTIONTYPE = 'repo:staging-uri';
public function generateOldValue($object) {
return $object->getDetail('staging-uri');
}
public function applyInternalEffects($object, $value) {
$object->setDetail('staging-uri', $value);
}
public function getTitle() {
$old = $this->getOldValue();
$new = $this->getNewValue();
if (!strlen($old)) {
return pht(
'%s set %s as the staging area for this repository.',
$this->renderAuthor(),
$this->renderNewValue());
} else if (!strlen($new)) {
return pht(
'%s removed %s as the staging area for this repository.',
$this->renderAuthor(),
$this->renderOldValue());
} else {
return pht(
'%s changed the staging area for this repository from '.
'%s to %s.',
$this->renderAuthor(),
$this->renderOldValue(),
$this->renderNewValue());
}
}
public function validateTransactions($object, array $xactions) {
$errors = array();
$old = $this->generateOldValue($object);
foreach ($xactions as $xaction) {
$new = $xaction->getNewValue();
if (!strlen($new)) {
continue;
}
if ($new === $old) {
continue;
}
try {
PhabricatorRepository::assertValidRemoteURI($new);
} catch (Exception $ex) {
$errors[] = $this->newInvalidError(
$ex->getMessage(),
$xaction);
continue;
}
}
return $errors;
}
}

View file

@ -0,0 +1,39 @@
<?php
final class PhabricatorRepositorySymbolLanguagesTransaction
extends PhabricatorRepositoryTransactionType {
const TRANSACTIONTYPE = 'repo:symbol-language';
public function generateOldValue($object) {
return $object->getSymbolLanguages();
}
public function applyInternalEffects($object, $value) {
$object->setDetail('symbol-languages', $value);
}
public function getTitle() {
$old = $this->getOldValue();
$new = $this->getNewValue();
if ($old) {
$display_old = implode(', ', $old);
} else {
$display_old = pht('Any');
}
if ($new) {
$display_new = implode(', ', $new);
} else {
$display_new = pht('Any');
}
return pht(
'%s changed indexed languages from %s to %s.',
$this->renderAuthor(),
$this->renderValue($display_old),
$this->renderValue($display_new));
}
}

View file

@ -0,0 +1,78 @@
<?php
final class PhabricatorRepositorySymbolSourcesTransaction
extends PhabricatorRepositoryTransactionType {
const TRANSACTIONTYPE = 'repo:symbol-source';
public function generateOldValue($object) {
return $object->getSymbolSources();
}
public function applyInternalEffects($object, $value) {
$object->setDetail('symbol-sources', $value);
}
public function getTitle() {
$old = $this->getOldValue();
$new = $this->getNewValue();
if ($old) {
$display_old = $this->renderHandleList($old);
} else {
$display_old = $this->renderValue(pht('None'));
}
if ($new) {
$display_new = $this->renderHandleList($new);
} else {
$display_new = $this->renderValue(pht('None'));
}
return pht(
'%s changed symbol sources from %s to %s.',
$this->renderAuthor(),
$display_old,
$display_new);
}
public function validateTransactions($object, array $xactions) {
$errors = array();
foreach ($xactions as $xaction) {
$old = $object->getSymbolSources();
$new = $xaction->getNewValue();
// If the viewer is adding new repositories, make sure they are
// valid and visible.
$add = array_diff($new, $old);
if (!$add) {
continue;
}
$repositories = id(new PhabricatorRepositoryQuery())
->setViewer($this->getActor())
->withPHIDs($add)
->execute();
$repositories = mpull($repositories, null, 'getPHID');
foreach ($add as $phid) {
if (isset($repositories[$phid])) {
continue;
}
$errors[] = $this->newInvalidError(
pht(
'Repository ("%s") does not exist, or you do not have '.
'permission to see it.',
$phid),
$xaction);
break;
}
}
return $errors;
}
}

View file

@ -0,0 +1,42 @@
<?php
final class PhabricatorRepositoryTrackOnlyTransaction
extends PhabricatorRepositoryTransactionType {
const TRANSACTIONTYPE = 'repo:track-only';
public function generateOldValue($object) {
return array_keys($object->getDetail('branch-filter', array()));
}
public function applyInternalEffects($object, $value) {
$object->setDetail('branch-filter', array_fill_keys($value, true));
}
public function getTitle() {
$old = $this->getOldValue();
$new = $this->getNewValue();
if (!$new) {
return pht(
'%s set this repository to track all branches.',
$this->renderAuthor());
} else if (!$old) {
return pht(
'%s set this repository to track branches: %s.',
$this->renderAuthor(),
$this->renderValue(implode(', ', $new)));
} else {
return pht(
'%s changed tracked branches from %s to %s.',
$this->renderAuthor(),
$this->renderValue(implode(', ', $old)),
$this->renderValue(implode(', ', $new)));
}
}
public function validateTransactions($object, array $xactions) {
return $this->validateRefList($object, $xactions);
}
}

View file

@ -0,0 +1,49 @@
<?php
abstract class PhabricatorRepositoryTransactionType
extends PhabricatorModularTransactionType {
protected function validateRefList($object, array $xactions) {
$errors = array();
foreach ($xactions as $xaction) {
foreach ($xaction->getNewValue() as $pattern) {
// Check for invalid regular expressions.
$regexp = PhabricatorRepository::extractBranchRegexp($pattern);
if ($regexp !== null) {
$ok = @preg_match($regexp, '');
if ($ok === false) {
$errors[] = $this->newInvalidError(
pht(
'Expression "%s" is not a valid regular expression. Note '.
'that you must include delimiters.',
$regexp),
$xaction);
continue;
}
}
// Check for formatting mistakes like `regex(...)` instead of
// `regexp(...)`.
$matches = null;
if (preg_match('/^([^(]+)\\(.*\\)\z/', $pattern, $matches)) {
switch ($matches[1]) {
case 'regexp':
break;
default:
$errors[] = $this->newInvalidError(
pht(
'Matching function "%s(...)" is not recognized. Valid '.
'functions are: regexp(...).',
$matches[1]),
$xaction);
break;
}
}
}
}
return $errors;
}
}

View file

@ -0,0 +1,66 @@
<?php
final class PhabricatorRepositoryVCSTransaction
extends PhabricatorRepositoryTransactionType {
const TRANSACTIONTYPE = 'repo:vcs';
public function generateOldValue($object) {
return $object->getVersionControlSystem();
}
public function applyInternalEffects($object, $value) {
$object->setVersionControlSystem($value);
}
public function validateTransactions($object, array $xactions) {
$errors = array();
$vcs_map = PhabricatorRepositoryType::getAllRepositoryTypes();
$current_vcs = $object->getVersionControlSystem();
if (!$this->isNewObject()) {
foreach ($xactions as $xaction) {
if ($xaction->getNewValue() == $current_vcs) {
continue;
}
$errors[] = $this->newInvalidError(
pht(
'You can not change the version control system an existing '.
'repository uses. It can only be set when a repository is '.
'first created.'),
$xaction);
}
return $errors;
}
$value = $object->getVersionControlSystem();
foreach ($xactions as $xaction) {
$value = $xaction->getNewValue();
if (isset($vcs_map[$value])) {
continue;
}
$errors[] = $this->newInvalidError(
pht(
'Specified version control system must be a VCS '.
'recognized by Phabricator. Valid systems are: %s.',
implode(', ', array_keys($vcs_map))),
$xaction);
}
if ($value === null) {
$errors[] = $this->newRequiredError(
pht(
'When creating a repository, you must specify a valid '.
'underlying version control system. Valid systems are: %s.',
implode(', ', array_keys($vcs_map))));
}
return $errors;
}
}

View file

@ -32,7 +32,7 @@ final class PhabricatorApplicationTransactionValueController
case PhabricatorTransactions::TYPE_VIEW_POLICY:
case PhabricatorTransactions::TYPE_EDIT_POLICY:
case PhabricatorTransactions::TYPE_JOIN_POLICY:
case PhabricatorRepositoryTransaction::TYPE_PUSH_POLICY:
case PhabricatorRepositoryPushPolicyTransaction::TRANSACTIONTYPE:
break;
default:
return new Aphront404Response();

View file

@ -199,6 +199,35 @@ abstract class PhabricatorModularTransactionType
return $this->renderHandle($this->getNewValue());
}
final protected function renderOldPolicy() {
return $this->renderPolicy($this->getOldValue(), 'old');
}
final protected function renderNewPolicy() {
return $this->renderPolicy($this->getNewValue(), 'new');
}
final protected function renderPolicy($phid, $mode) {
$viewer = $this->getViewer();
$handles = $viewer->loadHandles(array($phid));
$policy = PhabricatorPolicy::newFromPolicyAndHandle(
$phid,
$handles[$phid]);
if ($this->isTextMode()) {
return $this->renderValue($policy->getFullName());
}
$storage = $this->getStorage();
if ($policy->getType() == PhabricatorPolicyType::TYPE_CUSTOM) {
$policy->setHref('/transactions/'.$mode.'/'.$storage->getPHID().'/');
$policy->setWorkflow(true);
}
return $this->renderValue($policy->renderDescription());
}
final protected function renderHandleList(array $phids) {
$viewer = $this->getViewer();
$display = $viewer->renderHandleList($phids)