Skip to content

Commit 5cac661

Browse files
committed
feat(cli): add --config override to all relevant commands
1 parent a67bb1b commit 5cac661

File tree

3 files changed

+108
-25
lines changed

3 files changed

+108
-25
lines changed

sqlx-cli/src/lib.rs

Lines changed: 36 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
use std::io;
2-
use std::path::PathBuf;
32
use std::time::Duration;
43

5-
use anyhow::{Context, Result};
64
use futures::{Future, TryFutureExt};
75

86
use sqlx::{AnyConnection, Connection};
@@ -33,7 +31,7 @@ pub fn maybe_apply_dotenv() {
3331

3432
pub use sqlx::_unstable::config::{self, Config};
3533

36-
pub async fn run(opt: Opt) -> Result<()> {
34+
pub async fn run(opt: Opt) -> anyhow::Result<()> {
3735
// This `select!` is here so that when the process receives a `SIGINT` (CTRL + C),
3836
// the futures currently running on this task get dropped before the program exits.
3937
// This is currently necessary for the consumers of the `dialoguer` crate to restore
@@ -53,19 +51,20 @@ pub async fn run(opt: Opt) -> Result<()> {
5351
}
5452
}
5553

56-
async fn do_run(opt: Opt) -> Result<()> {
57-
let config = config_from_current_dir().await?;
58-
54+
async fn do_run(opt: Opt) -> anyhow::Result<()> {
5955
match opt.command {
6056
Command::Migrate(migrate) => match migrate.command {
61-
MigrateCommand::Add(opts) => migrate::add(config, opts).await?,
57+
MigrateCommand::Add(opts) => migrate::add(opts).await?,
6258
MigrateCommand::Run {
6359
source,
60+
config,
6461
dry_run,
6562
ignore_missing,
6663
mut connect_opts,
6764
target_version,
6865
} => {
66+
let config = config.load_config().await?;
67+
6968
connect_opts.populate_db_url(config)?;
7069

7170
migrate::run(
@@ -80,11 +79,14 @@ async fn do_run(opt: Opt) -> Result<()> {
8079
}
8180
MigrateCommand::Revert {
8281
source,
82+
config,
8383
dry_run,
8484
ignore_missing,
8585
mut connect_opts,
8686
target_version,
8787
} => {
88+
let config = config.load_config().await?;
89+
8890
connect_opts.populate_db_url(config)?;
8991

9092
migrate::revert(
@@ -99,43 +101,66 @@ async fn do_run(opt: Opt) -> Result<()> {
99101
}
100102
MigrateCommand::Info {
101103
source,
104+
config,
102105
mut connect_opts,
103106
} => {
107+
let config = config.load_config().await?;
108+
104109
connect_opts.populate_db_url(config)?;
105110

106111
migrate::info(config, &source, &connect_opts).await?
107112
}
108-
MigrateCommand::BuildScript { source, force } => {
113+
MigrateCommand::BuildScript {
114+
source,
115+
config,
116+
force,
117+
} => {
118+
let config = config.load_config().await?;
119+
109120
migrate::build_script(config, &source, force)?
110121
}
111122
},
112123

113124
Command::Database(database) => match database.command {
114-
DatabaseCommand::Create { mut connect_opts } => {
125+
DatabaseCommand::Create {
126+
config,
127+
mut connect_opts,
128+
} => {
129+
let config = config.load_config().await?;
130+
115131
connect_opts.populate_db_url(config)?;
116132
database::create(&connect_opts).await?
117133
}
118134
DatabaseCommand::Drop {
119135
confirmation,
136+
config,
120137
mut connect_opts,
121138
force,
122139
} => {
140+
let config = config.load_config().await?;
141+
123142
connect_opts.populate_db_url(config)?;
124143
database::drop(&connect_opts, !confirmation.yes, force).await?
125144
}
126145
DatabaseCommand::Reset {
127146
confirmation,
128147
source,
148+
config,
129149
mut connect_opts,
130150
force,
131151
} => {
152+
let config = config.load_config().await?;
153+
132154
connect_opts.populate_db_url(config)?;
133155
database::reset(config, &source, &connect_opts, !confirmation.yes, force).await?
134156
}
135157
DatabaseCommand::Setup {
136158
source,
159+
config,
137160
mut connect_opts,
138161
} => {
162+
let config = config.load_config().await?;
163+
139164
connect_opts.populate_db_url(config)?;
140165
database::setup(config, &source, &connect_opts).await?
141166
}
@@ -147,7 +172,9 @@ async fn do_run(opt: Opt) -> Result<()> {
147172
workspace,
148173
mut connect_opts,
149174
args,
175+
config,
150176
} => {
177+
let config = config.load_config().await?;
151178
connect_opts.populate_db_url(config)?;
152179
prepare::run(check, all, workspace, connect_opts, args).await?
153180
}
@@ -203,18 +230,3 @@ where
203230
)
204231
.await
205232
}
206-
207-
async fn config_from_current_dir() -> anyhow::Result<&'static Config> {
208-
// Tokio does file I/O on a background task anyway
209-
tokio::task::spawn_blocking(|| {
210-
let path = PathBuf::from("sqlx.toml");
211-
212-
if path.exists() {
213-
eprintln!("Found `sqlx.toml` in current directory; reading...");
214-
}
215-
216-
Config::read_with_or_default(move || Ok(path))
217-
})
218-
.await
219-
.context("unexpected error loading config")
220-
}

sqlx-cli/src/migrate.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@ use std::fs::{self, File};
1313
use std::path::Path;
1414
use std::time::Duration;
1515

16-
pub async fn add(config: &Config, opts: AddMigrationOpts) -> anyhow::Result<()> {
16+
pub async fn add(opts: AddMigrationOpts) -> anyhow::Result<()> {
17+
let config = opts.config.load_config().await?;
18+
1719
let source = opts.source.resolve(config);
1820

1921
fs::create_dir_all(source).context("Unable to create migrations directory")?;

sqlx-cli/src/opt.rs

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use clap_complete::Shell;
1111
use sqlx::migrate::Migrator;
1212
use std::env;
1313
use std::ops::{Deref, Not};
14+
use std::path::PathBuf;
1415

1516
const HELP_STYLES: Styles = Styles::styled()
1617
.header(AnsiColor::Blue.on_default().bold())
@@ -67,6 +68,9 @@ pub enum Command {
6768

6869
#[clap(flatten)]
6970
connect_opts: ConnectOpts,
71+
72+
#[clap(flatten)]
73+
config: ConfigOpt,
7074
},
7175

7276
#[clap(alias = "mig")]
@@ -90,13 +94,19 @@ pub enum DatabaseCommand {
9094
Create {
9195
#[clap(flatten)]
9296
connect_opts: ConnectOpts,
97+
98+
#[clap(flatten)]
99+
config: ConfigOpt,
93100
},
94101

95102
/// Drops the database specified in your DATABASE_URL.
96103
Drop {
97104
#[clap(flatten)]
98105
confirmation: Confirmation,
99106

107+
#[clap(flatten)]
108+
config: ConfigOpt,
109+
100110
#[clap(flatten)]
101111
connect_opts: ConnectOpts,
102112

@@ -113,6 +123,9 @@ pub enum DatabaseCommand {
113123
#[clap(flatten)]
114124
source: MigrationSourceOpt,
115125

126+
#[clap(flatten)]
127+
config: ConfigOpt,
128+
116129
#[clap(flatten)]
117130
connect_opts: ConnectOpts,
118131

@@ -126,6 +139,9 @@ pub enum DatabaseCommand {
126139
#[clap(flatten)]
127140
source: MigrationSourceOpt,
128141

142+
#[clap(flatten)]
143+
config: ConfigOpt,
144+
129145
#[clap(flatten)]
130146
connect_opts: ConnectOpts,
131147
},
@@ -212,6 +228,9 @@ pub enum MigrateCommand {
212228
#[clap(flatten)]
213229
source: MigrationSourceOpt,
214230

231+
#[clap(flatten)]
232+
config: ConfigOpt,
233+
215234
/// List all the migrations to be run without applying
216235
#[clap(long)]
217236
dry_run: bool,
@@ -233,6 +252,9 @@ pub enum MigrateCommand {
233252
#[clap(flatten)]
234253
source: MigrationSourceOpt,
235254

255+
#[clap(flatten)]
256+
config: ConfigOpt,
257+
236258
/// List the migration to be reverted without applying
237259
#[clap(long)]
238260
dry_run: bool,
@@ -255,6 +277,9 @@ pub enum MigrateCommand {
255277
#[clap(flatten)]
256278
source: MigrationSourceOpt,
257279

280+
#[clap(flatten)]
281+
config: ConfigOpt,
282+
258283
#[clap(flatten)]
259284
connect_opts: ConnectOpts,
260285
},
@@ -266,6 +291,9 @@ pub enum MigrateCommand {
266291
#[clap(flatten)]
267292
source: MigrationSourceOpt,
268293

294+
#[clap(flatten)]
295+
config: ConfigOpt,
296+
269297
/// Overwrite the build script if it already exists.
270298
#[clap(long)]
271299
force: bool,
@@ -279,6 +307,9 @@ pub struct AddMigrationOpts {
279307
#[clap(flatten)]
280308
pub source: MigrationSourceOpt,
281309

310+
#[clap(flatten)]
311+
pub config: ConfigOpt,
312+
282313
/// If set, create an up-migration only. Conflicts with `--reversible`.
283314
#[clap(long, conflicts_with = "reversible")]
284315
simple: bool,
@@ -358,6 +389,20 @@ pub struct NoDotenvOpt {
358389
pub no_dotenv: bool,
359390
}
360391

392+
#[derive(Args, Debug)]
393+
pub struct ConfigOpt {
394+
/// Override the path to the config file.
395+
///
396+
/// Defaults to `sqlx.toml` in the current directory, if it exists.
397+
///
398+
/// Configuration file loading may be bypassed with `--config=/dev/null` on Linux,
399+
/// or `--config=NUL` on Windows.
400+
///
401+
/// Config file loading is enabled by the `sqlx-toml` feature.
402+
#[clap(long)]
403+
pub config: Option<PathBuf>,
404+
}
405+
361406
impl ConnectOpts {
362407
/// Require a database URL to be provided, otherwise
363408
/// return an error.
@@ -401,6 +446,30 @@ impl ConnectOpts {
401446
}
402447
}
403448

449+
impl ConfigOpt {
450+
pub async fn load_config(&self) -> anyhow::Result<&'static Config> {
451+
let path = self.config.clone();
452+
453+
// Tokio does file I/O on a background task anyway
454+
tokio::task::spawn_blocking(|| {
455+
if let Some(path) = path {
456+
let err_str = format!("error reading config from {path:?}");
457+
Config::try_read_with(|| Ok(path)).context(err_str)
458+
} else {
459+
let path = PathBuf::from("sqlx.toml");
460+
461+
if path.exists() {
462+
eprintln!("Found `sqlx.toml` in current directory; reading...");
463+
}
464+
465+
Ok(Config::read_with_or_default(move || Ok(path)))
466+
}
467+
})
468+
.await
469+
.context("unexpected error loading config")?
470+
}
471+
}
472+
404473
/// Argument for automatic confirmation.
405474
#[derive(Args, Copy, Clone, Debug)]
406475
pub struct Confirmation {

0 commit comments

Comments
 (0)