mirror of
https://we.phorge.it/source/arcanist.git
synced 2024-12-01 19:22:41 +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".
|
||||
$components = preg_replace(
|
||||
'('.preg_quote(DIRECTORY_SEPARATOR).'{2,})',
|
||||
DIRECTORY_SEPARATOR);
|
||||
DIRECTORY_SEPARATOR,
|
||||
$components);
|
||||
|
||||
return $components;
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ final class ArcanistGitWorkingCopy
|
|||
$working_directory,
|
||||
$ancestor_directory) {
|
||||
|
||||
if (!Filesystem::pathExits($ancestor_directory.'/.git')) {
|
||||
if (!Filesystem::pathExists($ancestor_directory.'/.git')) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ final class ArcanistMercurialWorkingCopy
|
|||
$working_directory,
|
||||
$ancestor_directory) {
|
||||
|
||||
if (!Filesystem::pathExits($ancestor_directory.'/.hg')) {
|
||||
if (!Filesystem::pathExists($ancestor_directory.'/.hg')) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
@ -39,11 +39,11 @@ final class ArcanistSubversionWorkingCopy
|
|||
$working_directory,
|
||||
$ancestor_directory) {
|
||||
|
||||
if (!Filesystem::pathExits($ancestor_directory.'/.svn')) {
|
||||
if (!Filesystem::pathExists($ancestor_directory.'/.svn')) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return id(new self());
|
||||
return new self();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ abstract class ArcanistWorkingCopy
|
|||
|
||||
public static function newFromWorkingDirectory($path) {
|
||||
$working_types = id(new PhutilClassMapQuery())
|
||||
->setParentClass(__CLASS__)
|
||||
->setAncestorClass(__CLASS__)
|
||||
->execute();
|
||||
|
||||
// Find the outermost directory which is under version control. We go from
|
||||
|
|
|
@ -45,6 +45,14 @@ final class ArcanistRuntime {
|
|||
'repeat' => true,
|
||||
'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))
|
||||
|
@ -202,9 +210,10 @@ final class ArcanistRuntime {
|
|||
}
|
||||
|
||||
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) {
|
||||
$engine->setWorkingCopy($working_copy);
|
||||
}
|
||||
|
@ -214,28 +223,16 @@ final class ArcanistRuntime {
|
|||
|
||||
private function loadLibraries(
|
||||
PhutilArgumentParser $args,
|
||||
ArcanistConfigurationManager $config) {
|
||||
ArcanistConfigurationSourceList $config) {
|
||||
|
||||
// TOOLSETS: Make this work again -- or replace it entirely with package
|
||||
// management?
|
||||
return;
|
||||
|
||||
$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();
|
||||
$working_copy = $config->getWorkingCopyIdentity();
|
||||
$working_copy = $this->getWorkingCopy();
|
||||
|
||||
$cli_libraries = $args->getArg('library');
|
||||
if ($cli_libraries) {
|
||||
|
@ -463,7 +460,7 @@ final class ArcanistRuntime {
|
|||
private function resolveAliases(
|
||||
array $workflows,
|
||||
array $argv,
|
||||
ArcanistConfigurationManager $config) {
|
||||
ArcanistConfigurationSourceList $config) {
|
||||
|
||||
$command = head($argv);
|
||||
|
||||
|
|
Loading…
Reference in a new issue