mirror of
https://we.phorge.it/source/arcanist.git
synced 2024-11-09 00:12:40 +01:00
[Wilds] Prepare for more modular configuration management
Summary: Ref T13098. This is kind of a catch-all diff with stuff that didn't fit in prior diffs, and which fixes some bugs with that stuff now that I made it at least sort of reachable. Beyond bugs, the general idea is to replace `ConfigurationManager` (a big class which knew about config-end-to-end) with a more modern/modular `ConfigurationEngine` using the standard Engine + EngineExtension modularity pattern. Configuration becomes a `ConfigurationSourceList` of `ConfigurationSource` objects, each of which represents one source (a config file, `--config x=y`, etc). The various sources will have the logic to parse values (e.g., decode `x=y` flags or JSON files on disk). A new `--config-file` allows you to replace the system (`/etc/arcconfig`) and user (`~/.arcrc`) files. This also gets rid of `--library` support entirely for now since it's kind of messy to bridge until Config works. I expect to either restore it or replace it with `arc install` and similar. Test Plan: Ran `arc liberate`; it actually works now. (The Config stuff does not actually work yet.) Reviewers: amckinley Reviewed By: amckinley Maniphest Tasks: T13098 Differential Revision: https://secure.phabricator.com/D19694
This commit is contained in:
parent
11599cedb6
commit
412484022b
23 changed files with 765 additions and 534 deletions
File diff suppressed because it is too large
Load diff
6
src/config/ArcanistArcConfigurationEngineExtension.php
Normal file
6
src/config/ArcanistArcConfigurationEngineExtension.php
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class ArcanistArcConfigurationEngineExtension
|
||||||
|
extends ArcanistConfigurationEngineExtension {
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class ArcanistConduitConfigurationEngineExtension
|
||||||
|
extends ArcanistConfigurationEngineExtension {
|
||||||
|
|
||||||
|
}
|
6
src/config/ArcanistConfigOption.php
Normal file
6
src/config/ArcanistConfigOption.php
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
abstract class ArcanistConfigOption
|
||||||
|
extends Phobject {
|
||||||
|
|
||||||
|
}
|
98
src/config/ArcanistConfigurationEngine.php
Normal file
98
src/config/ArcanistConfigurationEngine.php
Normal file
|
@ -0,0 +1,98 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class ArcanistConfigurationEngine
|
||||||
|
extends Phobject {
|
||||||
|
|
||||||
|
private $workingCopy;
|
||||||
|
private $arguments;
|
||||||
|
|
||||||
|
public function setWorkingCopy(ArcanistWorkingCopy $working_copy) {
|
||||||
|
$this->workingCopy = $working_copy;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getWorkingCopy() {
|
||||||
|
return $this->workingCopy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setArguments(PhutilArgumentParser $arguments) {
|
||||||
|
$this->arguments = $arguments;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getArguments() {
|
||||||
|
if (!$this->arguments) {
|
||||||
|
throw new PhutilInvalidStateException('setArguments');
|
||||||
|
}
|
||||||
|
return $this->arguments;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function newConfigurationSourceList() {
|
||||||
|
$list = new ArcanistConfigurationSourceList();
|
||||||
|
|
||||||
|
$list->addSource(new ArcanistDefaultsConfigurationSource());
|
||||||
|
|
||||||
|
$arguments = $this->getArguments();
|
||||||
|
|
||||||
|
// If the invoker has provided one or more configuration files with
|
||||||
|
// "--config-file" arguments, read those files instead of the system
|
||||||
|
// and user configuration files. Otherwise, read the system and user
|
||||||
|
// configuration files.
|
||||||
|
|
||||||
|
$config_files = $arguments->getArg('config-file');
|
||||||
|
if ($config_files) {
|
||||||
|
foreach ($config_files as $config_file) {
|
||||||
|
$list->addSource(new ArcanistFileConfigurationSource($config_file));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$system_path = $this->getSystemConfigurationFilePath();
|
||||||
|
$list->addSource(new ArcanistSystemConfigurationSource($system_path));
|
||||||
|
|
||||||
|
$user_path = $this->getUserConfigurationFilePath();
|
||||||
|
$list->addSource(new ArcanistUserConfigurationSource($user_path));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// If we're running in a working copy, load the ".arcconfig" and any
|
||||||
|
// local configuration.
|
||||||
|
$working_copy = $this->getWorkingCopy();
|
||||||
|
if ($working_copy) {
|
||||||
|
$project_path = $working_copy->getProjectConfigurationFilePath();
|
||||||
|
if ($project_path !== null) {
|
||||||
|
$list->addSource(new ArcanistProjectConfigurationSource($project_path));
|
||||||
|
}
|
||||||
|
|
||||||
|
$local_path = $working_copy->getLocalConfigurationFilePath();
|
||||||
|
if ($local_path !== null) {
|
||||||
|
$list->addSource(new ArcanistLocalConfigurationSource($local_path));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the invoker has provided "--config" arguments, parse those now.
|
||||||
|
$runtime_args = $arguments->getArg('config');
|
||||||
|
if ($runtime_args) {
|
||||||
|
$list->addSource(new ArcanistRuntimeConfigurationSource($runtime_args));
|
||||||
|
}
|
||||||
|
|
||||||
|
return $list;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getSystemConfigurationFilePath() {
|
||||||
|
if (phutil_is_windows()) {
|
||||||
|
return Filesystem::resolvePath(
|
||||||
|
'Phabricator/Arcanist/config',
|
||||||
|
getenv('ProgramData'));
|
||||||
|
} else {
|
||||||
|
return '/etc/arcconfig';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getUserConfigurationFilePath() {
|
||||||
|
if (phutil_is_windows()) {
|
||||||
|
return getenv('APPDATA').'/.arcrc';
|
||||||
|
} else {
|
||||||
|
return getenv('HOME').'/.arcrc';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
6
src/config/ArcanistConfigurationEngineExtension.php
Normal file
6
src/config/ArcanistConfigurationEngineExtension.php
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class ArcanistConfigurationEngineExtension
|
||||||
|
extends Phobject {
|
||||||
|
|
||||||
|
}
|
13
src/config/ArcanistConfigurationSourceList.php
Normal file
13
src/config/ArcanistConfigurationSourceList.php
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class ArcanistConfigurationSourceList
|
||||||
|
extends Phobject {
|
||||||
|
|
||||||
|
private $sources = array();
|
||||||
|
|
||||||
|
public function addSource(ArcanistConfigurationSource $source) {
|
||||||
|
$this->sources[] = $source;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
6
src/config/source/ArcanistConfigurationSource.php
Normal file
6
src/config/source/ArcanistConfigurationSource.php
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
abstract class ArcanistConfigurationSource
|
||||||
|
extends Phobject {
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class ArcanistDefaultsConfigurationSource
|
||||||
|
extends ArcanistConfigurationSource {
|
||||||
|
|
||||||
|
}
|
6
src/config/source/ArcanistFileConfigurationSource.php
Normal file
6
src/config/source/ArcanistFileConfigurationSource.php
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class ArcanistFileConfigurationSource
|
||||||
|
extends ArcanistConfigurationSource {
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
abstract class ArcanistFilesystemConfigurationSource
|
||||||
|
extends ArcanistConfigurationSource {
|
||||||
|
|
||||||
|
}
|
6
src/config/source/ArcanistLocalConfigurationSource.php
Normal file
6
src/config/source/ArcanistLocalConfigurationSource.php
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class ArcanistLocalConfigurationSource
|
||||||
|
extends ArcanistWorkingCopyConfigurationSource {
|
||||||
|
|
||||||
|
}
|
6
src/config/source/ArcanistProjectConfigurationSource.php
Normal file
6
src/config/source/ArcanistProjectConfigurationSource.php
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class ArcanistProjectConfigurationSource
|
||||||
|
extends ArcanistWorkingCopyConfigurationSource {
|
||||||
|
|
||||||
|
}
|
6
src/config/source/ArcanistRuntimeConfigurationSource.php
Normal file
6
src/config/source/ArcanistRuntimeConfigurationSource.php
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class ArcanistRuntimeConfigurationSource
|
||||||
|
extends ArcanistConfigurationSource {
|
||||||
|
|
||||||
|
}
|
6
src/config/source/ArcanistSystemConfigurationSource.php
Normal file
6
src/config/source/ArcanistSystemConfigurationSource.php
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class ArcanistSystemConfigurationSource
|
||||||
|
extends ArcanistFilesystemConfigurationSource {
|
||||||
|
|
||||||
|
}
|
6
src/config/source/ArcanistUserConfigurationSource.php
Normal file
6
src/config/source/ArcanistUserConfigurationSource.php
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class ArcanistUserConfigurationSource
|
||||||
|
extends ArcanistFilesystemConfigurationSource {
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
abstract class ArcanistWorkingCopyConfigurationSource
|
||||||
|
extends ArcanistFilesystemConfigurationSource {
|
||||||
|
|
||||||
|
}
|
|
@ -1054,7 +1054,8 @@ final class Filesystem extends Phobject {
|
||||||
// separator, so we don't end up with "path//to///thing.c".
|
// separator, so we don't end up with "path//to///thing.c".
|
||||||
$components = preg_replace(
|
$components = preg_replace(
|
||||||
'('.preg_quote(DIRECTORY_SEPARATOR).'{2,})',
|
'('.preg_quote(DIRECTORY_SEPARATOR).'{2,})',
|
||||||
DIRECTORY_SEPARATOR);
|
DIRECTORY_SEPARATOR,
|
||||||
|
$components);
|
||||||
|
|
||||||
return $components;
|
return $components;
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@ final class ArcanistGitWorkingCopy
|
||||||
$working_directory,
|
$working_directory,
|
||||||
$ancestor_directory) {
|
$ancestor_directory) {
|
||||||
|
|
||||||
if (!Filesystem::pathExits($ancestor_directory.'/.git')) {
|
if (!Filesystem::pathExists($ancestor_directory.'/.git')) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ final class ArcanistMercurialWorkingCopy
|
||||||
$working_directory,
|
$working_directory,
|
||||||
$ancestor_directory) {
|
$ancestor_directory) {
|
||||||
|
|
||||||
if (!Filesystem::pathExits($ancestor_directory.'/.hg')) {
|
if (!Filesystem::pathExists($ancestor_directory.'/.hg')) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,11 +39,11 @@ final class ArcanistSubversionWorkingCopy
|
||||||
$working_directory,
|
$working_directory,
|
||||||
$ancestor_directory) {
|
$ancestor_directory) {
|
||||||
|
|
||||||
if (!Filesystem::pathExits($ancestor_directory.'/.svn')) {
|
if (!Filesystem::pathExists($ancestor_directory.'/.svn')) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return id(new self());
|
return new self();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ abstract class ArcanistWorkingCopy
|
||||||
|
|
||||||
public static function newFromWorkingDirectory($path) {
|
public static function newFromWorkingDirectory($path) {
|
||||||
$working_types = id(new PhutilClassMapQuery())
|
$working_types = id(new PhutilClassMapQuery())
|
||||||
->setParentClass(__CLASS__)
|
->setAncestorClass(__CLASS__)
|
||||||
->execute();
|
->execute();
|
||||||
|
|
||||||
// Find the outermost directory which is under version control. We go from
|
// Find the outermost directory which is under version control. We go from
|
||||||
|
|
|
@ -45,6 +45,14 @@ final class ArcanistRuntime {
|
||||||
'repeat' => true,
|
'repeat' => true,
|
||||||
'help' => pht('Specify a runtime configuration value.'),
|
'help' => pht('Specify a runtime configuration value.'),
|
||||||
),
|
),
|
||||||
|
array(
|
||||||
|
'name' => 'config-file',
|
||||||
|
'param' => 'path',
|
||||||
|
'repeat' => true,
|
||||||
|
'help' => pht(
|
||||||
|
'Load one or more configuration files. If this flag is provided, '.
|
||||||
|
'the system and user configuration files are ignored.'),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
$args = id(new PhutilArgumentParser($argv))
|
$args = id(new PhutilArgumentParser($argv))
|
||||||
|
@ -202,9 +210,10 @@ final class ArcanistRuntime {
|
||||||
}
|
}
|
||||||
|
|
||||||
private function loadConfiguration(PhutilArgumentParser $args) {
|
private function loadConfiguration(PhutilArgumentParser $args) {
|
||||||
$engine = new ArcanistConfigurationEngine();
|
$engine = id(new ArcanistConfigurationEngine())
|
||||||
|
->setArguments($args);
|
||||||
|
|
||||||
$working_copy = ArcanistWorkingCopyIdentity::newFromPath(getcwd());
|
$working_copy = ArcanistWorkingCopy::newFromWorkingDirectory(getcwd());
|
||||||
if ($working_copy) {
|
if ($working_copy) {
|
||||||
$engine->setWorkingCopy($working_copy);
|
$engine->setWorkingCopy($working_copy);
|
||||||
}
|
}
|
||||||
|
@ -214,28 +223,16 @@ final class ArcanistRuntime {
|
||||||
|
|
||||||
private function loadLibraries(
|
private function loadLibraries(
|
||||||
PhutilArgumentParser $args,
|
PhutilArgumentParser $args,
|
||||||
ArcanistConfigurationManager $config) {
|
ArcanistConfigurationSourceList $config) {
|
||||||
|
|
||||||
|
// TOOLSETS: Make this work again -- or replace it entirely with package
|
||||||
|
// management?
|
||||||
|
return;
|
||||||
|
|
||||||
$is_trace = $args->getArg('trace');
|
$is_trace = $args->getArg('trace');
|
||||||
|
|
||||||
if ($is_trace) {
|
|
||||||
$libraries = array(
|
|
||||||
'phutil',
|
|
||||||
'arcanist',
|
|
||||||
);
|
|
||||||
|
|
||||||
foreach ($libraries as $library_name) {
|
|
||||||
$this->logTrace(
|
|
||||||
pht('LOAD'),
|
|
||||||
pht(
|
|
||||||
'Loaded "%s" from "%s".',
|
|
||||||
$library_name,
|
|
||||||
phutil_get_library_root($library_name)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$load = array();
|
$load = array();
|
||||||
$working_copy = $config->getWorkingCopyIdentity();
|
$working_copy = $this->getWorkingCopy();
|
||||||
|
|
||||||
$cli_libraries = $args->getArg('library');
|
$cli_libraries = $args->getArg('library');
|
||||||
if ($cli_libraries) {
|
if ($cli_libraries) {
|
||||||
|
@ -463,7 +460,7 @@ final class ArcanistRuntime {
|
||||||
private function resolveAliases(
|
private function resolveAliases(
|
||||||
array $workflows,
|
array $workflows,
|
||||||
array $argv,
|
array $argv,
|
||||||
ArcanistConfigurationManager $config) {
|
ArcanistConfigurationSourceList $config) {
|
||||||
|
|
||||||
$command = head($argv);
|
$command = head($argv);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue