Most notably:
- Unlike MSYS, Cygwin seems to always properly handle symlinks (at least
in common scenarios)
- With ACL, "x" permission also requires "r" do to anything, be it files
or directories
Closes#12642
Intermittent test failure suggests that kill(3p) returns before the
signal is delivered. Fix the failure by waiting until the signal
has been delivered before continuing the test.
Fixes#12635
Commit a4b6348315 (clippy: fix collapsible_match lint, 2026-04-18) made
it so '$' characters are handled here, which contradicts the comment.
Remove it.
This flag is implied by matches that require replacements. Reflect that
in the Completion::new, reducing the number of places where we raise the
flag. This slightly simplifies tasks like proving the parent commit.
There are other scenarios (e.g. wildcards) where we currently set
the flag additionally.
Commit 3546ffa3ef (reader handle_completions(): remove dead filtering code,
2026-01-02) gives a proof of correctness that still makes sense;
The first lemma ("if will_replace_token") is trivially true, so no need to
assert it.
The second lemma ("if !will_replace_token") is violated in some edge cases:
we claim that given a token "-c", the option completion "--clip" is an exact match,
which is not true, it's a substring match.
Fix that, asserting the claim.
If we get to this code path, we'll only get completions for user
names, so technically the full StringFuzzyMatch with its ranking of
samecase/smartcase/icase (only showing the best) might be overkill,
but it seems like a good idea to treat this the same way as other
completions.
The occasion for this commit is to correct a wrong
StringFuzzyMatch::exact_match() in the icase branch; which will be
important for a following commit. Add a test for that.
This is not a functional change, since the variable names don't have
spaces, but it is more robust to changes and removes ShellCheck warnings
Part of #12636
When `system_tests` is called without arguments, `[ -n "$@" ]` becomes
`[ -n ]`, which is true, resulting in running `export`, which lists all
exported variables, unnecessarily cluttering the output.
If `system_tests` is called with more than one argument, the check would
fail because having more than one argument after `-n` is invalid syntax.
Fix this by using `$*`, which concatenates all positional arguments to
`system_tests` into a single value.
Part of #12636
If a directory has a control sequence in it, then prompt_pwd (used in
the default prompt) would emit it to the console, which could cause
the terminal to interpret the escape sequence.
Strip control sequences from within prompt_pwd, in the same way as
we do in __fish_paste.fish, to sanitize it.
Closes#12629
The main changes are:
- disabling some checks related to POSIX file permissions when a filesystem is
mounted with "noacl" (default on MSYS2)
- disabling some checks related to symlinks when using fake ones (file copy)
Windows with acl hasn't been tested because 1) Cygwin itself does not have any
Rust package yet to compile fish, and 2) MSYS2 defaults to `noacl`
Part of #12171
- Use the different strings for different checks to more easily narrow down
where a failure happens
- Move CHECK comments outside a `if...else...end` to avoid giving the impression
that the check only runs in the `if` case.
Part of #12171
Previously, SIGTERM immediately re-raised with SIG_DFL, killing
fish without saving history. SIGHUP deferred via a flag but never
re-raised, so the parent saw a normal exit instead of signal death.
Unify both signals: the handler stores the signal number in a single
AtomicI32, the reader loop exits normally, throwing_main() saves
history and re-raises with SIG_DFL so the parent sees WIFSIGNALED.
Fixes#10300Closes#12615
Move the functions for escaping and unescaping strings from
`src/common.rs` into `fish_common`. It might make sense to move them
into a dedicated crate at some point, but for now just move them to the
preexisting crate to unblock other extraction.
Closes#12625
This time, move char constants from `src/expand.rs` to
`fish_widestring`, which resolves a dependency cycle between
`src/expand.rs` and `src/common.rs`.
Part of #12625
The decoding functions for our widestrings are already in the
`fish_widestring` crate, so by symmetry, it makes sense to put the
encoding functions there as well. This also makes it easier to depend on
these functions, giving more options when it comes to further code
extraction.
Part of #12625
Use `fish_widestring` as the place where char definitions live. This has
the advantage that all our code can depend on `fish_widestring` without
introducing dependency cycles. Having a common place for character
definitions also makes it easier to see which chars have a special
meaning assigned to them.
This change also unblocks some follow-up refactoring by removing a
dependency cycle between `src/common.rs` and `src/wildcard.rs`.
Part of #12625
These functions don't depend on `wcstringutil` functionality, so there
is no need for them to be there. The advantage of putting them into our
`widestring` crate is that quite a lot of code depends on it, and
extracting some of that code would result in crate dependency cycles if
the functions stayed in the `wcstringutil` crate. Our `widestring` crate
does not depend on any of our other crates, so there won't be any cyclic
dependency issues with code in it.
Part of #12625
It makes a lot more sense to have this function in the same module as
the other escaping functions. There was no usage of this function in
`parse_util` except for the test, so it makes little sense to keep the
function there. Moving it also eliminates a pointless cyclic dependency
between `common` and `parse_util`.
Part of #12625
Exporting it as both `safe_write_loop` and `write_loop` is redundant and
causes inconsistencies. Remove the `pub use` and use `write_loop` for
the function name. It is shorter, and in Rust the default assumption is
that code is safe unless otherwise indicated, so there is no need to be
explicit about it.
Part of #12625
Not reexporting means that imports have to change to directly import
from `fish_common`. This makes it easier to see which dependencies on
`src/common.rs` actually remain, which helps with identifying candidates
for extraction.
While at it, group some imports.
Part of #12625