From 5309b7b5e53c6d742a779bc82dcafe815de0dd56 Mon Sep 17 00:00:00 2001 From: Frank LENORMAND Date: Wed, 4 Jul 2018 09:49:53 +0300 Subject: [PATCH] src: Add a `-sync` flag to the write commands --- src/commands.cc | 60 +++++++++++++++++++++++++++++++++---------------- src/file.cc | 9 +++++--- src/file.hh | 4 ++-- 3 files changed, 49 insertions(+), 24 deletions(-) diff --git a/src/commands.cc b/src/commands.cc index b196f847..dec1edab 100644 --- a/src/commands.cc +++ b/src/commands.cc @@ -326,20 +326,25 @@ void write_buffer(const ParametersParser& parser, Context& context, const ShellC and (parser.positional_count() == 0 or real_path(parser[0]) == buffer.name())) throw runtime_error("cannot overwrite the buffer when in readonly mode"); + const bool sync_file = (bool)parser.get_switch("sync"); auto filename = parser.positional_count() == 0 ? buffer.name() : parse_filename(parser[0]); context.hooks().run_hook("BufWritePre", filename, context); - write_buffer_to_file(buffer, filename, force); + write_buffer_to_file(buffer, filename, force, sync_file); context.hooks().run_hook("BufWritePost", filename, context); } const CommandDesc write_cmd = { "write", "w", - "write [filename]: write the current buffer to its file " - "or to [filename] if specified", - single_optional_param, + "write [-sync] [filename]: write the current buffer to its file " + "or to [filename] if specified; the underlying file can be" + "synchronized with the filesystem with the -sync switch", + ParameterDesc{ + { { "sync", { false, "force the synchronization of the file onto the filesystem" } } }, + ParameterDesc::Flags::SwitchesOnlyAtStart, 0, 1 + }, CommandFlags::None, CommandHelper{}, filename_completer, @@ -349,16 +354,20 @@ const CommandDesc write_cmd = { const CommandDesc force_write_cmd = { "write!", "w!", - "write [filename]: write the current buffer to its file " - "or to [filename] if specified, even when the file is write protected", - single_optional_param, + "write [-sync] [filename]: write the current buffer to its file " + "or to [filename] if specified, even when the file is write protected;" + "the underlying file can be synchronized with the filesystem with the -sync switch", + ParameterDesc{ + { { "sync", { false, "force the synchronization of the file onto the filesystem" } } }, + ParameterDesc::Flags::SwitchesOnlyAtStart, 0, 1 + }, CommandFlags::None, CommandHelper{}, filename_completer, write_buffer, }; -void write_all_buffers(Context& context) +void write_all_buffers(Context& context, bool sync = false) { // Copy buffer list because hooks might be creating/deleting buffers Vector> buffers; @@ -373,7 +382,7 @@ void write_all_buffers(Context& context) and !(buffer->flags() & Buffer::Flags::ReadOnly)) { buffer->run_hook_in_own_context("BufWritePre", buffer->name(), context.name()); - write_buffer_to_file(*buffer, buffer->name()); + write_buffer_to_file(*buffer, buffer->name(), sync); buffer->run_hook_in_own_context("BufWritePost", buffer->name(), context.name()); } } @@ -382,12 +391,18 @@ void write_all_buffers(Context& context) const CommandDesc write_all_cmd = { "write-all", "wa", - "write all buffers that are associated to a file", - no_params, + "write-all [-sync]: write all buffers that are associated to a file;" + "all open files can be synchronized with the filesystem with the -sync switch", + ParameterDesc{ + { { "sync", { false, "force the synchronization of the file onto the filesystem" } } }, + ParameterDesc::Flags::None, 0, 0 + }, CommandFlags::None, CommandHelper{}, CommandCompleter{}, - [](const ParametersParser&, Context& context, const ShellContext&){ write_all_buffers(context); } + [](const ParametersParser& parser, Context& context, const ShellContext&){ + write_all_buffers(context, (bool)parser.get_switch("sync")); + } }; static void ensure_all_buffers_are_saved() @@ -486,9 +501,12 @@ void write_quit(const ParametersParser& parser, Context& context, const CommandDesc write_quit_cmd = { "write-quit", "wq", - "write current buffer and quit current client. An optional integer " - "parameter can set the client exit status", - { {}, ParameterDesc::Flags::SwitchesAsPositional, 0, 1 }, + "write-quit [-sync] [exit_code]: write current buffer and quit current client. An optional integer parameter can set the client exit status;" + "all open files can be synchronized with the filesystem with the -sync switch", + ParameterDesc{ + { { "sync", { false, "force the synchronization of the file onto the filesystem" } } }, + ParameterDesc::Flags::SwitchesOnlyAtStart, 0, 1 + }, CommandFlags::None, CommandHelper{}, CommandCompleter{}, @@ -510,15 +528,19 @@ const CommandDesc force_write_quit_cmd = { const CommandDesc write_all_quit_cmd = { "write-all-quit", "waq", - "write all buffers associated to a file and quit current client. An " - "optional integer parameter can set the client exit status", - { {}, ParameterDesc::Flags::SwitchesAsPositional, 0, 1 }, + "write-all-quit [-sync] [exit_code]: write all buffers associated to a file and quit current client." + "An optional integer parameter can set the client exit status;" + "all open files can be synchronized with the filesystem with the -sync switch", + ParameterDesc{ + { { "sync", { false, "force the synchronization of the file onto the filesystem" } } }, + ParameterDesc::Flags::SwitchesOnlyAtStart, 0, 0 + }, CommandFlags::None, CommandHelper{}, CommandCompleter{}, [](const ParametersParser& parser, Context& context, const ShellContext& shell_context) { - write_all_buffers(context); + write_all_buffers(context, (bool)parser.get_switch("sync")); quit(parser, context, shell_context); } }; diff --git a/src/file.cc b/src/file.cc index 8d067d6c..a71bdb55 100644 --- a/src/file.cc +++ b/src/file.cc @@ -257,7 +257,7 @@ void write(int fd, StringView data) } } -void write_buffer_to_fd(Buffer& buffer, int fd) +void write_buffer_to_fd(Buffer& buffer, int fd, bool sync) { auto eolformat = buffer.options()["eolformat"].get(); StringView eoldata; @@ -278,9 +278,12 @@ void write_buffer_to_fd(Buffer& buffer, int fd) write(fd, linedata.substr(0, linedata.length()-1)); write(fd, eoldata); } + + if (sync) + ::fsync(fd); } -void write_buffer_to_file(Buffer& buffer, StringView filename, bool force) +void write_buffer_to_file(Buffer& buffer, StringView filename, bool force, bool sync) { struct stat st; auto zfilename = filename.zstr(); @@ -306,7 +309,7 @@ void write_buffer_to_file(Buffer& buffer, StringView filename, bool force) { auto close_fd = on_scope_end([fd]{ close(fd); }); - write_buffer_to_fd(buffer, fd); + write_buffer_to_fd(buffer, fd, sync); } if ((buffer.flags() & Buffer::Flags::File) and diff --git a/src/file.hh b/src/file.hh index f5a8cf0b..963cbce2 100644 --- a/src/file.hh +++ b/src/file.hh @@ -51,8 +51,8 @@ struct MappedFile struct stat st {}; }; -void write_buffer_to_file(Buffer& buffer, StringView filename, bool force = false); -void write_buffer_to_fd(Buffer& buffer, int fd); +void write_buffer_to_file(Buffer& buffer, StringView filename, bool force = false, bool sync = false); +void write_buffer_to_fd(Buffer& buffer, int fd, bool sync = false); void write_buffer_to_backup_file(Buffer& buffer); String find_file(StringView filename, StringView buf_dir, ConstArrayView paths);