Skip to content

Commit baa9d96

Browse files
author
epriestley
committedJan 21, 2013
Increase the power of bin/config
Summary: Fixes T2254. Make the CLI for config more powerful: - Add validation for `set`. - Add `get`. - Add `list`. - Add `delete`. The `get` command produces fairly verbose JSON to support flags like `--all`, or `--source database` later. The other commands are straightforward. Test Plan: Tested `config set`: $ ./bin/config set Usage Exception: Specify a configuration key and a value to set it to. $ ./bin/config set x Usage Exception: Specify a value to set the key 'x' to. $ ./bin/config set phabricator.base-uri Usage Exception: Specify a value to set the key 'phabricator.base-uri' to. $ ./bin/config set phabricator.base-uri x Usage Exception: Config option 'phabricator.base-uri' is invalid. The URI must start with 'http://' or 'https://'. $ ./bin/config set phabricator.base-uri http://x Usage Exception: Config option 'phabricator.base-uri' is invalid. The URI must contain a dot ('.'), like 'http://example.com/', not just a bare name like 'http://example/'. Some web browsers will not set cookies on domains with no TLD. $ ./bin/config set phabricator.base-uri http://x.com Set 'phabricator.base-uri' in local configuration. $ Tested `config get`: $ ./bin/config get pygments.enabled { "config" : [] } $ ./bin/config set pygments.enabled true Set 'pygments.enabled' in local configuration. $ ./bin/config get pygments.enabled { "config" : [ { "key" : "pygments.enabled", "source" : "local", "value" : true } ] } $ Tested `config delete`: $ ./bin/config delete Usage Exception: Specify a configuration key to delete. $ ./bin/config delete x x Usage Exception: Too many arguments: expected one key. $ ./bin/config delete x Usage Exception: No such configuration key 'x'! Use `config list` to list all keys. $ ./bin/config delete pygments.enabled Deleted 'pygments.enabled' from local configuration. $ ./bin/config delete pygments.enabled Usage Exception: Configuration key 'pygments.enabled' is not set in local configuration! $ Tested `config list`: $ ./bin/config list account.editable account.minimum-password-length amazon-ec2.access-key amazon-ec2.secret-key amazon-s3.access-key amazon-s3.endpoint amazon-s3.secret-key amazon-ses.access-key amazon-ses.secret-key aphront.default-application-configuration-class audit.can-author-close-audit auth.email-domains auth.login-message auth.password-auth-enabled auth.require-email-verification auth.sessions.conduit auth.sessions.web auth.sshkeys.enabled cache.enable-deflate celerity.force-disk-reads celerity.minify celerity.resource-hash celerity.resource-path config.hide config.lock config.mask controller.oauth-registration darkconsole.always-on darkconsole.enabled debug.profile-rate debug.stop-on-redirect differential.allow-reopen differential.allow-self-accept differential.always-allow-close differential.anonymous-access differential.custom-remarkup-block-rules differential.custom-remarkup-rules differential.days-fresh differential.days-stale differential.enable-email-accept differential.expose-emails-prudently differential.field-selector differential.generated-paths differential.require-test-plan-field differential.revision-custom-detail-renderer differential.show-host-field differential.show-test-plan-field differential.whitespace-matters disqus.application-id disqus.application-secret disqus.auth-enabled disqus.auth-permanent disqus.registration-enabled disqus.shortname environment.append-paths events.listeners facebook.application-id facebook.application-secret facebook.auth-enabled facebook.auth-permanent facebook.registration-enabled facebook.require-https-auth feed.http-hooks feed.public files.image-mime-types files.viewable-mime-types gcdaemon.ttl.daemon-logs gcdaemon.ttl.differential-parse-cache gcdaemon.ttl.general-cache gcdaemon.ttl.herald-transcripts gcdaemon.ttl.markup-cache gcdaemon.ttl.task-archive github.application-id github.application-secret github.auth-enabled github.auth-permanent github.registration-enabled google.application-id google.application-secret google.auth-enabled google.auth-permanent google.registration-enabled ldap.activedirectory_domain ldap.anonymous-user-name ldap.anonymous-user-password ldap.auth-enabled ldap.base_dn ldap.hostname ldap.port ldap.real_name_attributes ldap.referrals ldap.search-first ldap.search_attribute ldap.start-tls ldap.username-attribute ldap.version load-libraries log.access.format log.access.path maniphest.custom-fields maniphest.custom-task-extensions-class maniphest.default-priority maniphest.enabled metamta.can-send-as-user metamta.default-address metamta.differential.attach-patches metamta.differential.inline-patches metamta.differential.patch-format metamta.differential.reply-handler metamta.differential.reply-handler-domain metamta.differential.subject-prefix metamta.differential.unified-comment-context metamta.diffusion.attach-patches metamta.diffusion.byte-limit metamta.diffusion.inline-patches metamta.diffusion.reply-handler metamta.diffusion.reply-handler-domain metamta.diffusion.subject-prefix metamta.diffusion.time-limit metamta.domain metamta.herald.show-hints metamta.insecure-auth-with-reply-to metamta.macro.reply-handler-domain metamta.macro.subject-prefix metamta.mail-adapter metamta.maniphest.default-public-author metamta.maniphest.public-create-email metamta.maniphest.reply-handler metamta.maniphest.reply-handler-domain metamta.maniphest.subject-prefix metamta.one-mail-per-recipient metamta.package.reply-handler metamta.package.subject-prefix metamta.pholio.reply-handler-domain metamta.pholio.subject-prefix metamta.placeholder-to-recipient metamta.precedence-bulk metamta.public-replies metamta.re-prefix metamta.recipients.show-hints metamta.reply.show-hints metamta.send-immediately metamta.single-reply-handler-prefix metamta.user-address-format metamta.vary-subjects mysql.configuration-provider mysql.host mysql.implementation mysql.pass mysql.user notification.client-uri notification.debug notification.enabled notification.log notification.pidfile notification.server-uri notification.user phabricator.application-id phabricator.application-secret phabricator.auth-enabled phabricator.auth-permanent phabricator.base-uri phabricator.csrf-key phabricator.env phabricator.mail-key phabricator.oauth-uri phabricator.production-uri phabricator.registration-enabled phabricator.serious-business phabricator.setup phabricator.show-beta-applications phabricator.show-error-callout phabricator.show-stack-traces phabricator.timezone phame.skins phd.log-directory phd.pid-directory phd.start-taskmasters phd.trace phd.verbose phid.external-loaders phpmailer.mailer phpmailer.smtp-host phpmailer.smtp-password phpmailer.smtp-port phpmailer.smtp-protocol phpmailer.smtp-user phriction.enabled policy.allow-public pygments.dropdown-choices pygments.enabled recaptcha.enabled recaptcha.private-key recaptcha.public-key remarkup.enable-embedded-youtube repository.default-local-path search.elastic.host search.engine-selector security.alternate-file-domain security.hmac-key security.require-https sendgrid.api-key sendgrid.api-user storage.default-namespace storage.engine-selector storage.local-disk.path storage.mysql-engine.max-size storage.s3.bucket storage.upload-size-limit style.monospace syntax-highlighter.engine syntax.filemap test.value tokenizer.ondemand translation.override translation.provider uri.allowed-protocols $ Reviewers: btrahan, codeblock Reviewed By: btrahan CC: aran Maniphest Tasks: T2254 Differential Revision: https://secure.phabricator.com/D4570
1 parent 08e61c6 commit baa9d96

