From bf7eefd8dc815dde9cfb74d4cc3574e0592ffac0 Mon Sep 17 00:00:00 2001 From: Maksim Bondarenkov <119937608+ognevny@users.noreply.github.com> Date: Mon, 18 Aug 2025 19:52:06 +0700 Subject: [PATCH] fish: update to 4.0.2 (#5572) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: 王宇逸 --- fish/0001-support-cygwin.patch | 207 +++++++++++++++++++++++++++++++++ fish/0002-patch-dep.patch | 132 +++++++++++++++++++++ fish/PKGBUILD | 64 +++++----- 3 files changed, 373 insertions(+), 30 deletions(-) create mode 100644 fish/0001-support-cygwin.patch create mode 100644 fish/0002-patch-dep.patch diff --git a/fish/0001-support-cygwin.patch b/fish/0001-support-cygwin.patch new file mode 100644 index 00000000..74587a87 --- /dev/null +++ b/fish/0001-support-cygwin.patch @@ -0,0 +1,207 @@ +diff --git a/Cargo.toml b/Cargo.toml +index d592a1aaf2d9..c942fcaee91b 100644 +--- a/Cargo.toml ++++ b/Cargo.toml +@@ -71,6 +71,9 @@ serial_test = { version = "3", default-features = false } + cc = "1.0.94" + rsconf = "0.2.2" + ++[target.'cfg(windows)'.build-dependencies] ++unix_path = "1.0.1" ++ + [lib] + crate-type = ["rlib"] + path = "src/lib.rs" +diff --git a/build.rs b/build.rs +index c633905e28b5..8f87702322ec 100644 +--- a/build.rs ++++ b/build.rs +@@ -227,6 +232,11 @@ fn has_small_stack(_: &Target) -> Result> { + } + + fn setup_paths() { ++ #[cfg(unix)] ++ use std::path::PathBuf; ++ #[cfg(windows)] ++ use unix_path::{Path, PathBuf}; ++ + fn get_path(name: &str, default: &str, onvar: PathBuf) -> PathBuf { + let mut var = PathBuf::from(env::var(name).unwrap_or(default.to_string())); + if var.is_relative() { +diff --git a/src/common.rs b/src/common.rs +index d4a8a32daeb5..f4af57cd98e7 100644 +--- a/src/common.rs ++++ b/src/common.rs +@@ -1070,7 +1070,7 @@ pub fn get_obfuscation_read_char() -> char { + /// In this case, we assume no external program has written to the terminal behind our back, making + /// the multiline prompt usable. See #2859 and https://github.com/Microsoft/BashOnWindows/issues/545 + pub fn has_working_tty_timestamps() -> bool { +- if cfg!(target_os = "windows") { ++ if cfg!(any(target_os = "windows", target_os = "cygwin")) { + false + } else if cfg!(target_os = "linux") { + !is_windows_subsystem_for_linux(WSL::V1) +@@ -1124,11 +1124,10 @@ pub fn str2wcstring(inp: &[u8]) -> WString { + // TODO This check used to be conditionally compiled only on affected platforms. + true + } else { +- const _: () = assert!(mem::size_of::() == mem::size_of::()); + let mut codepoint = u32::from(c); + ret = unsafe { + mbrtowc( +- std::ptr::addr_of_mut!(codepoint).cast(), ++ std::ptr::addr_of_mut!(codepoint), + std::ptr::addr_of!(inp[pos]).cast(), + inp.len() - pos, + &mut state, +@@ -1331,9 +1330,7 @@ pub fn fish_setlocale() { + fn can_be_encoded(wc: char) -> bool { + let mut converted = [0 as libc::c_char; AT_LEAST_MB_LEN_MAX]; + let mut state = zero_mbstate(); +- unsafe { +- wcrtomb(converted.as_mut_ptr(), wc as libc::wchar_t, &mut state) != 0_usize.wrapping_sub(1) +- } ++ unsafe { wcrtomb(converted.as_mut_ptr(), wc as u32, &mut state) != 0_usize.wrapping_sub(1) } + } + + /// Call read, blocking and repeating on EINTR. Exits on EAGAIN. +diff --git a/src/env_dispatch.rs b/src/env_dispatch.rs +index 2f2950718e41..030988a79159 100644 +--- a/src/env_dispatch.rs ++++ b/src/env_dispatch.rs +@@ -199,7 +199,10 @@ fn guess_emoji_width(vars: &EnvStack) { + } else { + // Default to whatever the system's wcwidth gives for U+1F603, but only if it's at least + // 1 and at most 2. ++ #[cfg(not(target_os = "cygwin"))] + let width = crate::fallback::wcwidth('😃').clamp(1, 2); ++ #[cfg(target_os = "cygwin")] ++ let width = 2isize; + FISH_EMOJI_WIDTH.store(width, Ordering::Relaxed); + FLOG!(term_support, "default emoji width:", width); + } +diff --git a/src/fallback.rs b/src/fallback.rs +index 3e1334479819..c5f1caa60530 100644 +--- a/src/fallback.rs ++++ b/src/fallback.rs +@@ -3,15 +3,15 @@ + //! + //! Many of these functions are more or less broken and incomplete. + ++use crate::wchar::prelude::*; + use crate::widecharwidth::{WcLookupTable, WcWidth}; +-use crate::{common::is_console_session, wchar::prelude::*}; + use errno::{errno, Errno}; + use once_cell::sync::Lazy; + use std::cmp; ++use std::ffi::CString; + use std::fs::File; + use std::os::fd::FromRawFd; + use std::sync::atomic::{AtomicIsize, Ordering}; +-use std::{ffi::CString, mem}; + + /// Width of ambiguous East Asian characters and, as of TR11, all private-use characters. + /// 1 is the typical default, but we accept any non-negative override via `$fish_ambiguous_width`. +@@ -32,12 +32,13 @@ pub static FISH_EMOJI_WIDTH: AtomicIsize = AtomicIsize::new(1); + static WC_LOOKUP_TABLE: Lazy = Lazy::new(WcLookupTable::new); + + /// A safe wrapper around the system `wcwidth()` function ++#[cfg(not(target_os = "cygwin"))] + pub fn wcwidth(c: char) -> isize { + extern "C" { + pub fn wcwidth(c: libc::wchar_t) -> libc::c_int; + } + +- const _: () = assert!(mem::size_of::() >= mem::size_of::()); ++ const _: () = assert!(std::mem::size_of::() >= std::mem::size_of::()); + let width = unsafe { wcwidth(c as libc::wchar_t) }; + isize::try_from(width).unwrap() + } +@@ -48,7 +49,8 @@ pub fn fish_wcwidth(c: char) -> isize { + // The system version of wcwidth should accurately reflect the ability to represent characters + // in the console session, but knows nothing about the capabilities of other terminal emulators + // or ttys. Use it from the start only if we are logged in to the physical console. +- if is_console_session() { ++ #[cfg(not(target_os = "cygwin"))] ++ if crate::common::is_console_session() { + return wcwidth(c); + } + +@@ -73,8 +75,16 @@ pub fn fish_wcwidth(c: char) -> isize { + let width = WC_LOOKUP_TABLE.classify(c); + match width { + WcWidth::NonCharacter | WcWidth::NonPrint | WcWidth::Combining | WcWidth::Unassigned => { +- // Fall back to system wcwidth in this case. +- wcwidth(c) ++ #[cfg(not(target_os = "cygwin"))] ++ { ++ // Fall back to system wcwidth in this case. ++ wcwidth(c) ++ } ++ #[cfg(target_os = "cygwin")] ++ { ++ // No system wcwidth for UTF-32 on cygwin. ++ 0 ++ } + } + WcWidth::Ambiguous | WcWidth::PrivateUse => { + // TR11: "All private-use characters are by default classified as Ambiguous". +diff --git a/src/input_common.rs b/src/input_common.rs +index 3cdf5b6edc68..d49b718ed667 100644 +--- a/src/input_common.rs ++++ b/src/input_common.rs +@@ -1288,7 +1288,7 @@ pub(crate) fn decode_input_byte( + let mut codepoint = u32::from(res); + match unsafe { + mbrtowc( +- std::ptr::addr_of_mut!(codepoint).cast(), ++ std::ptr::addr_of_mut!(codepoint), + std::ptr::addr_of!(read_byte).cast(), + 1, + state, +diff --git a/src/tests/string_escape.rs b/src/tests/string_escape.rs +index ba8ee7534ebf..3cce5fbc8286 100644 +--- a/src/tests/string_escape.rs ++++ b/src/tests/string_escape.rs +@@ -244,7 +244,7 @@ fn test_convert_private_use() { + let len = unsafe { + wcrtomb( + std::ptr::addr_of_mut!(converted[0]).cast(), +- c as libc::wchar_t, ++ c as u32, + &mut state, + ) + }; +diff --git a/src/wcstringutil.rs b/src/wcstringutil.rs +index cbb415bde3a1..41f0ee834ee5 100644 +--- a/src/wcstringutil.rs ++++ b/src/wcstringutil.rs +@@ -331,7 +331,7 @@ pub fn wcs2string_callback(input: &wstr, mut func: impl FnMut(&[u8]) -> bool) -> + let len = unsafe { + wcrtomb( + std::ptr::addr_of_mut!(converted[0]).cast(), +- c as libc::wchar_t, ++ c as u32, + &mut state, + ) + }; +diff --git a/src/wutil/encoding.rs b/src/wutil/encoding.rs +index a3661661e600..66384ae12d73 100644 +--- a/src/wutil/encoding.rs ++++ b/src/wutil/encoding.rs +@@ -1,11 +1,8 @@ + extern "C" { +- pub fn wcrtomb(s: *mut libc::c_char, wc: libc::wchar_t, ps: *mut mbstate_t) -> usize; +- pub fn mbrtowc( +- pwc: *mut libc::wchar_t, +- s: *const libc::c_char, +- n: usize, +- p: *mut mbstate_t, +- ) -> usize; ++ #[cfg_attr(target_os = "cygwin", link_name = "c32rtomb")] ++ pub fn wcrtomb(s: *mut libc::c_char, wc: u32, ps: *mut mbstate_t) -> usize; ++ #[cfg_attr(target_os = "cygwin", link_name = "mbrtoc32")] ++ pub fn mbrtowc(pwc: *mut u32, s: *const libc::c_char, n: usize, p: *mut mbstate_t) -> usize; + } + + // HACK This should be mbstate_t from libc but that's not exposed. Since it's only written by diff --git a/fish/0002-patch-dep.patch b/fish/0002-patch-dep.patch new file mode 100644 index 00000000..a024c443 --- /dev/null +++ b/fish/0002-patch-dep.patch @@ -0,0 +1,132 @@ +diff --git a/Cargo.toml b/Cargo.toml +index 37cdc1332..3aa89374e 100644 +--- a/Cargo.toml ++++ b/Cargo.toml +@@ -40,7 +40,7 @@ libc = "0.2.155" + # disabling default features uses the stdlib instead, but it doubles the time to rewrite the history + # files as of 22 April 2024. + lru = "0.12.3" +-nix = { version = "0.29.0", default-features = false, features = [ ++nix = { version = "0.30.1", default-features = false, features = [ + "event", + "inotify", + "resource", +diff --git a/src/common.rs b/src/common.rs +index f4af57cd9..48252b7e6 100644 +--- a/src/common.rs ++++ b/src/common.rs +@@ -1337,7 +1337,7 @@ fn can_be_encoded(wc: char) -> bool { + /// Return the number of bytes read, or 0 on EOF, or an error. + pub fn read_blocked(fd: RawFd, buf: &mut [u8]) -> nix::Result { + loop { +- let res = nix::unistd::read(fd, buf); ++ let res = nix::unistd::read(unsafe { BorrowedFd::borrow_raw(fd) }, buf); + if let Err(nix::Error::EINTR) = res { + continue; + } +@@ -1379,8 +1379,7 @@ pub fn write_loop(fd: &Fd, buf: &[u8]) -> std::io::Result<()> { + /// favor of native rust read/write methods at some point. + /// + /// Returns the number of bytes read or an IO error. +-pub fn read_loop(fd: &Fd, buf: &mut [u8]) -> std::io::Result { +- let fd = fd.as_raw_fd(); ++pub fn read_loop(fd: &Fd, buf: &mut [u8]) -> std::io::Result { + loop { + match nix::unistd::read(fd, buf) { + Ok(read) => { +diff --git a/src/env_universal_common.rs b/src/env_universal_common.rs +index e6e76a067..42ba921f1 100644 +--- a/src/env_universal_common.rs ++++ b/src/env_universal_common.rs +@@ -24,7 +24,7 @@ + use std::ffi::CString; + use std::fs::File; + use std::mem::MaybeUninit; +-use std::os::fd::{AsFd, AsRawFd, RawFd}; ++use std::os::fd::{AsFd, AsRawFd}; + use std::os::unix::prelude::MetadataExt; + + // Pull in the O_EXLOCK constant if it is defined, otherwise set it to 0. +@@ -398,7 +398,7 @@ fn load_from_fd(&mut self, file: &mut File, callbacks: &mut CallbackDataList) { + } else { + // Read a variables table from the file. + let mut new_vars = VarTable::new(); +- let format = Self::read_message_internal(file.as_raw_fd(), &mut new_vars); ++ let format = Self::read_message_internal(file, &mut new_vars); + + // Hacky: if the read format is in the future, avoid overwriting the file: never try to + // save. +@@ -726,7 +726,7 @@ fn parse_message_2x_internal(msg: &wstr, vars: &mut VarTable, storage: &mut WStr + } + } + +- fn read_message_internal(fd: RawFd, vars: &mut VarTable) -> UvarFormat { ++ fn read_message_internal(fd: impl AsFd, vars: &mut VarTable) -> UvarFormat { + // Read everything from the fd. Put a sane limit on it. + let mut contents = vec![]; + let mut buffer = [0_u8; 4096]; +diff --git a/src/fds.rs b/src/fds.rs +index fbc7507db..42ec61d1c 100644 +--- a/src/fds.rs ++++ b/src/fds.rs +@@ -30,7 +30,7 @@ pub struct AutoCloseFd { + + impl Read for AutoCloseFd { + fn read(&mut self, buf: &mut [u8]) -> std::io::Result { +- nix::unistd::read(self.as_raw_fd(), buf).map_err(std::io::Error::from) ++ nix::unistd::read(self, buf).map_err(std::io::Error::from) + } + } + +@@ -187,7 +187,7 @@ fn heightenize_fd(fd: OwnedFd, input_has_cloexec: bool) -> nix::Result + } + + // Here we are asking the kernel to give us a cloexec fd. +- let newfd = match nix::fcntl::fcntl(raw_fd, FcntlArg::F_DUPFD_CLOEXEC(FIRST_HIGH_FD)) { ++ let newfd = match nix::fcntl::fcntl(&fd, FcntlArg::F_DUPFD_CLOEXEC(FIRST_HIGH_FD)) { + Ok(newfd) => newfd, + Err(err) => { + perror("fcntl"); +@@ -238,7 +238,7 @@ pub fn open_cloexec(path: &CStr, flags: OFlag, mode: nix::sys::stat::Mode) -> ni + // If it is that's our cancel signal, so we abort. + loop { + let ret = nix::fcntl::open(path, flags | OFlag::O_CLOEXEC, mode); +- let ret = ret.map(|raw_fd| unsafe { File::from_raw_fd(raw_fd) }); ++ let ret = ret.map(|raw_fd| File::from(raw_fd)); + match ret { + Ok(file) => { + return Ok(file); +diff --git a/src/reader.rs b/src/reader.rs +index 45cb70554..f5d28ef0c 100644 +--- a/src/reader.rs ++++ b/src/reader.rs +@@ -30,6 +30,7 @@ + use std::num::NonZeroUsize; + use std::ops::ControlFlow; + use std::ops::Range; ++use std::os::fd::BorrowedFd; + use std::os::fd::RawFd; + use std::pin::Pin; + use std::rc::Rc; +@@ -783,7 +784,7 @@ fn read_ni(parser: &Parser, fd: RawFd, io: &IoChain) -> i32 { + loop { + let mut buff = [0_u8; 4096]; + +- match nix::unistd::read(fd, &mut buff) { ++ match nix::unistd::read(unsafe { BorrowedFd::borrow_raw(fd) }, &mut buff) { + Ok(0) => { + // EOF. + break; +diff --git a/src/topic_monitor.rs b/src/topic_monitor.rs +index 4698001f3..3f83ad9c3 100644 +--- a/src/topic_monitor.rs ++++ b/src/topic_monitor.rs +@@ -243,7 +243,7 @@ pub fn wait(&self) { + let _ = FdReadableSet::is_fd_readable(fd, Timeout::Forever); + } + let mut ignored: u8 = 0; +- match unistd::read(fd, std::slice::from_mut(&mut ignored)) { ++ match unistd::read(&pipes.read, std::slice::from_mut(&mut ignored)) { + Ok(1) => break, + Ok(_) => continue, + // EAGAIN should only be possible if TSAN workarounds have been applied diff --git a/fish/PKGBUILD b/fish/PKGBUILD index e73bceaf..8d152ee5 100644 --- a/fish/PKGBUILD +++ b/fish/PKGBUILD @@ -1,69 +1,73 @@ - +# Contributor: 王宇逸 pkgname=fish -pkgver=3.7.1 -pkgrel=6 -epoch= +pkgver=4.0.2 +pkgrel=1 pkgdesc='Smart and user friendly shell intended mostly for interactive use' -arch=('i686' 'x86_64') +arch=('x86_64') url="https://fishshell.com/" msys2_repository_url="https://github.com/fish-shell/fish-shell" msys2_references=( "cpe: cpe:/a:fishshell:fish" ) license=('spdx:GPL-2.0-only') -depends=('gcc-libs' 'gettext' 'libpcre2_16' 'man-db' 'ncurses') -makedepends=('gcc' 'gettext-devel' 'intltool' 'ncurses-devel' 'pcre2-devel' 'cmake') +depends=('gcc-libs' 'gettext' 'libpcre2_32' 'libpcre2_8' 'man-db') +makedepends=('gcc' 'gettext-devel' 'intltool' 'pcre2-devel' 'cmake' 'pkgconf' 'rust' 'ninja') optdepends=('python: for manual page completion parser and web configuration tool') install=fish.install backup=('etc/fish/config.fish' 'etc/fish/msys2.fish' 'etc/fish/perlbin.fish') source=("https://github.com/fish-shell/fish-shell/releases/download/${pkgver}/${pkgname}-${pkgver}.tar.xz"{,.asc} - "https://raw.githubusercontent.com/fish-shell/fish-shell/4868166f86e2f6c7c54082c36c9c7a5d67dc1092/share/completions/rustc.fish" + 0001-support-cygwin.patch + 0002-patch-dep.patch config.fish msys2.fish msystem.fish - perlbin.fish - 0001-cmake-4-backport.patch) -sha256sums=('614c9f5643cd0799df391395fa6bbc3649427bb839722ce3b114d3bbc1a3b250' + perlbin.fish) +sha256sums=('6e1ecdb164285fc057b2f35acbdc20815c1623099e7bb47bbfc011120adf7e83' 'SKIP' - '97a6fc8746dbb7117de79446c4b85f412624f8f797bb10f12e07361c4995bc23' + '8b94656c9f6118c19efa2bcb960b447863ff8b9b1f6ee957e00d6d87d8ef79f0' + 'b2739eee8f030f468eaf435982ac50056738f5a7bfefe5288cd13430f57498bc' '983c3273e0249957ed6c40785e005739da30f31d4f029383f257f9990d38811a' '8bb0d28df47b66e6785f7db00a2c4316bc15960e67bdec0daca7f811f5bf3895' '71c6990b39caf5d50c10f10074283adfc6a36aafff30fd54f7eb451d4e007496' - 'b136a9fa94abf53e302f7a1cc28def03b58dd2326990c5f02ceb4988341a5ac6' - '5b6168131d30cf0f4a5b39b1e8728eb882414586792101e571879d92efcaac5c') + 'b136a9fa94abf53e302f7a1cc28def03b58dd2326990c5f02ceb4988341a5ac6') validpgpkeys=('003837986104878835FA516D7A67D962D88A709A') # David Adam prepare() { cd "${pkgname}-${pkgver}" + patch -Np1 -i ../0001-support-cygwin.patch + patch -Np1 -i ../0002-patch-dep.patch - # https://github.com/fish-shell/fish-shell/issues/11116 - patch -p1 < "${srcdir}/0001-cmake-4-backport.patch" + cargo add unix-path@1.0.1 + cargo update -p errno@0.3.9 --precise 0.3.11 + cargo fetch --locked --target 'x86_64-pc-cygwin' } build() { - cd "${srcdir}/${pkgname}-${pkgver}" - export CXXFLAGS+=" ${CPPFLAGS}" + export FISH_BUILD_VERSION="${pkgver}-${pkgrel} (Built by MSYS2 project)" cmake \ - -B build \ + -GNinja \ -DCMAKE_INSTALL_PREFIX=/usr \ -DCMAKE_INSTALL_SYSCONFDIR=/etc \ - -DCMAKE_BUILD_TYPE=None \ - -Wno-dev + -DCMAKE_BUILD_TYPE=Release \ + -Wno-dev \ + -DRust_COMPILER=/usr/bin/rustc \ + -DRust_CARGO=/usr/bin/cargo \ + -DRust_CARGO_TARGET=x86_64-pc-cygwin \ + -DRust_CARGO_HOST_TARGET=x86_64-pc-cygwin \ + -DRust_RESOLVE_RUSTUP_TOOLCHAINS=OFF \ + -S "${pkgname}-${pkgver}" \ + -B build cmake --build build } package() { - cd "${srcdir}/${pkgname}-${pkgver}/build" + DESTDIR="${pkgdir}" cmake --install build - DESTDIR="${pkgdir}" cmake --install . - - install -D -m644 "${srcdir}/config.fish" "${pkgdir}/etc/fish/config.fish" - install -D -m644 "${srcdir}/msys2.fish" "${pkgdir}/etc/fish/msys2.fish" - install -D -m644 "${srcdir}/msystem.fish" "${pkgdir}/etc/fish/msystem.fish" - install -D -m644 "${srcdir}/perlbin.fish" "${pkgdir}/etc/fish/perlbin.fish" - # install more fresh rustc completions because it was buggy - install -D -m644 "${srcdir}/rustc.fish" "${pkgdir}/usr/share/fish/completions/rustc.fish" + install -D -m644 "config.fish" "${pkgdir}/etc/fish/config.fish" + install -D -m644 "msys2.fish" "${pkgdir}/etc/fish/msys2.fish" + install -D -m644 "msystem.fish" "${pkgdir}/etc/fish/msystem.fish" + install -D -m644 "perlbin.fish" "${pkgdir}/etc/fish/perlbin.fish" }