Skip to content

Commit e9b0074

Browse files
committed
chore(release): 2.9.0 — the plugin release
A minor bump, not a patch: `cd -q` is new behaviour in the zsh dialect, and the crash it sits next to made the default plugin set unusable for anyone who typed `man`. Verified from a clean tree before tagging: norminette clean; debug (SAFE=1) and release OPT=1 both build with -Werror; the golden suite green on the debug build and again on the release build; the whole-script corpus (114) and the hard corpus (17) green; the full pty suite green by discovery; help, cli-opts, login, cd-posix, user-install and update-config gates green; the plugin corpus and the new framework gate green on both the release and the ASan build; and verify_alloc green -- byte-identical output on both heaps, no leaks on either.
1 parent b2ec099 commit e9b0074

3 files changed

Lines changed: 78 additions & 2 deletions

File tree

‎RELEASE.md‎

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,82 @@ shows you how to drive the shell.
88

99
---
1010

11+
## v2.9.0 — *the plugin release*
12+
13+
`man bash` killed the shell. Not an edge case anyone contrived: a stock
14+
install with the default plugins on, the first time you read a manual
15+
page. oh-my-zsh's colored-man-pages wraps `man` in a function that builds
16+
an environment array — `environment+=( PAGER="${commands[less]:-$PAGER}" )`
17+
— and hellish took a SIGSEGV on the array element, took the interactive
18+
shell down with it, and left the user at exit 139.
19+
20+
The plugin was innocent, and so was zsh. The bug was that
21+
`reparse_assignment_words` promotes **every** word shaped like
22+
`NAME=value` to an assignment node, wherever it stands, but only a simple
23+
command's own children were ever converted back to plain words. A word in
24+
a `for` list or inside an array literal therefore reached `split_words`
25+
still shaped as an assignment — a node whose second child is another word,
26+
where the splitter asserts every child is a token. `for x in A=1`,
27+
`e=( A=1 )` and `arr+=( K=$v )` all crashed, in both dialects, on both
28+
allocators, for as long as array literals have split like bash.
29+
30+
- **An assignment-shaped word outside command position is a plain word**,
31+
which is what bash has always made of it: `for x in A=$V` splits and
32+
globs like any other word. One helper, `clone_as_word`, flattens the
33+
node on the way into the three read-only expansion drivers, and the
34+
fast path no longer reaches inside a node it cannot read.
35+
- **`A=1 e=( B=$A )` sees `A`.** Array elements now expand with the
36+
command's earlier pre-assignments temporarily applied, exactly as the
37+
scalar path already did; before, they read the old environment and
38+
stored `B=`.
39+
- **`cd -q` works in the zsh dialect.** It is zsh's flag for moving
40+
without firing the chpwd hooks, and extract — also on by default — runs
41+
`builtin cd -q` four times, including the one that returns you to the
42+
directory you started in. Every archive it opened printed
43+
`cd: -q: invalid option`. It stays rejected in bash mode, because bash
44+
rejects it and the golden suite exists to say so.
45+
46+
### The gap that let it ship
47+
48+
The plugin corpus said colored-man-pages was fine, and it was right: the
49+
file *loaded*, silently, defining its four functions. Nothing ever
50+
**ran** what it defined. Sourcing a wrapper is not calling it, and the
51+
whole point of that plugin is the `man` you type afterwards.
52+
53+
- `tests/assign_shaped_words`: 46 bash-diffed cases — for-lists, array
54+
literals, append, quoting, globs, tildes, command substitution,
55+
`local -a`, `declare -a`, pre-assignment visibility, and the exact
56+
idiom the plugin uses.
57+
- `tests/hxp_framework_test.py`: the configuration a user actually ends
58+
up with, not one file at a time. It installs the framework into a
59+
throwaway `HOME` (from a checkout, an installed `~/.hellish`, or a
60+
cached tarball — and skips out loud when it has none), loads it, runs
61+
its own suite, answers every management command, then **uses** what the
62+
plugins define. It fails on the old binary with SIGSEGV, four ways.
63+
- The plugin corpus grew an exercise step: a row may now name one command
64+
that goes through the code the plugin left behind, skipped by name when
65+
the external it needs is missing rather than passing in silence.
66+
- `cd -q` is covered on both sides: the bash-mode rejection in the golden
67+
suite, the zsh behaviour (including that `-q` suppresses chpwd while a
68+
plain `cd` does not) against a real zsh in `make cd-zsh-test`.
69+
- `make hxp-test` runs the framework gate on its own; `make
70+
plugin-corpus` and CI run it on both the release and the ASan build.
71+
72+
### Also here
73+
74+
- The dead `incs/sh_state.h` is gone: a second, 22-field `t_shell` that
75+
nothing had included for a long time, and that a reader could easily
76+
mistake for the real one in `incs/shell.h`.
77+
- Five module READMEs (`builtins`, `core`, `environment`, `helpers`,
78+
`lexer`) match the code again. They still called the project sh42,
79+
listed seven builtins where the table registers around seventy, claimed
80+
`env` was one, quoted the obsolete struct, and named functions
81+
(`execute_ast`, `xgetpid`, `longest_matching_str`) that no longer
82+
exist. `helpers` said nothing at all about the parse arena or the word
83+
slab, which is most of what that directory is.
84+
85+
---
86+
1187
## v2.8.10 — *the wait release*
1288

1389
The arm64 rung kept failing one golden case after 2.8.9's process-group

‎incs/version.h‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515

1616
/* The single source of truth for the running shell's version. Bumped in step
1717
with the git tag / GitHub release / npm package / docker image. */
18-
# define HELLISH_VERSION "2.8.10"
18+
# define HELLISH_VERSION "2.9.0"
1919

2020
/* Where releases live; used by the `update` builtin and the daily check. */
2121
# define HELLISH_REPO "Univers42/hellish"

‎npm/package.json‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "hellish-shell",
3-
"version": "2.8.10",
3+
"version": "2.9.0",
44
"description": "hellish — a fast, POSIX-compliant shell, with horns",
55
"bin": {
66
"hellish": "bin/hellish.js"

0 commit comments

Comments
 (0)