#include "Util.hpp"
#include <core/exceptions.hpp>
+#include <util/file.hpp>
#include <util/string.hpp>
Args::Args(Args&& other) noexcept : m_args(std::move(other.m_args))
std::optional<Args>
Args::from_atfile(const std::string& filename, AtFileFormat format)
{
- std::string argtext;
- try {
- argtext = Util::read_text_file(filename);
- } catch (core::Error&) {
+ const auto argtext = util::read_file<std::string>(filename);
+ if (!argtext) {
return std::nullopt;
}
Args args;
- auto pos = argtext.c_str();
+ auto pos = argtext->c_str();
std::string argbuf;
- argbuf.resize(argtext.length() + 1);
+ argbuf.resize(argtext->length() + 1);
auto argpos = argbuf.begin();
// Used to track quoting state; if \0 we are not inside quotes. Otherwise
#pragma once
#include "NonCopyable.hpp"
-#include "Util.hpp"
#include <deque>
#include <optional>
#include <string>
#include <string_view>
+#include <vector>
class Args
{
#include <core/exceptions.hpp>
#include <core/wincompat.hpp>
#include <util/expected.hpp>
+#include <util/file.hpp>
#include <util/path.hpp>
#include <util/string.hpp>
const auto st = Stat::stat(resolved_path);
if (!st) {
Util::ensure_dir_exists(Util::dir_name(resolved_path));
- try {
- Util::write_file(resolved_path, "");
- } catch (const core::Error& e) {
- throw core::Error("failed to write to {}: {}", resolved_path, e.what());
+ const auto result = util::write_file(resolved_path, "");
+ if (!result) {
+ throw core::Error(
+ "failed to write to {}: {}", resolved_path, result.error());
}
}
#pragma once
#include "NonCopyable.hpp"
-#include "Util.hpp"
#include <core/Sloppiness.hpp>
#include "assertions.hpp"
#include <core/exceptions.hpp>
+#include <util/file.hpp>
#include <util/path.hpp>
#include <algorithm>
}
const std::string& output_dep = ctx.args_info.output_dep;
- std::string file_content;
- try {
- file_content = Util::read_file(output_dep);
- } catch (const core::Error& e) {
- LOG("Cannot open dependency file {}: {}", output_dep, e.what());
+ const auto file_content = util::read_file<std::string>(output_dep);
+ if (!file_content) {
+ LOG("Cannot open dependency file {}: {}", output_dep, file_content.error());
return;
}
- const auto new_content = rewrite_source_paths(ctx, file_content);
+ const auto new_content = rewrite_source_paths(ctx, *file_content);
if (new_content) {
- Util::write_file(output_dep, *new_content);
+ util::write_file(output_dep, *new_content);
} else {
LOG("No paths in dependency file {} made relative", output_dep);
}
#include "fmtmacros.hpp"
#include <core/wincompat.hpp>
+#include <util/file.hpp>
#include <fcntl.h>
#include <sys/stat.h>
return *this;
}
-bool
+nonstd::expected<void, std::string>
Hash::hash_fd(int fd)
{
- return Util::read_fd(
+ return util::read_fd(
fd, [this](const void* data, size_t size) { hash(data, size); });
}
-bool
+nonstd::expected<void, std::string>
Hash::hash_file(const std::string& path)
{
Fd fd(open(path.c_str(), O_RDONLY | O_BINARY));
if (!fd) {
LOG("Failed to open {}: {}", path, strerror(errno));
- return false;
+ return nonstd::make_unexpected(strerror(errno));
}
- bool ret = hash_fd(*fd);
- return ret;
+ return hash_fd(*fd);
}
void
#include "Digest.hpp"
#include "third_party/blake3/blake3.h"
+#include <third_party/nonstd/expected.hpp>
#include <cstdint>
#include <cstdio>
// text input file followed by a newline.
Hash& hash(int64_t x);
- // Add contents read from an open file descriptor to the hash.
+ // Add file contents to the hash.
//
// If hash debugging is enabled, the data is written verbatim to the text
// input file.
- //
- // Returns true on success, otherwise false.
- bool hash_fd(int fd);
+ nonstd::expected<void, std::string> hash_file(const std::string& path);
- // Add file contents to the hash.
+ // Add contents read from an open file descriptor to the hash.
//
// If hash debugging is enabled, the data is written verbatim to the text
// input file.
- //
- // Returns true on success, otherwise false.
- bool hash_file(const std::string& path);
+ nonstd::expected<void, std::string> hash_fd(int fd);
// Add `text` to the text debug file.
void add_debug_text(std::string_view text);
#include <core/exceptions.hpp>
#include <core/wincompat.hpp>
+#include <util/file.hpp>
#include <fcntl.h>
#include <sys/stat.h>
{
ASSERT(m_dest_fd);
- try {
- Util::write_fd(*m_dest_fd, data, size);
- } catch (core::Error& e) {
- throw core::Error("Failed to write to {}: {}", m_dest_path, e.what());
+ const auto result = util::write_fd(*m_dest_fd, data, size);
+ if (!result) {
+ throw core::Error("Failed to write to {}: {}", m_dest_path, result.error());
}
}
|| (m_dest_file_type == FileType::dependency && !m_dest_path.empty())) {
m_dest_data.append(reinterpret_cast<const char*>(data), size);
} else if (m_dest_fd) {
- try {
- Util::write_fd(*m_dest_fd, data, size);
- } catch (core::Error& e) {
- throw WriteError(FMT("Failed to write to {}: {}", m_dest_path, e.what()));
+ const auto result = util::write_fd(*m_dest_fd, data, size);
+ if (!result) {
+ throw WriteError(
+ FMT("Failed to write to {}: {}", m_dest_path, result.error()));
}
}
}
ResultRetriever::write_dependency_file()
{
ASSERT(m_ctx.args_info.dependency_target);
- const auto& dep_target = *m_ctx.args_info.dependency_target;
-
- try {
- size_t start_pos = 0;
- const size_t colon_pos = m_dest_data.find(": ");
- if (colon_pos != std::string::npos) {
- const auto obj_in_dep_file =
- std::string_view(m_dest_data).substr(0, colon_pos);
- if (obj_in_dep_file != dep_target) {
- Util::write_fd(*m_dest_fd, dep_target.data(), dep_target.length());
- start_pos = colon_pos;
- }
- }
- Util::write_fd(*m_dest_fd,
- m_dest_data.data() + start_pos,
- m_dest_data.length() - start_pos);
- } catch (core::Error& e) {
- throw WriteError(FMT("Failed to write to {}: {}", m_dest_path, e.what()));
+ auto write_data = [&](auto data, auto size) {
+ const auto result = util::write_fd(*m_dest_fd, data, size);
+ if (!result) {
+ throw WriteError(
+ FMT("Failed to write to {}: {}", m_dest_path, result.error()));
+ }
+ };
+
+ size_t start_pos = 0;
+ const size_t colon_pos = m_dest_data.find(": ");
+ if (colon_pos != std::string::npos) {
+ const auto obj_in_dep_file =
+ std::string_view(m_dest_data).substr(0, colon_pos);
+ const auto& dep_target = *m_ctx.args_info.dependency_target;
+ if (obj_in_dep_file != dep_target) {
+ write_data(dep_target.data(), dep_target.length());
+ start_pos = colon_pos;
+ }
}
+
+ write_data(m_dest_data.data() + start_pos, m_dest_data.length() - start_pos);
}
#include <Finalizer.hpp>
#include <core/exceptions.hpp>
#include <core/wincompat.hpp>
+#include <util/file.hpp>
#include <util/path.hpp>
#include <util/string.hpp>
void
copy_fd(int fd_in, int fd_out)
{
- read_fd(fd_in,
- [=](const void* data, size_t size) { write_fd(fd_out, data, size); });
+ util::read_fd(fd_in, [=](const void* data, size_t size) {
+ util::write_fd(fd_out, data, size);
+ });
}
void
}
int err = 0;
try {
- write_fd(fd, buf, bytes_to_write);
+ util::write_fd(fd, buf, bytes_to_write);
} catch (core::Error&) {
err = errno;
}
text_to_send = &modified_text;
}
- try {
- write_fd(fd, text_to_send->data(), text_to_send->length());
- } catch (core::Error& e) {
- throw core::Error("Failed to write to {}: {}", fd, e.what());
+ const auto result =
+ util::write_fd(fd, text_to_send->data(), text_to_send->length());
+ if (!result) {
+ throw core::Error("Failed to write to {}: {}", fd, result.error());
}
}
#include <core/wincompat.hpp>
#include <storage/Storage.hpp>
#include <util/expected.hpp>
+#include <util/file.hpp>
#include <util/path.hpp>
#include <util/string.hpp>
static nonstd::expected<void, Failure>
process_preprocessed_file(Context& ctx, Hash& hash, const std::string& path)
{
- std::string data;
- try {
- data = Util::read_file(path);
- } catch (core::Error&) {
+ auto data = util::read_file<std::string>(path);
+ if (!data) {
+ LOG("Failed reading {}: {}", path, data.error());
return nonstd::make_unexpected(Statistic::internal_error);
}
// Bytes between p and q are pending to be hashed.
- const char* p = &data[0];
- char* q = &data[0];
- const char* end = p + data.length();
+ char* q = &(*data)[0];
+ const char* p = q;
+ const char* end = p + data->length();
// There must be at least 7 characters (# 1 "x") left to potentially find an
// include file path.
// HP/AIX:
|| (q[1] == 'l' && q[2] == 'i' && q[3] == 'n' && q[4] == 'e'
&& q[5] == ' '))
- && (q == data.data() || q[-1] == '\n')) {
+ && (q == data->data() || q[-1] == '\n')) {
// Workarounds for preprocessor linemarker bugs in GCC version 6.
if (q[2] == '3') {
if (util::starts_with(q, hash_31_command_line_newline)) {
return nonstd::make_unexpected(
Failure(Statistic::unsupported_code_directive));
} else if (strncmp(q, "___________", 10) == 0
- && (q == data.data() || q[-1] == '\n')) {
+ && (q == data->data() || q[-1] == '\n')) {
// Unfortunately the distcc-pump wrapper outputs standard output lines:
// __________Using distcc-pump from /usr/bin
// __________Using # distcc servers in pump mode
static std::optional<Digest>
result_key_from_depfile(Context& ctx, Hash& hash)
{
- std::string file_content;
- try {
- file_content = Util::read_file(ctx.args_info.output_dep);
- } catch (const core::Error& e) {
- LOG(
- "Cannot open dependency file {}: {}", ctx.args_info.output_dep, e.what());
+ const auto file_content =
+ util::read_file<std::string>(ctx.args_info.output_dep);
+ if (!file_content) {
+ LOG("Cannot open dependency file {}: {}",
+ ctx.args_info.output_dep,
+ file_content.error());
return std::nullopt;
}
- for (std::string_view token : Depfile::tokenize(file_content)) {
+ for (std::string_view token : Depfile::tokenize(*file_content)) {
if (util::ends_with(token, ":")) {
continue;
}
std::move(tmp_stderr.fd));
if (status != 0 && !ctx.diagnostics_color_failed
&& ctx.config.compiler_type() == CompilerType::gcc) {
- auto errors = Util::read_file(tmp_stderr.path);
- if (errors.find("fdiagnostics-color") != std::string::npos) {
+ const auto errors = util::read_file<std::string>(tmp_stderr.path);
+ if (errors && errors->find("fdiagnostics-color") != std::string::npos) {
// GCC versions older than 4.9 don't understand -fdiagnostics-color, and
// non-GCC compilers misclassified as CompilerType::gcc might not do it
// either. We assume that if the error message contains
}
}
- try {
- return DoExecuteResult{
- status,
- capture_stdout ? Util::read_file(tmp_stdout.path) : std::string(),
- Util::read_file(tmp_stderr.path),
- };
- } catch (core::Error&) {
- // The stdout or stderr file was removed - cleanup in progress? Better bail
- // out.
+ std::string stdout_data;
+ if (capture_stdout) {
+ auto stdout_data_result = util::read_file<std::string>(tmp_stdout.path);
+ if (!stdout_data_result) {
+ // The stdout file was removed - cleanup in progress? Better bail out.
+ return nonstd::make_unexpected(Statistic::missing_cache_file);
+ }
+ stdout_data = std::move(*stdout_data_result);
+ }
+
+ auto stderr_data_result = util::read_file<std::string>(tmp_stderr.path);
+ if (!stderr_data_result) {
+ // The stdout file was removed - cleanup in progress? Better bail out.
return nonstd::make_unexpected(Statistic::missing_cache_file);
}
+
+ return DoExecuteResult{status, stdout_data, *stderr_data_result};
}
static core::Manifest
#include <util/TextTable.hpp>
#include <util/XXH3_128.hpp>
#include <util/expected.hpp>
+#include <util/file.hpp>
#include <util/string.hpp>
#include <fcntl.h>
util::XXH3_128 checksum;
Fd fd(arg == "-" ? STDIN_FILENO : open(arg.c_str(), O_RDONLY));
if (fd) {
- Util::read_fd(*fd, [&checksum](const void* data, size_t size) {
+ util::read_fd(*fd, [&checksum](const void* data, size_t size) {
checksum.update(data, size);
});
const auto digest = checksum.digest();
case HASH_FILE: {
Hash hash;
- const bool ok =
+ const auto result =
arg == "-" ? hash.hash_fd(STDIN_FILENO) : hash.hash_file(arg);
- if (ok) {
+ if (result) {
PRINT(stdout, "{}\n", hash.digest().to_string());
} else {
- PRINT(stderr, "Error: Failed to hash {}\n", arg);
+ PRINT(stderr, "Error: Failed to hash {}: {}\n", arg, result.error());
return EXIT_FAILURE;
}
break;
#include <core/exceptions.hpp>
#include <core/wincompat.hpp>
+#include <util/file.hpp>
#include <util/path.hpp>
#ifdef HAVE_UNISTD_H
if (args.length() > 8192) {
TemporaryFile tmp_file(FMT("{}/cmd_args", temp_dir));
args = Win32Util::argv_to_string(argv + 1, sh, true);
- Util::write_fd(*tmp_file.fd, args.data(), args.length());
+ util::write_fd(*tmp_file.fd, args.data(), args.length());
args = FMT(R"("{}" "@{}")", full_path, tmp_file.path);
tmp_file_path = tmp_file.path;
LOG("Arguments from {}", tmp_file.path);
#include <core/exceptions.hpp>
#include <core/wincompat.hpp>
+#include <util/file.hpp>
#include <util/string.hpp>
#ifdef INODE_CACHE_SUPPORTED
(void)ctx;
#endif
- std::string data;
- try {
- data = Util::read_file(path, size_hint);
- } catch (core::Error&) {
+ const auto data = util::read_file<std::string>(path, size_hint);
+ if (!data) {
return HASH_SOURCE_CODE_ERROR;
}
int result = HASH_SOURCE_CODE_OK;
if (check_temporal_macros) {
- result |= check_for_temporal_macros(data);
+ result |= check_for_temporal_macros(*data);
}
Hash hash;
- hash.hash(data);
+ hash.hash(*data);
digest = hash.digest();
#ifdef INODE_CACHE_SUPPORTED
return false;
}
int fd = _open_osfhandle((intptr_t)pipe_out[0], O_BINARY);
- bool ok = hash.hash_fd(fd);
- if (!ok) {
- LOG("Error hashing compiler check command output: {}", strerror(errno));
+ const auto compiler_check_result = hash.hash_fd(fd);
+ if (!compiler_check_result) {
+ LOG("Error hashing compiler check command output: {}",
+ compiler_check_result.error());
}
WaitForSingleObject(pi.hProcess, INFINITE);
DWORD exitcode;
LOG("Compiler check command returned {}", exitcode);
return false;
}
- return ok;
+ return bool(compiler_check_result);
#else
int pipefd[2];
if (pipe(pipefd) == -1) {
} else {
// Parent.
close(pipefd[1]);
- bool ok = hash.hash_fd(pipefd[0]);
- if (!ok) {
- LOG("Error hashing compiler check command output: {}", strerror(errno));
+ const auto hash_result = hash.hash_fd(pipefd[0]);
+ if (!hash_result) {
+ LOG("Error hashing compiler check command output: {}",
+ hash_result.error());
}
close(pipefd[0]);
LOG("Compiler check command returned {}", WEXITSTATUS(status));
return false;
}
- return ok;
+ return bool(hash_result);
}
#endif
}
}
});
- Util::write_file(cleaned_stamp, "");
+ util::write_file(cleaned_stamp, "");
}
std::optional<core::StatisticsCounters>
#include <AtomicFile.hpp>
#include <Logging.hpp>
-#include <Util.hpp>
#include <core/exceptions.hpp>
#include <fmtmacros.hpp>
#include <util/LockFile.hpp>
+#include <util/file.hpp>
namespace storage::primary {
{
core::StatisticsCounters counters;
- std::string data;
- try {
- data = Util::read_file(m_path);
- } catch (const core::Error&) {
+ const auto data = util::read_file<std::string>(m_path);
+ if (!data) {
// Ignore.
return counters;
}
size_t i = 0;
- const char* str = data.c_str();
+ const char* str = data->c_str();
while (true) {
char* end;
const uint64_t value = std::strtoull(str, &end, 10);
void
LongLivedLockFile::on_after_acquire()
{
- try {
- Util::write_file(m_alive_file, "");
- } catch (const core::Error& e) {
- LOG("Failed to create {}: {}", m_alive_file, e.what());
+ const auto result = util::write_file(m_alive_file, "");
+ if (!result) {
+ LOG("Failed to write {}: {}", m_alive_file, result.error());
}
+
LOG_RAW("Starting keep-alive thread");
m_keep_alive_thread = std::thread([=] {
while (true) {
#include <Fd.hpp>
#include <Logging.hpp>
-#include <Util.hpp>
+#include <Stat.hpp>
#include <fmtmacros.hpp>
#ifdef HAVE_UNISTD_H
#include "../src/Args.hpp"
#include "TestUtil.hpp"
+#include <util/file.hpp>
+
#include "third_party/doctest.h"
TEST_SUITE_BEGIN("Args");
SUBCASE("Empty")
{
- Util::write_file("at_file", "");
+ util::write_file("at_file", "");
args = *Args::from_atfile("at_file");
CHECK(args.size() == 0);
}
SUBCASE("One argument without newline")
{
- Util::write_file("at_file", "foo");
+ util::write_file("at_file", "foo");
args = *Args::from_atfile("at_file");
CHECK(args.size() == 1);
CHECK(args[0] == "foo");
SUBCASE("One argument with newline")
{
- Util::write_file("at_file", "foo\n");
+ util::write_file("at_file", "foo\n");
args = *Args::from_atfile("at_file");
CHECK(args.size() == 1);
CHECK(args[0] == "foo");
SUBCASE("Multiple simple arguments")
{
- Util::write_file("at_file", "x y z\n");
+ util::write_file("at_file", "x y z\n");
args = *Args::from_atfile("at_file");
CHECK(args.size() == 3);
CHECK(args[0] == "x");
SUBCASE("Tricky quoting")
{
- Util::write_file(
+ util::write_file(
"at_file",
"first\rsec\\\tond\tthi\\\\rd\nfourth \tfif\\ th \"si'x\\\" th\""
" 'seve\nth'\\");
SUBCASE("Only escape double quote and backslash in alternate format")
{
- Util::write_file("at_file", "\"\\\"\\a\\ \\\\\\ \\b\\\"\"\\");
+ util::write_file("at_file", "\"\\\"\\a\\ \\\\\\ \\b\\\"\"\\");
args = *Args::from_atfile("at_file", Args::AtFileFormat::msvc);
CHECK(args.size() == 1);
CHECK(args[0] == "\"\\a\\ \\\\ \\b\"\\");
SUBCASE("Ignore single quote in alternate format")
{
- Util::write_file("at_file", "'a b'");
+ util::write_file("at_file", "'a b'");
args = *Args::from_atfile("at_file", Args::AtFileFormat::msvc);
CHECK(args.size() == 2);
CHECK(args[0] == "'a");
// Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
#include "../src/AtomicFile.hpp"
-#include "../src/Util.hpp"
#include "TestUtil.hpp"
+#include <Stat.hpp>
+#include <util/file.hpp>
+
#include "third_party/doctest.h"
using TestUtil::TestContext;
atomic_file.write(util::Blob{0x65, 0x6c});
fputs("lo", atomic_file.stream());
atomic_file.commit();
- CHECK(Util::read_file("test") == "hello");
+ CHECK(*util::read_file<std::string>("test") == "hello");
}
TEST_CASE("Not committing")
AtomicFile atomic_file("test", AtomicFile::Mode::text);
atomic_file.write("hello");
}
- CHECK_THROWS_WITH(Util::read_file("test"), "No such file or directory");
+ CHECK(!Stat::stat("test"));
}
TEST_SUITE_END();
#include "TestUtil.hpp"
#include <core/exceptions.hpp>
+#include <util/file.hpp>
#include "third_party/doctest.h"
#include "third_party/fmt/core.h"
std::string base_dir = FMT("C:/{0}/foo/{0}", user);
#endif
- Util::write_file(
+ util::write_file(
"ccache.conf",
"base_dir = " + base_dir + "\n"
"cache_dir=\n"
SUBCASE("missing equal sign")
{
- Util::write_file("ccache.conf", "no equal sign");
+ util::write_file("ccache.conf", "no equal sign");
REQUIRE_THROWS_WITH(config.update_from_file("ccache.conf"),
"ccache.conf:1: missing equal sign");
}
SUBCASE("unknown key")
{
- Util::write_file("ccache.conf", "# Comment\nfoo = bar");
+ util::write_file("ccache.conf", "# Comment\nfoo = bar");
CHECK(config.update_from_file("ccache.conf"));
}
SUBCASE("invalid bool")
{
- Util::write_file("ccache.conf", "disable=");
+ util::write_file("ccache.conf", "disable=");
REQUIRE_THROWS_WITH(config.update_from_file("ccache.conf"),
"ccache.conf:1: not a boolean value: \"\"");
- Util::write_file("ccache.conf", "disable=foo");
+ util::write_file("ccache.conf", "disable=foo");
REQUIRE_THROWS_WITH(config.update_from_file("ccache.conf"),
"ccache.conf:1: not a boolean value: \"foo\"");
}
SUBCASE("invalid variable reference")
{
- Util::write_file("ccache.conf", "base_dir = ${foo");
+ util::write_file("ccache.conf", "base_dir = ${foo");
REQUIRE_THROWS_WITH(
config.update_from_file("ccache.conf"),
"ccache.conf:1: syntax error: missing '}' after \"foo\"");
SUBCASE("empty umask")
{
- Util::write_file("ccache.conf", "umask = ");
+ util::write_file("ccache.conf", "umask = ");
CHECK(config.update_from_file("ccache.conf"));
CHECK(config.umask() == std::nullopt);
}
SUBCASE("invalid size")
{
- Util::write_file("ccache.conf", "max_size = foo");
+ util::write_file("ccache.conf", "max_size = foo");
REQUIRE_THROWS_WITH(config.update_from_file("ccache.conf"),
"ccache.conf:1: invalid size: \"foo\"");
// Other cases tested in test_Util.c.
SUBCASE("unknown sloppiness")
{
- Util::write_file("ccache.conf", "sloppiness = time_macros, foo");
+ util::write_file("ccache.conf", "sloppiness = time_macros, foo");
CHECK(config.update_from_file("ccache.conf"));
CHECK(config.sloppiness().to_bitmask()
== static_cast<uint32_t>(core::Sloppy::time_macros));
SUBCASE("invalid unsigned")
{
- Util::write_file("ccache.conf", "max_files =");
+ util::write_file("ccache.conf", "max_files =");
REQUIRE_THROWS_WITH(config.update_from_file("ccache.conf"),
"ccache.conf:1: invalid unsigned integer: \"\"");
- Util::write_file("ccache.conf", "max_files = -42");
+ util::write_file("ccache.conf", "max_files = -42");
REQUIRE_THROWS_WITH(config.update_from_file("ccache.conf"),
"ccache.conf:1: invalid unsigned integer: \"-42\"");
- Util::write_file("ccache.conf", "max_files = foo");
+ util::write_file("ccache.conf", "max_files = foo");
REQUIRE_THROWS_WITH(config.update_from_file("ccache.conf"),
"ccache.conf:1: invalid unsigned integer: \"foo\"");
}
SUBCASE("relative base dir")
{
- Util::write_file("ccache.conf", "base_dir = relative/path");
+ util::write_file("ccache.conf", "base_dir = relative/path");
REQUIRE_THROWS_WITH(
config.update_from_file("ccache.conf"),
"ccache.conf:1: not an absolute path: \"relative/path\"");
- Util::write_file("ccache.conf", "base_dir =");
+ util::write_file("ccache.conf", "base_dir =");
CHECK(config.update_from_file("ccache.conf"));
}
}
SUBCASE("set new value")
{
- Util::write_file("ccache.conf", "path = vanilla\n");
+ util::write_file("ccache.conf", "path = vanilla\n");
config.set_value_in_file("ccache.conf", "compiler", "chocolate");
- std::string content = Util::read_file("ccache.conf");
+ std::string content = *util::read_file<std::string>("ccache.conf");
CHECK(content == "path = vanilla\ncompiler = chocolate\n");
}
SUBCASE("existing value")
{
- Util::write_file("ccache.conf", "path = chocolate\nstats = chocolate\n");
+ util::write_file("ccache.conf", "path = chocolate\nstats = chocolate\n");
config.set_value_in_file("ccache.conf", "path", "vanilla");
- std::string content = Util::read_file("ccache.conf");
+ std::string content = *util::read_file<std::string>("ccache.conf");
CHECK(content == "path = vanilla\nstats = chocolate\n");
}
SUBCASE("unknown option")
{
- Util::write_file("ccache.conf", "path = chocolate\nstats = chocolate\n");
+ util::write_file("ccache.conf", "path = chocolate\nstats = chocolate\n");
try {
config.set_value_in_file("ccache.conf", "foo", "bar");
CHECK(false);
CHECK(std::string(e.what()) == "unknown configuration option \"foo\"");
}
- std::string content = Util::read_file("ccache.conf");
+ std::string content = *util::read_file<std::string>("ccache.conf");
CHECK(content == "path = chocolate\nstats = chocolate\n");
}
SUBCASE("unknown sloppiness")
{
- Util::write_file("ccache.conf", "path = vanilla\n");
+ util::write_file("ccache.conf", "path = vanilla\n");
config.set_value_in_file("ccache.conf", "sloppiness", "foo");
- std::string content = Util::read_file("ccache.conf");
+ std::string content = *util::read_file<std::string>("ccache.conf");
CHECK(content == "path = vanilla\nsloppiness = foo\n");
}
SUBCASE("comments are kept")
{
- Util::write_file("ccache.conf", "# c1\npath = blueberry\n#c2\n");
+ util::write_file("ccache.conf", "# c1\npath = blueberry\n#c2\n");
config.set_value_in_file("ccache.conf", "path", "vanilla");
config.set_value_in_file("ccache.conf", "compiler", "chocolate");
- std::string content = Util::read_file("ccache.conf");
+ std::string content = *util::read_file<std::string>("ccache.conf");
CHECK(content == "# c1\npath = vanilla\n#c2\ncompiler = chocolate\n");
}
}
{
TestContext test_context;
- Util::write_file(
+ util::write_file(
"test.conf",
"absolute_paths_in_stderr = true\n"
#ifndef _WIN32
#include "TestUtil.hpp"
#include <Fd.hpp>
+#include <util/file.hpp>
#include "third_party/doctest.h"
init(config);
InodeCache inode_cache(config);
- Util::write_file("a", "");
+ util::write_file("a", "");
Digest digest;
int return_value;
init(config);
InodeCache inode_cache(config);
- Util::write_file("a", "a text");
+ util::write_file("a", "a text");
CHECK(put(inode_cache, "a", "a text", 1));
CHECK(inode_cache.get_misses() == 0);
CHECK(inode_cache.get_errors() == 0);
- Util::write_file("a", "something else");
+ util::write_file("a", "something else");
CHECK(!inode_cache.get("a",
InodeCache::ContentType::checked_for_temporal_macros,
init(config);
InodeCache inode_cache(config);
- Util::write_file("a", "a text");
+ util::write_file("a", "a text");
Digest binary_digest = Hash().hash("binary").digest();
Digest code_digest = Hash().hash("code").digest();
#include <core/exceptions.hpp>
#include <core/wincompat.hpp>
+#include <util/file.hpp>
#include "third_party/doctest.h"
{
TestContext test_context;
- Util::write_file("a", "");
- Util::write_file("b", "");
+ util::write_file("a", "");
+ util::write_file("b", "");
auto a_stat = Stat::stat("a");
auto b_stat = Stat::stat("b");
CHECK(a_stat.same_inode_as(a_stat));
CHECK(!a_stat.same_inode_as(b_stat));
- Util::write_file("a", "change size");
+ util::write_file("a", "change size");
auto new_a_stat = Stat::stat("a");
CHECK(new_a_stat.same_inode_as(a_stat));
{
TestContext test_context;
- Util::write_file("file", "1234567");
+ util::write_file("file", "1234567");
auto stat = Stat::stat("file");
CHECK(stat);
{
TestContext test_context;
- Util::write_file("file", "1234567");
+ util::write_file("file", "1234567");
#ifdef _WIN32
REQUIRE(CreateSymbolicLinkA(
{
TestContext test_context;
- Util::write_file("a", "");
+ util::write_file("a", "");
#ifdef _WIN32
REQUIRE(CreateHardLinkA("b", "a", nullptr));
CHECK(stat_a.inode() == stat_b.inode());
CHECK(stat_a.same_inode_as(stat_b));
- Util::write_file("a", "1234567");
+ util::write_file("a", "1234567");
stat_a = Stat::stat("a");
stat_b = Stat::stat("b");
{
TestContext test_context;
- Util::write_file("file", "");
+ util::write_file("file", "");
DWORD prev_attrs = GetFileAttributesA("file");
REQUIRE(prev_attrs != INVALID_FILE_ATTRIBUTES);
Finalizer cleanup([&] { CloseHandle(handle); });
// Sanity check we can't open the file for read/write access.
- REQUIRE_THROWS_AS(Util::read_file("file"), const core::Error&);
+ REQUIRE(!util::read_file<std::string>("file"));
SUBCASE("stat file no sharing")
{
#include <core/exceptions.hpp>
#include <core/wincompat.hpp>
+#include <util/file.hpp>
#include "third_party/doctest.h"
CHECK(Util::create_dir("create/dir"));
CHECK(Stat::stat("create/dir").is_directory());
- Util::write_file("create/dir/file", "");
+ util::write_file("create/dir/file", "");
CHECK(!Util::create_dir("create/dir/file"));
}
CHECK_NOTHROW(Util::ensure_dir_exists("create/dir"));
CHECK(Stat::stat("create/dir").is_directory());
- Util::write_file("create/dir/file", "");
+ util::write_file("create/dir/file", "");
CHECK_THROWS_WITH(
Util::ensure_dir_exists("create/dir/file"),
"Failed to create directory create/dir/file: Not a directory");
SUBCASE("Link file to nonexistent destination")
{
- Util::write_file("old", "content");
+ util::write_file("old", "content");
CHECK_NOTHROW(Util::hard_link("old", "new"));
- CHECK(Util::read_file("new") == "content");
+ CHECK(*util::read_file<std::string>("new") == "content");
}
SUBCASE("Link file to existing destination")
{
- Util::write_file("old", "content");
- Util::write_file("new", "other content");
+ util::write_file("old", "content");
+ util::write_file("new", "other content");
CHECK_NOTHROW(Util::hard_link("old", "new"));
- CHECK(Util::read_file("new") == "content");
+ CHECK(*util::read_file<std::string>("new") == "content");
}
SUBCASE("Link nonexistent file")
#ifndef _WIN32
TestContext test_context;
- Util::write_file("file", "");
+ util::write_file("file", "");
REQUIRE(Util::create_dir("dir1/dir2"));
REQUIRE(symlink("dir1/dir2", "symlink") == 0);
const auto cwd = Util::get_actual_cwd();
#include <core/Statistic.hpp>
#include <core/wincompat.hpp>
+#include <util/file.hpp>
#include "third_party/doctest.h"
Context ctx;
ctx.orig_args = Args::from_string("cc -c foo.c -fsyntax-only");
- Util::write_file("foo.c", "");
+ util::write_file("foo.c", "");
const ProcessArgsResult result = process_args(ctx);
Context ctx;
ctx.orig_args = Args::from_string("cc -c foo.c -E");
- Util::write_file("foo.c", "");
+ util::write_file("foo.c", "");
CHECK(process_args(ctx).error == Statistic::called_for_preprocessing);
}
Context ctx;
ctx.orig_args = Args::from_string("cc -c foo.c -M");
- Util::write_file("foo.c", "");
+ util::write_file("foo.c", "");
CHECK(process_args(ctx).error == Statistic::unsupported_compiler_option);
}
" -Wp,-MT,wpmt -Wp,-MQ,wpmq -Wp,-MF,wpf";
Context ctx;
ctx.orig_args = Args::from_string("cc " + dep_args + " -c foo.c -o foo.o");
- Util::write_file("foo.c", "");
+ util::write_file("foo.c", "");
ctx.config.set_run_second_cpp(false);
const ProcessArgsResult result = process_args(ctx);
" -Wp,-MT,wpmt -Wp,-MQ,wpmq -Wp,-MF,wpf";
Context ctx;
ctx.orig_args = Args::from_string("cc " + dep_args + " -c foo.c -o foo.o");
- Util::write_file("foo.c", "");
+ util::write_file("foo.c", "");
const ProcessArgsResult result = process_args(ctx);
Context ctx;
ctx.orig_args =
Args::from_string("cc " + cpp_args + " " + dep_args + " -c foo.c -o foo.o");
- Util::write_file("foo.c", "");
+ util::write_file("foo.c", "");
ctx.config.set_run_second_cpp(false);
const ProcessArgsResult result = process_args(ctx);
Context ctx;
ctx.orig_args =
Args::from_string("cc " + cpp_args + " " + dep_args + " -c foo.c -o foo.o");
- Util::write_file("foo.c", "");
+ util::write_file("foo.c", "");
const ProcessArgsResult result = process_args(ctx);
const std::string dep_args = "-MMD -MFfoo.d -MT mt -MTmt -MQmq";
Context ctx;
ctx.orig_args = Args::from_string("cc -c " + dep_args + " foo.c -o foo.o");
- Util::write_file("foo.c", "");
+ util::write_file("foo.c", "");
const ProcessArgsResult result = process_args(ctx);
TestContext test_context;
Context ctx;
ctx.orig_args = Args::from_string("cc -c -MD foo.c -MF foo.d -o foo.o");
- Util::write_file("foo.c", "");
+ util::write_file("foo.c", "");
const ProcessArgsResult result = process_args(ctx);
TestContext test_context;
Context ctx;
ctx.orig_args = Args::from_string("cc -c -MD foo.c -MF foo.d -o foo.o");
- Util::write_file("foo.c", "");
+ util::write_file("foo.c", "");
ctx.config.set_run_second_cpp(false);
const ProcessArgsResult result = process_args(ctx);
TestContext test_context;
Context ctx;
ctx.orig_args = Args::from_string("cc -c -MD foo.c -o foo.o");
- Util::write_file("foo.c", "");
+ util::write_file("foo.c", "");
ctx.config.set_run_second_cpp(false);
const ProcessArgsResult result = process_args(ctx);
TestContext test_context;
Context ctx;
ctx.orig_args = Args::from_string("cc -c -MD foo.c -o foo.o");
- Util::write_file("foo.c", "");
+ util::write_file("foo.c", "");
const ProcessArgsResult result = process_args(ctx);
TestContext test_context;
Context ctx;
ctx.orig_args = Args::from_string("cc -c -MF=path foo.c -o foo.o");
- Util::write_file("foo.c", "");
+ util::write_file("foo.c", "");
const ProcessArgsResult result = process_args(ctx);
Context ctx;
- Util::write_file("foo.c", "");
+ util::write_file("foo.c", "");
ctx.config.set_base_dir(get_root());
std::string arg_string =
FMT("cc --sysroot={}/foo/bar -c foo.c", ctx.actual_cwd);
Context ctx;
- Util::write_file("foo.c", "");
+ util::write_file("foo.c", "");
ctx.config.set_base_dir(get_root());
std::string arg_string = FMT("cc --sysroot {}/foo -c foo.c", ctx.actual_cwd);
ctx.orig_args = Args::from_string(arg_string);
ctx.orig_args =
Args::from_string("cc -c foo.c -o foo.o -MMD -MT bar -MFfoo.d");
- Util::write_file("foo.c", "");
+ util::write_file("foo.c", "");
const ProcessArgsResult result = process_args(ctx);
CHECK(!result.error);
ctx.orig_args =
Args::from_string("cc -c foo.c -o foo.o -MMD -MFfoo.d -MT foo -MTbar");
- Util::write_file("foo.c", "");
+ util::write_file("foo.c", "");
const ProcessArgsResult result = process_args(ctx);
CHECK(!result.error);
ctx.orig_args =
Args::from_string("cc -c foo.c -o foo.o -MMD -MFfoo.d -MQ foo -MQbar");
- Util::write_file("foo.c", "");
+ util::write_file("foo.c", "");
const ProcessArgsResult result = process_args(ctx);
CHECK(!result.error);
TestContext test_context;
Context ctx;
ctx.orig_args = Args::from_string("gcc -c -MD -MP -MFfoo.d -MQ foo.d foo.c");
- Util::write_file("foo.c", "");
+ util::write_file("foo.c", "");
const ProcessArgsResult result = process_args(ctx);
TestContext test_context;
Context ctx;
ctx.orig_args = Args::from_string("gcc -c -MD -MP -MFfoo.d -MT foo.d foo.c");
- Util::write_file("foo.c", "");
+ util::write_file("foo.c", "");
const ProcessArgsResult result = process_args(ctx);
TestContext test_context;
Context ctx;
ctx.orig_args = Args::from_string("gcc -c -MD -MP -MFfoo.d -MQfoo.d foo.c");
- Util::write_file("foo.c", "");
+ util::write_file("foo.c", "");
const ProcessArgsResult result = process_args(ctx);
TestContext test_context;
Context ctx;
ctx.orig_args = Args::from_string("gcc -c -MD -MP -MFfoo.d -MTfoo.d foo.c");
- Util::write_file("foo.c", "");
+ util::write_file("foo.c", "");
const ProcessArgsResult result = process_args(ctx);
Context ctx;
- Util::write_file("foo.c", "");
+ util::write_file("foo.c", "");
ctx.config.set_base_dir(get_root());
std::string arg_string = FMT("cc -isystem {}/foo -c foo.c", ctx.actual_cwd);
ctx.orig_args = Args::from_string(arg_string);
Context ctx;
- Util::write_file("foo.c", "");
+ util::write_file("foo.c", "");
ctx.config.set_base_dir("/"); // posix
// Windows path doesn't work concatenated.
std::string cwd = get_posix_path(ctx.actual_cwd);
Context ctx;
- Util::write_file("foo.c", "");
+ util::write_file("foo.c", "");
ctx.config.set_base_dir("/"); // posix
// Windows path doesn't work concatenated.
std::string cwd = get_posix_path(ctx.actual_cwd);
TestContext test_context;
Context ctx;
ctx.orig_args = Args::from_string("cc -g1 -gsplit-dwarf foo.c -c");
- Util::write_file("foo.c", "");
+ util::write_file("foo.c", "");
const ProcessArgsResult result = process_args(ctx);
TestContext test_context;
Context ctx;
ctx.orig_args = Args::from_string("cc -gsplit-dwarf -g1 foo.c -c");
- Util::write_file("foo.c", "");
+ util::write_file("foo.c", "");
const ProcessArgsResult result = process_args(ctx);
Context ctx;
ctx.orig_args = Args::from_string(
"cc -Wa,foo foo.c -g -c -DX -Werror -Xlinker fie -Xlinker,fum -Wno-error");
- Util::write_file("foo.c", "");
+ util::write_file("foo.c", "");
const ProcessArgsResult result = process_args(ctx);
Context ctx;
ctx.config.set_compiler_type(CompilerType::nvcc);
ctx.orig_args = Args::from_string("nvcc -optf foo.optf,bar.optf");
- Util::write_file("foo.c", "");
- Util::write_file("foo.optf", "-c foo.c -g -Wall -o");
- Util::write_file("bar.optf", "out -DX");
+ util::write_file("foo.c", "");
+ util::write_file("foo.optf", "-c foo.c -g -Wall -o");
+ util::write_file("bar.optf", "out -DX");
const ProcessArgsResult result = process_args(ctx);
ctx.orig_args =
Args::from_string("clang -c foo.c " + common_args + " " + color_diag + " "
+ extra_args + " " + pch_pth_variants);
- Util::write_file("foo.c", "");
+ util::write_file("foo.c", "");
const ProcessArgsResult result = process_args(ctx);
CHECK(result.preprocessor_args.to_string()
{
TestContext test_context;
Context ctx;
- Util::write_file("foo.c", "");
+ util::write_file("foo.c", "");
SUBCASE("intel option")
{
#include "TestUtil.hpp"
#include <core/wincompat.hpp>
+#include <util/file.hpp>
#include "third_party/doctest.h"
SUBCASE("Follow symlink to actual compiler")
{
const auto cwd = Util::get_actual_cwd();
- Util::write_file(FMT("{}/gcc", cwd), "");
+ util::write_file(FMT("{}/gcc", cwd), "");
CHECK(symlink("gcc", FMT("{}/intermediate", cwd).c_str()) == 0);
const auto cc = FMT("{}/cc", cwd);
CHECK(symlink("intermediate", cc.c_str()) == 0);
-// Copyright (C) 2021 Joel Rosdahl and other contributors
+// Copyright (C) 2021-2022 Joel Rosdahl and other contributors
//
// See doc/AUTHORS.adoc for a complete list of contributors.
//
#include <Util.hpp>
#include <core/StatsLog.hpp>
+#include <util/file.hpp>
#include <third_party/doctest.h>
{
TestContext test_context;
- Util::write_file("stats.log", "# comment\ndirect_cache_hit\n");
+ util::write_file("stats.log", "# comment\ndirect_cache_hit\n");
const auto counters = StatsLog("stats.log").read();
CHECK(counters.get(Statistic::direct_cache_hit) == 1);
stats_log.log_result("foo.c", {"cache_miss"});
stats_log.log_result("bar.c", {"preprocessed_cache_hit"});
- CHECK(Util::read_file("stats.log")
+ CHECK(*util::read_file<std::string>("stats.log")
== "# foo.c\ncache_miss\n# bar.c\npreprocessed_cache_hit\n");
}
#include "../src/hashutil.hpp"
#include "TestUtil.hpp"
+#include <util/file.hpp>
+
#include "third_party/doctest.h"
using TestUtil::TestContext;
Hash h2;
#ifndef _WIN32
- Util::write_file("stderr.sh", "#!/bin/sh\necho foo >&2\n");
+ util::write_file("stderr.sh", "#!/bin/sh\necho foo >&2\n");
chmod("stderr.sh", 0555);
CHECK(hash_command_output(h1, "echo foo", "not used"));
CHECK(hash_command_output(h2, "./stderr.sh", "not used"));
#else
- Util::write_file("stderr.bat", "@echo off\r\necho foo>&2\r\n");
+ util::write_file("stderr.bat", "@echo off\r\necho foo>&2\r\n");
CHECK(hash_command_output(h1, "echo foo", "not used"));
CHECK(hash_command_output(h2, "stderr.bat", "not used"));
#endif
Hash h2;
#ifndef _WIN32
- Util::write_file("foo.sh", "#!/bin/sh\necho foo\necho bar\n");
+ util::write_file("foo.sh", "#!/bin/sh\necho foo\necho bar\n");
chmod("foo.sh", 0555);
CHECK(hash_multicommand_output(h2, "echo foo; echo bar", "not used"));
CHECK(hash_multicommand_output(h1, "./foo.sh", "not used"));
#else
- Util::write_file("foo.bat", "@echo off\r\necho foo\r\necho bar\r\n");
+ util::write_file("foo.bat", "@echo off\r\necho foo\r\necho bar\r\n");
CHECK(hash_multicommand_output(h2, "echo foo; echo bar", "not used"));
CHECK(hash_multicommand_output(h1, "foo.bat", "not used"));
#endif
-// Copyright (C) 2011-2021 Joel Rosdahl and other contributors
+// Copyright (C) 2011-2022 Joel Rosdahl and other contributors
//
// See doc/AUTHORS.adoc for a complete list of contributors.
//
#include <core/Statistic.hpp>
#include <fmtmacros.hpp>
#include <storage/primary/StatsFile.hpp>
+#include <util/file.hpp>
#include <third_party/doctest.h>
{
TestContext test_context;
- Util::write_file("test", "bad 1 2 3 4 5\n");
+ util::write_file("test", "bad 1 2 3 4 5\n");
const auto counters = StatsFile("test").read();
REQUIRE(counters.size() == static_cast<size_t>(Statistic::END));
{
TestContext test_context;
- Util::write_file("test", "0 1 2 3 27 5\n");
+ util::write_file("test", "0 1 2 3 27 5\n");
const auto counters = StatsFile("test").read();
REQUIRE(counters.size() == static_cast<size_t>(Statistic::END));
content += FMT("{}\n", i);
}
- Util::write_file("test", content);
+ util::write_file("test", content);
const auto counters = StatsFile("test").read();
REQUIRE(counters.size() == count);
{
TestContext test_context;
- Util::write_file("test", "0 1 2 3 27 5\n");
+ util::write_file("test", "0 1 2 3 27 5\n");
auto counters = StatsFile("test").update([](auto& cs) {
cs.increment(Statistic::internal_error, 1);
#include <Util.hpp>
#include <storage/primary/util.hpp>
+#include <util/file.hpp>
#include <third_party/doctest.h>
Util::create_dir("0/1");
Util::create_dir("0/f/c");
- Util::write_file("0/file_a", "");
- Util::write_file("0/1/file_b", "1");
- Util::write_file("0/1/file_c", "12");
- Util::write_file("0/f/c/file_d", "123");
+ util::write_file("0/file_a", "");
+ util::write_file("0/1/file_b", "1");
+ util::write_file("0/1/file_c", "12");
+ util::write_file("0/f/c/file_d", "123");
auto null_receiver = [](double) {};
{
TestContext test_context;
- Util::write_file("test.alive", "");
+ util::write_file("test.alive", "");
const timespec long_time_ago{0, 0};
util::set_timestamps("test.alive", long_time_ago);
CHECK(symlink("foo", "test.lock") == 0);
{
TestContext test_context;
- Util::write_file("test.alive", "");
+ util::write_file("test.alive", "");
const timespec long_time_ago{0, 0};
util::set_timestamps("test.alive", long_time_ago);
CHECK(symlink("foo", "test.lock") == 0);