diff --git a/.gitignore b/.gitignore index db3e8a64e2..f6bc699d3f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,10 +1,6 @@ .DS_Store ._* -/docs/ -/src/.phutil_module_cache -/conf/custom/* /webroot/rsrc/custom -/.divinercache .#* *# *~ @@ -15,3 +11,15 @@ # Arcanist scratch directory /.arc + +# Diviner +/docs/ +/.divinercache + +# libphutil +/src/.phutil_module_cache + +# Configuration +/conf/custom/* +/conf/local/local.json +/conf/local/ENVIRONMENT diff --git a/bin/config b/bin/config new file mode 120000 index 0000000000..068eb7da38 --- /dev/null +++ b/bin/config @@ -0,0 +1 @@ +../scripts/setup/manage_config.php \ No newline at end of file diff --git a/conf/local/.keep b/conf/local/.keep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/scripts/setup/manage_config.php b/scripts/setup/manage_config.php new file mode 100755 index 0000000000..7e649a7ac1 --- /dev/null +++ b/scripts/setup/manage_config.php @@ -0,0 +1,22 @@ +#!/usr/bin/env php +setTagline('manage configuration'); +$args->setSynopsis(<<parseStandardArguments(); + +$workflows = array( + new PhabricatorConfigManagementSetWorkflow(), + new PhutilHelpArgumentWorkflow(), +); + +$args->parseWorkflows($workflows); diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index 8d816451cf..6834b6cb97 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -687,6 +687,9 @@ phutil_register_library_map(array( 'PhabricatorConfigEntryDAO' => 'applications/config/storage/PhabricatorConfigEntryDAO.php', 'PhabricatorConfigFileSource' => 'infrastructure/env/PhabricatorConfigFileSource.php', 'PhabricatorConfigListController' => 'applications/config/controller/PhabricatorConfigListController.php', + 'PhabricatorConfigLocalSource' => 'infrastructure/env/PhabricatorConfigLocalSource.php', + 'PhabricatorConfigManagementSetWorkflow' => 'infrastructure/env/management/PhabricatorConfigManagementSetWorkflow.php', + 'PhabricatorConfigManagementWorkflow' => 'infrastructure/env/management/PhabricatorConfigManagementWorkflow.php', 'PhabricatorConfigProxySource' => 'infrastructure/env/PhabricatorConfigProxySource.php', 'PhabricatorConfigSource' => 'infrastructure/env/PhabricatorConfigSource.php', 'PhabricatorConfigStackSource' => 'infrastructure/env/PhabricatorConfigStackSource.php', @@ -2000,6 +2003,9 @@ phutil_register_library_map(array( 'PhabricatorConfigEntryDAO' => 'PhabricatorLiskDAO', 'PhabricatorConfigFileSource' => 'PhabricatorConfigProxySource', 'PhabricatorConfigListController' => 'PhabricatorConfigController', + 'PhabricatorConfigLocalSource' => 'PhabricatorConfigProxySource', + 'PhabricatorConfigManagementSetWorkflow' => 'PhabricatorConfigManagementWorkflow', + 'PhabricatorConfigManagementWorkflow' => 'PhutilArgumentWorkflow', 'PhabricatorConfigProxySource' => 'PhabricatorConfigSource', 'PhabricatorConfigStackSource' => 'PhabricatorConfigSource', 'PhabricatorContentSourceView' => 'AphrontView', diff --git a/src/infrastructure/env/PhabricatorConfigLocalSource.php b/src/infrastructure/env/PhabricatorConfigLocalSource.php new file mode 100644 index 0000000000..8e3c524061 --- /dev/null +++ b/src/infrastructure/env/PhabricatorConfigLocalSource.php @@ -0,0 +1,51 @@ +loadConfig(); + $this->setSource(new PhabricatorConfigDictionarySource($config)); + } + + public function setKeys(array $keys) { + $result = parent::setKeys($keys); + $this->saveConfig(); + return $result; + } + + public function deleteKeys(array $keys) { + $result = parent::deleteKeys($keys); + $this->saveConfig(); + return parent::deleteKeys($keys); + } + + private function loadConfig() { + $path = $this->getConfigPath(); + if (@file_exists($path)) { + $data = @file_get_contents($path); + if ($data) { + $data = json_decode($data, true); + if (is_array($data)) { + return $data; + } + } + } + + return array(); + } + + private function saveConfig() { + $config = $this->getSource()->getAllKeys(); + $json = new PhutilJSON(); + $data = $json->encodeFormatted($config); + Filesystem::writeFile($this->getConfigPath(), $data); + } + + private function getConfigPath() { + $root = dirname(phutil_get_library_root('phabricator')); + $path = $root.'/conf/local/local.json'; + return $path; + } + +} diff --git a/src/infrastructure/env/PhabricatorConfigProxySource.php b/src/infrastructure/env/PhabricatorConfigProxySource.php index 15055d6cb9..953aebd5d5 100644 --- a/src/infrastructure/env/PhabricatorConfigProxySource.php +++ b/src/infrastructure/env/PhabricatorConfigProxySource.php @@ -29,15 +29,15 @@ abstract class PhabricatorConfigProxySource } public function canWrite() { - return $this->getSource->canWrite(); + return $this->getSource()->canWrite(); } public function setKeys(array $keys) { - return $this->getSource->setKeys(); + return $this->getSource()->setKeys($keys); } public function deleteKeys(array $keys) { - return $this->getSource->deleteKeys(); + return $this->getSource()->deleteKeys(); } } diff --git a/src/infrastructure/env/PhabricatorEnv.php b/src/infrastructure/env/PhabricatorEnv.php index 784736cf2e..60e259dff6 100644 --- a/src/infrastructure/env/PhabricatorEnv.php +++ b/src/infrastructure/env/PhabricatorEnv.php @@ -139,6 +139,14 @@ final class PhabricatorEnv { $env = idx($_ENV, $env_var); } + if (!$env) { + $root = dirname(phutil_get_library_root('phabricator')); + $path = $root.'/conf/local/ENVIRONMENT'; + if (Filesystem::pathExists($path)) { + $env = trim(Filesystem::readFile($path)); + } + } + return $env; } diff --git a/src/infrastructure/env/management/PhabricatorConfigManagementSetWorkflow.php b/src/infrastructure/env/management/PhabricatorConfigManagementSetWorkflow.php new file mode 100644 index 0000000000..c94db76958 --- /dev/null +++ b/src/infrastructure/env/management/PhabricatorConfigManagementSetWorkflow.php @@ -0,0 +1,50 @@ +setName('set') + ->setExamples('**set** __key__ __value__') + ->setSynopsis('Set a local configuration value.') + ->setArguments( + array( + array( + 'name' => 'args', + 'wildcard' => true, + ), + )); + } + + public function execute(PhutilArgumentParser $args) { + $console = PhutilConsole::getConsole(); + + $argv = $args->getArg('args'); + if (count($argv) == 0) { + throw new PhutilArgumentUsageException( + "Specify a configuration key and a value to set it to."); + } + + $key = $argv[0]; + + if (count($argv) == 1) { + throw new PhutilArgumentUsageException( + "Specify a value to set the key '{$key}' to."); + } + + $value = $argv[1]; + + if (count($argv) > 2) { + throw new PhutilArgumentUsageException( + "Too many arguments: expected one key and one value."); + } + + $config = new PhabricatorConfigLocalSource(); + $config->setKeys(array($key => $value)); + + $console->writeOut( + pht("Set '%s' to '%s' in local configuration.", $key, $value)."\n"); + } + +} diff --git a/src/infrastructure/env/management/PhabricatorConfigManagementWorkflow.php b/src/infrastructure/env/management/PhabricatorConfigManagementWorkflow.php new file mode 100644 index 0000000000..f984b0ea6e --- /dev/null +++ b/src/infrastructure/env/management/PhabricatorConfigManagementWorkflow.php @@ -0,0 +1,10 @@ +