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_direstableceTQ_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 ciejecuta 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
tqpara este capítulo está en5-interface/03-what-the-air-carries/.