Fix failing system tests on Cygwin

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
This commit is contained in:
Nahor
2025-11-17 12:25:40 -08:00
committed by Johannes Altmanninger
parent 52495c8124
commit 440e7fcbc1
27 changed files with 478 additions and 117 deletions

View File

@@ -8,11 +8,29 @@ if [ "$FISH_CHECK_LINT" = false ]; then
lint=false
fi
case "$(uname)" in
MSYS*)
is_cygwin=true
cygwin_var=MSYS
;;
CYGWIN*)
is_cygwin=true
cygwin_var=CYGWIN
;;
*)
is_cygwin=false
;;
esac
check_dependency_versions=false
if [ "${FISH_CHECK_DEPENDENCY_VERSIONS:-false}" != false ]; then
check_dependency_versions=true
fi
green='\e[0;32m'
yellow='\e[1;33m'
reset='\e[m'
if $check_dependency_versions; then
command -v curl
command -v jq
@@ -83,12 +101,45 @@ if $lint; then
cargo clippy --workspace --all-targets $features
done
fi
cargo test --no-default-features --workspace --all-targets
# When running `cargo test`, some binaries (e.g. `fish_gettext_extraction`)
# are dynamically linked against Rust's `std-xxx.dll` instead of being
# statically link as they usually are.
# On Cygwin, `PATH`is not properly updated to point to the `std-xxx.dll`
# location, so we have to do it manually.
# See:
# - https://github.com/rust-lang/rust/issues/149050
# - https://github.com/msys2/MSYS2-packages/issues/5784
(
if $is_cygwin; then
export PATH="$PATH:$(rustc --print target-libdir)"
fi
cargo test --no-default-features --workspace --all-targets
)
cargo test --doc --workspace
if $lint; then
cargo doc --workspace --no-deps
fi
FISH_GETTEXT_EXTRACTION_DIR=$gettext_template_dir "$workspace_root/tests/test_driver.py" "$build_dir"
# Using "()" not "{}" because we do want a subshell (for the export)
system_tests() (
[ -n "$@" ] && export "$@"
export FISH_GETTEXT_EXTRACTION_DIR="$gettext_template_dir"
"$workspace_root/tests/test_driver.py" "$build_dir"
)
test_cmd='FISH_GETTEXT_EXTRACTION_DIR="$gettext_template_dir" "$workspace_root/tests/test_driver.py" "$build_dir"'
if $is_cygwin; then
echo -e "=== Running ${green}integration tests ${yellow}with${green} symlinks${reset}"
system_tests $cygwin_var=winsymlinks
echo -e "=== Running ${green}integration tests ${yellow}without${green} symlinks${reset}"
system_tests $cygwin_var=winsymlinks
else
echo -e "=== Running ${green}integration tests${reset}"
system_tests
fi
exit
}

View File

@@ -0,0 +1,10 @@
# localization: skip(private)
function __fish_cygwin_noacl
# MSYS (default) and Cygwin (non-default) mounts may not support POSIX permissions.
__fish_is_cygwin
and {
mount |
string match "*on $(stat -c %m -- $argv[1]) *" |
string match -qr "[(,]noacl[),]"
}
end

View File

@@ -0,0 +1,4 @@
# localization: skip(private)
function __fish_is_cygwin
__fish_uname | string match -qr "^(MSYS|CYGWIN)"
end

View File

@@ -9,6 +9,21 @@ function __fish_make_cache_dir --description "Create and return XDG_CACHE_HOME"
# So if you call `__fish_make_cache_dir completions`,
# this creates e.g. ~/.cache/fish/completions
if not path is -d $xdg_cache_home/fish/"$argv[1]"
mkdir -m 700 -p $xdg_cache_home/fish/"$argv[1]"
set -l mkdir_options -m 700
# Can't set the permission in Cygwin on a `noacl` mount
if __fish_is_cygwin
# Find the first existing parent so we can `stat` it and get its mountpoint
set -l existing_parent $xdg_cache_home/fish/"$argv[1]"
while not path is -d $existing_parent
set existing_parent (path dirname $existing_parent)
end
if __fish_cygwin_noacl "$existing_parent"
set mkdir_options
end
end
mkdir $mkdir_options -p $xdg_cache_home/fish/"$argv[1]"
end; and echo $xdg_cache_home/fish/"$argv[1]"
end

View File

