Skip to content

Commit ac10042

Browse files
authored
Fix hardlinks in tar unpacking (#11221)
In astral-sh/tokio-tar#2, we accidentally changed the `target_base` from the target base to the parent of the file. This would cause hardlink unpacking to fail. Example: A hardlink at `hardlinked-0.1.0/pyproject.toml` pointing to `hardlinked-0.1.0/pyproject.toml.real` would try pointing to `hardlinked-0.1.0/hardlinked-0.1.0/pyproject.toml.real` instead and fail the unpacking. The actual fix is in astral-tokio-tar, on the uv side there are only tests. Fixes #11213
1 parent 748582e commit ac10042

File tree

3 files changed

+79
-2
lines changed

3 files changed

+79
-2
lines changed

Cargo.lock

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ uv-workspace = { path = "crates/uv-workspace" }
7373
anstream = { version = "0.6.15" }
7474
anyhow = { version = "1.0.89" }
7575
arcstr = { version = "1.2.0" }
76-
astral-tokio-tar = { git = "https://github.com/astral-sh/tokio-tar", rev = "ba2b140f27d081c463335f0d68b5f8df8e6c845e" }
76+
astral-tokio-tar = { git = "https://github.com/astral-sh/tokio-tar", rev = "efeaea927c7a40ee66121de2e1bebfd5d7a4a602" }
7777
async-channel = { version = "2.3.1" }
7878
async-compression = { version = "0.4.12", features = ["bzip2", "gzip", "xz", "zstd"] }
7979
async-trait = { version = "0.1.82" }

crates/uv/tests/it/build.rs

+77
Original file line numberDiff line numberDiff line change
@@ -1746,3 +1746,80 @@ fn build_version_mismatch() -> Result<()> {
17461746
"###);
17471747
Ok(())
17481748
}
1749+
1750+
#[cfg(unix)] // Symlinks aren't universally available on windows.
1751+
#[test]
1752+
fn build_with_symlink() -> Result<()> {
1753+
let context = TestContext::new("3.12");
1754+
context
1755+
.temp_dir
1756+
.child("pyproject.toml.real")
1757+
.write_str(indoc! {r#"
1758+
[project]
1759+
name = "softlinked"
1760+
version = "0.1.0"
1761+
requires-python = ">=3.12"
1762+
1763+
[build-system]
1764+
requires = ["hatchling"]
1765+
build-backend = "hatchling.build"
1766+
"#})?;
1767+
std::os::unix::fs::symlink(
1768+
context.temp_dir.child("pyproject.toml.real"),
1769+
context.temp_dir.child("pyproject.toml"),
1770+
)?;
1771+
context
1772+
.temp_dir
1773+
.child("src/softlinked/__init__.py")
1774+
.touch()?;
1775+
uv_snapshot!(context.filters(), context.build(), @r###"
1776+
success: true
1777+
exit_code: 0
1778+
----- stdout -----
1779+
1780+
----- stderr -----
1781+
Building source distribution...
1782+
Building wheel from source distribution...
1783+
Successfully built dist/softlinked-0.1.0.tar.gz
1784+
Successfully built dist/softlinked-0.1.0-py3-none-any.whl
1785+
"###);
1786+
Ok(())
1787+
}
1788+
1789+
#[test]
1790+
fn build_with_hardlink() -> Result<()> {
1791+
let context = TestContext::new("3.12");
1792+
context
1793+
.temp_dir
1794+
.child("pyproject.toml.real")
1795+
.write_str(indoc! {r#"
1796+
[project]
1797+
name = "hardlinked"
1798+
version = "0.1.0"
1799+
requires-python = ">=3.12"
1800+
1801+
[build-system]
1802+
requires = ["hatchling"]
1803+
build-backend = "hatchling.build"
1804+
"#})?;
1805+
fs_err::hard_link(
1806+
context.temp_dir.child("pyproject.toml.real"),
1807+
context.temp_dir.child("pyproject.toml"),
1808+
)?;
1809+
context
1810+
.temp_dir
1811+
.child("src/hardlinked/__init__.py")
1812+
.touch()?;
1813+
uv_snapshot!(context.filters(), context.build(), @r###"
1814+
success: true
1815+
exit_code: 0
1816+
----- stdout -----
1817+
1818+
----- stderr -----
1819+
Building source distribution...
1820+
Building wheel from source distribution...
1821+
Successfully built dist/hardlinked-0.1.0.tar.gz
1822+
Successfully built dist/hardlinked-0.1.0-py3-none-any.whl
1823+
"###);
1824+
Ok(())
1825+
}

0 commit comments

Comments
 (0)