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 b188c83717
commit 3e1da43434
6 changed files with 271 additions and 60 deletions

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