xvc-config 0.7.0

Xvc configuration management
Documentation
# Xvc Configuration Manager

The `xvc-config` crate provides a general solution for maintaining configuration settings across different sources with cascading precedence. It is part of the [Xvc](https://xvc.dev) project, a version control system focused on data and MLOps.

## Core Concepts

This crate provides a flexible configuration system that loads and merges settings from multiple sources in a defined order of precedence. Later sources override the settings from earlier ones. The standard hierarchy is:

1.  **Default Values**: Hard-coded defaults that provide a baseline.
2.  **System-wide Configuration**: For system-level settings (e.g., `/etc/xvc/config.toml`).
3.  **User-specific Configuration**: For user-level settings (e.g., `~/.config/xvc/config.toml`).
4.  **Project Configuration**: Stored in the repository, shared with all contributors (e.g., `.xvc/config.toml`).
5.  **Local Project Configuration**: Specific to a local clone of the repository, ignored by Git (e.g., `.xvc/config.local.toml`).
6.  **Environment Variables**: Allows overriding configuration with environment variables (e.g., `XVC_CORE_VERBOSITY=info`).
7.  **Command-line Arguments**: The highest precedence, for on-the-fly modifications.

## Architecture

The configuration system is built around three main structs:

-   **`XvcConfiguration`**: A struct that holds the complete, final configuration for the application. Every field is required and fully populated.
-   **`XvcOptionalConfiguration`**: A parallel struct where every field is wrapped in an `Option`. This is used to represent partial configurations loaded from a single source (like a TOML file or environment variables).
-   **`XvcConfigParams`**: A builder-style struct that specifies *how* to load the configuration. It defines the paths to config files and which sources (system, user, environment, etc.) to include.

The final `XvcConfiguration` is built by:
1.  Starting with a base configuration from `default_config()`.
2.  Loading partial configurations (`XvcOptionalConfiguration`) from each source.
3.  Merging each partial configuration into the base configuration in order of precedence using the `merge_configs` function.

## Usage

The `xvc-config` crate provides the building blocks for configuration management. A higher-level orchestrator would use these components to load and merge the final settings.

### Example: Building a Configuration Manually

This example demonstrates how to use the core components to build a configuration.

```rust
use std::collections::HashMap;
use xvc_config::{
    blank_optional_config, default_config, merge_configs, XvcOptionalConfiguration,
    OptionalCoreConfig,
};

// 1. Start with the default configuration.
let mut config = default_config();
println!("Default verbosity: {}", config.core.verbosity);

// 2. Create a partial configuration, as if loaded from a file or env vars.
let mut user_override = blank_optional_config();
user_override.core = Some(OptionalCoreConfig {
    verbosity: Some("debug".to_string()),
    ..Default::default()
});

// 3. Merge the user override into the base configuration.
config = merge_configs(&config, &user_override);
println!("Verbosity after merge: {}", config.core.verbosity);

// 4. Load configuration from environment variables (or any HashMap).
let mut env_vars = HashMap::new();
env_vars.insert("XVC_CORE_VERBOSITY".to_string(), "warn".to_string());
let env_config = XvcOptionalConfiguration::from_hash_map("XVC_", &env_vars);

// 5. Merge the environment configuration.
config = merge_configs(&config, &env_config);
println!("Final verbosity from env: {}", config.core.verbosity);

assert_eq!(config.core.verbosity, "warn");
```