/*
* Notmuch support for mutt
*
- * Copyright (C) 2011 Karel Zak <kzak@redhat.com>
+ * Copyright (C) 2011, 2012 Karel Zak <kzak@redhat.com>
*/
#if HAVE_CONFIG_H
# include "config.h"
struct nm_hdrdata *data = h->data;
if (data) {
+ dprint(2, (debugfile, "nm: freeing header %p\n", data));
FREE(&data->folder);
FREE(&data->tags);
FREE(&data);
}
if (data) {
+ dprint(1, (debugfile, "nm: freeing context data %p\n", data));
if (data->db)
notmuch_database_close(data->db);
FREE(&data->db_filename);
char *nm_header_get_fullpath(HEADER *h, char *buf, size_t bufsz)
{
snprintf(buf, bufsz, "%s/%s", nm_header_get_folder(h), h->path);
+ dprint(2, (debugfile, "nm: returns fullpath '%s'\n", buf));
return buf;
}
ctx->data = (void *) data;
ctx->mx_close = free_data;
+ dprint(1, (debugfile, "nm: initialize context data %p\n", data));
+
if (url_parse_query(ctx->path, &data->db_filename, &data->query_items)) {
mutt_error(_("failed to parse notmuch uri: %s"), ctx->path);
data->db_filename = NULL;
data->db_query = safe_strdup(item->value);
}
+ dprint(2, (debugfile, "nm: query '%s'\n", data->db_query));
+
return data->db_query;
}
if (strncmp(db_filename, "notmuch://", 10) == 0)
db_filename += 10;
+ dprint(2, (debugfile, "nm: db filename '%s'\n", db_filename));
return db_filename;
}
return NULL;
if (!db_filename)
return NULL;
+ dprint(1, (debugfile, "nm: db open '%s'\n", db_filename));
+
data->db = notmuch_database_open(db_filename,
writable ? NOTMUCH_DATABASE_MODE_READ_WRITE :
NOTMUCH_DATABASE_MODE_READ_ONLY);
struct nm_data *data = get_data(ctx);
if (data && data->db) {
+ dprint(1, (debugfile, "nm: db close\n"));
notmuch_database_close(data->db);
data->db = NULL;
data->longrun = FALSE;
{
struct nm_data *data = get_data(ctx);
- if (data && get_db(ctx, writable))
+ if (data && get_db(ctx, writable)) {
data->longrun = TRUE;
+ dprint(2, (debugfile, "nm: long run initialied\n"));
+ }
}
void nm_longrun_done(CONTEXT *ctx)
{
struct nm_data *data = get_data(ctx);
- if (data)
+ if (data) {
release_db(ctx);
+ dprint(2, (debugfile, "nm: long run deinitialied\n"));
+ }
}
static int is_longrun(CONTEXT *ctx)
return data && data->longrun;
}
+void nm_debug_check(CONTEXT *ctx)
+{
+ struct nm_data *data;
+
+ if (ctx->magic != M_NOTMUCH)
+ return;
+
+ data = get_data(ctx);
+ if (!data)
+ return;
+
+ if (data->db) {
+ dprint(1, (debugfile, "nm: ERROR: db is open, closing\n"));
+ release_db(ctx);
+ }
+}
+
static int get_database_mtime(CONTEXT *ctx, time_t *mtime)
{
char path[_POSIX_PATH_MAX];
return -1;
snprintf(path, sizeof(path), "%s/.notmuch/xapian", get_db_filename(ctx));
+ dprint(2, (debugfile, "nm: checking '%s' mtime\n", path));
+
if (stat(path, &st))
return -1;
goto err;
notmuch_query_set_sort(q, NOTMUCH_SORT_NEWEST_FIRST);
+ dprint(2, (debugfile, "nm: query succesfully initialized\n"));
return q;
err:
if (!is_longrun(ctx))
char *tstr = NULL, *p;
size_t sz = 0;
+ dprint(2, (debugfile, "nm: tags update requested (%s)\n", h->env->message_id));
+
for (tags = notmuch_message_get_tags(msg);
tags && notmuch_tags_valid(tags);
notmuch_tags_move_to_next(tags)) {
if (data->tags && tstr && strcmp(data->tags, tstr) == 0) {
FREE(&tstr);
+ dprint(2, (debugfile, "nm: tags unchanged\n"));
return 1;
}
FREE(&data->tags);
data->tags = tstr;
+ dprint(2, (debugfile, "nm: new tags: '%s'\n", tstr));
return 0;
}
/*
* set/update HEADE->path and HEADER->data->path
*/
-static void update_message_path(HEADER *h, const char *path)
+static int update_message_path(HEADER *h, const char *path)
{
struct nm_hdrdata *data = h->data;
char *p;
+ dprint(2, (debugfile, "nm: path update requested path=%s, (%s)\n",
+ path, h->env->message_id));
+
p = strrchr(path, '/');
if (p && p - path > 3 &&
(strncmp(p - 3, "cur", 3) == 0 ||
p -= 3;
h->path = safe_strdup(p);
data->folder = strndup(path, p - path - 1);
+
+ dprint(2, (debugfile, "nm: folder='%s', file='%s'\n", data->folder, h->path));
+ return 0;
}
+
+ return 1;
}
static struct nm_hdrdata *create_hdrdata(HEADER *h, const char *path,
h->data = data;
h->free_cb = free_header_data;
- update_message_path(h, path);
- update_message_tags(h, msg);
+ dprint(2, (debugfile, "nm: initialize header data: [hdr=%p, data=%p] (%s)\n",
+ h, data, h->env->message_id));
+ if (update_message_path(h, path))
+ return NULL;
+
+ update_message_tags(h, msg);
return data;
}
if (!path)
return;
+ dprint(2, (debugfile, "nm: appending message, i=%d, (%s)\n",
+ ctx->msgcount,
+ notmuch_message_get_message_id(msg)));
+
if (ctx->msgcount >= ctx->hdrmax)
mx_alloc_memory(ctx);
if (!h)
return;
- create_hdrdata(h, path, msg);
+ if (create_hdrdata(h, path, msg) == NULL) {
+ mutt_free_header(&h);
+ dprint(1, (debugfile, "nm: failed to append header!\n"));
+ return;
+ }
h->active = 1;
h->index = ctx->msgcount;
if (ctx->magic != M_NOTMUCH || (!ctx->data && init_data(ctx)))
return -1;
+ dprint(1, (debugfile, "nm: reading messages...\n"));
+
q = get_query(ctx, FALSE);
if (!q)
goto done;
ctx->mtime = time(NULL);
mx_update_context(ctx, ctx->msgcount);
+
+ dprint(1, (debugfile, "nm: reading messages... done [rc=%d, count=%d]\n",
+ rc, ctx->msgcount));
return rc;
}
strncpy(buf, uri, bufsz);
buf[bufsz - 1] = '\0';
+
+ dprint(1, (debugfile, "nm: uri from query '%s'\n", buf));
return buf;
}
notmuch_message_t *msg;
char *id = nm_header_get_id(hdr);
+ dprint(2, (debugfile, "nm: find message (%s)\n", id));
+
msg = id && db ? notmuch_database_find_message(db, id) : NULL;
FREE(&id);
|| !(msg = get_nm_message(db, hdr)))
goto done;
+ dprint(1, (debugfile, "nm: tags modify: '%s'\n", buf0));
+
buf = safe_strdup(buf0);
notmuch_message_freeze(msg);
*end = '\0';
- if (*tag == '-')
+ if (*tag == '-') {
+ dprint(1, (debugfile, "nm: remove tag: '%s'\n", tag + 1));
notmuch_message_remove_tag(msg, tag + 1);
- else
+ } else {
+ dprint(1, (debugfile, "nm: add tag: '%s'\n", *tag == '+' ? tag + 1 : tag));
notmuch_message_add_tag(msg, *tag == '+' ? tag + 1 : tag);
+ }
end = tag = NULL;
}
release_db(ctx);
if (hdr->changed)
ctx->mtime = time(NULL);
+ dprint(1, (debugfile, "nm: tags modify done [rc=%d]\n", rc));
return rc;
}
const char *old, const char *new)
{
notmuch_status_t st;
+ notmuch_message_t *msg = NULL;
if (!db)
return -1;
- st = notmuch_database_add_message(db, new, NULL);
+ if (new && access(new, F_OK) == 0) {
+ dprint(2, (debugfile, "nm: add filename '%s'\n", new));
+ st = notmuch_database_add_message(db, new, &msg);
+ } else
+ /* if the new file does not exist then we remove old file only */
+ st = NOTMUCH_STATUS_SUCCESS;
+
if (st == NOTMUCH_STATUS_DUPLICATE_MESSAGE_ID ||
- st == NOTMUCH_STATUS_SUCCESS)
+ st == NOTMUCH_STATUS_SUCCESS) {
+ dprint(2, (debugfile, "nm: remove filename '%s'\n", old));
notmuch_database_remove_message(db, old);
+ }
+ if (msg)
+ notmuch_message_maildir_flags_to_tags(msg);
return 0;
}
|| !old)
return -1;
+ dprint(1, (debugfile, "nm: update filenames, old='%s', new='%s'\n", old, new));
return _nm_update_filename(get_db(ctx, TRUE), old, new);
}
if (ctx->magic != M_NOTMUCH || (!ctx->data && init_data(ctx)))
return -1;
+ dprint(1, (debugfile, "nm: sync start ...\n"));
+
if (!ctx->quiet) {
snprintf(msgbuf, sizeof (msgbuf), _("Writing %s..."), ctx->path);
mutt_progress_init(&progress, msgbuf, M_PROGRESS_MSG,
break;
}
if (h->deleted) {
+ dprint(2, (debugfile, "nm: remove filename '%s'\n", old));
notmuch_database_remove_message(db, old);
changed = 1;
} else if (*new && *old) {
release_db(ctx);
if (changed)
ctx->mtime = time(NULL);
+
+ dprint(1, (debugfile, "nm: .... sync done [rc=%d]\n", rc));
return rc;
}
{
unsigned res = 0;
notmuch_query_t *q = notmuch_query_create(db, qstr);
+
if (q) {
res = notmuch_query_count_messages(q);
notmuch_query_destroy(q);
+ dprint(1, (debugfile, "nm: count '%s', result=%d\n", qstr, res));
}
return res;
}
notmuch_database_t *db = NULL;
int rc = -1, dflt = 0;
+ dprint(1, (debugfile, "nm: count\n"));
+
if (url_parse_query(path, &db_filename, &query_items)) {
mutt_error(_("failed to parse notmuch uri: %s"), path);
goto done;
dflt = 1;
}
+ dprint(1, (debugfile, "nm: count open DB\n"));
db = notmuch_database_open(db_filename, NOTMUCH_DATABASE_MODE_READ_ONLY);
if (!db) {
mutt_error (_("Cannot open notmuch database: %s"), db_filename);
rc = 0;
done:
- if (db)
+ if (db) {
notmuch_database_close(db);
+ dprint(1, (debugfile, "nm: count close DB\n"));
+ }
if (!dflt)
FREE(&db_filename);
url_free_tags(query_items);
+
+ dprint(1, (debugfile, "nm: count done [rc=%d]\n", rc));
return rc;
}
if (!id)
return NULL;
+ dprint(2, (debugfile, "nm: mutt header, id='%s'\n", id));
+
if (!ctx->id_hash) {
+ dprint(2, (debugfile, "nm: init hash\n"));
ctx->id_hash = mutt_make_id_hash(ctx);
if (!ctx->id_hash)
return NULL;
safe_realloc(mid, sz);
snprintf(*mid, sz, "<%s>", id);
+
+ dprint(2, (debugfile, "nm: mutt id='%s'\n", *mid));
return hash_find(ctx->id_hash, *mid);
}
int nm_check_database(CONTEXT *ctx, int *index_hint)
{
- time_t mtime;
+ time_t mtime = 0;
notmuch_query_t *q;
notmuch_messages_t *msgs;
int i, limit, new_messages = 0, occult = 0, new_flags = 0;
if (get_database_mtime(ctx, &mtime))
return -1;
- if (ctx->mtime >= mtime)
+
+ if (ctx->mtime >= mtime) {
+ dprint(2, (debugfile, "nm: check unnecessary (db=%d ctx=%d)\n", mtime, ctx->mtime));
return 0;
+ }
+
+ dprint(1, (debugfile, "nm: checking (db=%d ctx=%d)\n", mtime, ctx->mtime));
q = get_query(ctx, FALSE);
if (!q)
goto done;
+ dprint(1, (debugfile, "nm: start checking (count=%d)\n", ctx->msgcount));
+
for (i = 0; i < ctx->msgcount; i++)
ctx->hdrs[i]->active = 0;
ctx->mtime = time(NULL);
+ dprint(1, (debugfile, "nm: ... check done [new=%d, new_flags=%d, occult=%d]\n",
+ new_messages, new_flags, occult));
+
return occult ? M_REOPENED :
new_messages ? M_NEW_MAIL :
new_flags ? M_FLAGS : 0;
}
-
-