1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-12-05 21:26:14 +01:00

(stable) Promote 2019 Week 35

This commit is contained in:
epriestley 2019-08-31 07:54:26 -07:00
commit 4fca51c75c
16 changed files with 291 additions and 35 deletions

View file

@ -4470,6 +4470,7 @@ phutil_register_library_map(array(
'PhabricatorRepositoryIdentityTransaction' => 'applications/repository/storage/PhabricatorRepositoryIdentityTransaction.php', 'PhabricatorRepositoryIdentityTransaction' => 'applications/repository/storage/PhabricatorRepositoryIdentityTransaction.php',
'PhabricatorRepositoryIdentityTransactionQuery' => 'applications/repository/query/PhabricatorRepositoryIdentityTransactionQuery.php', 'PhabricatorRepositoryIdentityTransactionQuery' => 'applications/repository/query/PhabricatorRepositoryIdentityTransactionQuery.php',
'PhabricatorRepositoryIdentityTransactionType' => 'applications/repository/xaction/PhabricatorRepositoryIdentityTransactionType.php', 'PhabricatorRepositoryIdentityTransactionType' => 'applications/repository/xaction/PhabricatorRepositoryIdentityTransactionType.php',
'PhabricatorRepositoryMaintenanceTransaction' => 'applications/repository/xaction/PhabricatorRepositoryMaintenanceTransaction.php',
'PhabricatorRepositoryManagementCacheWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementCacheWorkflow.php', 'PhabricatorRepositoryManagementCacheWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementCacheWorkflow.php',
'PhabricatorRepositoryManagementClusterizeWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementClusterizeWorkflow.php', 'PhabricatorRepositoryManagementClusterizeWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementClusterizeWorkflow.php',
'PhabricatorRepositoryManagementDiscoverWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementDiscoverWorkflow.php', 'PhabricatorRepositoryManagementDiscoverWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementDiscoverWorkflow.php',
@ -4478,6 +4479,7 @@ phutil_register_library_map(array(
'PhabricatorRepositoryManagementListPathsWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementListPathsWorkflow.php', 'PhabricatorRepositoryManagementListPathsWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementListPathsWorkflow.php',
'PhabricatorRepositoryManagementListWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementListWorkflow.php', 'PhabricatorRepositoryManagementListWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementListWorkflow.php',
'PhabricatorRepositoryManagementLookupUsersWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementLookupUsersWorkflow.php', 'PhabricatorRepositoryManagementLookupUsersWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementLookupUsersWorkflow.php',
'PhabricatorRepositoryManagementMaintenanceWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementMaintenanceWorkflow.php',
'PhabricatorRepositoryManagementMarkImportedWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementMarkImportedWorkflow.php', 'PhabricatorRepositoryManagementMarkImportedWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementMarkImportedWorkflow.php',
'PhabricatorRepositoryManagementMarkReachableWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementMarkReachableWorkflow.php', 'PhabricatorRepositoryManagementMarkReachableWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementMarkReachableWorkflow.php',
'PhabricatorRepositoryManagementMirrorWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementMirrorWorkflow.php', 'PhabricatorRepositoryManagementMirrorWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementMirrorWorkflow.php',
@ -10911,6 +10913,7 @@ phutil_register_library_map(array(
'PhabricatorRepositoryIdentityTransaction' => 'PhabricatorModularTransaction', 'PhabricatorRepositoryIdentityTransaction' => 'PhabricatorModularTransaction',
'PhabricatorRepositoryIdentityTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'PhabricatorRepositoryIdentityTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
'PhabricatorRepositoryIdentityTransactionType' => 'PhabricatorModularTransactionType', 'PhabricatorRepositoryIdentityTransactionType' => 'PhabricatorModularTransactionType',
'PhabricatorRepositoryMaintenanceTransaction' => 'PhabricatorRepositoryTransactionType',
'PhabricatorRepositoryManagementCacheWorkflow' => 'PhabricatorRepositoryManagementWorkflow', 'PhabricatorRepositoryManagementCacheWorkflow' => 'PhabricatorRepositoryManagementWorkflow',
'PhabricatorRepositoryManagementClusterizeWorkflow' => 'PhabricatorRepositoryManagementWorkflow', 'PhabricatorRepositoryManagementClusterizeWorkflow' => 'PhabricatorRepositoryManagementWorkflow',
'PhabricatorRepositoryManagementDiscoverWorkflow' => 'PhabricatorRepositoryManagementWorkflow', 'PhabricatorRepositoryManagementDiscoverWorkflow' => 'PhabricatorRepositoryManagementWorkflow',
@ -10919,6 +10922,7 @@ phutil_register_library_map(array(
'PhabricatorRepositoryManagementListPathsWorkflow' => 'PhabricatorRepositoryManagementWorkflow', 'PhabricatorRepositoryManagementListPathsWorkflow' => 'PhabricatorRepositoryManagementWorkflow',
'PhabricatorRepositoryManagementListWorkflow' => 'PhabricatorRepositoryManagementWorkflow', 'PhabricatorRepositoryManagementListWorkflow' => 'PhabricatorRepositoryManagementWorkflow',
'PhabricatorRepositoryManagementLookupUsersWorkflow' => 'PhabricatorRepositoryManagementWorkflow', 'PhabricatorRepositoryManagementLookupUsersWorkflow' => 'PhabricatorRepositoryManagementWorkflow',
'PhabricatorRepositoryManagementMaintenanceWorkflow' => 'PhabricatorRepositoryManagementWorkflow',
'PhabricatorRepositoryManagementMarkImportedWorkflow' => 'PhabricatorRepositoryManagementWorkflow', 'PhabricatorRepositoryManagementMarkImportedWorkflow' => 'PhabricatorRepositoryManagementWorkflow',
'PhabricatorRepositoryManagementMarkReachableWorkflow' => 'PhabricatorRepositoryManagementWorkflow', 'PhabricatorRepositoryManagementMarkReachableWorkflow' => 'PhabricatorRepositoryManagementWorkflow',
'PhabricatorRepositoryManagementMirrorWorkflow' => 'PhabricatorRepositoryManagementWorkflow', 'PhabricatorRepositoryManagementMirrorWorkflow' => 'PhabricatorRepositoryManagementWorkflow',

View file

@ -30,4 +30,8 @@ final class PhabricatorMarkupCache extends PhabricatorCacheDAO {
) + parent::getConfiguration(); ) + parent::getConfiguration();
} }
public function getSchemaPersistence() {
return PhabricatorConfigTableSchema::PERSISTENCE_CACHE;
}
} }

View file

@ -48,11 +48,19 @@ abstract class PhabricatorConfigSchemaSpec extends Phobject {
abstract public function buildSchemata(); abstract public function buildSchemata();
protected function buildLiskObjectSchema(PhabricatorLiskDAO $object) { protected function buildLiskObjectSchema(PhabricatorLiskDAO $object) {
$index_options = array();
$persistence = $object->getSchemaPersistence();
if ($persistence !== null) {
$index_options['persistence'] = $persistence;
}
$this->buildRawSchema( $this->buildRawSchema(
$object->getApplicationName(), $object->getApplicationName(),
$object->getTableName(), $object->getTableName(),
$object->getSchemaColumns(), $object->getSchemaColumns(),
$object->getSchemaKeys()); $object->getSchemaKeys(),
$index_options);
} }
protected function buildFerretIndexSchema(PhabricatorFerretEngine $engine) { protected function buildFerretIndexSchema(PhabricatorFerretEngine $engine) {

View file

@ -145,9 +145,22 @@ final class DiffusionRepositoryController extends DiffusionController {
->setRight(array($this->branchButton, $actions_button, $clone_button)) ->setRight(array($this->branchButton, $actions_button, $clone_button))
->addClass('diffusion-action-bar'); ->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()) $view = id(new PHUITwoColumnView())
->setHeader($header) ->setHeader($header)
->setFooter(array( ->setFooter(
array(
$status_view,
$bar, $bar,
$description, $description,
$content, $content,
@ -327,6 +340,8 @@ final class DiffusionRepositoryController extends DiffusionController {
if (!$repository->isTracked()) { if (!$repository->isTracked()) {
$header->setStatus('fa-ban', 'dark', pht('Inactive')); $header->setStatus('fa-ban', 'dark', pht('Inactive'));
} else if ($repository->isReadOnly()) {
$header->setStatus('fa-wrench', 'indigo', pht('Under Maintenance'));
} else if ($repository->isImporting()) { } else if ($repository->isImporting()) {
$ratio = $repository->loadImportProgress(); $ratio = $repository->loadImportProgress();
$percentage = sprintf('%.2f%%', 100 * $ratio); $percentage = sprintf('%.2f%%', 100 * $ratio);

View file

@ -302,6 +302,12 @@ final class DiffusionServeController extends DiffusionController {
} }
if ($is_push) { if ($is_push) {
if ($repository->isReadOnly()) {
return new PhabricatorVCSResponse(
503,
$repository->getReadOnlyMessageForDisplay());
}
$can_write = $can_write =
$repository->canServeProtocol($proto_https, true) || $repository->canServeProtocol($proto_https, true) ||
$repository->canServeProtocol($proto_http, true); $repository->canServeProtocol($proto_http, true);

View file

@ -255,6 +255,10 @@ abstract class DiffusionSSHWorkflow extends PhabricatorSSHWorkflow {
'user account.')); 'user account.'));
} }
if ($repository->isReadOnly()) {
throw new Exception($repository->getReadOnlyMessageForDisplay());
}
$protocol = PhabricatorRepositoryURI::BUILTIN_PROTOCOL_SSH; $protocol = PhabricatorRepositoryURI::BUILTIN_PROTOCOL_SSH;
if ($repository->canServeProtocol($protocol, true)) { if ($repository->canServeProtocol($protocol, true)) {
$can_push = PhabricatorPolicyFilter::hasCapability( $can_push = PhabricatorPolicyFilter::hasCapability(

View file

@ -59,7 +59,6 @@ final class PhabricatorUser
private $rawCacheData = array(); private $rawCacheData = array();
private $usableCacheData = array(); private $usableCacheData = array();
private $authorities = array();
private $handlePool; private $handlePool;
private $csrfSalt; private $csrfSalt;
@ -705,23 +704,6 @@ final class PhabricatorUser
} }
/**
* Grant a user a source of authority, to let them bypass policy checks they
* could not otherwise.
*/
public function grantAuthority($authority) {
$this->authorities[] = $authority;
return $this;
}
/**
* Get authorities granted to the user.
*/
public function getAuthorities() {
return $this->authorities;
}
public function hasConduitClusterToken() { public function hasConduitClusterToken() {
return ($this->conduitClusterToken !== self::ATTACHABLE); return ($this->conduitClusterToken !== self::ATTACHABLE);
} }

View file

@ -52,6 +52,13 @@ final class PhabricatorRepositoryPullEngine
$repository = $this->getRepository(); $repository = $this->getRepository();
$viewer = PhabricatorUser::getOmnipotentUser(); $viewer = PhabricatorUser::getOmnipotentUser();
if ($repository->isReadOnly()) {
$this->skipPull(
pht(
"Skipping pull on read-only repository.\n\n%s",
$repository->getReadOnlyMessageForDisplay()));
}
$is_hg = false; $is_hg = false;
$is_git = false; $is_git = false;
$is_svn = false; $is_svn = false;

View file

@ -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;
}
}

View file

@ -1410,6 +1410,12 @@ final class PhabricatorRepository extends PhabricatorRepositoryDAO
} }
} }
if ($write) {
if ($this->isReadOnly()) {
return false;
}
}
return false; return false;
} }
@ -2266,6 +2272,35 @@ final class PhabricatorRepository extends PhabricatorRepositoryDAO
return $this->isGit(); 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 )---------------------------------------------------- */ /* -( Repository URIs )---------------------------------------------------- */

View file

@ -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());
}
}
}

