src: Reload buffers when their contents' hash changes
Instead of triggering a reload event when the timestamp of a buffer's underlying file changes, do so when its contents are actually modified.
This commit is contained in:
parent
936bd923ea
commit
e1bd076f5e
|
@ -78,7 +78,7 @@ Buffer::Buffer(String name, Flags flags, StringView data,
|
||||||
m_history{{HistoryId::Invalid}},
|
m_history{{HistoryId::Invalid}},
|
||||||
m_history_id{HistoryId::First},
|
m_history_id{HistoryId::First},
|
||||||
m_last_save_history_id{HistoryId::First},
|
m_last_save_history_id{HistoryId::First},
|
||||||
m_fs_timestamp{fs_timestamp.tv_sec, fs_timestamp.tv_nsec}
|
m_fs_status{fs_timestamp, data.length(), hash_value(data)}
|
||||||
{
|
{
|
||||||
ParsedLines parsed_lines = parse_lines(data);
|
ParsedLines parsed_lines = parse_lines(data);
|
||||||
|
|
||||||
|
@ -122,7 +122,7 @@ void Buffer::on_registered()
|
||||||
run_hook_in_own_context(Hook::BufNewFile, m_name);
|
run_hook_in_own_context(Hook::BufNewFile, m_name);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
kak_assert(m_fs_timestamp != InvalidTime);
|
kak_assert(m_fs_status.timestamp != InvalidTime);
|
||||||
run_hook_in_own_context(Hook::BufOpenFile, m_name);
|
run_hook_in_own_context(Hook::BufOpenFile, m_name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -305,7 +305,7 @@ void Buffer::reload(StringView data, timespec fs_timestamp)
|
||||||
apply_options(options(), parsed_lines);
|
apply_options(options(), parsed_lines);
|
||||||
|
|
||||||
m_last_save_history_id = m_history_id;
|
m_last_save_history_id = m_history_id;
|
||||||
m_fs_timestamp = fs_timestamp;
|
m_fs_status = {fs_timestamp, data.length(), hash_value(data)};
|
||||||
}
|
}
|
||||||
|
|
||||||
void Buffer::commit_undo_group()
|
void Buffer::commit_undo_group()
|
||||||
|
@ -607,7 +607,7 @@ void Buffer::notify_saved()
|
||||||
|
|
||||||
m_flags &= ~Flags::New;
|
m_flags &= ~Flags::New;
|
||||||
m_last_save_history_id = m_history_id;
|
m_last_save_history_id = m_history_id;
|
||||||
m_fs_timestamp = get_fs_timestamp(m_name);
|
m_fs_status.timestamp = get_fs_timestamp(m_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
BufferCoord Buffer::advance(BufferCoord coord, ByteCount count) const
|
BufferCoord Buffer::advance(BufferCoord coord, ByteCount count) const
|
||||||
|
@ -663,16 +663,16 @@ BufferCoord Buffer::char_prev(BufferCoord coord) const
|
||||||
return { coord.line, column };
|
return { coord.line, column };
|
||||||
}
|
}
|
||||||
|
|
||||||
timespec Buffer::fs_timestamp() const
|
void Buffer::set_fs_status(FsStatus status)
|
||||||
{
|
{
|
||||||
kak_assert(m_flags & Flags::File);
|
kak_assert(m_flags & Flags::File);
|
||||||
return m_fs_timestamp;
|
m_fs_status = std::move(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Buffer::set_fs_timestamp(timespec ts)
|
const FsStatus& Buffer::fs_status() const
|
||||||
{
|
{
|
||||||
kak_assert(m_flags & Flags::File);
|
kak_assert(m_flags & Flags::File);
|
||||||
m_fs_timestamp = ts;
|
return m_fs_status;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Buffer::on_option_changed(const Option& option)
|
void Buffer::on_option_changed(const Option& option)
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include "coord.hh"
|
#include "coord.hh"
|
||||||
#include "constexpr_utils.hh"
|
#include "constexpr_utils.hh"
|
||||||
#include "enum.hh"
|
#include "enum.hh"
|
||||||
|
#include "file.hh"
|
||||||
#include "optional.hh"
|
#include "optional.hh"
|
||||||
#include "safe_ptr.hh"
|
#include "safe_ptr.hh"
|
||||||
#include "scope.hh"
|
#include "scope.hh"
|
||||||
|
@ -141,9 +142,9 @@ public:
|
||||||
BufferCoord erase(BufferCoord begin, BufferCoord end);
|
BufferCoord erase(BufferCoord begin, BufferCoord end);
|
||||||
BufferCoord replace(BufferCoord begin, BufferCoord end, StringView content);
|
BufferCoord replace(BufferCoord begin, BufferCoord end, StringView content);
|
||||||
|
|
||||||
size_t timestamp() const;
|
size_t timestamp() const;
|
||||||
timespec fs_timestamp() const;
|
void set_fs_status(FsStatus);
|
||||||
void set_fs_timestamp(timespec ts);
|
const FsStatus& fs_status() const;
|
||||||
|
|
||||||
void commit_undo_group();
|
void commit_undo_group();
|
||||||
bool undo(size_t count = 1);
|
bool undo(size_t count = 1);
|
||||||
|
@ -284,7 +285,7 @@ private:
|
||||||
|
|
||||||
Vector<Change, MemoryDomain::BufferMeta> m_changes;
|
Vector<Change, MemoryDomain::BufferMeta> m_changes;
|
||||||
|
|
||||||
timespec m_fs_timestamp;
|
FsStatus m_fs_status;
|
||||||
|
|
||||||
// Values are just data holding by the buffer, they are not part of its
|
// Values are just data holding by the buffer, they are not part of its
|
||||||
// observable state
|
// observable state
|
||||||
|
|
|
@ -287,7 +287,7 @@ void Client::reload_buffer()
|
||||||
{
|
{
|
||||||
context().print_status({ format("error while reloading buffer: '{}'", error.what()),
|
context().print_status({ format("error while reloading buffer: '{}'", error.what()),
|
||||||
context().faces()["Error"] });
|
context().faces()["Error"] });
|
||||||
buffer.set_fs_timestamp(get_fs_timestamp(buffer.name()));
|
buffer.set_fs_status(get_fs_status(buffer.name()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -312,7 +312,7 @@ void Client::on_buffer_reload_key(Key key)
|
||||||
else if (key == 'n' or key == 'N' or key == Key::Escape)
|
else if (key == 'n' or key == 'N' or key == Key::Escape)
|
||||||
{
|
{
|
||||||
// reread timestamp in case the file was modified again
|
// reread timestamp in case the file was modified again
|
||||||
buffer.set_fs_timestamp(get_fs_timestamp(buffer.name()));
|
buffer.set_fs_status(get_fs_status(buffer.name()));
|
||||||
print_status({ format("'{}' kept", buffer.display_name()),
|
print_status({ format("'{}' kept", buffer.display_name()),
|
||||||
context().faces()["Information"] });
|
context().faces()["Information"] });
|
||||||
if (key == 'N')
|
if (key == 'N')
|
||||||
|
@ -354,9 +354,16 @@ void Client::check_if_buffer_needs_reloading()
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const String& filename = buffer.name();
|
const String& filename = buffer.name();
|
||||||
timespec ts = get_fs_timestamp(filename);
|
const timespec ts = get_fs_timestamp(filename);
|
||||||
if (ts == InvalidTime or ts == buffer.fs_timestamp())
|
const auto status = buffer.fs_status();
|
||||||
|
|
||||||
|
if (ts == InvalidTime or ts == status.timestamp)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (MappedFile fd{filename};
|
||||||
|
fd.st.st_size == status.file_size and hash_data(fd.data, fd.st.st_size) == status.hash)
|
||||||
|
return;
|
||||||
|
|
||||||
if (reload == Autoreload::Ask)
|
if (reload == Autoreload::Ask)
|
||||||
{
|
{
|
||||||
StringView bufname = buffer.display_name();
|
StringView bufname = buffer.display_name();
|
||||||
|
|
|
@ -610,6 +610,13 @@ timespec get_fs_timestamp(StringView filename)
|
||||||
return st.st_mtim;
|
return st.st_mtim;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FsStatus get_fs_status(StringView filename)
|
||||||
|
{
|
||||||
|
MappedFile fd{filename};
|
||||||
|
|
||||||
|
return {fd.st.st_mtim, fd.st.st_size, hash_data(fd.data, fd.st.st_size)};
|
||||||
|
}
|
||||||
|
|
||||||
String get_kak_binary_path()
|
String get_kak_binary_path()
|
||||||
{
|
{
|
||||||
char buffer[2048];
|
char buffer[2048];
|
||||||
|
|
|
@ -86,7 +86,15 @@ Vector<String> list_files(StringView directory);
|
||||||
|
|
||||||
void make_directory(StringView dir, mode_t mode);
|
void make_directory(StringView dir, mode_t mode);
|
||||||
|
|
||||||
|
struct FsStatus
|
||||||
|
{
|
||||||
|
timespec timestamp;
|
||||||
|
ByteCount file_size;
|
||||||
|
size_t hash;
|
||||||
|
};
|
||||||
|
|
||||||
timespec get_fs_timestamp(StringView filename);
|
timespec get_fs_timestamp(StringView filename);
|
||||||
|
FsStatus get_fs_status(StringView filename);
|
||||||
|
|
||||||
constexpr bool operator==(const timespec& lhs, const timespec& rhs)
|
constexpr bool operator==(const timespec& lhs, const timespec& rhs)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue
Block a user