Skip to content

Commit b1e6a87

Browse files
committed
fix(macros): don't mutate environment variables
1 parent 91d26ba commit b1e6a87

File tree

1 file changed

+56
-24
lines changed
  • sqlx-macros-core/src/query

1 file changed

+56
-24
lines changed

sqlx-macros-core/src/query/mod.rs

+56-24
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ struct Metadata {
7474
manifest_dir: PathBuf,
7575
offline: bool,
7676
database_url: Option<String>,
77+
offline_dir: Option<String>,
7778
workspace_root: Arc<Mutex<Option<PathBuf>>>,
7879
}
7980

@@ -114,39 +115,21 @@ static METADATA: Lazy<Mutex<HashMap<String, Metadata>>> = Lazy::new(Default::def
114115
fn init_metadata(manifest_dir: &String) -> Metadata {
115116
let manifest_dir: PathBuf = manifest_dir.into();
116117

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);
139119

140120
let offline = env("SQLX_OFFLINE")
121+
.ok()
122+
.or(offline)
141123
.map(|s| s.eq_ignore_ascii_case("true") || s == "1")
142124
.unwrap_or(false);
143125

144-
let database_url = env("DATABASE_URL").ok();
126+
let database_url = env("DATABASE_URL").ok().or(database_url);
145127

146128
Metadata {
147129
manifest_dir,
148130
offline,
149131
database_url,
132+
offline_dir,
150133
workspace_root: Arc::new(Mutex::new(None)),
151134
}
152135
}
@@ -182,7 +165,7 @@ pub fn expand_input<'a>(
182165

183166
// Check SQLX_OFFLINE_DIR, then local .sqlx, then workspace .sqlx.
184167
let dirs = [
185-
|_: &Metadata| env("SQLX_OFFLINE_DIR").ok().map(PathBuf::from),
168+
|meta: &Metadata| meta.offline_dir.as_deref().map(PathBuf::from),
186169
|meta: &Metadata| Some(meta.manifest_dir.join(".sqlx")),
187170
|meta: &Metadata| Some(meta.workspace_root().join(".sqlx")),
188171
];
@@ -402,3 +385,52 @@ fn env(name: &str) -> Result<String, std::env::VarError> {
402385
std::env::var(name)
403386
}
404387
}
388+
389+
/// Get `DATABASE_URL`, `SQLX_OFFLINE` and `SQLX_OFFLINE_DIR` from the `.env`.
390+
fn load_dot_env(manifest_dir: &PathBuf) -> (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

Comments
 (0)