This makes Foo::bar work for both a namespace Foo and a class Foo.
Regarding naming:
-* Use UpperCamelCase for types (e.g. classes and structs).
-* Use snake_case for namespaces, functions and variables.
+* Use UpperCamelCase for types (e.g. classes and structs) and namespaces.
+* Use UPPER_CASE names for macros.
+* Use snake_case for other names (functions, variables, enum values, etc.).
* Use an "m_" prefix for non-public member variables.
* Use a "g_" prefix for global mutable variables.
* Use a "k_" prefix for global constants.
-* Use UPPER_CASE names for macros.
src/CacheFile.cpp \
src/Config.cpp \
src/ProgressBar.cpp \
+ src/Util.cpp \
src/args.cpp \
src/ccache.cpp \
src/cleanup.cpp \
src/hash.cpp \
src/hashutil.cpp \
src/language.cpp \
+ src/legacy_util.cpp \
src/lockfile.cpp \
src/manifest.cpp \
src/result.cpp \
src/stats.cpp \
- src/unify.cpp \
- src/util.cpp
+ src/unify.cpp
generated_sources = \
src/version.cpp
third_party_sources = \
test_suites += unittest/test_Checksum.cpp
test_suites += unittest/test_Config.cpp
+test_suites += unittest/test_Util.cpp
test_suites += unittest/test_args.cpp
test_suites += unittest/test_argument_processing.cpp
test_suites += unittest/test_compopt.cpp
test_suites += unittest/test_legacy_util.cpp
test_suites += unittest/test_lockfile.cpp
test_suites += unittest/test_stats.cpp
-test_suites += unittest/test_util.cpp
test_sources += unittest/catch2_tests.cpp
test_sources += unittest/framework.cpp
src/Config.hpp \
src/Error.hpp \
src/ProgressBar.hpp \
+ src/Util.hpp \
src/ccache.hpp \
src/cleanup.hpp \
src/common_header.hpp \
src/result.hpp \
src/system.hpp \
src/unify.hpp \
- src/util.hpp \
unittest/framework.hpp \
unittest/util.hpp
third_party_headers = \
#include "AtomicFile.hpp"
#include "Error.hpp"
+#include "Util.hpp"
#include "ccache.hpp"
#include <cassert>
AtomicFile::AtomicFile(const std::string& path, Mode mode) : m_path(path)
{
- auto fd_and_path = util::create_temp_fd(path);
+ auto fd_and_path = Util::create_temp_fd(path);
m_stream = fdopen(fd_and_path.first, mode == Mode::binary ? "w+b" : "w+");
m_tmp_path = std::move(fd_and_path.second);
}
#include "CacheFile.hpp"
-#include "util.hpp"
+#include "Util.hpp"
const struct stat&
CacheFile::stat() const
CacheFile::Type
CacheFile::type() const
{
- if (util::ends_with(m_path, ".manifest")) {
+ if (Util::ends_with(m_path, ".manifest")) {
return Type::manifest;
- } else if (util::ends_with(m_path, ".result")) {
+ } else if (Util::ends_with(m_path, ".result")) {
return Type::result;
} else {
return Type::unknown;
#include "AtomicFile.hpp"
#include "Error.hpp"
-#include "util.hpp"
+#include "Util.hpp"
#include <algorithm>
#include <cassert>
// Previously any value meant true, but this was surprising to users, who
// might do something like CCACHE_DISABLE=0 and expect ccache to be
// enabled.
- std::string lower_value = util::to_lowercase(value);
+ std::string lower_value = Util::to_lowercase(value);
if (value == "0" || lower_value == "false" || lower_value == "disable"
|| lower_value == "no") {
throw Error(fmt::format(
while (end != std::string::npos) {
end = value.find_first_of(", ", start);
std::string token =
- util::strip_whitespace(value.substr(start, end - start));
+ Util::strip_whitespace(value.substr(start, end - start));
if (token == "file_macro") {
result |= SLOPPY_FILE_MACRO;
} else if (token == "file_stat_matches") {
std::string* value,
std::string* error_message)
{
- std::string stripped_line = util::strip_whitespace(line);
+ std::string stripped_line = Util::strip_whitespace(line);
if (stripped_line.empty() || stripped_line[0] == '#') {
return true;
}
}
*key = stripped_line.substr(0, equal_pos);
*value = stripped_line.substr(equal_pos + 1);
- *key = util::strip_whitespace(*key);
- *value = util::strip_whitespace(*value);
+ *key = Util::strip_whitespace(*key);
+ *value = Util::strip_whitespace(*value);
return true;
}
for (char** env = environ; *env; ++env) {
std::string setting = *env;
const std::string prefix = "CCACHE_";
- if (!util::starts_with(setting, prefix)) {
+ if (!Util::starts_with(setting, prefix)) {
continue;
}
size_t equal_pos = setting.find('=');
std::string key = setting.substr(prefix.size(), equal_pos - prefix.size());
std::string value = setting.substr(equal_pos + 1);
- bool negate = util::starts_with(key, "NO");
+ bool negate = Util::starts_with(key, "NO");
if (negate) {
key = key.substr(2);
}
break;
case ConfigItem::compression_level: {
- auto level = util::parse_int(value);
+ auto level = Util::parse_int(value);
if (level < -128 || level > 127) {
throw Error("compression level must be between -128 and 127");
}
--- /dev/null
+// Copyright (C) 2019 Joel Rosdahl and other contributors
+//
+// See doc/AUTHORS.adoc for a complete list of contributors.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Software Foundation, Inc., 51
+// Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+#include "Util.hpp"
+
+#include "ccache.hpp"
+#include "util.hpp"
+
+#include <algorithm>
+#include <fstream>
+
+namespace {
+
+void
+get_cache_files_internal(const std::string& dir,
+ uint8_t level,
+ const Util::ProgressReceiver& progress_receiver,
+ std::vector<std::shared_ptr<CacheFile>>& files)
+{
+ DIR* d = opendir(dir.c_str());
+ if (!d) {
+ return;
+ }
+
+ std::vector<std::string> directories;
+ dirent* de;
+ while ((de = readdir(d))) {
+ std::string name = de->d_name;
+ if (name == "" || name == "." || name == ".." || name == "CACHEDIR.TAG"
+ || name == "stats" || Util::starts_with(name, ".nfs")) {
+ continue;
+ }
+
+ if (name.length() == 1) {
+ directories.push_back(name);
+ } else {
+ files.push_back(
+ std::make_shared<CacheFile>(fmt::format("{}/{}", dir, name)));
+ }
+ }
+ closedir(d);
+
+ if (level == 1) {
+ progress_receiver(1.0 / (directories.size() + 1));
+ }
+
+ for (size_t i = 0; i < directories.size(); ++i) {
+ get_cache_files_internal(
+ dir + "/" + directories[i], level + 1, progress_receiver, files);
+ if (level == 1) {
+ progress_receiver(1.0 * (i + 1) / (directories.size() + 1));
+ }
+ }
+}
+
+} // namespace
+
+namespace Util {
+
+std::string
+base_name(const std::string& path)
+{
+ size_t n = path.rfind('/');
+#ifdef _WIN32
+ size_t n2 = path.rfind('\\');
+ if (n2 != std::string::npos && n2 > n) {
+ n = n2;
+ }
+#endif
+ return n == std::string::npos ? path : path.substr(n + 1);
+}
+
+bool
+create_dir(const std::string& dir)
+{
+ struct stat st;
+ if (stat(dir.c_str(), &st) == 0) {
+ if (S_ISDIR(st.st_mode)) {
+ return true;
+ } else {
+ errno = ENOTDIR;
+ return false;
+ }
+ } else {
+ if (!create_dir(Util::dir_name(dir))) {
+ return false;
+ }
+ int result = mkdir(dir.c_str(), 0777);
+ // Treat an already existing directory as OK since the file system could
+ // have changed in between calling stat and actually creating the
+ // directory. This can happen when there are multiple instances of ccache
+ // running and trying to create the same directory chain, which usually is
+ // the case when the cache root does not initially exist. As long as one of
+ // the processes creates the directories then our condition is satisfied
+ // and we avoid a race condition.
+ return result == 0 || errno == EEXIST;
+ }
+}
+
+std::pair<int, std::string>
+create_temp_fd(const std::string& path_prefix)
+{
+ char* tmp_path = x_strdup(path_prefix.c_str());
+ int fd = create_tmp_fd(&tmp_path);
+ std::string actual_path = tmp_path;
+ free(tmp_path);
+ return {fd, actual_path};
+}
+
+std::string
+dir_name(const std::string& path)
+{
+ size_t n = path.rfind('/');
+#ifdef _WIN32
+ size_t n2 = path.rfind('\\');
+ if (n2 != std::string::npos && n2 > n) {
+ n = n2;
+ }
+#endif
+ if (n == std::string::npos) {
+ return ".";
+ }
+ return n == 0 ? "/" : path.substr(0, n);
+}
+
+bool
+ends_with(const std::string& string, const std::string& suffix)
+{
+ return suffix.length() <= string.length()
+ && string.compare(
+ string.length() - suffix.length(), suffix.length(), suffix)
+ == 0;
+}
+
+void
+for_each_level_1_subdir(const std::string& cache_dir,
+ const SubdirVisitor& subdir_visitor,
+ const ProgressReceiver& progress_receiver)
+{
+ for (int i = 0; i <= 0xF; i++) {
+ double progress = 1.0 * i / 16;
+ progress_receiver(progress);
+ std::string subdir_path = fmt::format("{}/{:x}", cache_dir, i);
+ subdir_visitor(subdir_path, [&](double inner_progress) {
+ progress_receiver(progress + inner_progress / 16);
+ });
+ }
+ progress_receiver(1.0);
+}
+
+void
+get_level_1_files(const std::string& dir,
+ const ProgressReceiver& progress_receiver,
+ std::vector<std::shared_ptr<CacheFile>>& files)
+{
+ get_cache_files_internal(dir, 1, progress_receiver, files);
+}
+
+int
+parse_int(const std::string& value)
+{
+ size_t end;
+ long result;
+ bool failed = false;
+ try {
+ result = std::stol(value, &end, 10);
+ } catch (std::exception&) {
+ failed = true;
+ }
+ if (failed || end != value.size() || result < std::numeric_limits<int>::min()
+ || result > std::numeric_limits<int>::max()) {
+ throw Error(fmt::format("invalid integer: \"{}\"", value));
+ }
+ return result;
+}
+
+std::string
+read_file(const std::string& path)
+{
+ std::ifstream file(path);
+ if (!file) {
+ throw Error(fmt::format("{}: {}", path, strerror(errno)));
+ }
+ return std::string(std::istreambuf_iterator<char>(file),
+ std::istreambuf_iterator<char>());
+}
+
+bool
+starts_with(const std::string& string, const std::string& prefix)
+{
+ return prefix.length() <= string.length()
+ && string.compare(0, prefix.length(), prefix) == 0;
+}
+
+std::string
+strip_whitespace(const std::string& string)
+{
+ auto is_space = [](int ch) { return std::isspace(ch); };
+ auto start = std::find_if_not(string.begin(), string.end(), is_space);
+ auto end = std::find_if_not(string.rbegin(), string.rend(), is_space).base();
+ return start < end ? std::string(start, end) : std::string();
+}
+
+std::string
+to_lowercase(const std::string& string)
+{
+ std::string result = string;
+ std::transform(result.begin(), result.end(), result.begin(), tolower);
+ return result;
+}
+
+// Write file data from a string.
+void
+write_file(const std::string& path, const std::string& data, bool binary)
+{
+ std::ofstream file(path,
+ binary ? std::ios::out | std::ios::binary : std::ios::out);
+ if (!file) {
+ throw Error(fmt::format("{}: {}", path, strerror(errno)));
+ }
+ file << data;
+}
+
+} // namespace Util
#include <utility>
#include <vector>
-namespace util {
+namespace Util {
typedef std::function<void(double)> ProgressReceiver;
typedef std::function<void(std::shared_ptr<CacheFile>)> CacheFileVisitor;
const std::string& data,
bool binary = false);
-} // namespace util
+} // namespace Util
#include "Error.hpp"
#include "ProgressBar.hpp"
+#include "Util.hpp"
#include "cleanup.hpp"
#include "compopt.hpp"
-#include "util.hpp"
#include <fmt/core.h>
#include <limits>
hash_delimiter(hash, "cc_mtime");
hash_int(hash, st->st_size);
hash_int(hash, st->st_mtime);
- } else if (util::starts_with(g_config.compiler_check(), "string:")) {
+ } else if (Util::starts_with(g_config.compiler_check(), "string:")) {
hash_delimiter(hash, "cc_hash");
hash_string(hash, g_config.compiler_check().c_str() + strlen("string:"));
} else if (g_config.compiler_check() == "content" || !allow_command) {
static void
create_initial_config_file(const char* path)
{
- if (!util::create_dir(util::dir_name(path))) {
+ if (!Util::create_dir(Util::dir_name(path))) {
return;
}
clean_up_dir(const std::string& subdir,
uint64_t max_size,
uint32_t max_files,
- const util::ProgressReceiver& progress_receiver)
+ const Util::ProgressReceiver& progress_receiver)
{
cc_log("Cleaning up cache directory %s", subdir.c_str());
std::vector<std::shared_ptr<CacheFile>> files;
- util::get_level_1_files(
+ Util::get_level_1_files(
subdir, [&](double progress) { progress_receiver(progress / 3); }, files);
uint64_t cache_size = 0;
// Delete any tmp files older than 1 hour right away.
if (file->stat().st_mtime + 3600 < current_time
- && util::base_name(file->path()).find(".tmp.") != std::string::npos) {
+ && Util::base_name(file->path()).find(".tmp.") != std::string::npos) {
x_unlink(file->path().c_str());
continue;
}
break;
}
- if (util::ends_with(file->path(), ".stderr")) {
+ if (Util::ends_with(file->path(), ".stderr")) {
// In order to be nice to legacy ccache versions, make sure that the .o
// file is deleted before .stderr, because if the ccache process gets
// killed after deleting the .stderr but before deleting the .o, the
// Clean up all cache subdirectories.
void
clean_up_all(const Config& config,
- const util::ProgressReceiver& progress_receiver)
+ const Util::ProgressReceiver& progress_receiver)
{
- util::for_each_level_1_subdir(
+ Util::for_each_level_1_subdir(
config.cache_dir(),
[&](const std::string& subdir,
- const util::ProgressReceiver& sub_progress_receiver) {
+ const Util::ProgressReceiver& sub_progress_receiver) {
clean_up_dir(subdir,
config.max_size() / 16,
config.max_files() / 16,
// Wipe one cache subdirectory.
static void
wipe_dir(const std::string& subdir,
- const util::ProgressReceiver& progress_receiver)
+ const Util::ProgressReceiver& progress_receiver)
{
cc_log("Clearing out cache directory %s", subdir.c_str());
std::vector<std::shared_ptr<CacheFile>> files;
- util::get_level_1_files(
+ Util::get_level_1_files(
subdir, [&](double progress) { progress_receiver(progress / 2); }, files);
for (size_t i = 0; i < files.size(); ++i) {
// Wipe all cached files in all subdirectories.
void
-wipe_all(const Config& config, const util::ProgressReceiver& progress_receiver)
+wipe_all(const Config& config, const Util::ProgressReceiver& progress_receiver)
{
- util::for_each_level_1_subdir(
+ Util::for_each_level_1_subdir(
config.cache_dir(), wipe_dir, progress_receiver);
}
#pragma once
-#include "util.hpp"
+#include "Util.hpp"
#include <string>
void clean_up_dir(const std::string& subdir,
uint64_t max_size,
uint32_t max_files,
- const util::ProgressReceiver& progress_receiver);
+ const Util::ProgressReceiver& progress_receiver);
void clean_up_all(const Config& config,
- const util::ProgressReceiver& progress_receiver);
+ const Util::ProgressReceiver& progress_receiver);
void wipe_all(const Config& config,
- const util::ProgressReceiver& progress_receiver);
+ const Util::ProgressReceiver& progress_receiver);
void
compress_stats(const Config& config,
- const util::ProgressReceiver& progress_receiver)
+ const Util::ProgressReceiver& progress_receiver)
{
uint64_t on_disk_size = 0;
uint64_t compr_size = 0;
uint64_t compr_orig_size = 0;
uint64_t incompr_size = 0;
- util::for_each_level_1_subdir(
+ Util::for_each_level_1_subdir(
config.cache_dir(),
[&](const std::string& subdir,
- const util::ProgressReceiver& sub_progress_receiver) {
+ const Util::ProgressReceiver& sub_progress_receiver) {
std::vector<std::shared_ptr<CacheFile>> files;
- util::get_level_1_files(
+ Util::get_level_1_files(
subdir,
[&](double progress) { sub_progress_receiver(progress / 2); },
files);
#pragma once
#include "Config.hpp"
-#include "util.hpp"
+#include "Util.hpp"
void compress_stats(const Config& config,
- const util::ProgressReceiver& progress_receiver);
+ const Util::ProgressReceiver& progress_receiver);
#include "Config.hpp"
#include "Error.hpp"
+#include "Util.hpp"
#include "ccache.hpp"
-#include <algorithm>
#include <fmt/core.h>
-#include <fstream>
#include <string>
#ifdef HAVE_PWD_H
char* tmpl = format("%s.%s", *fname, tmp_string());
int fd = mkstemp(tmpl);
if (fd == -1 && errno == ENOENT) {
- if (!util::create_dir(util::dir_name(*fname))) {
+ if (!Util::create_dir(Util::dir_name(*fname))) {
fatal("Failed to create directory %s: %s",
x_dirname(*fname),
strerror(errno));
return (double)time(NULL);
#endif
}
-
-namespace {
-
-void
-get_cache_files_internal(const std::string& dir,
- uint8_t level,
- const util::ProgressReceiver& progress_receiver,
- std::vector<std::shared_ptr<CacheFile>>& files)
-{
- DIR* d = opendir(dir.c_str());
- if (!d) {
- return;
- }
-
- std::vector<std::string> directories;
- dirent* de;
- while ((de = readdir(d))) {
- std::string name = de->d_name;
- if (name == "" || name == "." || name == ".." || name == "CACHEDIR.TAG"
- || name == "stats" || util::starts_with(name, ".nfs")) {
- continue;
- }
-
- if (name.length() == 1) {
- directories.push_back(name);
- } else {
- files.push_back(
- std::make_shared<CacheFile>(fmt::format("{}/{}", dir, name)));
- }
- }
- closedir(d);
-
- if (level == 1) {
- progress_receiver(1.0 / (directories.size() + 1));
- }
-
- for (size_t i = 0; i < directories.size(); ++i) {
- get_cache_files_internal(
- dir + "/" + directories[i], level + 1, progress_receiver, files);
- if (level == 1) {
- progress_receiver(1.0 * (i + 1) / (directories.size() + 1));
- }
- }
-}
-
-} // namespace
-
-namespace util {
-
-std::string
-base_name(const std::string& path)
-{
- size_t n = path.rfind('/');
-#ifdef _WIN32
- size_t n2 = path.rfind('\\');
- if (n2 != std::string::npos && n2 > n) {
- n = n2;
- }
-#endif
- return n == std::string::npos ? path : path.substr(n + 1);
-}
-
-bool
-create_dir(const std::string& dir)
-{
- struct stat st;
- if (stat(dir.c_str(), &st) == 0) {
- if (S_ISDIR(st.st_mode)) {
- return true;
- } else {
- errno = ENOTDIR;
- return false;
- }
- } else {
- if (!create_dir(util::dir_name(dir))) {
- return false;
- }
- int result = mkdir(dir.c_str(), 0777);
- // Treat an already existing directory as OK since the file system could
- // have changed in between calling stat and actually creating the
- // directory. This can happen when there are multiple instances of ccache
- // running and trying to create the same directory chain, which usually is
- // the case when the cache root does not initially exist. As long as one of
- // the processes creates the directories then our condition is satisfied
- // and we avoid a race condition.
- return result == 0 || errno == EEXIST;
- }
-}
-
-std::pair<int, std::string>
-create_temp_fd(const std::string& path_prefix)
-{
- char* tmp_path = x_strdup(path_prefix.c_str());
- int fd = create_tmp_fd(&tmp_path);
- std::string actual_path = tmp_path;
- free(tmp_path);
- return {fd, actual_path};
-}
-
-std::string
-dir_name(const std::string& path)
-{
- size_t n = path.rfind('/');
-#ifdef _WIN32
- size_t n2 = path.rfind('\\');
- if (n2 != std::string::npos && n2 > n) {
- n = n2;
- }
-#endif
- if (n == std::string::npos) {
- return ".";
- }
- return n == 0 ? "/" : path.substr(0, n);
-}
-
-bool
-ends_with(const std::string& string, const std::string& suffix)
-{
- return suffix.length() <= string.length()
- && string.compare(
- string.length() - suffix.length(), suffix.length(), suffix)
- == 0;
-}
-
-void
-for_each_level_1_subdir(const std::string& cache_dir,
- const SubdirVisitor& subdir_visitor,
- const ProgressReceiver& progress_receiver)
-{
- for (int i = 0; i <= 0xF; i++) {
- double progress = 1.0 * i / 16;
- progress_receiver(progress);
- std::string subdir_path = fmt::format("{}/{:x}", cache_dir, i);
- subdir_visitor(subdir_path, [&](double inner_progress) {
- progress_receiver(progress + inner_progress / 16);
- });
- }
- progress_receiver(1.0);
-}
-
-void
-get_level_1_files(const std::string& dir,
- const ProgressReceiver& progress_receiver,
- std::vector<std::shared_ptr<CacheFile>>& files)
-{
- get_cache_files_internal(dir, 1, progress_receiver, files);
-}
-
-int
-parse_int(const std::string& value)
-{
- size_t end;
- long result;
- bool failed = false;
- try {
- result = std::stol(value, &end, 10);
- } catch (std::exception&) {
- failed = true;
- }
- if (failed || end != value.size() || result < std::numeric_limits<int>::min()
- || result > std::numeric_limits<int>::max()) {
- throw Error(fmt::format("invalid integer: \"{}\"", value));
- }
- return result;
-}
-
-std::string
-read_file(const std::string& path)
-{
- std::ifstream file(path);
- if (!file) {
- throw Error(fmt::format("{}: {}", path, strerror(errno)));
- }
- return std::string(std::istreambuf_iterator<char>(file),
- std::istreambuf_iterator<char>());
-}
-
-bool
-starts_with(const std::string& string, const std::string& prefix)
-{
- return prefix.length() <= string.length()
- && string.compare(0, prefix.length(), prefix) == 0;
-}
-
-std::string
-strip_whitespace(const std::string& string)
-{
- auto is_space = [](int ch) { return std::isspace(ch); };
- auto start = std::find_if_not(string.begin(), string.end(), is_space);
- auto end = std::find_if_not(string.rbegin(), string.rend(), is_space).base();
- return start < end ? std::string(start, end) : std::string();
-}
-
-std::string
-to_lowercase(const std::string& string)
-{
- std::string result = string;
- std::transform(result.begin(), result.end(), result.begin(), tolower);
- return result;
-}
-
-// Write file data from a string.
-void
-write_file(const std::string& path, const std::string& data, bool binary)
-{
- std::ofstream file(path,
- binary ? std::ios::out | std::ios::binary : std::ios::out);
- if (!file) {
- throw Error(fmt::format("{}: {}", path, strerror(errno)));
- }
- file << data;
-}
-
-} // namespace util
// this program; if not, write to the Free Software Foundation, Inc., 51
// Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+#include "Util.hpp"
#include "ccache.hpp"
-#include "util.hpp"
// This function acquires a lockfile for the given path. Returns true if the
// lock was acquired, otherwise false. If the lock has been considered stale
cc_log("lockfile_acquire: open WRONLY %s: %s", lockfile, strerror(errno));
if (saved_errno == ENOENT) {
// Directory doesn't exist?
- if (util::create_dir(util::dir_name(lockfile))) {
+ if (Util::create_dir(Util::dir_name(lockfile))) {
// OK. Retry.
continue;
}
cc_log("lockfile_acquire: symlink %s: %s", lockfile, strerror(saved_errno));
if (saved_errno == ENOENT) {
// Directory doesn't exist?
- if (util::create_dir(util::dir_name(lockfile))) {
+ if (Util::create_dir(Util::dir_name(lockfile))) {
// OK. Retry.
continue;
}
#include "framework.hpp"
-#include "../src/util.hpp"
+#include "../src/Util.hpp"
#include "util.hpp"
#include <float.h>
printf("=== SUITE: %s ===\n", name);
}
dir_before_suite = gnu_getcwd();
- util::create_dir(name);
+ Util::create_dir(name);
cct_chdir(name);
current_suite = name;
}
printf("--- TEST: %s ---\n", name);
}
dir_before_test = gnu_getcwd();
- util::create_dir(name);
+ Util::create_dir(name);
cct_chdir(name);
current_test = name;
#include "../src/Config.hpp"
#include "../src/Error.hpp"
+#include "../src/Util.hpp"
#include "../src/ccache.hpp"
-#include "../src/util.hpp"
#include <catch.hpp>
#include <fmt/core.h>
std::string base_dir = fmt::format("C:/{0}/foo/{0}", user);
#endif
- util::write_file(
+ Util::write_file(
"ccache.conf",
"base_dir = " + base_dir + "\n"
"cache_dir=\n"
SECTION("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"),
Equals("ccache.conf:1: missing equal sign"));
}
SECTION("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"));
}
SECTION("invalid bool")
{
- util::write_file("ccache.conf", "disable=");
+ Util::write_file("ccache.conf", "disable=");
REQUIRE_THROWS_WITH(config.update_from_file("ccache.conf"),
Equals("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"),
Equals("ccache.conf:1: not a boolean value: \"foo\""));
}
SECTION("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"),
Equals("ccache.conf:1: syntax error: missing '}' after \"foo\""));
- // Other cases tested in test_util.c.
+ // Other cases tested in test_Util.c.
}
SECTION("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::numeric_limits<uint32_t>::max());
}
SECTION("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"),
Equals("ccache.conf:1: invalid size: \"foo\""));
- // Other cases tested in test_util.c.
+ // Other cases tested in test_Util.c.
}
SECTION("invalid sloppiness")
{
- util::write_file("ccache.conf", "sloppiness = file_macro, foo");
+ Util::write_file("ccache.conf", "sloppiness = file_macro, foo");
REQUIRE_THROWS_WITH(config.update_from_file("ccache.conf"),
Equals("ccache.conf:1: unknown sloppiness: \"foo\""));
}
SECTION("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"),
Equals("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"),
Equals("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"),
Equals("ccache.conf:1: invalid unsigned integer: \"foo\""));
SECTION("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"),
Equals("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"));
}
SECTION("bad dir levels")
{
- util::write_file("ccache.conf", "cache_dir_levels = 0");
+ Util::write_file("ccache.conf", "cache_dir_levels = 0");
try {
config.update_from_file("ccache.conf");
CHECK(false);
== "ccache.conf:1: cache directory levels must be between 1 and 8");
}
- util::write_file("ccache.conf", "cache_dir_levels = 9");
+ Util::write_file("ccache.conf", "cache_dir_levels = 9");
try {
config.update_from_file("ccache.conf");
CHECK(false);
{
SECTION("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("ccache.conf");
CHECK(content == "path = vanilla\ncompiler = chocolate\n");
}
SECTION("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("ccache.conf");
CHECK(content == "path = vanilla\nstats = chocolate\n");
}
SECTION("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("ccache.conf");
CHECK(content == "path = chocolate\nstats = chocolate\n");
}
}
TEST_CASE("Config::visit_items")
{
- util::write_file(
+ Util::write_file(
"test.conf",
"base_dir = /bd\n"
"cache_dir = cd\n"
--- /dev/null
+// Copyright (C) 2019 Joel Rosdahl and other contributors
+//
+// See doc/AUTHORS.adoc for a complete list of contributors.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Software Foundation, Inc., 51
+// Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+#include "../src/Util.hpp"
+
+#include <catch.hpp>
+
+using Catch::Equals;
+
+TEST_CASE("Util::base_name")
+{
+ CHECK(Util::base_name("") == "");
+ CHECK(Util::base_name(".") == ".");
+ CHECK(Util::base_name("foo") == "foo");
+ CHECK(Util::base_name("/") == "");
+ CHECK(Util::base_name("/foo") == "foo");
+ CHECK(Util::base_name("/foo/bar/f.txt") == "f.txt");
+}
+
+TEST_CASE("Util::create_dir")
+{
+ CHECK(Util::create_dir("/"));
+
+ CHECK(Util::create_dir("create/dir"));
+ struct stat st;
+ CHECK(stat("create/dir", &st) == 0);
+ CHECK(S_ISDIR(st.st_mode));
+
+ Util::write_file("create/dir/file", "");
+ CHECK(!Util::create_dir("create/dir/file"));
+}
+
+TEST_CASE("Util::dir_name")
+{
+ CHECK(Util::dir_name("") == ".");
+ CHECK(Util::dir_name(".") == ".");
+ CHECK(Util::dir_name("foo") == ".");
+ CHECK(Util::dir_name("/") == "/");
+ CHECK(Util::dir_name("/foo") == "/");
+ CHECK(Util::dir_name("/foo/bar/f.txt") == "/foo/bar");
+}
+
+TEST_CASE("Util::ends_with")
+{
+ CHECK(Util::ends_with("", ""));
+ CHECK(Util::ends_with("x", ""));
+ CHECK(Util::ends_with("x", "x"));
+ CHECK(Util::ends_with("xy", ""));
+ CHECK(Util::ends_with("xy", "y"));
+ CHECK(Util::ends_with("xy", "xy"));
+ CHECK(Util::ends_with("xyz", ""));
+ CHECK(Util::ends_with("xyz", "z"));
+ CHECK(Util::ends_with("xyz", "yz"));
+ CHECK(Util::ends_with("xyz", "xyz"));
+
+ CHECK_FALSE(Util::ends_with("", "x"));
+ CHECK_FALSE(Util::ends_with("x", "y"));
+ CHECK_FALSE(Util::ends_with("x", "xy"));
+}
+
+TEST_CASE("Util::for_each_level_1_subdir")
+{
+ std::vector<std::string> actual;
+ Util::for_each_level_1_subdir(
+ "cache_dir",
+ [&](const std::string& subdir, const Util::ProgressReceiver&) {
+ actual.push_back(subdir);
+ },
+ [](double) {});
+
+ std::vector<std::string> expected = {
+ "cache_dir/0",
+ "cache_dir/1",
+ "cache_dir/2",
+ "cache_dir/3",
+ "cache_dir/4",
+ "cache_dir/5",
+ "cache_dir/6",
+ "cache_dir/7",
+ "cache_dir/8",
+ "cache_dir/9",
+ "cache_dir/a",
+ "cache_dir/b",
+ "cache_dir/c",
+ "cache_dir/d",
+ "cache_dir/e",
+ "cache_dir/f",
+ };
+ CHECK(actual == expected);
+}
+
+TEST_CASE("Util::get_level_1_files")
+{
+ Util::create_dir("e/m/p/t/y");
+
+ 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");
+
+ std::vector<std::shared_ptr<CacheFile>> files;
+ auto null_receiver = [](double) {};
+
+ SECTION("nonexistent subdirectory")
+ {
+ Util::get_level_1_files("2", null_receiver, files);
+ CHECK(files.empty());
+ }
+
+ SECTION("empty subdirectory")
+ {
+ Util::get_level_1_files("e", null_receiver, files);
+ CHECK(files.empty());
+ }
+
+ SECTION("simple case")
+ {
+ Util::get_level_1_files("0", null_receiver, files);
+ REQUIRE(files.size() == 4);
+
+ // Files within a level are in arbitrary order, sort them to be able to
+ // verify them.
+ std::sort(files.begin(),
+ files.end(),
+ [](const std::shared_ptr<CacheFile>& f1,
+ const std::shared_ptr<CacheFile>& f2) {
+ return f1->path() < f2->path();
+ });
+
+ CHECK(files[0]->path() == "0/1/file_b");
+ CHECK(files[0]->stat().st_size == 1);
+ CHECK(files[1]->path() == "0/1/file_c");
+ CHECK(files[1]->stat().st_size == 2);
+ CHECK(files[2]->path() == "0/f/c/file_d");
+ CHECK(files[2]->stat().st_size == 3);
+ CHECK(files[3]->path() == "0/file_a");
+ CHECK(files[3]->stat().st_size == 0);
+ }
+}
+
+TEST_CASE("Util::parse_int")
+{
+ CHECK(Util::parse_int("0") == 0);
+ CHECK(Util::parse_int("2") == 2);
+ CHECK(Util::parse_int("-17") == -17);
+ CHECK(Util::parse_int("42") == 42);
+ CHECK(Util::parse_int("0666") == 666);
+ CHECK(Util::parse_int(" 777") == 777);
+
+ CHECK_THROWS_WITH(Util::parse_int(""), Equals("invalid integer: \"\""));
+ CHECK_THROWS_WITH(Util::parse_int("x"), Equals("invalid integer: \"x\""));
+ CHECK_THROWS_WITH(Util::parse_int("0x"), Equals("invalid integer: \"0x\""));
+ CHECK_THROWS_WITH(Util::parse_int("0x4"), Equals("invalid integer: \"0x4\""));
+ CHECK_THROWS_WITH(Util::parse_int("0 "), Equals("invalid integer: \"0 \""));
+}
+
+TEST_CASE("Util::read_file and Util::write_file")
+{
+ Util::write_file("test", "foo\nbar\n");
+ std::string data = Util::read_file("test");
+ CHECK(data == "foo\nbar\n");
+}
+
+TEST_CASE("Util::starts_with")
+{
+ CHECK(Util::starts_with("", ""));
+ CHECK(Util::starts_with("x", ""));
+ CHECK(Util::starts_with("x", "x"));
+ CHECK(Util::starts_with("xy", ""));
+ CHECK(Util::starts_with("xy", "x"));
+ CHECK(Util::starts_with("xy", "xy"));
+ CHECK(Util::starts_with("xyz", ""));
+ CHECK(Util::starts_with("xyz", "x"));
+ CHECK(Util::starts_with("xyz", "xy"));
+ CHECK(Util::starts_with("xyz", "xyz"));
+
+ CHECK_FALSE(Util::starts_with("", "x"));
+ CHECK_FALSE(Util::starts_with("x", "y"));
+ CHECK_FALSE(Util::starts_with("x", "xy"));
+}
+
+TEST_CASE("Util::strip_whitespace")
+{
+ CHECK(Util::strip_whitespace("") == "");
+ CHECK(Util::strip_whitespace("x") == "x");
+ CHECK(Util::strip_whitespace(" x") == "x");
+ CHECK(Util::strip_whitespace("x ") == "x");
+ CHECK(Util::strip_whitespace(" x ") == "x");
+ CHECK(Util::strip_whitespace(" \n\tx \n\t") == "x");
+ CHECK(Util::strip_whitespace(" x y ") == "x y");
+}
+
+TEST_CASE("Util::to_lowercase")
+{
+ CHECK(Util::to_lowercase("") == "");
+ CHECK(Util::to_lowercase("x") == "x");
+ CHECK(Util::to_lowercase("X") == "x");
+ CHECK(Util::to_lowercase(" x_X@") == " x_x@");
+}
+++ /dev/null
-// Copyright (C) 2019 Joel Rosdahl and other contributors
-//
-// See doc/AUTHORS.adoc for a complete list of contributors.
-//
-// This program is free software; you can redistribute it and/or modify it
-// under the terms of the GNU General Public License as published by the Free
-// Software Foundation; either version 3 of the License, or (at your option)
-// any later version.
-//
-// This program is distributed in the hope that it will be useful, but WITHOUT
-// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
-// more details.
-//
-// You should have received a copy of the GNU General Public License along with
-// this program; if not, write to the Free Software Foundation, Inc., 51
-// Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-
-#include "../src/util.hpp"
-
-#include <catch.hpp>
-
-using Catch::Equals;
-
-TEST_CASE("util::base_name")
-{
- CHECK(util::base_name("") == "");
- CHECK(util::base_name(".") == ".");
- CHECK(util::base_name("foo") == "foo");
- CHECK(util::base_name("/") == "");
- CHECK(util::base_name("/foo") == "foo");
- CHECK(util::base_name("/foo/bar/f.txt") == "f.txt");
-}
-
-TEST_CASE("util::create_dir")
-{
- CHECK(util::create_dir("/"));
-
- CHECK(util::create_dir("create/dir"));
- struct stat st;
- CHECK(stat("create/dir", &st) == 0);
- CHECK(S_ISDIR(st.st_mode));
-
- util::write_file("create/dir/file", "");
- CHECK(!util::create_dir("create/dir/file"));
-}
-
-TEST_CASE("util::dir_name")
-{
- CHECK(util::dir_name("") == ".");
- CHECK(util::dir_name(".") == ".");
- CHECK(util::dir_name("foo") == ".");
- CHECK(util::dir_name("/") == "/");
- CHECK(util::dir_name("/foo") == "/");
- CHECK(util::dir_name("/foo/bar/f.txt") == "/foo/bar");
-}
-
-TEST_CASE("util::ends_with")
-{
- CHECK(util::ends_with("", ""));
- CHECK(util::ends_with("x", ""));
- CHECK(util::ends_with("x", "x"));
- CHECK(util::ends_with("xy", ""));
- CHECK(util::ends_with("xy", "y"));
- CHECK(util::ends_with("xy", "xy"));
- CHECK(util::ends_with("xyz", ""));
- CHECK(util::ends_with("xyz", "z"));
- CHECK(util::ends_with("xyz", "yz"));
- CHECK(util::ends_with("xyz", "xyz"));
-
- CHECK_FALSE(util::ends_with("", "x"));
- CHECK_FALSE(util::ends_with("x", "y"));
- CHECK_FALSE(util::ends_with("x", "xy"));
-}
-
-TEST_CASE("util::for_each_level_1_subdir")
-{
- std::vector<std::string> actual;
- util::for_each_level_1_subdir(
- "cache_dir",
- [&](const std::string& subdir, const util::ProgressReceiver&) {
- actual.push_back(subdir);
- },
- [](double) {});
-
- std::vector<std::string> expected = {
- "cache_dir/0",
- "cache_dir/1",
- "cache_dir/2",
- "cache_dir/3",
- "cache_dir/4",
- "cache_dir/5",
- "cache_dir/6",
- "cache_dir/7",
- "cache_dir/8",
- "cache_dir/9",
- "cache_dir/a",
- "cache_dir/b",
- "cache_dir/c",
- "cache_dir/d",
- "cache_dir/e",
- "cache_dir/f",
- };
- CHECK(actual == expected);
-}
-
-TEST_CASE("util::get_level_1_files")
-{
- util::create_dir("e/m/p/t/y");
-
- 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");
-
- std::vector<std::shared_ptr<CacheFile>> files;
- auto null_receiver = [](double) {};
-
- SECTION("nonexistent subdirectory")
- {
- util::get_level_1_files("2", null_receiver, files);
- CHECK(files.empty());
- }
-
- SECTION("empty subdirectory")
- {
- util::get_level_1_files("e", null_receiver, files);
- CHECK(files.empty());
- }
-
- SECTION("simple case")
- {
- util::get_level_1_files("0", null_receiver, files);
- REQUIRE(files.size() == 4);
-
- // Files within a level are in arbitrary order, sort them to be able to
- // verify them.
- std::sort(files.begin(),
- files.end(),
- [](const std::shared_ptr<CacheFile>& f1,
- const std::shared_ptr<CacheFile>& f2) {
- return f1->path() < f2->path();
- });
-
- CHECK(files[0]->path() == "0/1/file_b");
- CHECK(files[0]->stat().st_size == 1);
- CHECK(files[1]->path() == "0/1/file_c");
- CHECK(files[1]->stat().st_size == 2);
- CHECK(files[2]->path() == "0/f/c/file_d");
- CHECK(files[2]->stat().st_size == 3);
- CHECK(files[3]->path() == "0/file_a");
- CHECK(files[3]->stat().st_size == 0);
- }
-}
-
-TEST_CASE("util::parse_int")
-{
- CHECK(util::parse_int("0") == 0);
- CHECK(util::parse_int("2") == 2);
- CHECK(util::parse_int("-17") == -17);
- CHECK(util::parse_int("42") == 42);
- CHECK(util::parse_int("0666") == 666);
- CHECK(util::parse_int(" 777") == 777);
-
- CHECK_THROWS_WITH(util::parse_int(""), Equals("invalid integer: \"\""));
- CHECK_THROWS_WITH(util::parse_int("x"), Equals("invalid integer: \"x\""));
- CHECK_THROWS_WITH(util::parse_int("0x"), Equals("invalid integer: \"0x\""));
- CHECK_THROWS_WITH(util::parse_int("0x4"), Equals("invalid integer: \"0x4\""));
- CHECK_THROWS_WITH(util::parse_int("0 "), Equals("invalid integer: \"0 \""));
-}
-
-TEST_CASE("util::read_file and util::write_file")
-{
- util::write_file("test", "foo\nbar\n");
- std::string data = util::read_file("test");
- CHECK(data == "foo\nbar\n");
-}
-
-TEST_CASE("util::starts_with")
-{
- CHECK(util::starts_with("", ""));
- CHECK(util::starts_with("x", ""));
- CHECK(util::starts_with("x", "x"));
- CHECK(util::starts_with("xy", ""));
- CHECK(util::starts_with("xy", "x"));
- CHECK(util::starts_with("xy", "xy"));
- CHECK(util::starts_with("xyz", ""));
- CHECK(util::starts_with("xyz", "x"));
- CHECK(util::starts_with("xyz", "xy"));
- CHECK(util::starts_with("xyz", "xyz"));
-
- CHECK_FALSE(util::starts_with("", "x"));
- CHECK_FALSE(util::starts_with("x", "y"));
- CHECK_FALSE(util::starts_with("x", "xy"));
-}
-
-TEST_CASE("util::strip_whitespace")
-{
- CHECK(util::strip_whitespace("") == "");
- CHECK(util::strip_whitespace("x") == "x");
- CHECK(util::strip_whitespace(" x") == "x");
- CHECK(util::strip_whitespace("x ") == "x");
- CHECK(util::strip_whitespace(" x ") == "x");
- CHECK(util::strip_whitespace(" \n\tx \n\t") == "x");
- CHECK(util::strip_whitespace(" x y ") == "x y");
-}
-
-TEST_CASE("util::to_lowercase")
-{
- CHECK(util::to_lowercase("") == "");
- CHECK(util::to_lowercase("x") == "x");
- CHECK(util::to_lowercase("X") == "x");
- CHECK(util::to_lowercase(" x_X@") == " x_x@");
-}