@@ -2,6 +2,8 @@
set -g fish (realpath $fish)
cygwin_nosymlinks && set nosymlinks
# Store pwd to later go back before cleaning up
set -l oldpwd (pwd)
@@ -25,30 +27,37 @@ rm -rf $tmp
# Create a test directory to store our stuff.
# macOS likes to return symlinks from (mktemp -d), make sure it does not.
set -l base (realpath (mktemp -d))
set real (realpath (mktemp -d))
set link $base/link
ln -s $real $link
cd $link
prevd
nextd
test "$PWD" = "$link" || echo "\$PWD != \$link:"\n "\$PWD: $PWD"\n "\$link: $link"\n
test (pwd) = "$link" || echo "(pwd) != \$link:"\n "\$PWD: "(pwd)\n "\$link: $link"\n
test (pwd -P) = "$real" || echo "(pwd -P) != \$real:"\n "\$PWD: $PWD"\n "\$real: $real"\n
test (pwd -P -L) = "$link" || echo "(pwd -P -L) != \$link:"\n "\$PWD: $PWD"\n "\$link: $link"\n
if not set -q nosymlinks
set real (realpath (mktemp -d))
set link $base/link
ln -s $real $link
cd $link
prevd
nextd
test "$PWD" = "$link" || echo "\$PWD != \$link:"\n "\$PWD: $PWD"\n "\$link: $link"\n
test (pwd) = "$link" || echo "(pwd) != \$link:"\n "\$PWD: "(pwd)\n "\$link: $link"\n
test (pwd -P) = "$real" || echo "(pwd -P) != \$real:"\n "\$PWD: $PWD"\n "\$real: $real"\n
test (pwd -P -L) = "$link" || echo "(pwd -P -L) != \$link:"\n "\$PWD: $PWD"\n "\$link: $link"\n
end
# Expect no output on success.
pwd abc
# CHECKERR: pwd: expected 0 arguments; got 1
mkdir -p $base/pwd_real/subdir
ln -s $base/pwd_real $base/pwd_link
cd $base/pwd_link/subdir
rmdir $base/pwd_real/subdir $base/pwd_real
pwd -P
# CHECKERR: pwd: realpath failed: No such file or directory
if set -q nosymlinks
echo "pwd: realpath failed: No such file or directory" >&2
else
mkdir -p $base/pwd_real/subdir
ln -s $base/pwd_real $base/pwd_link
cd $base/pwd_link/subdir
rmdir $base/pwd_real/subdir $base/pwd_real
pwd -P
end
# CHECKERR: pwd: realpath failed: {{.+}}
# Create a symlink and verify logical completion.
# create directory $base/through/the/looking/glass
# symlink $base/somewhere/teleport -> $base/through/the/looking/glass
# symlink $base/somewhere/rabbithole -> $base/through/the/looking/glass
# verify that .. completions work
cd $base
mkdir -p $base/through/the/looking/glass
@@ -63,7 +72,13 @@ mkdir $base/through/the/looking/d2
mkdir $base/through/the/looking/d3
ln -s $base/through/the/looking/glass $base/somewhere/rabbithole
cd $base/somewhere/rabbithole
if set -q nosymlinks
# This is where we would be going if symlinks were working. This invalidates
# that particular test case, but now we can proceed with the tests
cd $base/through/the/looking/glass
else
cd $base/somewhere/rabbithole
end
echo "ls:"
complete -C'ls ../'
#CHECK: ls:
@@ -75,6 +90,9 @@ complete -C'ls ../'
#CHECK: ../d3/
#CHECK: ../glass/
if set -q nosymlinks
cd $base/somewhere/rabbithole
end
echo "cd:"
complete -C'cd ../'
#CHECK: cd:
@@ -154,9 +172,18 @@ cd file
#CHECKERR: called on line {{\d+}} of file {{.*}}/cd.fish
# a directory that isn't executable
mkdir bad-perms
chmod -x bad-perms
cd bad-perms
if cygwin_noacl ./
echo "cd: Permission denied: 'bad-perms'" >&2
echo "fake/cd.fish (line 123):" >&2
echo "builtin cd \$argv" >&2
echo "^" >&2
echo "in function 'cd' with arguments 'bad-perms'" >&2
echo "called on line 123 of file fake/cd.fish" >&2
else
mkdir bad-perms
chmod -x bad-perms
cd bad-perms
end
#CHECKERR: cd: Permission denied: 'bad-perms'
#CHECKERR: {{.*}}/cd.fish (line {{\d+}}):
#CHECKERR: builtin cd $argv
@@ -189,7 +216,16 @@ cd $old_path
set CDPATH $old_cdpath $PWD/cdpath-dir
cd nonexistent
cd $old_path
cd bad-perms
if cygwin_noacl ./
echo "cd: Permission denied: 'bad-perms'" >&2
echo "fake/cd.fish (line 123):" >&2
echo "builtin cd \$argv" >&2
echo "^" >&2
echo "in function 'cd' with arguments 'bad-perms'" >&2
echo "called on line 123 of file fake/cd.fish" >&2
else
cd bad-perms
end
# Permission errors are still a problem!
#CHECKERR: cd: Permission denied: 'bad-perms'
#CHECKERR: {{.*}}/cd.fish (line {{\d+}}):
@@ -248,10 +284,19 @@ echo $status
# CHECK: 1
cd (mktemp -d)
ln -s no/such/directory broken-symbolic-link
begin
set -lx CDPATH
cd broken-symbolic-link
if set -q nosymlinks
echo "cd: 'fake/broken-symbolic-link' is a broken symbolic link to 'no/such/directory'" >&2
echo "fake/cd.fish (line 123):" >&2
echo "builtin cd \$argv" >&2
echo "^" >&2
echo "in function 'cd' with arguments 'broken-symbolic-link'" >&2
echo "called on line 123 of file fake/cd.fish" >&2
else
ln -s no/such/directory broken-symbolic-link
begin
set -lx CDPATH
cd broken-symbolic-link
end
end
# CHECKERR: cd: '{{.*}}/broken-symbolic-link' is a broken symbolic link to 'no/such/directory'
# CHECKERR: {{.*}}/cd.fish (line {{\d+}}):
@@ -261,9 +306,18 @@ end
# CHECKERR: called on line {{\d+}} of file {{.*}}/cd.fish
# Make sure that "broken symlink" is reported over "no such file or directory".
begin
set -lx CDPATH other
cd broken-symbolic-link
if set -q nosymlinks
echo "cd: 'fake/broken-symbolic-link' is a broken symbolic link to 'no/such/directory'" >&2
echo "fake/cd.fish (line 123):" >&2
echo "builtin cd \$argv" >&2
echo "^" >&2
echo "in function 'cd' with arguments 'broken-symbolic-link'" >&2
echo "called on line 123 of file fake/cd.fish" >&2
else
begin
set -lx CDPATH other
cd broken-symbolic-link
end
end
# CHECKERR: cd: '{{.*}}/broken-symbolic-link' is a broken symbolic link to 'no/such/directory'
# CHECKERR: {{.*}}/cd.fish (line {{\d+}}):
@@ -322,9 +376,18 @@ end
HOME="" cd
# CHECKERR: cd: Could not find home directory
ln -s loop1 loop2
ln -s loop2 loop1
cd loop1
if set -q nosymlinks
echo "cd: Too many levels of symbolic links: 'loop1'" >&2
echo "fake/cd.fish (line 123):" >&2
echo "builtin cd \$argv" >&2
echo "^" >&2
echo "in function 'cd' with arguments 'loop1'" >&2
echo "called on line 123 of file fake/cd.fish" >&2
else
ln -s loop1 loop2
ln -s loop2 loop1
cd loop1
end
# CHECKERR: cd: Too many levels of symbolic links: 'loop1'
# CHECKERR: {{.*}}/cd.fish (line {{\d+}}):
# CHECKERR: builtin cd $argv

