Store timespec for buffer fs timestamps, not just time_t
time_t has a resolution of one second, which cause troubles when a file changes multiple time during that same second.
This commit is contained in:
parent
122a799ecb
commit
e2720f1fbe
|
@ -18,7 +18,7 @@ namespace Kakoune
|
|||
{
|
||||
|
||||
Buffer::Buffer(String name, Flags flags, BufferLines lines,
|
||||
time_t fs_timestamp)
|
||||
timespec fs_timestamp)
|
||||
: Scope(GlobalScope::instance()),
|
||||
m_name((flags & Flags::File) ? real_path(parse_filename(name)) : std::move(name)),
|
||||
m_display_name((flags & Flags::File) ? compact_path(m_name) : m_name),
|
||||
|
@ -160,7 +160,7 @@ struct Buffer::Modification
|
|||
}
|
||||
};
|
||||
|
||||
void Buffer::reload(BufferLines lines, time_t fs_timestamp)
|
||||
void Buffer::reload(BufferLines lines, timespec fs_timestamp)
|
||||
{
|
||||
if (lines.empty())
|
||||
lines.emplace_back(StringData::create("\n"));
|
||||
|
@ -531,13 +531,13 @@ ByteCoord Buffer::char_prev(ByteCoord coord) const
|
|||
return coord;
|
||||
}
|
||||
|
||||
time_t Buffer::fs_timestamp() const
|
||||
timespec Buffer::fs_timestamp() const
|
||||
{
|
||||
kak_assert(m_flags & Flags::File);
|
||||
return m_fs_timestamp;
|
||||
}
|
||||
|
||||
void Buffer::set_fs_timestamp(time_t ts)
|
||||
void Buffer::set_fs_timestamp(timespec ts)
|
||||
{
|
||||
kak_assert(m_flags & Flags::File);
|
||||
m_fs_timestamp = ts;
|
||||
|
|
|
@ -14,7 +14,7 @@ namespace Kakoune
|
|||
|
||||
class Buffer;
|
||||
|
||||
constexpr time_t InvalidTime = 0;
|
||||
constexpr timespec InvalidTime = { -1, -1 };
|
||||
|
||||
// A BufferIterator permits to iterate over the characters of a buffer
|
||||
class BufferIterator
|
||||
|
@ -79,7 +79,7 @@ public:
|
|||
};
|
||||
|
||||
Buffer(String name, Flags flags, BufferLines lines = {},
|
||||
time_t fs_timestamp = InvalidTime);
|
||||
timespec fs_timestamp = InvalidTime);
|
||||
Buffer(const Buffer&) = delete;
|
||||
Buffer& operator= (const Buffer&) = delete;
|
||||
~Buffer();
|
||||
|
@ -93,8 +93,8 @@ public:
|
|||
BufferIterator erase(BufferIterator begin, BufferIterator end);
|
||||
|
||||
size_t timestamp() const;
|
||||
time_t fs_timestamp() const;
|
||||
void set_fs_timestamp(time_t ts);
|
||||
timespec fs_timestamp() const;
|
||||
void set_fs_timestamp(timespec ts);
|
||||
|
||||
void commit_undo_group();
|
||||
bool undo();
|
||||
|
@ -152,7 +152,7 @@ public:
|
|||
|
||||
void run_hook_in_own_context(StringView hook_name, StringView param);
|
||||
|
||||
void reload(BufferLines lines, time_t fs_timestamp = InvalidTime);
|
||||
void reload(BufferLines lines, timespec fs_timestamp = InvalidTime);
|
||||
|
||||
void check_invariant() const;
|
||||
|
||||
|
@ -213,7 +213,7 @@ private:
|
|||
|
||||
Vector<Change, MemoryDomain::BufferMeta> m_changes;
|
||||
|
||||
time_t m_fs_timestamp;
|
||||
timespec m_fs_timestamp;
|
||||
|
||||
// Values are just data holding by the buffer, they are not part of its
|
||||
// observable state
|
||||
|
|
|
@ -47,7 +47,7 @@ ByteCount get_byte_to_column(const Buffer& buffer, CharCount tabstop, CharCoord
|
|||
}
|
||||
|
||||
Buffer* create_buffer_from_data(StringView data, StringView name,
|
||||
Buffer::Flags flags, time_t fs_timestamp)
|
||||
Buffer::Flags flags, timespec fs_timestamp)
|
||||
{
|
||||
bool bom = false, crlf = false;
|
||||
|
||||
|
@ -98,7 +98,7 @@ Buffer* create_fifo_buffer(String name, int fd, bool scroll)
|
|||
if (buffer)
|
||||
{
|
||||
buffer->flags() |= Buffer::Flags::NoUndo;
|
||||
buffer->reload({"\n"_ss}, 0);
|
||||
buffer->reload({"\n"_ss}, InvalidTime);
|
||||
}
|
||||
else
|
||||
buffer = new Buffer(std::move(name), Buffer::Flags::Fifo | Buffer::Flags::NoUndo);
|
||||
|
|
|
@ -34,7 +34,7 @@ Buffer* create_fifo_buffer(String name, int fd, bool scroll = false);
|
|||
|
||||
Buffer* create_buffer_from_data(StringView data, StringView name,
|
||||
Buffer::Flags flags,
|
||||
time_t fs_timestamp = InvalidTime);
|
||||
timespec fs_timestamp = InvalidTime);
|
||||
|
||||
void write_to_debug_buffer(StringView str);
|
||||
|
||||
|
|
|
@ -246,7 +246,7 @@ void Client::check_if_buffer_needs_reloading()
|
|||
return;
|
||||
|
||||
const String& filename = buffer.name();
|
||||
time_t ts = get_fs_timestamp(filename);
|
||||
timespec ts = get_fs_timestamp(filename);
|
||||
if (ts == InvalidTime or ts == buffer.fs_timestamp())
|
||||
return;
|
||||
if (reload == Ask)
|
||||
|
|
16
src/file.cc
16
src/file.cc
|
@ -180,13 +180,13 @@ Buffer* create_buffer_from_file(StringView filename)
|
|||
throw file_access_error(real_filename, "is a directory");
|
||||
if (S_ISFIFO(st.st_mode)) // Do not try to read fifos, use them as write only
|
||||
return create_buffer_from_data({}, real_filename,
|
||||
Buffer::Flags::File, st.st_mtime);
|
||||
Buffer::Flags::File, st.st_mtim);
|
||||
|
||||
const char* data = (const char*)mmap(nullptr, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
|
||||
auto unmap = on_scope_end([&]{ munmap((void*)data, st.st_size); });
|
||||
|
||||
return create_buffer_from_data({data, data + st.st_size}, real_filename,
|
||||
Buffer::Flags::File, st.st_mtime);
|
||||
Buffer::Flags::File, st.st_mtim);
|
||||
}
|
||||
|
||||
static void write(int fd, StringView data)
|
||||
|
@ -423,11 +423,11 @@ Vector<String> complete_command(StringView prefix, ByteCount cursor_pos)
|
|||
return res;
|
||||
}
|
||||
|
||||
typedef decltype(stat::st_mtime) TimeSpec;
|
||||
typedef decltype(stat::st_mtim) TimeSpec;
|
||||
|
||||
struct CommandCache
|
||||
{
|
||||
TimeSpec mtime = {};
|
||||
TimeSpec mtim = {};
|
||||
Vector<String> commands;
|
||||
};
|
||||
static UnorderedMap<String, CommandCache, MemoryDomain::Commands> command_cache;
|
||||
|
@ -442,7 +442,7 @@ Vector<String> complete_command(StringView prefix, ByteCount cursor_pos)
|
|||
continue;
|
||||
|
||||
auto& cache = command_cache[dirname];
|
||||
if (memcmp(&cache.mtime, &st.st_mtime, sizeof(TimeSpec)) != 0)
|
||||
if (memcmp(&cache.mtim, &st.st_mtim, sizeof(TimeSpec)) != 0)
|
||||
{
|
||||
auto filter = [&](const dirent& entry) {
|
||||
struct stat st;
|
||||
|
@ -457,7 +457,7 @@ Vector<String> complete_command(StringView prefix, ByteCount cursor_pos)
|
|||
};
|
||||
|
||||
cache.commands = list_files("", dirname, filter);
|
||||
memcpy(&cache.mtime, &st.st_mtime, sizeof(TimeSpec));
|
||||
memcpy(&cache.mtim, &st.st_mtim, sizeof(TimeSpec));
|
||||
}
|
||||
for (auto& cmd : cache.commands)
|
||||
{
|
||||
|
@ -471,12 +471,12 @@ Vector<String> complete_command(StringView prefix, ByteCount cursor_pos)
|
|||
return res;
|
||||
}
|
||||
|
||||
time_t get_fs_timestamp(StringView filename)
|
||||
timespec get_fs_timestamp(StringView filename)
|
||||
{
|
||||
struct stat st;
|
||||
if (stat(filename.zstr(), &st) != 0)
|
||||
return InvalidTime;
|
||||
return st.st_mtime;
|
||||
return st.st_mtim;
|
||||
}
|
||||
|
||||
String get_kak_binary_path()
|
||||
|
|
12
src/file.hh
12
src/file.hh
|
@ -52,7 +52,17 @@ Vector<String> list_files(StringView directory);
|
|||
|
||||
void make_directory(StringView dir);
|
||||
|
||||
time_t get_fs_timestamp(StringView filename);
|
||||
timespec get_fs_timestamp(StringView filename);
|
||||
|
||||
constexpr bool operator==(const timespec& lhs, const timespec& rhs)
|
||||
{
|
||||
return lhs.tv_sec == rhs.tv_sec and lhs.tv_nsec == rhs.tv_nsec;
|
||||
}
|
||||
|
||||
constexpr bool operator!=(const timespec& lhs, const timespec& rhs)
|
||||
{
|
||||
return not (lhs == rhs);
|
||||
}
|
||||
|
||||
CandidateList complete_filename(StringView prefix, const Regex& ignore_regex,
|
||||
ByteCount cursor_pos = -1);
|
||||
|
|
Loading…
Reference in New Issue
Block a user