From e07b45f44724cb9686021757d16bfc03b98b6793 Mon Sep 17 00:00:00 2001 From: Fabian Homborg Date: Sat, 15 Dec 2018 11:13:38 +0100 Subject: [PATCH 1/9] Revert "completions/git: Allow aliases with whitespace in the command" This reverts commit 081e14fd213b99f0a28c71e801bf5f60a843be75, which was bogus. --- share/completions/git.fish | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/share/completions/git.fish b/share/completions/git.fish index ca8f24f75..60822fe49 100644 --- a/share/completions/git.fish +++ b/share/completions/git.fish @@ -445,7 +445,7 @@ end # So instead, we store the aliases in global variables, named after the alias, containing the command. # This is because alias:command is an n:1 mapping (an alias can only have one corresponding command, # but a command can be aliased multiple times) -git config -z --get-regexp 'alias\..*' | while read -lz alias command +git config -z --get-regexp 'alias\..*' | while read -lz alias command _ # Git aliases can contain chars that variable names can't - escape them. set alias (string replace 'alias.' '' -- $alias | string escape --style=var) set -g __fish_git_alias_$alias $command From 1f871c4d0c5c0e1e155bc5bf535a1bfc7ee866f9 Mon Sep 17 00:00:00 2001 From: Aaron Gyes Date: Fri, 14 Dec 2018 11:42:23 -0800 Subject: [PATCH 2/9] builtin_test.cpp: check for ERANGE and special fish_wcstoll errno We were not parsing an in-range number when we claimed we were, and were thus failing to error with invalid numbers and returned a wrong test result. Fixed #5414 Also, provide the detail we can for the other error cases. --- src/builtin_test.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/builtin_test.cpp b/src/builtin_test.cpp index 07ae926b9..07aa37356 100644 --- a/src/builtin_test.cpp +++ b/src/builtin_test.cpp @@ -657,7 +657,7 @@ static bool parse_number(const wcstring &arg, number_t *number, wcstring_list_t // invalid (e.g. not a representable integer). *number = number_t{integral, 0.0}; return true; - } else if (got_float) { + } else if (got_float && errno != ERANGE) { // Here we parsed an (in range) floating point value that could not be parsed as an integer. // Break the floating point value into base and delta. Ensure that base is <= the floating // point value. @@ -667,7 +667,11 @@ static bool parse_number(const wcstring &arg, number_t *number, wcstring_list_t return true; } else { // We could not parse a float or an int. - errors.push_back(format_string(_(L"invalid number '%ls'"), arg.c_str())); + // Check for special fish_wcsto* value or show standard EINVAL/ERANGE error. + if (errno == -1) + errors.push_back(format_string(_(L"Integer %lld in '%ls' followed by non-digit"), integral, argcs)); + else + errors.push_back(format_string(L"%s: '%ls'", strerror(errno), argcs)); return false; } } From b404b9392cac8e14314f757fbc72f7692df275bf Mon Sep 17 00:00:00 2001 From: Aaron Gyes Date: Fri, 14 Dec 2018 12:43:18 -0800 Subject: [PATCH 3/9] builtin_test.cpp: split a long line, add braces --- src/builtin_test.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/builtin_test.cpp b/src/builtin_test.cpp index 07aa37356..cac1167b2 100644 --- a/src/builtin_test.cpp +++ b/src/builtin_test.cpp @@ -668,10 +668,12 @@ static bool parse_number(const wcstring &arg, number_t *number, wcstring_list_t } else { // We could not parse a float or an int. // Check for special fish_wcsto* value or show standard EINVAL/ERANGE error. - if (errno == -1) - errors.push_back(format_string(_(L"Integer %lld in '%ls' followed by non-digit"), integral, argcs)); - else + if (errno == -1) { + errors.push_back(format_string(_(L"Integer %lld in '%ls' followed by non-digit"), + integral, argcs)); + } else { errors.push_back(format_string(L"%s: '%ls'", strerror(errno), argcs)); + } return false; } } From cf2b40040aaf8fa39d7e56657eab4e130e0a1026 Mon Sep 17 00:00:00 2001 From: Aaron Gyes Date: Sat, 15 Dec 2018 21:05:27 -0800 Subject: [PATCH 4/9] STATUS_INVALID_ARGS = 2 The rest of the high-numbered exit codes are not values used by scripts or builtins, they are internal to fish and come out of the parser for example. Prior to adding STATUS_INVALID_ARGS, builtins were usually exiting 2 if they had a special exit status for the situation of bad arguments. Set it to 2. --- src/common.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/common.h b/src/common.h index 83d6cd0ba..49a381f0f 100644 --- a/src/common.h +++ b/src/common.h @@ -1078,9 +1078,13 @@ enum { STATUS_CMD_OK = 0, /// The status code used for failure exit in a command (but not if the args were invalid). STATUS_CMD_ERROR = 1, + /// The status code used for invalid arguments given to a command. This is distinct from valid + /// arguments that might result in a command failure. An invalid args condition is something + /// like an unrecognized flag, missing or too many arguments, an invalid integer, etc. But + STATUS_INVALID_ARGS = 2, + /// The status code used when a command was not found. STATUS_CMD_UNKNOWN = 127, - /// TODO: Figure out why we have two distinct failure codes for when an external command cannot /// be run. /// @@ -1095,10 +1099,6 @@ enum { STATUS_ILLEGAL_CMD = 123, /// The status code used when `read` is asked to consume too much data. STATUS_READ_TOO_MUCH = 122, - /// The status code used for invalid arguments given to a command. This is distinct from valid - /// arguments that might result in a command failure. An invalid args condition is something - /// like an unrecognized flag, missing or too many arguments, an invalid integer, etc. But - STATUS_INVALID_ARGS = 121, }; /* Normally casting an expression to void discards its value, but GCC From 57d6124e6e925490f601d1b77cf1f72bf663c699 Mon Sep 17 00:00:00 2001 From: Aaron Gyes Date: Sat, 15 Dec 2018 22:05:19 -0800 Subject: [PATCH 5/9] builtin_test: don't exit 1 for eval errors, add tests for big args Return STATUS_INVALID_ARGS when failing due to evaluation errors, so we can tell the difference between an error and falseness. Add a test for the ERANGE error --- src/builtin_test.cpp | 15 +++++++++------ src/fish_tests.cpp | 23 ++++++++++++++++------- tests/test4.out | 2 +- 3 files changed, 26 insertions(+), 14 deletions(-) diff --git a/src/builtin_test.cpp b/src/builtin_test.cpp index cac1167b2..7284034a3 100644 --- a/src/builtin_test.cpp +++ b/src/builtin_test.cpp @@ -648,7 +648,6 @@ static bool parse_number(const wcstring &arg, number_t *number, wcstring_list_t const wchar_t *argcs = arg.c_str(); double floating = 0; bool got_float = parse_double(argcs, &floating); - errno = 0; long long integral = fish_wcstoll(argcs); bool got_int = (errno == 0); @@ -656,6 +655,7 @@ static bool parse_number(const wcstring &arg, number_t *number, wcstring_list_t // Here the value is just an integer; ignore the floating point parse because it may be // invalid (e.g. not a representable integer). *number = number_t{integral, 0.0}; + return true; } else if (got_float && errno != ERANGE) { // Here we parsed an (in range) floating point value that could not be parsed as an integer. @@ -664,6 +664,7 @@ static bool parse_number(const wcstring &arg, number_t *number, wcstring_list_t double intpart = std::floor(floating); double delta = floating - intpart; *number = number_t{static_cast(intpart), delta}; + return true; } else { // We could not parse a float or an int. @@ -835,7 +836,7 @@ int builtin_test(parser_t &parser, io_streams_t &streams, wchar_t **argv) { const wcstring_list_t args(argv + 1, argv + 1 + argc); if (argc == 0) { - return STATUS_CMD_ERROR; // Per 1003.1, exit false. + return STATUS_INVALID_ARGS; // Per 1003.1, exit false. } else if (argc == 1) { // Per 1003.1, exit true if the arg is non-empty. return args.at(0).empty() ? STATUS_CMD_ERROR : STATUS_CMD_OK; @@ -858,11 +859,13 @@ int builtin_test(parser_t &parser, io_streams_t &streams, wchar_t **argv) { wcstring_list_t eval_errors; bool result = expr->evaluate(eval_errors); - if (!eval_errors.empty() && !should_suppress_stderr_for_tests()) { - streams.err.append(L"test returned eval errors:\n"); - for (size_t i = 0; i < eval_errors.size(); i++) { - streams.err.append_format(L"\t%ls\n", eval_errors.at(i).c_str()); + if (!eval_errors.empty()) { + if (!should_suppress_stderr_for_tests()) { + for (size_t i = 0; i < eval_errors.size(); i++) { + streams.err.append_format(L"\t%ls\n", eval_errors.at(i).c_str()); + } } + return STATUS_INVALID_ARGS; } return result ? STATUS_CMD_OK : STATUS_CMD_ERROR; } diff --git a/src/fish_tests.cpp b/src/fish_tests.cpp index 02136d888..f60942542 100644 --- a/src/fish_tests.cpp +++ b/src/fish_tests.cpp @@ -2155,7 +2155,12 @@ static bool run_one_test_test(int expected, wcstring_list_t &lst, bool bracket) argv[i + 1] = NULL; io_streams_t streams(0); int result = builtin_test(parser, streams, argv); + + if (expected != result) + err(L"expected builtin_test() to return %d, got %d", expected, result); + delete[] argv; + return expected == result; } @@ -2207,13 +2212,13 @@ static void test_test() { do_test(run_test_test(0, L"' 2' -eq 2")); do_test(run_test_test(0, L"'2 ' -eq 2")); do_test(run_test_test(0, L"' 2 ' -eq 2")); - do_test(run_test_test(1, L"' 2x' -eq 2")); - do_test(run_test_test(1, L"'' -eq 0")); - do_test(run_test_test(1, L"'' -ne 0")); - do_test(run_test_test(1, L"' ' -eq 0")); - do_test(run_test_test(1, L"' ' -ne 0")); - do_test(run_test_test(1, L"'x' -eq 0")); - do_test(run_test_test(1, L"'x' -ne 0")); + do_test(run_test_test(2, L"' 2x' -eq 2")); + do_test(run_test_test(2, L"'' -eq 0")); + do_test(run_test_test(2, L"'' -ne 0")); + do_test(run_test_test(2, L"' ' -eq 0")); + do_test(run_test_test(2, L"' ' -ne 0")); + do_test(run_test_test(2, L"'x' -eq 0")); + do_test(run_test_test(2, L"'x' -ne 0")); do_test(run_test_test(1, L"-1 -ne -1")); do_test(run_test_test(0, L"abc != def")); do_test(run_test_test(1, L"abc = def")); @@ -2284,6 +2289,10 @@ static void test_test() { do_test(run_test_test(1, L"-4611686018427387904 -ge 4611686018427387904")); do_test(run_test_test(1, L"4611686018427387904 -gt 4611686018427387904")); do_test(run_test_test(0, L"4611686018427387904 -ge 4611686018427387904")); + + // test out-of-range numbers + do_test(run_test_test(2, L"99999999999999999999999999 -ge 1")); + do_test(run_test_test(2, L"1 -eq -99999999999999999999999999.9")); } static void test_wcstod() { diff --git a/tests/test4.out b/tests/test4.out index e0d388e26..a7af43eef 100644 --- a/tests/test4.out +++ b/tests/test4.out @@ -38,7 +38,7 @@ Test 22 pass 6 0 7 4 8 0 -9 121 +9 2 10 0 A 11 1 B From 14ee19cc1b60e426b6f86c7c8663660c339a805a Mon Sep 17 00:00:00 2001 From: Fabian Homborg Date: Tue, 18 Dec 2018 11:03:33 +0100 Subject: [PATCH 6/9] Use HAVE_WCSTOD_L also in header --- src/fallback.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fallback.h b/src/fallback.h index b0680de05..f8b7d4977 100644 --- a/src/fallback.h +++ b/src/fallback.h @@ -199,6 +199,6 @@ int flock(int fd, int op); #endif -#ifndef wcstod_l +#ifndef HAVE_WCSTOD_L double wcstod_l(const wchar_t *enptr, wchar_t **endptr, locale_t loc); #endif From d6e315d25db5c2a10b552cddd3aec93ce9398f26 Mon Sep 17 00:00:00 2001 From: David Adam Date: Thu, 20 Dec 2018 21:36:01 +0800 Subject: [PATCH 7/9] cmake: define _GNU_SOURCE Fixes the build on Cygwin. Analogous to AC_USE_SYSTEM_EXTENSIONS under Autoconf. Closes #5423. --- config_cmake.h.in | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/config_cmake.h.in b/config_cmake.h.in index 2c23ad452..d234acba9 100644 --- a/config_cmake.h.in +++ b/config_cmake.h.in @@ -142,6 +142,11 @@ /* Define to 1 if tparm accepts a fixed amount of paramters. */ #cmakedefine TPARM_SOLARIS_KLUDGE 1 +/* Enable GNU extensions on systems that have them. */ +#ifndef _GNU_SOURCE +# define _GNU_SOURCE 1 +#endif + /* The size of wchar_t in bits. */ #define WCHAR_T_BITS ${WCHAR_T_BITS} From 0c25d7a49c2f4fa24ed8ac6decf6210244b2f01f Mon Sep 17 00:00:00 2001 From: David Adam Date: Fri, 28 Dec 2018 20:56:17 +0800 Subject: [PATCH 8/9] CHANGELOG: 3.0.0 updates --- CHANGELOG.md | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5deaf80e4..c2efdde7e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,21 @@ +# fish 3.0.0 (released December 28, 2018) + +fish 3 is a major release, which introduces some breaking changes alongside improved functionality. Although most existing scripts will continue to work, they should be reviewed against the list contained in the 3.0b1 release notes below. + +Compared to the beta release of fish 3.0b1, fish version 3.0.0: + +- builds correctly against musl libc (#5407) +- handles huge numeric arguments to `test` correctly (#5414) +- removes the history colouring introduced in 3.0b1, which did not always work correctly + +There is one significant known issue which was not able to be corrected before the release: + +- fish 3.0.0 builds on Cygwin (#5423), but does not run correctly (#5426) and will result in a hanging terminal when started. Cygwin users are encouraged to continue using 2.7.1 until a release which corrects this is available. + +If you are upgrading from version 2.7.1 or before, please also review the release notes for 3.0b1 (included below). + +--- + # fish 3.0b1 (released December 11, 2018) fish 3 is a major release, which introduces some breaking changes alongside improved functionality. Although most existing scripts will continue to work, they should be reviewed against the list below. @@ -57,7 +75,7 @@ A new feature flags mechanism is added for staging deprecations and breaking cha - `exec` prompts for confirmation if background jobs are running. - `funced` has a new `--save` option to automatically save the edited function after successfully editing (#4668). - `functions` has a new ` --handlers` option to show functions registered as event handlers (#4694). -- `history search` supports globs for wildcard searching (#3136) and has a new `--reverse` option to show entries from oldest to newest (#4375).. +- `history search` supports globs for wildcard searching (#3136) and has a new `--reverse` option to show entries from oldest to newest (#4375). - `jobs` has a new `--quiet` option to silence the output. - `read` has a new `--delimiter` option for splitting input into arrays (#4256). - `read` writes directly to stdout if called without arguments (#4407). From 938ce48d259d1ceee51312b6b3e005fabfc07d1f Mon Sep 17 00:00:00 2001 From: David Adam Date: Fri, 28 Dec 2018 21:01:03 +0800 Subject: [PATCH 9/9] Bump version for 3.0.0 --- osx/Info.plist | 2 +- osx/config.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osx/Info.plist b/osx/Info.plist index ada78049b..2eb4b5a8e 100644 --- a/osx/Info.plist +++ b/osx/Info.plist @@ -17,7 +17,7 @@ CFBundlePackageType APPL CFBundleShortVersionString - 2.7.900 + 3.0.0 CFBundleVersion 0.1 LSApplicationCategoryType diff --git a/osx/config.h b/osx/config.h index d9f913647..d8036fee7 100644 --- a/osx/config.h +++ b/osx/config.h @@ -206,7 +206,7 @@ #define PACKAGE_NAME "fish" /* Define to the full name and version of this package. */ -#define PACKAGE_STRING "fish 3.0b1" +#define PACKAGE_STRING "fish 3.0.0" /* Define to the one symbol short name of this package. */ #define PACKAGE_TARNAME "fish" @@ -215,7 +215,7 @@ #define PACKAGE_URL "" /* Define to the version of this package. */ -#define PACKAGE_VERSION "3.0b1" +#define PACKAGE_VERSION "3.0.0" /* The size of `wchar_t', as computed by sizeof. */ #define SIZEOF_WCHAR_T 4