View File

@@ -1,11 +1,13 @@
# RUN: env PATH="a::b" CDPATH="d::e" MANPATH="x::y" %fish %s
# RUN: env PATH="/usr/bin:a::b" CDPATH="d::e" MANPATH="x::y" %fish %s
# PATH must contain `/usr/bin` for the test to work on Cygwin (Cygwin must be
# able to find its DLLs when loading fish.exe)
# In PATH and CDPATH, empty elements are treated the same as "."
# In fish we replace them explicitly. Ensure that works.
# Do not replace empties in MATHPATH - see #4158.
# Do not replace empties in MANPATH - see #4158.
echo "$PATH"
# CHECK: a:.:b
# CHECK: /usr/bin:a:.:b
echo "$CDPATH"
# CHECK: d:.:e

View File

@@ -1,6 +1,13 @@
#RUN: fish=%fish %fish %s
__fish_migrate # make sure the interactive fish doesn't need mkdir in PATH
set -g PATH
if __fish_is_cygwin
# The Cygwin/MSYS DLLs must be in the path, otherwise fish cannot be
# executed
set -g PATH /usr/bin
else
set -g PATH
end
$fish -c "nonexistent-command-1234 banana rama"
#CHECKERR: fish: Unknown command: nonexistent-command-1234
#CHECKERR: fish:

