tree-type 0.4.5

Rust macros for creating type-safe filesystem tree structures
Documentation
#![allow(deprecated)]

use tree_type::tree_type;

// This test demonstrates the real issue from t93:
// Symlinks are defined correctly in the macro (identifiers exist)
// But at runtime, the target files don't exist, so symlinks aren't created
// The user sees "no symlinks" but doesn't understand why
tree_type! {
    TestSymlinks {
        config/ {
            #[required]
            production("production.toml"),  // Target exists as identifier, user must create
            #[symlink(production)]         // Symlink is valid at compile time
            active("active.toml")
        }
    }
}

#[test]
fn test_symlink_fails_when_target_file_missing() {
    let temp_dir = tempfile::tempdir().unwrap();
    let test = TestSymlinks::new(temp_dir.path()).unwrap();

    // sync() succeeds but doesn't create the symlink because target file doesn't exist
    let result = test.sync();
    assert!(result.is_ok());

    // The production file doesn't exist (no default content)
    assert!(!test.config().production().exists());

    // The symlink isn't created because the target doesn't exist
    assert!(!test.config().active().exists());

    // This is the issue: user sees "no symlinks" but doesn't know why
    // The error message should explain that the target file is missing
}

#[test]
fn test_symlink_works_when_target_file_exists() {
    let temp_dir = tempfile::tempdir().unwrap();
    let test = TestSymlinks::new(temp_dir.path()).unwrap();

    // Create the target file first
    test.config()
        .production()
        .write("production config")
        .unwrap();

    // Now sync() should create the symlink
    let result = test.sync();
    assert!(result.is_ok());

    // The symlink should now exist
    assert!(test.config().active().exists());
}

// This test should now fail to compile with the enhanced validation
// because the target doesn't have default content
/*
tree_type! {
    TestSymlinksWithValidation {
        config/ {
            production("production.toml"),  // No default content
            #[symlink(production)]         // Should cause compile error
            active("active.toml")
        }
    }
}
*/

// This test should compile successfully because target has default content
tree_type! {
    TestSymlinksWithDefault {
        config/ {
            #[default("default production config")]
            production("production.toml"),  // Has default content
            #[symlink(production)]         // Should compile successfully
            active("active.toml")
        }
    }
}

#[test]
fn test_symlink_with_default_target_works() {
    let temp_dir = tempfile::tempdir().unwrap();
    let test = TestSymlinksWithDefault::new(temp_dir.path()).unwrap();

    // sync() should create both the target file and the symlink
    let result = test.sync();
    assert!(result.is_ok());

    // Both files should exist
    assert!(test.config().production().exists());
    assert!(test.config().active().exists());

    // The symlink should point to the target
    let target_content = test.config().production().read_to_string().unwrap();
    let symlink_content = test.config().active().read_to_string().unwrap();
    assert_eq!(target_content, symlink_content);
}