fix(functions): dedupe conflicting paru/yay wrapper generators
__fish_config_sync_logging carried its own inferior copy of the paru/yay wrapper generator (tee-based, no PTY, no progress-bar rendering, hard-coded /usr/bin/paru|yay) alongside the canonical version-6 generators in conf.d/paru-wrapper.fish and conf.d/yay-wrapper.fish. Both wrote the same file with different version markers and the same misattributed provenance comment, so whichever ran last won and a subsequent C5 toggle would flip it back. See startup-latency-JOB-BRIEF-FINDINGS.md §2. __fish_config_sync_logging now delegates entirely to the canonical generators instead of carrying a copy: they already resolve the real binary via __fish_real_command (never /usr/bin-assumed) and independently gate on their own C2/C5 keys, covering both the enabled-regenerate and disabled-remove cases. One behavior change falls out of delegating rather than special-casing around it: a wrapper is no longer generated when C2 (paru-autoexec / yay-autoexec) is disabled, even if C5 logging is on. The removed sync-logging copy never checked C2, so it could reinstall a wrapper the user had explicitly turned auto-exec off for. Adds functions/_fish_source_scoped.fish: a small helper that runs source inside its own function-call boundary. source itself runs in the caller's scope, so a bare return inside a sourced conf.d guard (both files have several) would otherwise unwind whatever function called source directly -- verified with a minimal repro before relying on it. Routing through this helper contains the return to just that call, so calling paru's generator and then yay's actually reaches the second call. Manually verified end-to-end in an isolated HOME/XDG sandbox with a stubbed paru/yay: enable generates both v6 wrappers, disable removes both and drops the sentinel, re-enable regenerates them and clears the sentinel.
This commit is contained in:
@@ -28,84 +28,38 @@ function __fish_config_sync_logging --description 'Sync C5 logging state: sentin
|
||||
set config_home "$HOME/.config"
|
||||
end
|
||||
set -l sentinel "$config_home/fish/.logging_disabled"
|
||||
set -l paru_wrapper "$HOME/.local/bin/paru"
|
||||
set -l yay_wrapper "$HOME/.local/bin/yay"
|
||||
set -l wrapper_version 1
|
||||
|
||||
if __fish_config_op_enabled (status current-function)
|
||||
# Logging enabled: remove sentinel and regenerate wrappers if binaries exist
|
||||
# Logging enabled: remove sentinel
|
||||
rm -f $sentinel
|
||||
|
||||
# Restart tmux pipe-pane for the current pane if inside tmux
|
||||
_tmux_pipe_log
|
||||
|
||||
if test -x /usr/bin/paru
|
||||
mkdir -p (dirname $paru_wrapper)
|
||||
printf '%s\n' \
|
||||
'#!/usr/bin/env bash' \
|
||||
"# paru-wrapper-version: $wrapper_version" \
|
||||
'# Auto-generated by conf.d/paru-wrapper.fish — do not edit by hand.' \
|
||||
'# Tees paru output to a timestamped log file and prunes old ones.' \
|
||||
'set -o pipefail' \
|
||||
'' \
|
||||
'log_dir="${SCROLLBACK_HISTORY_DIR:-$HOME/.terminal_history}"' \
|
||||
'mkdir -p "$log_dir"' \
|
||||
'log_file="$log_dir/paru_$(date +%Y-%m-%d_%H-%M-%S).log"' \
|
||||
'' \
|
||||
'/usr/bin/paru "$@" 2>&1 | tee "$log_file"' \
|
||||
'' \
|
||||
'max_files="${SCROLLBACK_HISTORY_MAX_FILES:-100}"' \
|
||||
'mapfile -t logs < <(ls -1t "$log_dir"/paru_*.log 2>/dev/null)' \
|
||||
'excess=$(( ${#logs[@]} - max_files ))' \
|
||||
'for (( i = ${#logs[@]} - 1; i >= ${#logs[@]} - excess && i >= 0; i-- )); do' \
|
||||
' rm -f "${logs[$i]}"' \
|
||||
'done' \
|
||||
>$paru_wrapper
|
||||
chmod +x $paru_wrapper
|
||||
end
|
||||
|
||||
if test -x /usr/bin/yay
|
||||
mkdir -p (dirname $yay_wrapper)
|
||||
printf '%s\n' \
|
||||
'#!/usr/bin/env bash' \
|
||||
"# yay-wrapper-version: $wrapper_version" \
|
||||
'# Auto-generated by conf.d/yay-wrapper.fish — do not edit by hand.' \
|
||||
'# Tees yay output to a timestamped log file and prunes old ones.' \
|
||||
'set -o pipefail' \
|
||||
'' \
|
||||
'log_dir="${SCROLLBACK_HISTORY_DIR:-$HOME/.terminal_history}"' \
|
||||
'mkdir -p "$log_dir"' \
|
||||
'log_file="$log_dir/yay_$(date +%Y-%m-%d_%H-%M-%S).log"' \
|
||||
'' \
|
||||
'/usr/bin/yay "$@" 2>&1 | tee "$log_file"' \
|
||||
'' \
|
||||
'max_files="${SCROLLBACK_HISTORY_MAX_FILES:-100}"' \
|
||||
'mapfile -t logs < <(ls -1t "$log_dir"/yay_*.log 2>/dev/null)' \
|
||||
'excess=$(( ${#logs[@]} - max_files ))' \
|
||||
'for (( i = ${#logs[@]} - 1; i >= ${#logs[@]} - excess && i >= 0; i-- )); do' \
|
||||
' rm -f "${logs[$i]}"' \
|
||||
'done' \
|
||||
>$yay_wrapper
|
||||
chmod +x $yay_wrapper
|
||||
end
|
||||
else
|
||||
# Logging disabled: create sentinel and remove any generated wrappers
|
||||
# Logging disabled: create sentinel
|
||||
mkdir -p (dirname $sentinel)
|
||||
touch $sentinel
|
||||
|
||||
if test -f $paru_wrapper
|
||||
and grep -q "# paru-wrapper-version:" $paru_wrapper 2>/dev/null
|
||||
rm -f $paru_wrapper
|
||||
end
|
||||
|
||||
if test -f $yay_wrapper
|
||||
and grep -q "# yay-wrapper-version:" $yay_wrapper 2>/dev/null
|
||||
rm -f $yay_wrapper
|
||||
end
|
||||
|
||||
# Stop tmux pipe-pane for the current pane if inside tmux
|
||||
if set -q TMUX
|
||||
tmux pipe-pane 2>/dev/null
|
||||
end
|
||||
end
|
||||
|
||||
# Delegate paru/yay wrapper (re)generation and removal to the canonical
|
||||
# generators. They resolve the real binary via __fish_real_command
|
||||
# (never /usr/bin-assumed) and independently gate on their own C2/C5
|
||||
# keys, so sourcing them here covers both the enabled-regenerate and
|
||||
# disabled-remove cases without duplicating that logic. Previously this
|
||||
# function carried its own inferior copy (tee instead of a PTY, no
|
||||
# progress-bar rendering, hard-coded /usr/bin/paru|yay), which fought
|
||||
# the canonical generator for the wrapper file on every version-marker
|
||||
# mismatch. See startup-latency-JOB-BRIEF-FINDINGS.md §2.
|
||||
#
|
||||
# Routed through _fish_source_scoped: both files `return` early on
|
||||
# several guard checks, and a sourced `return` exits the *calling*
|
||||
# function, which would otherwise abort this function and skip
|
||||
# whichever of paru/yay hadn't run yet.
|
||||
_fish_source_scoped "$__fish_config_dir/conf.d/paru-wrapper.fish"
|
||||
_fish_source_scoped "$__fish_config_dir/conf.d/yay-wrapper.fish"
|
||||
end
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
# Copyright (C) 2026 Rootiest
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
# SYNOPSIS
|
||||
# _fish_source_scoped <file>
|
||||
#
|
||||
# DESCRIPTION
|
||||
# Sources <file> inside its own function-call boundary. `source` runs
|
||||
# in the caller's own scope, so a bare `return` in a sourced file --
|
||||
# used by several conf.d guards as an early exit -- would otherwise
|
||||
# unwind whatever function called `source` directly, not just the
|
||||
# sourced file. Calling through this helper contains it to here.
|
||||
#
|
||||
# ARGUMENTS
|
||||
# file Path to the fish script to source
|
||||
#
|
||||
# EXIT STATUS
|
||||
# 0 File does not exist (nothing to do)
|
||||
# Exit status of the sourced file otherwise
|
||||
#
|
||||
# EXAMPLE
|
||||
# _fish_source_scoped $__fish_config_dir/conf.d/paru-wrapper.fish
|
||||
function _fish_source_scoped --argument-names file
|
||||
test -f $file; or return 0
|
||||
source $file
|
||||
end
|
||||
Reference in New Issue
Block a user