[lnav -i] write file to install to temp file

Related to #1240
pull/1242/head
Tim Stack 2 months ago
parent 53b0a606d6
commit b4b08fc3f5

@ -117,9 +117,12 @@ read_file(const ghc::filesystem::path& path)
}
}
Result<void, std::string>
write_file(const ghc::filesystem::path& path, const string_fragment& content)
Result<write_file_result, std::string>
write_file(const ghc::filesystem::path& path,
const string_fragment& content,
std::set<write_file_options> options)
{
write_file_result retval;
auto tmp_pattern = path;
tmp_pattern += ".XXXXXX";
@ -138,7 +141,25 @@ write_file(const ghc::filesystem::path& path, const string_fragment& content)
bytes_written,
content.length()));
}
std::error_code ec;
if (options.count(write_file_options::backup_existing)) {
if (ghc::filesystem::exists(path, ec)) {
auto backup_path = path;
backup_path += ".bak";
ghc::filesystem::rename(path, backup_path, ec);
if (ec) {
return Err(
fmt::format(FMT_STRING("unable to backup file {}: {}"),
path.string(),
ec.message()));
}
retval.wfr_backup_path = backup_path;
}
}
ghc::filesystem::rename(tmp_pair.first, path, ec);
if (ec) {
return Err(
@ -147,7 +168,7 @@ write_file(const ghc::filesystem::path& path, const string_fragment& content)
ec.message()));
}
return Ok();
return Ok(retval);
}
std::string

@ -30,6 +30,7 @@
#ifndef lnav_fs_util_hh
#define lnav_fs_util_hh
#include <set>
#include <string>
#include <vector>
@ -84,8 +85,18 @@ Result<std::pair<ghc::filesystem::path, auto_fd>, std::string> open_temp_file(
Result<std::string, std::string> read_file(const ghc::filesystem::path& path);
Result<void, std::string> write_file(const ghc::filesystem::path& path,
const string_fragment& content);
enum class write_file_options {
backup_existing,
};
struct write_file_result {
nonstd::optional<ghc::filesystem::path> wfr_backup_path;
};
Result<write_file_result, std::string> write_file(
const ghc::filesystem::path& path,
const string_fragment& content,
std::set<write_file_options> options = {});
std::string build_path(const std::vector<ghc::filesystem::path>& paths);

@ -2762,45 +2762,64 @@ SELECT tbl_name FROM sqlite_master WHERE sql LIKE 'CREATE VIRTUAL TABLE%'
? configs_installed_path
: formats_installed_path)
/ dst_name;
auto_fd in_fd, out_fd;
if ((in_fd = open(file_path.c_str(), O_RDONLY)) == -1) {
perror("unable to open file to install");
} else if ((out_fd = lnav::filesystem::openp(
dst_path, O_WRONLY | O_CREAT | O_TRUNC, 0644))
== -1)
{
fprintf(stderr,
"error: unable to open destination: %s -- %s\n",
dst_path.c_str(),
strerror(errno));
} else {
char buffer[2048];
ssize_t rc;
while ((rc = read(in_fd, buffer, sizeof(buffer))) > 0) {
ssize_t remaining = rc, written;
while (remaining > 0) {
written = write(out_fd, buffer, rc);
if (written == -1) {
fprintf(stderr,
"error: unable to install file "
"-- %s\n",
strerror(errno));
exit(EXIT_FAILURE);
}
auto read_res = lnav::filesystem::read_file(file_path);
if (read_res.isErr()) {
auto um = lnav::console::user_message::error(
attr_line_t("cannot read file to install -- ")
.append(lnav::roles::file(file_path)))
.with_reason(read_res.unwrap());
remaining -= written;
}
lnav::console::print(stderr, um);
return EXIT_FAILURE;
}
auto file_content = read_res.unwrap();
auto read_dst_res = lnav::filesystem::read_file(dst_path);
if (read_dst_res.isOk()) {
auto dst_content = read_dst_res.unwrap();
if (dst_content == file_content) {
auto um = lnav::console::user_message::info(
attr_line_t("file is already installed at -- ")
.append(lnav::roles::file(dst_path)));
lnav::console::print(stdout, um);
return EXIT_SUCCESS;
}
}
lnav::console::print(
stderr,
lnav::console::user_message::ok(
attr_line_t("installed -- ")
.append(lnav::roles::file(dst_path))));
auto write_res = lnav::filesystem::write_file(
dst_path,
file_content,
{lnav::filesystem::write_file_options::backup_existing});
if (write_res.isErr()) {
auto um = lnav::console::user_message::error(
attr_line_t("failed to install file to -- ")
.append(lnav::roles::file(dst_path)))
.with_reason(write_res.unwrapErr());
lnav::console::print(stderr, um);
return EXIT_FAILURE;
}
auto write_file_res = write_res.unwrap();
auto um = lnav::console::user_message::ok(
attr_line_t("installed -- ")
.append(lnav::roles::file(dst_path)));
if (write_file_res.wfr_backup_path) {
um.with_note(
attr_line_t("the previously installed ")
.append_quoted(
lnav::roles::file(dst_path.filename().string()))
.append(" was backed up to -- ")
.append(lnav::roles::file(
write_file_res.wfr_backup_path.value().string())));
}
lnav::console::print(stdout, um);
}
return EXIT_SUCCESS;
}

