sqlx-data.json removal prep work (#1184)

* macros: Reduce I/O

by doing all .env and environment variable reading inside a Lazy initializer.

* Use the default runtime and TLS backend for all examples

Before, rust-analyzer was always hitting the
"only one runtime can be enabled" compile_error in sqlx-rt.
This commit is contained in:
Jonas Platte 2021-05-22 02:33:56 +02:00 committed by GitHub
parent 13f7c7124a
commit 901f858fbc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 88 additions and 54 deletions

View File

@ -9,5 +9,5 @@ anyhow = "1.0"
async-std = { version = "1.8.0", features = [ "attributes" ] } async-std = { version = "1.8.0", features = [ "attributes" ] }
futures = "0.3" futures = "0.3"
paw = "1.0" paw = "1.0"
sqlx = { path = "../../../", features = [ "mysql", "runtime-async-std-rustls" ] } sqlx = { path = "../../../", features = [ "mysql", "runtime-async-std-native-tls" ] }
structopt = { version = "0.3", features = [ "paw" ] } structopt = { version = "0.3", features = [ "paw" ] }

View File

@ -58,7 +58,7 @@ _rt-async-std = []
_rt-tokio = [] _rt-tokio = []
# offline building support # offline building support
offline = ["sqlx-core/offline", "hex", "once_cell", "serde", "serde_json", "sha2"] offline = ["sqlx-core/offline", "hex", "serde", "serde_json", "sha2"]
# database # database
mysql = ["sqlx-core/mysql"] mysql = ["sqlx-core/mysql"]
@ -82,7 +82,7 @@ futures = { version = "0.3.4", default-features = false, features = ["executor"]
hex = { version = "0.4.2", optional = true } hex = { version = "0.4.2", optional = true }
heck = "0.3.1" heck = "0.3.1"
either = "1.5.3" either = "1.5.3"
once_cell = { version = "1.5.2", optional = true } once_cell = "1.5.2"
proc-macro2 = { version = "1.0.9", default-features = false } proc-macro2 = { version = "1.0.9", default-features = false }
sqlx-core = { version = "0.5.3", default-features = false, path = "../sqlx-core" } sqlx-core = { version = "0.5.3", default-features = false, path = "../sqlx-core" }
sqlx-rt = { version = "0.5.3", default-features = false, path = "../sqlx-rt" } sqlx-rt = { version = "0.5.3", default-features = false, path = "../sqlx-rt" }

View File

@ -1,8 +1,6 @@
use std::env;
use std::path::Path;
#[cfg(feature = "offline")]
use std::path::PathBuf; use std::path::PathBuf;
use once_cell::sync::Lazy;
use proc_macro2::TokenStream; use proc_macro2::TokenStream;
use syn::Type; use syn::Type;
use url::Url; use url::Url;
@ -24,60 +22,96 @@ mod data;
mod input; mod input;
mod output; mod output;
struct Metadata {
manifest_dir: PathBuf,
offline: bool,
database_url: Option<String>,
#[cfg(feature = "offline")]
target_dir: PathBuf,
#[cfg(feature = "offline")]
workspace_root: PathBuf,
}
// If we are in a workspace, lookup `workspace_root` since `CARGO_MANIFEST_DIR` won't // If we are in a workspace, lookup `workspace_root` since `CARGO_MANIFEST_DIR` won't
// reflect the workspace dir: https://github.com/rust-lang/cargo/issues/3946 // reflect the workspace dir: https://github.com/rust-lang/cargo/issues/3946
static METADATA: Lazy<Metadata> = Lazy::new(|| {
use std::env;
let manifest_dir = env::var("CARGO_MANIFEST_DIR")
.expect("`CARGO_MANIFEST_DIR` must be set")
.into();
#[cfg(feature = "offline")] #[cfg(feature = "offline")]
static CRATE_ROOT: once_cell::sync::Lazy<PathBuf> = once_cell::sync::Lazy::new(|| { let target_dir =
env::var_os("CARGO_TARGET_DIR").map_or_else(|| "target".into(), |dir| dir.into());
// If a .env file exists at CARGO_MANIFEST_DIR, load environment variables from this,
// otherwise fallback to default dotenv behaviour.
let env_path = METADATA.manifest_dir.join(".env");
if env_path.exists() {
let res = dotenv::from_path(&env_path);
if let Err(e) = res {
panic!("failed to load environment from {:?}, {}", env_path, e);
}
} else {
let _ = dotenv::dotenv();
}
// TODO: Switch to `var_os` after feature(osstring_ascii) is stable.
// Stabilization PR: https://github.com/rust-lang/rust/pull/80193
let offline = env::var("SQLX_OFFLINE")
.map(|s| s.eq_ignore_ascii_case("true") || s == "1")
.unwrap_or(false);
let database_url = env::var("DATABASE_URL").ok();
#[cfg(feature = "offline")]
let workspace_root = {
use serde::Deserialize; use serde::Deserialize;
use std::process::Command; use std::process::Command;
let manifest_dir = env::var("CARGO_MANIFEST_DIR").expect("`CARGO_MANIFEST_DIR` must be set");
let cargo = env::var_os("CARGO").expect("`CARGO` must be set"); let cargo = env::var_os("CARGO").expect("`CARGO` must be set");
let output = Command::new(&cargo) let output = Command::new(&cargo)
.args(&["metadata", "--format-version=1"]) .args(&["metadata", "--format-version=1"])
.current_dir(manifest_dir) .current_dir(&manifest_dir)
.output() .output()
.expect("Could not fetch metadata"); .expect("Could not fetch metadata");
#[derive(Deserialize)] #[derive(Deserialize)]
struct Metadata { struct CargoMetadata {
workspace_root: PathBuf, workspace_root: PathBuf,
} }
let metadata: Metadata = let metadata: CargoMetadata =
serde_json::from_slice(&output.stdout).expect("Invalid `cargo metadata` output"); serde_json::from_slice(&output.stdout).expect("Invalid `cargo metadata` output");
metadata.workspace_root metadata.workspace_root
};
Metadata {
manifest_dir,
offline,
database_url,
#[cfg(feature = "offline")]
target_dir,
#[cfg(feature = "offline")]
workspace_root,
}
}); });
pub fn expand_input(input: QueryMacroInput) -> crate::Result<TokenStream> { pub fn expand_input(input: QueryMacroInput) -> crate::Result<TokenStream> {
let manifest_dir = match &*METADATA {
env::var("CARGO_MANIFEST_DIR").map_err(|_| "`CARGO_MANIFEST_DIR` must be set")?; Metadata {
offline: false,
// If a .env file exists at CARGO_MANIFEST_DIR, load environment variables from this, database_url: Some(db_url),
// otherwise fallback to default dotenv behaviour. ..
let env_path = Path::new(&manifest_dir).join(".env"); } => expand_from_db(input, &db_url),
if env_path.exists() {
dotenv::from_path(&env_path)
.map_err(|e| format!("failed to load environment from {:?}, {}", env_path, e))?
}
// if `dotenv` wasn't initialized by the above we make sure to do it here
match (
dotenv::var("SQLX_OFFLINE")
.map(|s| s.eq_ignore_ascii_case("true") || s == "1")
.unwrap_or(false),
dotenv::var("DATABASE_URL"),
) {
(false, Ok(db_url)) => expand_from_db(input, &db_url),
#[cfg(feature = "offline")] #[cfg(feature = "offline")]
_ => { _ => {
let data_file_path = Path::new(&manifest_dir).join("sqlx-data.json"); let data_file_path = METADATA.manifest_dir.join("sqlx-data.json");
let workspace_data_file_path = METADATA.workspace_root.join("sqlx-data.json");
let workspace_data_file_path = CRATE_ROOT.join("sqlx-data.json");
if data_file_path.exists() { if data_file_path.exists() {
expand_from_file(input, data_file_path) expand_from_file(input, data_file_path)
@ -93,12 +127,16 @@ pub fn expand_input(input: QueryMacroInput) -> crate::Result<TokenStream> {
} }
#[cfg(not(feature = "offline"))] #[cfg(not(feature = "offline"))]
(true, _) => { Metadata { offline: true, .. } => {
Err("The cargo feature `offline` has to be enabled to use `SQLX_OFFLINE`".into()) Err("The cargo feature `offline` has to be enabled to use `SQLX_OFFLINE`".into())
} }
#[cfg(not(feature = "offline"))] #[cfg(not(feature = "offline"))]
(false, Err(_)) => Err("`DATABASE_URL` must be set to use query macros".into()), Metadata {
offline: false,
database_url: None,
..
} => Err("`DATABASE_URL` must be set to use query macros".into()),
} }
} }
@ -322,11 +360,7 @@ where
// If the build is offline, the cache is our input so it's pointless to also write data for it. // If the build is offline, the cache is our input so it's pointless to also write data for it.
#[cfg(feature = "offline")] #[cfg(feature = "offline")]
if !offline { if !offline {
let mut save_dir = let save_dir = METADATA.target_dir.join("sqlx");
PathBuf::from(env::var("CARGO_TARGET_DIR").unwrap_or_else(|_| "target/".into()));
save_dir.push("sqlx");
std::fs::create_dir_all(&save_dir)?; std::fs::create_dir_all(&save_dir)?;
data.save_in(save_dir, input.src_span)?; data.save_in(save_dir, input.src_span)?;
} }