We rarely attach trait methods to stdlib types so this warning is unlikely to
be a true positive It is a false positive for the methods defined in future.rs.
It's not always obvious which method is selected when it's available in the
stdlib but I haven't seen a build failure yet. So let's disable the warning.
In future we might be able suppress it per method, see Rust issue 48919.
We often want to format and print a string to a fd, usually stdout/stderr.
In general we can't use "format!", "print!", "eprint!" etc. because they don't
know about our use of WString where we encode of invalid Unicode characters
in the private use area.
Instead we use "wwrite_to_fd()".
Since we unfortunately don't have a "wformat!()" yet, we use "sprintf!()"
to create a formatted wstring to pass to "wwrite_to_fd()".
Add "printf!" and "eprintf!" to stand in for "print!" and "eprint!".
For printing to files other than stdout and stderr, keep "fwprintf!" but
drop the "w" since our "sprintf!" always produces wide strings.
Replace "fputws" with "fprintf" though we could also use "wwrite_to_fd"
if performance matters.
Unlike std::io::stdout(), we don't use locking yet.
Remaining work:
- There are more places where we use \be?print(ln)?!
Usually we print strings that are guaranteed to be valid UTF-8, but not
always. We should probably make all of them respect our WString semantics
but preferrably keep using the native Rust format strings (#9948).
- I think flog.rs currently uses String so it won't handle invalid Unicode
characters. We should probably fix this as well.
These compile checks are expected to produce compiler errors on some systems.
The errors show up when there is an unrelated error, this is probably quite
confusing so fix that. Should revisit this later.
Like FLOGF!, this now needs at least one argument to format.
This avoids some issues with missing variables and broken format
strings - it is how I found 13ba5bd405 -
where disown had a format string, with two placeholders, but no
arguments to fill them with.
For use in e.g. macros, where it's otherwise hard to tell if we have
something to format or not, this adds a wgettext_maybe_fmt! version to
"maybe" format, if necessary.
In LastC++11, an empty history item means we either reached the end of history,
or the item is actually empty. The second meaning is still true. We never
append empty history items but the history file might have been modified.
Fixes#10129
Recall that universal notifiers are used to report changes to universal
variables to other shell instances. This adds a new strategy based on using
inotify to directly monitor the universal variables
file.
We have tried this in the past and abandoned it because it doesn't properly
work on some CI systems - let's try again.
This
1. Skips access() if we only have "special" permissions like the owner
that need stat
2. Does the geteuid()/getegid() *once* outside of filter_path, if we
need it
In the extreme case of `path filter --perm user,group` it will remove
3 syscalls per file.
Drop support for history file version 1.
ParseExecutionContext no longer contains an OperationContext because in my
first implementation, ParseExecutionContext didn't have interior mutability.
We should probably try to add it back.
Add a few to-do style comments. Search for "todo!" and "PORTING".
Co-authored-by: Xiretza <xiretza@xiretza.xyz>
(complete, wildcard, expand, history, history/file)
Co-authored-by: Henrik Hørlück Berg <36937807+henrikhorluck@users.noreply.github.com>
(builtins/set)
This reduces noise in the upcoming "Port execution" commit.
I accidentally made IoStreams a "class" instead of a "struct". Would be
easy to correct that but this will be deleted soon, so I don't think we care.
* wildcard: Remove file size from the description
We no longer add descriptions for normal file completions, so this was
only ever reached if this was a command completion, and then it was
only added if the file wasn't a regular file... in which case it can't
be an executable.
So this was dead.
* Make possible_link() a maybe
This gives us the full information, not just "no" or "maybe"
* wildcard: Rationalize file/command completions
This keeps the entry_t as long as possible, and asks it, so especially
on systems with working d_type we can get by without a single stat in
most cases.
Then it guts file_get_desc, because that is only used for command
completions - we have been disabling file descriptions for *years*,
and so this is never called there.
That means we have no need to print descriptions about e.g. broken symlinks, because those are not executable.
Put together, what this means is that we, in most cases, only do
an *access(2)* call instead of a stat, because that might be checking
more permissions.
So we have the following constellations:
- If we have d_type:
- We need a stat() for every _symlink_ to get the type (e.g. dir or regular)
(this is for most symlinks, if we want to know if it's a dir or executable)
- We need an access() for every file for executables
- If we do not have d_type:
- We need a stat() for every file
- We need an lstat() for every file if we do descriptions
(i.e. just for command completion)
- We need an access() for every file for executables
As opposed to the current way, where every file gets one lstat whether
with d_type or not, and an additional stat() for links, *and* an
access.
So we go from two syscalls to one for executables.
* Some more comments
* rust link option
* rust remove size
* rust accessovaganza
* Check for .dll first for WSL
This saves quite a few checks if e.g. System32 is in $PATH (which it
is if you inherit windows paths, IIRC).
Note: Our WSL check currently fails for WSL2, where this would
be *more* important because of how abysmal the filesystem performance
on that is.
This is off by one from the C++ version.
It wasn't super obvious why this worked in the first place.
Looks like args[0] is "-" because we are invoked like
fish -c 'exec "${@}"' - "${@}"
and it looks like "-" is treated like "--" by bash, so we emulate that.
See https://github.com/fish-shell/fish-shell/issues/367#issuecomment-11740812
This function only ever returns true if target_os=linux, so we need to invert
the OS check.
In the first invocation, this function may allocate heap memory.
Clarify that this is safe.
[ja: I don't have the original commit handy so I made up the log message]
The following "Port execution" commit will use RefCell for the wait handle
store. If we hold a borrow while we are running an event (which may run
script code) there will be a borrowing conflict. Avoid this by returning
the borrow earlier.
This makes it so expand_intermediate_segment knows about the case
where it's last, only followed by a "/".
When it is, it can do without the file_id for finding links (we don't
resolve the files we get here), which allows us to remove a stat()
call.
This speeds up the case of `...*/` by quite a bit.
If that last component was a directory with 1000 subdirectories we
could skip 1000 stat calls!
One slight weirdness: We refuse to add links to directories that we already visited, even if they are the last component and we don't actually follow them. That means we can't do the fast path here either, but we do know if something is a link (if we get d_type), so it still works in common cases.
This fixes the following deadlock. The C++ functions path_get_config and
path_get_data lazily determine paths and then cache those in a C++ static
variable. The path determination requires inspecting the environment stack.
If these functions are first called while the environment stack is locked
(in this case, when fetching the $history variable) we can get a deadlock.
The fix is to call them eagerly during env_init. This can be removed once
the corresponding C++ functions are removed.
This issue caused fish_config to fail to report colors and themes.
Add a test.
Unlike our C++ tests, our Rust tests fail as soon as an assertion fails.
Whether this is desired is debatable; it seems fine for
most cases and is easier to implement.
This means that Rust tests usually don't need to print anything besides
what assert!/assert_eq! already provide.
One exception is the history merge test. Let's add a simple err!() macro to
support this. Unlike the C++ err() it does not yet print colors.
Currently all of our macros live in common.rs, to keep the import graph simple.
Notably this exposes config.h to Rust (for UVAR_FILE_SET_MTIME_HACK).
In future we should move the CMake checks into build.rs so we can potentially
get rid of CMake.
On the following "Port execution" commit, ASan will complain if we read
beyond a terminating null byte in get_autosuggestion_performer(). This is
actually working as intended but we need to appease ASan somehow..
get_pwd_slash() uses "if var.is_empty()" but it should be "if !var.is_empty()".
This wasn't a problem so far because in practice most code paths use the
get_pwd_slash() override from EnvStackImpl. The generic one is used in the
upcoming unit tests.
This adopts the Rust postfork code, bridging it from C++ exec module.
We use direct function calls for the bridge, rather than cxx/autocxx, so that we
can be sure that no memory allocations or other shenanigans are happening.
This implements the "postfork" code in Rust, including calling fork(),
exec(), and all the bits that have to happen in between. postfork lives
in the fork_exec module.
It is not yet adopted.
This introduces a new module called fork_exec, which will be for posix_spawn,
postfork, and flog_safe - stuff concerned with actually executing binaries,
and error reporting.
Add a FLOG_SAFE! macro which writes errors to the flog fd in an
async-signal-safe way. This implementation differs from the C++ in that we
allow printing integers directly - no requiring them to be converted to a
buffer first.
This makes it so
```fish
if -e foo
# do something
end
```
complains about `-e` not being a command instead of `end` being used
outside of an if-block.
That means both that `-e` could now be used as a command name (it
already can outside of `if`!) *and* that we get a better error!
The only way to get `if` to be a decorated statement now is to use `if
-h` or `if --help` specifically (with a literal option).
The same goes for switch, while and begin.
It would be possible, alternatively, to disallow `if -e` and point
towards using `test` instead, but the "unknown command" message should
already point towards using `test` more than pointing at the
"end" (that might be quite far away).