@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Allow bin/config to affect database configuration and migrate between local and database configuration

Summary: Fixes T4018. Basically hits the bullet points in that task description except the "ideally" one.

Test Plan:
ran bin/config migrate and saw sensible output.

```
~> ./bin/config migrate
Migrating file-based config to more modern config...
Skipping config of source type PhabricatorConfigDatabaseSource...
Skipping config of source type PhabricatorConfigLocalSource...
Skipping config of source type PhabricatorConfigDefaultSource...
Done. Migrated 0 keys.
```

Reviewers: epriestley

Reviewed By: epriestley

Subscribers: hach-que, epriestley, Korvin

Maniphest Tasks: T4018

Differential Revision: https://secure.phabricator.com/D10490

+251 -42
+2
src/__phutil_library_map__.php
··· 1380 1380 'PhabricatorConfigManagementDeleteWorkflow' => 'applications/config/management/PhabricatorConfigManagementDeleteWorkflow.php', 1381 1381 'PhabricatorConfigManagementGetWorkflow' => 'applications/config/management/PhabricatorConfigManagementGetWorkflow.php', 1382 1382 'PhabricatorConfigManagementListWorkflow' => 'applications/config/management/PhabricatorConfigManagementListWorkflow.php', 1383 + 'PhabricatorConfigManagementMigrateWorkflow' => 'applications/config/management/PhabricatorConfigManagementMigrateWorkflow.php', 1383 1384 'PhabricatorConfigManagementSetWorkflow' => 'applications/config/management/PhabricatorConfigManagementSetWorkflow.php', 1384 1385 'PhabricatorConfigManagementWorkflow' => 'applications/config/management/PhabricatorConfigManagementWorkflow.php', 1385 1386 'PhabricatorConfigOption' => 'applications/config/option/PhabricatorConfigOption.php', ··· 4342 4343 'PhabricatorConfigManagementDeleteWorkflow' => 'PhabricatorConfigManagementWorkflow', 4343 4344 'PhabricatorConfigManagementGetWorkflow' => 'PhabricatorConfigManagementWorkflow', 4344 4345 'PhabricatorConfigManagementListWorkflow' => 'PhabricatorConfigManagementWorkflow', 4346 + 'PhabricatorConfigManagementMigrateWorkflow' => 'PhabricatorConfigManagementWorkflow', 4345 4347 'PhabricatorConfigManagementSetWorkflow' => 'PhabricatorConfigManagementWorkflow', 4346 4348 'PhabricatorConfigManagementWorkflow' => 'PhabricatorManagementWorkflow', 4347 4349 'PhabricatorConfigOption' => array(
+4 -1
src/applications/config/controller/PhabricatorConfigIgnoreController.php
··· 59 59 } 60 60 61 61 PhabricatorConfigEditor::storeNewValue( 62 - $config_entry, $list, $this->getRequest()); 62 + $this->getRequest()->getUser(), 63 + $config_entry, 64 + $list, 65 + PhabricatorContentSource::newFromRequest($this->getRequest())); 63 66 } 64 67 65 68 }
+26 -4
src/applications/config/editor/PhabricatorConfigEditor.php
··· 113 113 } 114 114 115 115 public static function storeNewValue( 116 + PhabricatorUser $user, 116 117 PhabricatorConfigEntry $config_entry, 117 118 $value, 118 - AphrontRequest $request) { 119 + PhabricatorContentSource $source) { 119 120 120 121 $xaction = id(new PhabricatorConfigTransaction()) 121 122 ->setTransactionType(PhabricatorConfigTransaction::TYPE_EDIT) ··· 126 127 )); 127 128 128 129 $editor = id(new PhabricatorConfigEditor()) 129 - ->setActor($request->getUser()) 130 - ->setContinueOnNoEffect(true) 131 - ->setContentSourceFromRequest($request); 130 + ->setActor($user) 131 + ->setContinueOnNoEffect(true) 132 + ->setContentSource($source); 133 + 134 + $editor->applyTransactions($config_entry, array($xaction)); 135 + } 136 + 137 + public static function deleteConfig( 138 + PhabricatorUser $user, 139 + PhabricatorConfigEntry $config_entry, 140 + PhabricatorContentSource $source) { 141 + 142 + $xaction = id(new PhabricatorConfigTransaction()) 143 + ->setTransactionType(PhabricatorConfigTransaction::TYPE_EDIT) 144 + ->setNewValue( 145 + array( 146 + 'deleted' => true, 147 + 'value' => null, 148 + )); 149 + 150 + $editor = id(new PhabricatorConfigEditor()) 151 + ->setActor($user) 152 + ->setContinueOnNoEffect(true) 153 + ->setContentSource($source); 132 154 133 155 $editor->applyTransactions($config_entry, array($xaction)); 134 156 }
+37 -10
src/applications/config/management/PhabricatorConfigManagementDeleteWorkflow.php
··· 7 7 $this 8 8 ->setName('delete') 9 9 ->setExamples('**delete** __key__') 10 - ->setSynopsis('Delete a local configuration value.') 10 + ->setSynopsis(pht('Delete a local configuration value.')) 11 11 ->setArguments( 12 12 array( 13 13 array( 14 + 'name' => 'database', 15 + 'help' => pht('Delete configuration in the database instead of '. 16 + 'in local configuration.'), 17 + ), 18 + array( 14 19 'name' => 'args', 15 20 'wildcard' => true, 16 21 ), ··· 22 27 23 28 $argv = $args->getArg('args'); 24 29 if (count($argv) == 0) { 25 - throw new PhutilArgumentUsageException( 26 - 'Specify a configuration key to delete.'); 30 + throw new PhutilArgumentUsageException(pht( 31 + 'Specify a configuration key to delete.')); 27 32 } 28 33 29 34 $key = $argv[0]; 30 35 31 36 if (count($argv) > 1) { 32 - throw new PhutilArgumentUsageException( 33 - 'Too many arguments: expected one key.'); 37 + throw new PhutilArgumentUsageException(pht( 38 + 'Too many arguments: expected one key.')); 34 39 } 35 40 36 - $config = new PhabricatorConfigLocalSource(); 41 + 42 + $use_database = $args->getArg('database'); 43 + if ($use_database) { 44 + $config = new PhabricatorConfigDatabaseSource('default'); 45 + $config_type = 'database'; 46 + } else { 47 + $config = new PhabricatorConfigLocalSource(); 48 + $config_type = 'local'; 49 + } 37 50 $values = $config->getKeys(array($key)); 38 51 if (!$values) { 39 - throw new PhutilArgumentUsageException( 40 - "Configuration key '{$key}' is not set in local configuration!"); 52 + throw new PhutilArgumentUsageException(pht( 53 + "Configuration key '%s' is not set in %s configuration!", 54 + $key, 55 + $config_type)); 41 56 } 42 57 43 - $config->deleteKeys(array($key)); 58 + if ($use_database) { 59 + $config_entry = id(new PhabricatorConfigOption()) 60 + ->loadOneWhere( 61 + 'namespace = %s and key = %s', 62 + 'default', 63 + $key); 64 + PhabricatorConfigEditor::deleteConfig( 65 + $this->getViewer(), 66 + $config_entry, 67 + PhabricatorContentSource::newConsoleSource()); 68 + } else { 69 + $config->deleteKeys(array($key)); 70 + } 44 71 45 72 $console->writeOut( 46 - pht("Deleted '%s' from local configuration.", $key)."\n"); 73 + pht("Deleted '%s' from %s configuration.", $key, $config_type)."\n"); 47 74 } 48 75 49 76 }
+50 -5
src/applications/config/management/PhabricatorConfigManagementGetWorkflow.php
··· 40 40 "keys."); 41 41 } 42 42 43 + $values = array(); 43 44 $config = new PhabricatorConfigLocalSource(); 44 - $values = $config->getKeys(array($key)); 45 + $local_value = $config->getKeys(array($key)); 46 + if (empty($local_value)) { 47 + $values['local'] = array( 48 + 'key' => $key, 49 + 'value' => null, 50 + 'status' => 'unset', 51 + 'errorInfo' => null, 52 + ); 53 + } else { 54 + $values['local'] = array( 55 + 'key' => $key, 56 + 'value' => reset($local_value), 57 + 'status' => 'set', 58 + 'errorInfo' => null, 59 + ); 60 + } 61 + 62 + $database_config = new PhabricatorConfigDatabaseSource('default'); 63 + try { 64 + $database_value = $database_config->getKeys(array($key)); 65 + if (empty($database_value)) { 66 + $values['database'] = array( 67 + 'key' => $key, 68 + 'value' => null, 69 + 'status' => 'unset', 70 + 'errorInfo' => null, 71 + ); 72 + } else { 73 + $values['database'] = array( 74 + 'key' => $key, 75 + 'value' => reset($database_value), 76 + 'status' => 'set', 77 + 'errorInfo' => null, 78 + ); 79 + } 80 + } catch (Exception $e) { 81 + $values['database'] = array( 82 + 'key' => $key, 83 + 'value' => null, 84 + 'status' => 'error', 85 + 'errorInfo' => pht('Database source is not configured properly'), 86 + ); 87 + } 45 88 46 89 $result = array(); 47 - foreach ($values as $key => $value) { 90 + foreach ($values as $source => $value) { 48 91 $result[] = array( 49 - 'key' => $key, 50 - 'source' => 'local', 51 - 'value' => $value, 92 + 'key' => $value['key'], 93 + 'source' => $source, 94 + 'value' => $value['value'], 95 + 'status' => $value['status'], 96 + 'errorInfo' => $value['errorInfo'], 52 97 ); 53 98 } 54 99 $result = array(
+75
src/applications/config/management/PhabricatorConfigManagementMigrateWorkflow.php
··· 1 + <?php 2 + 3 + final class PhabricatorConfigManagementMigrateWorkflow 4 + extends PhabricatorConfigManagementWorkflow { 5 + 6 + protected function didConstruct() { 7 + $this 8 + ->setName('migrate') 9 + ->setExamples('**migrate**') 10 + ->setSynopsis(pht( 11 + 'Migrate file-based configuration to more modern storage.')); 12 + } 13 + 14 + public function execute(PhutilArgumentParser $args) { 15 + $console = PhutilConsole::getConsole(); 16 + $key_count = 0; 17 + 18 + $options = PhabricatorApplicationConfigOptions::loadAllOptions(); 19 + $local_config = new PhabricatorConfigLocalSource(); 20 + $database_config = new PhabricatorConfigDatabaseSource('default'); 21 + $config_sources = PhabricatorEnv::getConfigSourceStack()->getStack(); 22 + $console->writeOut( 23 + pht('Migrating file-based config to more modern config...')."\n"); 24 + foreach ($config_sources as $config_source) { 25 + if (!($config_source instanceof PhabricatorConfigFileSource)) { 26 + $console->writeOut( 27 + pht('Skipping config of source type %s...', 28 + get_class($config_source))."\n"); 29 + continue; 30 + } 31 + $console->writeOut(pht('Migrating file source...')."\n"); 32 + $all_keys = $config_source->getAllKeys(); 33 + foreach ($all_keys as $key => $value) { 34 + $option = idx($options, $key); 35 + if (!$option) { 36 + $console->writeOut(pht('Skipping obsolete option: %s', $key)."\n"); 37 + continue; 38 + } 39 + $in_local = $local_config->getKeys(array($option->getKey())); 40 + if ($in_local) { 41 + $console->writeOut(pht( 42 + 'Skipping option "%s"; already in local config.', $key)."\n"); 43 + continue; 44 + } 45 + $is_locked = $option->getLocked(); 46 + if ($is_locked) { 47 + $local_config->setKeys(array($option->getKey() => $value)); 48 + $key_count++; 49 + $console->writeOut(pht( 50 + 'Migrated option "%s" from file to local config.', $key)."\n"); 51 + } else { 52 + $in_database = $database_config->getKeys(array($option->getKey())); 53 + if ($in_database) { 54 + $console->writeOut(pht( 55 + 'Skipping option "%s"; already in database config.', $key)."\n"); 56 + continue; 57 + } else { 58 + PhabricatorConfigEditor::deleteConfig( 59 + $this->getViewer(), 60 + $option, 61 + PhabricatorContentSource::newFromConsole()); 62 + $key_count++; 63 + $console->writeOut(pht( 64 + 'Migrated option "%s" from file to local config.', $key)."\n"); 65 + } 66 + } 67 + } 68 + } 69 + 70 + $console->writeOut(pht( 71 + 'Done. Migrated %d keys.', $key_count)."\n"); 72 + return 0; 73 + } 74 + 75 + }
+51 -20
src/applications/config/management/PhabricatorConfigManagementSetWorkflow.php
··· 7 7 $this 8 8 ->setName('set') 9 9 ->setExamples('**set** __key__ __value__') 10 - ->setSynopsis('Set a local configuration value.') 10 + ->setSynopsis(pht('Set a local configuration value.')) 11 11 ->setArguments( 12 12 array( 13 + array( 14 + 'name' => 'database', 15 + 'help' => pht('Update configuration in the database instead of '. 16 + 'in local configuration.'), 17 + ), 13 18 array( 14 19 'name' => 'args', 15 20 'wildcard' => true, ··· 21 26 $console = PhutilConsole::getConsole(); 22 27 $argv = $args->getArg('args'); 23 28 if (count($argv) == 0) { 24 - throw new PhutilArgumentUsageException( 25 - 'Specify a configuration key and a value to set it to.'); 29 + throw new PhutilArgumentUsageException(pht( 30 + 'Specify a configuration key and a value to set it to.')); 26 31 } 27 32 28 33 $key = $argv[0]; 29 34 30 35 if (count($argv) == 1) { 31 - throw new PhutilArgumentUsageException( 32 - "Specify a value to set the key '{$key}' to."); 36 + throw new PhutilArgumentUsageException(pht( 37 + "Specify a value to set the key '%s' to.", 38 + $key)); 33 39 } 34 40 35 41 $value = $argv[1]; 36 42 37 43 if (count($argv) > 2) { 38 - throw new PhutilArgumentUsageException( 39 - 'Too many arguments: expected one key and one value.'); 44 + throw new PhutilArgumentUsageException(pht( 45 + 'Too many arguments: expected one key and one value.')); 40 46 } 41 47 42 48 $options = PhabricatorApplicationConfigOptions::loadAllOptions(); 43 49 if (empty($options[$key])) { 44 - throw new PhutilArgumentUsageException( 45 - "No such configuration key '{$key}'! Use `config list` to list all ". 46 - "keys."); 50 + throw new PhutilArgumentUsageException(pht( 51 + "No such configuration key '%s'! Use `config list` to list all ". 52 + "keys.", 53 + $key)); 47 54 } 48 55 49 56 $option = $options[$key]; ··· 57 64 break; 58 65 case 'int': 59 66 if (!ctype_digit($value)) { 60 - throw new PhutilArgumentUsageException( 61 - "Config key '{$key}' is of type '{$type}'. Specify an integer."); 67 + throw new PhutilArgumentUsageException(pht( 68 + "Config key '%s' is of type '%s'. Specify an integer.", 69 + $key, 70 + $type)); 62 71 } 63 72 $value = (int)$value; 64 73 break; ··· 68 77 } else if ($value == 'false') { 69 78 $value = false; 70 79 } else { 71 - throw new PhutilArgumentUsageException( 72 - "Config key '{$key}' is of type '{$type}'. ". 73 - "Specify 'true' or 'false'."); 80 + throw new PhutilArgumentUsageException(pht( 81 + "Config key '%s' is of type '%s'. ". 82 + "Specify 'true' or 'false'.", 83 + $key, 84 + $type)); 74 85 } 75 86 break; 76 87 default: 77 88 $value = json_decode($value, true); 78 89 if (!is_array($value)) { 79 - throw new PhutilArgumentUsageException( 80 - "Config key '{$key}' is of type '{$type}'. Specify it in JSON."); 90 + throw new PhutilArgumentUsageException(pht( 91 + "Config key '%s' is of type '%s'. Specify it in JSON.", 92 + $key, 93 + $type)); 81 94 } 82 95 break; 96 + } 97 + $use_database = $args->getArg('database'); 98 + if ($option->getLocked() && $use_database) { 99 + throw new PhutilArgumentUsageException(pht( 100 + "Config key '%s' is locked and can only be set in local ". 101 + 'configuration.', 102 + $key)); 83 103 } 84 104 85 105 try { ··· 89 109 throw new PhutilArgumentUsageException($validation->getMessage()); 90 110 } 91 111 92 - $config = new PhabricatorConfigLocalSource(); 93 - $config->setKeys(array($key => $value)); 112 + if ($use_database) { 113 + $config_type = 'database'; 114 + PhabricatorConfigEditor::storeNewValue( 115 + $this->getViewer(), 116 + id(new PhabricatorConfigEntry()) 117 + ->loadOneWhere('namespace = %s AND key = %s', 'default', $key), 118 + $value, 119 + PhabricatorContentSource::newConsoleSource()); 120 + } else { 121 + $config_type = 'local'; 122 + id(new PhabricatorConfigLocalSource()) 123 + ->setKeys(array($key => $value)); 124 + } 94 125 95 126 $console->writeOut( 96 - pht("Set '%s' in local configuration.", $key)."\n"); 127 + pht("Set '%s' in %s configuration.", $key, $config_type)."\n"); 97 128 } 98 129 99 130 }
+2 -1
src/applications/meta/controller/PhabricatorApplicationEditController.php
··· 104 104 PhabricatorPolicyCapability::CAN_EDIT); 105 105 106 106 PhabricatorConfigEditor::storeNewValue( 107 + $user, 107 108 $config_entry, 108 109 $value, 109 - $this->getRequest()); 110 + PhabricatorContentSource::newFromRequest($this->getRequest())); 110 111 } 111 112 112 113 return id(new AphrontRedirectResponse())->setURI($view_uri);
+4 -1
src/applications/meta/controller/PhabricatorApplicationUninstallController.php
··· 90 90 } 91 91 92 92 PhabricatorConfigEditor::storeNewValue( 93 - $config_entry, $list, $this->getRequest()); 93 + $this->getRequest()->getUser(), 94 + $config_entry, 95 + $list, 96 + PhabricatorContentSource::newFromRequest($this->getRequest())); 94 97 } 95 98 96 99 }