mu-maildir: refactor some duplicate code

mu-flags & mu-maildir were having some duplicate code; refactor it into mu-message-file.{cc,hh}
This commit is contained in:
Dirk-Jan C. Binnema
2022-06-03 21:59:27 +03:00
parent 9c59e894db
commit 172ff25bb6
9 changed files with 311 additions and 256 deletions

View File

@ -247,123 +247,6 @@ Mu::maildir_clear_links(const std::string& path)
return Ok();
}
Result<std::string>
Mu::maildir_from_path(const std::string& path, const std::string& root)
{
const auto pos = path.find(root);
if (pos != 0 || path[root.length()] != '/')
return Err(Error{Error::Code::InvalidArgument,
"root '%s' is not a root for path '%s'",
root.c_str(), path.c_str()});
auto mdir{path.substr(root.length())};
auto slash{mdir.rfind('/')};
if (G_UNLIKELY(slash == std::string::npos) || slash < 4)
return Err(Error{Error::Code::InvalidArgument,
"invalid path: %s", path.c_str()});
mdir.erase(slash);
auto subdir = mdir.data() + slash - 4;
if (G_UNLIKELY(strncmp(subdir, "/cur", 4) != 0 && strncmp(subdir, "/new", 4)))
return Err(Error::Code::InvalidArgument,
"cannot find '/new' or '/cur' - invalid path: %s",
path.c_str());
if (mdir.length() == 4)
return "/";
mdir.erase(mdir.length() - 4);
return Ok(std::move(mdir));
}
/*
* The file-components, ie.
* 1631819685.fb7b279bbb0a7b66.evergrey:2,RS
* => {
* "1631819685.fb7b279bbb0a7b66.evergrey",
* ':',
* "2,",
* "RS"
* }
*/
struct FileParts {
std::string base;
char separator;
std::string flags_suffix;
};
static FileParts
message_file_parts(const std::string& file)
{
const auto pos{file.find_last_of(":!;")};
/* no suffix at all? */
if (pos == std::string::npos ||
pos > file.length() - 3 ||
file[pos + 1] != '2' ||
file[pos + 2] != ',')
return FileParts{ file, ':', {}};
return FileParts {
file.substr(0, pos),
file[pos],
file.substr(pos + 3)
};
}
struct DirFile {
std::string dir;
std::string file;
bool is_new;
};
static Result<DirFile>
base_message_dir_file(const std::string& path)
{
constexpr auto newdir{ G_DIR_SEPARATOR_S "new"};
char *dirname{g_path_get_dirname(path.c_str())};
bool is_new{!!g_str_has_suffix(dirname, newdir)};
std::string mdir{dirname, ::strlen(dirname) - 4};
g_free(dirname);
char *basename{g_path_get_basename(path.c_str())};
std::string bname{basename};
g_free(basename);
return Ok(DirFile{std::move(mdir), std::move(bname), is_new});
}
// refactor: we have the same code in mu-flags.cc
Mu::Result<Mu::Flags>
Mu::maildir_flags_from_path(const std::string& path)
{ /*
* this gets us the source maildir filesystem path, the directory
* in which new/ & cur/ lives, and the source file
*/
auto dirfile{base_message_dir_file(path)};
if (!dirfile)
return Err(std::move(dirfile.error()));
/* a message under new/ is just.. New. Filename is not considered */
if (dirfile->is_new)
return Ok(Flags::New);
/* it's cur/ message, so parse the file name */
const auto parts{message_file_parts(dirfile->file)};
auto flags{flags_from_absolute_expr(parts.flags_suffix,
true/*ignore invalid*/)};
if (!flags)
return Err(Error{Error::Code::InvalidArgument,
"invalid flags ('%s')", parts.flags_suffix.c_str()});
else
return Ok(std::move(flags.value()));
}
static size_t
get_file_size(const std::string& path)