mirror of
https://github.com/astral-sh/uv.git
synced 2025-11-01 04:17:37 +00:00
Ensure mtime of site packages is updated during wheel installation (#2545)
Closes https://github.com/astral-sh/uv/issues/2530
This commit is contained in:
parent
136e744a9f
commit
baa30697a4
2 changed files with 72 additions and 2 deletions
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
use std::path::Path;
|
||||
use std::str::FromStr;
|
||||
use std::time::SystemTime;
|
||||
|
||||
use fs_err as fs;
|
||||
use fs_err::{DirEntry, File};
|
||||
|
|
@ -263,6 +264,31 @@ fn clone_wheel_files(
|
|||
count += 1;
|
||||
}
|
||||
|
||||
// The directory mtime is not updated when cloning and the mtime is used by CPython's
|
||||
// import mechanisms to determine if it should look for new packages in a directory.
|
||||
// Here, we force the mtime to be updated to ensure that packages are importable without
|
||||
// manual cache invalidation.
|
||||
//
|
||||
// <https://github.com/python/cpython/blob/8336cb2b6f428246803b02a4e97fce49d0bb1e09/Lib/importlib/_bootstrap_external.py#L1601>
|
||||
let now = SystemTime::now();
|
||||
|
||||
// `File.set_modified` is not available in `fs_err` yet
|
||||
#[allow(clippy::disallowed_types)]
|
||||
match std::fs::File::open(site_packages.as_ref()) {
|
||||
Ok(dir) => {
|
||||
if let Err(err) = dir.set_modified(now) {
|
||||
debug!(
|
||||
"Failed to update mtime for {}: {err}",
|
||||
site_packages.as_ref().display()
|
||||
);
|
||||
}
|
||||
}
|
||||
Err(err) => debug!(
|
||||
"Failed to open {} to update mtime: {err}",
|
||||
site_packages.as_ref().display()
|
||||
),
|
||||
}
|
||||
|
||||
Ok(count)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,13 +1,12 @@
|
|||
#![cfg(all(feature = "python", feature = "pypi"))]
|
||||
|
||||
use std::process::Command;
|
||||
|
||||
use anyhow::Result;
|
||||
use assert_cmd::prelude::*;
|
||||
use assert_fs::prelude::*;
|
||||
use base64::{prelude::BASE64_STANDARD as base64, Engine};
|
||||
use indoc::indoc;
|
||||
use itertools::Itertools;
|
||||
use std::process::Command;
|
||||
use url::Url;
|
||||
|
||||
use common::{uv_snapshot, TestContext, EXCLUDE_NEWER, INSTA_FILTERS};
|
||||
|
|
@ -2843,3 +2842,48 @@ fn install_index_with_relative_links_authenticated() {
|
|||
|
||||
context.assert_command("import anyio").success();
|
||||
}
|
||||
|
||||
/// The modified time of `site-packages` should change on package installation.
|
||||
#[cfg(unix)]
|
||||
#[test]
|
||||
fn install_site_packages_mtime_updated() -> Result<()> {
|
||||
use std::os::unix::fs::MetadataExt;
|
||||
|
||||
let context = TestContext::new("3.12");
|
||||
|
||||
let site_packages = context.site_packages();
|
||||
|
||||
// `mtime` is only second-resolution so we include the nanoseconds as well
|
||||
let metadata = site_packages.metadata()?;
|
||||
let pre_mtime = metadata.mtime();
|
||||
let pre_mtime_ns = metadata.mtime_nsec();
|
||||
|
||||
// Install a package.
|
||||
uv_snapshot!(command(&context)
|
||||
.arg("anyio")
|
||||
.arg("--strict"), @r###"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
Resolved 3 packages in [TIME]
|
||||
Downloaded 3 packages in [TIME]
|
||||
Installed 3 packages in [TIME]
|
||||
+ anyio==4.0.0
|
||||
+ idna==3.4
|
||||
+ sniffio==1.3.0
|
||||
"###
|
||||
);
|
||||
|
||||
let metadata = site_packages.metadata()?;
|
||||
let post_mtime = metadata.mtime();
|
||||
let post_mtime_ns = metadata.mtime_nsec();
|
||||
|
||||
assert!(
|
||||
(post_mtime, post_mtime_ns) > (pre_mtime, pre_mtime_ns),
|
||||
"Expected newer mtime than {pre_mtime}.{pre_mtime_ns} but got {post_mtime}.{post_mtime_ns}"
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue