Clone of https://github.com/NixOS/nixpkgs.git (to stress-test knotserver)
at fix-function-merge 347 lines 14 kB view raw
1{ stdenv 2, lib 3, fetchurl 4, fetchpatch 5, coreutils 6, which 7, gnused 8, gnugrep 9, groff 10, gawk 11, man-db 12, getent 13, libiconv 14, pcre2 15, gettext 16, ncurses 17, python3 18, cmake 19, fishPlugins 20, procps 21 22# used to generate autocompletions from manpages and for configuration editing in the browser 23, usePython ? true 24 25, runCommand 26, writeText 27, nixosTests 28, nix-update-script 29, useOperatingSystemEtc ? true 30 # An optional string containing Fish code that initializes the environment. 31 # This is run at the very beginning of initialization. If it sets $NIX_PROFILES 32 # then Fish will use that to configure its function, completion, and conf.d paths. 33 # For example: 34 # fishEnvPreInit = "source /etc/fish/my-env-preinit.fish"; 35 # It can also be a function that takes one argument, which is a function that 36 # takes a path to a bash file and converts it to fish. For example: 37 # fishEnvPreInit = source: source "${nix}/etc/profile.d/nix-daemon.sh"; 38, fishEnvPreInit ? null 39}: 40let 41 etcConfigAppendix = writeText "config.fish.appendix" '' 42 ############### Nix hook for sourcing /etc/fish/config.fish ############### 43 # # 44 # Origin: 45 # This fish package was called with the attribute 46 # "useOperatingSystemEtc = true;". 47 # 48 # Purpose: 49 # Fish ordinarily sources /etc/fish/config.fish as 50 # $__fish_sysconfdir/config.fish, 51 # and $__fish_sysconfdir is defined at compile-time, baked into the C++ 52 # component of fish. By default, it is set to "/etc/fish". When building 53 # through Nix, $__fish_sysconfdir gets set to $out/etc/fish. Here we may 54 # have included a custom $out/etc/config.fish in the fish package, 55 # as specified, but according to the value of useOperatingSystemEtc, we 56 # may want to further source the real "/etc/fish/config.fish" file. 57 # 58 # When this option is enabled, this segment should appear the very end of 59 # "$out/etc/config.fish". This is to emulate the behavior of fish itself 60 # with respect to /etc/fish/config.fish and ~/.config/fish/config.fish: 61 # source both, but source the more global configuration files earlier 62 # than the more local ones, so that more local configurations inherit 63 # from but override the more global locations. 64 # 65 # Special care needs to be taken, when fish is called from an FHS user env 66 # or similar setup, because this configuration file will then be relocated 67 # to /etc/fish/config.fish, so we test for this case to avoid nontermination. 68 69 if test -f /etc/fish/config.fish && test /etc/fish/config.fish != (status filename) 70 source /etc/fish/config.fish 71 end 72 73 # # 74 ############### Nix hook for sourcing /etc/fish/config.fish ############### 75 ''; 76 77 fishPreInitHooks = writeText "__fish_build_paths_suffix.fish" '' 78 # source nixos environment 79 # note that this is required: 80 # 1. For all shells, not just login shells (mosh needs this as do some other command-line utilities) 81 # 2. Before the shell is initialized, so that config snippets can find the commands they use on the PATH 82 builtin status is-login 83 or test -z "$__fish_nixos_env_preinit_sourced" -a -z "$ETC_PROFILE_SOURCED" -a -z "$ETC_ZSHENV_SOURCED" 84 ${if fishEnvPreInit != null then '' 85 and begin 86 ${lib.removeSuffix "\n" (if lib.isFunction fishEnvPreInit then fishEnvPreInit sourceWithFenv else fishEnvPreInit)} 87 end'' else '' 88 and test -f /etc/fish/nixos-env-preinit.fish 89 and source /etc/fish/nixos-env-preinit.fish''} 90 and set -gx __fish_nixos_env_preinit_sourced 1 91 92 test -n "$NIX_PROFILES" 93 and begin 94 # We ensure that __extra_* variables are read in $__fish_datadir/config.fish 95 # with a preference for user-configured data by making sure the package-specific 96 # data comes last. Files are loaded/sourced in encounter order, duplicate 97 # basenames get skipped, so we assure this by prepending Nix profile paths 98 # (ordered in reverse of the $NIX_PROFILE variable) 99 # 100 # Note that at this point in evaluation, there is nothing whatsoever on the 101 # fish_function_path. That means we don't have most fish builtins, e.g., `eval`. 102 103 104 # additional profiles are expected in order of precedence, which means the reverse of the 105 # NIX_PROFILES variable (same as config.environment.profiles) 106 set -l __nix_profile_paths (string split ' ' $NIX_PROFILES)[-1..1] 107 108 set -p __extra_completionsdir \ 109 $__nix_profile_paths"/etc/fish/completions" \ 110 $__nix_profile_paths"/share/fish/vendor_completions.d" 111 set -p __extra_functionsdir \ 112 $__nix_profile_paths"/etc/fish/functions" \ 113 $__nix_profile_paths"/share/fish/vendor_functions.d" 114 set -p __extra_confdir \ 115 $__nix_profile_paths"/etc/fish/conf.d" \ 116 $__nix_profile_paths"/share/fish/vendor_conf.d" 117 end 118 ''; 119 120 # This is wrapped in begin/end in case the user wants to apply redirections. 121 # This does mean the basic usage of sourcing a single file will produce 122 # `begin; begin; …; end; end` but that's ok. 123 sourceWithFenv = path: '' 124 begin # fenv 125 # This happens before $__fish_datadir/config.fish sets fish_function_path, so it is currently 126 # unset. We set it and then completely erase it, leaving its configuration to $__fish_datadir/config.fish 127 set fish_function_path ${fishPlugins.foreign-env}/share/fish/vendor_functions.d $__fish_datadir/functions 128 fenv source ${lib.escapeShellArg path} 129 set -l fenv_status $status 130 # clear fish_function_path so that it will be correctly set when we return to $__fish_datadir/config.fish 131 set -e fish_function_path 132 test $fenv_status -eq 0 133 end # fenv 134 ''; 135 136 fish = stdenv.mkDerivation rec { 137 pname = "fish"; 138 version = "3.7.1"; 139 140 src = fetchurl { 141 # There are differences between the release tarball and the tarball GitHub 142 # packages from the tag. Specifically, it comes with a file containing its 143 # version, which is used in `build_tools/git_version_gen.sh` to determine 144 # the shell's actual version (and what it displays when running `fish 145 # --version`), as well as the local documentation for all builtins (and 146 # maybe other things). 147 url = "https://github.com/fish-shell/fish-shell/releases/download/${version}/${pname}-${version}.tar.xz"; 148 hash = "sha256-YUyfVkPNB5nfOROV+mu8NklCe7g5cizjsRTTu8GjslA="; 149 }; 150 151 # Fix FHS paths in tests 152 postPatch = '' 153 # src/fish_tests.cpp 154 sed -i 's|/bin/ls|${coreutils}/bin/ls|' src/fish_tests.cpp 155 sed -i 's|is_potential_path(L"/usr"|is_potential_path(L"/nix"|' src/fish_tests.cpp 156 sed -i 's|L"/bin/echo"|L"${coreutils}/bin/echo"|' src/fish_tests.cpp 157 sed -i 's|L"/bin/c"|L"${coreutils}/bin/c"|' src/fish_tests.cpp 158 sed -i 's|L"/bin/ca"|L"${coreutils}/bin/ca"|' src/fish_tests.cpp 159 # disable flakey test 160 sed -i '/{TEST_GROUP("history_races"), history_tests_t::test_history_races},/d' src/fish_tests.cpp 161 162 # tests/checks/cd.fish 163 sed -i 's|/bin/pwd|${coreutils}/bin/pwd|' tests/checks/cd.fish 164 165 # tests/checks/redirect.fish 166 sed -i 's|/bin/echo|${coreutils}/bin/echo|' tests/checks/redirect.fish 167 168 # tests/checks/vars_as_commands.fish 169 sed -i 's|/usr/bin|${coreutils}/bin|' tests/checks/vars_as_commands.fish 170 171 # tests/checks/jobs.fish 172 sed -i 's|ps -o stat|${procps}/bin/ps -o stat|' tests/checks/jobs.fish 173 sed -i 's|/bin/echo|${coreutils}/bin/echo|' tests/checks/jobs.fish 174 175 # tests/checks/job-control-noninteractive.fish 176 sed -i 's|/bin/echo|${coreutils}/bin/echo|' tests/checks/job-control-noninteractive.fish 177 178 # tests/checks/complete.fish 179 sed -i 's|/bin/ls|${coreutils}/bin/ls|' tests/checks/complete.fish 180 '' + lib.optionalString stdenv.isDarwin '' 181 # Tests use pkill/pgrep which are currently not built on Darwin 182 # See https://github.com/NixOS/nixpkgs/pull/103180 183 rm tests/pexpects/exit.py 184 rm tests/pexpects/job_summary.py 185 rm tests/pexpects/signals.py 186 187 # pexpect tests are flaky in general 188 # See https://github.com/fish-shell/fish-shell/issues/8789 189 rm tests/pexpects/bind.py 190 '' + lib.optionalString stdenv.isLinux '' 191 # pexpect tests are flaky on aarch64-linux (also x86_64-linux) 192 # See https://github.com/fish-shell/fish-shell/issues/8789 193 rm tests/pexpects/exit_handlers.py 194 ''; 195 196 outputs = [ "out" "doc" ]; 197 strictDeps = true; 198 nativeBuildInputs = [ 199 cmake 200 gettext 201 ]; 202 203 buildInputs = [ 204 ncurses 205 libiconv 206 pcre2 207 ]; 208 209 cmakeFlags = [ 210 "-DCMAKE_INSTALL_DOCDIR=${placeholder "doc"}/share/doc/fish" 211 ] ++ lib.optionals stdenv.isDarwin [ 212 "-DMAC_CODESIGN_ID=OFF" 213 ]; 214 215 # Fish’s test suite needs to be able to look up process information and send signals. 216 sandboxProfile = lib.optionalString stdenv.isDarwin '' 217 (allow mach-lookup mach-task-name) 218 (allow signal (target children)) 219 ''; 220 221 # The optional string is kind of an inelegant way to get fish to cross compile. 222 # Fish needs coreutils as a runtime dependency, and it gets put into 223 # CMAKE_PREFIX_PATH, which cmake uses to look up build time programs, so it 224 # was clobbering the PATH. It probably needs to be fixed at a lower level. 225 preConfigure = '' 226 patchShebangs ./build_tools/git_version_gen.sh 227 '' + lib.optionalString (stdenv.hostPlatform != stdenv.buildPlatform) '' 228 export CMAKE_PREFIX_PATH= 229 ''; 230 231 # Required binaries during execution 232 propagatedBuildInputs = [ 233 coreutils 234 gnugrep 235 gnused 236 groff 237 gettext 238 ] ++ lib.optional (!stdenv.isDarwin) man-db; 239 240 doCheck = true; 241 242 nativeCheckInputs = [ 243 coreutils 244 (python3.withPackages (ps: [ ps.pexpect ])) 245 procps 246 ]; 247 248 checkPhase = '' 249 make test 250 ''; 251 252 postInstall = with lib; '' 253 sed -r "s|command grep|command ${gnugrep}/bin/grep|" \ 254 -i "$out/share/fish/functions/grep.fish" 255 sed -e "s|\|cut|\|${coreutils}/bin/cut|" \ 256 -i "$out/share/fish/functions/fish_prompt.fish" 257 sed -e "s|uname|${coreutils}/bin/uname|" \ 258 -i "$out/share/fish/functions/__fish_pwd.fish" \ 259 "$out/share/fish/functions/prompt_pwd.fish" 260 sed -e "s|sed |${gnused}/bin/sed |" \ 261 -i "$out/share/fish/functions/alias.fish" \ 262 "$out/share/fish/functions/prompt_pwd.fish" 263 sed -i "s|nroff|${groff}/bin/nroff|" \ 264 "$out/share/fish/functions/__fish_print_help.fish" 265 sed -e "s|clear;|${getBin ncurses}/bin/clear;|" \ 266 -i "$out/share/fish/functions/fish_default_key_bindings.fish" 267 sed -i "s|/usr/local/sbin /sbin /usr/sbin||" \ 268 $out/share/fish/completions/{sudo.fish,doas.fish} 269 sed -e "s| awk | ${gawk}/bin/awk |" \ 270 -i $out/share/fish/functions/{__fish_print_packages.fish,__fish_print_addresses.fish,__fish_describe_command.fish,__fish_complete_man.fish,__fish_complete_convert_options.fish} \ 271 $out/share/fish/completions/{cwebp,adb,ezjail-admin,grunt,helm,heroku,lsusb,make,p4,psql,rmmod,vim-addons}.fish 272 273 '' + optionalString usePython '' 274 cat > $out/share/fish/functions/__fish_anypython.fish <<EOF 275 function __fish_anypython 276 echo ${python3.interpreter} 277 return 0 278 end 279 EOF 280 281 '' + optionalString stdenv.isLinux '' 282 for cur in $out/share/fish/functions/*.fish; do 283 sed -e "s|/usr/bin/getent|${getent}/bin/getent|" \ 284 -i "$cur" 285 done 286 287 '' + optionalString (!stdenv.isDarwin) '' 288 sed -i "s|Popen(\['manpath'|Popen(\['${man-db}/bin/manpath'|" \ 289 "$out/share/fish/tools/create_manpage_completions.py" 290 sed -i "s|command manpath|command ${man-db}/bin/manpath|" \ 291 "$out/share/fish/functions/man.fish" 292 '' + optionalString useOperatingSystemEtc '' 293 tee -a $out/etc/fish/config.fish < ${etcConfigAppendix} 294 '' + '' 295 tee -a $out/share/fish/__fish_build_paths.fish < ${fishPreInitHooks} 296 ''; 297 298 meta = with lib; { 299 description = "Smart and user-friendly command line shell"; 300 homepage = "https://fishshell.com/"; 301 changelog = "https://github.com/fish-shell/fish-shell/releases/tag/${version}"; 302 license = licenses.gpl2Only; 303 platforms = platforms.unix; 304 maintainers = with maintainers; [ adamcstephens cole-h winter ]; 305 mainProgram = "fish"; 306 }; 307 308 passthru = { 309 shellPath = "/bin/fish"; 310 tests = { 311 nixos = lib.optionalAttrs stdenv.isLinux nixosTests.fish; 312 313 # Test the fish_config tool by checking the generated splash page. 314 # Since the webserver requires a port to run, it is not started. 315 fishConfig = 316 let fishScript = writeText "test.fish" '' 317 set -x __fish_bin_dir ${fish}/bin 318 echo $__fish_bin_dir 319 cp -r ${fish}/share/fish/tools/web_config/* . 320 chmod -R +w * 321 322 # if we don't set `delete=False`, the file will get cleaned up 323 # automatically (leading the test to fail because there's no 324 # tempfile to check) 325 ${lib.getExe gnused} -e 's@, mode="w"@, mode="w", delete=False@' -i webconfig.py 326 327 # we delete everything after the fileurl is assigned 328 ${lib.getExe gnused} -e '/fileurl =/q' -i webconfig.py 329 echo "print(fileurl)" >> webconfig.py 330 331 # and check whether the message appears on the page 332 # cannot test the http server because it needs a localhost port 333 cat (${python3}/bin/python ./webconfig.py \ 334 | tail -n1 | ${lib.getExe gnused} -e 's|file://||' \ 335 ) | ${lib.getExe gnugrep} -q 'a href="http://localhost.*Start the Fish Web config' 336 ''; 337 in 338 runCommand "test-web-config" { } '' 339 HOME=$(mktemp -d) 340 ${fish}/bin/fish ${fishScript} && touch $out 341 ''; 342 }; 343 updateScript = nix-update-script { }; 344 }; 345 }; 346in 347fish