View file

@ -25,11 +25,30 @@ final class PhabricatorEditEngineSubtypeTransaction
} }
public function validateTransactions($object, array $xactions) { public function validateTransactions($object, array $xactions) {
$map = $object->getEngine() $errors = array();
if (!$xactions) {
return $errors;
}
$engine = $object->getEngine();
if (!$engine->supportsSubtypes()) {
foreach ($xactions as $xaction) {
$errors[] = $this->newInvalidError(
pht(
'Edit engine (of class "%s") does not support subtypes, so '.
'subtype transactions can not be applied to it.',
get_class($engine)),
$xaction);
}
return $errors;
}
$map = $engine
->setViewer($this->getActor()) ->setViewer($this->getActor())
->newSubtypeMap(); ->newSubtypeMap();
$errors = array();
foreach ($xactions as $xaction) { foreach ($xactions as $xaction) {
$new = $xaction->getNewValue(); $new = $xaction->getNewValue();

View file

@ -1881,6 +1881,10 @@ abstract class LiskDAO extends Phobject
->getMaximumByteLengthForDataType($data_type); ->getMaximumByteLengthForDataType($data_type);
} }
public function getSchemaPersistence() {
return null;
}
/* -( AphrontDatabaseTableRefInterface )----------------------------------- */ /* -( AphrontDatabaseTableRefInterface )----------------------------------- */

View file

@ -298,6 +298,14 @@ final class PhabricatorStorageManagementAPI extends Phobject {
return self::isCharacterSetAvailableOnConnection($character_set, $conn); return self::isCharacterSetAvailableOnConnection($character_set, $conn);
} }
public function getClientCharset() {
if ($this->isCharacterSetAvailable('utf8mb4')) {
return 'utf8mb4';
} else {
return 'utf8';
}
}
public static function isCharacterSetAvailableOnConnection( public static function isCharacterSetAvailableOnConnection(
$character_set, $character_set,
AphrontDatabaseConnection $conn) { AphrontDatabaseConnection $conn) {

View file

@ -14,7 +14,8 @@ final class PhabricatorStorageManagementDumpWorkflow
'name' => 'for-replica', 'name' => 'for-replica',
'help' => pht( 'help' => pht(
'Add __--master-data__ to the __mysqldump__ command, '. 'Add __--master-data__ to the __mysqldump__ command, '.
'generating a CHANGE MASTER statement in the output.'), 'generating a CHANGE MASTER statement in the output. This '.
'option also dumps all data, including caches.'),
), ),
array( array(
'name' => 'output', 'name' => 'output',
@ -54,6 +55,8 @@ final class PhabricatorStorageManagementDumpWorkflow
$output_file = $args->getArg('output'); $output_file = $args->getArg('output');
$is_compress = $args->getArg('compress'); $is_compress = $args->getArg('compress');
$is_overwrite = $args->getArg('overwrite'); $is_overwrite = $args->getArg('overwrite');
$is_noindex = $args->getArg('no-indexes');
$is_replica = $args->getArg('for-replica');
if ($is_compress) { if ($is_compress) {
if ($output_file === null) { if ($output_file === null) {
@ -79,6 +82,14 @@ final class PhabricatorStorageManagementDumpWorkflow
} }
} }
if ($is_replica && $is_noindex) {
throw new PhutilArgumentUsageException(
pht(
'The "--for-replica" flag can not be used with the '.
'"--no-indexes" flag. Replication dumps must contain a complete '.
'representation of database state.'));
}
if ($output_file !== null) { if ($output_file !== null) {
if (Filesystem::pathExists($output_file)) { if (Filesystem::pathExists($output_file)) {
if (!$is_overwrite) { if (!$is_overwrite) {
@ -94,8 +105,6 @@ final class PhabricatorStorageManagementDumpWorkflow
$api = $this->getSingleAPI(); $api = $this->getSingleAPI();
$patches = $this->getPatches(); $patches = $this->getPatches();
$with_indexes = !$args->getArg('no-indexes');
$applied = $api->getAppliedPatches(); $applied = $api->getAppliedPatches();
if ($applied === null) { if ($applied === null) {
throw new PhutilArgumentUsageException( throw new PhutilArgumentUsageException(
@ -119,6 +128,9 @@ final class PhabricatorStorageManagementDumpWorkflow
$schemata = $actual_map[$ref_key]; $schemata = $actual_map[$ref_key];
$expect = $expect_map[$ref_key]; $expect = $expect_map[$ref_key];
$with_caches = $is_replica;
$with_indexes = !$is_noindex;
$targets = array(); $targets = array();
foreach ($schemata->getDatabases() as $database_name => $database) { foreach ($schemata->getDatabases() as $database_name => $database) {
$expect_database = $expect->getDatabase($database_name); $expect_database = $expect->getDatabase($database_name);
@ -143,7 +155,7 @@ final class PhabricatorStorageManagementDumpWorkflow
// When dumping tables, leave the data in cache tables in the // When dumping tables, leave the data in cache tables in the
// database. This will be automatically rebuild after the data // database. This will be automatically rebuild after the data
// is restored and does not need to be persisted in backups. // is restored and does not need to be persisted in backups.
$with_data = false; $with_data = $with_caches;
break; break;
case PhabricatorConfigTableSchema::PERSISTENCE_INDEX: case PhabricatorConfigTableSchema::PERSISTENCE_INDEX:
// When dumping tables, leave index data behind of the caller // When dumping tables, leave index data behind of the caller
@ -179,9 +191,11 @@ final class PhabricatorStorageManagementDumpWorkflow
$argv = array(); $argv = array();
$argv[] = '--hex-blob'; $argv[] = '--hex-blob';
$argv[] = '--single-transaction'; $argv[] = '--single-transaction';
$argv[] = '--default-character-set=utf8';
if ($args->getArg('for-replica')) { $argv[] = '--default-character-set';
$argv[] = $api->getClientCharset();
if ($is_replica) {
$argv[] = '--master-data'; $argv[] = '--master-data';
} }
@ -340,7 +354,6 @@ final class PhabricatorStorageManagementDumpWorkflow
return 0; return 0;
} }
private function writeData($data, $file, $is_compress, $output_file) { private function writeData($data, $file, $is_compress, $output_file) {
if (!strlen($data)) { if (!strlen($data)) {
return; return;

View file

@ -31,8 +31,8 @@ final class PhabricatorStorageManagementShellWorkflow
} }
return phutil_passthru( return phutil_passthru(
'mysql --protocol=TCP --default-character-set=utf8mb4 '. 'mysql --protocol=TCP --default-character-set %R -u %s %C -h %s %C',
'-u %s %C -h %s %C', $api->getClientCharset(),
$api->getUser(), $api->getUser(),
$flag_password, $flag_password,
$host, $host,