remove some dead code

This commit is contained in:
Dirk-Jan C. Binnema 2021-01-20 11:18:33 +02:00
parent 362c53a7e7
commit 98744c66f7
14 changed files with 49 additions and 1092 deletions

View File

@ -238,7 +238,7 @@ Contacts::add (ContactInfo&& ci)
if (ci.last_seen > ci_existing.last_seen) { // update.
wash(ci.name);
ci_existing.name = std::move(ci.name);
ci_existing.name = std::move(ci.name);
ci_existing.email = std::move(ci.email);
wash(ci.full_address);

View File

@ -207,43 +207,6 @@ Mu::mu_maildir_link (const char* src, const char *targetpath, GError **err)
}
static MuError
process_dir (const char* path, const char *mdir,
MuMaildirWalkMsgCallback msg_cb,
MuMaildirWalkDirCallback dir_cb, gboolean full,
void *data);
static MuError
process_file (const char* fullpath, const char* mdir,
MuMaildirWalkMsgCallback msg_cb, void *data)
{
MuError result;
struct stat statbuf;
if (!msg_cb)
return MU_OK;
if (G_UNLIKELY(access(fullpath, R_OK) != 0)) {
g_warning ("cannot access %s: %s", fullpath,
strerror(errno));
return MU_ERROR;
}
if (G_UNLIKELY(stat (fullpath, &statbuf) != 0)) {
g_warning ("cannot stat %s: %s", fullpath, strerror(errno));
return MU_ERROR;
}
result = (msg_cb)(fullpath, mdir, &statbuf, data);
if (result == MU_STOP)
g_debug ("callback said 'MU_STOP' for %s", fullpath);
else if (result == MU_ERROR)
g_warning ("%s: error in callback (%s)",
__func__, fullpath);
return result;
}
/*
* determine if path is a maildir leaf-dir; ie. if it's 'cur' or 'new'
@ -280,290 +243,6 @@ Mu::mu_maildir_is_leaf_dir (const char *path)
}
/* check if there path contains file; used for checking if there is
* MU_MAILDIR_NOINDEX_FILE or MU_MAILDIR_NOUPDATE_FILE in this
* dir; */
static gboolean
dir_contains_file (const char *path, const char *file)
{
const char* fullpath;
/* static buffer */
fullpath = mu_str_fullpath_s (path, file);
if (access (fullpath, F_OK) == 0)
return TRUE;
else if (G_UNLIKELY(errno != ENOENT && errno != EACCES))
g_warning ("error testing for %s/%s: %s",
fullpath, file, strerror(errno));
return FALSE;
}
static gboolean
is_dotdir_to_ignore (const char* dir)
{
int i;
const char* ignore[] = {
".notmuch",
".nnmaildir",
".#evolution"
}; /* when adding names, check the optimization below */
if (dir[0] != '.')
return FALSE; /* not a dotdir */
if (dir[1] == '\0' || (dir[1] == '.' && dir[2] == '\0'))
return TRUE; /* ignore '.' and '..' */
/* optimization: special dirs have 'n' or '#' in pos 1 */
if (dir[1] != 'n' && dir[1] != '#')
return FALSE; /* not special: don't ignore */
for (i = 0; i != G_N_ELEMENTS(ignore); ++i)
if (strcmp(dir, ignore[i]) == 0)
return TRUE;
return FALSE; /* don't ignore */
}
static gboolean
ignore_dir_entry (struct dirent *entry, unsigned char d_type)
{
if (G_LIKELY(d_type == DT_REG)) {
guint u;
/* ignore emacs tempfiles */
if (entry->d_name[0] == '#')
return TRUE;
/* ignore dovecot metadata */
if (entry->d_name[0] == 'd' &&
strncmp (entry->d_name, "dovecot", 7) == 0)
return TRUE;
/* ignore special files */
if (entry->d_name[0] == '.')
return TRUE;
/* ignore core files */
if (entry->d_name[0] == 'c' &&
strncmp (entry->d_name, "core", 4) == 0)
return TRUE;
/* ignore tmp/backup files; find the last char */
for (u = 0; entry->d_name[u] != '\0'; ++u) {
switch (entry->d_name[u]) {
case '#':
case '~':
/* looks like a backup / tempsave file */
if (entry->d_name[u + 1] == '\0')
return TRUE;
continue;
default:
continue;
}
}
return FALSE; /* other files: don't ignore */
} else if (d_type == DT_DIR)
return is_dotdir_to_ignore (entry->d_name);
else
return TRUE; /* ignore non-normal files, non-dirs */
}
/*
* return the maildir value for the the path - this is the directory
* for the message (with the top-level dir as "/"), and without the
* leaf "/cur" or "/new". In other words, contatenate old_mdir + "/" + dir,
* unless dir is either 'new' or 'cur'. The value will be used in queries.
*/
static char*
get_mdir_for_path (const char *old_mdir, const char *dir)
{
/* if the current dir is not 'new' or 'cur', contatenate
* old_mdir an dir */
if ((dir[0] == 'n' && strcmp(dir, "new") == 0) ||
(dir[0] == 'c' && strcmp(dir, "cur") == 0) ||
(dir[0] == 't' && strcmp(dir, "tmp") == 0))
return strdup (old_mdir ? old_mdir : G_DIR_SEPARATOR_S);
else
return g_strconcat (old_mdir ? old_mdir : "",
G_DIR_SEPARATOR_S, dir, NULL);
}
static MuError
process_dir_entry (const char* path, const char* mdir, struct dirent *entry,
MuMaildirWalkMsgCallback cb_msg,
MuMaildirWalkDirCallback cb_dir,
gboolean full, void *data)
{
const char *fp;
char* fullpath;
unsigned char d_type;
/* we have to copy the buffer from fullpath_s, because it
* returns a static buffer, and we maybe called reentrantly */
fp = mu_str_fullpath_s (path, entry->d_name);
fullpath = g_newa (char, strlen(fp) + 1);
strcpy (fullpath, fp);
d_type = get_dtype(entry, fullpath, FALSE/*stat*/);
/* ignore special files/dirs */
if (ignore_dir_entry (entry, d_type)) {
/* g_debug ("ignoring %s\n", entry->d_name); */
return MU_OK;
}
switch (d_type) {
case DT_REG: /* we only want files in cur/ and new/ */
if (!mu_maildir_is_leaf_dir (path))
return MU_OK;
return process_file (fullpath, mdir, cb_msg, data);
case DT_DIR: {
char *my_mdir;
MuError rv;
/* my_mdir is the search maildir (the dir starting
* with the top-level maildir as /, and without the
* /tmp, /cur, /new */
my_mdir = get_mdir_for_path (mdir, entry->d_name);
rv = process_dir (fullpath, my_mdir, cb_msg, cb_dir, full, data);
g_free (my_mdir);
return rv;
}
default:
return MU_OK; /* ignore other types */
}
}
#ifdef HAVE_STRUCT_DIRENT_D_INO
static int
dirent_cmp (struct dirent *d1, struct dirent *d2)
{
/* we do it his way instead of a simple d1->d_ino - d2->d_ino
* because this way, we don't need 64-bit numbers for the
* actual sorting */
if (d1->d_ino < d2->d_ino)
return -1;
else if (d1->d_ino > d2->d_ino)
return 1;
else
return 0;
}
#endif /*HAVE_STRUCT_DIRENT_D_INO*/
static MuError
process_dir_entries (DIR *dir, const char* path, const char* mdir,
MuMaildirWalkMsgCallback msg_cb,
MuMaildirWalkDirCallback dir_cb,
gboolean full, void *data)
{
MuError result;
GSList *lst, *c;
for (lst = NULL;;) {
struct dirent *entry, *res;
errno = 0;
res = readdir (dir);
if (res) {
entry = (struct dirent*)g_memdup (res, sizeof(struct dirent));
lst = g_slist_prepend (lst, entry);
} else if (errno == 0) {
break;
} else {
g_warning ("error scanning dir: %s", strerror(errno));
return MU_ERROR_FILE;
}
}
/* we sort by inode; this makes things much faster on
* extfs2,3 */
#if HAVE_STRUCT_DIRENT_D_INO
c = lst = g_slist_sort (lst, (GCompareFunc)dirent_cmp);
#endif /*HAVE_STRUCT_DIRENT_D_INO*/
for (c = lst, result = MU_OK; c && result == MU_OK; c = g_slist_next(c))
result = process_dir_entry (path, mdir, (struct dirent*)c->data,
msg_cb, dir_cb, full, data);
g_slist_foreach (lst, (GFunc)g_free, NULL);
g_slist_free (lst);
return result;
}
static MuError
process_dir (const char* path, const char* mdir,
MuMaildirWalkMsgCallback msg_cb, MuMaildirWalkDirCallback dir_cb,
gboolean full, void *data)
{
MuError result;
DIR* dir;
/* if it has a noindex file, we ignore this dir */
if (dir_contains_file (path, MU_MAILDIR_NOINDEX_FILE) ||
(!full && dir_contains_file (path, MU_MAILDIR_NOUPDATE_FILE))) {
g_debug ("found noindex/noupdate: ignoring dir %s", path);
return MU_OK;
}
if (dir_cb) {
MuError rv;
rv = dir_cb (path, TRUE/*enter*/, data);
/* ignore this dir; not necessarily an _error_, dir might
* be up-to-date and return MU_IGNORE */
if (rv == MU_IGNORE)
return MU_OK;
else if (rv != MU_OK)
return rv;
}
dir = opendir (path);
if (!dir) {
g_warning ("cannot access %s: %s", path, strerror(errno));
return MU_OK;
}
result = process_dir_entries (dir, path, mdir, msg_cb, dir_cb,
full, data);
closedir (dir);
/* only run dir_cb if it exists and so far, things went ok */
if (dir_cb && result == MU_OK)
return dir_cb (path, FALSE/*leave*/, data);
return result;
}
MuError
Mu::mu_maildir_walk (const char *path, MuMaildirWalkMsgCallback cb_msg,
MuMaildirWalkDirCallback cb_dir, gboolean full,
void *data)
{
MuError rv;
char *mypath;
g_return_val_if_fail (path && cb_msg, MU_ERROR);
g_return_val_if_fail (mu_util_check_dir(path, TRUE, FALSE), MU_ERROR);
/* strip the final / or \ */
mypath = g_strdup (path);
if (mypath[strlen(mypath)-1] == G_DIR_SEPARATOR)
mypath[strlen(mypath)-1] = '\0';
rv = process_dir (mypath, NULL, cb_msg, cb_dir, full, data);
g_free (mypath);
return rv;
}
static gboolean
clear_links (const char *path, DIR *dir)
{

View File

@ -64,57 +64,6 @@ gboolean mu_maildir_mkdir (const char* path, mode_t mode, gboolean noindex,
gboolean mu_maildir_link (const char* src, const char *targetpath,
GError **err);
/**
* MuMaildirWalkMsgCallback -- callback function for
* mu_path_walk_maildir; see the documentation there. It will be
* called for each message found, with fullpath containing the full
* path to the message, mdir containing the maildir -- that is, when
* indexing ~/Maildir, a message ~/Maildir/foo/bar/cur/msg would have
* the maildir "foo/bar". Then, the information from 'stat' of this
* file (see stat(3)), and a user_data pointer
*/
typedef MuError (*MuMaildirWalkMsgCallback)
(const char* fullpath, const char* mdir, struct stat *statinfo,
void *user_data);
/**
* MuPathWalkDirCallback -- callback function for mu_path_walk_maildir; see the
* documentation there. It will be called each time a dir is entered or left,
* with 'enter' being TRUE upon entering, FALSE otherwise
*/
typedef MuError (*MuMaildirWalkDirCallback)
(const char* fullpath, gboolean enter, void *user_data);
/**
* start a recursive walk of a maildir; for each file found, we call
* callback with the path (with the Maildir path of scanner_new as
* root), the filename, the timestamp (mtime) of the file,and the
* *data pointer, for user data. dot-files are ignored, as well as
* files outside cur/ and new/ dirs and unreadable files; however,
* dotdirs are visited (ie. '.dotdir/cur'), so this enables Maildir++.
* (http://www.inter7.com/courierimap/README.maildirquota.html, search
* for 'Mission statement'). In addition, dirs containing a file named
* '.noindex' are ignored, as are their subdirectories, and dirs
* containing a file called '.noupdate' are ignored, unless @param
* full is TRUE.
*
* mu_walk_maildir stops if the callbacks return something different
* from MU_OK. For example, it can return MU_STOP to stop the scan, or
* some error.
*
* @param path the maildir path to scan
* @param cb_msg the callback function called for each msg
* @param cb_dir the callback function called for each dir
* @param full whether do a full scan, i.e., to ignore .noupdate files
* @param data user data pointer
*
* @return a scanner result; MU_OK if everything went ok,
* MU_STOP if we want to stop, or MU_ERROR in
* case of error
*/
MuError mu_maildir_walk (const char *path, MuMaildirWalkMsgCallback cb_msg,
MuMaildirWalkDirCallback cb_dir, gboolean full,
void *data);
/**
* recursively delete all the symbolic links in a directory tree
*
@ -126,8 +75,6 @@ MuError mu_maildir_walk (const char *path, MuMaildirWalkMsgCallback cb_msg,
*/
gboolean mu_maildir_clear_links (const char* dir, GError **err);
/**
* whether the directory path ends in '/cur/' or '/new/'
*

View File

@ -135,8 +135,8 @@ mu_msg_destroy (MuMsg *self)
{ /* cleanup the strings / lists we stored */
mu_str_free_list (self->_free_later_str);
g_slist_foreach (self->_free_later_lst,
(GFunc)mu_str_free_list, NULL);
for (auto cur = self->_free_later_lst; cur; cur = g_slist_next(cur))
g_slist_free_full((GSList*)cur->data, g_free);
g_slist_free (self->_free_later_lst);
}

View File

@ -165,7 +165,7 @@ process_field (const std::string& field, Flags flags)
add_field (fields, MU_MSG_FIELD_ID_SUBJECT);
add_field (fields, MU_MSG_FIELD_ID_BODY_TEXT);
} else {
const auto id = field_id (field.c_str());
const auto id = field_id (field);
if (id != MU_MSG_FIELD_ID_NONE)
add_field (fields, id);
}
@ -176,7 +176,7 @@ process_field (const std::string& field, Flags flags)
static bool
is_range_field (const std::string& field)
{
const auto id = field_id (field.c_str());
const auto id = field_id (field);
if (id == MU_MSG_FIELD_ID_NONE)
return false;
else
@ -192,7 +192,7 @@ static MyRange
process_range (const std::string& field, const std::string& lower,
const std::string& upper)
{
const auto id = field_id (field.c_str());
const auto id = field_id (field);
if (id == MU_MSG_FIELD_ID_NONE)
return { lower, upper };
@ -213,7 +213,7 @@ process_range (const std::string& field, const std::string& lower,
std::vector<std::string>
Parser::Private::process_regex (const std::string& field, const std::regex& rx) const
{
const auto id = field_id (field.c_str());
const auto id = field_id (field);
if (id == MU_MSG_FIELD_ID_NONE)
return {};

View File

@ -59,10 +59,6 @@ constexpr auto DefaultMaxMessageSize = 100'000'000U;
constexpr auto ExpectedSchemaVersion = MU_STORE_SCHEMA_VERSION;
extern "C" {
static unsigned add_or_update_msg (MuStore *store, unsigned docid, MuMsg *msg, GError **err);
}
/* we cache these prefix strings, so we don't have to allocate them all
* the time; this should save 10-20 string allocs per message */
G_GNUC_CONST static const std::string&
@ -239,6 +235,9 @@ struct Store::Private {
return make_metadata(path);
}
Xapian::docid add_or_update_msg (Xapian::docid docid, MuMsg *msg, GError **err);
Xapian::Document new_doc_from_message (MuMsg *msg);
const bool read_only_{};
std::unique_ptr<Xapian::Database> db_;
@ -384,8 +383,7 @@ Store::add_message (const std::string& path)
throw Error{Error::Code::Message, "failed to create message: %s",
gerr ? gerr->message : "something went wrong"};
auto store{reinterpret_cast<MuStore*>(this)}; // yuk.
const auto docid{add_or_update_msg (store, 0, msg, &gerr)};
const auto docid{priv_->add_or_update_msg (0, msg, &gerr)};
mu_msg_unref (msg);
if (G_UNLIKELY(docid == MU_STORE_INVALID_DOCID))
throw Error{Error::Code::Message, "failed to add message: %s",
@ -401,10 +399,8 @@ Store::add_message (const std::string& path)
bool
Store::update_message (MuMsg *msg, unsigned docid)
{
auto store{reinterpret_cast<MuStore*>(this)}; // yuk.
GError *gerr{};
const auto docid2{add_or_update_msg (store, docid, msg, &gerr)};
const auto docid2{priv_->add_or_update_msg (docid, msg, &gerr)};
if (G_UNLIKELY(docid != docid2))
throw Error{Error::Code::Internal, "failed to update message",
@ -588,112 +584,6 @@ Store::commit () try
} MU_XAPIAN_CATCH_BLOCK;
////////////////////////////////////////////////////////////////////////////////
// C compat
extern "C" {
struct MuStore_ { Mu::Store* self; };
static const Mu::Store*
self (const MuStore *store)
{
if (!store) {
g_error ("invalid store"); // terminates
return {};
}
return reinterpret_cast<const Mu::Store*>(store);
}
static Mu::Store*
mutable_self (MuStore *store)
{
if (!store) {
g_error ("invalid store"); // terminates
return {};
}
auto s = reinterpret_cast<Mu::Store*>(store);
if (s->metadata().read_only) {
g_error ("store is read-only"); // terminates
return {};
}
return s;
}
MuStore*
mu_store_new_readable (const char* xpath, GError **err)
{
g_return_val_if_fail (xpath, NULL);
g_debug ("opening database at %s (read-only)", xpath);
try {
return reinterpret_cast<MuStore*>(new Store (xpath));
} catch (const Mu::Error& me) {
g_warning ("failed to open database: %s", me.what());
} catch (const Xapian::Error& dbe) {
g_warning ("failed to open database @ %s: %s", xpath,
dbe.get_error_string() ? dbe.get_error_string() : "something went wrong");
}
g_set_error (err, MU_ERROR_DOMAIN, MU_ERROR_XAPIAN_CANNOT_OPEN,
"failed to open database @ %s", xpath);
return NULL;
}
MuStore*
mu_store_ref (MuStore* store)
{
g_return_val_if_fail (store, NULL);
g_return_val_if_fail (self(store)->priv()->ref_count_ > 0, NULL);
++self(store)->priv()->ref_count_;
return store;
}
MuStore*
mu_store_unref (MuStore* store)
{
g_return_val_if_fail (store, NULL);
g_return_val_if_fail (self(store)->priv()->ref_count_ > 0, NULL);
auto me = reinterpret_cast<Mu::Store*>(store);
if (--me->priv()->ref_count_ == 0)
delete me;
return NULL;
}
unsigned
mu_store_count (const MuStore *store, GError **err)
{
g_return_val_if_fail (store, (unsigned)-1);
try {
return self(store)->size();
} MU_XAPIAN_CATCH_BLOCK_G_ERROR_RETURN(err, MU_ERROR_XAPIAN,
(unsigned)-1);
}
const char*
mu_store_schema_version (const MuStore *store)
{
g_return_val_if_fail (store, NULL);
return self(store)->metadata().schema_version.c_str();
}
static void
add_terms_values_date (Xapian::Document& doc, MuMsg *msg, MuMsgFieldId mfid)
{
@ -958,7 +848,7 @@ add_terms_values_body (Xapian::Document& doc, MuMsg *msg,
struct MsgDoc {
Xapian::Document *_doc;
MuMsg *_msg;
Store *_store;
Store::Private *_priv;
/* callback data, to determine whether this message is 'personal' */
gboolean _personal;
const StringVec *_my_addresses;
@ -1085,7 +975,7 @@ each_contact_info (MuMsgContact *contact, MsgDoc *msgdoc)
add_term(*msgdoc->_doc, pfx + flat);
add_address_subfields (*msgdoc->_doc, contact->email, pfx);
/* store it also in our contacts cache */
auto& contacts = msgdoc->_store->priv()->contacts_;
auto& contacts{msgdoc->_priv->contacts_};
contacts.add(Mu::ContactInfo(contact->full_address,
contact->email,
contact->name ? contact->name : "",
@ -1095,11 +985,12 @@ each_contact_info (MuMsgContact *contact, MsgDoc *msgdoc)
return TRUE;
}
static Xapian::Document
new_doc_from_message (MuStore *store, MuMsg *msg)
Xapian::Document
Store::Private::new_doc_from_message (MuMsg *msg)
{
Xapian::Document doc;
MsgDoc docinfo = {&doc, msg, mutable_self(store), 0, NULL};
MsgDoc docinfo = {&doc, msg, this, 0, NULL};
mu_msg_field_foreach ((MuMsgFieldForeachFunc)add_terms_values, &docinfo);
@ -1112,7 +1003,7 @@ new_doc_from_message (MuStore *store, MuMsg *msg)
else if (msgdoc->_personal)
return TRUE; // already deemed personal
if (msgdoc->_store->contacts().is_personal(contact->email))
if (msgdoc->_priv->contacts_.is_personal(contact->email))
msgdoc->_personal = true; // this one's personal.
return TRUE;
@ -1150,38 +1041,29 @@ update_threading_info (MuMsg *msg, Xapian::Document& doc)
}
static unsigned
add_or_update_msg (MuStore *store, unsigned docid, MuMsg *msg, GError **err)
Xapian::docid
Store::Private::add_or_update_msg (unsigned docid, MuMsg *msg, GError **err)
{
g_return_val_if_fail (store, MU_STORE_INVALID_DOCID);
g_return_val_if_fail (msg, MU_STORE_INVALID_DOCID);
try {
Xapian::docid id;
Xapian::Document doc (new_doc_from_message(store, msg));
Xapian::Document doc (new_doc_from_message(msg));
const std::string term (get_uid_term (mu_msg_get_path(msg)));
auto self = mutable_self(store);
auto wdb = self->priv()->writable_db();
add_term (doc, term);
// update the threading info if this message has a message id
if (mu_msg_get_msgid (msg))
update_threading_info (msg, doc);
if (docid == 0)
id = wdb.replace_document (term, doc);
else {
wdb.replace_document (docid, doc);
id = docid;
}
return id;
if (docid == 0)
return writable_db().replace_document (term, doc);
writable_db().replace_document (docid, doc);
return docid;
} MU_XAPIAN_CATCH_BLOCK_G_ERROR (err, MU_ERROR_XAPIAN_STORE_FAILED);
return MU_STORE_INVALID_DOCID;
}
} // extern C

View File

@ -22,8 +22,6 @@
#include <mu-msg.hh>
#ifdef __cplusplus
#include <string>
#include <vector>
#include <mutex>
@ -38,6 +36,10 @@
namespace Mu {
/* http://article.gmane.org/gmane.comp.search.xapian.general/3656 */
#define MU_STORE_MAX_TERM_LENGTH (240)
#define MU_STORE_INVALID_DOCID 0
class Store {
public:
using Id = unsigned; /**< Id for a message in the store (internally,
@ -292,79 +294,4 @@ private:
} // namespace Mu
#endif /*__cplusplus*/
#include <glib.h>
#include <inttypes.h>
#include <utils/mu-util.h>
#include <mu-contacts.hh>
G_BEGIN_DECLS
struct MuStore_;
typedef struct MuStore_ MuStore;
/* http://article.gmane.org/gmane.comp.search.xapian.general/3656 */
#define MU_STORE_MAX_TERM_LENGTH (240)
/**
* create a new read-only Xapian store, for querying documents
*
* @param path the path to the database
* @param err to receive error info or NULL. err->code is MuError value
*
* @return a new MuStore object with ref count == 1, or NULL in case of error;
* free with mu_store_unref
*/
MuStore* mu_store_new_readable (const char* xpath, GError **err)
G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT;
/**
* increase the reference count for this store with 1
*
* @param store a valid store object
*
* @return the same store with increased ref count, or NULL in case of
* error
*/
MuStore* mu_store_ref (MuStore *store);
/**
* decrease the reference count for this store with 1
*
* @param store a valid store object
*
* @return NULL
*/
MuStore* mu_store_unref (MuStore *store);
/**
* get the version of the xapian database (ie., the version of the
* 'schema' we are using). If this version != MU_STORE_SCHEMA_VERSION,
* it's means we need to a full reindex.
*
* @param store the store to inspect
*
* @return the version of the database as a newly allocated string
* (free with g_free); if there is no version yet, it will return NULL
*/
const char* mu_store_schema_version (const MuStore* store);
/**
* get the numbers of documents in the database
*
* @param index a valid MuStore instance
* @param err to receive error info or NULL. err->code is MuError value
*
* @return the number of documents in the database; (unsigned)-1 in
* case of error
*/
unsigned mu_store_count (const MuStore *store, GError **err);
#define MU_STORE_INVALID_DOCID 0
G_END_DECLS
#endif /* __MU_STORE_HH__ */

View File

@ -191,207 +191,6 @@ test_mu_maildir_mkdir_05 (void)
==, FALSE);
}
static gchar*
copy_test_data (void)
{
gchar *dir, *cmd;
dir = test_mu_common_get_random_tmpdir();
cmd = g_strdup_printf ("mkdir -p -m 0700 %s", dir);
if (g_test_verbose())
g_debug ("cmd: %s\n", cmd);
g_assert (g_spawn_command_line_sync (cmd, NULL, NULL, NULL, NULL));
g_free (cmd);
cmd = g_strdup_printf ("cp -R %s %s", MU_TESTMAILDIR, dir);
if (g_test_verbose())
g_debug ("cmd: %s\n", cmd);
g_assert (g_spawn_command_line_sync (cmd, NULL, NULL, NULL, NULL));
g_free (cmd);
return dir;
}
typedef struct {
int _file_count;
int _dir_entered;
int _dir_left;
} WalkData;
static MuError
dir_cb (const char *fullpath, gboolean enter, WalkData *data)
{
if (enter)
++data->_dir_entered;
else
++data->_dir_left;
if (g_test_verbose())
g_debug ("%s: %s: %s (%u)\n", __func__, enter ? "entering" : "leaving",
fullpath, enter ? data->_dir_entered : data->_dir_left);
return MU_OK;
}
static MuError
msg_cb (const char *fullpath, const char* mdir, struct stat *statinfo,
WalkData *data)
{
++data->_file_count;
return MU_OK;
}
static void
test_mu_maildir_walk_01 (void)
{
char *tmpdir;
WalkData data;
MuError rv;
tmpdir = copy_test_data ();
memset (&data, 0, sizeof(WalkData));
rv = mu_maildir_walk (tmpdir,
(MuMaildirWalkMsgCallback)msg_cb,
(MuMaildirWalkDirCallback)dir_cb,
TRUE,
&data);
g_assert_cmpuint (MU_OK, ==, rv);
g_assert_cmpuint (data._file_count, ==, 19);
g_assert_cmpuint (data._dir_entered,==, 5);
g_assert_cmpuint (data._dir_left,==, 5);
g_free (tmpdir);
}
static void
test_mu_maildir_walk (void)
{
char *tmpdir, *cmd, *dir;
WalkData data;
MuError rv;
tmpdir = copy_test_data ();
memset (&data, 0, sizeof(WalkData));
/* mark the 'new' dir with '.noindex', to ignore it */
dir = g_strdup_printf ("%s%ctestdir%cnew", tmpdir,
G_DIR_SEPARATOR, G_DIR_SEPARATOR);
cmd = g_strdup_printf ("chmod 700 %s", dir);
g_assert (g_spawn_command_line_sync (cmd, NULL, NULL, NULL, NULL));
g_free (cmd);
cmd = g_strdup_printf ("touch %s%c.noindex", dir, G_DIR_SEPARATOR);
g_assert (g_spawn_command_line_sync (cmd, NULL, NULL, NULL, NULL));
g_free (cmd);
g_free (dir);
rv = mu_maildir_walk (tmpdir,
(MuMaildirWalkMsgCallback)msg_cb,
(MuMaildirWalkDirCallback)dir_cb,
TRUE,
&data);
g_assert_cmpuint (MU_OK, ==, rv);
g_assert_cmpuint (data._file_count, ==, 15);
g_assert_cmpuint (data._dir_entered,==, 4);
g_assert_cmpuint (data._dir_left,==, 4);
g_free (tmpdir);
}
static void
test_mu_maildir_walk_with_noupdate (void)
{
char *tmpdir, *cmd, *dir;
WalkData data;
MuError rv;
tmpdir = copy_test_data ();
/* mark the 'new' dir with '.noindex', to ignore it */
dir = g_strdup_printf ("%s%ctestdir%cnew", tmpdir,
G_DIR_SEPARATOR, G_DIR_SEPARATOR);
cmd = g_strdup_printf ("chmod 700 %s", dir);
g_assert (g_spawn_command_line_sync (cmd, NULL, NULL, NULL, NULL));
g_free (cmd);
memset (&data, 0, sizeof(WalkData));
rv = mu_maildir_walk (tmpdir,
(MuMaildirWalkMsgCallback)msg_cb,
(MuMaildirWalkDirCallback)dir_cb,
FALSE, /* ie., non-full update */
&data);
g_assert_cmpuint (MU_OK, ==, rv);
g_assert_cmpuint (data._file_count, ==, 19);
g_assert_cmpuint (data._dir_entered,==, 5);
g_assert_cmpuint (data._dir_left,==, 5);
/* again, full update. results should be the same, since there
* is no noupdate yet */
memset (&data, 0, sizeof(WalkData));
rv = mu_maildir_walk (tmpdir,
(MuMaildirWalkMsgCallback)msg_cb,
(MuMaildirWalkDirCallback)dir_cb,
TRUE, /* ie., full update */
&data);
g_assert_cmpuint (MU_OK, ==, rv);
g_assert_cmpuint (data._file_count, ==, 19);
g_assert_cmpuint (data._dir_entered,==, 5);
g_assert_cmpuint (data._dir_left,==, 5);
/* add a '.noupdate' file; this affects the outcome when the
* 4th arg to mu_maildir_walk is FALSE */
cmd = g_strdup_printf ("touch %s%c.noupdate", dir, G_DIR_SEPARATOR);
g_assert (g_spawn_command_line_sync (cmd, NULL, NULL, NULL, NULL));
g_free (cmd);
memset (&data, 0, sizeof(WalkData));
rv = mu_maildir_walk (tmpdir,
(MuMaildirWalkMsgCallback)msg_cb,
(MuMaildirWalkDirCallback)dir_cb,
FALSE, /* non-full update */
&data);
g_assert_cmpuint (MU_OK, ==, rv);
g_assert_cmpuint (data._file_count, ==, 15);
g_assert_cmpuint (data._dir_entered,==, 4);
g_assert_cmpuint (data._dir_left,==, 4);
/* now run again, but do a full update */
memset (&data, 0, sizeof(WalkData));
rv = mu_maildir_walk (tmpdir,
(MuMaildirWalkMsgCallback)msg_cb,
(MuMaildirWalkDirCallback)dir_cb,
TRUE, /* full update */
&data);
g_assert_cmpuint (MU_OK, ==, rv);
g_assert_cmpuint (data._file_count, ==, 19);
g_assert_cmpuint (data._dir_entered,==, 5);
g_assert_cmpuint (data._dir_left,==, 5);
g_free (dir);
g_free (tmpdir);
}
static void
test_mu_maildir_get_flags_from_path (void)
{
@ -661,15 +460,6 @@ main (int argc, char *argv[])
g_test_add_func ("/mu-maildir/mu-maildir-mkdir-05",
test_mu_maildir_mkdir_05);
/* mu_util_maildir_walk */
g_test_add_func ("/mu-maildir/mu-maildir-walk-01",
test_mu_maildir_walk_01);
g_test_add_func ("/mu-maildir/mu-maildir-walk",
test_mu_maildir_walk);
g_test_add_func ("/mu-maildir/mu-maildir-walk-with-noupdate",
test_mu_maildir_walk_with_noupdate);
/* get/set flags */
g_test_add_func("/mu-maildir/mu-maildir-get-new-path-new",
test_mu_maildir_get_new_path_new);

View File

@ -39,7 +39,11 @@ mu_date_str_s (const char* frm, time_t t)
g_return_val_if_fail (frm, NULL);
tmbuf = localtime(&t);
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wformat-nonliteral"
len = strftime (buf, sizeof(buf) - 1, frm, tmbuf);
#pragma GCC diagnostic pop
if (len == 0)
return ""; /* not necessarily an error... */

View File

@ -22,6 +22,9 @@
#include "config.h"
#endif /*HAVE_CONFIG_H*/
#ifndef _XOPEN_SOURCE
#define _XOPEN_SOURCE (500)
#endif /*_XOPEN_SOURCE*/
#include <glib.h>
#include <string.h>
@ -38,7 +41,7 @@ mu_str_size_s (size_t s)
static char buf[32];
char *tmp;
tmp = g_format_size_for_display ((goffset)s);
tmp = g_format_size((goffset)s);
strncpy (buf, tmp, sizeof(buf));
buf[sizeof(buf) -1] = '\0'; /* just in case */
g_free (tmp);
@ -46,13 +49,6 @@ mu_str_size_s (size_t s)
return buf;
}
char*
mu_str_size (size_t s)
{
return g_strdup (mu_str_size_s(s));
}
char*
mu_str_summarize (const char* str, size_t max_lines)
{
@ -94,34 +90,6 @@ mu_str_summarize (const char* str, size_t max_lines)
return summary;
}
char*
mu_str_replace (const char *str, const char *substr, const char *repl)
{
GString *gstr;
const char *cur;
g_return_val_if_fail (str, NULL);
g_return_val_if_fail (substr, NULL);
g_return_val_if_fail (repl, NULL);
gstr = g_string_sized_new (2 * strlen (str));
for (cur = str; *cur; ++cur) {
if (g_str_has_prefix (cur, substr)) {
g_string_append (gstr, repl);
cur += strlen (substr) - 1;
} else
g_string_append_c (gstr, *cur);
}
return g_string_free (gstr, FALSE);
}
char*
mu_str_from_list (const GSList *lst, char sepa)
{
@ -179,69 +147,6 @@ mu_str_to_list (const char *str, char sepa, gboolean strip)
return lst;
}
GSList*
mu_str_esc_to_list (const char *strings)
{
GSList *lst;
GString *part;
unsigned u;
gboolean quoted, escaped;
g_return_val_if_fail (strings, NULL);
part = g_string_new (NULL);
for (u = 0, lst = NULL, quoted = FALSE, escaped = FALSE;
u != strlen (strings); ++u) {
char kar;
kar = strings[u];
if (kar == '\\') {
if (escaped)
g_string_append_c (part, '\\');
escaped = !escaped;
continue;
}
if (quoted && kar != '"') {
g_string_append_c (part, kar);
continue;
}
switch (kar) {
case '"':
if (!escaped)
quoted = !quoted;
else
g_string_append_c (part, kar);
continue;
case ' ':
if (part->len > 0) {
lst = g_slist_prepend
(lst, g_string_free (part, FALSE));
part = g_string_new (NULL);
}
continue;
default:
g_string_append_c (part, kar);
}
}
if (part->len)
lst = g_slist_prepend (lst, g_string_free (part, FALSE));
return g_slist_reverse (lst);
}
void
mu_str_free_list (GSList *lst)
{
g_slist_foreach (lst, (GFunc)g_free, NULL);
g_slist_free (lst);
}
/* this function is critical for sorting performance; therefore, no
* regexps, but just some good old c pointer magic */
@ -306,34 +211,6 @@ mu_str_fullpath_s (const char* path, const char* name)
}
char*
mu_str_escape_c_literal (const gchar* str, gboolean in_quotes)
{
const char* cur;
GString *tmp;
g_return_val_if_fail (str, NULL);
tmp = g_string_sized_new (2 * strlen(str));
if (in_quotes)
g_string_append_c (tmp, '"');
for (cur = str; *cur; ++cur)
switch (*cur) {
case '\\': tmp = g_string_append (tmp, "\\\\"); break;
case '"': tmp = g_string_append (tmp, "\\\""); break;
default: tmp = g_string_append_c (tmp, *cur);
}
if (in_quotes)
g_string_append_c (tmp, '"');
return g_string_free (tmp, FALSE);
}
/* turn \0-terminated buf into ascii (which is a utf8 subset); convert
* any non-ascii into '.'
*/

View File

@ -40,8 +40,6 @@ G_BEGIN_DECLS
* 10-based SI units, _not_ the powers-of-2 based ones.
*
* mu_str_size_s returns a ptr to a static buffer,
* while mu_str_size returns dynamically allocated
* memory that must be freed after use.
*
* @param t the size as an size_t
*
@ -49,20 +47,6 @@ G_BEGIN_DECLS
* for what to do with it
*/
const char* mu_str_size_s (size_t s);
char* mu_str_size (size_t s) G_GNUC_WARN_UNUSED_RESULT;
/**
* Replace all occurrences of substr in str with repl
*
* @param str a string
* @param substr some string to replace
* @param repl a replacement string
*
* @return a newly allocated string with the substr replaced by repl; free with g_free
*/
char *mu_str_replace (const char *str, const char *substr, const char *repl);
/**
* get a 'summary' of the string, ie. the first /n/ lines of the
@ -87,18 +71,6 @@ char* mu_str_summarize (const char* str, size_t max_lines)
*/
const char* mu_str_fullpath_s (const char* path, const char* name);
/**
* escape a string like a string literal in C; ie. replace \ with \\,
* and " with \"
*
* @param str a non-NULL str
* @param in_quotes whether the result should be enclosed in ""
*
* @return the escaped string, newly allocated (free with g_free)
*/
char* mu_str_escape_c_literal (const gchar* str, gboolean in_quotes)
G_GNUC_WARN_UNUSED_RESULT;
/**
* turn a string into plain ascii by replacing each non-ascii
* character with a dot ('.'). Replacement is done in-place.
@ -162,24 +134,12 @@ char* mu_str_from_list (const GSList *lst, char sepa);
*/
GSList* mu_str_to_list (const char *str, char sepa, gboolean strip);
/**
* convert a string (with possible escaping) to a list. list items are
* separated by one or more spaces. list items can be quoted (using
* '"').
*
* @param str a string
*
* @return a list of elements or NULL in case of error, free with
* mu_str_free_list
*/
GSList* mu_str_esc_to_list (const char *str);
/**
* free a GSList consisting of allocated strings
*
* @param lst a GSList
*/
void mu_str_free_list (GSList *lst);
#define mu_str_free_list(lst) g_slist_free_full(lst, g_free)
/**
* strip the subject of Re:, Fwd: etc.

View File

@ -23,9 +23,11 @@
#include <config.h>
#endif /*HAVE_CONFIG_H*/
#include "mu-util.h"
#define _XOPEN_SOURCE 500
#ifndef _XOPEN_SOURCE
#define _XOPEN_SOURCE (500)
#endif /*_XOPEN_SOURCE*/
#include "mu-util.h"
#ifdef HAVE_WORDEXP_H
#include <wordexp.h> /* for shell-style globbing */
#endif /*HAVE_WORDEXP_H*/

View File

@ -32,73 +32,6 @@
#include "mu-str.h"
static void
test_mu_str_size_01 (void)
{
struct lconv *lc;
char *tmp2;
lc = localeconv();
g_assert_cmpstr (mu_str_size_s (0), ==, "0 bytes");
tmp2 = g_strdup_printf ("97%s7 KB", lc->decimal_point);
g_assert_cmpstr (mu_str_size_s (100000), ==, tmp2);
g_free (tmp2);
tmp2 = g_strdup_printf ("1%s0 MB", lc->decimal_point);
g_assert_cmpstr (mu_str_size_s (1100*1000), ==, tmp2);
g_free (tmp2);
}
static void
test_mu_str_size_02 (void)
{
struct lconv *lc;
char *tmp1, *tmp2;
lc = localeconv();
tmp2 = g_strdup_printf ("1%s0 MB", lc->decimal_point);
tmp1 = mu_str_size (999999);
g_assert_cmpstr (tmp1, !=, tmp2);
g_free (tmp1);
g_free (tmp2);
}
static void
test_mu_str_esc_to_list (void)
{
int i;
struct {
const char* str;
const char* strs[3];
} strings [] = {
{ "maildir:foo",
{"maildir:foo", NULL, NULL}},
{ "maildir:sent items",
{"maildir:sent", "items", NULL}},
{ "\"maildir:sent items\"",
{"maildir:sent items", NULL, NULL}},
};
for (i = 0; i != G_N_ELEMENTS(strings); ++i) {
GSList *lst, *cur;
unsigned u;
lst = mu_str_esc_to_list (strings[i].str);
for (cur = lst, u = 0; cur; cur = g_slist_next(cur), ++u)
g_assert_cmpstr ((const char*)cur->data,==,
strings[i].strs[u]);
mu_str_free_list (lst);
}
}
static void
assert_cmplst (GSList *lst, const char *items[])
{
@ -189,33 +122,6 @@ test_mu_str_to_list_strip (void)
mu_str_free_list (lst);
}
static void
test_mu_str_replace (void)
{
unsigned u;
struct {
const char* str;
const char* sub;
const char *repl;
const char *exp;
} strings [] = {
{ "hello", "ll", "xx", "hexxo" },
{ "hello", "hello", "hi", "hi" },
{ "hello", "foo", "bar", "hello" }
};
for (u = 0; u != G_N_ELEMENTS(strings); ++u) {
char *res;
res = mu_str_replace (strings[u].str,
strings[u].sub,
strings[u].repl);
g_assert_cmpstr (res,==,strings[u].exp);
g_free (res);
}
}
static void
test_mu_str_remove_ctrl_in_place (void)
{
@ -248,12 +154,6 @@ main (int argc, char *argv[])
g_test_init (&argc, &argv, NULL);
/* mu_str_size */
g_test_add_func ("/mu-str/mu-str-size-01",
test_mu_str_size_01);
g_test_add_func ("/mu-str/mu-str-size-02",
test_mu_str_size_02);
g_test_add_func ("/mu-str/mu-str-from-list",
test_mu_str_from_list);
g_test_add_func ("/mu-str/mu-str-to-list",
@ -261,12 +161,6 @@ main (int argc, char *argv[])
g_test_add_func ("/mu-str/mu-str-to-list-strip",
test_mu_str_to_list_strip);
g_test_add_func ("/mu-str/mu-str-replace",
test_mu_str_replace);
g_test_add_func ("/mu-str/mu-str-esc-to-list",
test_mu_str_esc_to_list);
g_test_add_func ("/mu-str/mu_str_remove_ctrl_in_place",
test_mu_str_remove_ctrl_in_place);

View File

@ -116,16 +116,11 @@ search (const char* query, unsigned expected)
static void
test_mu_index (void)
{
MuStore *store;
gchar *xpath;
xpath = g_strdup_printf ("%s%c%s", DBPATH, G_DIR_SEPARATOR, "xapian");
gchar *xpath{g_strdup_printf ("%s%c%s", DBPATH, G_DIR_SEPARATOR, "xapian")};
g_printerr ("*** %s\n", DBPATH);
store = mu_store_new_readable (xpath, NULL);
g_assert (store);
Mu::Store store{xpath, true};
g_assert_cmpuint (mu_store_count (store, NULL), ==, 13);
mu_store_unref (store);
g_assert_cmpuint (store.size(), ==, 13);
g_free (xpath);
}
@ -348,8 +343,8 @@ test_mu_extract_01 (void)
==,
"MIME-parts in this message:\n"
" 1 <none> text/plain [<none>] (27 bytes)\n"
" 2 sittingbull.jpg image/jpeg [inline] (23.3 KB)\n"
" 3 custer.jpg image/jpeg [inline] (21.1 KB)\n");
" 2 sittingbull.jpg image/jpeg [inline] (23.9\302\240kB)\n"
" 3 custer.jpg image/jpeg [inline] (21.6\302\240kB)\n");
/* we expect zero lines of error output */
g_assert_cmpuint (newlines_in_output(erroutput),==,0);