diff --git a/lib/mu-maildir.cc b/lib/mu-maildir.cc index 1b191768..1045ca1b 100644 --- a/lib/mu-maildir.cc +++ b/lib/mu-maildir.cc @@ -147,7 +147,8 @@ check_subdir(const std::string& src, bool& in_cur) } static Mu::Result -get_target_fullpath(const std::string& src, const std::string& targetpath) +get_target_fullpath(const std::string& src, const std::string& targetpath, + bool unique_names) { bool in_cur{}; if (auto&& res = check_subdir(src, in_cur); !res) @@ -159,21 +160,30 @@ get_target_fullpath(const std::string& src, const std::string& targetpath) * including a hash of the srcname in the targetname. This helps if * there are copies of a message (which all have the same basename) */ - auto targetfullpath = format("%s%c%s%c%u_%s", - targetpath.c_str(), - G_DIR_SEPARATOR, in_cur ? "cur" : "new", - G_DIR_SEPARATOR, - g_str_hash(src.c_str()), - srcfile); + std::string fulltargetpath; + if (unique_names) + fulltargetpath = format("%s%c%s%c%u_%s", + targetpath.c_str(), + G_DIR_SEPARATOR, in_cur ? "cur" : "new", + G_DIR_SEPARATOR, + g_str_hash(src.c_str()), + srcfile); + else + fulltargetpath = format("%s%c%s%c%s", + targetpath.c_str(), + G_DIR_SEPARATOR, in_cur ? "cur" : "new", + G_DIR_SEPARATOR, + srcfile); g_free(srcfile); - return targetfullpath; + return fulltargetpath; } Result -Mu::maildir_link(const std::string& src, const std::string& targetpath) +Mu::maildir_link(const std::string& src, const std::string& targetpath, + bool unique_names) { - auto path_res{get_target_fullpath(src, targetpath)}; + auto path_res{get_target_fullpath(src, targetpath, unique_names)}; if (!path_res) return Err(std::move(path_res.error())); diff --git a/lib/mu-maildir.hh b/lib/mu-maildir.hh index f4f38d36..7976b04b 100644 --- a/lib/mu-maildir.hh +++ b/lib/mu-maildir.hh @@ -48,7 +48,7 @@ namespace Mu { * @return a valid result (!!result) or an Error */ Result maildir_mkdir(const std::string& path, mode_t mode=0700, - bool noindex=false); + bool noindex=false); /** * Create a symbolic link to a mail message @@ -57,10 +57,13 @@ Result maildir_mkdir(const std::string& path, mode_t mode=0700, * @param targetpath the path to the target maildir; ie., *not* * MyMaildir/cur, but just MyMaildir/. The function will figure out * the correct subdir then. + * @param unique_names whether to create unique names; should be true unless + * for tests. * * @return a valid result (!!result) or an Error */ -Result maildir_link(const std::string& src, const std::string& targetpath); +Result maildir_link(const std::string& src, const std::string& targetpath, + bool unique_names=true); /** * Recursively delete all the symbolic links in a directory tree diff --git a/lib/tests/test-mu-maildir.cc b/lib/tests/test-mu-maildir.cc index 364e9cdd..c8f06903 100644 --- a/lib/tests/test-mu-maildir.cc +++ b/lib/tests/test-mu-maildir.cc @@ -24,6 +24,7 @@ #include #include #include +#include #include "test-mu-common.hh" #include "mu-maildir.hh" @@ -454,6 +455,47 @@ test_maildir_from_path(void) } } +static void +test_maildir_link() +{ + TempDir tmpdir{false}; + + g_message("%s", tmpdir.path().c_str()); + + g_assert_true(!!maildir_mkdir(tmpdir.path() + "/foo")); + g_assert_true(!!maildir_mkdir(tmpdir.path() + "/bar")); + + const auto srcpath1 = tmpdir.path() + "/foo/cur/msg1"; + const auto srcpath2 = tmpdir.path() + "/foo/new/msg2"; + + { + std::ofstream stream(srcpath1); + stream.write("cur", 3); + g_assert_true(stream.good()); + stream.close(); + } + + { + std::ofstream stream(srcpath2); + stream.write("new", 3); + g_assert_true(stream.good()); + stream.close(); + } + + g_assert_true(!!maildir_link(srcpath1, tmpdir.path() + "/bar", false)); + g_assert_true(!!maildir_link(srcpath2, tmpdir.path() + "/bar", false)); + + const auto dstpath1 = tmpdir.path() + "/bar/cur/msg1"; + const auto dstpath2 = tmpdir.path() + "/bar/new/msg2"; + + g_assert_true(g_access(dstpath1.c_str(), F_OK) == 0); + g_assert_true(g_access(dstpath2.c_str(), F_OK) == 0); + + g_assert_true(!!maildir_clear_links(tmpdir.path() + "/bar")); + g_assert_false(g_access(dstpath1.c_str(), F_OK) == 0); + g_assert_false(g_access(dstpath2.c_str(), F_OK) == 0); +} + int main(int argc, char* argv[]) { @@ -479,11 +521,7 @@ main(int argc, char* argv[]) g_test_add_func("/mu-maildir/mu-maildir-from-path", test_maildir_from_path); - g_log_set_handler( - NULL, - (GLogLevelFlags)(G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL | G_LOG_FLAG_RECURSION), - (GLogFunc)black_hole, - NULL); + g_test_add_func("/mu-maildir/mu-maildir-link", test_maildir_link); return g_test_run(); }