Support workspaces for offline feature

This patch enables having a top-level `sqlx-data.json` file within a
workspace.

It does this by using a full clean / check instead of `cargo rustc`
which fails on a workspace.

A `--merged` flag is introduced to switch to the workspace behavior

Fixes #353.

Signed-off-by: Joe Grund <jgrund@whamcloud.io>
This commit is contained in:
Joe Grund 2020-07-07 10:49:56 -04:00 committed by Ryan Leckey
parent a445f9f431
commit 21661c2c9c
No known key found for this signature in database
GPG Key ID: F8AA68C235AB08C9
6 changed files with 269 additions and 53 deletions

222
Cargo.lock generated
View File

@ -40,6 +40,12 @@ dependencies = [
"threadpool",
]
[[package]]
name = "ahash"
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f6789e291be47ace86a60303502173d84af8327e3627ecf334356ee0f87a164c"
[[package]]
name = "ahash"
version = "0.5.8"
@ -298,13 +304,34 @@ version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
[[package]]
name = "block-buffer"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b"
dependencies = [
"block-padding",
"byte-tools",
"byteorder",
"generic-array 0.12.3",
]
[[package]]
name = "block-buffer"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4"
dependencies = [
"generic-array",
"generic-array 0.14.4",
]
[[package]]
name = "block-padding"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5"
dependencies = [
"byte-tools",
]
[[package]]
@ -345,6 +372,12 @@ version = "3.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2e8c087f005730276d1096a652e92a8bacee2e2472bcc9715a74d2bec38b5820"
[[package]]
name = "byte-tools"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7"
[[package]]
name = "byteorder"
version = "1.3.4"
@ -369,12 +402,24 @@ version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8de60b887edf6d74370fc8eb177040da4847d971d6234c7b13a6da324ef0caf"
dependencies = [
"semver",
"semver 0.9.0",
"serde",
"serde_derive",
"serde_json",
]
[[package]]
name = "cargo_metadata"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "83f95cf4bf0dda0ac2e65371ae7215d0dce3c187613a9dbf23aaa9374186f97a"
dependencies = [
"semver 0.11.0",
"semver-parser 0.10.0",
"serde",
"serde_json",
]
[[package]]
name = "cast"
version = "0.2.3"
@ -680,7 +725,7 @@ version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "58bcd97a54c7ca5ce2f6eb16f6bede5b0ab5f0055fedc17d2f0b4466e21671ca"
dependencies = [
"generic-array",
"generic-array 0.14.4",
"subtle",
]
@ -729,13 +774,22 @@ dependencies = [
"zeroize 0.9.3",
]
[[package]]
name = "digest"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5"
dependencies = [
"generic-array 0.12.3",
]
[[package]]
name = "digest"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066"
dependencies = [
"generic-array",
"generic-array 0.14.4",
]
[[package]]
@ -793,6 +847,12 @@ version = "2.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7531096570974c3a9dcf9e4b8e1cede1ec26cf5046219fb3b9d897503b9be59"
[[package]]
name = "fake-simd"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed"
[[package]]
name = "fastrand"
version = "1.4.0"
@ -959,6 +1019,15 @@ dependencies = [
"slab",
]
[[package]]
name = "generic-array"
version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec"
dependencies = [
"typenum",
]
[[package]]
name = "generic-array"
version = "0.14.4"
@ -1034,6 +1103,18 @@ name = "hashbrown"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04"
dependencies = [
"ahash 0.4.6",
]
[[package]]
name = "hashlink"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d99cf782f0dc4372d26846bec3de7804ceb5df083c2d4462c0b8d2330e894fa8"
dependencies = [
"hashbrown",
]
[[package]]
name = "heck"
@ -1066,7 +1147,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "deae6d9dbb35ec2c502d62b8f7b1c000a0822c3b0794ba36b3149c0a1c840dff"
dependencies = [
"crypto-mac",
"digest",
"digest 0.9.0",
]
[[package]]
@ -1270,15 +1351,6 @@ dependencies = [
"cfg-if 0.1.10",
]
[[package]]
name = "lru-cache"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "31e24f1ad8321ca0e8a1e0ac13f23cb668e6f5466c2c57319f6a5cf1cc8e3b1c"
dependencies = [
"linked-hash-map",
]
[[package]]
name = "maplit"
version = "1.0.2"
@ -1303,9 +1375,9 @@ version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b5a279bb9607f9f53c22d496eade00d138d1bdcccd07d74650387cf94942a15"
dependencies = [
"block-buffer",
"digest",
"opaque-debug",
"block-buffer 0.9.0",
"digest 0.9.0",
"opaque-debug 0.3.0",
]
[[package]]
@ -1519,6 +1591,12 @@ version = "11.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a170cebd8021a008ea92e4db85a72f80b35df514ec664b296fdcbb654eac0b2c"
[[package]]
name = "opaque-debug"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c"
[[package]]
name = "opaque-debug"
version = "0.3.0"
@ -1656,6 +1734,49 @@ version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
[[package]]
name = "pest"
version = "2.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "10f4872ae94d7b90ae48754df22fd42ad52ce740b8f370b03da4835417403e53"
dependencies = [
"ucd-trie",
]
[[package]]
name = "pest_derive"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "833d1ae558dc601e9a60366421196a8d94bc0ac980476d0b67e1d0988d72b2d0"
dependencies = [
"pest",
"pest_generator",
]
[[package]]
name = "pest_generator"
version = "2.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "99b8db626e31e5b81787b9783425769681b347011cc59471e33ea46d2ea0cf55"
dependencies = [
"pest",
"pest_meta",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "pest_meta"
version = "2.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "54be6e404f5317079812fc8f9f5279de376d8856929e21c184ecf6bbd692a11d"
dependencies = [
"maplit",
"pest",
"sha-1 0.8.2",
]
[[package]]
name = "pin-project"
version = "1.0.1"
@ -1927,7 +2048,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3648b669b10afeab18972c105e284a7b953a669b0be3514c27f9b17acab2f9cd"
dependencies = [
"byteorder",
"digest",
"digest 0.9.0",
"lazy_static",
"num-bigint-dig",
"num-integer",
@ -1958,7 +2079,7 @@ version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
dependencies = [
"semver",
"semver 0.9.0",
]
[[package]]
@ -2044,7 +2165,17 @@ version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
dependencies = [
"semver-parser",
"semver-parser 0.7.0",
"serde",
]
[[package]]
name = "semver"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6"
dependencies = [
"semver-parser 0.10.0",
"serde",
]
@ -2054,6 +2185,16 @@ version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
[[package]]
name = "semver-parser"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0e012c6c5380fb91897ba7b9261a0f565e624e869d42fe1a1d03fa0d68a083d5"
dependencies = [
"pest",
"pest_derive",
]
[[package]]
name = "serde"
version = "1.0.117"
@ -2096,17 +2237,29 @@ dependencies = [
"serde",
]
[[package]]
name = "sha-1"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7d94d0bede923b3cea61f3f1ff57ff8cdfd77b400fb8f9998949e0cf04163df"
dependencies = [
"block-buffer 0.7.3",
"digest 0.8.1",
"fake-simd",
"opaque-debug 0.2.3",
]
[[package]]
name = "sha-1"
version = "0.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ce3cdf1b5e620a498ee6f2a171885ac7e22f0e12089ec4b3d22b84921792507c"
dependencies = [
"block-buffer",
"block-buffer 0.9.0",
"cfg-if 1.0.0",
"cpuid-bool",
"digest",
"opaque-debug",
"digest 0.9.0",
"opaque-debug 0.3.0",
]
[[package]]
@ -2121,11 +2274,11 @@ version = "0.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6e7aab86fe2149bad8c507606bdb3f4ef5e7b2380eb92350f56122cca72a42a8"
dependencies = [
"block-buffer",
"block-buffer 0.9.0",
"cfg-if 1.0.0",
"cpuid-bool",
"digest",
"opaque-debug",
"digest 0.9.0",
"opaque-debug 0.3.0",
]
[[package]]
@ -2228,7 +2381,7 @@ version = "0.2.0"
dependencies = [
"anyhow",
"async-trait",
"cargo_metadata",
"cargo_metadata 0.10.0",
"chrono",
"clap 3.0.0-beta.2",
"console 0.11.3",
@ -2249,7 +2402,7 @@ dependencies = [
name = "sqlx-core"
version = "0.4.0"
dependencies = [
"ahash",
"ahash 0.5.8",
"atoi",
"base64 0.13.0",
"bigdecimal",
@ -2263,7 +2416,7 @@ dependencies = [
"crossbeam-channel 0.4.4",
"crossbeam-queue",
"crossbeam-utils 0.7.2",
"digest",
"digest 0.9.0",
"either",
"encoding_rs",
"futures-channel",
@ -2278,7 +2431,6 @@ dependencies = [
"libc",
"libsqlite3-sys",
"log",
"lru-cache",
"md-5",
"memchr",
"num-bigint 0.3.1",
@ -2292,7 +2444,7 @@ dependencies = [
"rustls",
"serde",
"serde_json",
"sha-1",
"sha-1 0.9.2",
"sha2",
"smallvec",
"sqlformat",
@ -2357,11 +2509,13 @@ dependencies = [
name = "sqlx-macros"
version = "0.4.0"
dependencies = [
"cargo_metadata 0.12.1",
"dotenv",
"either",
"futures",
"heck",
"hex",
"lazy_static",
"proc-macro2",
"quote",
"serde",
@ -2793,6 +2947,12 @@ version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33"
[[package]]
name = "ucd-trie"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c"
[[package]]
name = "unicode-bidi"
version = "0.3.4"

View File

@ -53,9 +53,17 @@ hint: This command only works in the manifest directory of a Cargo package."#
DatabaseCommand::Setup { source } => database::setup(&source, &database_url).await?,
},
Command::Prepare { check: false, args } => prepare::run(&database_url, args)?,
Command::Prepare {
check: false,
merged,
args,
} => prepare::run(&database_url, merged, args)?,
Command::Prepare { check: true, args } => prepare::check(&database_url, args)?,
Command::Prepare {
check: true,
merged,
args,
} => prepare::check(&database_url, merged, args)?,
};
Ok(())

View File

@ -29,6 +29,10 @@ pub enum Command {
#[clap(long)]
check: bool,
/// Generate a single top-level `sqlx-data.json` file when using a cargo workspace.
#[clap(long)]
merged: bool,
/// Arguments to be passed to `cargo rustc ...`.
#[clap(last = true)]
args: Vec<String>,

View File

@ -13,7 +13,7 @@ use std::{env, fs};
type QueryData = BTreeMap<String, serde_json::Value>;
type JsonObject = serde_json::Map<String, serde_json::Value>;
pub fn run(url: &str, cargo_args: Vec<String>) -> anyhow::Result<()> {
pub fn run(url: &str, merge: bool, cargo_args: Vec<String>) -> anyhow::Result<()> {
#[derive(serde::Serialize)]
struct DataFile {
db: &'static str,
@ -22,7 +22,7 @@ pub fn run(url: &str, cargo_args: Vec<String>) -> anyhow::Result<()> {
}
let db_kind = get_db_kind(url)?;
let data = run_prepare_step(cargo_args)?;
let data = run_prepare_step(merge, cargo_args)?;
if data.is_empty() {
println!(
@ -45,9 +45,9 @@ pub fn run(url: &str, cargo_args: Vec<String>) -> anyhow::Result<()> {
Ok(())
}
pub fn check(url: &str, cargo_args: Vec<String>) -> anyhow::Result<()> {
pub fn check(url: &str, merge: bool, cargo_args: Vec<String>) -> anyhow::Result<()> {
let db_kind = get_db_kind(url)?;
let data = run_prepare_step(cargo_args)?;
let data = run_prepare_step(merge, cargo_args)?;
let data_file = fs::read("sqlx-data.json").context(
"failed to open `sqlx-data.json`; you may need to run `cargo sqlx prepare` first",
@ -78,7 +78,7 @@ pub fn check(url: &str, cargo_args: Vec<String>) -> anyhow::Result<()> {
Ok(())
}
fn run_prepare_step(cargo_args: Vec<String>) -> anyhow::Result<QueryData> {
fn run_prepare_step(merge: bool, cargo_args: Vec<String>) -> anyhow::Result<QueryData> {
// path to the Cargo executable
let cargo = env::var("CARGO")
.context("`prepare` subcommand may only be invoked as `cargo sqlx prepare`")?;
@ -92,20 +92,41 @@ fn run_prepare_step(cargo_args: Vec<String>) -> anyhow::Result<QueryData> {
// have repeatedly caused issues in the past.
let _ = remove_dir_all(metadata.target_directory.join("sqlx"));
let check_status = Command::new(&cargo)
.arg("rustc")
.args(cargo_args)
.arg("--")
.arg("--emit")
.arg("dep-info,metadata")
// set an always-changing cfg so we can consistently trigger recompile
.arg("--cfg")
.arg(format!(
"__sqlx_recompile_trigger=\"{}\"",
SystemTime::UNIX_EPOCH.elapsed()?.as_millis()
))
.env("SQLX_OFFLINE", "false")
.status()?;
let check_status = if merge {
let check_status = Command::new(&cargo).arg("clean").status()?;
if !check_status.success() {
bail!("`cargo clean` failed with status: {}", check_status);
}
Command::new(&cargo)
.arg("check")
.args(cargo_args)
.env(
"RUSTFLAGS",
format!(
"--cfg __sqlx_recompile_trigger=\"{}\"",
SystemTime::UNIX_EPOCH.elapsed()?.as_millis()
),
)
.env("SQLX_OFFLINE", "false")
.status()?
} else {
Command::new(&cargo)
.arg("rustc")
.args(cargo_args)
.arg("--")
.arg("--emit")
.arg("dep-info,metadata")
// set an always-changing cfg so we can consistently trigger recompile
.arg("--cfg")
.arg(format!(
"__sqlx_recompile_trigger=\"{}\"",
SystemTime::UNIX_EPOCH.elapsed()?.as_millis()
))
.env("SQLX_OFFLINE", "false")
.status()?
};
if !check_status.success() {
bail!("`cargo check` failed with status: {}", check_status);

View File

@ -53,11 +53,13 @@ bit-vec = [ "sqlx-core/bit-vec" ]
json = [ "sqlx-core/json", "serde_json" ]
[dependencies]
cargo_metadata = "0.12.1"
dotenv = { version = "0.15.0", default-features = false }
futures = { version = "0.3.4", default-features = false, features = [ "executor" ] }
hex = { version = "0.4.2", optional = true }
heck = "0.3.1"
either = "1.5.3"
lazy_static = "1.4.0"
proc-macro2 = { version = "1.0.9", default-features = false }
sqlx-core = { version = "0.4.0", default-features = false, path = "../sqlx-core" }
sqlx-rt = { version = "0.2.0", default-features = false, path = "../sqlx-rt" }

View File

@ -1,5 +1,5 @@
use std::borrow::Cow;
use std::env;
use std::{borrow::Cow, path::PathBuf};
use proc_macro2::{Span, TokenStream};
use syn::Type;
@ -16,12 +16,29 @@ use crate::database::DatabaseExt;
use crate::query::data::QueryData;
use crate::query::input::RecordType;
use either::Either;
use lazy_static::lazy_static;
mod args;
mod data;
mod input;
mod output;
// 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
lazy_static! {
static ref CRATE_ROOT: PathBuf = {
let manifest_dir =
env::var("CARGO_MANIFEST_DIR").expect("`CARGO_MANIFEST_DIR` must be set");
let metadata = cargo_metadata::MetadataCommand::new()
.current_dir(manifest_dir)
.exec()
.expect("Could not fetch metadata");
metadata.workspace_root
};
}
pub fn expand_input(input: QueryMacroInput) -> crate::Result<TokenStream> {
let manifest_dir =
env::var("CARGO_MANIFEST_DIR").map_err(|_| "`CARGO_MANIFEST_DIR` must be set")?;
@ -47,8 +64,12 @@ pub fn expand_input(input: QueryMacroInput) -> crate::Result<TokenStream> {
_ => {
let data_file_path = std::path::Path::new(&manifest_dir).join("sqlx-data.json");
let workspace_data_file_path = CRATE_ROOT.join("sqlx-data.json");
if data_file_path.exists() {
expand_from_file(input, data_file_path)
} else if workspace_data_file_path.exists() {
expand_from_file(input, workspace_data_file_path)
} else {
Err(
"`DATABASE_URL` must be set, or `cargo sqlx prepare` must have been run \