utils: add join_paths + tests

This commit is contained in:
Dirk-Jan C. Binnema
2023-01-28 18:46:35 +02:00
parent daef904ca1
commit 25635c5cfe
2 changed files with 50 additions and 18 deletions

View File

@ -78,13 +78,13 @@ Mu::play (const std::string& path)
argv[0] = program_path->c_str(); argv[0] = program_path->c_str();
argv[1] = path.c_str(); argv[1] = path.c_str();
argv[2] = nullptr; argv[2] = nullptr;
GError *err{}; GError *err{};
if (!g_spawn_async ({}, (gchar**)&argv, {}, G_SPAWN_SEARCH_PATH, maybe_setsid, if (!g_spawn_async ({}, (gchar**)&argv, {}, G_SPAWN_SEARCH_PATH, maybe_setsid,
{}, {}, &err)) {}, {}, &err))
return Err(Error::Code::File, &err/*consumes*/, "failed to open '%s' with '%s'", return Err(Error::Code::File, &err/*consumes*/, "failed to open '%s' with '%s'",
path. c_str(), program_path->c_str()); path. c_str(), program_path->c_str());
return Ok(); return Ok();
} }
@ -109,7 +109,7 @@ Mu::determine_dtype (const std::string& path, bool use_lstat)
{ {
int res; int res;
struct stat statbuf{}; struct stat statbuf{};
if (use_lstat) if (use_lstat)
res = ::lstat(path.c_str(), &statbuf); res = ::lstat(path.c_str(), &statbuf);
else else
@ -257,6 +257,17 @@ test_program_in_path(void)
g_assert_true(!!program_in_path("ls")); g_assert_true(!!program_in_path("ls"));
} }
static void
test_join_paths()
{
assert_equal(join_paths(), "");
assert_equal(join_paths("a"), "a");
assert_equal(join_paths("a", "b"), "a/b");
assert_equal(join_paths("/a/b///c/d//", "e"), "/a/b/c/d/e");
}
int int
main(int argc, char* argv[]) main(int argc, char* argv[])
@ -272,12 +283,12 @@ main(int argc, char* argv[])
test_check_dir_03); test_check_dir_03);
g_test_add_func("/utils/check-dir-04", g_test_add_func("/utils/check-dir-04",
test_check_dir_04); test_check_dir_04);
g_test_add_func("/utils/determine-dtype-with-lstat", g_test_add_func("/utils/determine-dtype-with-lstat",
test_determine_dtype_with_lstat); test_determine_dtype_with_lstat);
g_test_add_func("/utils/program-in-path", g_test_add_func("/utils/program-in-path",
test_program_in_path); test_program_in_path);
g_test_add_func("/utils/join-paths",
test_join_paths);
return g_test_run(); return g_test_run();
} }

View File

@ -24,8 +24,8 @@
#include <cinttypes> #include <cinttypes>
#include <sys/stat.h> #include <sys/stat.h>
#include <utils/mu-sexp.hh>
#include <utils/mu-option.hh> #include <utils/mu-option.hh>
#include <utils/mu-regex.hh>
namespace Mu { namespace Mu {
@ -43,22 +43,22 @@ namespace Mu {
*/ */
Result<void> play(const std::string& path); Result<void> play(const std::string& path);
/** /**
* Find program in PATH * Find program in PATH
* *
* @param name the name of the program * @param name the name of the program
* *
* @return either the full path to program, or Nothing if not found. * @return either the full path to program, or Nothing if not found.
*/ */
Option<std::string> program_in_path(const std::string& name); Option<std::string> program_in_path(const std::string& name);
/** /**
* Check if the directory has the given attributes * Check if the directory has the given attributes
* *
* @param path path to dir * @param path path to dir
* @param readable is it readable? * @param readable is it readable?
* @param writeable is it writable? * @param writeable is it writable?
* *
* @return true if is is a directory with given attributes; false otherwise. * @return true if is is a directory with given attributes; false otherwise.
*/ */
bool check_dir(const std::string& path, bool readable, bool writeable); bool check_dir(const std::string& path, bool readable, bool writeable);
@ -72,8 +72,8 @@ bool check_dir(const std::string& path, bool readable, bool writeable);
* @return * @return
*/ */
std::string canonicalize_filename(const std::string& path, const std::string& relative_to); std::string canonicalize_filename(const std::string& path, const std::string& relative_to);
/* /*
* for OSs with out support for direntry->d_type, like Solaris * for OSs with out support for direntry->d_type, like Solaris
*/ */
#ifndef DT_UNKNOWN #ifndef DT_UNKNOWN
@ -108,7 +108,7 @@ enum {
* *
* @return DT_REG, DT_DIR, DT_LNK, or DT_UNKNOWN (other values are not supported * @return DT_REG, DT_DIR, DT_LNK, or DT_UNKNOWN (other values are not supported
* currently) * currently)
*/ */
uint8_t determine_dtype(const std::string& path, bool use_lstat); uint8_t determine_dtype(const std::string& path, bool use_lstat);
@ -135,7 +135,28 @@ enum struct RuntimePath {
* @return the path name * @return the path name
*/ */
std::string runtime_path(RuntimePath path, const std::string& muhome=""); std::string runtime_path(RuntimePath path, const std::string& muhome="");
/**
* Join path components into a path (with '/')
*
* @param s a string-convertible value
* @param args 0 or more string-convertible values
*
* @return the path
*/
static inline std::string join_paths() { return {}; }
template<typename S, typename...Args>
std::string join_paths(S&& s, Args...args) {
static std::string sepa{"/"};
auto&& str{std::string{std::forward<S>(s)}};
if (auto&& rest{join_paths(std::forward<Args>(args)...)}; !rest.empty())
str += (sepa + rest);
static auto rx = Regex::make("//*").value();
return rx.replace(str, sepa);
} }
#endif /* MU_UTILS_FILE_HH__ */
} // namespace Mu
#endif /* MU_UTILS_FILE_HH__ */