Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions gix-fs/src/capabilities.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}
}
}
11 changes: 8 additions & 3 deletions gix-fs/src/symlink.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand Down Expand Up @@ -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
Expand Down
58 changes: 29 additions & 29 deletions gix-index/src/fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,32 +7,32 @@
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);

/// Lifecycle
impl Metadata {
/// Obtain the metadata at `path` without following symlinks.
pub fn from_path_no_follow(path: &Path) -> Result<Self, std::io::Error> {
#[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<Self, std::io::Error> {
#[cfg(not(windows))]
#[cfg(unix)]
{
rustix::fs::fstat(file).map(Metadata).map_err(Into::into)
}
#[cfg(windows)]
#[cfg(not(unix))]
file.metadata().map(Metadata)
}
}
Expand All @@ -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<SystemTime> {
#[cfg(not(windows))]
#[cfg(unix)]
{
#[cfg(not(any(target_os = "aix", target_os = "hurd")))]
let seconds = self.0.st_mtime;
Expand All @@ -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()
}

Expand All @@ -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<SystemTime> {
#[cfg(not(windows))]
#[cfg(unix)]
{
#[cfg(not(any(target_os = "aix", target_os = "hurd")))]
let seconds = self.0.st_ctime;
Expand All @@ -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<SystemTime> {
// 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
Expand Down
1 change: 1 addition & 0 deletions gix-path/src/lib.rs
Original file line number Diff line number Diff line change
@@ -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
Expand Down
Loading