9 files changed

+254
-53
lines changed
 

‎scripts/setup/manage_config.php

+3
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,10 @@
1515
$args->parseStandardArguments();
1616

1717
$workflows = array(
18+
new PhabricatorConfigManagementListWorkflow(),
1819
new PhabricatorConfigManagementSetWorkflow(),
20+
new PhabricatorConfigManagementGetWorkflow(),
21+
new PhabricatorConfigManagementDeleteWorkflow(),
1922
new PhutilHelpArgumentWorkflow(),
2023
);
2124

‎src/__phutil_library_map__.php

+8-2
Original file line numberDiff line numberDiff line change
@@ -719,8 +719,11 @@
719719
'PhabricatorConfigJSON' => 'applications/config/json/PhabricatorConfigJSON.php',
720720
'PhabricatorConfigListController' => 'applications/config/controller/PhabricatorConfigListController.php',
721721
'PhabricatorConfigLocalSource' => 'infrastructure/env/PhabricatorConfigLocalSource.php',
722-
'PhabricatorConfigManagementSetWorkflow' => 'infrastructure/env/management/PhabricatorConfigManagementSetWorkflow.php',
723-
'PhabricatorConfigManagementWorkflow' => 'infrastructure/env/management/PhabricatorConfigManagementWorkflow.php',
722+
'PhabricatorConfigManagementDeleteWorkflow' => 'applications/config/management/PhabricatorConfigManagementDeleteWorkflow.php',
723+
'PhabricatorConfigManagementGetWorkflow' => 'applications/config/management/PhabricatorConfigManagementGetWorkflow.php',
724+
'PhabricatorConfigManagementListWorkflow' => 'applications/config/management/PhabricatorConfigManagementListWorkflow.php',
725+
'PhabricatorConfigManagementSetWorkflow' => 'applications/config/management/PhabricatorConfigManagementSetWorkflow.php',
726+
'PhabricatorConfigManagementWorkflow' => 'applications/config/management/PhabricatorConfigManagementWorkflow.php',
724727
'PhabricatorConfigOption' => 'applications/config/option/PhabricatorConfigOption.php',
725728
'PhabricatorConfigProxySource' => 'infrastructure/env/PhabricatorConfigProxySource.php',
726729
'PhabricatorConfigSource' => 'infrastructure/env/PhabricatorConfigSource.php',
@@ -2117,6 +2120,9 @@
21172120
'PhabricatorConfigIssueViewController' => 'PhabricatorConfigController',
21182121
'PhabricatorConfigListController' => 'PhabricatorConfigController',
21192122
'PhabricatorConfigLocalSource' => 'PhabricatorConfigProxySource',
2123+
'PhabricatorConfigManagementDeleteWorkflow' => 'PhabricatorConfigManagementWorkflow',
2124+
'PhabricatorConfigManagementGetWorkflow' => 'PhabricatorConfigManagementWorkflow',
2125+
'PhabricatorConfigManagementListWorkflow' => 'PhabricatorConfigManagementWorkflow',
21202126
'PhabricatorConfigManagementSetWorkflow' => 'PhabricatorConfigManagementWorkflow',
21212127
'PhabricatorConfigManagementWorkflow' => 'PhutilArgumentWorkflow',
21222128
'PhabricatorConfigOption' =>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
<?php
2+
3+
final class PhabricatorConfigManagementDeleteWorkflow
4+
extends PhabricatorConfigManagementWorkflow {
5+
6+
protected function didConstruct() {
7+
$this
8+
->setName('delete')
9+
->setExamples('**delete** __key__')
10+
->setSynopsis('Delete a local configuration value.')
11+
->setArguments(
12+
array(
13+
array(
14+
'name' => 'args',
15+
'wildcard' => true,
16+
),
17+
));
18+
}
19+
20+
public function execute(PhutilArgumentParser $args) {
21+
$console = PhutilConsole::getConsole();
22+
23+
$argv = $args->getArg('args');
24+
if (count($argv) == 0) {
25+
throw new PhutilArgumentUsageException(
26+
"Specify a configuration key to delete.");
27+
}
28+
29+
$key = $argv[0];
30+
31+
if (count($argv) > 1) {
32+
throw new PhutilArgumentUsageException(
33+
"Too many arguments: expected one key.");
34+
}
35+
36+
$options = PhabricatorApplicationConfigOptions::loadAllOptions();
37+
if (empty($options[$key])) {
38+
throw new PhutilArgumentUsageException(
39+
"No such configuration key '{$key}'! Use `config list` to list all ".
40+
"keys.");
41+
}
42+
43+
$config = new PhabricatorConfigLocalSource();
44+
$values = $config->getKeys(array($key));
45+
if (!$values) {
46+
throw new PhutilArgumentUsageException(
47+
"Configuration key '{$key}' is not set in local configuration!");
48+
}
49+
50+
$config->deleteKeys(array($key));
51+
52+
$console->writeOut(
53+
pht("Deleted '%s' from local configuration.", $key)."\n");
54+
}
55+
56+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
<?php
2+
3+
final class PhabricatorConfigManagementGetWorkflow
4+
extends PhabricatorConfigManagementWorkflow {
5+
6+
protected function didConstruct() {
7+
$this
8+
->setName('get')
9+
->setExamples('**get** __key__')
10+
->setSynopsis('Get a local configuration value.')
11+
->setArguments(
12+
array(
13+
array(
14+
'name' => 'args',
15+
'wildcard' => true,
16+
),
17+
));
18+
}
19+
20+
public function execute(PhutilArgumentParser $args) {
21+
$console = PhutilConsole::getConsole();
22+
23+
$argv = $args->getArg('args');
24+
if (count($argv) == 0) {
25+
throw new PhutilArgumentUsageException(
26+
"Specify a configuration key to get.");
27+
}
28+
29+
$key = $argv[0];
30+
31+
if (count($argv) > 1) {
32+
throw new PhutilArgumentUsageException(
33+
"Too many arguments: expected one key.");
34+
}
35+
36+
$options = PhabricatorApplicationConfigOptions::loadAllOptions();
37+
if (empty($options[$key])) {
38+
throw new PhutilArgumentUsageException(
39+
"No such configuration key '{$key}'! Use `config list` to list all ".
40+
"keys.");
41+
}
42+
43+
$config = new PhabricatorConfigLocalSource();
44+
$values = $config->getKeys(array($key));
45+
46+
$result = array();
47+
foreach ($values as $key => $value) {
48+
$result[] = array(
49+
'key' => $key,
50+
'source' => 'local',
51+
'value' => $value,
52+
);
53+
}
54+
$result = array(
55+
'config' => $result,
56+
);
57+
58+
$json = new PhutilJSON();
59+
$console->writeOut($json->encodeFormatted($result));
60+
}
61+
62+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
3+
final class PhabricatorConfigManagementListWorkflow
4+
extends PhabricatorConfigManagementWorkflow {
5+
6+
protected function didConstruct() {
7+
$this
8+
->setName('list')
9+
->setExamples('**list**')
10+
->setSynopsis('List all configuration keys.');
11+
}
12+
13+
public function execute(PhutilArgumentParser $args) {
14+
$options = PhabricatorApplicationConfigOptions::loadAllOptions();
15+
ksort($options);
16+
17+
$console = PhutilConsole::getConsole();
18+
foreach ($options as $option) {
19+
$console->writeOut($option->getKey()."\n");
20+
}
21+
22+
return 0;
23+
}
24+
25+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
<?php
2+
3+
final class PhabricatorConfigManagementSetWorkflow
4+
extends PhabricatorConfigManagementWorkflow {
5+
6+
protected function didConstruct() {
7+
$this
8+
->setName('set')
9+
->setExamples('**set** __key__ __value__')
10+
->setSynopsis('Set a local configuration value.')
11+
->setArguments(
12+
array(
13+
array(
14+
'name' => 'args',
15+
'wildcard' => true,
16+
),
17+
));
18+
}
19+
20+
public function execute(PhutilArgumentParser $args) {
21+
$console = PhutilConsole::getConsole();
22+
23+
$argv = $args->getArg('args');
24+
if (count($argv) == 0) {
25+
throw new PhutilArgumentUsageException(
26+
"Specify a configuration key and a value to set it to.");
27+
}
28+
29+
$key = $argv[0];
30+
31+
if (count($argv) == 1) {
32+
throw new PhutilArgumentUsageException(
33+
"Specify a value to set the key '{$key}' to.");
34+
}
35+
36+
$value = $argv[1];
37+
38+
if (count($argv) > 2) {
39+
throw new PhutilArgumentUsageException(
40+
"Too many arguments: expected one key and one value.");
41+
}
42+
43+
$options = PhabricatorApplicationConfigOptions::loadAllOptions();
44+
if (empty($options[$key])) {
45+
throw new PhutilArgumentUsageException(
46+
"No such configuration key '{$key}'! Use `config list` to list all ".
47+
"keys.");
48+
}
49+
50+
$option = $options[$key];
51+
52+
$type = $option->getType();
53+
switch ($type) {
54+
case 'string':
55+
case 'class':
56+
$value = (string)$value;
57+
break;
58+
case 'int':
59+
if (!ctype_digit($value)) {
60+
throw new PhutilArgumentUsageException(
61+
"Config key '{$key}' is of type '{$type}'. Specify an integer.");
62+
}
63+
$value = (int)$value;
64+
break;
65+
case 'bool':
66+
if ($value == 'true') {
67+
$value = true;
68+
} else if ($value == 'false') {
69+
$value = false;
70+
} else {
71+
throw new PhutilArgumentUsageException(
72+
"Config key '{$key}' is of type '{$type}'. ".
73+
"Specify 'true' or 'false'.");
74+
}
75+
break;
76+
default:
77+
$value = json_decode($value, true);
78+
if (!is_array($value)) {
79+
throw new PhutilArgumentUsageException(
80+
"Config key '{$key}' is of type '{$type}'. Specify it in JSON.");
81+
}
82+
break;
83+
}
84+
85+
try {
86+
$option->getGroup()->validateOption($option, $value);
87+
} catch (PhabricatorConfigValidationException $validation) {
88+
// Convert this into a usage exception so we don't dump a stack trace.
89+
throw new PhutilArgumentUsageException($validation->getMessage());
90+
}
91+
92+
$config = new PhabricatorConfigLocalSource();
93+
$config->setKeys(array($key => $value));
94+
95+
$console->writeOut(
96+
pht("Set '%s' in local configuration.", $key)."\n");
97+
}
98+
99+
}

‎src/infrastructure/env/PhabricatorConfigProxySource.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ public function setKeys(array $keys) {
3838
}
3939

4040
public function deleteKeys(array $keys) {
41-
$this->getSource()->deleteKeys();
41+
$this->getSource()->deleteKeys($keys);
4242
return $this;
4343
}
4444

‎src/infrastructure/env/management/PhabricatorConfigManagementSetWorkflow.php

-50
This file was deleted.

0 commit comments

Comments
 (0)
Failed to load comments.