diff --git a/gix-fs/src/capabilities.rs b/gix-fs/src/capabilities.rs index ec7c4c7a35..f79b07ef5e 100644 --- a/gix-fs/src/capabilities.rs +++ b/gix-fs/src/capabilities.rs @@ -169,3 +169,15 @@ impl Capabilities { res } } + +#[cfg(target_os = "wasi")] +impl Default for Capabilities { + fn default() -> Self { + Capabilities { + precompose_unicode: false, + ignore_case: false, + executable_bit: false, + symlink: true, + } + } +} diff --git a/gix-fs/src/symlink.rs b/gix-fs/src/symlink.rs index 5022332f26..ce8eb2a867 100644 --- a/gix-fs/src/symlink.rs +++ b/gix-fs/src/symlink.rs @@ -3,15 +3,20 @@ use std::{io, io::ErrorKind::AlreadyExists, path::Path}; /// Create a new symlink at `link` which points to `original`. /// /// Note that `original` doesn't have to exist. -#[cfg(not(windows))] +#[cfg(unix)] pub fn create(original: &Path, link: &Path) -> io::Result<()> { std::os::unix::fs::symlink(original, link) } +#[cfg(target_os = "wasi")] +pub fn create(original: &Path, link: &Path) -> io::Result<()> { + std::fs::soft_link(original, link) +} + /// Remove a symlink. /// /// Note that on only on windows this is special. -#[cfg(not(windows))] +#[cfg(any(unix, target_os = "wasi"))] pub fn remove(path: &Path) -> io::Result<()> { std::fs::remove_file(path) } @@ -50,7 +55,7 @@ pub fn create(original: &Path, link: &Path) -> io::Result<()> { /// Return true if `err` indicates that a file collision happened, i.e. a symlink couldn't be created as the `link` /// already exists as filesystem object. -#[cfg(not(windows))] +#[cfg(any(unix, target_os = "wasi"))] pub fn is_collision_error(err: &std::io::Error) -> bool { // TODO: use ::IsDirectory as well when stabilized instead of raw_os_error(), and ::FileSystemLoop respectively err.kind() == AlreadyExists diff --git a/gix-index/src/fs.rs b/gix-index/src/fs.rs index 2be45bb8d7..409a280803 100644 --- a/gix-index/src/fs.rs +++ b/gix-index/src/fs.rs @@ -7,10 +7,10 @@ use std::{path::Path, time::SystemTime}; /// A structure to partially mirror [`std::fs::Metadata`]. -#[cfg(not(windows))] +#[cfg(unix)] pub struct Metadata(rustix::fs::Stat); -#[cfg(windows)] +#[cfg(not(unix))] /// A structure to partially mirror [`std::fs::Metadata`]. pub struct Metadata(std::fs::Metadata); @@ -18,21 +18,21 @@ pub struct Metadata(std::fs::Metadata); impl Metadata { /// Obtain the metadata at `path` without following symlinks. pub fn from_path_no_follow(path: &Path) -> Result { - #[cfg(not(windows))] + #[cfg(unix)] { rustix::fs::lstat(path).map(Metadata).map_err(Into::into) } - #[cfg(windows)] + #[cfg(not(unix))] path.symlink_metadata().map(Metadata) } /// Obtain the metadata at `path` without following symlinks. pub fn from_file(file: &std::fs::File) -> Result { - #[cfg(not(windows))] + #[cfg(unix)] { rustix::fs::fstat(file).map(Metadata).map_err(Into::into) } - #[cfg(windows)] + #[cfg(not(unix))] file.metadata().map(Metadata) } } @@ -42,17 +42,17 @@ impl Metadata { impl Metadata { /// Return true if the metadata belongs to a directory pub fn is_dir(&self) -> bool { - #[cfg(not(windows))] + #[cfg(unix)] { (self.0.st_mode as u32 & libc::S_IFMT as u32) == libc::S_IFDIR as u32 } - #[cfg(windows)] + #[cfg(not(unix))] self.0.is_dir() } /// Return the time at which the underlying file was modified. pub fn modified(&self) -> Option { - #[cfg(not(windows))] + #[cfg(unix)] { #[cfg(not(any(target_os = "aix", target_os = "hurd")))] let seconds = self.0.st_mtime; @@ -70,7 +70,7 @@ impl Metadata { let seconds = seconds as i64; system_time_from_secs_nanos(seconds, nanoseconds.try_into().ok()?) } - #[cfg(windows)] + #[cfg(not(unix))] self.0.modified().ok() } @@ -79,7 +79,7 @@ impl Metadata { /// Note that this differs from [`std::fs::Metadata::created()`] which would return /// the inode birth time, which is notably different to what `git` does. pub fn created(&self) -> Option { - #[cfg(not(windows))] + #[cfg(unix)] { #[cfg(not(any(target_os = "aix", target_os = "hurd")))] let seconds = self.0.st_ctime; @@ -97,93 +97,93 @@ impl Metadata { let seconds = seconds as i64; system_time_from_secs_nanos(seconds, nanoseconds.try_into().ok()?) } - #[cfg(windows)] + #[cfg(not(unix))] self.0.created().ok() } /// Return the size of the file in bytes. pub fn len(&self) -> u64 { - #[cfg(not(windows))] + #[cfg(unix)] { self.0.st_size as u64 } - #[cfg(windows)] + #[cfg(not(unix))] self.0.len() } /// Return the device id on which the file is located, or 0 on windows. pub fn dev(&self) -> u64 { - #[cfg(not(windows))] + #[cfg(unix)] { self.0.st_dev as u64 } - #[cfg(windows)] + #[cfg(not(unix))] 0 } /// Return the inode id tracking the file, or 0 on windows. pub fn ino(&self) -> u64 { - #[cfg(not(windows))] + #[cfg(unix)] { self.0.st_ino as u64 } - #[cfg(windows)] + #[cfg(not(unix))] 0 } /// Return the user-id of the file or 0 on windows. pub fn uid(&self) -> u32 { - #[cfg(not(windows))] + #[cfg(unix)] { self.0.st_uid as u32 } - #[cfg(windows)] + #[cfg(not(unix))] 0 } /// Return the group-id of the file or 0 on windows. pub fn gid(&self) -> u32 { - #[cfg(not(windows))] + #[cfg(unix)] { self.0.st_gid as u32 } - #[cfg(windows)] + #[cfg(not(unix))] 0 } /// Return `true` if the file's executable bit is set, or `false` on windows. pub fn is_executable(&self) -> bool { - #[cfg(not(windows))] + #[cfg(unix)] { (self.0.st_mode as u32 & libc::S_IFMT as u32) == libc::S_IFREG as u32 && self.0.st_mode as u32 & libc::S_IXUSR as u32 == libc::S_IXUSR as u32 } - #[cfg(windows)] + #[cfg(not(unix))] gix_fs::is_executable(&self.0) } /// Return `true` if the file's is a symbolic link. pub fn is_symlink(&self) -> bool { - #[cfg(not(windows))] + #[cfg(unix)] { (self.0.st_mode as u32 & libc::S_IFMT as u32) == libc::S_IFLNK as u32 } - #[cfg(windows)] + #[cfg(not(unix))] self.0.is_symlink() } /// Return `true` if this is a regular file, executable or not. pub fn is_file(&self) -> bool { - #[cfg(not(windows))] + #[cfg(unix)] { (self.0.st_mode as u32 & libc::S_IFMT as u32) == libc::S_IFREG as u32 } - #[cfg(windows)] + #[cfg(not(unix))] self.0.is_file() } } -#[cfg(not(windows))] +#[cfg(unix)] fn system_time_from_secs_nanos(secs: i64, nanos: i32) -> Option { // Copied from https://github.com/rust-lang/rust at a8ece1190bf6b340175bc5b688e52bd29924f483, MIT licensed, and adapted. // On Apple OS, dates before epoch are represented differently than on other diff --git a/gix-path/src/lib.rs b/gix-path/src/lib.rs index 5157e78fec..57088d2aa7 100644 --- a/gix-path/src/lib.rs +++ b/gix-path/src/lib.rs @@ -1,3 +1,4 @@ +#![cfg_attr(target_os = "wasi", feature(wasip2))] //! This crate contains an assortment of utilities to deal with paths and their conversions. //! //! Generally `git` treats paths as bytes, but inherently assumes non-illformed UTF-8 as encoding on windows. Internally, it expects