|
1 | 1 | use std::collections::HashMap; |
2 | | -use std::path::PathBuf; |
| 2 | +use std::path::{Path, PathBuf}; |
3 | 3 | use std::sync::{Arc, Mutex}; |
4 | 4 | use std::{fs, io}; |
5 | 5 |
|
@@ -74,6 +74,7 @@ struct Metadata { |
74 | 74 | manifest_dir: PathBuf, |
75 | 75 | offline: bool, |
76 | 76 | database_url: Option<String>, |
| 77 | + offline_dir: Option<String>, |
77 | 78 | workspace_root: Arc<Mutex<Option<PathBuf>>>, |
78 | 79 | } |
79 | 80 |
|
@@ -114,39 +115,21 @@ static METADATA: Lazy<Mutex<HashMap<String, Metadata>>> = Lazy::new(Default::def |
114 | 115 | fn init_metadata(manifest_dir: &String) -> Metadata { |
115 | 116 | let manifest_dir: PathBuf = manifest_dir.into(); |
116 | 117 |
|
117 | | - // If a .env file exists at CARGO_MANIFEST_DIR, load environment variables from this, |
118 | | - // otherwise fallback to default dotenv behaviour. |
119 | | - let env_path = manifest_dir.join(".env"); |
120 | | - |
121 | | - #[cfg_attr(not(procmacro2_semver_exempt), allow(unused_variables))] |
122 | | - let env_path = if env_path.exists() { |
123 | | - // Load the new environment variables and override the old ones if necessary. |
124 | | - let res = dotenvy::from_path_override(&env_path); |
125 | | - if let Err(e) = res { |
126 | | - panic!("failed to load environment from {env_path:?}, {e}"); |
127 | | - } |
128 | | - |
129 | | - Some(env_path) |
130 | | - } else { |
131 | | - dotenvy::dotenv_override().ok() |
132 | | - }; |
133 | | - |
134 | | - // tell the compiler to watch the `.env` for changes, if applicable |
135 | | - #[cfg(procmacro2_semver_exempt)] |
136 | | - if let Some(env_path) = env_path.as_ref().and_then(|path| path.to_str()) { |
137 | | - proc_macro::tracked_path::path(env_path); |
138 | | - } |
| 118 | + let (database_url, offline, offline_dir) = load_dot_env(&manifest_dir); |
139 | 119 |
|
140 | 120 | let offline = env("SQLX_OFFLINE") |
| 121 | + .ok() |
| 122 | + .or(offline) |
141 | 123 | .map(|s| s.eq_ignore_ascii_case("true") || s == "1") |
142 | 124 | .unwrap_or(false); |
143 | 125 |
|
144 | | - let database_url = env("DATABASE_URL").ok(); |
| 126 | + let database_url = env("DATABASE_URL").ok().or(database_url); |
145 | 127 |
|
146 | 128 | Metadata { |
147 | 129 | manifest_dir, |
148 | 130 | offline, |
149 | 131 | database_url, |
| 132 | + offline_dir, |
150 | 133 | workspace_root: Arc::new(Mutex::new(None)), |
151 | 134 | } |
152 | 135 | } |
@@ -182,7 +165,7 @@ pub fn expand_input<'a>( |
182 | 165 |
|
183 | 166 | // Check SQLX_OFFLINE_DIR, then local .sqlx, then workspace .sqlx. |
184 | 167 | let dirs = [ |
185 | | - |_: &Metadata| env("SQLX_OFFLINE_DIR").ok().map(PathBuf::from), |
| 168 | + |meta: &Metadata| meta.offline_dir.as_deref().map(PathBuf::from), |
186 | 169 | |meta: &Metadata| Some(meta.manifest_dir.join(".sqlx")), |
187 | 170 | |meta: &Metadata| Some(meta.workspace_root().join(".sqlx")), |
188 | 171 | ]; |
@@ -402,3 +385,52 @@ fn env(name: &str) -> Result<String, std::env::VarError> { |
402 | 385 | std::env::var(name) |
403 | 386 | } |
404 | 387 | } |
| 388 | + |
| 389 | +/// Get `DATABASE_URL`, `SQLX_OFFLINE` and `SQLX_OFFLINE_DIR` from the `.env`. |
| 390 | +fn load_dot_env(manifest_dir: &Path) -> (Option<String>, Option<String>, Option<String>) { |
| 391 | + let mut env_path = manifest_dir.join(".env"); |
| 392 | + |
| 393 | + // If a .env file exists at CARGO_MANIFEST_DIR, load environment variables from this, |
| 394 | + // otherwise fallback to default dotenv file. |
| 395 | + #[cfg_attr(not(procmacro2_semver_exempt), allow(unused_variables))] |
| 396 | + let env_file = if env_path.exists() { |
| 397 | + let res = dotenvy::from_path_iter(&env_path); |
| 398 | + match res { |
| 399 | + Ok(iter) => Some(iter), |
| 400 | + Err(e) => panic!("failed to load environment from {env_path:?}, {e}"), |
| 401 | + } |
| 402 | + } else { |
| 403 | + #[allow(unused_assignments)] |
| 404 | + { |
| 405 | + env_path = PathBuf::from(".env"); |
| 406 | + } |
| 407 | + dotenvy::dotenv_iter().ok() |
| 408 | + }; |
| 409 | + |
| 410 | + let mut offline = None; |
| 411 | + let mut database_url = None; |
| 412 | + let mut offline_dir = None; |
| 413 | + |
| 414 | + if let Some(env_file) = env_file { |
| 415 | + // tell the compiler to watch the `.env` for changes. |
| 416 | + #[cfg(procmacro2_semver_exempt)] |
| 417 | + if let Some(env_path) = env_path.to_str() { |
| 418 | + proc_macro::tracked_path::path(env_path); |
| 419 | + } |
| 420 | + |
| 421 | + for item in env_file { |
| 422 | + let Ok((key, value)) = item else { |
| 423 | + continue; |
| 424 | + }; |
| 425 | + |
| 426 | + match key.as_str() { |
| 427 | + "DATABASE_URL" => database_url = Some(value), |
| 428 | + "SQLX_OFFLINE" => offline = Some(value), |
| 429 | + "SQLX_OFFLINE_DIR" => offline_dir = Some(value), |
| 430 | + _ => {} |
| 431 | + }; |
| 432 | + } |
| 433 | + } |
| 434 | + |
| 435 | + (database_url, offline, offline_dir) |
| 436 | +} |
0 commit comments