cfgmatic-paths 2.2.0

Cross-platform configuration path discovery following XDG and platform conventions
Documentation
# cfgmatic-paths

[![Crates.io](https://img.shields.io/crates/v/cfgmatic-paths)](https://crates.io/crates/cfgmatic-paths)
[![Docs.rs](https://docs.rs/cfgmatic-paths/badge.svg)](https://docs.rs/cfgmatic-paths)
[![License](https://img.shields.io/badge/license-MIT%2FApache--2.0-blue)](LICENSE-MIT)
[![Unsafe](https://img.shields.io/badge/unsafe-forbidden-success.svg)](https://github.com/rust-secure-code/safety-dance/)

Cross-platform configuration path discovery following XDG and platform conventions.

## Overview

This crate provides a platform-agnostic way to discover configuration directories following the conventions of each operating system:

- **Unix/Linux**: XDG Base Directory Specification
- **macOS CLI**: XDG (same as Unix)
- **macOS GUI**: Application Support directories (with `macos-gui` feature)
- **Windows**: Known Folder IDs (AppData, ProgramData)

## Architecture

```
crates/cfgmatic-paths/
├── Cargo.toml
├── src/
│   ├── lib.rs           # Public API and convenience functions
│   ├── builder.rs       # PathsBuilder and PathFinder
│   ├── core/            # Core domain types
│   │   ├── mod.rs       # Module exports
│   │   ├── app_type.rs  # AppType (CLI, GUI, Service)
│   │   ├── config_tier.rs # ConfigTier (User, Local, System)
│   │   ├── discovery.rs # ConfigDiscovery, ConfigCandidate, PathStatus
│   │   └── pattern.rs   # FilePattern for matching config files
│   ├── platform/        # Platform-specific implementations
│   │   ├── mod.rs       # DirectoryFinder trait
│   │   ├── unix.rs      # XDG for Unix/Linux/macOS CLI
│   │   ├── windows.rs   # Windows Known Folders
│   │   └── macos_gui.rs # macOS Application Support
│   ├── env/             # Environment abstraction for testing
│   │   ├── mod.rs       # Env trait
│   │   └── std_env.rs   # StdEnv implementation
│   └── filesystem/      # Filesystem abstraction for testing
│       ├── mod.rs       # Fs trait
│       └── std_fs.rs    # StdFs implementation
```

## Usage

### Basic Usage

```rust
use cfgmatic_paths::PathsBuilder;

// Create a path finder for your application
let finder = PathsBuilder::new("myapp").build();

// Get user config directories
let user_dirs = finder.user_dirs();
println!("User config dirs: {:?}", user_dirs);

// Ensure the primary user config directory exists
if let Ok(config_dir) = finder.ensure_user_config_dir() {
    println!("Config dir: {}", config_dir.display());
}
```

### Configuration Discovery

The crate provides comprehensive configuration discovery with full diagnostics:

```rust
use cfgmatic_paths::{discover_config, PathsBuilder};

// Quick discovery
let discovery = discover_config("myapp");

println!("Preferred path for new config: {}", discovery.preferred_path.display());

if let Some(found) = &discovery.found_path {
    println!("Found existing config at: {}", found.display());
}

// See all candidates that were searched
for candidate in discovery.candidates {
    println!("  - {:?}: {} ({:?})",
        candidate.tier,
        candidate.path.display(),
        candidate.status
    );
}

// Check for config fragments (conf.d style)
for fragment in &discovery.fragments {
    println!("Fragment: {}", fragment.display());
}
```

### Path Without Existence Check

Get the preferred configuration path without checking if it exists:

```rust
use cfgmatic_paths::{config_path, config_file_path};

// Get the preferred config directory
let dir = config_path("myapp");
println!("Config directory: {}", dir.display());

// Get a specific config file path
let file = config_file_path("myapp", "config.toml");
println!("Config file: {}", file.display());
```

### Multi-File Configuration Discovery

Find all configuration files matching a pattern:

```rust
use cfgmatic_paths::{PathsBuilder, FilePattern};

let finder = PathsBuilder::new("myapp").build();

// Find all config files with common extensions
let pattern = FilePattern::extensions("config", &["toml", "yaml", "json"]);
let configs = finder.find_config_files(&pattern);

for config in configs {
    if config.exists() {
        println!("Found config: {} ({:?})",
            config.path.display(),
            config.tier
        );
    }
}
```

### Conf.d Style Fragments

Find configuration fragments from conf.d-style directories:

```rust
use cfgmatic_paths::{PathsBuilder, FilePattern};

let finder = PathsBuilder::new("myapp").build();

// Find all .conf files in conf.d directories
let pattern = FilePattern::glob("*.conf");
let fragments = finder.find_fragments(&pattern, "conf.d");

for fragment in fragments {
    println!("Fragment: {}", fragment.display());
}
```

### Convenience Functions

```rust
use cfgmatic_paths::{find_existing_dir, ensure_config_dir, get_all_dirs};

// Find the first existing config directory
if let Some(dir) = find_existing_dir("myapp") {
    println!("Found: {}", dir.display());
}

// Ensure user config directory exists
let config_dir = ensure_config_dir("myapp")?;

// Get all directories with metadata
for info in get_all_dirs("myapp") {
    println!("{:?}: {} (exists: {})",
        info.tier, info.path.display(), info.exists);
}
```

## Configuration Tiers

Configuration directories are organized into three tiers:

1. **User** (`ConfigTier::User`): User-specific configs in home directory.
   Highest priority, typically writable.

2. **Local** (`ConfigTier::Local`): Machine-specific configs.
   Medium priority, may be writable.

3. **System** (`ConfigTier::System`): System-wide configs.
   Lowest priority, typically read-only.

## Platform Details

### Unix/Linux (XDG)

- User: `$XDG_CONFIG_HOME/<app>/` (default: `~/.config/<app>/`)
- Legacy: `~/.<app>rc` (optional, enabled by default)
- System: `$XDG_CONFIG_DIRS/<app>/` (default: `/etc/xdg/<app>/`)

### macOS

#### CLI Applications (default)

Uses XDG (same as Unix/Linux).

#### GUI Applications (with `macos-gui` feature)

- User: `~/Library/Application Support/<bundle-id>/`
- System: `/Library/Application Support/<bundle-id>/`

### Windows

- User Roaming: `%APPDATA%\<Company>\<App>\`
- User Local: `%LOCALAPPDATA%\<Company>\<App>\`
- System: `%PROGRAMDATA%\<Company>\<App>\`

## Testing

The crate provides abstractions for testing:

- `Env`: Mock environment variables
- `Fs`: Mock filesystem operations

These allow testing without modifying the actual environment or filesystem.

## Features

- `default`: No additional features enabled.
- `macos-gui`: Use macOS Application Support directories instead of XDG.
- `test-helpers`: Additional utilities for testing (future).

## Relationship to cfgmatic

This crate is the foundation for the `cfgmatic` configuration framework:

- `cfgmatic-paths`: Path discovery (this crate)
- `cfgmatic`: File search, merging, watching (uses `cfgmatic-paths`)

The separation allows:

1. Independent use of path discovery
2. Testing without filesystem dependencies
3. Platform-specific optimizations

## License

This project is licensed under either of

- Apache License, Version 2.0 ([LICENSE-APACHE]LICENSE-APACHE or <http://www.apache.org/licenses/LICENSE-2.0>)
- MIT license ([LICENSE-MIT]LICENSE-MIT or <http://opensource.org/licenses/MIT>)

at your option.