Skip to content

Commit cf3ce13

Browse files
ascheyabonander
authored andcommitted
fix(prepare): store temporary query files inside the workspace
1 parent 70934d7 commit cf3ce13

File tree

4 files changed

+39
-4
lines changed

4 files changed

+39
-4
lines changed

FAQ.md

+7-1
Original file line numberDiff line numberDiff line change
@@ -200,11 +200,17 @@ as an ergonomic choice it does _not_ block committing if `cargo sqlx prepare` fa
200200

201201
We're working on a way for the macros to save their data to the filesystem automatically which should be part of SQLx 0.7,
202202
so your pre-commit hook would then just need to stage the changed files. This can be enabled by creating a directory
203-
and setting the `SQLX_OFFLINE_DIR` environment variable to it before compiling, e.g.
203+
and setting the `SQLX_OFFLINE_DIR` environment variable to it before compiling.
204+
Additionally, if you're not using Cargo or have a nonstandard setup, you may want to set the `SQLX_TMP`
205+
variable in order to store temporary query files somewhere that isn't picked up by git.
206+
These files should get cleaned up automatically, but they may not if there's a failure. For example:
204207

205208
```shell
206209
$ mkdir .sqlx
207210
$ export SQLX_OFFLINE_DIR="./.sqlx"`
211+
$ # Optional and only useful if using a nonstandard setup, ensures temp files won't get picked up by git on failure
212+
$ mkdir ./my-custom-target/sqlx
213+
$ export SQLX_TMP="./my-custom-target/sqlx-tmp"
208214
$ cargo check
209215
```
210216

sqlx-cli/src/prepare.rs

+9
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,14 @@ fn run_prepare_step(ctx: &PrepareCtx, cache_dir: &Path) -> anyhow::Result<()> {
147147
"Failed to create query cache directory: {:?}",
148148
cache_dir
149149
))?;
150+
151+
// Create directory to hold temporary query files before they get persisted to SQLX_OFFLINE_DIR
152+
let tmp_dir = ctx.metadata.target_directory().join("sqlx-tmp");
153+
fs::create_dir_all(&tmp_dir).context(format!(
154+
"Failed to create temporary query cache directory: {:?}",
155+
cache_dir
156+
))?;
157+
150158
// Only delete sqlx-*.json files to avoid accidentally deleting any user data.
151159
for query_file in glob_query_files(cache_dir).context("Failed to read query cache files")? {
152160
fs::remove_file(&query_file)
@@ -163,6 +171,7 @@ fn run_prepare_step(ctx: &PrepareCtx, cache_dir: &Path) -> anyhow::Result<()> {
163171
check_command
164172
.arg("check")
165173
.args(&ctx.cargo_args)
174+
.env("SQLX_TMP", tmp_dir)
166175
.env("DATABASE_URL", &ctx.connect_opts.database_url)
167176
.env("SQLX_OFFLINE", "false")
168177
.env("SQLX_OFFLINE_DIR", cache_dir);

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

+9-2
Original file line numberDiff line numberDiff line change
@@ -157,10 +157,17 @@ where
157157
}
158158
}
159159

160-
pub(super) fn save_in(&self, dir: impl AsRef<Path>) -> crate::Result<()> {
160+
pub(super) fn save_in(
161+
&self,
162+
dir: impl AsRef<Path>,
163+
tmp_dir: impl AsRef<Path>,
164+
) -> crate::Result<()> {
161165
// Output to a temporary file first, then move it atomically to avoid clobbering
162166
// other invocations trying to write to the same path.
163-
let mut tmp_file = tempfile::NamedTempFile::new()
167+
168+
// Use a temp directory inside the workspace to avoid potential issues
169+
// with persisting the file across filesystems.
170+
let mut tmp_file = tempfile::NamedTempFile::new_in(tmp_dir)
164171
.map_err(|err| format!("failed to create query file: {:?}", err))?;
165172
serde_json::to_writer_pretty(tmp_file.as_file_mut(), self)
166173
.map_err(|err| format!("failed to serialize query data to file: {:?}", err))?;

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

+14-1
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,19 @@ where
357357
if let Ok(dir) = env("SQLX_OFFLINE_DIR") {
358358
let path = PathBuf::from(&dir);
359359

360+
// Prefer SQLX_TMP if set explicitly.
361+
// Otherwise fallback to CARGO_TARGET_DIR and then the standard target directory.
362+
let tmp_dir = if let Ok(tmp_dir) = env("SQLX_TMP") {
363+
PathBuf::from(tmp_dir)
364+
} else if let Ok(target_dir) = env("CARGO_TARGET_DIR") {
365+
PathBuf::from(target_dir)
366+
} else {
367+
let tmp_target = PathBuf::from("./target/sqlx");
368+
fs::create_dir_all(&tmp_target)
369+
.map_err(|e| format!("Error creating cache directory: {e:?}"))?;
370+
tmp_target
371+
};
372+
360373
match fs::metadata(&path) {
361374
Err(e) => {
362375
if e.kind() != io::ErrorKind::NotFound {
@@ -376,7 +389,7 @@ where
376389
}
377390

378391
// .sqlx exists and is a directory, store data.
379-
data.save_in(path)?;
392+
data.save_in(path, tmp_dir)?;
380393
}
381394
}
382395
}

0 commit comments

Comments
 (0)