Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F15387133
D20748.id.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
13 KB
Referenced Files
None
Subscribers
None
D20748.id.diff
View Options
diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -4470,6 +4470,7 @@
'PhabricatorRepositoryIdentityTransaction' => 'applications/repository/storage/PhabricatorRepositoryIdentityTransaction.php',
'PhabricatorRepositoryIdentityTransactionQuery' => 'applications/repository/query/PhabricatorRepositoryIdentityTransactionQuery.php',
'PhabricatorRepositoryIdentityTransactionType' => 'applications/repository/xaction/PhabricatorRepositoryIdentityTransactionType.php',
+ 'PhabricatorRepositoryMaintenanceTransaction' => 'applications/repository/xaction/PhabricatorRepositoryMaintenanceTransaction.php',
'PhabricatorRepositoryManagementCacheWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementCacheWorkflow.php',
'PhabricatorRepositoryManagementClusterizeWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementClusterizeWorkflow.php',
'PhabricatorRepositoryManagementDiscoverWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementDiscoverWorkflow.php',
@@ -4478,6 +4479,7 @@
'PhabricatorRepositoryManagementListPathsWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementListPathsWorkflow.php',
'PhabricatorRepositoryManagementListWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementListWorkflow.php',
'PhabricatorRepositoryManagementLookupUsersWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementLookupUsersWorkflow.php',
+ 'PhabricatorRepositoryManagementMaintenanceWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementMaintenanceWorkflow.php',
'PhabricatorRepositoryManagementMarkImportedWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementMarkImportedWorkflow.php',
'PhabricatorRepositoryManagementMarkReachableWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementMarkReachableWorkflow.php',
'PhabricatorRepositoryManagementMirrorWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementMirrorWorkflow.php',
@@ -10911,6 +10913,7 @@
'PhabricatorRepositoryIdentityTransaction' => 'PhabricatorModularTransaction',
'PhabricatorRepositoryIdentityTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
'PhabricatorRepositoryIdentityTransactionType' => 'PhabricatorModularTransactionType',
+ 'PhabricatorRepositoryMaintenanceTransaction' => 'PhabricatorRepositoryTransactionType',
'PhabricatorRepositoryManagementCacheWorkflow' => 'PhabricatorRepositoryManagementWorkflow',
'PhabricatorRepositoryManagementClusterizeWorkflow' => 'PhabricatorRepositoryManagementWorkflow',
'PhabricatorRepositoryManagementDiscoverWorkflow' => 'PhabricatorRepositoryManagementWorkflow',
@@ -10919,6 +10922,7 @@
'PhabricatorRepositoryManagementListPathsWorkflow' => 'PhabricatorRepositoryManagementWorkflow',
'PhabricatorRepositoryManagementListWorkflow' => 'PhabricatorRepositoryManagementWorkflow',
'PhabricatorRepositoryManagementLookupUsersWorkflow' => 'PhabricatorRepositoryManagementWorkflow',
+ 'PhabricatorRepositoryManagementMaintenanceWorkflow' => 'PhabricatorRepositoryManagementWorkflow',
'PhabricatorRepositoryManagementMarkImportedWorkflow' => 'PhabricatorRepositoryManagementWorkflow',
'PhabricatorRepositoryManagementMarkReachableWorkflow' => 'PhabricatorRepositoryManagementWorkflow',
'PhabricatorRepositoryManagementMirrorWorkflow' => 'PhabricatorRepositoryManagementWorkflow',
diff --git a/src/applications/diffusion/controller/DiffusionRepositoryController.php b/src/applications/diffusion/controller/DiffusionRepositoryController.php
--- a/src/applications/diffusion/controller/DiffusionRepositoryController.php
+++ b/src/applications/diffusion/controller/DiffusionRepositoryController.php
@@ -145,13 +145,26 @@
->setRight(array($this->branchButton, $actions_button, $clone_button))
->addClass('diffusion-action-bar');
+ $status_view = null;
+ if ($repository->isReadOnly()) {
+ $status_view = id(new PHUIInfoView())
+ ->setSeverity(PHUIInfoView::SEVERITY_WARNING)
+ ->setErrors(
+ array(
+ phutil_escape_html_newlines(
+ $repository->getReadOnlyMessageForDisplay()),
+ ));
+ }
+
$view = id(new PHUITwoColumnView())
->setHeader($header)
- ->setFooter(array(
- $bar,
- $description,
- $content,
- ));
+ ->setFooter(
+ array(
+ $status_view,
+ $bar,
+ $description,
+ $content,
+ ));
if ($page_has_content) {
$view->setTabs($tabs);
@@ -327,6 +340,8 @@
if (!$repository->isTracked()) {
$header->setStatus('fa-ban', 'dark', pht('Inactive'));
+ } else if ($repository->isReadOnly()) {
+ $header->setStatus('fa-wrench', 'indigo', pht('Under Maintenance'));
} else if ($repository->isImporting()) {
$ratio = $repository->loadImportProgress();
$percentage = sprintf('%.2f%%', 100 * $ratio);
diff --git a/src/applications/diffusion/controller/DiffusionServeController.php b/src/applications/diffusion/controller/DiffusionServeController.php
--- a/src/applications/diffusion/controller/DiffusionServeController.php
+++ b/src/applications/diffusion/controller/DiffusionServeController.php
@@ -302,6 +302,12 @@
}
if ($is_push) {
+ if ($repository->isReadOnly()) {
+ return new PhabricatorVCSResponse(
+ 503,
+ $repository->getReadOnlyMessageForDisplay());
+ }
+
$can_write =
$repository->canServeProtocol($proto_https, true) ||
$repository->canServeProtocol($proto_http, true);
diff --git a/src/applications/diffusion/ssh/DiffusionSSHWorkflow.php b/src/applications/diffusion/ssh/DiffusionSSHWorkflow.php
--- a/src/applications/diffusion/ssh/DiffusionSSHWorkflow.php
+++ b/src/applications/diffusion/ssh/DiffusionSSHWorkflow.php
@@ -255,6 +255,10 @@
'user account.'));
}
+ if ($repository->isReadOnly()) {
+ throw new Exception($repository->getReadOnlyMessageForDisplay());
+ }
+
$protocol = PhabricatorRepositoryURI::BUILTIN_PROTOCOL_SSH;
if ($repository->canServeProtocol($protocol, true)) {
$can_push = PhabricatorPolicyFilter::hasCapability(
diff --git a/src/applications/repository/engine/PhabricatorRepositoryPullEngine.php b/src/applications/repository/engine/PhabricatorRepositoryPullEngine.php
--- a/src/applications/repository/engine/PhabricatorRepositoryPullEngine.php
+++ b/src/applications/repository/engine/PhabricatorRepositoryPullEngine.php
@@ -52,6 +52,13 @@
$repository = $this->getRepository();
$viewer = PhabricatorUser::getOmnipotentUser();
+ if ($repository->isReadOnly()) {
+ $this->skipPull(
+ pht(
+ "Skipping pull on read-only repository.\n\n%s",
+ $repository->getReadOnlyMessageForDisplay()));
+ }
+
$is_hg = false;
$is_git = false;
$is_svn = false;
diff --git a/src/applications/repository/management/PhabricatorRepositoryManagementMaintenanceWorkflow.php b/src/applications/repository/management/PhabricatorRepositoryManagementMaintenanceWorkflow.php
new file mode 100644
--- /dev/null
+++ b/src/applications/repository/management/PhabricatorRepositoryManagementMaintenanceWorkflow.php
@@ -0,0 +1,104 @@
+<?php
+
+final class PhabricatorRepositoryManagementMaintenanceWorkflow
+ extends PhabricatorRepositoryManagementWorkflow {
+
+ protected function didConstruct() {
+ $this
+ ->setName('maintenance')
+ ->setExamples(
+ "**maintenance** --start __message__ __repository__ ...\n".
+ "**maintenance** --stop __repository__")
+ ->setSynopsis(
+ pht('Set or clear read-only mode for repository maintenance.'))
+ ->setArguments(
+ array(
+ array(
+ 'name' => 'start',
+ 'param' => 'message',
+ 'help' => pht(
+ 'Put repositories into maintenance mode.'),
+ ),
+ array(
+ 'name' => 'stop',
+ 'help' => pht(
+ 'Take repositories out of maintenance mode, returning them '.
+ 'to normal serice.'),
+ ),
+ array(
+ 'name' => 'repositories',
+ 'wildcard' => true,
+ ),
+ ));
+ }
+
+ public function execute(PhutilArgumentParser $args) {
+ $viewer = $this->getViewer();
+
+ $repositories = $this->loadRepositories($args, 'repositories');
+ if (!$repositories) {
+ throw new PhutilArgumentUsageException(
+ pht('Specify one or more repositories to act on.'));
+ }
+
+ $message = $args->getArg('start');
+ $is_start = (bool)strlen($message);
+ $is_stop = $args->getArg('stop');
+
+ if (!$is_start && !$is_stop) {
+ throw new PhutilArgumentUsageException(
+ pht(
+ 'Use "--start <message>" to put repositories into maintenance '.
+ 'mode, or "--stop" to take them out of maintenance mode.'));
+ }
+
+ if ($is_start && $is_stop) {
+ throw new PhutilArgumentUsageException(
+ pht(
+ 'Specify either "--start" or "--stop", but not both.'));
+ }
+
+ $content_source = $this->newContentSource();
+ $diffusion_phid = id(new PhabricatorDiffusionApplication())->getPHID();
+
+ if ($is_start) {
+ $new_value = $message;
+ } else {
+ $new_value = null;
+ }
+
+ foreach ($repositories as $repository) {
+ $xactions = array();
+
+ $xactions[] = $repository->getApplicationTransactionTemplate()
+ ->setTransactionType(
+ PhabricatorRepositoryMaintenanceTransaction::TRANSACTIONTYPE)
+ ->setNewValue($new_value);
+
+ $repository->getApplicationTransactionEditor()
+ ->setActor($viewer)
+ ->setActingAsPHID($diffusion_phid)
+ ->setContentSource($content_source)
+ ->setContinueOnNoEffect(true)
+ ->setContinueOnMissingFields(true)
+ ->applyTransactions($repository, $xactions);
+
+ if ($is_start) {
+ echo tsprintf(
+ "%s\n",
+ pht(
+ 'Put repository "%s" into maintenance mode.',
+ $repository->getDisplayName()));
+ } else {
+ echo tsprintf(
+ "%s\n",
+ pht(
+ 'Took repository "%s" out of maintenance mode.',
+ $repository->getDisplayName()));
+ }
+ }
+
+ return 0;
+ }
+
+}
diff --git a/src/applications/repository/storage/PhabricatorRepository.php b/src/applications/repository/storage/PhabricatorRepository.php
--- a/src/applications/repository/storage/PhabricatorRepository.php
+++ b/src/applications/repository/storage/PhabricatorRepository.php
@@ -1410,6 +1410,12 @@
}
}
+ if ($write) {
+ if ($this->isReadOnly()) {
+ return false;
+ }
+ }
+
return false;
}
@@ -2266,6 +2272,35 @@
return $this->isGit();
}
+ public function isReadOnly() {
+ return (bool)$this->getDetail('read-only');
+ }
+
+ public function setReadOnly($read_only) {
+ return $this->setDetail('read-only', $read_only);
+ }
+
+ public function getReadOnlyMessage() {
+ return $this->getDetail('read-only-message');
+ }
+
+ public function setReadOnlyMessage($message) {
+ return $this->setDetail('read-only-message', $message);
+ }
+
+ public function getReadOnlyMessageForDisplay() {
+ $parts = array();
+ $parts[] = pht(
+ 'This repository is currently in read-only maintenance mode.');
+
+ $message = $this->getReadOnlyMessage();
+ if ($message !== null) {
+ $parts[] = $message;
+ }
+
+ return implode("\n\n", $parts);
+ }
+
/* -( Repository URIs )---------------------------------------------------- */
diff --git a/src/applications/repository/xaction/PhabricatorRepositoryMaintenanceTransaction.php b/src/applications/repository/xaction/PhabricatorRepositoryMaintenanceTransaction.php
new file mode 100644
--- /dev/null
+++ b/src/applications/repository/xaction/PhabricatorRepositoryMaintenanceTransaction.php
@@ -0,0 +1,43 @@
+<?php
+
+final class PhabricatorRepositoryMaintenanceTransaction
+ extends PhabricatorRepositoryTransactionType {
+
+ const TRANSACTIONTYPE = 'maintenance';
+
+ public function generateOldValue($object) {
+ return $object->getReadOnlyMessage();
+ }
+
+ public function applyInternalEffects($object, $value) {
+ if ($value === null) {
+ $object
+ ->setReadOnly(false)
+ ->setReadOnlyMessage(null);
+ } else {
+ $object
+ ->setReadOnly(true)
+ ->setReadOnlyMessage($value);
+ }
+ }
+
+ public function getTitle() {
+ $old = $this->getOldValue();
+ $new = $this->getNewValue();
+
+ if (strlen($old) && !strlen($new)) {
+ return pht(
+ '%s took this repository out of maintenance mode.',
+ $this->renderAuthor());
+ } else if (!strlen($old) && strlen($new)) {
+ return pht(
+ '%s put this repository into maintenance mode.',
+ $this->renderAuthor());
+ } else {
+ return pht(
+ '%s updated the maintenance message for this repository.',
+ $this->renderAuthor());
+ }
+ }
+
+}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Mar 16, 1:53 AM (1 w, 11 h ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7704592
Default Alt Text
D20748.id.diff (13 KB)
Attached To
Mode
D20748: Provide a simple read-only maintenance mode for repositories
Attached
Detach File
Event Timeline
Log In to Comment