|
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