View File

@@ -1,6 +1,6 @@
#RUN: fish=%fish %fish %s
# REQUIRES: %fish -c "is_cygwin"
# REQUIRES: %fish -c "__fish_is_cygwin"
mkdir dir
echo "#!/bin/sh" >dir/foo.exe

View File

@@ -1,4 +1,5 @@
#RUN: fish=%fish %fish %s
function complete_test_alpha1
echo $argv
end
@@ -420,8 +421,12 @@ rm -r $dir
set -l dir (mktemp -d)
cd $dir
: >command-not-in-path
chmod +x command-not-in-path
if cygwin_noacl ./
echo "#!/bin/sh" >command-not-in-path
else
: >command-not-in-path
chmod +x command-not-in-path
end
complete -p $PWD/command-not-in-path -xa relative-path
complete -C './command-not-in-path '
# CHECK: relative-path
@@ -434,8 +439,12 @@ HOME=$PWD complete -C '~/command-not-in-path '
# Non-canonical command path
mkdir -p subdir
: >subdir/command-in-subdir
chmod +x subdir/command-in-subdir
if cygwin_noacl ./
echo "#!/bin/sh" >subdir/command-in-subdir
else
: >subdir/command-in-subdir
chmod +x subdir/command-in-subdir
end
complete -p "$PWD/subdir/command-in-subdir" -xa custom-completions
complete -C './subdir/../subdir/command-in-subdir '
# CHECK: custom-completions
@@ -695,8 +704,12 @@ complete -C"command-line-aware-completions "
# CHECK: command-line-aware-completions
begin
: >"$TMPDIR/-command-starting-with-dash"
chmod +x "$TMPDIR/-command-starting-with-dash"
if cygwin_noacl ./
echo "#!/bin/sh" >"$TMPDIR/-command-starting-with-dash"
else
: >"$TMPDIR/-command-starting-with-dash"
chmod +x "$TMPDIR/-command-starting-with-dash"
end
set -l PATH "$TMPDIR" $PATH
complete -C-command-starting-with

View File

@@ -11,7 +11,15 @@ $fish -c ''
# Check that existing directories kept their permissions, and new directories
# have the right permissions according to the XDG Base Directory Specification.
# Use command ls and awk to strip off xattr or SELinux indicators.
command ls -ld $dir/old $dir/old/new $dir/old/new/fish | awk '{print substr($1, 1, 10)}'
command ls -ld $dir/old | awk '{print substr($1, 1, 10)}'
# CHECK: drwxr-xr-x
set -l ls_result "$(command ls -ld $dir/old/new $dir/old/new/fish | awk '{print substr($1, 1, 10)}')"
if cygwin_noacl $dir
# No permission support => fake the result
string replace -a drwxr-xr-x drwx------ $ls_result
else
printf "%s" "$ls_result"
end
# CHECK: drwx------
# CHECK: drwx------

View File

@@ -1,5 +1,8 @@
#RUN: fish=%fish %fish %s
# Cygwin/MSYS PATH automatically inherits the Windows PATH
# REQUIRES: %fish -c "not __fish_is_cygwin"
if command -q getconf
# (no env -u, some systems don't support that)
set -l getconf (command -s getconf)

View File

@@ -286,7 +286,11 @@ set expandedtilde (env HOME=$tmpdir/linkhome $fish -c 'echo ~')
if test $expandedtilde != $tmpdir/linkhome
echo '~ expands to' $expandedtilde ' - expected ' $tmpdir/linkhome
end
rm $tmpdir/linkhome
if cygwin_nosymlinks
rmdir $tmpdir/linkhome
else
rm $tmpdir/linkhome
end
rmdir $tmpdir/realhome
rmdir $tmpdir
@@ -337,7 +341,7 @@ printf '<%s>\n' ($fish -c 'echo "$abc["' 2>&1)
set -l pager command less
echo foo | $pager
#CHECKERR: {{.*}}checks/expansion.fish (line 339): The expanded command is a keyword.
#CHECKERR: {{.*}}checks/expansion.fish (line {{\d+}}): The expanded command is a keyword.
#CHECKERR: echo foo | $pager
#CHECKERR: ^~~~~^

View File

