← Índice

5.3 Lo que transporta el aire

Esta traducción fue asistida por IA y revisada superficialmente. Si encuentras errores o algo no suena natural, escríbeme — lo agradezco.

Una buena instrucción describe lo general; los detalles pertenecen al taller. Dónde guardar el trabajo terminado no es una pregunta para la herramienta - es una pregunta de lugar. En un taller, un rincón; en otro, otro; en uno temporal, en ningún sitio y no por mucho tiempo. Un archivo de configuración no puede hablar por sí mismo. Hay que cambiarlo antes de una mudanza. Las mudanzas ocurren más a menudo de lo planeado.

Lo que necesitas

tq lee config.toml - toma data_dir de ahí, o usa el directorio actual por defecto. Eso funciona para una ubicación. Un desarrollador con datos en ~/tq-data y un job de CI con datos en /tmp/ci-tq debe o bien editar el archivo antes de cada ejecución, o mantener dos archivos e intercambiarlos según sea necesario. Ambas opciones requieren trabajo manual.

Una variable de entorno resuelve el problema de otra manera: no toca el archivo, no requiere versionado, y vive exactamente lo que se necesita - una ejecución, una sesión, un job de CI.

La construcción

std::env::var("TQ_DATA_DIR") devuelve Ok(String) si la variable está establecida, y Err si no. if let Ok(dir) toma el valor solo en caso de éxito; si la variable no está establecida, el bloque se omite.

Dos cambios en src/config/mod.rs - config se convierte en mut, y después de cargar el archivo se añade una comprobación de la variable de entorno:

// src/config/mod.rs - CAMBIADO
pub fn load(path: &Path) -> TqResult<Config> {
    let mut config = if !path.exists() {           // CAMBIADO: let -> let mut
        Config::default()
    } else {
        let content = fs::read_to_string(path).map_err(|e| TqError::Parse(e.to_string()))?;
        toml::from_str(&content).map_err(|e| TqError::Parse(e.to_string()))?
    };

    if let Ok(dir) = std::env::var("TQ_DATA_DIR") {  // NUEVO
        config.data_dir = PathBuf::from(dir);          // NUEVO
    }                                                   // NUEVO

    if !config.data_dir.exists() {
        return Err(TqError::Parse(format!(
            "data_dir '{}' does not exist; create it with: mkdir -p {}",
            config.data_dir.display(),
            config.data_dir.display()
        )));
    }
    Ok(config)
}

Primero se carga el archivo (o se toma el valor por defecto), luego - si la variable está establecida - se sobreescribe data_dir. La comprobación de existencia viene al final, tras consultar todas las fuentes. Prioridad: TQ_DATA_DIR > config.toml > valor por defecto.

Las letras mayúsculas y el prefijo TQ_ son una convención Unix: las variables de entorno son legibles por cualquier herramienta, y el nombre debe ser suficientemente distintivo para no colisionar con el de otro.

El test para el nuevo camino vive en src/config/tests.rs. En Rust 2024, set_var requiere unsafe (detalles en M6.x), y la variable se elimina antes de unwrap() - si la aserción falla, remove_var ya se ha ejecutado:

#[test]
fn env_var_overrides_data_dir() {
    let tmp = std::env::temp_dir().join("tq-m53-env");
    std::fs::create_dir_all(&tmp).unwrap();
    unsafe { std::env::set_var("TQ_DATA_DIR", &tmp) };
    let result = Config::load(Path::new("nonexistent.toml"));
    unsafe { std::env::remove_var("TQ_DATA_DIR") };
    assert_eq!(result.unwrap().data_dir, tmp);
}

Nota. env_var_overrides_data_dir establece TQ_DATA_DIR - una variable de entorno de todo el proceso compartida entre todos los hilos. Cuando los tests se ejecutan en paralelo, dos tests pueden establecer valores diferentes simultáneamente e interferir entre sí. En este libro se elige el camino simple: make ci ejecuta los tests con --test-threads=1, lo que elimina el problema potencial.

# Makefile - CAMBIADO
ci:
	@cargo fmt --check && cargo clippy -- -D warnings && cargo test -- --test-threads=1

El resultado

$ mkdir -p /tmp/tq-test
$ TQ_DATA_DIR=/tmp/tq-test cargo run -- list

La lista está vacía: /tmp/tq-test no contiene ningún tasks.json. Es lo esperado - la variable cambia dónde busca tq, no qué hay ahí.

Una ruta inválida:

$ TQ_DATA_DIR=/nonexistent cargo run -- list
tq: parse error: data_dir '/nonexistent' does not exist; create it with: mkdir -p /nonexistent

make ci pasa.

El código completo de tq para este capítulo está en 5-interface/03-what-the-air-carries/.