mirror of
https://github.com/martinvonz/jj.git
synced 2025-01-19 19:08:08 +00:00
config: add convenient method to insert value into layer, migrate callers
Some checks are pending
binaries / Build binary artifacts (push) Waiting to run
nix / flake check (push) Waiting to run
build / build (, macos-13) (push) Waiting to run
build / build (, macos-14) (push) Waiting to run
build / build (, ubuntu-latest) (push) Waiting to run
build / build (, windows-latest) (push) Waiting to run
build / build (--all-features, ubuntu-latest) (push) Waiting to run
build / Build jj-lib without Git support (push) Waiting to run
build / Check protos (push) Waiting to run
build / Check formatting (push) Waiting to run
build / Check that MkDocs can build the docs (push) Waiting to run
build / Check that MkDocs can build the docs with latest Python and uv (push) Waiting to run
build / cargo-deny (advisories) (push) Waiting to run
build / cargo-deny (bans licenses sources) (push) Waiting to run
build / Clippy check (push) Waiting to run
Codespell / Codespell (push) Waiting to run
website / prerelease-docs-build-deploy (ubuntu-latest) (push) Waiting to run
Scorecards supply-chain security / Scorecards analysis (push) Waiting to run
Some checks are pending
binaries / Build binary artifacts (push) Waiting to run
nix / flake check (push) Waiting to run
build / build (, macos-13) (push) Waiting to run
build / build (, macos-14) (push) Waiting to run
build / build (, ubuntu-latest) (push) Waiting to run
build / build (, windows-latest) (push) Waiting to run
build / build (--all-features, ubuntu-latest) (push) Waiting to run
build / Build jj-lib without Git support (push) Waiting to run
build / Check protos (push) Waiting to run
build / Check formatting (push) Waiting to run
build / Check that MkDocs can build the docs (push) Waiting to run
build / Check that MkDocs can build the docs with latest Python and uv (push) Waiting to run
build / cargo-deny (advisories) (push) Waiting to run
build / cargo-deny (bans licenses sources) (push) Waiting to run
build / Clippy check (push) Waiting to run
Codespell / Codespell (push) Waiting to run
website / prerelease-docs-build-deploy (ubuntu-latest) (push) Waiting to run
Scorecards supply-chain security / Scorecards analysis (push) Waiting to run
The current implementation is silly, which will be reimplemented to be using toml_edit::DocumentMut. "jj config set" will probably be ported to this API.
This commit is contained in:
parent
4e1b71b6b1
commit
da3c75b3cb
3 changed files with 65 additions and 59 deletions
|
@ -358,21 +358,21 @@ pub fn config_from_environment(
|
|||
|
||||
/// Environment variables that should be overridden by config values
|
||||
fn env_base_layer() -> ConfigLayer {
|
||||
let mut builder = config::Config::builder();
|
||||
let mut layer = ConfigLayer::empty(ConfigSource::EnvBase);
|
||||
if !env::var("NO_COLOR").unwrap_or_default().is_empty() {
|
||||
// "User-level configuration files and per-instance command-line arguments
|
||||
// should override $NO_COLOR." https://no-color.org/
|
||||
builder = builder.set_override("ui.color", "never").unwrap();
|
||||
layer.set_value("ui.color", "never").unwrap();
|
||||
}
|
||||
if let Ok(value) = env::var("PAGER") {
|
||||
builder = builder.set_override("ui.pager", value).unwrap();
|
||||
layer.set_value("ui.pager", value).unwrap();
|
||||
}
|
||||
if let Ok(value) = env::var("VISUAL") {
|
||||
builder = builder.set_override("ui.editor", value).unwrap();
|
||||
layer.set_value("ui.editor", value).unwrap();
|
||||
} else if let Ok(value) = env::var("EDITOR") {
|
||||
builder = builder.set_override("ui.editor", value).unwrap();
|
||||
layer.set_value("ui.editor", value).unwrap();
|
||||
}
|
||||
ConfigLayer::with_data(ConfigSource::EnvBase, builder.build().unwrap())
|
||||
layer
|
||||
}
|
||||
|
||||
pub fn default_config_layers() -> Vec<ConfigLayer> {
|
||||
|
@ -397,38 +397,32 @@ pub fn default_config_layers() -> Vec<ConfigLayer> {
|
|||
|
||||
/// Environment variables that override config values
|
||||
fn env_overrides_layer() -> ConfigLayer {
|
||||
let mut builder = config::Config::builder();
|
||||
let mut layer = ConfigLayer::empty(ConfigSource::EnvOverrides);
|
||||
if let Ok(value) = env::var("JJ_USER") {
|
||||
builder = builder.set_override("user.name", value).unwrap();
|
||||
layer.set_value("user.name", value).unwrap();
|
||||
}
|
||||
if let Ok(value) = env::var("JJ_EMAIL") {
|
||||
builder = builder.set_override("user.email", value).unwrap();
|
||||
layer.set_value("user.email", value).unwrap();
|
||||
}
|
||||
if let Ok(value) = env::var("JJ_TIMESTAMP") {
|
||||
builder = builder
|
||||
.set_override("debug.commit-timestamp", value)
|
||||
.unwrap();
|
||||
layer.set_value("debug.commit-timestamp", value).unwrap();
|
||||
}
|
||||
if let Ok(Ok(value)) = env::var("JJ_RANDOMNESS_SEED").map(|s| s.parse::<i64>()) {
|
||||
builder = builder
|
||||
.set_override("debug.randomness-seed", value)
|
||||
.unwrap();
|
||||
layer.set_value("debug.randomness-seed", value).unwrap();
|
||||
}
|
||||
if let Ok(value) = env::var("JJ_OP_TIMESTAMP") {
|
||||
builder = builder
|
||||
.set_override("debug.operation-timestamp", value)
|
||||
.unwrap();
|
||||
layer.set_value("debug.operation-timestamp", value).unwrap();
|
||||
}
|
||||
if let Ok(value) = env::var("JJ_OP_HOSTNAME") {
|
||||
builder = builder.set_override("operation.hostname", value).unwrap();
|
||||
layer.set_value("operation.hostname", value).unwrap();
|
||||
}
|
||||
if let Ok(value) = env::var("JJ_OP_USERNAME") {
|
||||
builder = builder.set_override("operation.username", value).unwrap();
|
||||
layer.set_value("operation.username", value).unwrap();
|
||||
}
|
||||
if let Ok(value) = env::var("JJ_EDITOR") {
|
||||
builder = builder.set_override("ui.editor", value).unwrap();
|
||||
layer.set_value("ui.editor", value).unwrap();
|
||||
}
|
||||
ConfigLayer::with_data(ConfigSource::EnvOverrides, builder.build().unwrap())
|
||||
layer
|
||||
}
|
||||
|
||||
/// Parses `--config-toml` arguments.
|
||||
|
@ -762,24 +756,20 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn test_resolved_config_values_single_key() {
|
||||
let env_base_config = config::Config::builder()
|
||||
.set_override("user.name", "base-user-name")
|
||||
.unwrap()
|
||||
.set_override("user.email", "base@user.email")
|
||||
.unwrap()
|
||||
.build()
|
||||
let mut env_base_layer = ConfigLayer::empty(ConfigSource::EnvBase);
|
||||
env_base_layer
|
||||
.set_value("user.name", "base-user-name")
|
||||
.unwrap();
|
||||
let repo_config = config::Config::builder()
|
||||
.set_override("user.email", "repo@user.email")
|
||||
.unwrap()
|
||||
.build()
|
||||
env_base_layer
|
||||
.set_value("user.email", "base@user.email")
|
||||
.unwrap();
|
||||
let mut repo_layer = ConfigLayer::empty(ConfigSource::Repo);
|
||||
repo_layer
|
||||
.set_value("user.email", "repo@user.email")
|
||||
.unwrap();
|
||||
let mut config = StackedConfig::empty();
|
||||
config.add_layer(ConfigLayer::with_data(
|
||||
ConfigSource::EnvBase,
|
||||
env_base_config,
|
||||
));
|
||||
config.add_layer(ConfigLayer::with_data(ConfigSource::Repo, repo_config));
|
||||
config.add_layer(env_base_layer);
|
||||
config.add_layer(repo_layer);
|
||||
// Note: "email" is alphabetized, before "name" from same layer.
|
||||
insta::assert_debug_snapshot!(
|
||||
resolved_config_values(&config, &ConfigNamePathBuf::root()),
|
||||
|
@ -906,21 +896,14 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn test_resolved_config_values_filter_path() {
|
||||
let user_config = config::Config::builder()
|
||||
.set_override("test-table1.foo", "user-FOO")
|
||||
.unwrap()
|
||||
.set_override("test-table2.bar", "user-BAR")
|
||||
.unwrap()
|
||||
.build()
|
||||
.unwrap();
|
||||
let repo_config = config::Config::builder()
|
||||
.set_override("test-table1.bar", "repo-BAR")
|
||||
.unwrap()
|
||||
.build()
|
||||
.unwrap();
|
||||
let mut user_layer = ConfigLayer::empty(ConfigSource::User);
|
||||
user_layer.set_value("test-table1.foo", "user-FOO").unwrap();
|
||||
user_layer.set_value("test-table2.bar", "user-BAR").unwrap();
|
||||
let mut repo_layer = ConfigLayer::empty(ConfigSource::Repo);
|
||||
repo_layer.set_value("test-table1.bar", "repo-BAR").unwrap();
|
||||
let mut config = StackedConfig::empty();
|
||||
config.add_layer(ConfigLayer::with_data(ConfigSource::User, user_config));
|
||||
config.add_layer(ConfigLayer::with_data(ConfigSource::Repo, repo_config));
|
||||
config.add_layer(user_layer);
|
||||
config.add_layer(repo_layer);
|
||||
insta::assert_debug_snapshot!(
|
||||
resolved_config_values(&config, &ConfigNamePathBuf::from_iter(["test-table1"])),
|
||||
@r#"
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
use std::borrow::Borrow;
|
||||
use std::convert::Infallible;
|
||||
use std::fmt;
|
||||
use std::mem;
|
||||
use std::ops::Range;
|
||||
use std::path::Path;
|
||||
use std::path::PathBuf;
|
||||
|
@ -60,6 +61,11 @@ pub enum ConfigGetError {
|
|||
},
|
||||
}
|
||||
|
||||
/// Error that can occur when updating config variable.
|
||||
#[derive(Debug, Error)]
|
||||
#[error(transparent)]
|
||||
pub struct ConfigUpdateError(pub ConfigError);
|
||||
|
||||
/// Extension methods for `Result<T, ConfigGetError>`.
|
||||
pub trait ConfigGetResultExt<T> {
|
||||
/// Converts `NotFound` error to `Ok(None)`, leaving other errors.
|
||||
|
@ -232,6 +238,11 @@ pub struct ConfigLayer {
|
|||
}
|
||||
|
||||
impl ConfigLayer {
|
||||
/// Creates new layer with empty data.
|
||||
pub fn empty(source: ConfigSource) -> Self {
|
||||
Self::with_data(source, config::Config::default())
|
||||
}
|
||||
|
||||
/// Creates new layer with the configuration variables `data`.
|
||||
pub fn with_data(source: ConfigSource, data: config::Config) -> Self {
|
||||
ConfigLayer {
|
||||
|
@ -314,6 +325,21 @@ impl ConfigLayer {
|
|||
) -> Result<Option<&ConfigValue>, &ConfigValue> {
|
||||
look_up_item(&self.data.cache, name.into_name_path().borrow())
|
||||
}
|
||||
|
||||
/// Sets new `value` to the `name` path.
|
||||
pub fn set_value(
|
||||
&mut self,
|
||||
name: &str, // TODO: impl ToConfigNamePath
|
||||
value: impl Into<ConfigValue>,
|
||||
) -> Result<(), ConfigUpdateError> {
|
||||
self.data = config::Config::builder()
|
||||
.add_source(mem::take(&mut self.data))
|
||||
.set_override(name, value)
|
||||
.map_err(ConfigUpdateError)?
|
||||
.build()
|
||||
.map_err(ConfigUpdateError)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Looks up item from the `root_item`. Returns `Some(item)` if an item found at
|
||||
|
|
|
@ -38,14 +38,11 @@ use testutils::TestRepoBackend;
|
|||
|
||||
fn config_with_commit_timestamp(timestamp: &str) -> StackedConfig {
|
||||
let mut config = testutils::base_user_config();
|
||||
config.add_layer(ConfigLayer::with_data(
|
||||
ConfigSource::User,
|
||||
config::Config::builder()
|
||||
.set_override("debug.commit-timestamp", timestamp)
|
||||
.unwrap()
|
||||
.build()
|
||||
.unwrap(),
|
||||
));
|
||||
let mut layer = ConfigLayer::empty(ConfigSource::User);
|
||||
layer
|
||||
.set_value("debug.commit-timestamp", timestamp)
|
||||
.unwrap();
|
||||
config.add_layer(layer);
|
||||
config
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue