message/flags: add flags_from_path

Borrow from mu-maildir, to which we cannot link.
This commit is contained in:
Dirk-Jan C. Binnema 2022-03-28 22:14:05 +03:00
parent 27ebfb3b3c
commit 9f062ae482
3 changed files with 99 additions and 3 deletions

View File

@ -39,6 +39,90 @@ Mu::flags_to_string(Flags flags)
}
/*
* 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 Option<DirFile>
base_message_dir_file(const std::string& path)
{
constexpr auto newdir{ G_DIR_SEPARATOR_S "new"};
if (path.empty())
return Nothing;
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 DirFile{std::move(mdir), std::move(bname), is_new};
}
Mu::Option<Mu::Flags>
Mu::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 Nothing;
/* a message under new/ is just.. New. Filename is not considered */
if (dirfile->is_new)
return Flags::New;
/* it's cur/ message, so parse the file name */
const auto parts{message_file_parts(dirfile->file)};
return flags_from_absolute_expr(parts.flags_suffix, true/*ignore invalid*/);
}
/*
* flags & flag-info
*/

View File

@ -278,7 +278,7 @@ flags_from_delta_expr(std::string_view expr, Flags flags,
* @return either messages flags or Nothing in case of error.
*/
constexpr Option<Flags>
flags_from_expr(std::string_view expr,
flags_from_expr(std::string_view expr,
Option<Flags> flags = Nothing)
{
if (expr.empty())
@ -291,6 +291,19 @@ flags_from_expr(std::string_view expr,
return flags_from_absolute_expr(expr, true);
}
/**
* Get the Maildir flags from the full path of a mailfile. The flags are as
* specified in http://cr.yp.to/proto/maildir.html, plus MU_MSG_FLAG_NEW for new
* messages, ie the ones that live in new/. The flags are logically OR'ed. Note
* that the file does not have to exist; the flags are based on the path only.
*
* @param pathname of a mailfile; it does not have to refer to an existing
* file/message
*
* @return the message flags or Nothing
*/
Option<Flags> flags_from_path(const std::string& path);
/**
* Filter out flags which are not in the given category
*

View File

@ -305,8 +305,7 @@ base_message_dir_file(const std::string& path)
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::mu_maildir_flags_from_path(const std::string& path)