Compare commits

...
Author SHA1 Message Date
ohmyzsh[bot] 06d207d8c3 chore(z): update to 7f8ff4df 2026-10-04 08:09:00 +00:00
3 changed files with 27 additions and 15 deletions

No files matched your search

+1 -1
View File
@@ -46,7 +46,7 @@ dependencies:
plugins/z:
branch: master
repo: agkozak/zsh-z
version: 102fb78036ed76feedf623907483691777a1d510
version: 7f8ff4df11b50a14e3666c7cd212baa399c9b92a
precopy: |
set -e
rm -r tests
+12 -1
View File
@@ -38,6 +38,17 @@ Zsh-z is a drop-in replacement for `rupa/z` and will, by default, use the same d
## News
### v2.0.1 (October 1, 2026)
- **Database writes now work with `setopt NO_CLOBBER`.** Under `NO_CLOBBER`,
every database write could fail with `can't clobber parameter tmpfd containing
file descriptor 0`, even when the database already existed. That error no longer
occurs ([#81](https://github.com/agkozak/zsh-z/issues/81)).
- **Database and lockfile creation now works with `setopt NO_CLOBBER`.** With
`NO_CLOBBER` set and `APPEND_CREATE` unset, Zsh-z could not create a missing
database or lockfile. It now creates them without changing your shell options or
losing existing directory history ([#105](https://github.com/agkozak/zsh-z/issues/105)).
### v2.0 (August 14, 2026)
Version **2.0** is a major step forward, and these are the changes most worth knowing about:
@@ -47,7 +58,7 @@ Version **2.0** is a major step forward, and these are the changes most worth kn
- **Safer, crash-resistant concurrent writes.** Writes are now guarded by a dedicated, stable lockfile using `zsh/system` file locking, with a bounded wait for lock acquisition (the new [`ZSHZ_LOCK_TIMEOUT`](#settings), default `1` second). Write errors are handled gracefully, and locks are always released even if a write is interrupted. On Cygwin and MSYS2 a write is also retried briefly if Windows refuses it: a virus scanner or the search indexer that opens the database in the instant between its being written and its being moved into place makes the move fail, which used to lose that one directory silently. Zsh-z now retries the move briefly.
- **Your database file now has `600` permissions** -- readable and writable only by you -- so that other users on a shared system cannot read your directory history ([#92](https://github.com/agkozak/zsh-z/issues/92)). On Zsh 5+ this uses the in-process `zf_chmod` builtin; on Zsh 4.3.11 it uses a `umask`-in-a-subshell technique that avoids the fork-and-exec of an external `chmod`.
- **`COMPLETE_ALIASES` works automatically in normal setups.** Tab completion no longer breaks when you have `setopt COMPLETE_ALIASES` enabled. Zsh-z registers the alias automatically on the first Tab press, so the manual `compdef` line that earlier versions required is no longer necessary. [See below](#complete_aliases).
- **Fixed a `can't clobber parameter tmpfd` error on some Zsh builds.** On certain Zsh builds, every database write could fail with `can't clobber parameter tmpfd containing file descriptor 0`, leaving an error at each new prompt. The file descriptor used for the temporary database file is now held in an unset scalar rather than one seeded with `0`, so the write never trips Zsh's file-descriptor-clobber guard ([#81](https://github.com/agkozak/zsh-z/issues/81)).
- **Fixed a `can't clobber parameter tmpfd` error on some Zsh builds.** On certain Zsh builds, every database write could fail with `can't clobber parameter tmpfd containing file descriptor 0`, leaving an error at each new prompt ([#81](https://github.com/agkozak/zsh-z/issues/81)). *Correction:* the error occurs under `setopt NO_CLOBBER`, and the v2.0 change did not fix it there; v2.0.1 does.
- **A misconfigured database file no longer closes your shell -- or nags you at every prompt.** When `ZSHZ_DATA` points at a directory, or names a file without a directory, Zsh-z now reports the problem and returns instead of calling `exit`. The per-prompt `--add` stays quiet about it, so you are told once, when you actually run `z`, rather than at every prompt ([#103](https://github.com/agkozak/zsh-z/issues/103); props @ahjota).
- **`z -x` can now remove the entry for a directory that no longer exists -- and can no longer crash Zsh 4.3.11.** The removal target used to have to exist on disk, so a database entry whose directory had been deleted -- exactly the entry you most want gone -- could not be removed. `z -x /deleted/dir` (and `z -xR`) now canonicalizes the argument without requiring it to exist, resolving symlinks in as much of the path as is still present. The same change fixes a crash on Zsh 4.3.11, where an upstream bug makes `${x:A}` segfault when the top-level component of the path is missing: `z -x /gone/sub` -- or a `ZSHZ_DATA` pointing into a missing top-level directory -- could kill the shell there.
- **More robust startup and operation.** A version check on an unsupported Zsh no longer risks exiting your interactive shell.
+14 -13
View File
@@ -371,16 +371,17 @@ zshz() {
# before the lock is taken, and on Cygwin/MSYS2 a concurrent writer's rename
# passes through a window in which the datafile is unlinked or delete-
# pending, so any second syscall on the path (chmod) -- or even the creating
# open itself -- can fail spuriously. Append mode (>>) creates the file
# without truncating one that a concurrent writer has just renamed into
# place. The first attempt is silent; if the file still does not exist
# open itself -- can fail spuriously. Forced append redirection (>>|) creates
# the file even under NO_CLOBBER with APPEND_CREATE disabled, without
# truncating one that a concurrent writer has just renamed into place.
# The first attempt is silent; if the file still does not exist
# afterward (so no concurrent writer supplied it), retry loudly so that real
# failures (directory permissions, read-only filesystem) reach the user.
[[ -f $datafile ]] || {
mkdir -p "${datafile:h}" &&
( umask 077; : >> "$datafile" ) 2> /dev/null ||
( umask 077; : >>| "$datafile" ) 2> /dev/null ||
[[ -f $datafile ]] ||
( umask 077; : >> "$datafile" )
( umask 077; : >>| "$datafile" )
# When $ZSHZ_OWNER is set (e.g. under `sudo -s'), hand the freshly created
# file off to that user immediately, so a query-only invocation can't leave
# behind a root-owned .z that the normal-user shell can't read. `-h' so a
@@ -525,14 +526,14 @@ zshz() {
# two-inodes race the stable lockfile exists to prevent.
# Under $ZSHZ_OWNER all of this runs with root's authority on a path the
# unprivileged owner controls, and every step follows a symlink: `-f'
# tests the target, `>>' creates a dangling one, and flock opens it.
# tests the target, `>>|' creates a dangling one, and flock opens it.
# $datafile survives a planted link only because the `mv' below replaces
# it outright; the lockfile is deliberately never removed, so a symlink
# here would persist and be acted on at every subsequent write. Refuse.
local _lock_owner=${ZSHZ_OWNER:-${_Z_OWNER}}
[[ -n $_lock_owner && -L $lockfile ]] && return 1
if [[ ! -f $lockfile ]]; then
( umask 077; : >> "$lockfile" ) 2> /dev/null
( umask 077; : >>| "$lockfile" ) 2> /dev/null
[[ -n $_lock_owner ]] &&
${ZSHZ[CHOWN]} -h "${_lock_owner}:$(id -ng "${_lock_owner}")" "$lockfile"
fi
@@ -585,13 +586,13 @@ zshz() {
# Discard entries that are incomplete or incorrectly formatted
lines=( ${(M)lines:#/*\|[[:digit:]]##[.,]#[[:digit:]]#\|[[:digit:]]##} )
# Hold the fd in an *unset* scalar, not `integer tmpfd' (which seeds it
# with 0). On some Zsh builds, `exec {tmpfd}>|...' refuses to clobber a
# parameter already holding a number that names an open fd -- and 0 is
# stdin, always open -- yielding "can't clobber parameter tmpfd
# containing file descriptor 0". An empty scalar isn't a valid fd, so
# the guard never fires. See https://github.com/agkozak/zsh-z/issues/81
# Explicitly unset the local scalar before allocating a file descriptor.
# Under NO_CLOBBER, even an empty scalar can be treated as fd 0 (stdin),
# causing `exec {tmpfd}>|...' to refuse to overwrite it. The `>|' only
# overrides file clobber protection, not the descriptor parameter check.
# See https://github.com/agkozak/zsh-z/issues/81
local tmpfd
unset tmpfd
case $action in
--add)
# When zf_chmod isn't available (Zsh 4.3.11), avoid the