* support '.noupdate' -- similar to '.noindex', maildirs containing

'.noupdate' will be ignored; however, they will _not_ be ignored when doing
  a full update (--rebuild)
This commit is contained in:
djcb 2012-05-22 10:19:49 +03:00
parent 5d5533c953
commit 9367f1ac6d
8 changed files with 208 additions and 125 deletions

View File

@ -309,7 +309,6 @@ mu_index_set_xbatch_size (MuIndex *index, guint xbatchsize)
MuError MuError
mu_index_run (MuIndex *index, const char* path, mu_index_run (MuIndex *index, const char* path,
gboolean reindex, MuIndexStats *stats, gboolean reindex, MuIndexStats *stats,
@ -337,6 +336,7 @@ mu_index_run (MuIndex *index, const char* path,
rv = mu_maildir_walk (path, rv = mu_maildir_walk (path,
(MuMaildirWalkMsgCallback)on_run_maildir_msg, (MuMaildirWalkMsgCallback)on_run_maildir_msg,
(MuMaildirWalkDirCallback)on_run_maildir_dir, (MuMaildirWalkDirCallback)on_run_maildir_dir,
reindex, /* re-index, ie. do a full update */
&cb_data); &cb_data);
mu_store_flush (index->_store); mu_store_flush (index->_store);
@ -393,7 +393,7 @@ mu_index_stats (MuIndex *index, const char* path,
return mu_maildir_walk (path, return mu_maildir_walk (path,
(MuMaildirWalkMsgCallback)on_stats_maildir_file, (MuMaildirWalkMsgCallback)on_stats_maildir_file,
NULL,&cb_data); NULL, FALSE, &cb_data);
} }
struct _CleanupData { struct _CleanupData {

View File

@ -1,7 +1,7 @@
/* -*-mode: c; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-*/ /* -*-mode: c; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-*/
/* /*
** Copyright (C) 2008-2011 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> ** Copyright (C) 2008-2012 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
** **
** This program is free software; you can redistribute it and/or modify it ** This program is free software; you can redistribute it and/or modify it
** under the terms of the GNU General Public License as published by the ** under the terms of the GNU General Public License as published by the
@ -47,6 +47,8 @@
#include "mu-str.h" #include "mu-str.h"
#define MU_MAILDIR_NOINDEX_FILE ".noindex" #define MU_MAILDIR_NOINDEX_FILE ".noindex"
#define MU_MAILDIR_NOUPDATE_FILE ".noupdate"
/* On Linux (and some BSD), we have entry->d_type, but some file /* On Linux (and some BSD), we have entry->d_type, but some file
* systems (XFS, ReiserFS) do not support it, and set it DT_UNKNOWN. * systems (XFS, ReiserFS) do not support it, and set it DT_UNKNOWN.
@ -88,13 +90,11 @@ create_maildir (const char *path, mode_t mode, GError **err)
/* note, g_mkdir_with_parents won't detect an error if /* note, g_mkdir_with_parents won't detect an error if
* there's already such a dir, but with the wrong * there's already such a dir, but with the wrong
* permissions; so we need to check */ * permissions; so we need to check */
if (rv != 0 || !mu_util_check_dir(fullpath, TRUE, TRUE)) { if (rv != 0 || !mu_util_check_dir(fullpath, TRUE, TRUE))
g_set_error (err, MU_ERROR_DOMAIN, MU_ERROR_FILE_CANNOT_MKDIR, return mu_util_g_set_error
"creating dir failed for %s: %s", (err,MU_ERROR_FILE_CANNOT_MKDIR,
fullpath, "creating dir failed for %s: %s",
strerror (errno)); fullpath, strerror (errno));
return FALSE;
}
} }
return TRUE; return TRUE;
@ -114,13 +114,10 @@ create_noindex (const char *path, GError **err)
/* note, if the 'close' failed, creation may still have /* note, if the 'close' failed, creation may still have
* succeeded...*/ * succeeded...*/
if (fd < 0 || close (fd) != 0) { if (fd < 0 || close (fd) != 0)
g_set_error (err, MU_ERROR_DOMAIN, MU_ERROR_FILE_CANNOT_CREATE, return mu_util_g_set_error (err, MU_ERROR_FILE_CANNOT_CREATE,
"error in create_noindex: %s", "error in create_noindex: %s",
strerror (errno)); strerror (errno));
return FALSE;
}
return TRUE; return TRUE;
} }
@ -146,22 +143,22 @@ mu_maildir_mkdir (const char* path, mode_t mode, gboolean noindex, GError **err)
static gboolean static gboolean
check_subdir (const char *src, gboolean *in_cur, GError **err) check_subdir (const char *src, gboolean *in_cur, GError **err)
{ {
gboolean rv;
gchar *srcpath; gchar *srcpath;
srcpath = g_path_get_dirname (src); srcpath = g_path_get_dirname (src);
rv = TRUE;
if (g_str_has_suffix (srcpath, "new")) if (g_str_has_suffix (srcpath, "new"))
*in_cur = FALSE; *in_cur = FALSE;
else if (g_str_has_suffix (srcpath, "cur")) else if (g_str_has_suffix (srcpath, "cur"))
*in_cur = TRUE; *in_cur = TRUE;
else { else
g_set_error(err, 0, MU_ERROR_FILE_INVALID_SOURCE, rv = mu_util_g_set_error(err, MU_ERROR_FILE_INVALID_SOURCE,
"invalid source message '%s'", src); "invalid source message '%s'", src);
return FALSE;
}
g_free (srcpath); g_free (srcpath);
return TRUE; return rv;
} }
static gchar* static gchar*
@ -207,23 +204,21 @@ mu_maildir_link (const char* src, const char *targetpath, GError **err)
rv = symlink (src, targetfullpath); rv = symlink (src, targetfullpath);
if (rv != 0) { if (rv != 0)
g_set_error (err, MU_ERROR_DOMAIN, MU_ERROR_FILE_CANNOT_LINK, mu_util_g_set_error (err, MU_ERROR_FILE_CANNOT_LINK,
"error creating link %s => %s: %s", "error creating link %s => %s: %s",
targetfullpath, src, strerror (errno)); targetfullpath, src, strerror (errno));
g_free (targetfullpath);
return FALSE;
}
g_free (targetfullpath); g_free (targetfullpath);
return TRUE;
return rv == 0 ? TRUE: FALSE;
} }
static MuError static MuError
process_dir (const char* path, const gchar *mdir, process_dir (const char* path, const gchar *mdir,
MuMaildirWalkMsgCallback msg_cb, MuMaildirWalkMsgCallback msg_cb,
MuMaildirWalkDirCallback dir_cb, void *data); MuMaildirWalkDirCallback dir_cb, gboolean full,
void *data);
static MuError static MuError
process_file (const char* fullpath, const gchar* mdir, process_file (const char* fullpath, const gchar* mdir,
@ -292,26 +287,26 @@ is_maildir_new_or_cur (const char *path)
return FALSE; return FALSE;
} }
/* check if there is a noindex file (MU_MAILDIR_NOINDEX_FILE) in this
/* check if there path contains file; used for checking if there is
* MU_MAILDIR_NOINDEX_FILE or MU_MAILDIR_NOUPDATE_FILE in this
* dir; */ * dir; */
static gboolean static gboolean
has_noindex_file (const char *path) dir_contains_file (const char *path, const char *file)
{ {
const char* noindexpath; const char* fullpath;
/* static buffer */ /* static buffer */
noindexpath = mu_str_fullpath_s (path, MU_MAILDIR_NOINDEX_FILE); fullpath = mu_str_fullpath_s (path, file);
if (access (noindexpath, F_OK) == 0) if (access (fullpath, F_OK) == 0)
return TRUE; return TRUE;
else if (G_UNLIKELY(errno != ENOENT)) else if (G_UNLIKELY(errno != ENOENT))
g_warning ("error testing for noindex file %s: %s", g_warning ("error testing for %s/%s: %s",
noindexpath, strerror(errno)); fullpath, file, strerror(errno));
return FALSE; return FALSE;
} }
static gboolean static gboolean
is_dotdir_to_ignore (const char* dir) is_dotdir_to_ignore (const char* dir)
{ {
@ -351,6 +346,9 @@ ignore_dir_entry (struct dirent *entry, unsigned char d_type)
if (entry->d_name[0] == 'd' && if (entry->d_name[0] == 'd' &&
strncmp (entry->d_name, "dovecot", 7) == 0) strncmp (entry->d_name, "dovecot", 7) == 0)
return TRUE; return TRUE;
/* ignore special files */
if (entry->d_name[0] == '.')
return TRUE;
/* ignore core files */ /* ignore core files */
if (entry->d_name[0] == 'c' && if (entry->d_name[0] == 'c' &&
strncmp (entry->d_name, "core", 4) == 0) strncmp (entry->d_name, "core", 4) == 0)
@ -390,7 +388,7 @@ static MuError
process_dir_entry (const char* path, const char* mdir, struct dirent *entry, process_dir_entry (const char* path, const char* mdir, struct dirent *entry,
MuMaildirWalkMsgCallback cb_msg, MuMaildirWalkMsgCallback cb_msg,
MuMaildirWalkDirCallback cb_dir, MuMaildirWalkDirCallback cb_dir,
void *data) gboolean full, void *data)
{ {
const char *fp; const char *fp;
char* fullpath; char* fullpath;
@ -420,10 +418,9 @@ process_dir_entry (const char* path, const char* mdir, struct dirent *entry,
MuError rv; MuError rv;
/* my_mdir is the search maildir (the dir starting /* my_mdir is the search maildir (the dir starting
* with the top-level maildir as /, and without the * with the top-level maildir as /, and without the
* /tmp, /cur, /new * /tmp, /cur, /new */
*/
my_mdir = get_mdir_for_path (mdir, entry->d_name); my_mdir = get_mdir_for_path (mdir, entry->d_name);
rv = process_dir (fullpath, my_mdir, cb_msg, cb_dir, data); rv = process_dir (fullpath, my_mdir, cb_msg, cb_dir, full, data);
g_free (my_mdir); g_free (my_mdir);
return rv; return rv;
@ -470,7 +467,8 @@ dirent_cmp (struct dirent *d1, struct dirent *d2)
static MuError static MuError
process_dir_entries (DIR *dir, const char* path, const char* mdir, process_dir_entries (DIR *dir, const char* path, const char* mdir,
MuMaildirWalkMsgCallback msg_cb, MuMaildirWalkMsgCallback msg_cb,
MuMaildirWalkDirCallback dir_cb, void *data) MuMaildirWalkDirCallback dir_cb,
gboolean full, void *data)
{ {
MuError result; MuError result;
GSList *lst, *c; GSList *lst, *c;
@ -502,7 +500,7 @@ process_dir_entries (DIR *dir, const char* path, const char* mdir,
for (c = lst, result = MU_OK; c && result == MU_OK; c = g_slist_next(c)) 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, result = process_dir_entry (path, mdir, (struct dirent*)c->data,
msg_cb, dir_cb, data); msg_cb, dir_cb, full, data);
g_slist_foreach (lst, (GFunc)dirent_destroy, NULL); g_slist_foreach (lst, (GFunc)dirent_destroy, NULL);
g_slist_free (lst); g_slist_free (lst);
@ -513,22 +511,22 @@ process_dir_entries (DIR *dir, const char* path, const char* mdir,
static MuError static MuError
process_dir (const char* path, const char* mdir, process_dir (const char* path, const char* mdir,
MuMaildirWalkMsgCallback msg_cb, MuMaildirWalkMsgCallback msg_cb, MuMaildirWalkDirCallback dir_cb,
MuMaildirWalkDirCallback dir_cb, void *data) gboolean full, void *data)
{ {
MuError result; MuError result;
DIR* dir; DIR* dir;
/* if it has a noindex file, we ignore this dir */ /* if it has a noindex file, we ignore this dir */
if (has_noindex_file (path)) { if (dir_contains_file (path, MU_MAILDIR_NOINDEX_FILE) ||
g_debug ("found .noindex: ignoring dir %s", path); (!full && dir_contains_file (path, MU_MAILDIR_NOUPDATE_FILE))) {
g_debug ("found noindex/noupdate: ignoring dir %s", path);
return MU_OK; return MU_OK;
} }
dir = opendir (path); dir = opendir (path);
if (G_UNLIKELY(!dir)) { if (G_UNLIKELY(!dir)) {
g_warning ("%s: ignoring %s: %s", __FUNCTION__, g_warning ("opendir failed %s: %s", path, strerror(errno));
path, strerror(errno));
return MU_OK; return MU_OK;
} }
@ -541,7 +539,7 @@ process_dir (const char* path, const char* mdir,
} }
} }
result = process_dir_entries (dir, path, mdir, msg_cb, dir_cb, data); result = process_dir_entries (dir, path, mdir, msg_cb, dir_cb, full, data);
closedir (dir); closedir (dir);
/* only run dir_cb if it exists and so far, things went ok */ /* only run dir_cb if it exists and so far, things went ok */
@ -554,7 +552,8 @@ process_dir (const char* path, const char* mdir,
MuError MuError
mu_maildir_walk (const char *path, MuMaildirWalkMsgCallback cb_msg, mu_maildir_walk (const char *path, MuMaildirWalkMsgCallback cb_msg,
MuMaildirWalkDirCallback cb_dir, void *data) MuMaildirWalkDirCallback cb_dir, gboolean full,
void *data)
{ {
MuError rv; MuError rv;
char *mypath; char *mypath;
@ -567,7 +566,7 @@ mu_maildir_walk (const char *path, MuMaildirWalkMsgCallback cb_msg,
if (mypath[strlen(mypath)-1] == G_DIR_SEPARATOR) if (mypath[strlen(mypath)-1] == G_DIR_SEPARATOR)
mypath[strlen(mypath)-1] = '\0'; mypath[strlen(mypath)-1] = '\0';
rv = process_dir (mypath, NULL, cb_msg, cb_dir, data); rv = process_dir (mypath, NULL, cb_msg, cb_dir, full, data);
g_free (mypath); g_free (mypath);
return rv; return rv;
@ -617,8 +616,8 @@ clear_links (const gchar* dirname, DIR *dir, GError **err)
} }
if (errno != 0) if (errno != 0)
g_set_error (err, MU_ERROR_DOMAIN, MU_ERROR_FILE, mu_util_g_set_error (err, MU_ERROR_FILE,
"file error: %s", strerror(errno)); "file error: %s", strerror(errno));
return (rv == FALSE && errno == 0); return (rv == FALSE && errno == 0);
} }
@ -633,12 +632,10 @@ mu_maildir_clear_links (const gchar* path, GError **err)
g_return_val_if_fail (path, FALSE); g_return_val_if_fail (path, FALSE);
dir = opendir (path); dir = opendir (path);
if (!dir) { if (!dir)
g_set_error (err, MU_ERROR_DOMAIN, MU_ERROR_FILE_CANNOT_OPEN, return mu_util_g_set_error (err, MU_ERROR_FILE_CANNOT_OPEN,
"failed to open %s: %s", path, "failed to open %s: %s", path,
strerror(errno)); strerror(errno));
return FALSE;
}
rv = clear_links (path, dir, err); rv = clear_links (path, dir, err);
closedir (dir); closedir (dir);
@ -790,29 +787,23 @@ mu_maildir_get_new_path (const char *oldpath, const char *new_mdir,
static gboolean static gboolean
msg_move_check_pre (const gchar *src, const gchar *dst, GError **err) msg_move_check_pre (const gchar *src, const gchar *dst, GError **err)
{ {
if (!g_path_is_absolute(src)) { if (!g_path_is_absolute(src))
g_set_error (err, MU_ERROR_DOMAIN, MU_ERROR_FILE, return mu_util_g_set_error
"source is not an absolute path: '%s'", src); (err, MU_ERROR_FILE,
return FALSE; "source is not an absolute path: '%s'", src);
}
if (!g_path_is_absolute(dst)) { if (!g_path_is_absolute(dst))
g_set_error (err, MU_ERROR_DOMAIN, MU_ERROR_FILE, return mu_util_g_set_error
"target is not an absolute path: '%s'", dst); (err, MU_ERROR_FILE,
return FALSE; "target is not an absolute path: '%s'", dst);
}
if (access (src, R_OK) != 0) { if (access (src, R_OK) != 0)
g_set_error (err, MU_ERROR_DOMAIN, MU_ERROR_FILE, "cannot read %s", return mu_util_g_set_error (err, MU_ERROR_FILE,
src); "cannot read %s", src);
return FALSE;
}
if (access (dst, F_OK) == 0) { if (access (dst, F_OK) == 0)
g_set_error (err, MU_ERROR_DOMAIN, MU_ERROR_FILE, "%s already exists", return mu_util_g_set_error (err, MU_ERROR_FILE,
dst); "%s already exists", dst);
return FALSE;
}
return TRUE; return TRUE;
} }
@ -821,17 +812,13 @@ static gboolean
msg_move_check_post (const char *src, const char *dst, GError **err) msg_move_check_post (const char *src, const char *dst, GError **err)
{ {
/* double check -- is the target really there? */ /* double check -- is the target really there? */
if (access (dst, F_OK) != 0) { if (access (dst, F_OK) != 0)
g_set_error (err, MU_ERROR_DOMAIN, MU_ERROR_FILE, "can't find target (%s)", return mu_util_g_set_error
dst); (err, MU_ERROR_FILE, "can't find target (%s)", dst);
return FALSE;
}
if (access (src, F_OK) == 0) { if (access (src, F_OK) == 0)
g_set_error (err, MU_ERROR_DOMAIN, MU_ERROR_FILE, "source is still there (%s)", return mu_util_g_set_error
src); (err, MU_ERROR_FILE, "source still there (%s)", src);
return FALSE;
}
return TRUE; return TRUE;
} }
@ -843,16 +830,11 @@ msg_move (const char* src, const char *dst, GError **err)
if (!msg_move_check_pre (src, dst, err)) if (!msg_move_check_pre (src, dst, err))
return FALSE; return FALSE;
if (rename (src, dst) != 0) { if (rename (src, dst) != 0)
g_set_error (err, MU_ERROR_DOMAIN, MU_ERROR_FILE, "error moving %s to %s", return mu_util_g_set_error
src, dst); (err, MU_ERROR_FILE,"error moving %s to %s", src, dst);
return FALSE;
}
if (!msg_move_check_post (src, dst, err)) return msg_move_check_post (src, dst, err);
return FALSE;
return TRUE;
} }
gchar* gchar*
@ -869,18 +851,17 @@ mu_maildir_move_message (const char* oldpath, const char* targetmdir,
newfullpath = mu_maildir_get_new_path (oldpath, targetmdir, newfullpath = mu_maildir_get_new_path (oldpath, targetmdir,
newflags); newflags);
if (!newfullpath) { if (!newfullpath) {
g_set_error (err, MU_ERROR_DOMAIN, MU_ERROR_FILE, mu_util_g_set_error (err, MU_ERROR_FILE,
"failed to determine target full path"); "failed to determine targetpath");
return FALSE; return NULL;
} }
src_is_target = (g_strcmp0 (oldpath, newfullpath) == 0); src_is_target = (g_strcmp0 (oldpath, newfullpath) == 0);
if (!ignore_dups && src_is_target) { if (!ignore_dups && src_is_target) {
g_set_error (err, MU_ERROR_DOMAIN, MU_ERROR_FILE_TARGET_EQUALS_SOURCE, mu_util_g_set_error (err, MU_ERROR_FILE_TARGET_EQUALS_SOURCE,
"target equals source"); "target equals source");
return FALSE; return NULL;
} }
if (!src_is_target) { if (!src_is_target) {

View File

@ -96,7 +96,9 @@ typedef MuError (*MuMaildirWalkDirCallback)
* dotdirs are visited (ie. '.dotdir/cur'), so this enables Maildir++. * dotdirs are visited (ie. '.dotdir/cur'), so this enables Maildir++.
* (http://www.inter7.com/courierimap/README.maildirquota.html, search * (http://www.inter7.com/courierimap/README.maildirquota.html, search
* for 'Mission statement'). In addition, dirs containing a file named * for 'Mission statement'). In addition, dirs containing a file named
* '.noindex' are ignored, as are their subdirectories. * '.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 * 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 * from MU_OK. For example, it can return MU_STOP to stop the scan, or
@ -105,6 +107,7 @@ typedef MuError (*MuMaildirWalkDirCallback)
* @param path the maildir path to scan * @param path the maildir path to scan
* @param cb_msg the callback function called for each msg * @param cb_msg the callback function called for each msg
* @param cb_dir the callback function called for each dir * @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 * @param data user data pointer
* *
* @return a scanner result; MU_OK if everything went ok, * @return a scanner result; MU_OK if everything went ok,
@ -112,7 +115,8 @@ typedef MuError (*MuMaildirWalkDirCallback)
* case of error * case of error
*/ */
MuError mu_maildir_walk (const char *path, MuMaildirWalkMsgCallback cb_msg, MuError mu_maildir_walk (const char *path, MuMaildirWalkMsgCallback cb_msg,
MuMaildirWalkDirCallback cb_dir, void *data); MuMaildirWalkDirCallback cb_dir, gboolean full,
void *data);
/** /**
* recursively delete all the symbolic links in a directory tree * recursively delete all the symbolic links in a directory tree
* *

View File

@ -441,7 +441,7 @@ mu_util_fputs_encoded (const char *str, FILE *stream)
void gboolean
mu_util_g_set_error (GError **err, MuError errcode, const char *frm, ...) mu_util_g_set_error (GError **err, MuError errcode, const char *frm, ...)
{ {
va_list ap; va_list ap;
@ -459,6 +459,8 @@ mu_util_g_set_error (GError **err, MuError errcode, const char *frm, ...)
g_set_error (err, MU_ERROR_DOMAIN, errcode, "%s", msg); g_set_error (err, MU_ERROR_DOMAIN, errcode, "%s", msg);
g_free (msg); g_free (msg);
return FALSE;
} }

View File

@ -439,13 +439,15 @@ typedef enum _MuError MuError;
/** /**
* set an error if it's not already set * set an error if it's not already set, and return FALSE
* *
* @param err errptr, or NULL * @param err errptr, or NULL
* @param errcode error code * @param errcode error code
* @param frm printf-style format, followed by paremeters * @param frm printf-style format, followed by paremeters
*
* @return FALSE
*/ */
void mu_util_g_set_error (GError **err, MuError errcode, const char *frm, ...) gboolean mu_util_g_set_error (GError **err, MuError errcode, const char *frm, ...)
G_GNUC_PRINTF(3,4); G_GNUC_PRINTF(3,4);

View File

@ -256,6 +256,7 @@ test_mu_maildir_walk_01 (void)
rv = mu_maildir_walk (tmpdir, rv = mu_maildir_walk (tmpdir,
(MuMaildirWalkMsgCallback)msg_cb, (MuMaildirWalkMsgCallback)msg_cb,
(MuMaildirWalkDirCallback)dir_cb, (MuMaildirWalkDirCallback)dir_cb,
TRUE,
&data); &data);
g_assert_cmpuint (MU_OK, ==, rv); g_assert_cmpuint (MU_OK, ==, rv);
@ -269,7 +270,7 @@ test_mu_maildir_walk_01 (void)
static void static void
test_mu_maildir_walk_02 (void) test_mu_maildir_walk (void)
{ {
char *tmpdir, *cmd, *dir; char *tmpdir, *cmd, *dir;
WalkData data; WalkData data;
@ -287,13 +288,13 @@ test_mu_maildir_walk_02 (void)
cmd = g_strdup_printf ("touch %s%c.noindex", dir, G_DIR_SEPARATOR); 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_assert (g_spawn_command_line_sync (cmd, NULL, NULL, NULL, NULL));
g_free (cmd); g_free (cmd);
g_free (dir); g_free (dir);
rv = mu_maildir_walk (tmpdir, rv = mu_maildir_walk (tmpdir,
(MuMaildirWalkMsgCallback)msg_cb, (MuMaildirWalkMsgCallback)msg_cb,
(MuMaildirWalkDirCallback)dir_cb, (MuMaildirWalkDirCallback)dir_cb,
TRUE,
&data); &data);
g_assert_cmpuint (MU_OK, ==, rv); g_assert_cmpuint (MU_OK, ==, rv);
@ -305,6 +306,90 @@ test_mu_maildir_walk_02 (void)
g_free (tmpdir); 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, ==, 17);
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, ==, 17);
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, ==, 13);
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, ==, 17);
g_assert_cmpuint (data._dir_entered,==, 5);
g_assert_cmpuint (data._dir_left,==, 5);
g_free (dir);
g_free (tmpdir);
}
static void static void
@ -478,8 +563,10 @@ main (int argc, char *argv[])
/* mu_util_maildir_walk */ /* mu_util_maildir_walk */
g_test_add_func ("/mu-maildir/mu-maildir-walk-01", g_test_add_func ("/mu-maildir/mu-maildir-walk-01",
test_mu_maildir_walk_01); test_mu_maildir_walk_01);
g_test_add_func ("/mu-maildir/mu-maildir-walk-02", g_test_add_func ("/mu-maildir/mu-maildir-walk",
test_mu_maildir_walk_02); test_mu_maildir_walk);
g_test_add_func ("/mu-maildir/mu-maildir-walk-with-noupdate",
test_mu_maildir_walk_with_noupdate);
/* get/set flags */ /* get/set flags */
g_test_add_func("/mu-maildir/mu-maildir-get-new-path-01", g_test_add_func("/mu-maildir/mu-maildir-get-new-path-01",

View File

@ -1,4 +1,4 @@
.TH MU-EASY 1 "January 2012" "User Manuals" .TH MU-EASY 1 "May 2012" "User Manuals"
.SH NAME .SH NAME
@ -45,7 +45,8 @@ Normally, \fBmu index\fR visits all the directories under the top-level
Maildir; however, you can exclude certain directories (say, the 'trash' Maildir; however, you can exclude certain directories (say, the 'trash'
or 'spam' folders) by creating a file called \fI.noindex\fR in the directory. or 'spam' folders) by creating a file called \fI.noindex\fR in the directory.
When \fBmu\fR sees such a file, it will exclude this directory and its When \fBmu\fR sees such a file, it will exclude this directory and its
sub-directories from indexing. sub-directories from indexing. Also see \fB.noupdate\fR in the \fBmu-index\fR
manpage.
.SH SEARCHING YOUR E-MAIL .SH SEARCHING YOUR E-MAIL

View File

@ -1,6 +1,6 @@
.TH MU-INDEX 1 "May 2011" "User Manuals" .TH MU-INDEX 1 "May 2012" "User Manuals"
.SH NAME .SH NAME
mu index \- index e-mail messages stored in Maildirs mu index \- index e-mail messages stored in Maildirs
@ -14,7 +14,7 @@ mu index \- index e-mail messages stored in Maildirs
directories and storing the results in a Xapian database. The data can then be directories and storing the results in a Xapian database. The data can then be
queried using queried using
.BR mu-find(1) .BR mu-find(1)
\. \.
.B index .B index
understands Maildirs as defined by Daniel Bernstein for qmail(7). In addition, understands Maildirs as defined by Daniel Bernstein for qmail(7). In addition,
@ -33,6 +33,12 @@ directory and all of its subdirectories will be ignored. This can be useful to
exclude certain directories from the indexing process, for example directories exclude certain directories from the indexing process, for example directories
with spam-messages. with spam-messages.
If there is a file called \fI.noupdate\fR in a directory, the contents of that
directory and all of its subdirectories will be ignored, unless we do a full
rebuild (with \fB--rebuild\fR). This can be useful to speed up things you have
some maildirs that never change. Note that you can still search for these
messages, this only affects updating the database.
The first run of \fBmu index\fR may take a few minutes if you have a lot of The first run of \fBmu index\fR may take a few minutes if you have a lot of
mail (ten thousands of messages). Fortunately, such a full scan needs to be mail (ten thousands of messages). Fortunately, such a full scan needs to be
done only once; after that it suffices to index the changes, which goes much done only once; after that it suffices to index the changes, which goes much