@@ -37,7 +37,11 @@ git config --local alias.re 'restore --staged'
set -p PATH $PWD
echo "echo foo" >git-frobnicate
chmod +x git-frobnicate
if cygwin_noacl ./
echo "#!/bin/sh" >git-frobnicate
else
chmod +x git-frobnicate
end
complete -c git-frobnicate -xa 'foo bar baz'
complete -c git-frobnicate -l onto -xa 'onto1 onto2'

View File

@@ -36,8 +36,12 @@ string join \n **/anyfile | sort
# But symlink loops only get explored once.
mkdir -p dir1/child2/grandchild1
touch dir1/child2/grandchild1/differentfile
ln -s ../../child2/grandchild1 dir1/child2/grandchild1/link2
echo **/differentfile
if cygwin_nosymlinks
echo dir1/child2/grandchild1/differentfile
else
ln -s ../../child2/grandchild1 dir1/child2/grandchild1/link2
echo **/differentfile
end
# CHECK: dir1/child2/grandchild1/differentfile
rm -Rf *

View File

@@ -15,11 +15,14 @@ sleep 0.1
# There could already be zombies from previous tests run in this session or a test could be run
# simultaneously that causes a zombie to spawn, so limit the output only to processes started by
# this fish instance.
if not contains (uname) SunOS
ps -o ppid,stat
else
ps -o ppid,s
end | string match -e $fish_pid | string match '*Z*'
# Cygwin does not have zombies (or at least, `ps` cannot show if they are or not)
if not __fish_is_cygwin
if not contains (uname) SunOS
ps -o ppid,stat
else
ps -o ppid,s
end | string match -e $fish_pid | string match '*Z*'
end
# Verify disown can be used with last_pid, even if it is separate from the pgroup.
# This should silently succeed.

View File

@@ -1,5 +1,8 @@
# RUN: %fish %s
# Shebangless scripts cannot be marked executable without POSIX file permissions
# REQUIRES: %fish -c 'not cygwin_noacl $TMPDIR'
# Test for shebangless scripts - see 7802.
set testdir (mktemp -d)

View File

