We want all Rust and Python files formatted, and making formatting
behavior dependent on the directory `style.fish` is called from can be
counter-intuitive, especially since `check.sh`, which also calls
`style.fish` is otherwise written in a way that allows calling it from
arbitrary working directories and getting the same results.
Closes#11925
Ruff's default format is very similar to black's, so there are only a
few changes made to our Python code. They are all contained in this
commit. The primary benefit of this change is that ruff's performance is
about an order of magnitude better, reducing runtime on this repo down
to under 20ms on my machine, compared to over 150ms with black, and even
more if any changes are performed by black.
Closes#11894Closes#11918
Some versions of `/bin/sh`, e.g. the one on FreeBSD, do not propagate
variables set on a command through shell functions. This results in
`FISH_GETTEXT_EXTRACTION_FILE` being set in the `cargo` function, but
not for the actual `cargo` process spawned from the function, which
breaks our localization scripts and tests. Exporting the variable
prevents that.
Fixes#11896Closes#11899
The root cause was that FISH_CHECK_LINT was not set. By
default, check.sh should fail if any tool is not installed, see
59b43986e9 (build_tools/style.fish: fail if formatters are not
available, 2025-07-24); like it does for rustfmt and clippy.
This reverts commit fbfd29d6d2.
See #11884
As with `msgmerge`, this introduces unwanted empty comment lines above
`#, c-format`
lines. We don't need this strict formatting, so we get rid of the flag
and the associated empty comment lines.
Closes#11863
Default features are not needed for message extraction, so there is no
need to spend any resources on them.
If a PO files contains a syntax error, extraction would fail if the
`localize-messages` feature is active. This is undesirable, because it
results in an unnecessary failure with worse error messages than if the
`msgmerge` invocation of the `update_translations.fish` script fails.
Closes#11849
I'm not sure if our peer projects do this or if it's useful to have
on top of github releases (especially as most releases are patch
releases mainly).
We could certainly use "sphinx-build -b text" in
build_tools/release-notes.sh to extract a nice plaintext changelog
and send that, but that doesn't support links. Not sure about HTML
email either.
Use msgids to mark sections. In the PO format, comments are associated
with specific messages, which does not match the semantics for section
markers.
Furthermore, comments are not preserved by `msgmerge`, which required
quite convoluted handling to copy them over from the template.
By using msgids to mark sections, this problem is avoided.
This convoluted handling was also used for header comments. Header
comments are now handled in a simpler way. There is a fixed prefix,
identifying these comments, as well as a list variable containing the
lines which should be put into the header. When a PO file is generated,
all existing lines starting with the prefix are deleted, the and the
current version of the lines is prepended to the file.
Closes#11845
Integration_4.1.1 fails to generate release notes with
CHANGELOG.rst:9: WARNING: Bullet list ends without a blank
line; unexpected unindent. [docutils].
Since 205d80c75a (findrust: Simplify (#11328), 2025-03-30), we need
to set Rust_COMPILER and Rust_CARGO instead of Rust_TOOLCHAIN (which
is no longer used). Adjust macOS builds accordingly.
When I set only one of the two, the error messages were pretty
unintelligible. But I guess few normal users need to override the
Rust version, and they can always look here.
While at it, enable localization. AFAIK, the only reason why we didn't
do this on macOS were problems related to the gettext shared library /
dependency. We no longer need that, and it's already tested in CI.
Instead of adding these to the Markdown directly, add it to the
fake CHANGELOG.rst source, which makes escaping easier, and allows
generating other formats than Markdown in future.
GitHub-flavored Markdown translates line breaks to <br/>, which does
not match our intent. Work around that by joining lines when producing
Markdown output.
System tests typically run outside the workspace directory, but they
still have read-only access to the workspace; fix it accordingly.
This test only works on git checkouts, not in tarballs, so skip it
if .git doesn't exist.
Instead of having sphinx-build only build CHANGELOG.rst, build the
entire thing, so relative references (":doc:", ":ref:") can be resolved
properly. Replace our sed-based hacks with 'markdown_http_base'.
Release automation can be tested on any GitHub fork, using
build_tools/release.sh $version $repository_owner $git_remote
which should work perfectly except for macOS packages (which fail
unless provided GitHub secrets).
People might push tags to their forks, both non-release tags (which
would trigger an early failure in "is-release-tag") or replicas of
our actual release tags (which would create a draft release etc. and
only fail when building macOS packages).
Run on explicit workflow dispatch to make sure it's not triggered by
accident like that.
This means that we'll use the .github/workflows/release.yml from
the default branch (i.e. master), so try to make sure it matches the
version in the release, to prevent accidents.
Closes#11816
This completely removes our runtime dependency on gettext. As a
replacement, we have our own code for runtime localization in
`src/wutil/gettext.rs`. It considers the relevant locale variables to
decide which message catalogs to take localizations from. The use of
locale variables is mostly the same as in gettext, with the notable
exception that we do not support "default dialects". If `LANGUAGE=ll` is
set and we don't have a `ll` catalog but a `ll_CC` catalog, we will use
the catalog with the country code suffix. If multiple such catalogs
exist, we use an arbitrary one. (At the moment we have at most one
catalog per language, so this is not particularly relevant.)
By using an `EnvStack` to pass variables to gettext at runtime, we now
respect locale variables which are not exported.
For early output, we don't have an `EnvStack` to pass, so we add an
initialization function which constructs an `EnvStack` containing the
relevant locale variables from the corresponding Environment variables.
Treat `LANGUAGE` as path variable. This add automatic colon-splitting.
The sourcing of catalogs is completely reworked. Instead of looking for
MO files at runtime, we create catalogs as Rust maps at build time, by
converting PO files into MO data, which is not stored, but immediately
parsed to extract the mappings. From the mappings, we create Rust source
code as a build artifact, which is then macro-included in the crate's
library, i.e. `crates/gettext-maps/src/lib.rs`. The code in
`src/wutil/gettext.rs` includes the message catalogs from this library,
resulting in the message catalogs being built into the executable.
The `localize-messages` feature can now be used to control whether to
build with gettext support. By default, it is enabled. If `msgfmt` is
not available at build time, and `gettext` is enabled, a warning will be
emitted and fish is built with gettext support, but without any message
catalogs, so localization will not work then.
As a performance optimization, for each language we cache a separate
Rust source file containing its catalog as a map. This allows us to
reuse parsing results if the corresponding PO files have not changed
since we cached the parsing result.
Note that this approach does not eliminate our build-time dependency on
gettext. The process for generating PO files (which uses `msguniq` and
`msgmerge`) is unchanged, and we still need `msgfmt` to translate from
PO to MO. We could parse PO files directly, but these are significantly
more complex to parse, so we use `msgfmt` to do it for us and parse the
resulting MO data.
Advantages of the new approach:
- We have no runtime dependency on gettext anymore.
- The implementation has the same behavior everywhere.
- Our implementation is significantly simpler than GNU gettext.
- We can have localization in cargo-only builds by embedding
localizations into the code.
Previously, localization in such builds could only work reliably as
long as the binary was not moved from the build directory.
- We no longer have to take care of building and installing MO files in
build systems; everything we need for localization to work happens
automatically when building fish.
- Reduced overhead when disabling localization, both in compilation time
and binary size.
Disadvantages of this approach:
- Our own runtime implementation of gettext needs to be maintained.
- The implementation has a more limited feature set (but I don't think
it lacks any features which have been in use by fish).
Part of #11726Closes#11583Closes#11725Closes#11683
I'd like to move to a process where everything goes into master first,
and then flows downstream to any release branches (i.e. no merging
of Integration_* branches back into master).
The only thing we need to change for that is to add release notes for
patch releases eagerly on master. That implies that we want to use
the actual version instead of ???. (Only if something goes wrong
in the release process, we need to change this on both branches,
but that should happen too often.)
That configuration is already tested, but not clippy-checked yet.
This sometimes causes things like unused imports linger on master.
Let's at least enable clippy for stable Rust.
Also do the same build_tools/check.sh; since that script already runs
"cargo test --no-default-features", this shouldn't add much work,
though I didn't check that.
Also check that "cd fish-site && make && make new-release" doesn't
leave behind untracked files we're not aware of. This implies that
this script ought to refuse to run if there are untracked files,
at least in fish-site.
Things that are not currently happening in this workflow:
- No GPG-signature on the Git tag
- No *.asc signature file for the tarball (or for any other release assets)
- No GPG-signed Debian and other OBS packages
To-do:
- remove the corresponding entries from
https://github.com/fish-shell/fish-shell/wiki/Release-checklist
and link to this workflow.
- Maybe add some testing (for the Linux packages)?.
- Let's hope that this doesn't cause security issues.
Usage:
1. run "build_tools/release.sh $version"; this will create and push
a tag, which kicks off .github/workflows/release.yml
2. wait for the draft release to be created at
https://github.com/fish-shell/fish-shell/releases/tags/$version
3. publish the draft (manually, for now). This should unblock the
last part of the workflow (website updates).
Closes#10449
Incremental usage example:
version=4.0.3
repository_owner=fish-shell
remote=origin
cd ../fish-shell-secondary-worktree
git tag -d $version ||:
git push $remote :$version ||:
git reset --hard origin/Integration_$version
for d in .github build_tools; do {
rm -rf $d
cp -r ../fish-shell/$d .
git add $d
} done
git commit -m 'Backport CI/CD'
echo "See https://github.com/$repository_owner/fish-shell/actions"
echo "See the draft release at https://github.com/$repository_owner/fish-shell/releases/$version"
../fish-shell/build_tools/release.sh $version $repository_owner $remote
This allows having the proc macro crate as an optional dependency and speeds up
compilation in situations where `FISH_GETTEXT_EXTRACTION_FILE` changes, such as
the `build_tools/check.sh` script. Because we don't need to recompile on changes
to the environment variable when the feature is disabled, cargo can reuse
earlier compilation results instead of recompiling everything.
This speeds up the compilation work in `build_tools/check.sh` when no changes
were made which necessitate recompilation.
For such runs of `build_tools/check.sh`, these changes reduce the runtime on my
system by about 10 seconds, from 70 to 60, approximately.
The difference comes from the following two commands recompiling code without
the changes in this commit, but not with them:
- `cargo test --doc --workspace`
- `cargo doc --workspace`
As reported in #11711 and #11712, the update-checks make check.sh automatically
fail every 6 weeks, so it pressures people into updating Rust, and (what's
worse), updating fish's pinned Rust version, even when that's not relevant
to their intent (which is to run `clippy -Dwarnings` and all other checks).
The update-checks were added as a "temporary" solution to make sure that
our pinned version doesn't lag too far behind stable, which gives us an
opportunity to fix new warnings before most contributors see them.
As suggested in #11584, reasonable solutions might be either of:
1. stop pinning stable Rust and rely on beta-nightlies to fix CI failures early
2. use renovatebot or similar to automate Rust updates
Until then, remove the update check to reduce friction.
I'll still run it on my machine.
This reverts commit 6d061daa91.
build_tools/check.sh is supposed to fail on formatting violations. I don't
think we have a good reason for running build_tools/style.fish outside
check.sh.
black is the only formatter not versioned in CI -- but we can probably
satisfy all realistic versions.
Ref: https://github.com/fish-shell/fish-shell/pull/11608#discussion_r2173176621