Five years have passed, time for updates
[symlink] / README.md
index 69c2e6119dffcd7d4793408e1f467c7894b08435..c7a4f8658cd81baa0ef1e1e8897ae79b0dfd57ed 100644 (file)
--- a/README.md
+++ b/README.md
@@ -6,11 +6,13 @@
 Rust’s standard library exposes platform-specific ways to create symlinks:
 
 - On Windows, `std::os::windows::fs::{symlink_file, symlink_dir}` (because Windows does file and directory symlinks differently);
 Rust’s standard library exposes platform-specific ways to create symlinks:
 
 - On Windows, `std::os::windows::fs::{symlink_file, symlink_dir}` (because Windows does file and directory symlinks differently);
-- On Unixy platforms and Redox, `std::os::unix::fs::symlink` (because they don’t care about whether it’s a file or a directory).
+- On Unix platforms, `std::os::unix::fs::symlink` (because they don’t care about whether it’s a file or a directory).
 
 
-The situation is similar when removing symlinks: on Unixy platforms all symlinks are files and must be removed with `std::fs::remove_file`, but on Windows directory symlinks must be removed with `std::fs::remove_dir` instead.
+There’s also `std::fs::soft_link`, deprecated because of the whole Windows situation, but potentially still useful: as I write, at the start of 2022, it’s the only stable way to create a symlink on the wasm32-wasi target (`std::os::wasi::fs::symlink_path` not yet being stable).
 
 
-This is all a pain: as soon as you touch symlinks for Unix you need to add in lots of `#[cfg]` branches and other such messy things, or else lose Windows support for no good reason.
+The situation is similar when removing symlinks: on most platforms all symlinks are files and must be removed with `std::fs::remove_file`, but on Windows directory symlinks must be removed with `std::fs::remove_dir` instead.
+
+This is all a pain: as soon as you touch symlinks for Unix you need to add in lots of `#[cfg]` branches and other such messy things, or else lose Windows support for no good reason, or use a deprecated function that makes directory symlinks not work on Windows.
 
 Enter the `symlink` crate. This crate gives you six cross-platform functions instead:
 
 
 Enter the `symlink` crate. This crate gives you six cross-platform functions instead:
 
@@ -21,11 +23,9 @@ Enter the `symlink` crate. This crate gives you six cross-platform functions ins
 - `remove_symlink_dir`, which removes a directory symlink on Windows and a perfectly ordinary symlink on other platforms;
 - `remove_symlink_auto`, which removes a file or directory symlink on Windows, depending on an examination of the path, and a perfectly ordinary symlink on other platforms.
 
 - `remove_symlink_dir`, which removes a directory symlink on Windows and a perfectly ordinary symlink on other platforms;
 - `remove_symlink_auto`, which removes a file or directory symlink on Windows, depending on an examination of the path, and a perfectly ordinary symlink on other platforms.
 
-“What about `std::fs::soft_link`?” I hear you say. Yeah, that one got deprecated in Rust 1.1.0 because it didn’t do anything clever on Windows, it just created a file symlink, which is often wrong. `symlink_auto` creates a file *or* directory symlink, depending on what the target is. (Unlike `symlink_file` and `symlink_dir`, it returns an error if the destination doesn’t exist or can’t be statted.)
-
-And there’s no good way to delete a symlink at all.
+Back on the topic of `std::fs::soft_link`: it got deprecated in Rust 1.1.0 because it just created a file symlink on Windows, which is often wrong. `symlink_auto` creates a file *or* directory symlink, depending on what the target is. (But it’s also more fragile: unlike `symlink_file` and `symlink_dir`, it returns an error if the destination doesn’t exist or can’t be statted.)
 
 
-So that’s why this crate exists.
+And before this crate there was no good way to delete a symlink at all on Windows. Who knows, perhaps windows_file_type_ext will be stabilised eventually. But until then, there’s this crate.
 
 ## Best practices
 
 
 ## Best practices
 
@@ -33,11 +33,11 @@ You should generally avoid `symlink_auto` and `remove_symlink_auto`, preferring
 
 **Make sure you use absolute paths for the destination.** I haven’t tested whether relative paths are treated consistently across platforms yet (whether they’re relative to the working directory or the symlink source path). TODO!
 
 
 **Make sure you use absolute paths for the destination.** I haven’t tested whether relative paths are treated consistently across platforms yet (whether they’re relative to the working directory or the symlink source path). TODO!
 
-## Caution: this isn’t as useful as it looks
+## Caution: symlinks are still less reliable on Windows
 
 
-So now you can create or delete symlinks, right? Not so fast. Although Windows supports symlinks from Windows Vista onwards, it was viewed as a security or compatibility or something risk, and so prior to the Windows 10 Creators Update (due by mid-2017; currently available through the Windows Insider Program) it requires a special privilege, which basically means you’ve got to run a program as admin for it to be allowed to manipulate symlinks.
+You can only reliably use symlinks from the Windows 10 Creators Update (mid-2017) onwards.
 
 
-Also [Rust PR #38921](https://github.com/rust-lang/rust/pull/38921) needs to land before unprivileged symlink creation will work on the Windows 10 Creators Update. So we’re talking Rust 1.16 as the earliest.
+Before that, manipulating symlinks required a special privilege which practically meant you had to run a program as admin to get it to work. And symlinks were new to Vista; XP and older didn’t support them.
 
 ## My goal: integration with Rust
 
 
 ## My goal: integration with Rust
 
@@ -61,20 +61,30 @@ Note that despite the suggestions matching certain approaches for `symlink_auto`
 
 **Concerning `remove_*`**: I guess what’s done with the other three functions will guide what’s done with these three.
 
 
 **Concerning `remove_*`**: I guess what’s done with the other three functions will guide what’s done with these three.
 
-## Usage
-
-Cargo all the way: it’s the [`symlink` crate on crates.io](http://crates.io/crates/symlink).
-
 ## Unsafe code in this library
 
 ## Unsafe code in this library
 
-On Windows only there is some unavoidable unsafe code in `remove_symlink_auto` to determine whether a symlink is a file symlink or a directory symlink, because this detail is not exposed in the standard library.
+On Windows only there is some unavoidable unsafe code in `remove_symlink_auto` to determine whether a symlink is a file symlink or a directory symlink, because this detail is not exposed in a stable function in the standard library.
 
 ## Author
 
 
 ## Author
 
-[Chris Morgan](http://chrismorgan.info/) ([chris-morgan](https://gitlab.com/chris-morgan)) is the primary author and maintainer of this library.
+[Chris Morgan](https://chrismorgan.info/) is the author and maintainer of this library.
 
 ## License
 
 
 ## License
 
-This library is distributed under similar terms to Rust: dual licensed under the MIT license and the Apache license (version 2.0).
+Copyright © 2017–2022 Chris Morgan
+
+This project is distributed under the terms of three different licenses,
+at your choice:
+
+- Blue Oak Model License 1.0.0: https://blueoakcouncil.org/license/1.0.0
+- MIT License: https://opensource.org/licenses/MIT
+- Apache License, Version 2.0: https://www.apache.org/licenses/LICENSE-2.0
+
+If you do not have particular cause to select the MIT or the Apache-2.0
+license, Chris Morgan recommends that you select BlueOak-1.0.0, which is
+better and simpler than both MIT and Apache-2.0, which are only offered
+due to their greater recognition and their conventional use in the Rust
+ecosystem. (BlueOak-1.0.0 was only published in March 2019.)
 
 
-See LICENSE-APACHE, LICENSE-MIT, and COPYRIGHT for details.
+When using this code, ensure you comply with the terms of at least one of
+these licenses.