Create missing dir for `uv export`/ `uv pip compile` (#9648)

## Summary

Closes #9643.

I modified the `commit` fn so this applies to `uv compile --output-file`
too. But I can move it to the export module if we want to restrict this
to `uv export` only.

## Test Plan

`cargo test`
This commit is contained in:
Ahmed Ilyas 2024-12-04 22:20:30 +01:00 committed by GitHub
parent 231504b1d0
commit 7939d3fb5b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 76 additions and 0 deletions

View File

@ -231,6 +231,10 @@ impl<'a> OutputWriter<'a> {
/// Commit the buffer to the output file.
async fn commit(self) -> std::io::Result<()> {
if let Some(output_file) = self.output_file {
if let Some(parent_dir) = output_file.parent() {
fs_err::create_dir_all(parent_dir)?;
}
// If the output file is an existing symlink, write to the destination instead.
let output_file = fs_err::read_link(output_file)
.map(Cow::Owned)

View File

@ -761,6 +761,78 @@ fn frozen() -> Result<()> {
Ok(())
}
#[test]
fn create_missing_dir() -> Result<()> {
let context = TestContext::new("3.12");
let pyproject_toml = context.temp_dir.child("pyproject.toml");
pyproject_toml.write_str(
r#"
[project]
name = "project"
version = "0.1.0"
requires-python = ">=3.12"
dependencies = ["anyio==3.7.0"]
[build-system]
requires = ["setuptools>=42"]
build-backend = "setuptools.build_meta"
"#,
)?;
context.lock().assert().success();
uv_snapshot!(context.filters(), context.export()
.arg("--output-file")
.arg("requirements/requirements.txt"), @r###"
success: true
exit_code: 0
----- stdout -----
# This file was autogenerated by uv via the following command:
# uv export --cache-dir [CACHE_DIR] --output-file requirements/requirements.txt
-e .
anyio==3.7.0 \
--hash=sha256:275d9973793619a5374e1c89a4f4ad3f4b0a5510a2b5b939444bee8f4c4d37ce \
--hash=sha256:eddca883c4175f14df8aedce21054bfca3adb70ffe76a9f607aef9d7fa2ea7f0
idna==3.6 \
--hash=sha256:9ecdbbd083b06798ae1e86adcbfe8ab1479cf864e4ee30fe4e46a003d12491ca \
--hash=sha256:c05567e9c24a6b9faaa835c4821bad0590fbb9d5779e7caa6e1cc4978e7eb24f
sniffio==1.3.1 \
--hash=sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2 \
--hash=sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc
----- stderr -----
Resolved 4 packages in [TIME]
"###);
//
// Read the file contents.
let contents = apply_filters(
fs_err::read_to_string(
context
.temp_dir
.child("requirements")
.child("requirements.txt"),
)
.unwrap(),
context.filters(),
);
insta::assert_snapshot!(contents, @r###"
# This file was autogenerated by uv via the following command:
# uv export --cache-dir [CACHE_DIR] --output-file requirements/requirements.txt
-e .
anyio==3.7.0 \
--hash=sha256:275d9973793619a5374e1c89a4f4ad3f4b0a5510a2b5b939444bee8f4c4d37ce \
--hash=sha256:eddca883c4175f14df8aedce21054bfca3adb70ffe76a9f607aef9d7fa2ea7f0
idna==3.6 \
--hash=sha256:9ecdbbd083b06798ae1e86adcbfe8ab1479cf864e4ee30fe4e46a003d12491ca \
--hash=sha256:c05567e9c24a6b9faaa835c4821bad0590fbb9d5779e7caa6e1cc4978e7eb24f
sniffio==1.3.1 \
--hash=sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2 \
--hash=sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc
"###);
Ok(())
}
#[test]
fn non_project() -> Result<()> {
let context = TestContext::new("3.12");