mirror of
https://github.com/astral-sh/uv.git
synced 2025-09-30 22:11:12 +00:00
Allow symlinks to files in scripts directory (#5380)
## Summary Closes https://github.com/astral-sh/uv/issues/5359. ## Test Plan Unfortunately, the only packages I know of that use this are Ruff and uv, and both are too heavy to install in a recurring test, so: `uv tool install hatch==1.12.0 --with uv==0.2.27 --force --link-mode=symlink`
This commit is contained in:
parent
8942ec36c0
commit
ad4a15d0c2
2 changed files with 82 additions and 11 deletions
|
@ -441,13 +441,31 @@ fn install_script(
|
||||||
record: &mut [RecordEntry],
|
record: &mut [RecordEntry],
|
||||||
file: &DirEntry,
|
file: &DirEntry,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
if !file.file_type()?.is_file() {
|
let file_type = file.file_type()?;
|
||||||
|
|
||||||
|
if file_type.is_dir() {
|
||||||
return Err(Error::InvalidWheel(format!(
|
return Err(Error::InvalidWheel(format!(
|
||||||
"Wheel contains entry in scripts directory that is not a file: {}",
|
"Wheel contains an invalid entry (directory) in the `scripts` directory: {}",
|
||||||
file.path().display()
|
file.path().simplified_display()
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if file_type.is_symlink() {
|
||||||
|
let Ok(target) = file.path().canonicalize() else {
|
||||||
|
return Err(Error::InvalidWheel(format!(
|
||||||
|
"Wheel contains an invalid entry (broken symlink) in the `scripts` directory: {}",
|
||||||
|
file.path().simplified_display(),
|
||||||
|
)));
|
||||||
|
};
|
||||||
|
if target.is_dir() {
|
||||||
|
return Err(Error::InvalidWheel(format!(
|
||||||
|
"Wheel contains an invalid entry (directory symlink) in the `scripts` directory: {} ({})",
|
||||||
|
file.path().simplified_display(),
|
||||||
|
target.simplified_display()
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let script_absolute = layout.scheme.scripts.join(file.file_name());
|
let script_absolute = layout.scheme.scripts.join(file.file_name());
|
||||||
let script_relative =
|
let script_relative =
|
||||||
pathdiff::diff_paths(&script_absolute, site_packages).ok_or_else(|| {
|
pathdiff::diff_paths(&script_absolute, site_packages).ok_or_else(|| {
|
||||||
|
|
|
@ -105,12 +105,16 @@ fn install() -> Result<()> {
|
||||||
.join("__init__.cpython-312.pyc")
|
.join("__init__.cpython-312.pyc")
|
||||||
.exists());
|
.exists());
|
||||||
|
|
||||||
context.assert_command("import markupsafe").success();
|
context
|
||||||
|
.assert_command("from markupsafe import Markup")
|
||||||
|
.success();
|
||||||
|
|
||||||
// Removing the cache shouldn't invalidate the virtual environment.
|
// Removing the cache shouldn't invalidate the virtual environment.
|
||||||
fs::remove_dir_all(context.cache_dir.path())?;
|
fs::remove_dir_all(context.cache_dir.path())?;
|
||||||
|
|
||||||
context.assert_command("import markupsafe").success();
|
context
|
||||||
|
.assert_command("from markupsafe import Markup")
|
||||||
|
.success();
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -140,12 +144,16 @@ fn install_copy() -> Result<()> {
|
||||||
"###
|
"###
|
||||||
);
|
);
|
||||||
|
|
||||||
context.assert_command("import markupsafe").success();
|
context
|
||||||
|
.assert_command("from markupsafe import Markup")
|
||||||
|
.success();
|
||||||
|
|
||||||
// Removing the cache shouldn't invalidate the virtual environment.
|
// Removing the cache shouldn't invalidate the virtual environment.
|
||||||
fs::remove_dir_all(context.cache_dir.path())?;
|
fs::remove_dir_all(context.cache_dir.path())?;
|
||||||
|
|
||||||
context.assert_command("import markupsafe").success();
|
context
|
||||||
|
.assert_command("from markupsafe import Markup")
|
||||||
|
.success();
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -175,12 +183,55 @@ fn install_hardlink() -> Result<()> {
|
||||||
"###
|
"###
|
||||||
);
|
);
|
||||||
|
|
||||||
context.assert_command("import markupsafe").success();
|
context
|
||||||
|
.assert_command("from markupsafe import Markup")
|
||||||
|
.success();
|
||||||
|
|
||||||
// Removing the cache shouldn't invalidate the virtual environment.
|
// Removing the cache shouldn't invalidate the virtual environment.
|
||||||
fs::remove_dir_all(context.cache_dir.path())?;
|
fs::remove_dir_all(context.cache_dir.path())?;
|
||||||
|
|
||||||
context.assert_command("import markupsafe").success();
|
context
|
||||||
|
.assert_command("from markupsafe import Markup")
|
||||||
|
.success();
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Install a package into a virtual environment using symlink semantics.
|
||||||
|
#[test]
|
||||||
|
fn install_symlink() -> Result<()> {
|
||||||
|
let context = TestContext::new("3.12");
|
||||||
|
|
||||||
|
let requirements_txt = context.temp_dir.child("requirements.txt");
|
||||||
|
requirements_txt.write_str("MarkupSafe==2.1.3")?;
|
||||||
|
|
||||||
|
uv_snapshot!(context.pip_sync()
|
||||||
|
.arg("requirements.txt")
|
||||||
|
.arg("--link-mode")
|
||||||
|
.arg("symlink")
|
||||||
|
.arg("--strict"), @r###"
|
||||||
|
success: true
|
||||||
|
exit_code: 0
|
||||||
|
----- stdout -----
|
||||||
|
|
||||||
|
----- stderr -----
|
||||||
|
Resolved 1 package in [TIME]
|
||||||
|
Prepared 1 package in [TIME]
|
||||||
|
Installed 1 package in [TIME]
|
||||||
|
+ markupsafe==2.1.3
|
||||||
|
"###
|
||||||
|
);
|
||||||
|
|
||||||
|
context
|
||||||
|
.assert_command("from markupsafe import Markup")
|
||||||
|
.success();
|
||||||
|
|
||||||
|
// Removing the cache _should_ invalidate the virtual environment.
|
||||||
|
fs::remove_dir_all(context.cache_dir.path())?;
|
||||||
|
|
||||||
|
context
|
||||||
|
.assert_command("from markupsafe import Markup")
|
||||||
|
.failure();
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -210,7 +261,7 @@ fn install_many() -> Result<()> {
|
||||||
);
|
);
|
||||||
|
|
||||||
context
|
context
|
||||||
.assert_command("import markupsafe; import tomli")
|
.assert_command("from markupsafe import Markup; import tomli")
|
||||||
.success();
|
.success();
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -244,7 +295,9 @@ fn noop() -> Result<()> {
|
||||||
"###
|
"###
|
||||||
);
|
);
|
||||||
|
|
||||||
context.assert_command("import markupsafe").success();
|
context
|
||||||
|
.assert_command("from markupsafe import Markup")
|
||||||
|
.success();
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue