Fehler behoben: Umlaute, Latin-1, Fehlermeldungen, atomares Schreiben

Spaltennamen mit Umlauten in Ausdrücken, Latin-1-Dateien als UTF-8,
Fehler als eine Zeile (RDB_DEBUG=1 für Backtrace), Werte mit Tab oder
Zeilenumbruch abgelehnt, Tabellen und Indexe über Temp-Datei und rename,
update.rdb gibt den Satz bei Editorfehler zurück, sorttable -r stabil.
This commit is contained in:
wkh
2026-10-30 09:48:42 +01:00
parent 9f6c450492
commit 75c2424307
11 changed files with 164 additions and 42 deletions
+29
View File
@@ -46,9 +46,38 @@ module Rdb
COMMANDS[name] = Command.new(name, cmd.desc, cmd.syntax.sub(target, name), cmd.block)
end
# Write a file all at once: a temporary file next to it, then rename, so
# an interrupted run leaves the old file rather than half a new one.
def write_file(path, data)
path = File.realpath(path) if File.symlink?(path)
tmp = "#{path}.tmp#{Process.pid}"
File.binwrite(tmp, data)
File.chmod(File.stat(path).mode & 0o7777, tmp) if File.exist?(path)
File.rename(tmp, path)
ensure
File.delete(tmp) if tmp && File.exist?(tmp)
end
# A value is one cell of a tab-separated line: no tab, no line break.
def check_cells!(cells)
bad = cells.find { |c| c.to_s.match?(/[\t\r\n]/) }
die "value #{bad.to_s.inspect} contains a tab or line break" if bad
end
# Errors reach the user as one line; RDB_DEBUG=1 keeps the backtrace.
def run(name, args)
cmd = COMMANDS[name] or die("unknown command '#{name}'")
Env.new(name).instance_exec(args.dup, &cmd.block)
rescue Errno::EPIPE
exit 0
rescue Interrupt
exit 130
rescue SystemExit
raise
rescue StandardError => e
raise if ENV['RDB_DEBUG'].to_s.match?(/\A(1|yes|true)\z/i)
die("#{e.message} (#{e.class}; RDB_DEBUG=1 shows where)")
end
end
end