Page MenuHomePhabricator

D20748.id.diff
No OneTemporary

D20748.id.diff

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

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)

Event Timeline