[red-knot] Use web-time instead of FileTime::now (#16967)

## Summary

`std::time::now` isn't available on `wasm32-unknown-unknown` but it is
used by `FileTime::now`.

This PR replaces the usages of `FileTime::now` with a target specific
helper function that we already had in the memory file system.
Fixes https://github.com/astral-sh/ruff/issues/16966

## Test Plan

Tested that the playground no longer crash when adding an extra-path
This commit is contained in:
Micha Reiser 2025-03-25 14:03:30 +01:00 committed by GitHub
parent 4975c2f027
commit 8d16a5c8c9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 38 additions and 36 deletions

View file

@ -12,7 +12,7 @@ use red_knot_python_semantic::{resolve_module, ModuleName, PythonPlatform};
use ruff_db::files::{system_path_to_file, File, FileError};
use ruff_db::source::source_text;
use ruff_db::system::{
OsSystem, System, SystemPath, SystemPathBuf, UserConfigDirectoryOverrideGuard,
file_time_now, OsSystem, System, SystemPath, SystemPathBuf, UserConfigDirectoryOverrideGuard,
};
use ruff_db::{Db as _, Upcast};
use ruff_python_ast::PythonVersion;
@ -462,7 +462,7 @@ fn update_file(path: impl AsRef<SystemPath>, content: &str) -> anyhow::Result<()
std::thread::sleep(Duration::from_nanos(10));
filetime::set_file_handle_times(&file, None, Some(filetime::FileTime::now()))?;
filetime::set_file_handle_times(&file, None, Some(file_time_now()))?;
}
}

View file

@ -1,3 +1,5 @@
use crate::system::file_time_now;
/// A number representing the revision of a file.
///
/// Two revisions that don't compare equal signify that the file has been modified.
@ -16,7 +18,7 @@ impl FileRevision {
}
pub fn now() -> Self {
Self::from(filetime::FileTime::now())
Self::from(file_time_now())
}
pub const fn zero() -> Self {
@ -53,13 +55,12 @@ impl From<filetime::FileTime> for FileRevision {
#[cfg(test)]
mod tests {
use filetime::FileTime;
use super::*;
#[test]
fn revision_from_file_time() {
let file_time = FileTime::now();
let file_time = file_time_now();
let revision = FileRevision::from(file_time);
let revision = revision.as_u128();

View file

@ -7,6 +7,7 @@ pub use os::testing::UserConfigDirectoryOverrideGuard;
#[cfg(feature = "os")]
pub use os::OsSystem;
use filetime::FileTime;
use ruff_notebook::{Notebook, NotebookError};
use std::error::Error;
use std::fmt::{Debug, Formatter};
@ -346,3 +347,27 @@ pub enum GlobErrorKind {
IOError(io::Error),
NonUtf8Path,
}
#[cfg(not(target_arch = "wasm32"))]
pub fn file_time_now() -> FileTime {
FileTime::now()
}
#[cfg(target_arch = "wasm32")]
pub fn file_time_now() -> FileTime {
// Copied from FileTime::from_system_time()
let time = web_time::SystemTime::now();
time.duration_since(web_time::UNIX_EPOCH)
.map(|d| FileTime::from_unix_time(d.as_secs() as i64, d.subsec_nanos()))
.unwrap_or_else(|e| {
let until_epoch = e.duration();
let (sec_offset, nanos) = if until_epoch.subsec_nanos() == 0 {
(0, 0)
} else {
(-1, 1_000_000_000 - until_epoch.subsec_nanos())
};
FileTime::from_unix_time(-(until_epoch.as_secs() as i64) + sec_offset, nanos)
})
}

View file

@ -7,8 +7,8 @@ use filetime::FileTime;
use rustc_hash::FxHashMap;
use crate::system::{
walk_directory, DirectoryEntry, FileType, GlobError, GlobErrorKind, Metadata, Result,
SystemPath, SystemPathBuf, SystemVirtualPath, SystemVirtualPathBuf,
file_time_now, walk_directory, DirectoryEntry, FileType, GlobError, GlobErrorKind, Metadata,
Result, SystemPath, SystemPathBuf, SystemVirtualPath, SystemVirtualPathBuf,
};
use super::walk_directory::{
@ -163,7 +163,7 @@ impl MemoryFileSystem {
let file = get_or_create_file(&mut by_path, &normalized)?;
file.content = content.to_string();
file.last_modified = now();
file.last_modified = file_time_now();
Ok(())
}
@ -215,7 +215,7 @@ impl MemoryFileSystem {
std::collections::hash_map::Entry::Vacant(entry) => {
entry.insert(File {
content: content.to_string(),
last_modified: now(),
last_modified: file_time_now(),
});
}
std::collections::hash_map::Entry::Occupied(mut entry) => {
@ -310,7 +310,7 @@ impl MemoryFileSystem {
let mut by_path = self.inner.by_path.write().unwrap();
let normalized = self.normalize_path(path.as_ref());
get_or_create_file(&mut by_path, &normalized)?.last_modified = now();
get_or_create_file(&mut by_path, &normalized)?.last_modified = file_time_now();
Ok(())
}
@ -486,7 +486,7 @@ fn create_dir_all(
path.push(component);
let entry = paths.entry(path.clone()).or_insert_with(|| {
Entry::Directory(Directory {
last_modified: now(),
last_modified: file_time_now(),
})
});
@ -513,7 +513,7 @@ fn get_or_create_file<'a>(
let entry = paths.entry(normalized.to_path_buf()).or_insert_with(|| {
Entry::File(File {
content: String::new(),
last_modified: now(),
last_modified: file_time_now(),
})
});
@ -695,30 +695,6 @@ enum WalkerState {
Nested { path: SystemPathBuf, depth: usize },
}
#[cfg(not(target_arch = "wasm32"))]
fn now() -> FileTime {
FileTime::now()
}
#[cfg(target_arch = "wasm32")]
fn now() -> FileTime {
// Copied from FileTime::from_system_time()
let time = web_time::SystemTime::now();
time.duration_since(web_time::UNIX_EPOCH)
.map(|d| FileTime::from_unix_time(d.as_secs() as i64, d.subsec_nanos()))
.unwrap_or_else(|e| {
let until_epoch = e.duration();
let (sec_offset, nanos) = if until_epoch.subsec_nanos() == 0 {
(0, 0)
} else {
(-1, 1_000_000_000 - until_epoch.subsec_nanos())
};
FileTime::from_unix_time(-(until_epoch.as_secs() as i64) + sec_offset, nanos)
})
}
#[cfg(test)]
mod tests {
use std::io::ErrorKind;