@@ -1,6 +1,8 @@
#RUN: %fish %s
# The "path" builtin for dealing with paths
cygwin_nosymlinks && set nosymlinks
# Extension - for figuring out the file extension of a given path.
path extension /
or echo None
@@ -85,6 +87,7 @@ path basename /usr/bin/
# CHECK: bin
cd $TMPDIR
cygwin_noacl ./ && set -l noacl
mkdir -p bin
touch bin/{bash,bssh,chsh,dash,fish,slsh,ssh,zsh}
ln -s $TMPDIR/bin/bash bin/sh
@@ -134,13 +137,24 @@ path filter --type file,dir --perm exec,write bin/fish .
mkdir -p sbin
touch sbin/setuid-exe sbin/setgid-exe
chmod u+s,a+x sbin/setuid-exe
path filter --perm suid sbin/*
# Without POSIX permission, there is no way to set the setuid bit, so fake
# the output.
if set -q noacl
echo sbin/setuid-exe
else
chmod u+s,a+x sbin/setuid-exe
path filter --perm suid sbin/*
end
# CHECK: sbin/setuid-exe
# On at least FreeBSD on our CI this fails with "permission denied".
# So we can't test it, and we fake the output instead.
if chmod g+s,a+x sbin/setgid-exe 2>/dev/null
# Without POSIX permission, there is no way to set the setgid bit, so fake
# the result.
# And on at least FreeBSD on our CI this fails with "permission denied".
# So we can't test it, and we fake the output there too.
if set -q noacl
echo sbin/setgid-exe
else if chmod g+s,a+x sbin/setgid-exe 2>/dev/null
path filter --perm sgid sbin/*
else
echo sbin/setgid-exe
@@ -149,6 +163,12 @@ end
mkdir stuff
touch stuff/{read,write,exec,readwrite,readexec,writeexec,all,none}
if set -q noacl
echo "#!/bin/sh" >stuff/exec
echo "#!/bin/sh" >stuff/readexec
echo "#!/bin/sh" >stuff/writeexec
echo "#!/bin/sh" >stuff/all
end
chmod 400 stuff/read
chmod 200 stuff/write
chmod 100 stuff/exec
@@ -161,57 +181,113 @@ chmod 000 stuff/none
# Validate that globs are sorted.
test (path filter stuff/* | path sort | string join ",") = (path filter stuff/* | string join ",")
path filter --perm read stuff/*
# echo/CHECK to separate the output of different tests since they all blend
# together otherwise, making it hard to know which test failed.
echo "=== test --perm read"
# CHECK: === test --perm read
if set -q noacl
# noacl cannot mark files non-readable, filter out known bad files
path filter --perm read stuff/* | string match -rv ".*/(?:write|exec|writeexec|none).*"
else
path filter --perm read stuff/*
end
# CHECK: stuff/all
# CHECK: stuff/read
# CHECK: stuff/readexec
# CHECK: stuff/readwrite
path filter -r stuff/*
echo "=== test -r"
# CHECK: === test -r
if set -q noacl
path filter -r stuff/* | string match -rv ".*/(?:write|exec|writeexec|none).*"
else
path filter -r stuff/*
end
# CHECK: stuff/all
# CHECK: stuff/read
# CHECK: stuff/readexec
# CHECK: stuff/readwrite
echo "=== test --perm write"
# CHECK: === test --perm write
path filter --perm write stuff/*
# CHECK: stuff/all
# CHECK: stuff/readwrite
# CHECK: stuff/write
# CHECK: stuff/writeexec
echo "=== test -w"
# CHECK: === test -w
path filter -w stuff/*
# CHECK: stuff/all
# CHECK: stuff/readwrite
# CHECK: stuff/write
# CHECK: stuff/writeexec
echo "=== test --perm exec"
# CHECK: === test --perm exec
path filter --perm exec stuff/*
# CHECK: stuff/all
# CHECK: stuff/exec
# CHECK: stuff/readexec
# CHECK: stuff/writeexec
echo "=== test -x"
# CHECK: === test -x
path filter -x stuff/*
# CHECK: stuff/all
# CHECK: stuff/exec
# CHECK: stuff/readexec
# CHECK: stuff/writeexec
path filter --perm read,write stuff/*
echo "=== test --perm read,write"
# CHECK: === test --perm read,write
if set -q noacl
path filter --perm read,write stuff/* | string match -rv ".*/(?:write|writeexec).*"
else
path filter --perm read,write stuff/*
end
# CHECK: stuff/all
# CHECK: stuff/readwrite
path filter --perm read,exec stuff/*
echo "=== test --perm read,exec"
# CHECK: === test --perm read,exec
if set -q noacl
path filter --perm read,exec stuff/* | string match -rv ".*/(?:exec|writeexec).*"
else
path filter --perm read,exec stuff/*
end
# CHECK: stuff/all
# CHECK: stuff/readexec
echo "=== test --perm write,exec"
# CHECK: === test --perm write,exec
path filter --perm write,exec stuff/*
# CHECK: stuff/all
# CHECK: stuff/writeexec
path filter --perm read,write,exec stuff/*
echo "=== test --perm read,write,exec"
# CHECK: === test --perm read,write,exec
if set -q noacl
path filter --perm read,write,exec stuff/* | string match -rv ".*/(?:writeexec).*"
else
path filter --perm read,write,exec stuff/*
end
# CHECK: stuff/all
echo "=== test all"
# CHECK: === test all
path filter stuff/*
# CHECK: stuff/all
# CHECK: stuff/exec
@@ -242,7 +318,11 @@ path filter -f -- -foo
# CHECK: ./-foo
# We need to remove the rest of the path because we have no idea what its value looks like.
path resolve bin//sh | string match -r -- 'bin/bash$'
if set -q nosymlinks
echo bin/bash
else
path resolve bin//sh | string match -r -- 'bin/bash$'
end
# The "//" is squashed, and the symlink is resolved.
# sh here is bash
# CHECK: bin/bash
@@ -290,15 +370,21 @@ path sort --unique --key=basename {def,abc}/{456,123,789} def/{abc,def,0} abc/{f
# Symlink loop.
# It goes brrr.
ln -s target link
ln -s link target
if not set -q nosymlinks
ln -s target link
ln -s link target
end
test (path resolve target) = (pwd -P)/target
and echo target resolves to target
if set -q nosymlinks ||
test (path resolve target) = (pwd -P)/target
echo target resolves to target
end
# CHECK: target resolves to target
test (path resolve link) = (pwd -P)/link
and echo link resolves to link
if set -q nosymlinks ||
test (path resolve link) = (pwd -P)/link
echo link resolves to link
end
# CHECK: link resolves to link
# path mtime

View File

@@ -1,4 +1,7 @@
# RUN: %fish %s
cygwin_nosymlinks && set nosymlinks
# $XDG_DATA_HOME can itself be a relative path. So force it to an absolute
# path so we can remove it from any resolved paths below. This is needed
# because the contents of the builtin realpath.out file can't include any $PWD
@@ -59,7 +62,9 @@ popd
ln -fs fish $XDG_DATA_HOME/fish-symlink
set -l real_path (builtin realpath $XDG_DATA_HOME/fish-symlink)
set -l expected_real_path "$data_home_realpath/fish"
if test "$real_path" = "$expected_real_path"
if set -q nosymlinks
echo "fish-symlink handled correctly"
else if test "$real_path" = "$expected_real_path"
echo "fish-symlink handled correctly"
else
echo "fish-symlink not handled correctly: $real_path != $expected_real_path" >&2
@@ -103,12 +108,16 @@ or echo builtin realpath -s does not resolve .. or resolves symlink wrong
# A nonexistent file relative to a valid symlink to a directory gets converted.
# This depends on the symlink created by the previous test.
set -l real_path (builtin realpath $XDG_DATA_HOME/fish-symlink/nonexistent-file-relative-to-a-symlink)
set -l expected_real_path "$data_home_realpath/fish/nonexistent-file-relative-to-a-symlink"
if test "$real_path" = "$expected_real_path"
if set -q nosymlinks
echo "fish-symlink/nonexistent-file-relative-to-a-symlink correctly converted"
else
echo "failure nonexistent-file-relative-to-a-symlink: $real_path != $expected_real_path" >&2
set -l real_path (builtin realpath $XDG_DATA_HOME/fish-symlink/nonexistent-file-relative-to-a-symlink)
set -l expected_real_path "$data_home_realpath/fish/nonexistent-file-relative-to-a-symlink"
if test "$real_path" = "$expected_real_path"
echo "fish-symlink/nonexistent-file-relative-to-a-symlink correctly converted"
else
echo "failure nonexistent-file-relative-to-a-symlink: $real_path != $expected_real_path" >&2
end
end
# CHECK: fish-symlink/nonexistent-file-relative-to-a-symlink correctly converted
@@ -122,15 +131,19 @@ builtin realpath -s //bin
# CHECK: /bin
# A path with two symlinks, first to a directory, second to a file, is correctly resolved.
ln -fs fish $XDG_DATA_HOME/fish-symlink2
touch $XDG_DATA_HOME/fish/real_file
ln -fs real_file $XDG_DATA_HOME/fish/symlink_file
set -l real_path (builtin realpath $XDG_DATA_HOME/fish-symlink/symlink_file)
set -l expected_real_path "$data_home_realpath/fish/real_file"
if test "$real_path" = "$expected_real_path"
if set -q nosymlinks
echo "fish-symlink/symlink_file handled correctly"
else
echo "fish-symlink/symlink_file not handled correctly: $real_path != expected_real_path" >&2
ln -fs fish $XDG_DATA_HOME/fish-symlink2
touch $XDG_DATA_HOME/fish/real_file
ln -fs real_file $XDG_DATA_HOME/fish/symlink_file
set -l real_path (builtin realpath $XDG_DATA_HOME/fish-symlink/symlink_file)
set -l expected_real_path "$data_home_realpath/fish/real_file"
if test "$real_path" = "$expected_real_path"
echo "fish-symlink/symlink_file handled correctly"
else
echo "fish-symlink/symlink_file not handled correctly: $real_path != expected_real_path" >&2
end
end
# CHECK: fish-symlink/symlink_file handled correctly

View File

@@ -1,4 +1,5 @@
# RUN: fish=%fish %fish %s
# REQUIRES: %fish -c "not cygwin_nosymlinks"
# fish_variables
set -l target_file $XDG_CONFIG_HOME/fish/target_fish_variables

View File

@@ -86,8 +86,12 @@ end
#CHECK: good ot
#CHECK: good ot
ln -sf epoch epochlink
test epoch -ef epochlink && echo good ef || echo bad ef
if cygwin_nosymlinks
echo good ef
else
ln -sf epoch epochlink
test epoch -ef epochlink && echo good ef || echo bad ef
end
#CHECK: good ef
test epoch -ef old && echo bad ef || echo good ef

View File

@@ -18,10 +18,15 @@ isolated-tmux-start -C '
isolated-tmux capture-pane -p
# CHECK: prompt 0> <status=0> <>
set -q CI && set sleep sleep 10
set -U prompt_var changed
tmux-sleep
isolated-tmux send-keys Enter
if __fish_is_cygwin
# See issue #12074
echo "prompt 0> <status=0> <changed>"
else
set -q CI && set sleep sleep 10
set -U prompt_var changed
tmux-sleep
isolated-tmux send-keys Enter
end
# CHECK: prompt 0> <status=0> <changed>
isolated-tmux send-keys echo Space 123

View File

@@ -135,8 +135,14 @@ type -p other-test-type3
type -s other-test-type3
# CHECK: other-test-type3 is a function (Defined via `source`, copied via `source`)
touch ./test
chmod +x ./test
if cygwin_noacl ./
# In `noacl` mounts, Cygwin relies on the file content to set the `x` bit
# and ignores `chmod`
echo "#!/bin/sh" >./test
else
touch ./test
chmod +x ./test
end
PATH=.:$PATH type -P test
# CHECK: ./test

View File

@@ -26,6 +26,9 @@ for ulimit_opt in $ulimit_opts
set found true
echo "Using $ulimit_opt to increase hard limit" >&2
ulimit -H $ulimit_opt (math $max + 1) >/dev/null
and if __fish_is_cygwin
echo "ulimit: Permission denied when changing resource of type 'Fake result for Cygwin'" >&2
end
break
end
if not set -q found

View File

@@ -2,6 +2,13 @@
# Test the umask command. In particular the symbolic modes since they've been
# broken for four years (see issue #738) at the time I added these tests.
# When a path is mounted with `noacl` on Cygwin, file permissions are simulated
# in part based on the umask value.
# So masking the user execution bit when /usr/bin is mounted `noacl` will also
# prevent standard commands from executing, including `/usr/bin/cut` used by
# the `umask` function.
cygwin_noacl /usr/bin/ && set noacl
# Establish a base line umask.
umask 027
umask
@@ -27,10 +34,15 @@ umask 0282
# each interaction and did not find any bugs in how bash or fish handled these
# scenarios.
#
umask 0777
umask a-r
umask
umask -S
if set -q noacl
echo 0777
echo u=,g=,o=
else
umask 0777
umask a-r
umask
umask -S
end
#CHECK: 0777
#CHECK: u=,g=,o=
@@ -41,10 +53,15 @@ umask -S
#CHECK: 0677
#CHECK: u=x,g=,o=
umask 777
umask g+rwx,o+x
umask
umask -S
if set -q noacl
echo 0706
echo u=,g=rwx,o=x
else
umask 777
umask g+rwx,o+x
umask
umask -S
end
#CHECK: 0706
#CHECK: u=,g=rwx,o=x
@@ -62,24 +79,39 @@ umask -S
#CHECK: 0444
#CHECK: u=wx,g=wx,o=wx
umask 0
umask ug-rx
umask
umask -S
if set -q noacl
echo 0550
echo u=w,g=w,o=rwx
else
umask 0
umask ug-rx
umask
umask -S
end
#CHECK: 0550
#CHECK: u=w,g=w,o=rwx
umask 777
umask u+r,g+w,o=rw
umask
umask -S
if set -q noacl
echo 0351
echo u=r,g=w,o=rw
else
umask 777
umask u+r,g+w,o=rw
umask
umask -S
end
#CHECK: 0351
#CHECK: u=r,g=w,o=rw
umask 777
umask =r,g+w,o+x,o-r
umask
umask -S
if set -q noacl
echo 0316
echo u=r,g=rw,o=x
else
umask 777
umask =r,g+w,o+x,o-r
umask
umask -S
end
#CHECK: 0316
#CHECK: u=r,g=rw,o=x

View File

@@ -0,0 +1,8 @@
function cygwin_noacl --description \
"Return 0 if a path does not support POSIX file permissions on Cygwin/MSYS,
return 1 otherwise"
set -q argv[1] || { echo "cygwin_noacl: missing path" >&2; exit 2 }
__fish_cygwin_noacl $argv[1]
end

View File

@@ -0,0 +1,12 @@
function cygwin_nosymlinks --description \
"Return 0 if Cygwin fakes symlinks, return 1 otherwise"
switch (__fish_uname)
case "MSYS*"
not string match -q "*winsymlinks*" -- "$MSYS"
case "CYGWIN*"
not string match -q "*winsymlinks*" -- "$CYGWIN"
case "*"
return 1
end
end

View File

@@ -1,3 +0,0 @@
function is_cygwin
string match -qr "^(MSYS|CYGWIN)" -- (uname)
end