diff --git a/src/common.cc b/src/common.cc index 369ed376f..d9ce8fb48 100644 --- a/src/common.cc +++ b/src/common.cc @@ -38,6 +38,7 @@ #include #include #include +#include #include #include @@ -140,8 +141,20 @@ double get_time() { /// - `$HOME/a/b/../c/../../conky` -> `/home/conky_user/conky` std::filesystem::path to_real_path(const std::filesystem::path &source) { try { - std::string expanded = variable_substitute(source.string()); - return std::filesystem::canonical(expanded); + std::string input; + if (source.string().compare(0, 1, "~") == 0) { + const char *home = std::getenv("HOME"); + if (home) { + input = std::string(home) + source.string().substr(1); + } else { + input = source.string(); // Fallback if HOME is not set + } + } else { + input = source.string(); + } + std::string expanded = variable_substitute(input); + std::filesystem::path absolute = std::filesystem::absolute(expanded); + return std::filesystem::weakly_canonical(absolute); } catch (const std::filesystem::filesystem_error &e) { // file not found or permission issues NORM_ERR("can't canonicalize path: %s", source.c_str()); diff --git a/tests/test-common.cc b/tests/test-common.cc index 69bd12415..641ae2bbd 100644 --- a/tests/test-common.cc +++ b/tests/test-common.cc @@ -65,7 +65,13 @@ std::string get_invalid_environment_variable_name() { return variable_name; } -TEST_CASE("to_real_path becomes homedir", "[to_real_path]") { +TEST_CASE("to_real_path simplifies complex paths", "[to_real_path]") { + REQUIRE(to_real_path("/a/b/c/../d/../../e") == "/a/e"); +} +TEST_CASE("to_real_path resolves variables", "[to_real_path]") { + REQUIRE(to_real_path("$HOME/test") == std::string(getenv("HOME")) + "/test"); +} +TEST_CASE("to_real_path resolves `~` symbol", "[to_real_path]") { REQUIRE(to_real_path("~/test") == std::string(getenv("HOME")) + "/test"); }