Skip to content

Commit 4ea1ff6

Browse files
committed
Avoid erroring when creating venv in current working directory
1 parent b2c8f5e commit 4ea1ff6

File tree

2 files changed

+37
-8
lines changed

2 files changed

+37
-8
lines changed

crates/uv-virtualenv/src/virtualenv.rs

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,18 @@ pub(crate) fn create(
7777
base_python.display()
7878
);
7979

80+
// Extract the prompt and compute the absolute path prior to validating the location; otherwise,
81+
// we risk deleting (and recreating) the current working directory, which would cause the `CWD`
82+
// queries to fail.
83+
let prompt = match prompt {
84+
Prompt::CurrentDirectoryName => CWD
85+
.file_name()
86+
.map(|name| name.to_string_lossy().to_string()),
87+
Prompt::Static(value) => Some(value),
88+
Prompt::None => None,
89+
};
90+
let absolute = std::path::absolute(location)?;
91+
8092
// Validate the existing location.
8193
match location.metadata() {
8294
Ok(metadata) if metadata.is_file() => {
@@ -172,7 +184,8 @@ pub(crate) fn create(
172184
Err(err) => return Err(Error::Io(err)),
173185
}
174186

175-
let location = std::path::absolute(location)?;
187+
// Use the absolute path for all further operations.
188+
let location = absolute;
176189

177190
let bin_name = if cfg!(unix) {
178191
"bin"
@@ -182,13 +195,6 @@ pub(crate) fn create(
182195
unimplemented!("Only Windows and Unix are supported")
183196
};
184197
let scripts = location.join(&interpreter.virtualenv().scripts);
185-
let prompt = match prompt {
186-
Prompt::CurrentDirectoryName => CWD
187-
.file_name()
188-
.map(|name| name.to_string_lossy().to_string()),
189-
Prompt::Static(value) => Some(value),
190-
Prompt::None => None,
191-
};
192198

193199
// Add the CACHEDIR.TAG.
194200
cachedir::ensure_tag(&location)?;

crates/uv/tests/it/venv.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1572,3 +1572,26 @@ fn create_venv_nested_symlink_preservation() -> Result<()> {
15721572

15731573
Ok(())
15741574
}
1575+
1576+
#[test]
1577+
fn create_venv_current_working_directory() {
1578+
let context = TestContext::new_with_versions(&["3.12"]);
1579+
1580+
uv_snapshot!(context.filters(), context.venv()
1581+
.arg(".")
1582+
.arg("--python")
1583+
.arg("3.12"), @r"
1584+
success: true
1585+
exit_code: 0
1586+
----- stdout -----
1587+
1588+
----- stderr -----
1589+
Using CPython 3.12.[X] interpreter at: [PYTHON-3.12]
1590+
Creating virtual environment at: .
1591+
warning: A directory already exists at `.`. In the future, uv will require `--clear` to replace it
1592+
Activate with: source bin/activate
1593+
"
1594+
);
1595+
1596+
context.root.assert(predicates::path::is_dir());
1597+
}

0 commit comments

Comments
 (0)