X-Git-Url: https://git.chrismorgan.info/symlink/blobdiff_plain/f9fef0c05d2594bcfa763810046a473403d1cb53..dcc8849be3e8599c398361a487d22829307bef14:/src/lib.rs diff --git a/src/lib.rs b/src/lib.rs index a03d15b..6019c1f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,9 +1,12 @@ //! A small, cross-platform crate for creating symlinks. //! -#![cfg_attr(not(any(target_os = "redox", unix, windows)), doc = "**This platform is not Unix, Windows or Redox; symlinks are not available.**")] -//! -//! For efficiency, you should prefer to use `symlink_file` or `symlink_dir`—whichever is -//! appropriate—rather than `symlink_auto` +//! For efficiency, you should prefer to use [`symlink_file`] or [`symlink_dir`]—whichever is +//! appropriate—rather than [`symlink_auto`]. + +// Building docs produces rustdoc::broken_intra_doc_links warnings on std::os::{windows, unix}, +// depending on your platform. This is unfortunate because I then can’t RUSTDOCFLAGS="-D warnings" +// unless I suppress those, but suppressing those ones alone is messy, and suppressing all harmful, +// so I’m just leaving it at spurious square brackets being left in the output. // It’s generally nicer to produce an empty crate on unsupported platforms than to explode. @@ -15,17 +18,31 @@ use std::path::Path; #[path = "windows/mod.rs"] mod internal; -#[cfg(any(target_os = "redox", unix))] +#[cfg(not(windows))] mod internal { pub use std::fs::remove_file as remove_symlink_dir; pub use std::fs::remove_file as remove_symlink_auto; - // Note that this symlink function takes src and dst as &Path rather than as impl AsRef. - // I don’t know why that is, but I think we’ll go with impl AsRef in our public - // functions. Because of this disparity of signature, when I say that things are equivalent to - // calling std::os::unix::fs::symlink on Unix, you can see that I’m not being *quite* rigorous. + // Look, frankly, std::fs::soft_link and std::os::unix::fs::symlink call the same function, + // so this probably whole separate mod probably isn’t even warranted. + // But deprecated blah blah blah so I decided to use the std::os one anyway. + #[cfg(unix)] pub use std::os::unix::fs::{symlink as symlink_auto, symlink as symlink_file, symlink as symlink_dir}; + #[cfg(not(unix))] + // The compiler claims that std::fs::soft_link has been “replaced with + // std::os::unix::fs::symlink and std::os::windows::fs::{symlink_file, symlink_dir}” + // (rustc nightly 2021-12-26 deprecation warning message), but although that was true enough + // when it was deprecated, it’s no longer quite true because of the wasm32-wasi target, which + // supports symlinks through std::fs::soft_link but has no stable alternative (as I write, + // std::os::wasi::fs::symlink_path is behind feature(wasi_ext)). Frankly, I think that’s a fair + // (though imperfect) reason to *undeprecate* soft_link. Who knows what other platforms may in + // the future stop returning std::io::ErrorKind::Unsupported errors and start supporting + // std::fs::soft_link? (And for clarity, I note that no others do at the time of writing.) + #[allow(deprecated)] + pub use std::fs::{soft_link as symlink_auto, + soft_link as symlink_file, + soft_link as symlink_dir}; } /// Create a symlink (non-preferred way). @@ -35,21 +52,19 @@ mod internal { /// type of symlink based on that result. Therefore, if the destination does not exist or if you do /// not have permission to fetch its metadata, this will return an error on Windows. /// -/// On Unix platforms there is no distinction, so this isn’t magic: it’s precisely equivalent to -/// calling `std::os::unix::fs::symlink`. +/// On other platforms there is no distinction, so this isn’t magic: it’s precisely equivalent to +/// calling [`std::os::unix::fs::symlink`] or [`std::fs::soft_link`]. /// /// # A note on using this function /// /// Because this is slightly less efficient and more hazardous on Windows, you should prefer to use -/// [`symlink_file`](fn.symlink_file.html) or [`symlink_dir`](fn.symlink_dir.html) instead. Only -/// use this if you don’t know or care whether the destination is a file or a directory (but even -/// then, you do need to know that it exists). +/// [`symlink_file`] or [`symlink_dir`] instead. Only use this if you don’t know or care whether +/// the destination is a file or a directory (but even then, you do need to know that it exists). /// /// # Errors /// /// An error will be returned if the symlink cannot be created, or—on Windows—if the destination /// does not exist or cannot be read. -#[cfg(any(target_os = "redox", unix, windows))] #[inline] pub fn symlink_auto, Q: AsRef>(src: P, dst: Q) -> io::Result<()> { internal::symlink_auto(src.as_ref(), dst.as_ref()) @@ -57,17 +72,19 @@ pub fn symlink_auto, Q: AsRef>(src: P, dst: Q) -> io::Resul /// Create a symlink to a file. /// -/// On Windows, this is equivalent to `std::os::windows::fs::symlink_file`. If you call it with a -/// directory as the destination, TODO CONSEQUENCES. +/// On Windows, this is equivalent to [`std::os::windows::fs::symlink_file`]. If you call it with a +/// directory as the destination, [something may happen; you never know what][fow]. /// -/// On Unix, this is equivalent to `std::os::unix::fs::symlink`. If you call it with a directory as -/// the destination, nothing bad will happen, but you’re ruining your cross-platform technique and -/// ruining the point of this crate, so please don’t. +/// On Unix, this is equivalent to [`std::os::unix::fs::symlink`], and on other platforms it’s +/// equivalent to [`std::fs::soft_link`]. If you call it with a directory as the destination, +/// nothing bad will happen, but you’re ruining your cross-platform technique and ruining the point +/// of this crate, so please don’t. /// /// # Errors /// /// An error will be returned if the symlink cannot be created. -#[cfg(any(target_os = "redox", unix, windows))] +/// +/// [fow]: https://en.wikipedia.org/wiki/A_Fish_Out_of_Water_(book) #[inline] pub fn symlink_file, Q: AsRef>(src: P, dst: Q) -> io::Result<()> { internal::symlink_file(src.as_ref(), dst.as_ref()) @@ -75,17 +92,19 @@ pub fn symlink_file, Q: AsRef>(src: P, dst: Q) -> io::Resul /// Create a symlink to a directory. /// -/// On Windows, this is equivalent to `std::os::windows::fs::symlink_dir`. If you call it with a -/// directory as the destination, TODO CONSEQUENCES. +/// On Windows, this is equivalent to [`std::os::windows::fs::symlink_dir`]. If you call it with a +/// directory as the destination, [something may happen; you never know what][fow]. /// -/// On Unix, this is equivalent to `std::os::unix::fs::symlink`. If you call it with a directory as -/// the destination, nothing bad will happen, but you’re ruining your cross-platform technique and -/// ruining the point of this crate, so please don’t. +/// On Unix, this is equivalent to [`std::os::unix::fs::symlink`], and on other platforms it’s +/// equivalent to [`std::fs::soft_link`]. If you call it with a directory as the destination, +/// nothing bad will happen, but you’re ruining your cross-platform technique and ruining the point +/// of this crate, so please don’t. /// /// # Errors /// /// An error will be returned if the symlink cannot be created. -#[cfg(any(target_os = "redox", unix, windows))] +/// +/// [fow]: https://en.wikipedia.org/wiki/A_Fish_Out_of_Water_(book) #[inline] pub fn symlink_dir, Q: AsRef>(src: P, dst: Q) -> io::Result<()> { internal::symlink_dir(src.as_ref(), dst.as_ref()) @@ -99,15 +118,13 @@ pub fn symlink_dir, Q: AsRef>(src: P, dst: Q) -> io::Result /// # A note on using this function /// /// Because this is slightly less efficient on Windows, you should prefer to use -/// [`remove_symlink_file`](fn.remove_symlink_file.html) or -/// [`remove_symlink_dir`](fn.remove_symlink_dir.html) instead. Only use this if you don’t know or +/// [`remove_symlink_file`] or [`remove_symlink_dir`] instead. Only use this if you don’t know or /// care whether the destination is a file or a directory (but even then, you do need to know that /// it exists). /// /// # Errors /// /// An error will be returned if the symlink cannot be removed. -#[cfg(any(target_os = "redox", unix, windows))] #[inline] pub fn remove_symlink_auto>(path: P) -> io::Result<()> { internal::remove_symlink_auto(path) @@ -115,10 +132,9 @@ pub fn remove_symlink_auto>(path: P) -> io::Result<()> { /// Remove a directory symlink. /// -/// On Windows, this corresponds to `std::fs::remove_dir`. +/// On Windows, this corresponds to [`std::fs::remove_dir`]. /// -/// On Unix, this corresponds to `std::fs::remove_file`. -#[cfg(any(target_os = "redox", unix, windows))] +/// On Unix, this corresponds to [`std::fs::remove_file`]. #[inline] pub fn remove_symlink_dir>(path: P) -> io::Result<()> { internal::remove_symlink_dir(path) @@ -126,11 +142,8 @@ pub fn remove_symlink_dir>(path: P) -> io::Result<()> { /// Remove a file symlink. /// -/// This just calls `std::fs::remove_file`, but the function is provided here to correspond to -/// `remove_symlink_dir`. -/// -/// On Unix, this corresponds to `std::fs::remove_file`. -#[cfg(any(target_os = "redox", unix, windows))] +/// This just calls [`std::fs::remove_file`], but the function is provided here to correspond to +/// [`remove_symlink_dir`]. #[inline] pub fn remove_symlink_file>(path: P) -> io::Result<()> { fs::remove_file(path)