Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion src/libcmd/repl-interacter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ extern "C" {
}
#endif

#include <fstream>

#include "nix/util/signals.hh"
#include "nix/util/finally.hh"
#include "nix/cmd/repl-interacter.hh"
Expand Down Expand Up @@ -119,8 +121,17 @@ ReadlineLikeInteracter::Guard ReadlineLikeInteracter::init(detail::ReplCompleter
}
#if !USE_READLINE
el_hist_size = 1000;
#endif
// editline's read_history uses a fixed 256-byte buffer (SCREEN_INC),
// which silently splits lines longer than 255 characters into separate
// history entries. Use std::getline instead, which has no length limit.
if (std::ifstream ifs(historyFile); ifs.good()) {
std::string line;
while (std::getline(ifs, line))
add_history(line.c_str());
}
#else
read_history(historyFile.c_str());
#endif
auto oldRepl = curRepl;
curRepl = repl;
Guard restoreRepl([oldRepl] { curRepl = oldRepl; });
Expand Down
25 changes: 24 additions & 1 deletion tests/repl-completion.nix
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@ runCommand "repl-completion"
}
exit 0
'';
passAsFile = [ "expectScript" ];
passAsFile = [
"expectScript"
];
}
''
export NIX_STORE=$TMPDIR/store
Expand All @@ -41,5 +43,26 @@ runCommand "repl-completion"

nix-store --init
expect $expectScriptPath

# Write a 300-char line to the history file, then run a REPL session
# that reads it back (read_history) and writes it out (write_history).
histFile=$HOME/.local/share/nix/repl-history
mkdir -p "$(dirname "$histFile")"
printf '%0300d\n' 0 | tr '0' 'a' > "$histFile"
echo "short" >> "$histFile"

# unbuffer allocates a pty so nix repl runs the interactive
# ReadlineLikeInteracter path (read_history on init, write_history
# on exit). Plain piped input skips history entirely.
echo ":q" | unbuffer -p nix repl --offline --extra-experimental-features nix-command 2>/dev/null || true

# Verify the long line survived the read/write cycle.
maxLen=$(awk '{ print length }' "$histFile" | sort -rn | head -1)
if [ "$maxLen" -lt 300 ]; then
echo "FAIL: long history line was truncated (max length: $maxLen)"
exit 1
fi
echo "Long history line preserved (length: $maxLen)."

touch $out
''
Loading