@ -278,6 +278,12 @@ EXPECTED_FILES = \
$(srcdir)/%reldir%/test_events.sh_d9c7907f907b2335e1328b23fdc46d0968a608d9.out \
$(srcdir)/%reldir%/test_events.sh_ed8dc44add223341c03ccb7b3e18371bdb42b710.err \
$(srcdir)/%reldir%/test_events.sh_ed8dc44add223341c03ccb7b3e18371bdb42b710.out \
$(srcdir)/%reldir%/test_format_installer.sh_1e08efc3b8c7b67d944a1f8c475cd31d98d5b4f6.err \
$(srcdir)/%reldir%/test_format_installer.sh_1e08efc3b8c7b67d944a1f8c475cd31d98d5b4f6.out \
$(srcdir)/%reldir%/test_format_installer.sh_6cd73153a8990b8ddb8ce489e90ec667a442f7f9.err \
$(srcdir)/%reldir%/test_format_installer.sh_6cd73153a8990b8ddb8ce489e90ec667a442f7f9.out \
$(srcdir)/%reldir%/test_format_installer.sh_947cbc64a150c7fe2a17e1c7a69e9a932aeaa16b.err \
$(srcdir)/%reldir%/test_format_installer.sh_947cbc64a150c7fe2a17e1c7a69e9a932aeaa16b.out \
$(srcdir)/%reldir%/test_format_loader.sh_15e861d2327512a721fd42ae51dc5427689e0bb6.err \
$(srcdir)/%reldir%/test_format_loader.sh_15e861d2327512a721fd42ae51dc5427689e0bb6.out \
$(srcdir)/%reldir%/test_format_loader.sh_5992e2695b7e6cf1f3520dbb87af8fc2b8f27088.err \

@ -0,0 +1,2 @@
✘ error: unable to open configuration file: /non-existent/file
reason: No such file or directory

@ -0,0 +1,2 @@
✔ installed -- ../installer-test-home/.lnav/formats/installed/test_log.json
 = note: the previously installed “test_log.json” was backed up to -- ../installer-test-home/.lnav/formats/installed/test_log.json.bak

@ -0,0 +1 @@
ⓘ info: file is already installed at -- ../installer-test-home/.lnav/formats/installed/test_log.json

@ -8,6 +8,7 @@ rm -rf "${CONFIG_DIR}/.lnav/formats"
HOME=${CONFIG_DIR}
unset XDG_CONFIG_HOME
export HOME
export YES_COLOR=1
${lnav_test} -i ${srcdir}/formats/jsontest/format.json
@ -16,6 +17,19 @@ if ! test -f ${CONFIG_DIR}/.lnav/formats/installed/test_log.json; then
exit 1
fi
run_cap_test ${lnav_test} -i ${srcdir}/formats/jsontest/format.json
echo corrupt > ${CONFIG_DIR}/.lnav/formats/installed/test_log.json
run_cap_test env TEST_COMMENT='overwrite file' ${lnav_test} -i ${srcdir}/formats/jsontest/format.json
if ! test -f ${CONFIG_DIR}/.lnav/formats/installed/test_log.json.bak; then
echo "Format not backed up correctly?"
exit 1
fi
run_cap_test ${lnav_test} -i /non-existent/file
if test x"${TEST_GIT_INSTALL}" = x""; then
# Hitting the git repos frequently is slow/noisy
exit 0

Loading…
Cancel
Save